4 #include <glib/gi18n.h>
5 #include <gtk/gtkalignment.h>
6 #include <gtk/gtktooltips.h>
7 #include <gtk/gtktoolitem.h>
8 #include <gtk/gtktoggletoolbutton.h>
9 #include <gtk/gtkcheckmenuitem.h>
10 #include <gtk/gtkimagemenuitem.h>
12 #include "icon-size.h"
13 #include "ink-action.h"
15 #include "widgets/button.h"
16 #include "widgets/icon.h"
20 static void ink_action_class_init( InkActionClass* klass );
21 static void ink_action_init( InkAction* action );
22 static void ink_action_finalize( GObject* obj );
23 static void ink_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
24 static void ink_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
26 static GtkWidget* ink_action_create_menu_item( GtkAction* action );
27 static GtkWidget* ink_action_create_tool_item( GtkAction* action );
29 static GtkActionClass* gInkActionParentClass = 0;
31 struct _InkActionPrivate
32 {
33 gchar* iconId;
34 Inkscape::IconSize iconSize;
35 };
37 #define INK_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_ACTION_TYPE, InkActionPrivate ) )
39 GType ink_action_get_type( void )
40 {
41 static GType myType = 0;
42 if ( !myType ) {
43 static const GTypeInfo myInfo = {
44 sizeof( InkActionClass ),
45 NULL, /* base_init */
46 NULL, /* base_finalize */
47 (GClassInitFunc)ink_action_class_init,
48 NULL, /* class_finalize */
49 NULL, /* class_data */
50 sizeof( InkAction ),
51 0, /* n_preallocs */
52 (GInstanceInitFunc)ink_action_init,
53 NULL
54 };
56 myType = g_type_register_static( GTK_TYPE_ACTION, "InkAction", &myInfo, (GTypeFlags)0 );
57 }
59 return myType;
60 }
62 enum {
63 PROP_INK_ID = 1,
64 PROP_INK_SIZE
65 };
67 static void ink_action_class_init( InkActionClass* klass )
68 {
69 if ( klass ) {
70 gInkActionParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) );
71 GObjectClass * objClass = G_OBJECT_CLASS( klass );
73 objClass->finalize = ink_action_finalize;
74 objClass->get_property = ink_action_get_property;
75 objClass->set_property = ink_action_set_property;
77 klass->parent_class.create_menu_item = ink_action_create_menu_item;
78 klass->parent_class.create_tool_item = ink_action_create_tool_item;
79 /*klass->parent_class.connect_proxy = connect_proxy;*/
80 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
82 g_object_class_install_property( objClass,
83 PROP_INK_ID,
84 g_param_spec_string( "iconId",
85 "Icon ID",
86 "The id for the icon",
87 "",
88 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
90 g_object_class_install_property( objClass,
91 PROP_INK_SIZE,
92 g_param_spec_int( "iconSize",
93 "Icon Size",
94 "The size the icon",
95 (int)Inkscape::ICON_SIZE_MENU,
96 (int)Inkscape::ICON_SIZE_DECORATION,
97 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
98 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
100 g_type_class_add_private( klass, sizeof(InkActionClass) );
101 }
102 }
104 static void ink_action_init( InkAction* action )
105 {
106 action->private_data = INK_ACTION_GET_PRIVATE( action );
107 action->private_data->iconId = 0;
108 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
109 }
111 static void ink_action_finalize( GObject* obj )
112 {
113 InkAction* action = INK_ACTION( obj );
115 g_free( action->private_data->iconId );
116 g_free( action->private_data );
118 }
120 //Any strings passed in should already be localised
121 InkAction* ink_action_new( const gchar *name,
122 const gchar *label,
123 const gchar *tooltip,
124 const gchar *inkId,
125 Inkscape::IconSize size )
126 {
127 GObject* obj = (GObject*)g_object_new( INK_ACTION_TYPE,
128 "name", name,
129 "label", label,
130 "tooltip", tooltip,
131 "iconId", inkId,
132 "iconSize", size,
133 NULL );
135 InkAction* action = INK_ACTION( obj );
137 return action;
138 }
140 static void ink_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
141 {
142 InkAction* action = INK_ACTION( obj );
143 (void)action;
144 switch ( propId ) {
145 case PROP_INK_ID:
146 {
147 g_value_set_string( value, action->private_data->iconId );
148 }
149 break;
151 case PROP_INK_SIZE:
152 {
153 g_value_set_int( value, action->private_data->iconSize );
154 }
155 break;
157 default:
158 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
159 }
160 }
162 void ink_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
163 {
164 InkAction* action = INK_ACTION( obj );
165 (void)action;
166 switch ( propId ) {
167 case PROP_INK_ID:
168 {
169 gchar* tmp = action->private_data->iconId;
170 action->private_data->iconId = g_value_dup_string( value );
171 g_free( tmp );
172 }
173 break;
175 case PROP_INK_SIZE:
176 {
177 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
178 }
179 break;
181 default:
182 {
183 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
184 }
185 }
186 }
188 #include <gtk/gtkstock.h>
190 static GtkWidget* ink_action_create_menu_item( GtkAction* action )
191 {
192 InkAction* act = INK_ACTION( action );
193 GtkWidget* item = 0;
195 if ( act->private_data->iconId ) {
196 gchar* label = 0;
197 g_object_get( G_OBJECT(act), "label", &label, NULL );
199 item = gtk_image_menu_item_new_with_mnemonic( label );
200 GtkWidget* child = sp_icon_new( Inkscape::ICON_SIZE_MENU, act->private_data->iconId );
201 // TODO this work-around is until SPIcon will live properly inside of a popup menu
202 if ( SP_IS_ICON(child) ) {
203 SPIcon* icon = SP_ICON(child);
204 sp_icon_fetch_pixbuf( icon );
205 GdkPixbuf* target = gtk_action_is_sensitive(action) ? icon->pb : icon->pb_faded;
206 if ( target ) {
207 child = gtk_image_new_from_pixbuf( target );
208 gtk_widget_destroy( GTK_WIDGET(icon) );
209 }
210 }
211 gtk_widget_show_all( child );
212 gtk_image_menu_item_set_image( GTK_IMAGE_MENU_ITEM(item), child );
214 g_free( label );
215 label = 0;
216 } else {
217 item = gInkActionParentClass->create_menu_item( action );
218 }
220 return item;
221 }
223 static GtkWidget* ink_action_create_tool_item( GtkAction* action )
224 {
225 InkAction* act = INK_ACTION( action );
226 GtkWidget* item = gInkActionParentClass->create_tool_item(action);
228 if ( act->private_data->iconId ) {
229 if ( GTK_IS_TOOL_BUTTON(item) ) {
230 GtkToolButton* button = GTK_TOOL_BUTTON(item);
232 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
233 gtk_tool_button_set_icon_widget( button, child );
234 } else {
235 // For now trigger a warning but don't do anything else
236 GtkToolButton* button = GTK_TOOL_BUTTON(item);
237 (void)button;
238 }
239 }
241 // TODO investigate if needed
242 gtk_widget_show_all( item );
244 return item;
245 }
249 /* --------------------------------------------------------------- */
250 /* --------------------------------------------------------------- */
251 /* --------------------------------------------------------------- */
252 /* --------------------------------------------------------------- */
255 static void ink_toggle_action_class_init( InkToggleActionClass* klass );
256 static void ink_toggle_action_init( InkToggleAction* action );
257 static void ink_toggle_action_finalize( GObject* obj );
258 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
259 static void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
261 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action );
262 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action );
264 static void ink_toggle_action_update_icon( InkToggleAction* action );
266 static GtkToggleActionClass* gInkToggleActionParentClass = 0;
268 struct _InkToggleActionPrivate
269 {
270 gchar* iconId;
271 Inkscape::IconSize iconSize;
272 };
274 #define INK_TOGGLE_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_TOGGLE_ACTION_TYPE, InkToggleActionPrivate ) )
276 GType ink_toggle_action_get_type( void )
277 {
278 static GType myType = 0;
279 if ( !myType ) {
280 static const GTypeInfo myInfo = {
281 sizeof( InkToggleActionClass ),
282 NULL, /* base_init */
283 NULL, /* base_finalize */
284 (GClassInitFunc)ink_toggle_action_class_init,
285 NULL, /* class_finalize */
286 NULL, /* class_data */
287 sizeof( InkToggleAction ),
288 0, /* n_preallocs */
289 (GInstanceInitFunc)ink_toggle_action_init,
290 NULL
291 };
293 myType = g_type_register_static( GTK_TYPE_TOGGLE_ACTION, "InkToggleAction", &myInfo, (GTypeFlags)0 );
294 }
296 return myType;
297 }
300 static void ink_toggle_action_class_init( InkToggleActionClass* klass )
301 {
302 if ( klass ) {
303 gInkToggleActionParentClass = GTK_TOGGLE_ACTION_CLASS( g_type_class_peek_parent( klass ) );
304 GObjectClass * objClass = G_OBJECT_CLASS( klass );
306 objClass->finalize = ink_toggle_action_finalize;
307 objClass->get_property = ink_toggle_action_get_property;
308 objClass->set_property = ink_toggle_action_set_property;
310 klass->parent_class.parent_class.create_menu_item = ink_toggle_action_create_menu_item;
311 klass->parent_class.parent_class.create_tool_item = ink_toggle_action_create_tool_item;
312 /*klass->parent_class.connect_proxy = connect_proxy;*/
313 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
315 g_object_class_install_property( objClass,
316 PROP_INK_ID,
317 g_param_spec_string( "iconId",
318 "Icon ID",
319 "The id for the icon",
320 "",
321 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
323 g_object_class_install_property( objClass,
324 PROP_INK_SIZE,
325 g_param_spec_int( "iconSize",
326 "Icon Size",
327 "The size the icon",
328 (int)Inkscape::ICON_SIZE_MENU,
329 (int)99,
330 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
331 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
333 g_type_class_add_private( klass, sizeof(InkToggleActionClass) );
334 }
335 }
337 static void ink_toggle_action_init( InkToggleAction* action )
338 {
339 action->private_data = INK_TOGGLE_ACTION_GET_PRIVATE( action );
340 action->private_data->iconId = 0;
341 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
342 }
344 static void ink_toggle_action_finalize( GObject* obj )
345 {
346 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
348 g_free( action->private_data->iconId );
349 g_free( action->private_data );
351 }
353 InkToggleAction* ink_toggle_action_new( const gchar *name,
354 const gchar *label,
355 const gchar *tooltip,
356 const gchar *inkId,
357 Inkscape::IconSize size )
358 {
359 GObject* obj = (GObject*)g_object_new( INK_TOGGLE_ACTION_TYPE,
360 "name", name,
361 "label", label,
362 "tooltip", tooltip,
363 "iconId", inkId,
364 "iconSize", Inkscape::getRegisteredIconSize(size),
365 NULL );
367 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
369 return action;
370 }
372 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
373 {
374 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
375 (void)action;
376 switch ( propId ) {
377 case PROP_INK_ID:
378 {
379 g_value_set_string( value, action->private_data->iconId );
380 }
381 break;
383 case PROP_INK_SIZE:
384 {
385 g_value_set_int( value, action->private_data->iconSize );
386 }
387 break;
389 default:
390 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
391 }
392 }
394 void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
395 {
396 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
397 (void)action;
398 switch ( propId ) {
399 case PROP_INK_ID:
400 {
401 gchar* tmp = action->private_data->iconId;
402 action->private_data->iconId = g_value_dup_string( value );
403 g_free( tmp );
405 ink_toggle_action_update_icon( action );
406 }
407 break;
409 case PROP_INK_SIZE:
410 {
411 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
412 }
413 break;
415 default:
416 {
417 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
418 }
419 }
420 }
422 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action )
423 {
424 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_menu_item(action);
426 return item;
427 }
429 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action )
430 {
431 InkToggleAction* act = INK_TOGGLE_ACTION( action );
433 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_tool_item(action);
434 if ( GTK_IS_TOOL_BUTTON(item) ) {
435 GtkToolButton* button = GTK_TOOL_BUTTON(item);
436 if ( act->private_data->iconId ) {
437 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
438 GtkWidget* align = gtk_alignment_new( 0.5, 0.5, 0.0, 0.0 );
439 gtk_container_add( GTK_CONTAINER(align), child );
440 gtk_tool_button_set_icon_widget( button, align );
441 } else {
442 gchar *label;
443 g_object_get (G_OBJECT(action), "short_label", &label, NULL);
444 gtk_tool_button_set_label( button, label );
445 }
446 } else {
447 // For now trigger a warning but don't do anything else
448 GtkToolButton* button = GTK_TOOL_BUTTON(item);
449 (void)button;
450 }
451 gtk_widget_show_all( item );
453 return item;
454 }
457 static void ink_toggle_action_update_icon( InkToggleAction* action )
458 {
459 if ( action ) {
460 GSList* proxies = gtk_action_get_proxies( GTK_ACTION(action) );
461 while ( proxies ) {
462 if ( GTK_IS_TOOL_ITEM(proxies->data) ) {
463 if ( GTK_IS_TOOL_BUTTON(proxies->data) ) {
464 GtkToolButton* button = GTK_TOOL_BUTTON(proxies->data);
466 GtkWidget* child = sp_icon_new( action->private_data->iconSize, action->private_data->iconId );
467 gtk_widget_show_all( child );
468 gtk_tool_button_set_icon_widget( button, child );
469 }
470 }
472 proxies = g_slist_next( proxies );
473 }
474 }
475 }
478 /* --------------------------------------------------------------- */
479 /* --------------------------------------------------------------- */
480 /* --------------------------------------------------------------- */
481 /* --------------------------------------------------------------- */
484 static void ink_radio_action_class_init( InkRadioActionClass* klass );
485 static void ink_radio_action_init( InkRadioAction* action );
486 static void ink_radio_action_finalize( GObject* obj );
487 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
488 static void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
490 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action );
491 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action );
493 static GtkRadioActionClass* gInkRadioActionParentClass = 0;
495 struct _InkRadioActionPrivate
496 {
497 gchar* iconId;
498 Inkscape::IconSize iconSize;
499 };
501 #define INK_RADIO_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_RADIO_ACTION_TYPE, InkRadioActionPrivate ) )
503 GType ink_radio_action_get_type( void )
504 {
505 static GType myType = 0;
506 if ( !myType ) {
507 static const GTypeInfo myInfo = {
508 sizeof( InkRadioActionClass ),
509 NULL, /* base_init */
510 NULL, /* base_finalize */
511 (GClassInitFunc)ink_radio_action_class_init,
512 NULL, /* class_finalize */
513 NULL, /* class_data */
514 sizeof( InkRadioAction ),
515 0, /* n_preallocs */
516 (GInstanceInitFunc)ink_radio_action_init,
517 NULL
518 };
520 myType = g_type_register_static( GTK_TYPE_RADIO_ACTION, "InkRadioAction", &myInfo, (GTypeFlags)0 );
521 }
523 return myType;
524 }
527 static void ink_radio_action_class_init( InkRadioActionClass* klass )
528 {
529 if ( klass ) {
530 gInkRadioActionParentClass = GTK_RADIO_ACTION_CLASS( g_type_class_peek_parent( klass ) );
531 GObjectClass * objClass = G_OBJECT_CLASS( klass );
533 objClass->finalize = ink_radio_action_finalize;
534 objClass->get_property = ink_radio_action_get_property;
535 objClass->set_property = ink_radio_action_set_property;
537 klass->parent_class.parent_class.parent_class.create_menu_item = ink_radio_action_create_menu_item;
538 klass->parent_class.parent_class.parent_class.create_tool_item = ink_radio_action_create_tool_item;
539 /*klass->parent_class.connect_proxy = connect_proxy;*/
540 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
542 g_object_class_install_property( objClass,
543 PROP_INK_ID,
544 g_param_spec_string( "iconId",
545 "Icon ID",
546 "The id for the icon",
547 "",
548 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
550 g_object_class_install_property( objClass,
551 PROP_INK_SIZE,
552 g_param_spec_int( "iconSize",
553 "Icon Size",
554 "The size the icon",
555 (int)Inkscape::ICON_SIZE_MENU,
556 (int)Inkscape::ICON_SIZE_DECORATION,
557 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
558 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
560 g_type_class_add_private( klass, sizeof(InkRadioActionClass) );
561 }
562 }
564 static void ink_radio_action_init( InkRadioAction* action )
565 {
566 action->private_data = INK_RADIO_ACTION_GET_PRIVATE( action );
567 action->private_data->iconId = 0;
568 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
569 }
571 static void ink_radio_action_finalize( GObject* obj )
572 {
573 InkRadioAction* action = INK_RADIO_ACTION( obj );
575 g_free( action->private_data->iconId );
576 g_free( action->private_data );
578 }
580 InkRadioAction* ink_radio_action_new( const gchar *name,
581 const gchar *label,
582 const gchar *tooltip,
583 const gchar *inkId,
584 Inkscape::IconSize size )
585 {
586 GObject* obj = (GObject*)g_object_new( INK_RADIO_ACTION_TYPE,
587 "name", name,
588 "label", label,
589 "tooltip", tooltip,
590 "iconId", inkId,
591 "iconSize", Inkscape::getRegisteredIconSize(size),
592 NULL );
594 InkRadioAction* action = INK_RADIO_ACTION( obj );
596 return action;
597 }
599 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
600 {
601 InkRadioAction* action = INK_RADIO_ACTION( obj );
602 (void)action;
603 switch ( propId ) {
604 case PROP_INK_ID:
605 {
606 g_value_set_string( value, action->private_data->iconId );
607 }
608 break;
610 case PROP_INK_SIZE:
611 {
612 g_value_set_int( value, action->private_data->iconSize );
613 }
614 break;
616 default:
617 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
618 }
619 }
621 void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
622 {
623 InkRadioAction* action = INK_RADIO_ACTION( obj );
624 (void)action;
625 switch ( propId ) {
626 case PROP_INK_ID:
627 {
628 gchar* tmp = action->private_data->iconId;
629 action->private_data->iconId = g_value_dup_string( value );
630 g_free( tmp );
631 }
632 break;
634 case PROP_INK_SIZE:
635 {
636 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
637 }
638 break;
640 default:
641 {
642 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
643 }
644 }
645 }
647 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action )
648 {
649 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_menu_item(action);
651 return item;
652 }
654 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action )
655 {
656 InkRadioAction* act = INK_RADIO_ACTION( action );
657 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_tool_item(action);
659 if ( act->private_data->iconId ) {
660 if ( GTK_IS_TOOL_BUTTON(item) ) {
661 GtkToolButton* button = GTK_TOOL_BUTTON(item);
663 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
664 gtk_tool_button_set_icon_widget( button, child );
665 } else {
666 // For now trigger a warning but don't do anything else
667 GtkToolButton* button = GTK_TOOL_BUTTON(item);
668 (void)button;
669 }
670 }
672 // TODO investigate if needed
673 gtk_widget_show_all( item );
675 return item;
676 }