4 #include <glib/gi18n.h>
5 #include <gtk/gtktooltips.h>
6 #include <gtk/gtktoolitem.h>
7 #include <gtk/gtktoggletoolbutton.h>
8 #include <gtk/gtkcheckmenuitem.h>
9 #include <gtk/gtkimagemenuitem.h>
11 #include "icon-size.h"
12 #include "ink-action.h"
14 #include "widgets/button.h"
15 #include "widgets/icon.h"
19 static void ink_action_class_init( InkActionClass* klass );
20 static void ink_action_init( InkAction* action );
21 static void ink_action_finalize( GObject* obj );
22 static void ink_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
23 static void ink_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
25 static GtkWidget* ink_action_create_menu_item( GtkAction* action );
26 static GtkWidget* ink_action_create_tool_item( GtkAction* action );
28 static GtkActionClass* gInkActionParentClass = 0;
30 struct _InkActionPrivate
31 {
32 gchar* iconId;
33 Inkscape::IconSize iconSize;
34 };
36 #define INK_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_ACTION_TYPE, InkActionPrivate ) )
38 GType ink_action_get_type( void )
39 {
40 static GType myType = 0;
41 if ( !myType ) {
42 static const GTypeInfo myInfo = {
43 sizeof( InkActionClass ),
44 NULL, /* base_init */
45 NULL, /* base_finalize */
46 (GClassInitFunc)ink_action_class_init,
47 NULL, /* class_finalize */
48 NULL, /* class_data */
49 sizeof( InkAction ),
50 0, /* n_preallocs */
51 (GInstanceInitFunc)ink_action_init,
52 NULL
53 };
55 myType = g_type_register_static( GTK_TYPE_ACTION, "InkAction", &myInfo, (GTypeFlags)0 );
56 }
58 return myType;
59 }
61 enum {
62 PROP_INK_ID = 1,
63 PROP_INK_SIZE
64 };
66 static void ink_action_class_init( InkActionClass* klass )
67 {
68 if ( klass ) {
69 gInkActionParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) );
70 GObjectClass * objClass = G_OBJECT_CLASS( klass );
72 objClass->finalize = ink_action_finalize;
73 objClass->get_property = ink_action_get_property;
74 objClass->set_property = ink_action_set_property;
76 klass->parent_class.create_menu_item = ink_action_create_menu_item;
77 klass->parent_class.create_tool_item = ink_action_create_tool_item;
78 /*klass->parent_class.connect_proxy = connect_proxy;*/
79 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
81 g_object_class_install_property( objClass,
82 PROP_INK_ID,
83 g_param_spec_string( "iconId",
84 "Icon ID",
85 "The id for the icon",
86 "",
87 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
89 g_object_class_install_property( objClass,
90 PROP_INK_SIZE,
91 g_param_spec_int( "iconSize",
92 "Icon Size",
93 "The size the icon",
94 (int)Inkscape::ICON_SIZE_MENU,
95 (int)Inkscape::ICON_SIZE_DECORATION,
96 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
97 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
99 g_type_class_add_private( klass, sizeof(InkActionClass) );
100 }
101 }
103 static void ink_action_init( InkAction* action )
104 {
105 action->private_data = INK_ACTION_GET_PRIVATE( action );
106 action->private_data->iconId = 0;
107 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
108 }
110 static void ink_action_finalize( GObject* obj )
111 {
112 InkAction* action = INK_ACTION( obj );
114 g_free( action->private_data->iconId );
115 g_free( action->private_data );
117 }
119 //Any strings passed in should already be localised
120 InkAction* ink_action_new( const gchar *name,
121 const gchar *label,
122 const gchar *tooltip,
123 const gchar *inkId,
124 Inkscape::IconSize size )
125 {
126 GObject* obj = (GObject*)g_object_new( INK_ACTION_TYPE,
127 "name", name,
128 "label", label,
129 "tooltip", tooltip,
130 "iconId", inkId,
131 "iconSize", size,
132 NULL );
134 InkAction* action = INK_ACTION( obj );
136 return action;
137 }
139 static void ink_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
140 {
141 InkAction* action = INK_ACTION( obj );
142 (void)action;
143 switch ( propId ) {
144 case PROP_INK_ID:
145 {
146 g_value_set_string( value, action->private_data->iconId );
147 }
148 break;
150 case PROP_INK_SIZE:
151 {
152 g_value_set_int( value, action->private_data->iconSize );
153 }
154 break;
156 default:
157 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
158 }
159 }
161 void ink_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
162 {
163 InkAction* action = INK_ACTION( obj );
164 (void)action;
165 switch ( propId ) {
166 case PROP_INK_ID:
167 {
168 gchar* tmp = action->private_data->iconId;
169 action->private_data->iconId = g_value_dup_string( value );
170 g_free( tmp );
171 }
172 break;
174 case PROP_INK_SIZE:
175 {
176 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
177 }
178 break;
180 default:
181 {
182 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
183 }
184 }
185 }
187 #include <gtk/gtkstock.h>
189 static GtkWidget* ink_action_create_menu_item( GtkAction* action )
190 {
191 InkAction* act = INK_ACTION( action );
192 GtkWidget* item = 0;
194 if ( act->private_data->iconId ) {
195 gchar* label = 0;
196 g_object_get( G_OBJECT(act), "label", &label, NULL );
198 item = gtk_image_menu_item_new_with_mnemonic( label );
199 GtkWidget* child = sp_icon_new( Inkscape::ICON_SIZE_MENU, act->private_data->iconId );
200 // TODO this work-around is until SPIcon will live properly inside of a popup menu
201 if ( SP_IS_ICON(child) ) {
202 SPIcon* icon = SP_ICON(child);
203 sp_icon_fetch_pixbuf( icon );
204 GdkPixbuf* target = gtk_action_is_sensitive(action) ? icon->pb : icon->pb_faded;
205 if ( target ) {
206 child = gtk_image_new_from_pixbuf( target );
207 gtk_widget_destroy( GTK_WIDGET(icon) );
208 }
209 }
210 gtk_widget_show_all( child );
211 gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM(item), child );
213 g_free( label );
214 label = 0;
215 } else {
216 item = gInkActionParentClass->create_menu_item( action );
217 }
219 return item;
220 }
222 static GtkWidget* ink_action_create_tool_item( GtkAction* action )
223 {
224 InkAction* act = INK_ACTION( action );
225 GtkWidget* item = gInkActionParentClass->create_tool_item(action);
227 if ( act->private_data->iconId ) {
228 if ( GTK_IS_TOOL_BUTTON(item) ) {
229 GtkToolButton* button = GTK_TOOL_BUTTON(item);
231 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
232 gtk_tool_button_set_icon_widget( button, child );
233 } else {
234 // For now trigger a warning but don't do anything else
235 GtkToolButton* button = GTK_TOOL_BUTTON(item);
236 (void)button;
237 }
238 }
240 // TODO investigate if needed
241 gtk_widget_show_all( item );
243 return item;
244 }
248 /* --------------------------------------------------------------- */
249 /* --------------------------------------------------------------- */
250 /* --------------------------------------------------------------- */
251 /* --------------------------------------------------------------- */
254 static void ink_toggle_action_class_init( InkToggleActionClass* klass );
255 static void ink_toggle_action_init( InkToggleAction* action );
256 static void ink_toggle_action_finalize( GObject* obj );
257 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
258 static void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
260 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action );
261 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action );
263 static void ink_toggle_action_update_icon( InkToggleAction* action );
265 static GtkToggleActionClass* gInkToggleActionParentClass = 0;
267 struct _InkToggleActionPrivate
268 {
269 gchar* iconId;
270 Inkscape::IconSize iconSize;
271 };
273 #define INK_TOGGLE_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_TOGGLE_ACTION_TYPE, InkToggleActionPrivate ) )
275 GType ink_toggle_action_get_type( void )
276 {
277 static GType myType = 0;
278 if ( !myType ) {
279 static const GTypeInfo myInfo = {
280 sizeof( InkToggleActionClass ),
281 NULL, /* base_init */
282 NULL, /* base_finalize */
283 (GClassInitFunc)ink_toggle_action_class_init,
284 NULL, /* class_finalize */
285 NULL, /* class_data */
286 sizeof( InkToggleAction ),
287 0, /* n_preallocs */
288 (GInstanceInitFunc)ink_toggle_action_init,
289 NULL
290 };
292 myType = g_type_register_static( GTK_TYPE_TOGGLE_ACTION, "InkToggleAction", &myInfo, (GTypeFlags)0 );
293 }
295 return myType;
296 }
299 static void ink_toggle_action_class_init( InkToggleActionClass* klass )
300 {
301 if ( klass ) {
302 gInkToggleActionParentClass = GTK_TOGGLE_ACTION_CLASS( g_type_class_peek_parent( klass ) );
303 GObjectClass * objClass = G_OBJECT_CLASS( klass );
305 objClass->finalize = ink_toggle_action_finalize;
306 objClass->get_property = ink_toggle_action_get_property;
307 objClass->set_property = ink_toggle_action_set_property;
309 klass->parent_class.parent_class.create_menu_item = ink_toggle_action_create_menu_item;
310 klass->parent_class.parent_class.create_tool_item = ink_toggle_action_create_tool_item;
311 /*klass->parent_class.connect_proxy = connect_proxy;*/
312 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
314 g_object_class_install_property( objClass,
315 PROP_INK_ID,
316 g_param_spec_string( "iconId",
317 "Icon ID",
318 "The id for the icon",
319 "",
320 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
322 g_object_class_install_property( objClass,
323 PROP_INK_SIZE,
324 g_param_spec_int( "iconSize",
325 "Icon Size",
326 "The size the icon",
327 (int)Inkscape::ICON_SIZE_MENU,
328 (int)Inkscape::ICON_SIZE_DECORATION,
329 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
330 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
332 g_type_class_add_private( klass, sizeof(InkToggleActionClass) );
333 }
334 }
336 static void ink_toggle_action_init( InkToggleAction* action )
337 {
338 action->private_data = INK_TOGGLE_ACTION_GET_PRIVATE( action );
339 action->private_data->iconId = 0;
340 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
341 }
343 static void ink_toggle_action_finalize( GObject* obj )
344 {
345 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
347 g_free( action->private_data->iconId );
348 g_free( action->private_data );
350 }
352 InkToggleAction* ink_toggle_action_new( const gchar *name,
353 const gchar *label,
354 const gchar *tooltip,
355 const gchar *inkId,
356 Inkscape::IconSize size )
357 {
358 GObject* obj = (GObject*)g_object_new( INK_TOGGLE_ACTION_TYPE,
359 "name", name,
360 "label", label,
361 "tooltip", tooltip,
362 "iconId", inkId,
363 "iconSize", size,
364 NULL );
366 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
368 return action;
369 }
371 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
372 {
373 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
374 (void)action;
375 switch ( propId ) {
376 case PROP_INK_ID:
377 {
378 g_value_set_string( value, action->private_data->iconId );
379 }
380 break;
382 case PROP_INK_SIZE:
383 {
384 g_value_set_int( value, action->private_data->iconSize );
385 }
386 break;
388 default:
389 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
390 }
391 }
393 void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
394 {
395 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
396 (void)action;
397 switch ( propId ) {
398 case PROP_INK_ID:
399 {
400 gchar* tmp = action->private_data->iconId;
401 action->private_data->iconId = g_value_dup_string( value );
402 g_free( tmp );
404 ink_toggle_action_update_icon( action );
405 }
406 break;
408 case PROP_INK_SIZE:
409 {
410 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
411 }
412 break;
414 default:
415 {
416 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
417 }
418 }
419 }
421 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action )
422 {
423 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_menu_item(action);
425 return item;
426 }
428 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action )
429 {
430 InkToggleAction* act = INK_TOGGLE_ACTION( action );
432 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_tool_item(action);
433 if ( GTK_IS_TOOL_BUTTON(item) ) {
434 GtkToolButton* button = GTK_TOOL_BUTTON(item);
435 if ( act->private_data->iconId ) {
436 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
437 gtk_tool_button_set_icon_widget( button, child );
438 } else {
439 gchar *label;
440 g_object_get (G_OBJECT(action), "short_label", &label, NULL);
441 gtk_tool_button_set_label( button, label );
442 }
443 } else {
444 // For now trigger a warning but don't do anything else
445 GtkToolButton* button = GTK_TOOL_BUTTON(item);
446 (void)button;
447 }
448 gtk_widget_show_all( item );
450 return item;
451 }
454 static void ink_toggle_action_update_icon( InkToggleAction* action )
455 {
456 if ( action ) {
457 GSList* proxies = gtk_action_get_proxies( GTK_ACTION(action) );
458 while ( proxies ) {
459 if ( GTK_IS_TOOL_ITEM(proxies->data) ) {
460 if ( GTK_IS_TOOL_BUTTON(proxies->data) ) {
461 GtkToolButton* button = GTK_TOOL_BUTTON(proxies->data);
463 GtkWidget* child = sp_icon_new( action->private_data->iconSize, action->private_data->iconId );
464 gtk_widget_show_all( child );
465 gtk_tool_button_set_icon_widget( button, child );
466 }
467 }
469 proxies = g_slist_next( proxies );
470 }
471 }
472 }
475 /* --------------------------------------------------------------- */
476 /* --------------------------------------------------------------- */
477 /* --------------------------------------------------------------- */
478 /* --------------------------------------------------------------- */
481 static void ink_radio_action_class_init( InkRadioActionClass* klass );
482 static void ink_radio_action_init( InkRadioAction* action );
483 static void ink_radio_action_finalize( GObject* obj );
484 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
485 static void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
487 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action );
488 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action );
490 static GtkRadioActionClass* gInkRadioActionParentClass = 0;
492 struct _InkRadioActionPrivate
493 {
494 gchar* iconId;
495 Inkscape::IconSize iconSize;
496 };
498 #define INK_RADIO_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_RADIO_ACTION_TYPE, InkRadioActionPrivate ) )
500 GType ink_radio_action_get_type( void )
501 {
502 static GType myType = 0;
503 if ( !myType ) {
504 static const GTypeInfo myInfo = {
505 sizeof( InkRadioActionClass ),
506 NULL, /* base_init */
507 NULL, /* base_finalize */
508 (GClassInitFunc)ink_radio_action_class_init,
509 NULL, /* class_finalize */
510 NULL, /* class_data */
511 sizeof( InkRadioAction ),
512 0, /* n_preallocs */
513 (GInstanceInitFunc)ink_radio_action_init,
514 NULL
515 };
517 myType = g_type_register_static( GTK_TYPE_RADIO_ACTION, "InkRadioAction", &myInfo, (GTypeFlags)0 );
518 }
520 return myType;
521 }
524 static void ink_radio_action_class_init( InkRadioActionClass* klass )
525 {
526 if ( klass ) {
527 gInkRadioActionParentClass = GTK_RADIO_ACTION_CLASS( g_type_class_peek_parent( klass ) );
528 GObjectClass * objClass = G_OBJECT_CLASS( klass );
530 objClass->finalize = ink_radio_action_finalize;
531 objClass->get_property = ink_radio_action_get_property;
532 objClass->set_property = ink_radio_action_set_property;
534 klass->parent_class.parent_class.parent_class.create_menu_item = ink_radio_action_create_menu_item;
535 klass->parent_class.parent_class.parent_class.create_tool_item = ink_radio_action_create_tool_item;
536 /*klass->parent_class.connect_proxy = connect_proxy;*/
537 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
539 g_object_class_install_property( objClass,
540 PROP_INK_ID,
541 g_param_spec_string( "iconId",
542 "Icon ID",
543 "The id for the icon",
544 "",
545 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
547 g_object_class_install_property( objClass,
548 PROP_INK_SIZE,
549 g_param_spec_int( "iconSize",
550 "Icon Size",
551 "The size the icon",
552 (int)Inkscape::ICON_SIZE_MENU,
553 (int)Inkscape::ICON_SIZE_DECORATION,
554 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
555 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
557 g_type_class_add_private( klass, sizeof(InkRadioActionClass) );
558 }
559 }
561 static void ink_radio_action_init( InkRadioAction* action )
562 {
563 action->private_data = INK_RADIO_ACTION_GET_PRIVATE( action );
564 action->private_data->iconId = 0;
565 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
566 }
568 static void ink_radio_action_finalize( GObject* obj )
569 {
570 InkRadioAction* action = INK_RADIO_ACTION( obj );
572 g_free( action->private_data->iconId );
573 g_free( action->private_data );
575 }
577 InkRadioAction* ink_radio_action_new( const gchar *name,
578 const gchar *label,
579 const gchar *tooltip,
580 const gchar *inkId,
581 Inkscape::IconSize size )
582 {
583 GObject* obj = (GObject*)g_object_new( INK_RADIO_ACTION_TYPE,
584 "name", name,
585 "label", label,
586 "tooltip", tooltip,
587 "iconId", inkId,
588 "iconSize", size,
589 NULL );
591 InkRadioAction* action = INK_RADIO_ACTION( obj );
593 return action;
594 }
596 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
597 {
598 InkRadioAction* action = INK_RADIO_ACTION( obj );
599 (void)action;
600 switch ( propId ) {
601 case PROP_INK_ID:
602 {
603 g_value_set_string( value, action->private_data->iconId );
604 }
605 break;
607 case PROP_INK_SIZE:
608 {
609 g_value_set_int( value, action->private_data->iconSize );
610 }
611 break;
613 default:
614 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
615 }
616 }
618 void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
619 {
620 InkRadioAction* action = INK_RADIO_ACTION( obj );
621 (void)action;
622 switch ( propId ) {
623 case PROP_INK_ID:
624 {
625 gchar* tmp = action->private_data->iconId;
626 action->private_data->iconId = g_value_dup_string( value );
627 g_free( tmp );
628 }
629 break;
631 case PROP_INK_SIZE:
632 {
633 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
634 }
635 break;
637 default:
638 {
639 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
640 }
641 }
642 }
644 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action )
645 {
646 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_menu_item(action);
648 return item;
649 }
651 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action )
652 {
653 InkRadioAction* act = INK_RADIO_ACTION( action );
654 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_tool_item(action);
656 if ( act->private_data->iconId ) {
657 if ( GTK_IS_TOOL_BUTTON(item) ) {
658 GtkToolButton* button = GTK_TOOL_BUTTON(item);
660 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
661 gtk_tool_button_set_icon_widget( button, child );
662 } else {
663 // For now trigger a warning but don't do anything else
664 GtkToolButton* button = GTK_TOOL_BUTTON(item);
665 (void)button;
666 }
667 }
669 // TODO investigate if needed
670 gtk_widget_show_all( item );
672 return item;
673 }