Code

Cleanup of device internal handling and API.
[inkscape.git] / src / ui / dialog / icon-preview.cpp
1 /** @file
2  * @brief A simple dialog for previewing icon representation.
3  */
4 /* Authors:
5  *   Jon A. Cruz
6  *   Bob Jamison
7  *   Other dudes from The Inkscape Organization
8  *
9  * Copyright (C) 2004 Bob Jamison
10  * Copyright (C) 2005 Jon A. Cruz
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
18 #include <gtk/gtk.h>
19 #include <glib/gmem.h>
20 #include <glibmm/i18n.h>
21 #include <gtkmm/buttonbox.h>
22 #include <gtkmm/stock.h>
24 #include "desktop.h"
25 #include "desktop-handles.h"
26 #include "display/nr-arena.h"
27 #include "document.h"
28 #include "inkscape.h"
29 #include "preferences.h"
30 #include "selection.h"
31 #include "sp-root.h"
32 #include "xml/repr.h"
34 #include "icon-preview.h"
36 extern "C" {
37 // takes doc, root, icon, and icon name to produce pixels
38 guchar *
39 sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
40                   const gchar *name, unsigned int psize );
41 }
43 namespace Inkscape {
44 namespace UI {
45 namespace Dialogs {
48 IconPreviewPanel &IconPreviewPanel::getInstance()
49 {
50     IconPreviewPanel *instance = new IconPreviewPanel();
52     instance->refreshPreview();
54     return *instance;
55 }
57 //#########################################################################
58 //## E V E N T S
59 //#########################################################################
61 void IconPreviewPanel::on_button_clicked(int which)
62 {
63     if ( hot != which ) {
64         buttons[hot]->set_active( false );
66         hot = which;
67         updateMagnify();
68         _getContents()->queue_draw();
69     }
70 }
75 //#########################################################################
76 //## C O N S T R U C T O R    /    D E S T R U C T O R
77 //#########################################################################
78 /**
79  * Constructor
80  */
81 IconPreviewPanel::IconPreviewPanel() :
82     UI::Widget::Panel("", "/dialogs/iconpreview", SP_VERB_VIEW_ICON_PREVIEW),
83     hot(1),
84     refreshButton(0),
85     selectionButton(0)
86 {
87     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
88     numEntries = 0;
90     std::vector<Glib::ustring> pref_sizes = prefs->getAllDirs("/iconpreview/sizes/default");
91     std::vector<int> rawSizes;
93     for (std::vector<Glib::ustring>::iterator i = pref_sizes.begin(); i != pref_sizes.end(); ++i) {
94         if (prefs->getBool(*i + "/show", true)) {
95             int sizeVal = prefs->getInt(*i + "/value", -1);
96             if (sizeVal > 0) {
97                 rawSizes.push_back(sizeVal);
98             }
99         }
100     }
102     if ( !rawSizes.empty() ) {
103         numEntries = rawSizes.size();
104         sizes = new int[numEntries];
105         int i = 0;
106         for ( std::vector<int>::iterator it = rawSizes.begin(); it != rawSizes.end(); ++it, ++i ) {
107             sizes[i] = *it;
108         }
109     }
111     if ( numEntries < 1 )
112     {
113         numEntries = 5;
114         sizes = new int[numEntries];
115         sizes[0] = 16;
116         sizes[1] = 24;
117         sizes[2] = 32;
118         sizes[3] = 48;
119         sizes[4] = 128;
120     }
122     pixMem = new guchar*[numEntries];
123     images = new Gtk::Image*[numEntries];
124     labels = new Glib::ustring*[numEntries];
125     buttons = new Gtk::ToggleToolButton*[numEntries];
128     for ( int i = 0; i < numEntries; i++ ) {
129         char *label = g_strdup_printf(_("%d x %d"), sizes[i], sizes[i]);
130         labels[i] = new Glib::ustring(label);
131         g_free(label);
132         pixMem[i] = 0;
133         images[i] = 0;
134     }
137     magLabel.set_label( *labels[hot] );
139     Gtk::VBox* magBox = new Gtk::VBox();
141     magBox->pack_start( magnified );
142     magBox->pack_start( magLabel, Gtk::PACK_SHRINK );
145     Gtk::VBox * verts = new Gtk::VBox();
146     for ( int i = 0; i < numEntries; i++ ) {
147         pixMem[i] = new guchar[4 * sizes[i] * sizes[i]];
148         memset( pixMem[i], 0x00, 4 *  sizes[i] * sizes[i] );
150         GdkPixbuf *pb = gdk_pixbuf_new_from_data( pixMem[i], GDK_COLORSPACE_RGB, TRUE, 8, sizes[i], sizes[i], sizes[i] * 4, /*(GdkPixbufDestroyNotify)g_free*/NULL, NULL );
151         GtkImage* img = GTK_IMAGE( gtk_image_new_from_pixbuf( pb ) );
152         images[i] = Glib::wrap(img);
153         Glib::ustring label(*labels[i]);
154         buttons[i] = new Gtk::ToggleToolButton(label);
155         buttons[i]->set_active( i == hot );
156         buttons[i]->set_icon_widget(*images[i]);
158         tips.set_tip((*buttons[i]), label);
160         buttons[i]->signal_clicked().connect( sigc::bind<int>( sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i) );
163         verts->add(*buttons[i]);
164     }
166     iconBox.pack_start(splitter);
167     splitter.pack1( *magBox, true, true );
168     splitter.pack2( *verts, false, false );
171     //## The Refresh button
174     Gtk::HButtonBox* holder = new Gtk::HButtonBox( Gtk::BUTTONBOX_END );
175     _getContents()->pack_end(*holder, false, false);
177     selectionButton = new Gtk::ToggleButton(_("Selection")); // , GTK_RESPONSE_APPLY
178     holder->pack_start( *selectionButton, false, false );
179     tips.set_tip((*selectionButton), _("Selection only or whole document"));
180     selectionButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::modeToggled) );
182     gint val = prefs->getBool("/iconpreview/selectionOnly");
183     selectionButton->set_active( val != 0 );
185     refreshButton = new Gtk::Button(Gtk::Stock::REFRESH); // , GTK_RESPONSE_APPLY
186     holder->pack_end( *refreshButton, false, false );
187     tips.set_tip((*refreshButton), _("Refresh the icons"));
188     refreshButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::refreshPreview) );
191     _getContents()->pack_start(iconBox, Gtk::PACK_EXPAND_WIDGET);
193     show_all_children();
196 //#########################################################################
197 //## M E T H O D S
198 //#########################################################################
201 void IconPreviewPanel::refreshPreview()
203     SPDesktop *desktop = getDesktop();
204     if ( desktop ) {
206         if ( selectionButton && selectionButton->get_active() )
207         {
208             Inkscape::Selection * sel = sp_desktop_selection(desktop);
209             if ( sel ) {
210                 //g_message("found a selection to play with");
212                 GSList const *items = sel->itemList();
213                 SPObject *target = 0;
214                 while ( items && !target ) {
215                     SPItem* item = SP_ITEM( items->data );
216                     SPObject * obj = SP_OBJECT(item);
217                     gchar const *id = obj->getId();
218                     if ( id ) {
219                         target = obj;
220                     }
222                     items = g_slist_next(items);
223                 }
224                 if ( target ) {
225                     renderPreview(target);
226                 }
227             }
228         }
229         else
230         {
231             SPObject *target = desktop->currentRoot();
232             if ( target ) {
233                 renderPreview(target);
234             }
235         }
236     }
239 void IconPreviewPanel::modeToggled()
241     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
242     prefs->setBool("/iconpreview/selectionOnly", (selectionButton && selectionButton->get_active()));
244     refreshPreview();
247 void IconPreviewPanel::renderPreview( SPObject* obj )
249     SPDocument * doc = SP_OBJECT_DOCUMENT(obj);
250     gchar const * id = obj->getId();
252 //    g_message(" setting up to render '%s' as the icon", id );
254     NRArenaItem *root = NULL;
256     /* Create new arena */
257     NRArena *arena = NRArena::create();
259     /* Create ArenaItem and set transform */
260     unsigned int visionkey = sp_item_display_key_new(1);
262     root = sp_item_invoke_show ( SP_ITEM( SP_DOCUMENT_ROOT(doc) ),
263                                  arena, visionkey, SP_ITEM_SHOW_DISPLAY );
265     for ( int i = 0; i < numEntries; i++ ) {
266         guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i] );
267 //         g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") );
268         if ( px ) {
269             memcpy( pixMem[i], px, sizes[i] * sizes[i] * 4 );
270             g_free( px );
271             px = 0;
272         } else {
273             memset( pixMem[i], 0, sizes[i] * sizes[i] * 4 );
274         }
275         images[i]->queue_draw();
276     }
277     updateMagnify();
279     sp_item_invoke_hide(SP_ITEM(sp_document_root(doc)), visionkey);
280     nr_object_unref((NRObject *) arena);
283 void IconPreviewPanel::updateMagnify()
285     Glib::RefPtr<Gdk::Pixbuf> buf = images[hot]->get_pixbuf()->scale_simple( 128, 128, Gdk::INTERP_NEAREST );
286     magLabel.set_label( *labels[hot] );
287     magnified.set( buf );
288     magnified.queue_draw();
289     magnified.get_parent()->queue_draw();
293 } //namespace Dialogs
294 } //namespace UI
295 } //namespace Inkscape
297 /*
298   Local Variables:
299   mode:c++
300   c-file-style:"stroustrup"
301   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
302   indent-tabs-mode:nil
303   fill-column:99
304   End:
305 */
306 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :