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