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 = icon->pb;
204 if ( target ) {
205 child = gtk_image_new_from_pixbuf( target );
206 gtk_widget_set_sensitive(child, gtk_action_is_sensitive(action));
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)99,
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 SPAttributeEnum attr)
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 //"SP_ATTR_INKSCAPE", attr, // Why doesn't this work and do I need to use g_object_set_data below?
366 NULL );
368 g_object_set_data(obj, "SP_ATTR_INKSCAPE", GINT_TO_POINTER(attr));
369 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
371 return action;
372 }
374 static void ink_toggle_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
375 {
376 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
377 (void)action;
378 switch ( propId ) {
379 case PROP_INK_ID:
380 {
381 g_value_set_string( value, action->private_data->iconId );
382 }
383 break;
385 case PROP_INK_SIZE:
386 {
387 g_value_set_int( value, action->private_data->iconSize );
388 }
389 break;
391 default:
392 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
393 }
394 }
396 void ink_toggle_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
397 {
398 InkToggleAction* action = INK_TOGGLE_ACTION( obj );
399 (void)action;
400 switch ( propId ) {
401 case PROP_INK_ID:
402 {
403 gchar* tmp = action->private_data->iconId;
404 action->private_data->iconId = g_value_dup_string( value );
405 g_free( tmp );
407 ink_toggle_action_update_icon( action );
408 }
409 break;
411 case PROP_INK_SIZE:
412 {
413 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
414 }
415 break;
417 default:
418 {
419 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
420 }
421 }
422 }
424 static GtkWidget* ink_toggle_action_create_menu_item( GtkAction* action )
425 {
426 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_menu_item(action);
428 return item;
429 }
431 static GtkWidget* ink_toggle_action_create_tool_item( GtkAction* action )
432 {
433 InkToggleAction* act = INK_TOGGLE_ACTION( action );
435 GtkWidget* item = gInkToggleActionParentClass->parent_class.create_tool_item(action);
436 if ( GTK_IS_TOOL_BUTTON(item) ) {
437 GtkToolButton* button = GTK_TOOL_BUTTON(item);
438 if ( act->private_data->iconId ) {
439 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
440 GtkWidget* align = gtk_alignment_new( 0.5, 0.5, 0.0, 0.0 );
441 gtk_container_add( GTK_CONTAINER(align), child );
442 gtk_tool_button_set_icon_widget( button, align );
443 } else {
444 gchar *label;
445 g_object_get (G_OBJECT(action), "short_label", &label, NULL);
446 gtk_tool_button_set_label( button, label );
447 }
448 } else {
449 // For now trigger a warning but don't do anything else
450 GtkToolButton* button = GTK_TOOL_BUTTON(item);
451 (void)button;
452 }
453 gtk_widget_show_all( item );
455 return item;
456 }
459 static void ink_toggle_action_update_icon( InkToggleAction* action )
460 {
461 if ( action ) {
462 GSList* proxies = gtk_action_get_proxies( GTK_ACTION(action) );
463 while ( proxies ) {
464 if ( GTK_IS_TOOL_ITEM(proxies->data) ) {
465 if ( GTK_IS_TOOL_BUTTON(proxies->data) ) {
466 GtkToolButton* button = GTK_TOOL_BUTTON(proxies->data);
468 GtkWidget* child = sp_icon_new( action->private_data->iconSize, action->private_data->iconId );
469 gtk_widget_show_all( child );
470 gtk_tool_button_set_icon_widget( button, child );
471 }
472 }
474 proxies = g_slist_next( proxies );
475 }
476 }
477 }
480 /* --------------------------------------------------------------- */
481 /* --------------------------------------------------------------- */
482 /* --------------------------------------------------------------- */
483 /* --------------------------------------------------------------- */
486 static void ink_radio_action_class_init( InkRadioActionClass* klass );
487 static void ink_radio_action_init( InkRadioAction* action );
488 static void ink_radio_action_finalize( GObject* obj );
489 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
490 static void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
492 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action );
493 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action );
495 static GtkRadioActionClass* gInkRadioActionParentClass = 0;
497 struct _InkRadioActionPrivate
498 {
499 gchar* iconId;
500 Inkscape::IconSize iconSize;
501 };
503 #define INK_RADIO_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), INK_RADIO_ACTION_TYPE, InkRadioActionPrivate ) )
505 GType ink_radio_action_get_type( void )
506 {
507 static GType myType = 0;
508 if ( !myType ) {
509 static const GTypeInfo myInfo = {
510 sizeof( InkRadioActionClass ),
511 NULL, /* base_init */
512 NULL, /* base_finalize */
513 (GClassInitFunc)ink_radio_action_class_init,
514 NULL, /* class_finalize */
515 NULL, /* class_data */
516 sizeof( InkRadioAction ),
517 0, /* n_preallocs */
518 (GInstanceInitFunc)ink_radio_action_init,
519 NULL
520 };
522 myType = g_type_register_static( GTK_TYPE_RADIO_ACTION, "InkRadioAction", &myInfo, (GTypeFlags)0 );
523 }
525 return myType;
526 }
529 static void ink_radio_action_class_init( InkRadioActionClass* klass )
530 {
531 if ( klass ) {
532 gInkRadioActionParentClass = GTK_RADIO_ACTION_CLASS( g_type_class_peek_parent( klass ) );
533 GObjectClass * objClass = G_OBJECT_CLASS( klass );
535 objClass->finalize = ink_radio_action_finalize;
536 objClass->get_property = ink_radio_action_get_property;
537 objClass->set_property = ink_radio_action_set_property;
539 klass->parent_class.parent_class.parent_class.create_menu_item = ink_radio_action_create_menu_item;
540 klass->parent_class.parent_class.parent_class.create_tool_item = ink_radio_action_create_tool_item;
541 /*klass->parent_class.connect_proxy = connect_proxy;*/
542 /*klass->parent_class.disconnect_proxy = disconnect_proxy;*/
544 g_object_class_install_property( objClass,
545 PROP_INK_ID,
546 g_param_spec_string( "iconId",
547 "Icon ID",
548 "The id for the icon",
549 "",
550 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
552 g_object_class_install_property( objClass,
553 PROP_INK_SIZE,
554 g_param_spec_int( "iconSize",
555 "Icon Size",
556 "The size the icon",
557 (int)Inkscape::ICON_SIZE_MENU,
558 (int)Inkscape::ICON_SIZE_DECORATION,
559 (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR,
560 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
562 g_type_class_add_private( klass, sizeof(InkRadioActionClass) );
563 }
564 }
566 static void ink_radio_action_init( InkRadioAction* action )
567 {
568 action->private_data = INK_RADIO_ACTION_GET_PRIVATE( action );
569 action->private_data->iconId = 0;
570 action->private_data->iconSize = Inkscape::ICON_SIZE_SMALL_TOOLBAR;
571 }
573 static void ink_radio_action_finalize( GObject* obj )
574 {
575 InkRadioAction* action = INK_RADIO_ACTION( obj );
577 g_free( action->private_data->iconId );
578 g_free( action->private_data );
580 }
582 InkRadioAction* ink_radio_action_new( const gchar *name,
583 const gchar *label,
584 const gchar *tooltip,
585 const gchar *inkId,
586 Inkscape::IconSize size )
587 {
588 GObject* obj = (GObject*)g_object_new( INK_RADIO_ACTION_TYPE,
589 "name", name,
590 "label", label,
591 "tooltip", tooltip,
592 "iconId", inkId,
593 "iconSize", Inkscape::getRegisteredIconSize(size),
594 NULL );
596 InkRadioAction* action = INK_RADIO_ACTION( obj );
598 return action;
599 }
601 static void ink_radio_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
602 {
603 InkRadioAction* action = INK_RADIO_ACTION( obj );
604 (void)action;
605 switch ( propId ) {
606 case PROP_INK_ID:
607 {
608 g_value_set_string( value, action->private_data->iconId );
609 }
610 break;
612 case PROP_INK_SIZE:
613 {
614 g_value_set_int( value, action->private_data->iconSize );
615 }
616 break;
618 default:
619 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
620 }
621 }
623 void ink_radio_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
624 {
625 InkRadioAction* action = INK_RADIO_ACTION( obj );
626 (void)action;
627 switch ( propId ) {
628 case PROP_INK_ID:
629 {
630 gchar* tmp = action->private_data->iconId;
631 action->private_data->iconId = g_value_dup_string( value );
632 g_free( tmp );
633 }
634 break;
636 case PROP_INK_SIZE:
637 {
638 action->private_data->iconSize = (Inkscape::IconSize)g_value_get_int( value );
639 }
640 break;
642 default:
643 {
644 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
645 }
646 }
647 }
649 static GtkWidget* ink_radio_action_create_menu_item( GtkAction* action )
650 {
651 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_menu_item(action);
653 return item;
654 }
656 static GtkWidget* ink_radio_action_create_tool_item( GtkAction* action )
657 {
658 InkRadioAction* act = INK_RADIO_ACTION( action );
659 GtkWidget* item = gInkRadioActionParentClass->parent_class.parent_class.create_tool_item(action);
661 if ( act->private_data->iconId ) {
662 if ( GTK_IS_TOOL_BUTTON(item) ) {
663 GtkToolButton* button = GTK_TOOL_BUTTON(item);
665 GtkWidget* child = sp_icon_new( act->private_data->iconSize, act->private_data->iconId );
666 GtkWidget* align = gtk_alignment_new( 0.5, 0.5, 0.0, 0.0 );
667 gtk_container_add( GTK_CONTAINER(align), child );
668 gtk_tool_button_set_icon_widget( button, align );
669 } else {
670 // For now trigger a warning but don't do anything else
671 GtkToolButton* button = GTK_TOOL_BUTTON(item);
672 (void)button;
673 }
674 }
676 // TODO investigate if needed
677 gtk_widget_show_all( item );
679 return item;
680 }