/* * A simple dialog for previewing icon representation. * * Authors: * Jon A. Cruz * Bob Jamison * Other dudes from The Inkscape Organization * * Copyright (C) 2004 Bob Jamison * Copyright (C) 2005 Jon A. Cruz * * Released under GNU GPL, read the file 'COPYING' for more information */ #ifdef HAVE_CONFIG_H # include #endif #include "iconpreview.h" #include #include //for GTK_RESPONSE* types #include #include #include #include "prefs-utils.h" #include "inkscape.h" #include "document.h" #include "desktop-handles.h" #include "selection.h" #include "desktop.h" #include "display/nr-arena.h" #include "sp-root.h" #include "xml/repr.h" extern "C" { // takes doc, root, icon, and icon name to produce pixels guchar * sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, const gchar *name, unsigned int psize ); } namespace Inkscape { namespace UI { namespace Dialogs { IconPreviewPanel* IconPreviewPanel::instance = 0; IconPreviewPanel& IconPreviewPanel::getInstance() { if ( !instance ) { instance = new IconPreviewPanel(); } instance->refreshPreview(); return *instance; } //######################################################################### //## E V E N T S //######################################################################### void IconPreviewPanel::on_button_clicked(int which) { if ( hot != which ) { buttons[hot]->set_active( false ); hot = which; updateMagnify(); queue_draw(); } } //######################################################################### //## C O N S T R U C T O R / D E S T R U C T O R //######################################################################### /** * Constructor */ IconPreviewPanel::IconPreviewPanel() : Panel(), hot(1), refreshButton(0), selectionButton(0) { numEntries = 0; Inkscape::XML::Node *things = inkscape_get_repr(INKSCAPE, "iconpreview.sizes.default"); if (things) { std::vector rawSizes; for ( Inkscape::XML::Node *child = things->firstChild(); child; child = child->next() ) { gchar const *id = child->attribute("id"); if ( id ) { std::string path("iconpreview.sizes.default."); path += id; gint show = prefs_get_int_attribute_limited( path.c_str(), "show", 1, 0, 1 ); gint sizeVal = prefs_get_int_attribute( path.c_str(), "value", -1 ); if ( show && (sizeVal > 0) ) { rawSizes.push_back( sizeVal ); } } } if ( !rawSizes.empty() ) { numEntries = rawSizes.size(); sizes = new int[numEntries]; int i = 0; for ( std::vector::iterator it = rawSizes.begin(); it != rawSizes.end(); ++it, ++i ) { sizes[i] = *it; } } } if ( numEntries < 1 ) { numEntries = 5; sizes = new int[numEntries]; sizes[0] = 16; sizes[1] = 24; sizes[2] = 32; sizes[3] = 48; sizes[5] = 128; } pixMem = new guchar*[numEntries]; images = new Gtk::Image*[numEntries]; labels = new Glib::ustring*[numEntries]; buttons = new Gtk::ToggleToolButton*[numEntries]; for ( int i = 0; i < numEntries; i++ ) { char *label = g_strdup_printf(_("%d x %d"), sizes[i], sizes[i]); labels[i] = new Glib::ustring(label); g_free(label); pixMem[i] = 0; images[i] = 0; } magLabel.set_label( *labels[hot] ); Gtk::VBox* magBox = new Gtk::VBox(); magBox->pack_start( magnified ); magBox->pack_start( magLabel, Gtk::PACK_SHRINK ); Gtk::VBox * verts = new Gtk::VBox(); for ( int i = 0; i < numEntries; i++ ) { pixMem[i] = new guchar[4 * sizes[i] * sizes[i]]; memset( pixMem[i], 0x00, 4 * sizes[i] * sizes[i] ); GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], sizes[i] * 4, /*(GdkPixbufDestroyNotify)nr_free*/NULL, NULL ); GtkImage* img = GTK_IMAGE( gtk_image_new_from_pixbuf( pb ) ); images[i] = Glib::wrap(img); Glib::ustring label(*labels[i]); buttons[i] = new Gtk::ToggleToolButton(label); buttons[i]->set_active( i == hot ); buttons[i]->set_icon_widget(*images[i]); tips.set_tip((*buttons[i]), label); buttons[i]->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i) ); verts->add(*buttons[i]); } iconBox.pack_start(splitter); splitter.pack1( *magBox, true, true ); splitter.pack2( *verts, false, false ); //## The Refresh button 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 ); tips.set_tip((*selectionButton), _("Selection only or whole document")); selectionButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::modeToggled) ); gint val = prefs_get_int_attribute_limited( "iconpreview", "selectionOnly", 0, 0, 1 ); 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); show_all_children(); } //######################################################################### //## M E T H O D S //######################################################################### void IconPreviewPanel::refreshPreview() { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if ( desktop ) { if ( selectionButton && selectionButton->get_active() ) { Inkscape::Selection * sel = SP_DT_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 = SP_OBJECT_ID( obj ); if ( id ) { target = obj; } items = g_slist_next(items); } if ( target ) { renderPreview(target); } } } else { SPObject *target = desktop->currentRoot(); if ( target ) { renderPreview(target); } } } } void IconPreviewPanel::modeToggled() { prefs_set_int_attribute( "iconpreview", "selectionOnly", (selectionButton && selectionButton->get_active()) ? 1 : 0 ); refreshPreview(); } void IconPreviewPanel::renderPreview( SPObject* obj ) { SPDocument * doc = SP_OBJECT_DOCUMENT(obj); gchar * id = SP_OBJECT_ID(obj); // g_message(" setting up to render '%s' as the icon", id ); NRArenaItem *root = NULL; /* Create new arena */ NRArena *arena = NRArena::create(); /* Create ArenaItem and set transform */ unsigned int visionkey = sp_item_display_key_new(1); /* fixme: Memory manage root if needed (Lauris) */ root = sp_item_invoke_show ( SP_ITEM( SP_DOCUMENT_ROOT(doc) ), arena, visionkey, SP_ITEM_SHOW_DISPLAY ); for ( int i = 0; i < numEntries; i++ ) { guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i] ); // g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") ); if ( px ) { memcpy( pixMem[i], px, sizes[i] * sizes[i] * 4 ); g_free( px ); px = 0; } else { memset( pixMem[i], 0, sizes[i] * sizes[i] * 4 ); } images[i]->queue_draw(); } updateMagnify(); } void IconPreviewPanel::updateMagnify() { Glib::RefPtr buf = images[hot]->get_pixbuf()->scale_simple( 128, 128, Gdk::INTERP_NEAREST ); magLabel.set_label( *labels[hot] ); magnified.set( buf ); magnified.queue_draw(); magnified.get_parent()->queue_draw(); } } //namespace Dialogs } //namespace UI } //namespace Inkscape /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : //######################################################################### //## E N D O F F I L E //#########################################################################