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 InkAction* ink_action_new( const gchar *name,
120 const gchar *label,
121 const gchar *tooltip,
122 const gchar *inkId,
123 Inkscape::IconSize size )
124 {
125 GObject* obj = (GObject*)g_object_new( INK_ACTION_TYPE,
126 "name", name,
127 "label", label,
128 "tooltip", tooltip,
129 "iconId", inkId,
130 "iconSize", size,
131 NULL );
133 InkAction* action = INK_ACTION( obj );
135 return action;
136 }
138 static void ink_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
139 {
140 InkAction* action = INK_ACTION( obj );
141 (void)action;
142 switch ( propId ) {
143 case PROP_INK_ID:
144 {
145 g_value_set_string( value, action->private_data->iconId );
146 }
147 break;
149 case PROP_INK_SIZE:
150 {
151 g_value_set_int( value, action->private_data->iconSize );
152 }
153 break;
155 default:
156 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
157 }
158 }
160 void ink_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
161 {
162 InkAction* action = INK_ACTION( obj );
163 (void)action;
164 switch ( propId ) {
165 case PROP_INK_ID:
166 {
167 gchar* tmp = action->private_data->iconId;
168 action->private_data->iconId = g_value_dup_string( value );
169 g_free( tmp );
170 }
171 break;
173 case PROP_INK_SIZE:
174 {
175 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
176 }
177 break;
179 default:
180 {
181 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
182 }
183 }
184 }
186 #include <gtk/gtkstock.h>
188 static GtkWidget* ink_action_create_menu_item( GtkAction* action )
189 {
190 InkAction* act = INK_ACTION( action );
191 GtkWidget* item = 0;
193 if ( act->private_data->iconId ) {
194 gchar* label = 0;
195 g_object_get( G_OBJECT(act), "label", &label, NULL );
197 item = gtk_image_menu_item_new_with_mnemonic( label );
198 GtkWidget* child = sp_icon_new( Inkscape::ICON_SIZE_MENU, act->private_data->iconId );
199 // TODO this work-around is until SPIcon will live properly inside of a popup menu
200 if ( SP_IS_ICON(child) ) {
201 SPIcon* icon = SP_ICON(child);
202 sp_icon_fetch_pixbuf( icon );
203 GdkPixbuf* target = gtk_action_is_sensitive(action) ? icon->pb : icon->pb_faded;
204 if ( target ) {
205 child = gtk_image_new_from_pixbuf( target );
206 gtk_widget_destroy( GTK_WIDGET(icon) );
207 }
208 }
209 gtk_widget_show_all( child );
210 gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM(item), child );
212 g_free( label );
213 label = 0;
214 } else {
215 item = gInkActionParentClass->create_menu_item( action );
216 }
218 return item;
219 }
221 static GtkWidget* ink_action_create_tool_item( GtkAction* action )
222 {
223 InkAction* act = INK_ACTION( action );
224 GtkWidget* item = gInkActionParentClass->create_tool_item(action);
226 if ( act->private_data->iconId ) {
227 if ( GTK_IS_TOOL_BUTTON(item) ) {
228 GtkToolButton* button = GTK_TOOL_BUTTON(item);
230 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
231 gtk_tool_button_set_icon_widget( button, child );
232 } else {
233 // For now trigger a warning but don't do anything else
234 GtkToolButton* button = GTK_TOOL_BUTTON(item);
235 (void)button;
236 }
237 }
239 // TODO investigate if needed
240 gtk_widget_show_all( item );
242 return item;
243 }
247 /* --------------------------------------------------------------- */
248 /* --------------------------------------------------------------- */
249 /* --------------------------------------------------------------- */
250 /* --------------------------------------------------------------- */
253 static void ink_toggle_action_class_init( InkToggleActionClass* klass );
254 static void ink_toggle_action_init( InkToggleAction* action );
255 static void ink_toggle_action_finalize( GObject* obj );
256 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
257 static void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
259 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action );
260 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action );
262 static void ink_toggle_action_update_icon( InkToggleAction* action );
264 static GtkToggleActionClass* gInkToggleActionParentClass = 0;
266 struct _InkToggleActionPrivate
267 {
268 gchar* iconId;
269 Inkscape::IconSize iconSize;
270 };
272 #define INK_TOGGLE_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_TOGGLE_ACTION_TYPE, InkToggleActionPrivate ) )
274 GType ink_toggle_action_get_type( void )
275 {
276 static GType myType = 0;
277 if ( !myType ) {
278 static const GTypeInfo myInfo = {
279 sizeof( InkToggleActionClass ),
280 NULL, /* base_init */
281 NULL, /* base_finalize */
282 (GClassInitFunc)ink_toggle_action_class_init,
283 NULL, /* class_finalize */
284 NULL, /* class_data */
285 sizeof( InkToggleAction ),
286 0, /* n_preallocs */
287 (GInstanceInitFunc)ink_toggle_action_init,
288 NULL
289 };
291 myType = g_type_register_static( GTK_TYPE_TOGGLE_ACTION, "InkToggleAction", &myInfo, (GTypeFlags)0 );
292 }
294 return myType;
295 }
298 static void ink_toggle_action_class_init( InkToggleActionClass* klass )
299 {
300 if ( klass ) {
301 gInkToggleActionParentClass = GTK_TOGGLE_ACTION_CLASS( g_type_class_peek_parent( klass ) );
302 GObjectClass * objClass = G_OBJECT_CLASS( klass );
304 objClass->finalize = ink_toggle_action_finalize;
305 objClass->get_property = ink_toggle_action_get_property;
306 objClass->set_property = ink_toggle_action_set_property;
308 klass->parent_class.parent_class.create_menu_item = ink_toggle_action_create_menu_item;
309 klass->parent_class.parent_class.create_tool_item = ink_toggle_action_create_tool_item;
310 /*klass->parent_class.connect_proxy = connect_proxy;*/
311 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
313 g_object_class_install_property( objClass,
314 PROP_INK_ID,
315 g_param_spec_string( "iconId",
316 "Icon ID",
317 "The id for the icon",
318 "",
319 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
321 g_object_class_install_property( objClass,
322 PROP_INK_SIZE,
323 g_param_spec_int( "iconSize",
324 "Icon Size",
325 "The size the icon",
326 (int)Inkscape::ICON_SIZE_MENU,
327 (int)Inkscape::ICON_SIZE_DECORATION,
328 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
329 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
331 g_type_class_add_private( klass, sizeof(InkToggleActionClass) );
332 }
333 }
335 static void ink_toggle_action_init( InkToggleAction* action )
336 {
337 action->private_data = INK_TOGGLE_ACTION_GET_PRIVATE( action );
338 action->private_data->iconId = 0;
339 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
340 }
342 static void ink_toggle_action_finalize( GObject* obj )
343 {
344 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
346 g_free( action->private_data->iconId );
347 g_free( action->private_data );
349 }
351 InkToggleAction* ink_toggle_action_new( const gchar *name,
352 const gchar *label,
353 const gchar *tooltip,
354 const gchar *inkId,
355 Inkscape::IconSize size )
356 {
357 GObject* obj = (GObject*)g_object_new( INK_TOGGLE_ACTION_TYPE,
358 "name", name,
359 "label", label,
360 "tooltip", tooltip,
361 "iconId", inkId,
362 "iconSize", size,
363 NULL );
365 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
367 return action;
368 }
370 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
371 {
372 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
373 (void)action;
374 switch ( propId ) {
375 case PROP_INK_ID:
376 {
377 g_value_set_string( value, action->private_data->iconId );
378 }
379 break;
381 case PROP_INK_SIZE:
382 {
383 g_value_set_int( value, action->private_data->iconSize );
384 }
385 break;
387 default:
388 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
389 }
390 }
392 void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
393 {
394 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
395 (void)action;
396 switch ( propId ) {
397 case PROP_INK_ID:
398 {
399 gchar* tmp = action->private_data->iconId;
400 action->private_data->iconId = g_value_dup_string( value );
401 g_free( tmp );
403 ink_toggle_action_update_icon( action );
404 }
405 break;
407 case PROP_INK_SIZE:
408 {
409 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
410 }
411 break;
413 default:
414 {
415 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
416 }
417 }
418 }
420 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action )
421 {
422 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_menu_item(action);
424 return item;
425 }
427 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action )
428 {
429 InkToggleAction* act = INK_TOGGLE_ACTION( action );
430 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_tool_item(action);
432 if ( act->private_data->iconId ) {
433 if ( GTK_IS_TOOL_BUTTON(item) ) {
434 GtkToolButton* button = GTK_TOOL_BUTTON(item);
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 // For now trigger a warning but don't do anything else
440 GtkToolButton* button = GTK_TOOL_BUTTON(item);
441 (void)button;
442 }
443 }
445 // TODO investigate if needed
446 gtk_widget_show_all( item );
448 return item;
449 }
452 static void ink_toggle_action_update_icon( InkToggleAction* action )
453 {
454 if ( action ) {
455 GSList* proxies = gtk_action_get_proxies( GTK_ACTION(action) );
456 while ( proxies ) {
457 if ( GTK_IS_TOOL_ITEM(proxies->data) ) {
458 if ( GTK_IS_TOOL_BUTTON(proxies->data) ) {
459 GtkToolButton* button = GTK_TOOL_BUTTON(proxies->data);
461 GtkWidget* child = sp_icon_new( action->private_data->iconSize, action->private_data->iconId );
462 gtk_widget_show_all( child );
463 gtk_tool_button_set_icon_widget( button, child );
464 }
465 }
467 proxies = g_slist_next( proxies );
468 }
469 }
470 }
473 /* --------------------------------------------------------------- */
474 /* --------------------------------------------------------------- */
475 /* --------------------------------------------------------------- */
476 /* --------------------------------------------------------------- */
479 static void ink_radio_action_class_init( InkRadioActionClass* klass );
480 static void ink_radio_action_init( InkRadioAction* action );
481 static void ink_radio_action_finalize( GObject* obj );
482 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
483 static void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
485 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action );
486 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action );
488 static GtkRadioActionClass* gInkRadioActionParentClass = 0;
490 struct _InkRadioActionPrivate
491 {
492 gchar* iconId;
493 Inkscape::IconSize iconSize;
494 };
496 #define INK_RADIO_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_RADIO_ACTION_TYPE, InkRadioActionPrivate ) )
498 GType ink_radio_action_get_type( void )
499 {
500 static GType myType = 0;
501 if ( !myType ) {
502 static const GTypeInfo myInfo = {
503 sizeof( InkRadioActionClass ),
504 NULL, /* base_init */
505 NULL, /* base_finalize */
506 (GClassInitFunc)ink_radio_action_class_init,
507 NULL, /* class_finalize */
508 NULL, /* class_data */
509 sizeof( InkRadioAction ),
510 0, /* n_preallocs */
511 (GInstanceInitFunc)ink_radio_action_init,
512 NULL
513 };
515 myType = g_type_register_static( GTK_TYPE_RADIO_ACTION, "InkRadioAction", &myInfo, (GTypeFlags)0 );
516 }
518 return myType;
519 }
522 static void ink_radio_action_class_init( InkRadioActionClass* klass )
523 {
524 if ( klass ) {
525 gInkRadioActionParentClass = GTK_RADIO_ACTION_CLASS( g_type_class_peek_parent( klass ) );
526 GObjectClass * objClass = G_OBJECT_CLASS( klass );
528 objClass->finalize = ink_radio_action_finalize;
529 objClass->get_property = ink_radio_action_get_property;
530 objClass->set_property = ink_radio_action_set_property;
532 klass->parent_class.parent_class.parent_class.create_menu_item = ink_radio_action_create_menu_item;
533 klass->parent_class.parent_class.parent_class.create_tool_item = ink_radio_action_create_tool_item;
534 /*klass->parent_class.connect_proxy = connect_proxy;*/
535 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
537 g_object_class_install_property( objClass,
538 PROP_INK_ID,
539 g_param_spec_string( "iconId",
540 "Icon ID",
541 "The id for the icon",
542 "",
543 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
545 g_object_class_install_property( objClass,
546 PROP_INK_SIZE,
547 g_param_spec_int( "iconSize",
548 "Icon Size",
549 "The size the icon",
550 (int)Inkscape::ICON_SIZE_MENU,
551 (int)Inkscape::ICON_SIZE_DECORATION,
552 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
553 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
555 g_type_class_add_private( klass, sizeof(InkRadioActionClass) );
556 }
557 }
559 static void ink_radio_action_init( InkRadioAction* action )
560 {
561 action->private_data = INK_RADIO_ACTION_GET_PRIVATE( action );
562 action->private_data->iconId = 0;
563 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
564 }
566 static void ink_radio_action_finalize( GObject* obj )
567 {
568 InkRadioAction* action = INK_RADIO_ACTION( obj );
570 g_free( action->private_data->iconId );
571 g_free( action->private_data );
573 }
575 InkRadioAction* ink_radio_action_new( const gchar *name,
576 const gchar *label,
577 const gchar *tooltip,
578 const gchar *inkId,
579 Inkscape::IconSize size )
580 {
581 GObject* obj = (GObject*)g_object_new( INK_RADIO_ACTION_TYPE,
582 "name", name,
583 "label", label,
584 "tooltip", tooltip,
585 "iconId", inkId,
586 "iconSize", size,
587 NULL );
589 InkRadioAction* action = INK_RADIO_ACTION( obj );
591 return action;
592 }
594 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
595 {
596 InkRadioAction* action = INK_RADIO_ACTION( obj );
597 (void)action;
598 switch ( propId ) {
599 case PROP_INK_ID:
600 {
601 g_value_set_string( value, action->private_data->iconId );
602 }
603 break;
605 case PROP_INK_SIZE:
606 {
607 g_value_set_int( value, action->private_data->iconSize );
608 }
609 break;
611 default:
612 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
613 }
614 }
616 void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
617 {
618 InkRadioAction* action = INK_RADIO_ACTION( obj );
619 (void)action;
620 switch ( propId ) {
621 case PROP_INK_ID:
622 {
623 gchar* tmp = action->private_data->iconId;
624 action->private_data->iconId = g_value_dup_string( value );
625 g_free( tmp );
626 }
627 break;
629 case PROP_INK_SIZE:
630 {
631 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
632 }
633 break;
635 default:
636 {
637 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
638 }
639 }
640 }
642 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action )
643 {
644 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_menu_item(action);
646 return item;
647 }
649 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action )
650 {
651 InkRadioAction* act = INK_RADIO_ACTION( action );
652 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_tool_item(action);
654 if ( act->private_data->iconId ) {
655 if ( GTK_IS_TOOL_BUTTON(item) ) {
656 GtkToolButton* button = GTK_TOOL_BUTTON(item);
658 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
659 gtk_tool_button_set_icon_widget( button, child );
660 } else {
661 // For now trigger a warning but don't do anything else
662 GtkToolButton* button = GTK_TOOL_BUTTON(item);
663 (void)button;
664 }
665 }
667 // TODO investigate if needed
668 gtk_widget_show_all( item );
670 return item;
671 }