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 )
116 {
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;
136 }
138 void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
139 {
140 if ( klass ) {
141 gParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) );
142 GObjectClass* objClass = G_OBJECT_CLASS( klass );
144 gDataName = g_quark_from_string("ege-select1-action");
146 objClass->get_property = ege_select_one_action_get_property;
147 objClass->set_property = ege_select_one_action_set_property;
149 klass->parent_class.create_menu_item = create_menu_item;
150 klass->parent_class.create_tool_item = create_tool_item;
151 klass->parent_class.connect_proxy = connect_proxy;
152 klass->parent_class.disconnect_proxy = disconnect_proxy;
154 g_object_class_install_property( objClass,
155 PROP_MODEL,
156 g_param_spec_object( "model",
157 "Tree Model",
158 "Tree model of possible items",
159 GTK_TYPE_TREE_MODEL,
160 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
162 g_object_class_install_property( objClass,
163 PROP_ACTIVE,
164 g_param_spec_int( "active",
165 "Active Selection",
166 "The index of the selected item",
167 0, 20, 0,
168 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
170 g_object_class_install_property( objClass,
171 PROP_LABEL_COLUMN,
172 g_param_spec_int( "label-column",
173 "Display Column",
174 "The column of the model that holds display strings",
175 0, 20, 0,
176 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
178 g_object_class_install_property( objClass,
179 PROP_ICON_COLUMN,
180 g_param_spec_int( "icon-column",
181 "Icon Column",
182 "The column of the model that holds display icon name",
183 -1, 20, -1,
184 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
186 g_object_class_install_property( objClass,
187 PROP_TOOLTIP_COLUMN,
188 g_param_spec_int( "tooltip-column",
189 "Tooltip Column",
190 "The column of the model that holds tooltip strings",
191 -1, 20, -1,
192 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
194 g_object_class_install_property( objClass,
195 PROP_ICON_PROP,
196 g_param_spec_string( "icon-property",
197 "Icon Property",
198 "Target icon property",
199 "",
200 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
202 g_object_class_install_property( objClass,
203 PROP_APPEARANCE,
204 g_param_spec_string( "appearance",
205 "Appearance hint",
206 "A hint for how to display",
207 "",
208 (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
210 signals[CHANGED] = g_signal_new( "changed",
211 G_TYPE_FROM_CLASS(klass),
212 G_SIGNAL_RUN_FIRST,
213 G_STRUCT_OFFSET(EgeSelectOneActionClass, changed),
214 NULL, NULL,
215 g_cclosure_marshal_VOID__VOID,
216 G_TYPE_NONE, 0);
218 g_type_class_add_private( klass, sizeof(EgeSelectOneActionClass) );
219 }
220 }
223 void ege_select_one_action_init( EgeSelectOneAction* action )
224 {
225 action->private_data = EGE_SELECT_ONE_ACTION_GET_PRIVATE( action );
226 action->private_data->active = 0;
227 action->private_data->labelColumn = 0;
228 action->private_data->iconColumn = -1;
229 action->private_data->tooltipColumn = -1;
230 action->private_data->appearanceMode = APPEARANCE_NONE;
231 action->private_data->radioActionType = 0;
232 action->private_data->model = 0;
233 action->private_data->iconProperty = g_strdup("stock-id");
234 action->private_data->appearance = 0;
236 /* g_signal_connect( action, "notify", G_CALLBACK( fixup_labels ), NULL ); */
237 }
239 EgeSelectOneAction* ege_select_one_action_new( const gchar *name,
240 const gchar *label,
241 const gchar *tooltip,
242 const gchar *stock_id,
243 GtkTreeModel* model )
244 {
245 GObject* obj = (GObject*)g_object_new( EGE_SELECT_ONE_ACTION_TYPE,
246 "name", name,
247 "label", label,
248 "tooltip", tooltip,
249 "stock_id", stock_id,
250 "model", model,
251 "active", 0,
252 "icon-property", "stock-id",
253 NULL );
255 EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj );
257 return action;
258 }
261 gint ege_select_one_action_get_active( EgeSelectOneAction* action )
262 {
263 g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
264 return action->private_data->active;
265 }
267 void ege_select_one_action_set_active( EgeSelectOneAction* action, gint val )
268 {
269 g_object_set( G_OBJECT(action), "active", val, NULL );
270 }
272 gint ege_select_one_action_get_label_column( EgeSelectOneAction* action )
273 {
274 g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
275 return action->private_data->labelColumn;
276 }
278 void ege_select_one_action_set_label_column( EgeSelectOneAction* action, gint col )
279 {
280 g_object_set( G_OBJECT(action), "label-column", col, NULL );
281 }
283 gint ege_select_one_action_get_icon_column( EgeSelectOneAction* action )
284 {
285 g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
286 return action->private_data->iconColumn;
287 }
289 void ege_select_one_action_set_icon_column( EgeSelectOneAction* action, gint col )
290 {
291 g_object_set( G_OBJECT(action), "icon-column", col, NULL );
292 }
294 gint ege_select_one_action_get_tooltip_column( EgeSelectOneAction* action )
295 {
296 g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
297 return action->private_data->tooltipColumn;
298 }
300 void ege_select_one_action_set_tooltip_column( EgeSelectOneAction* action, gint col )
301 {
302 g_object_set( G_OBJECT(action), "tooltip-column", col, NULL );
303 }
305 void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar const* val )
306 {
307 g_object_set( G_OBJECT(action), "appearance", val, NULL );
308 }
310 void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec )
311 {
312 EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj );
313 switch ( propId ) {
314 case PROP_MODEL:
315 g_value_set_object( value, action->private_data->model );
316 break;
318 case PROP_ACTIVE:
319 g_value_set_int( value, action->private_data->active );
320 break;
322 case PROP_LABEL_COLUMN:
323 g_value_set_int( value, action->private_data->labelColumn );
324 break;
326 case PROP_ICON_COLUMN:
327 g_value_set_int( value, action->private_data->iconColumn );
328 break;
330 case PROP_TOOLTIP_COLUMN:
331 g_value_set_int( value, action->private_data->tooltipColumn );
332 break;
334 case PROP_ICON_PROP:
335 g_value_set_string( value, action->private_data->iconProperty );
336 break;
338 case PROP_APPEARANCE:
339 g_value_set_string( value, action->private_data->appearance );
340 break;
342 default:
343 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
344 }
345 }
347 void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec )
348 {
349 EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj );
350 switch ( propId ) {
351 case PROP_MODEL:
352 {
353 action->private_data->model = GTK_TREE_MODEL( g_value_get_object( value ) );
354 }
355 break;
357 case PROP_ACTIVE:
358 {
359 resync_active( action, g_value_get_int( value ) );
360 }
361 break;
363 case PROP_LABEL_COLUMN:
364 {
365 action->private_data->labelColumn = g_value_get_int( value );
366 }
367 break;
369 case PROP_ICON_COLUMN:
370 {
371 action->private_data->iconColumn = g_value_get_int( value );
372 }
373 break;
375 case PROP_TOOLTIP_COLUMN:
376 {
377 action->private_data->tooltipColumn = g_value_get_int( value );
378 }
379 break;
381 case PROP_ICON_PROP:
382 {
383 gchar* tmp = action->private_data->iconProperty;
384 gchar* newVal = g_value_dup_string( value );
385 action->private_data->iconProperty = newVal;
386 g_free( tmp );
387 }
388 break;
390 case PROP_APPEARANCE:
391 {
392 gchar* tmp = action->private_data->appearance;
393 gchar* newVal = g_value_dup_string( value );
394 action->private_data->appearance = newVal;
395 g_free( tmp );
397 if ( !action->private_data->appearance || (strcmp("", newVal) == 0) ) {
398 action->private_data->appearanceMode = APPEARANCE_NONE;
399 } else if ( strcmp("full", newVal) == 0 ) {
400 action->private_data->appearanceMode = APPEARANCE_FULL;
401 } else if ( strcmp("compact", newVal) == 0 ) {
402 action->private_data->appearanceMode = APPEARANCE_COMPACT;
403 } else if ( strcmp("minimal", newVal) == 0 ) {
404 action->private_data->appearanceMode = APPEARANCE_MINIMAL;
405 } else {
406 action->private_data->appearanceMode = APPEARANCE_UNKNOWN;
407 }
408 }
409 break;
411 default:
412 G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec );
413 }
414 }
416 GtkWidget* create_menu_item( GtkAction* action )
417 {
418 GtkWidget* item = 0;
420 if ( IS_EGE_SELECT_ONE_ACTION(action) ) {
421 EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION( action );
422 gchar* sss = 0;
423 gboolean valid = FALSE;
424 gint index = 0;
425 GtkTreeIter iter;
426 GSList* group = 0;
427 GtkWidget* subby = gtk_menu_new();
429 g_object_get( G_OBJECT(action), "label", &sss, NULL );
431 item = gtk_menu_item_new_with_label( sss );
433 valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter );
434 while ( valid ) {
435 gchar* str = 0;
436 gtk_tree_model_get( act->private_data->model, &iter,
437 act->private_data->labelColumn, &str,
438 -1 );
440 GtkWidget *item = gtk_radio_menu_item_new_with_label( group, str );
441 group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(item) );
442 gtk_menu_shell_append( GTK_MENU_SHELL(subby), item );
443 g_object_set_qdata( G_OBJECT(item), gDataName, act );
445 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), index == act->private_data->active );
447 g_free(str);
449 g_signal_connect( G_OBJECT(item), "toggled", G_CALLBACK(menu_toggled_cb), GINT_TO_POINTER(index) );
451 index++;
452 valid = gtk_tree_model_iter_next( act->private_data->model, &iter );
453 }
455 gtk_menu_item_set_submenu( GTK_MENU_ITEM(item), subby );
456 gtk_widget_show_all( subby );
458 g_free(sss);
459 } else {
460 item = gParentClass->create_menu_item( action );
461 }
463 return item;
464 }
467 void ege_select_one_action_set_radio_action_type( EgeSelectOneAction* action, GType radioActionType )
468 {
469 (void)action;
471 if ( g_type_is_a( radioActionType, GTK_TYPE_RADIO_ACTION ) ) {
472 action->private_data->radioActionType = radioActionType;
473 } else {
474 g_warning("Passed in type '%s' is not derived from '%s'", g_type_name(radioActionType), g_type_name(GTK_TYPE_RADIO_ACTION) );
475 }
476 }
478 GtkWidget* create_tool_item( GtkAction* action )
479 {
480 GtkWidget* item = 0;
482 if ( IS_EGE_SELECT_ONE_ACTION(action) && EGE_SELECT_ONE_ACTION(action)->private_data->model )
483 {
484 EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(action);
485 item = GTK_WIDGET( gtk_tool_item_new() );
487 if ( act->private_data->appearanceMode == APPEARANCE_FULL ) {
488 GtkWidget* holder = gtk_hbox_new( FALSE, 0 );
490 GtkRadioAction* ract = 0;
491 GtkWidget* sub = 0;
492 GSList* group = 0;
493 GtkTreeIter iter;
494 gboolean valid = FALSE;
495 gint index = 0;
496 GtkTooltips* tooltips = gtk_tooltips_new();
498 gchar* sss = 0;
499 g_object_get( G_OBJECT(action), "short_label", &sss, NULL );
500 if (sss) {
501 GtkWidget* lbl;
502 lbl = gtk_label_new(sss);
503 gtk_box_pack_start( GTK_BOX(holder), lbl, FALSE, FALSE, 4 );
504 }
506 valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter );
507 while ( valid ) {
508 gchar* str = 0;
509 gchar* tip = 0;
510 gchar* iconId = 0;
511 /*
512 gint size = 0;
513 */
514 gtk_tree_model_get( act->private_data->model, &iter,
515 act->private_data->labelColumn, &str,
516 -1 );
517 if ( act->private_data->iconColumn >= 0 ) {
518 gtk_tree_model_get( act->private_data->model, &iter,
519 act->private_data->iconColumn, &iconId,
520 -1 );
521 }
522 if ( act->private_data->tooltipColumn >= 0 ) {
523 gtk_tree_model_get( act->private_data->model, &iter,
524 act->private_data->tooltipColumn, &tip,
525 -1 );
526 }
528 if ( act->private_data->radioActionType ) {
529 void* obj = g_object_new( act->private_data->radioActionType,
530 "name", "Name 1",
531 "label", str,
532 "tooltip", tip,
533 "value", index,
534 /*
535 "iconId", iconId,
536 "iconSize", size,
537 */
538 NULL );
539 if ( iconId ) {
540 g_object_set( G_OBJECT(obj), act->private_data->iconProperty, iconId, NULL );
541 }
543 ract = GTK_RADIO_ACTION(obj);
544 } else {
545 ract = gtk_radio_action_new( "Name 1", str, tip, iconId, index );
546 }
548 gtk_radio_action_set_group( ract, group );
549 group = gtk_radio_action_get_group( ract );
551 if ( index == act->private_data->active ) {
552 gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(ract), TRUE );
553 }
554 g_signal_connect( G_OBJECT(ract), "changed", G_CALLBACK( proxy_action_chagned_cb ), act );
556 sub = gtk_action_create_tool_item( GTK_ACTION(ract) );
557 gtk_action_connect_proxy( GTK_ACTION(ract), sub );
558 gtk_tool_item_set_tooltip( GTK_TOOL_ITEM(sub), tooltips, tip, NULL );
560 gtk_box_pack_start( GTK_BOX(holder), sub, FALSE, FALSE, 0 );
562 g_free( str );
563 g_free( tip );
564 g_free( iconId );
566 index++;
567 valid = gtk_tree_model_iter_next( act->private_data->model, &iter );
568 }
570 g_object_set_data( G_OBJECT(holder), "ege-proxy_action-group", group );
571 g_object_set_data( G_OBJECT(holder), "ege-tooltips", tooltips );
573 gtk_container_add( GTK_CONTAINER(item), holder );
574 } else {
575 GtkWidget* holder = gtk_hbox_new( FALSE, 4 );
576 GtkWidget* normal = gtk_combo_box_new_with_model( act->private_data->model );
578 GtkCellRenderer * renderer = 0;
580 if ( act->private_data->iconColumn >= 0 ) {
581 renderer = gtk_cell_renderer_pixbuf_new();
582 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
584 // "icon-name"
585 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn );
586 }
588 renderer = gtk_cell_renderer_text_new();
589 gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
590 gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "text", act->private_data->labelColumn );
592 gtk_combo_box_set_active( GTK_COMBO_BOX(normal), act->private_data->active );
594 g_signal_connect( G_OBJECT(normal), "changed", G_CALLBACK(combo_changed_cb), action );
596 g_object_set_data( G_OBJECT(holder), "ege-combo-box", normal );
598 if (act->private_data->appearanceMode == APPEARANCE_COMPACT) {
599 gchar* sss = 0;
600 g_object_get( G_OBJECT(action), "short_label", &sss, NULL );
601 if (sss) {
602 GtkWidget* lbl;
603 lbl = gtk_label_new(sss);
604 gtk_box_pack_start( GTK_BOX(holder), lbl, FALSE, FALSE, 4 );
605 }
606 }
608 gtk_box_pack_start( GTK_BOX(holder), normal, FALSE, FALSE, 0 );
610 gtk_container_add( GTK_CONTAINER(item), holder );
611 }
613 gtk_widget_show_all( item );
614 } else {
615 item = gParentClass->create_tool_item( action );
616 }
618 return item;
619 }
622 void connect_proxy( GtkAction *action, GtkWidget *proxy )
623 {
624 gParentClass->connect_proxy( action, proxy );
625 }
627 void disconnect_proxy( GtkAction *action, GtkWidget *proxy )
628 {
629 gParentClass->disconnect_proxy( action, proxy );
630 }
633 void resync_active( EgeSelectOneAction* act, gint active )
634 {
635 if ( act->private_data->active != active ) {
636 act->private_data->active = active;
637 GSList* proxies = gtk_action_get_proxies( GTK_ACTION(act) );
638 while ( proxies ) {
639 if ( GTK_IS_TOOL_ITEM(proxies->data) ) {
640 /* Search for the things we built up in create_tool_item() */
641 GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) );
642 if ( children && children->data ) {
643 gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" );
644 if ( GTK_IS_COMBO_BOX(combodata) ) {
645 GtkComboBox* combo = GTK_COMBO_BOX(combodata);
646 if ( gtk_combo_box_get_active(combo) != active ) {
647 gtk_combo_box_set_active( combo, active );
648 }
649 } else if ( GTK_IS_HBOX(children->data) ) {
650 gpointer data = g_object_get_data( G_OBJECT(children->data), "ege-proxy_action-group" );
651 if ( data ) {
652 GSList* group = (GSList*)data;
653 GtkRadioAction* oneAction = GTK_RADIO_ACTION(group->data);
654 gint hot = gtk_radio_action_get_current_value( oneAction );
655 if ( hot != active ) {
656 /*gtk_radio_action_set_current_value( oneAction, active );*/
657 gint value = 0;
658 while ( group ) {
659 GtkRadioAction* possible = GTK_RADIO_ACTION(group->data);
660 g_object_get( G_OBJECT(possible), "value", &value, NULL );
661 if ( value == active ) {
662 /* Found the group member to set active */
663 gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(possible), TRUE );
664 break;
665 }
667 group = g_slist_next(group);
668 }
669 }
670 }
671 }
672 }
673 } else if ( GTK_IS_MENU_ITEM(proxies->data) ) {
674 GtkWidget* subMenu = gtk_menu_item_get_submenu( GTK_MENU_ITEM(proxies->data) );
675 GList* children = gtk_container_get_children( GTK_CONTAINER(subMenu) );
676 if ( children && (g_list_length(children) > (guint)active) ) {
677 gpointer data = g_list_nth_data( children, active );
678 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(data), TRUE );
679 }
680 }
682 proxies = g_slist_next( proxies );
683 }
685 g_signal_emit( G_OBJECT(act), signals[CHANGED], 0);
686 }
687 }
689 void combo_changed_cb( GtkComboBox* widget, gpointer user_data )
690 {
691 EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data);
692 gint newActive = gtk_combo_box_get_active(widget);
693 if (newActive != act->private_data->active) {
694 g_object_set( G_OBJECT(act), "active", newActive, NULL );
695 }
696 }
698 void menu_toggled_cb( GtkWidget* obj, gpointer data )
699 {
700 GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(obj);
701 EgeSelectOneAction* act = (EgeSelectOneAction*)g_object_get_qdata( G_OBJECT(obj), gDataName );
702 gint newActive = GPOINTER_TO_INT(data);
703 if ( gtk_check_menu_item_get_active(item) && (newActive != act->private_data->active) ) {
704 g_object_set( G_OBJECT(act), "active", newActive, NULL );
705 }
706 }
708 void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, gpointer user_data )
709 {
710 (void)current;
711 if ( gtk_toggle_action_get_active( GTK_TOGGLE_ACTION(action) ) ) {
712 EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data);
713 gint newActive = gtk_radio_action_get_current_value( action );
714 if ( newActive != act->private_data->active ) {
715 g_object_set( G_OBJECT(act), "active", newActive, NULL );
716 }
717 }
718 }