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"
18 static void ink_action_class_init( InkActionClass* klass );
19 static void ink_action_init( InkAction* action );
20 static void ink_action_finalize( GObject* obj );
21 static void ink_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
22 static void ink_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
24 static GtkWidget* ink_action_create_menu_item( GtkAction* action );
25 static GtkWidget* ink_action_create_tool_item( GtkAction* action );
27 static GtkActionClass* gInkActionParentClass = 0;
29 struct _InkActionPrivate
30 {
31 gchar* iconId;
32 Inkscape::IconSize iconSize;
33 };
35 #define INK_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_ACTION_TYPE, InkActionPrivate ) )
37 GType ink_action_get_type( void )
38 {
39 static GType myType = 0;
40 if ( !myType ) {
41 static const GTypeInfo myInfo = {
42 sizeof( InkActionClass ),
43 NULL, /* base_init */
44 NULL, /* base_finalize */
45 (GClassInitFunc)ink_action_class_init,
46 NULL, /* class_finalize */
47 NULL, /* class_data */
48 sizeof( InkAction ),
49 0, /* n_preallocs */
50 (GInstanceInitFunc)ink_action_init,
51 NULL
52 };
54 myType = g_type_register_static( GTK_TYPE_ACTION, "InkAction", &myInfo, (GTypeFlags)0 );
55 }
57 return myType;
58 }
60 enum {
61 PROP_INK_ID = 1,
62 PROP_INK_SIZE
63 };
65 static void ink_action_class_init( InkActionClass* klass )
66 {
67 if ( klass ) {
68 gInkActionParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) );
69 GObjectClass * objClass = G_OBJECT_CLASS( klass );
71 objClass->finalize = ink_action_finalize;
72 objClass->get_property = ink_action_get_property;
73 objClass->set_property = ink_action_set_property;
75 klass->parent_class.create_menu_item = ink_action_create_menu_item;
76 klass->parent_class.create_tool_item = ink_action_create_tool_item;
77 /*klass->parent_class.connect_proxy = connect_proxy;*/
78 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
80 g_object_class_install_property( objClass,
81 PROP_INK_ID,
82 g_param_spec_string( "iconId",
83 "Icon ID",
84 "The id for the icon",
85 "",
86 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
88 g_object_class_install_property( objClass,
89 PROP_INK_SIZE,
90 g_param_spec_int( "iconSize",
91 "Icon Size",
92 "The size the icon",
93 (int)Inkscape::ICON_SIZE_MENU,
94 (int)Inkscape::ICON_SIZE_DECORATION,
95 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
96 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
98 g_type_class_add_private( klass, sizeof(InkActionClass) );
99 }
100 }
102 static void ink_action_init( InkAction* action )
103 {
104 action->private_data = INK_ACTION_GET_PRIVATE( action );
105 action->private_data->iconId = 0;
106 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
107 }
109 static void ink_action_finalize( GObject* obj )
110 {
111 InkAction* action = INK_ACTION( obj );
113 g_free( action->private_data->iconId );
114 g_free( action->private_data );
116 }
118 //Any strings passed in should already be localised
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)99,
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 SPAttributeEnum attr)
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", Inkscape::getRegisteredIconSize(size),
364 //"SP_ATTR_INKSCAPE", attr, // Why doesn't this work and do I need to use g_object_set_data below?
365 NULL );
367 g_object_set_data(obj, "SP_ATTR_INKSCAPE", GINT_TO_POINTER(attr));
368 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
370 return action;
371 }
373 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
374 {
375 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
376 (void)action;
377 switch ( propId ) {
378 case PROP_INK_ID:
379 {
380 g_value_set_string( value, action->private_data->iconId );
381 }
382 break;
384 case PROP_INK_SIZE:
385 {
386 g_value_set_int( value, action->private_data->iconSize );
387 }
388 break;
390 default:
391 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
392 }
393 }
395 void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
396 {
397 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
398 (void)action;
399 switch ( propId ) {
400 case PROP_INK_ID:
401 {
402 gchar* tmp = action->private_data->iconId;
403 action->private_data->iconId = g_value_dup_string( value );
404 g_free( tmp );
406 ink_toggle_action_update_icon( action );
407 }
408 break;
410 case PROP_INK_SIZE:
411 {
412 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
413 }
414 break;
416 default:
417 {
418 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
419 }
420 }
421 }
423 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action )
424 {
425 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_menu_item(action);
427 return item;
428 }
430 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action )
431 {
432 InkToggleAction* act = INK_TOGGLE_ACTION( action );
434 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_tool_item(action);
435 if ( GTK_IS_TOOL_BUTTON(item) ) {
436 GtkToolButton* button = GTK_TOOL_BUTTON(item);
437 if ( act->private_data->iconId ) {
438 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
439 GtkWidget* align = gtk_alignment_new( 0.5, 0.5, 0.0, 0.0 );
440 gtk_container_add( GTK_CONTAINER(align), child );
441 gtk_tool_button_set_icon_widget( button, align );
442 } else {
443 gchar *label;
444 g_object_get (G_OBJECT(action), "short_label", &label, NULL);
445 gtk_tool_button_set_label( button, label );
446 }
447 } else {
448 // For now trigger a warning but don't do anything else
449 GtkToolButton* button = GTK_TOOL_BUTTON(item);
450 (void)button;
451 }
452 gtk_widget_show_all( item );
454 return item;
455 }
458 static void ink_toggle_action_update_icon( InkToggleAction* action )
459 {
460 if ( action ) {
461 GSList* proxies = gtk_action_get_proxies( GTK_ACTION(action) );
462 while ( proxies ) {
463 if ( GTK_IS_TOOL_ITEM(proxies->data) ) {
464 if ( GTK_IS_TOOL_BUTTON(proxies->data) ) {
465 GtkToolButton* button = GTK_TOOL_BUTTON(proxies->data);
467 GtkWidget* child = sp_icon_new( action->private_data->iconSize, action->private_data->iconId );
468 gtk_widget_show_all( child );
469 gtk_tool_button_set_icon_widget( button, child );
470 }
471 }
473 proxies = g_slist_next( proxies );
474 }
475 }
476 }
479 /* --------------------------------------------------------------- */
480 /* --------------------------------------------------------------- */
481 /* --------------------------------------------------------------- */
482 /* --------------------------------------------------------------- */
485 static void ink_radio_action_class_init( InkRadioActionClass* klass );
486 static void ink_radio_action_init( InkRadioAction* action );
487 static void ink_radio_action_finalize( GObject* obj );
488 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
489 static void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
491 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action );
492 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action );
494 static GtkRadioActionClass* gInkRadioActionParentClass = 0;
496 struct _InkRadioActionPrivate
497 {
498 gchar* iconId;
499 Inkscape::IconSize iconSize;
500 };
502 #define INK_RADIO_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_RADIO_ACTION_TYPE, InkRadioActionPrivate ) )
504 GType ink_radio_action_get_type( void )
505 {
506 static GType myType = 0;
507 if ( !myType ) {
508 static const GTypeInfo myInfo = {
509 sizeof( InkRadioActionClass ),
510 NULL, /* base_init */
511 NULL, /* base_finalize */
512 (GClassInitFunc)ink_radio_action_class_init,
513 NULL, /* class_finalize */
514 NULL, /* class_data */
515 sizeof( InkRadioAction ),
516 0, /* n_preallocs */
517 (GInstanceInitFunc)ink_radio_action_init,
518 NULL
519 };
521 myType = g_type_register_static( GTK_TYPE_RADIO_ACTION, "InkRadioAction", &myInfo, (GTypeFlags)0 );
522 }
524 return myType;
525 }
528 static void ink_radio_action_class_init( InkRadioActionClass* klass )
529 {
530 if ( klass ) {
531 gInkRadioActionParentClass = GTK_RADIO_ACTION_CLASS( g_type_class_peek_parent( klass ) );
532 GObjectClass * objClass = G_OBJECT_CLASS( klass );
534 objClass->finalize = ink_radio_action_finalize;
535 objClass->get_property = ink_radio_action_get_property;
536 objClass->set_property = ink_radio_action_set_property;
538 klass->parent_class.parent_class.parent_class.create_menu_item = ink_radio_action_create_menu_item;
539 klass->parent_class.parent_class.parent_class.create_tool_item = ink_radio_action_create_tool_item;
540 /*klass->parent_class.connect_proxy = connect_proxy;*/
541 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
543 g_object_class_install_property( objClass,
544 PROP_INK_ID,
545 g_param_spec_string( "iconId",
546 "Icon ID",
547 "The id for the icon",
548 "",
549 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
551 g_object_class_install_property( objClass,
552 PROP_INK_SIZE,
553 g_param_spec_int( "iconSize",
554 "Icon Size",
555 "The size the icon",
556 (int)Inkscape::ICON_SIZE_MENU,
557 (int)Inkscape::ICON_SIZE_DECORATION,
558 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
559 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
561 g_type_class_add_private( klass, sizeof(InkRadioActionClass) );
562 }
563 }
565 static void ink_radio_action_init( InkRadioAction* action )
566 {
567 action->private_data = INK_RADIO_ACTION_GET_PRIVATE( action );
568 action->private_data->iconId = 0;
569 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
570 }
572 static void ink_radio_action_finalize( GObject* obj )
573 {
574 InkRadioAction* action = INK_RADIO_ACTION( obj );
576 g_free( action->private_data->iconId );
577 g_free( action->private_data );
579 }
581 InkRadioAction* ink_radio_action_new( const gchar *name,
582 const gchar *label,
583 const gchar *tooltip,
584 const gchar *inkId,
585 Inkscape::IconSize size )
586 {
587 GObject* obj = (GObject*)g_object_new( INK_RADIO_ACTION_TYPE,
588 "name", name,
589 "label", label,
590 "tooltip", tooltip,
591 "iconId", inkId,
592 "iconSize", Inkscape::getRegisteredIconSize(size),
593 NULL );
595 InkRadioAction* action = INK_RADIO_ACTION( obj );
597 return action;
598 }
600 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
601 {
602 InkRadioAction* action = INK_RADIO_ACTION( obj );
603 (void)action;
604 switch ( propId ) {
605 case PROP_INK_ID:
606 {
607 g_value_set_string( value, action->private_data->iconId );
608 }
609 break;
611 case PROP_INK_SIZE:
612 {
613 g_value_set_int( value, action->private_data->iconSize );
614 }
615 break;
617 default:
618 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
619 }
620 }
622 void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
623 {
624 InkRadioAction* action = INK_RADIO_ACTION( obj );
625 (void)action;
626 switch ( propId ) {
627 case PROP_INK_ID:
628 {
629 gchar* tmp = action->private_data->iconId;
630 action->private_data->iconId = g_value_dup_string( value );
631 g_free( tmp );
632 }
633 break;
635 case PROP_INK_SIZE:
636 {
637 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
638 }
639 break;
641 default:
642 {
643 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
644 }
645 }
646 }
648 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action )
649 {
650 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_menu_item(action);
652 return item;
653 }
655 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action )
656 {
657 InkRadioAction* act = INK_RADIO_ACTION( action );
658 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_tool_item(action);
660 if ( act->private_data->iconId ) {
661 if ( GTK_IS_TOOL_BUTTON(item) ) {
662 GtkToolButton* button = GTK_TOOL_BUTTON(item);
664 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
665 gtk_tool_button_set_icon_widget( button, child );
666 } else {
667 // For now trigger a warning but don't do anything else
668 GtkToolButton* button = GTK_TOOL_BUTTON(item);
669 (void)button;
670 }
671 }
673 // TODO investigate if needed
674 gtk_widget_show_all( item );
676 return item;
677 }