index 088f630314fb1f5dcca0b2b8cb6d92c76168bd84..07e1ff43052a02bec77f857367a7bdd70b672e2e 100644 (file)
* Other dudes from The Inkscape Organization
*
* Copyright (C) 2004 Bob Jamison
- * Copyright (C) 2005 Jon A. Cruz
+ * Copyright (C) 2005,2010 Jon A. Cruz
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <gtk/gtk.h>
#include <glib/gmem.h>
#include <glibmm/i18n.h>
+#include <gtkmm/alignment.h>
#include <gtkmm/buttonbox.h>
#include <gtkmm/stock.h>
const gchar *name, unsigned int psize );
}
+#define noICON_VERBOSE 1
+
namespace Inkscape {
namespace UI {
-namespace Dialogs {
+namespace Dialog {
-IconPreviewPanel&
-IconPreviewPanel::getInstance()
+IconPreviewPanel &IconPreviewPanel::getInstance()
{
- static IconPreviewPanel &instance = *new IconPreviewPanel();
+ IconPreviewPanel *instance = new IconPreviewPanel();
- instance.refreshPreview();
+ instance->refreshPreview();
- return instance;
+ return *instance;
}
//#########################################################################
*/
IconPreviewPanel::IconPreviewPanel() :
UI::Widget::Panel("", "/dialogs/iconpreview", SP_VERB_VIEW_ICON_PREVIEW),
+ deskTrack(),
+ desktop(0),
+ document(0),
+ timer(0),
+ renderTimer(0),
+ pending(false),
+ minDelay(0.1),
+ targetId(),
hot(1),
- refreshButton(0),
- selectionButton(0)
+ selectionButton(0),
+ desktopChangeConn(),
+ docReplacedConn(),
+ docModConn(),
+ selChangedConn()
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
numEntries = 0;
+ bool pack = prefs->getBool("/iconpreview/pack", true);
+
std::vector<Glib::ustring> pref_sizes = prefs->getAllDirs("/iconpreview/sizes/default");
std::vector<int> rawSizes;
Gtk::VBox* magBox = new Gtk::VBox();
- magBox->pack_start( magnified );
+ Gtk::Frame *magFrame = Gtk::manage(new Gtk::Frame(_("Magnified:")));
+ magFrame->add( magnified );
+
+ magBox->pack_start( *magFrame, Gtk::PACK_EXPAND_WIDGET );
magBox->pack_start( magLabel, Gtk::PACK_SHRINK );
- Gtk::VBox * verts = new Gtk::VBox();
- for ( int i = 0; i < numEntries; i++ ) {
+ Gtk::VBox *verts = new Gtk::VBox();
+ Gtk::HBox *horiz = 0;
+ int previous = 0;
+ int avail = 0;
+ for ( int i = numEntries - 1; i >= 0; --i ) {
pixMem[i] = new guchar[4 * sizes[i] * sizes[i]];
memset( pixMem[i], 0x00, 4 * sizes[i] * sizes[i] );
Glib::ustring label(*labels[i]);
buttons[i] = new Gtk::ToggleToolButton(label);
buttons[i]->set_active( i == hot );
- buttons[i]->set_icon_widget(*images[i]);
+ if ( prefs->getBool("/iconpreview/showFrames", true) ) {
+ Gtk::Frame *frame = new Gtk::Frame();
+ frame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
+ frame->add(*images[i]);
+ buttons[i]->set_icon_widget(*Gtk::manage(frame));
+ } else {
+ buttons[i]->set_icon_widget(*images[i]);
+ }
tips.set_tip((*buttons[i]), label);
buttons[i]->signal_clicked().connect( sigc::bind<int>( sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i) );
- verts->add(*buttons[i]);
+ Gtk::Alignment *align = Gtk::manage(new Gtk::Alignment(0.5, 0.5, 0, 0));
+ align->add(*buttons[i]);
+
+ int pad = 12;
+ if ( !pack || ( (avail == 0) && (previous == 0) ) ) {
+ verts->pack_end(*align, Gtk::PACK_SHRINK);
+ previous = sizes[i];
+ avail = sizes[i];
+ } else {
+ if ((avail < pad) || ((sizes[i] > avail) && (sizes[i] < previous))) {
+ horiz = 0;
+ }
+ if ((horiz == 0) && (sizes[i] <= previous)) {
+ avail = previous;
+ }
+ if (sizes[i] <= avail) {
+ if (!horiz) {
+ horiz = Gtk::manage(new Gtk::HBox());
+ avail = previous;
+ verts->pack_end(*horiz, Gtk::PACK_SHRINK);
+ }
+ horiz->pack_start(*align, Gtk::PACK_EXPAND_WIDGET);
+ avail -= sizes[i];
+ avail -= pad; // a little extra for padding
+ } else {
+ horiz = 0;
+ verts->pack_end(*align, Gtk::PACK_SHRINK);
+ }
+ }
}
iconBox.pack_start(splitter);
splitter.pack1( *magBox, true, true );
- splitter.pack2( *verts, false, false );
-
-
- //## The Refresh button
-
+ Gtk::Frame *actuals = Gtk::manage(new Gtk::Frame(_("Actual Size:")));
+ actuals->add(*verts);
+ splitter.pack2( *actuals, false, false );
- Gtk::HButtonBox* holder = new Gtk::HButtonBox( Gtk::BUTTONBOX_END );
- _getContents()->pack_end(*holder, false, false);
- selectionButton = new Gtk::ToggleButton(_("Selection")); // , GTK_RESPONSE_APPLY
- holder->pack_start( *selectionButton, false, false );
+ selectionButton = new Gtk::CheckButton(C_("Icon preview window", "Sele_ction"), true);//selectionButton = (Gtk::ToggleButton*) gtk_check_button_new_with_mnemonic(_("_Selection")); // , GTK_RESPONSE_APPLY
+ magBox->pack_start( *selectionButton, Gtk::PACK_SHRINK );
tips.set_tip((*selectionButton), _("Selection only or whole document"));
selectionButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::modeToggled) );
gint val = prefs->getBool("/iconpreview/selectionOnly");
selectionButton->set_active( val != 0 );
- refreshButton = new Gtk::Button(Gtk::Stock::REFRESH); // , GTK_RESPONSE_APPLY
- holder->pack_end( *refreshButton, false, false );
- tips.set_tip((*refreshButton), _("Refresh the icons"));
- refreshButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::refreshPreview) );
-
- _getContents()->pack_start(iconBox, Gtk::PACK_EXPAND_WIDGET);
+ _getContents()->pack_start(iconBox, Gtk::PACK_SHRINK);
show_all_children();
+
+ // Connect this up last
+ desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &IconPreviewPanel::setDesktop) );
+ deskTrack.connect(GTK_WIDGET(gobj()));
+}
+
+IconPreviewPanel::~IconPreviewPanel()
+{
+ setDesktop(0);
+ if (timer) {
+ timer->stop();
+ delete timer;
+ timer = 0;
+ }
+ if ( renderTimer ) {
+ renderTimer->stop();
+ delete renderTimer;
+ renderTimer = 0;
+ }
+
+ selChangedConn.disconnect();
+ docModConn.disconnect();
+ docReplacedConn.disconnect();
+ desktopChangeConn.disconnect();
+ deskTrack.disconnect();
}
//#########################################################################
//#########################################################################
+#if ICON_VERBOSE
+static Glib::ustring getTimestr()
+{
+ Glib::ustring str;
+ GTimeVal now = {0, 0};
+ g_get_current_time(&now);
+ glong secs = now.tv_sec % 60;
+ glong mins = (now.tv_sec / 60) % 60;
+ gchar *ptr = g_strdup_printf(":%02ld:%02ld.%06ld", mins, secs, now.tv_usec);
+ str = ptr;
+ g_free(ptr);
+ ptr = 0;
+ return str;
+}
+#endif // ICON_VERBOSE
+
+void IconPreviewPanel::setDesktop( SPDesktop* desktop )
+{
+ Panel::setDesktop(desktop);
+
+ SPDocument *newDoc = (desktop) ? desktop->doc() : 0;
+
+ if ( desktop != this->desktop ) {
+ docReplacedConn.disconnect();
+ selChangedConn.disconnect();
+
+ this->desktop = Panel::getDesktop();
+ if ( this->desktop ) {
+ docReplacedConn = this->desktop->connectDocumentReplaced(sigc::hide<0>(sigc::mem_fun(this, &IconPreviewPanel::setDocument)));
+ if ( this->desktop->selection && Inkscape::Preferences::get()->getBool("/iconpreview/autoRefresh", true) ) {
+ selChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh)));
+ }
+ }
+ }
+ setDocument(newDoc);
+ deskTrack.setBase(desktop);
+}
+
+void IconPreviewPanel::setDocument( SPDocument *document )
+{
+ if (this->document != document) {
+ docModConn.disconnect();
+
+ this->document = document;
+ if (this->document) {
+ if ( Inkscape::Preferences::get()->getBool("/iconpreview/autoRefresh", true) ) {
+ docModConn = this->document->connectModified(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh)));
+ }
+ queueRefresh();
+ }
+ }
+}
+
void IconPreviewPanel::refreshPreview()
{
SPDesktop *desktop = getDesktop();
- if ( desktop ) {
-
+ if (!timer) {
+ timer = new Glib::Timer();
+ }
+ if (timer->elapsed() < minDelay) {
+#if ICON_VERBOSE
+ g_message( "%s Deferring refresh as too soon. calling queueRefresh()", getTimestr().c_str() );
+#endif //ICON_VERBOSE
+ // Do not refresh too quickly
+ queueRefresh();
+ } else if ( desktop ) {
+#if ICON_VERBOSE
+ g_message( "%s Refreshing preview.", getTimestr().c_str() );
+#endif // ICON_VERBOSE
+ bool hold = Inkscape::Preferences::get()->getBool("/iconpreview/selectionHold", true);
+ SPObject *target = 0;
if ( selectionButton && selectionButton->get_active() )
{
- Inkscape::Selection * sel = sp_desktop_selection(desktop);
- if ( sel ) {
- //g_message("found a selection to play with");
-
- GSList const *items = sel->itemList();
- SPObject *target = 0;
- while ( items && !target ) {
- SPItem* item = SP_ITEM( items->data );
- SPObject * obj = SP_OBJECT(item);
- gchar const *id = obj->getId();
- if ( id ) {
- target = obj;
+ target = (hold && !targetId.empty()) ? desktop->doc()->getObjectById( targetId.c_str() ) : 0;
+ if ( !target ) {
+ targetId.clear();
+ Inkscape::Selection * sel = sp_desktop_selection(desktop);
+ if ( sel ) {
+ //g_message("found a selection to play with");
+
+ GSList const *items = sel->itemList();
+ while ( items && !target ) {
+ SPItem* item = SP_ITEM( items->data );
+ SPObject * obj = SP_OBJECT(item);
+ gchar const *id = obj->getId();
+ if ( id ) {
+ targetId = id;
+ target = obj;
+ }
+
+ items = g_slist_next(items);
}
-
- items = g_slist_next(items);
- }
- if ( target ) {
- renderPreview(target);
}
}
+ } else {
+ target = desktop->currentRoot();
}
- else
- {
- SPObject *target = desktop->currentRoot();
- if ( target ) {
- renderPreview(target);
- }
+ if ( target ) {
+ renderPreview(target);
}
+#if ICON_VERBOSE
+ g_message( "%s resetting timer", getTimestr().c_str() );
+#endif // ICON_VERBOSE
+ timer->reset();
+ }
+}
+
+bool IconPreviewPanel::refreshCB()
+{
+ bool callAgain = true;
+ if (!timer) {
+ timer = new Glib::Timer();
+ }
+ if ( timer->elapsed() > minDelay ) {
+#if ICON_VERBOSE
+ g_message( "%s refreshCB() timer has progressed", getTimestr().c_str() );
+#endif // ICON_VERBOSE
+ callAgain = false;
+ refreshPreview();
+#if ICON_VERBOSE
+ g_message( "%s refreshCB() setting pending false", getTimestr().c_str() );
+#endif // ICON_VERBOSE
+ pending = false;
+ }
+ return callAgain;
+}
+
+void IconPreviewPanel::queueRefresh()
+{
+ if (!pending) {
+ pending = true;
+#if ICON_VERBOSE
+ g_message( "%s queueRefresh() Setting pending true", getTimestr().c_str() );
+#endif // ICON_VERBOSE
+ if (!timer) {
+ timer = new Glib::Timer();
+ }
+ Glib::signal_idle().connect( sigc::mem_fun(this, &IconPreviewPanel::refreshCB), Glib::PRIORITY_DEFAULT_IDLE );
}
}
void IconPreviewPanel::modeToggled()
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setBool("/iconpreview/selectionOnly", (selectionButton && selectionButton->get_active()));
+ bool selectionOnly = (selectionButton && selectionButton->get_active());
+ prefs->setBool("/iconpreview/selectionOnly", selectionOnly);
+ if ( !selectionOnly ) {
+ targetId.clear();
+ }
refreshPreview();
}
{
SPDocument * doc = SP_OBJECT_DOCUMENT(obj);
gchar const * id = obj->getId();
+ if ( !renderTimer ) {
+ renderTimer = new Glib::Timer();
+ }
+ renderTimer->reset();
-// g_message(" setting up to render '%s' as the icon", id );
+#if ICON_VERBOSE
+ g_message("%s setting up to render '%s' as the icon", getTimestr().c_str(), id );
+#endif // ICON_VERBOSE
NRArenaItem *root = NULL;
sp_item_invoke_hide(SP_ITEM(sp_document_root(doc)), visionkey);
nr_object_unref((NRObject *) arena);
+ renderTimer->stop();
+ minDelay = std::max( 0.1, renderTimer->elapsed() * 3.0 );
+#if ICON_VERBOSE
+ g_message(" render took %f seconds.", renderTimer->elapsed());
+#endif // ICON_VERBOSE
}
void IconPreviewPanel::updateMagnify()
magnified.get_parent()->queue_draw();
}
-
} //namespace Dialogs
} //namespace UI
} //namespace Inkscape
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :