Code

Applying fix from LP #183646
[inkscape.git] / src / ege-select-one-action.cpp
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  */
4 /* ***** BEGIN LICENSE BLOCK *****
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is EGE Select One Action.
18  *
19  * The Initial Developer of the Original Code is
20  * Jon A. Cruz.
21  * Portions created by the Initial Developer are Copyright (C) 2007
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either the GNU General Public License Version 2 or later (the "GPL"), or
28  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
40 /* Note: this file should be kept compilable as both .cpp and .c */
42 #include <string.h>
44 #include <gtk/gtkhbox.h>
45 #include <gtk/gtklabel.h>
46 #include <gtk/gtktoolitem.h>
47 #include <gtk/gtkcombobox.h>
48 #include <gtk/gtkcellrenderertext.h>
49 #include <gtk/gtkcellrendererpixbuf.h>
50 #include <gtk/gtkcelllayout.h>
51 #include <gtk/gtkradioaction.h>
52 #include <gtk/gtkradiomenuitem.h>
53 #include <gtk/gtktable.h>
55 #include "ege-select-one-action.h"
57 enum {
58     CHANGED = 0,
59     LAST_SIGNAL};
62 static void ege_select_one_action_class_init( EgeSelectOneActionClass* klass );
63 static void ege_select_one_action_init( EgeSelectOneAction* action );
64 static void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec );
65 static void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec );
67 static void resync_active( EgeSelectOneAction* act, gint active );
68 static void combo_changed_cb( GtkComboBox* widget, gpointer user_data );
69 static void menu_toggled_cb( GtkWidget* obj, gpointer data );
70 static void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, gpointer user_data );
72 static GtkWidget* create_menu_item( GtkAction* action );
73 static GtkWidget* create_tool_item( GtkAction* action );
74 static void connect_proxy( GtkAction *action, GtkWidget *proxy );
75 static void disconnect_proxy( GtkAction *action, GtkWidget *proxy );
77 static GtkActionClass* gParentClass = 0;
78 static guint signals[LAST_SIGNAL] = {0};
79 static GQuark gDataName = 0;
82 enum {
83     APPEARANCE_UNKNOWN = -1,
84     APPEARANCE_NONE = 0,
85     APPEARANCE_FULL,    // label, then all choices represented by separate buttons
86     APPEARANCE_COMPACT, // label, then choices in a drop-down menu
87     APPEARANCE_MINIMAL, // no label, just choices in a drop-down menu
88 };
90 struct _EgeSelectOneActionPrivate
91 {
92     gint active;
93     gint labelColumn;
94     gint iconColumn;
95     gint tooltipColumn;
96     gint appearanceMode;
97     GType radioActionType;
98     GtkTreeModel* model;
99     gchar* iconProperty;
100     gchar* appearance;
101 };
103 #define EGE_SELECT_ONE_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_SELECT_ONE_ACTION_TYPE, EgeSelectOneActionPrivate ) )
105 enum {
106     PROP_MODEL = 1,
107     PROP_ACTIVE,
108     PROP_LABEL_COLUMN,
109     PROP_ICON_COLUMN,
110     PROP_TOOLTIP_COLUMN,
111     PROP_ICON_PROP,
112     PROP_APPEARANCE
113 };
115 GType ege_select_one_action_get_type( void )
117     static GType myType = 0;
118     if ( !myType ) {
119         static const GTypeInfo myInfo = {
120             sizeof( EgeSelectOneActionClass ),
121             NULL, /* base_init */
122             NULL, /* base_finalize */
123             (GClassInitFunc)ege_select_one_action_class_init,
124             NULL, /* class_finalize */
125             NULL, /* class_data */
126             sizeof( EgeSelectOneAction ),
127             0, /* n_preallocs */
128             (GInstanceInitFunc)ege_select_one_action_init,
129             NULL
130         };
132         myType = g_type_register_static( GTK_TYPE_ACTION, "EgeSelectOneAction", &myInfo, (GTypeFlags)0 );
133     }
135     return myType;
138 GtkTreeModel *ege_select_one_action_get_model(EgeSelectOneAction* action ){
139     return GTK_TREE_MODEL(action->private_data->model);
141 void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
143     if ( klass ) {
144         gParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) );
145         GObjectClass* objClass = G_OBJECT_CLASS( klass );
147         gDataName = g_quark_from_string("ege-select1-action");
149         objClass->get_property = ege_select_one_action_get_property;
150         objClass->set_property = ege_select_one_action_set_property;
152         klass->parent_class.create_menu_item = create_menu_item;
153         klass->parent_class.create_tool_item = create_tool_item;
154         klass->parent_class.connect_proxy = connect_proxy;
155         klass->parent_class.disconnect_proxy = disconnect_proxy;
157         g_object_class_install_property( objClass,
158                                          PROP_MODEL,
159                                          g_param_spec_object( "model",
160                                                               "Tree Model",
161                                                               "Tree model of possible items",
162                                                               GTK_TYPE_TREE_MODEL,
163                                                               (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
165         g_object_class_install_property( objClass,
166                                          PROP_ACTIVE,
167                                          g_param_spec_int( "active",
168                                                            "Active Selection",
169                                                            "The index of the selected item",
170                                                            0, 20, 0,
171                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
173         g_object_class_install_property( objClass,
174                                          PROP_LABEL_COLUMN,
175                                          g_param_spec_int( "label-column",
176                                                            "Display Column",
177                                                            "The column of the model that holds display strings",
178                                                            0, 20, 0,
179                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
181         g_object_class_install_property( objClass,
182                                          PROP_ICON_COLUMN,
183                                          g_param_spec_int( "icon-column",
184                                                            "Icon Column",
185                                                            "The column of the model that holds display icon name",
186                                                            -1, 20, -1,
187                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
189         g_object_class_install_property( objClass,
190                                          PROP_TOOLTIP_COLUMN,
191                                          g_param_spec_int( "tooltip-column",
192                                                            "Tooltip Column",
193                                                           "The column of the model that holds tooltip strings",
194                                                            -1, 20, -1,
195                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
197         g_object_class_install_property( objClass,
198                                          PROP_ICON_PROP,
199                                          g_param_spec_string( "icon-property",
200                                                               "Icon Property",
201                                                               "Target icon property",
202                                                               "",
203                                                               (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
205         g_object_class_install_property( objClass,
206                                          PROP_APPEARANCE,
207                                          g_param_spec_string( "appearance",
208                                                               "Appearance hint",
209                                                               "A hint for how to display",
210                                                               "",
211                                                               (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
213         signals[CHANGED] = g_signal_new( "changed",
214                                          G_TYPE_FROM_CLASS(klass),
215                                          G_SIGNAL_RUN_FIRST,
216                                          G_STRUCT_OFFSET(EgeSelectOneActionClass, changed),
217                                          NULL, NULL,
218                                          g_cclosure_marshal_VOID__VOID,
219                                          G_TYPE_NONE, 0);
221         g_type_class_add_private( klass, sizeof(EgeSelectOneActionClass) );
222     }
226 void ege_select_one_action_init( EgeSelectOneAction* action )
228     action->private_data = EGE_SELECT_ONE_ACTION_GET_PRIVATE( action );
229     action->private_data->active = 0;
230     action->private_data->labelColumn = 0;
231     action->private_data->iconColumn = -1;
232     action->private_data->tooltipColumn = -1;
233     action->private_data->appearanceMode = APPEARANCE_NONE;
234     action->private_data->radioActionType = 0;
235     action->private_data->model = 0;
236     action->private_data->iconProperty = g_strdup("stock-id");
237     action->private_data->appearance = 0;
239 /*     g_signal_connect( action, "notify", G_CALLBACK( fixup_labels ), NULL ); */
242 EgeSelectOneAction* ege_select_one_action_new( const gchar *name,
243                                                const gchar *label,
244                                                const gchar *tooltip,
245                                                const gchar *stock_id,
246                                                GtkTreeModel* model )
248     GObject* obj = (GObject*)g_object_new( EGE_SELECT_ONE_ACTION_TYPE,
249                                            "name", name,
250                                            "label", label,
251                                            "tooltip", tooltip,
252                                            "stock_id", stock_id,
253                                            "model", model,
254                                            "active", 0,
255                                            "icon-property", "stock-id",
256                                            NULL );
258     EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj );
260     return action;
264 gint ege_select_one_action_get_active( EgeSelectOneAction* action )
266     g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
267     return action->private_data->active;
270 void ege_select_one_action_set_active( EgeSelectOneAction* action, gint val )
272     g_object_set( G_OBJECT(action), "active", val, NULL );
275 gint ege_select_one_action_get_label_column( EgeSelectOneAction* action )
277     g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
278     return action->private_data->labelColumn;
281 void ege_select_one_action_set_label_column( EgeSelectOneAction* action, gint col )
283     g_object_set( G_OBJECT(action), "label-column", col, NULL );
286 gint ege_select_one_action_get_icon_column( EgeSelectOneAction* action )
288     g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
289     return action->private_data->iconColumn;
292 void ege_select_one_action_set_icon_column( EgeSelectOneAction* action, gint col )
294     g_object_set( G_OBJECT(action), "icon-column", col, NULL );
297 gint ege_select_one_action_get_tooltip_column( EgeSelectOneAction* action )
299     g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
300     return action->private_data->tooltipColumn;
303 void ege_select_one_action_set_tooltip_column( EgeSelectOneAction* action, gint col )
305     g_object_set( G_OBJECT(action), "tooltip-column", col, NULL );
308 void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar const* val )
310     g_object_set( G_OBJECT(action), "appearance", val, NULL );
313 void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
315     EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj );
316     switch ( propId ) {
317         case PROP_MODEL:
318             g_value_set_object( value, action->private_data->model );
319             break;
321         case PROP_ACTIVE:
322             g_value_set_int( value, action->private_data->active );
323             break;
325         case PROP_LABEL_COLUMN:
326             g_value_set_int( value, action->private_data->labelColumn );
327             break;
329         case PROP_ICON_COLUMN:
330             g_value_set_int( value, action->private_data->iconColumn );
331             break;
333         case PROP_TOOLTIP_COLUMN:
334             g_value_set_int( value, action->private_data->tooltipColumn );
335             break;
337         case PROP_ICON_PROP:
338             g_value_set_string( value, action->private_data->iconProperty );
339             break;
341         case PROP_APPEARANCE:
342             g_value_set_string( value, action->private_data->appearance );
343             break;
345         default:
346             G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
347     }
350 void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
352     EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj );
353     switch ( propId ) {
354         case PROP_MODEL:
355         {
356             action->private_data->model = GTK_TREE_MODEL( g_value_get_object( value ) );
357         }
358         break;
360         case PROP_ACTIVE:
361         {
362             resync_active( action, g_value_get_int( value ) );
363         }
364         break;
366         case PROP_LABEL_COLUMN:
367         {
368             action->private_data->labelColumn = g_value_get_int( value );
369         }
370         break;
372         case PROP_ICON_COLUMN:
373         {
374             action->private_data->iconColumn = g_value_get_int( value );
375         }
376         break;
378         case PROP_TOOLTIP_COLUMN:
379         {
380             action->private_data->tooltipColumn = g_value_get_int( value );
381         }
382         break;
384         case PROP_ICON_PROP:
385         {
386             gchar* tmp = action->private_data->iconProperty;
387             gchar* newVal = g_value_dup_string( value );
388             action->private_data->iconProperty = newVal;
389             g_free( tmp );
390         }
391         break;
393         case PROP_APPEARANCE:
394         {
395             gchar* tmp = action->private_data->appearance;
396             gchar* newVal = g_value_dup_string( value );
397             action->private_data->appearance = newVal;
398             g_free( tmp );
400             if ( !action->private_data->appearance || (strcmp("", newVal) == 0) ) {
401                 action->private_data->appearanceMode = APPEARANCE_NONE;
402             } else if ( strcmp("full", newVal) == 0 ) {
403                 action->private_data->appearanceMode = APPEARANCE_FULL;
404             } else if ( strcmp("compact", newVal) == 0 ) {
405                 action->private_data->appearanceMode = APPEARANCE_COMPACT;
406             } else if ( strcmp("minimal", newVal) == 0 ) {
407                 action->private_data->appearanceMode = APPEARANCE_MINIMAL;
408             } else {
409                 action->private_data->appearanceMode = APPEARANCE_UNKNOWN;
410             }
411         }
412         break;
414         default:
415             G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
416     }
419 GtkWidget* create_menu_item( GtkAction* action )
421     GtkWidget* item = 0;
423     if ( IS_EGE_SELECT_ONE_ACTION(action) ) {
424         EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION( action );
425         gchar*  sss = 0;
426         gboolean valid = FALSE;
427         gint index = 0;
428         GtkTreeIter iter;
429         GSList* group = 0;
430         GtkWidget* subby = gtk_menu_new();
432         g_object_get( G_OBJECT(action), "label", &sss, NULL );
434         item = gtk_menu_item_new_with_label( sss );
436         valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter );
437         while ( valid ) {
438             gchar* str = 0;
439             gtk_tree_model_get( act->private_data->model, &iter,
440                                 act->private_data->labelColumn, &str,
441                                 -1 );
443             GtkWidget *item = gtk_radio_menu_item_new_with_label( group, str );
444             group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(item) );
445             gtk_menu_shell_append( GTK_MENU_SHELL(subby), item );
446             g_object_set_qdata( G_OBJECT(item), gDataName, act );
448             gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), index == act->private_data->active );
450             g_free(str);
452             g_signal_connect( G_OBJECT(item), "toggled", G_CALLBACK(menu_toggled_cb), GINT_TO_POINTER(index) );
454             index++;
455             valid = gtk_tree_model_iter_next( act->private_data->model, &iter );
456         }
458         gtk_menu_item_set_submenu( GTK_MENU_ITEM(item), subby );
459         gtk_widget_show_all( subby );
461         g_free(sss);
462     } else {
463         item = gParentClass->create_menu_item( action );
464     }
466     return item;
470 void ege_select_one_action_set_radio_action_type( EgeSelectOneAction* action, GType radioActionType )
472     (void)action;
474     if ( g_type_is_a( radioActionType, GTK_TYPE_RADIO_ACTION ) ) {
475         action->private_data->radioActionType = radioActionType;
476     } else {
477         g_warning("Passed in type '%s' is not derived from '%s'", g_type_name(radioActionType), g_type_name(GTK_TYPE_RADIO_ACTION) );
478     }
481 GtkWidget* create_tool_item( GtkAction* action )
483     GtkWidget* item = 0;
485     if ( IS_EGE_SELECT_ONE_ACTION(action) && EGE_SELECT_ONE_ACTION(action)->private_data->model )
486     {
487         EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(action);
488         item = GTK_WIDGET( gtk_tool_item_new() );
490         if ( act->private_data->appearanceMode == APPEARANCE_FULL ) {
491             GtkWidget* holder = gtk_hbox_new( FALSE, 0 );
493             GtkRadioAction* ract = 0;
494             GtkWidget* sub = 0;
495             GSList* group = 0;
496             GtkTreeIter iter;
497             gboolean valid = FALSE;
498             gint index = 0;
499             GtkTooltips* tooltips = gtk_tooltips_new();
501             gchar*  sss = 0;
502             g_object_get( G_OBJECT(action), "short_label", &sss, NULL );
503             if (sss) {
504                 GtkWidget* lbl;
505                 lbl = gtk_label_new(sss);
506                 gtk_box_pack_start( GTK_BOX(holder), lbl, FALSE, FALSE, 4 );
507             }
509             valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter );
510             while ( valid ) {
511                 gchar* str = 0;
512                 gchar* tip = 0;
513                 gchar* iconId = 0;
514                 /*
515                 gint size = 0;
516                 */
517                 gtk_tree_model_get( act->private_data->model, &iter,
518                                     act->private_data->labelColumn, &str,
519                                     -1 );
520                 if ( act->private_data->iconColumn >= 0 ) {
521                     gtk_tree_model_get( act->private_data->model, &iter,
522                                         act->private_data->iconColumn, &iconId,
523                                         -1 );
524                 }
525                 if ( act->private_data->tooltipColumn >= 0 ) {
526                     gtk_tree_model_get( act->private_data->model, &iter,
527                                         act->private_data->tooltipColumn, &tip,
528                                         -1 );
529                 }
531                 if ( act->private_data->radioActionType ) {
532                     void* obj = g_object_new( act->private_data->radioActionType,
533                                               "name", "Name 1",
534                                               "label", str,
535                                               "tooltip", tip,
536                                               "value", index,
537                                               /*
538                                               "iconId", iconId,
539                                               "iconSize", size,
540                                               */
541                                               NULL );
542                     if ( iconId ) {
543                         g_object_set( G_OBJECT(obj), act->private_data->iconProperty, iconId, NULL );
544                     }
546                     ract = GTK_RADIO_ACTION(obj);
547                 } else {
548                     ract = gtk_radio_action_new( "Name 1", str, tip, iconId, index );
549                 }
551                 gtk_radio_action_set_group( ract, group );
552                 group = gtk_radio_action_get_group( ract );
554                 if ( index == act->private_data->active ) {
555                     gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(ract), TRUE );
556                 }
557                 g_signal_connect( G_OBJECT(ract), "changed", G_CALLBACK( proxy_action_chagned_cb ), act );
559                 sub = gtk_action_create_tool_item( GTK_ACTION(ract) );
560                 gtk_action_connect_proxy( GTK_ACTION(ract), sub );
561                 gtk_tool_item_set_tooltip( GTK_TOOL_ITEM(sub), tooltips, tip, NULL );
563                 gtk_box_pack_start( GTK_BOX(holder), sub, FALSE, FALSE, 0 );
565                 g_free( str );
566                 g_free( tip );
567                 g_free( iconId );
569                 index++;
570                 valid = gtk_tree_model_iter_next( act->private_data->model, &iter );
571             }
573             g_object_set_data( G_OBJECT(holder), "ege-proxy_action-group", group );
574             g_object_set_data( G_OBJECT(holder), "ege-tooltips", tooltips );
576             gtk_container_add( GTK_CONTAINER(item), holder );
577         } else {
578             GtkWidget* holder = gtk_hbox_new( FALSE, 4 );
579             GtkWidget* normal = gtk_combo_box_new_with_model( act->private_data->model );
581             GtkCellRenderer * renderer = 0;
583             if ( act->private_data->iconColumn >= 0 ) {
584                 renderer = gtk_cell_renderer_pixbuf_new();
585                 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
587                 // "icon-name"
588                 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn );
589             }
591             renderer = gtk_cell_renderer_text_new();
592             gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
593             gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "text", act->private_data->labelColumn );
595             gtk_combo_box_set_active( GTK_COMBO_BOX(normal), act->private_data->active );
597             g_signal_connect( G_OBJECT(normal), "changed", G_CALLBACK(combo_changed_cb), action );
599             g_object_set_data( G_OBJECT(holder), "ege-combo-box", normal );
601             if (act->private_data->appearanceMode == APPEARANCE_COMPACT) {
602                 gchar*  sss = 0;
603                 g_object_get( G_OBJECT(action), "short_label", &sss, NULL );
604                 if (sss) {
605                     GtkWidget* lbl;
606                     lbl = gtk_label_new(sss);
607                     gtk_box_pack_start( GTK_BOX(holder), lbl, FALSE, FALSE, 4 );
608                 }
609             }
611             gtk_box_pack_start( GTK_BOX(holder), normal, FALSE, FALSE, 0 );
613             gtk_container_add( GTK_CONTAINER(item), holder );
614         }
616         gtk_widget_show_all( item );
617     } else {
618         item = gParentClass->create_tool_item( action );
619     }
621     return item;
625 void connect_proxy( GtkAction *action, GtkWidget *proxy )
627     gParentClass->connect_proxy( action, proxy );
630 void disconnect_proxy( GtkAction *action, GtkWidget *proxy )
632     gParentClass->disconnect_proxy( action, proxy );
636 void resync_active( EgeSelectOneAction* act, gint active )
638     if ( act->private_data->active != active ) {
639         act->private_data->active = active;
640         GSList* proxies = gtk_action_get_proxies( GTK_ACTION(act) );
641         while ( proxies ) {
642             if ( GTK_IS_TOOL_ITEM(proxies->data) ) {
643                 /* Search for the things we built up in create_tool_item() */
644                 GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) );
645                 if ( children && children->data ) {
646                     gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" );
647                     if ( GTK_IS_COMBO_BOX(combodata) ) {
648                         GtkComboBox* combo = GTK_COMBO_BOX(combodata);
649                         if ( gtk_combo_box_get_active(combo) != active ) {
650                             gtk_combo_box_set_active( combo, active );
651                         }
652                     } else if ( GTK_IS_HBOX(children->data) ) {
653                         gpointer data = g_object_get_data( G_OBJECT(children->data), "ege-proxy_action-group" );
654                         if ( data ) {
655                             GSList* group = (GSList*)data;
656                             GtkRadioAction* oneAction = GTK_RADIO_ACTION(group->data);
657                             gint hot = gtk_radio_action_get_current_value( oneAction );
658                             if ( hot != active ) {
659                                 /*gtk_radio_action_set_current_value( oneAction, active );*/
660                                 gint value = 0;
661                                 while ( group ) {
662                                     GtkRadioAction* possible = GTK_RADIO_ACTION(group->data);
663                                     g_object_get( G_OBJECT(possible), "value", &value, NULL );
664                                     if ( value == active ) {
665                                         /* Found the group member to set active */
666                                         gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(possible), TRUE );
667                                         break;
668                                     }
670                                     group = g_slist_next(group);
671                                 }
672                             }
673                         }
674                     }
675                 }
676             } else if ( GTK_IS_MENU_ITEM(proxies->data) ) {
677                 GtkWidget* subMenu = gtk_menu_item_get_submenu( GTK_MENU_ITEM(proxies->data) );
678                 GList* children = gtk_container_get_children( GTK_CONTAINER(subMenu) );
679                 if ( children && (g_list_length(children) > (guint)active) ) {
680                     gpointer data = g_list_nth_data( children, active );
681                     gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(data), TRUE );
682                 }
683             }
685             proxies = g_slist_next( proxies );
686         }
688         g_signal_emit( G_OBJECT(act), signals[CHANGED], 0);
689     }
692 void combo_changed_cb( GtkComboBox* widget, gpointer user_data )
694     EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data);
695     gint newActive = gtk_combo_box_get_active(widget);
696     if (newActive != act->private_data->active) {
697         g_object_set( G_OBJECT(act), "active", newActive, NULL );
698     }
701 void menu_toggled_cb( GtkWidget* obj, gpointer data )
703     GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(obj);
704     EgeSelectOneAction* act = (EgeSelectOneAction*)g_object_get_qdata( G_OBJECT(obj), gDataName );
705     gint newActive = GPOINTER_TO_INT(data);
706     if ( gtk_check_menu_item_get_active(item) && (newActive != act->private_data->active) ) {
707         g_object_set( G_OBJECT(act), "active", newActive, NULL );
708     }
711 void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, gpointer user_data )
713     (void)current;
714     if ( gtk_toggle_action_get_active( GTK_TOGGLE_ACTION(action) ) ) {
715         EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data);
716         gint newActive = gtk_radio_action_get_current_value( action );
717         if ( newActive != act->private_data->active ) {
718             g_object_set( G_OBJECT(act), "active", newActive, NULL );
719         }
720     }