Code

replace nr_new() with g_new(), and try to converge on using the glib allocator a...
[inkscape.git] / src / dialogs / iconpreview.cpp
1 /*
2  * 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 "iconpreview.h"
20 #include <gtk/gtk.h>
22 #include <glib/gmem.h>
23 #include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
24 #include <glibmm/i18n.h>
25 #include <gtkmm/buttonbox.h>
26 #include <gtkmm/stock.h>
28 #include "prefs-utils.h"
29 #include "inkscape.h"
30 #include "document.h"
31 #include "desktop-handles.h"
32 #include "selection.h"
33 #include "desktop.h"
34 #include "display/nr-arena.h"
35 #include "sp-root.h"
36 #include "xml/repr.h"
38 extern "C" {
39 // takes doc, root, icon, and icon name to produce pixels
40 guchar *
41 sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
42                   const gchar *name, unsigned int psize );
43 }
45 namespace Inkscape {
46 namespace UI {
47 namespace Dialogs {
50 IconPreviewPanel* IconPreviewPanel::instance = 0;
53 IconPreviewPanel& IconPreviewPanel::getInstance()
54 {
55     if ( !instance ) {
56         instance = new IconPreviewPanel();
57     }
59     instance->refreshPreview();
61     return *instance;
62 }
64 //#########################################################################
65 //## E V E N T S
66 //#########################################################################
68 void IconPreviewPanel::on_button_clicked(int which)
69 {
70     if ( hot != which ) {
71         buttons[hot]->set_active( false );
73         hot = which;
74         updateMagnify();
75         queue_draw();
76     }
77 }
82 //#########################################################################
83 //## C O N S T R U C T O R    /    D E S T R U C T O R
84 //#########################################################################
85 /**
86  * Constructor
87  */
88 IconPreviewPanel::IconPreviewPanel() :
89     Panel(),
90     hot(1),
91     refreshButton(0),
92     selectionButton(0)
93 {
94     numEntries = 0;
95     Inkscape::XML::Node *things = inkscape_get_repr(INKSCAPE, "iconpreview.sizes.default");
96     if (things) {
97         std::vector<int> rawSizes;
98         for ( Inkscape::XML::Node *child = things->firstChild(); child; child = child->next() )
99         {
100             gchar const *id = child->attribute("id");
101             if ( id )
102             {
103                 std::string path("iconpreview.sizes.default.");
104                 path += id;
105                 gint show = prefs_get_int_attribute_limited( path.c_str(), "show", 1, 0, 1 );
106                 gint sizeVal = prefs_get_int_attribute( path.c_str(), "value", -1 );
107                 if ( show && (sizeVal > 0) )
108                 {
109                     rawSizes.push_back( sizeVal );
110                 }
111             }
112         }
114         if ( !rawSizes.empty() )
115         {
116             numEntries = rawSizes.size();
117             sizes = new int[numEntries];
118             int i = 0;
119             for ( std::vector<int>::iterator it = rawSizes.begin(); it != rawSizes.end(); ++it, ++i ) {
120                 sizes[i] = *it;
121             }
122         }
123     }
125     if ( numEntries < 1 )
126     {
127         numEntries = 5;
128         sizes = new int[numEntries];
129         sizes[0] = 16;
130         sizes[1] = 24;
131         sizes[2] = 32;
132         sizes[3] = 48;
133         sizes[5] = 128;
134     }
136     pixMem = new guchar*[numEntries];
137     images = new Gtk::Image*[numEntries];
138     labels = new Glib::ustring*[numEntries];
139     buttons = new Gtk::ToggleToolButton*[numEntries];
142     for ( int i = 0; i < numEntries; i++ ) {
143         char *label = g_strdup_printf(_("%d x %d"), sizes[i], sizes[i]);
144         labels[i] = new Glib::ustring(label);
145         g_free(label);
146         pixMem[i] = 0;
147         images[i] = 0;
148     }
151     magLabel.set_label( *labels[hot] );
153     Gtk::VBox* magBox = new Gtk::VBox();
155     magBox->pack_start( magnified );
156     magBox->pack_start( magLabel, Gtk::PACK_SHRINK );
159     Gtk::VBox * verts = new Gtk::VBox();
160     for ( int i = 0; i < numEntries; i++ ) {
161         pixMem[i] = new guchar[4 * sizes[i] * sizes[i]];
162         memset( pixMem[i], 0x00, 4 *  sizes[i] * sizes[i] );
164         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 );
165         GtkImage* img = GTK_IMAGE( gtk_image_new_from_pixbuf( pb ) );
166         images[i] = Glib::wrap(img);
167         Glib::ustring label(*labels[i]);
168         buttons[i] = new Gtk::ToggleToolButton(label);
169         buttons[i]->set_active( i == hot );
170         buttons[i]->set_icon_widget(*images[i]);
172         tips.set_tip((*buttons[i]), label);
174         buttons[i]->signal_clicked().connect( sigc::bind<int>( sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i) );
177         verts->add(*buttons[i]);
178     }
180     iconBox.pack_start(splitter);
181     splitter.pack1( *magBox, true, true );
182     splitter.pack2( *verts, false, false );
185     //## The Refresh button
188     Gtk::HButtonBox* holder = new Gtk::HButtonBox( Gtk::BUTTONBOX_END );
189     _getContents()->pack_end( *holder, false, false );
191     selectionButton = new Gtk::ToggleButton(_("Selection")); // , GTK_RESPONSE_APPLY
192     holder->pack_start( *selectionButton, false, false );
193     tips.set_tip((*selectionButton), _("Selection only or whole document"));
194     selectionButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::modeToggled) );
196     gint val = prefs_get_int_attribute_limited( "iconpreview", "selectionOnly", 0, 0, 1 );
197     selectionButton->set_active( val != 0 );
199     refreshButton = new Gtk::Button(Gtk::Stock::REFRESH); // , GTK_RESPONSE_APPLY
200     holder->pack_end( *refreshButton, false, false );
201     tips.set_tip((*refreshButton), _("Refresh the icons"));
202     refreshButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::refreshPreview) );
205     _getContents()->pack_start(iconBox, Gtk::PACK_EXPAND_WIDGET);
207     show_all_children();
210 //#########################################################################
211 //## M E T H O D S
212 //#########################################################################
215 void IconPreviewPanel::refreshPreview()
217     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
218     if ( desktop ) {
220         if ( selectionButton && selectionButton->get_active() )
221         {
222             Inkscape::Selection * sel = sp_desktop_selection(desktop);
223             if ( sel ) {
224                 //g_message("found a selection to play with");
226                 GSList const *items = sel->itemList();
227                 SPObject *target = 0;
228                 while ( items && !target ) {
229                     SPItem* item = SP_ITEM( items->data );
230                     SPObject * obj = SP_OBJECT(item);
231                     gchar const *id = SP_OBJECT_ID( obj );
232                     if ( id ) {
233                         target = obj;
234                     }
236                     items = g_slist_next(items);
237                 }
238                 if ( target ) {
239                     renderPreview(target);
240                 }
241             }
242         }
243         else
244         {
245             SPObject *target = desktop->currentRoot();
246             if ( target ) {
247                 renderPreview(target);
248             }
249         }
250     }
253 void IconPreviewPanel::modeToggled()
255     prefs_set_int_attribute( "iconpreview", "selectionOnly", (selectionButton && selectionButton->get_active()) ? 1 : 0 );
257     refreshPreview();
260 void IconPreviewPanel::renderPreview( SPObject* obj )
262     SPDocument * doc = SP_OBJECT_DOCUMENT(obj);
263     gchar * id = SP_OBJECT_ID(obj);
265 //    g_message(" setting up to render '%s' as the icon", id );
267     NRArenaItem *root = NULL;
269     /* Create new arena */
270     NRArena *arena = NRArena::create();
272     /* Create ArenaItem and set transform */
273     unsigned int visionkey = sp_item_display_key_new(1);
275     /* fixme: Memory manage root if needed (Lauris) */
276     root = sp_item_invoke_show ( SP_ITEM( SP_DOCUMENT_ROOT(doc) ),
277                                  arena, visionkey, SP_ITEM_SHOW_DISPLAY );
279     for ( int i = 0; i < numEntries; i++ ) {
280         guchar * px = sp_icon_doc_icon( doc, root, id, sizes[i] );
281 //         g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") );
282         if ( px ) {
283             memcpy( pixMem[i], px, sizes[i] * sizes[i] * 4 );
284             g_free( px );
285             px = 0;
286         } else {
287             memset( pixMem[i], 0, sizes[i] * sizes[i] * 4 );
288         }
289         images[i]->queue_draw();
290     }
291     updateMagnify();
294 void IconPreviewPanel::updateMagnify()
296     Glib::RefPtr<Gdk::Pixbuf> buf = images[hot]->get_pixbuf()->scale_simple( 128, 128, Gdk::INTERP_NEAREST );
297     magLabel.set_label( *labels[hot] );
298     magnified.set( buf );
299     magnified.queue_draw();
300     magnified.get_parent()->queue_draw();
304 } //namespace Dialogs
305 } //namespace UI
306 } //namespace Inkscape
308 /*
309   Local Variables:
310   mode:c++
311   c-file-style:"stroustrup"
312   c-file-offsets:((innamespace . 0)(inline-open . 0))
313   indent-tabs-mode:nil
314   fill-column:99
315   End:
316 */
317 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
319 //#########################################################################
320 //## E N D    O F    F I L E
321 //#########################################################################