/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is EGE Select One Action. * * The Initial Developer of the Original Code is * Jon A. Cruz. * Portions created by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* Note: this file should be kept compilable as both .cpp and .c */ #include <string.h> #include <gtk/gtkhbox.h> #include <gtk/gtklabel.h> #include <gtk/gtktoolitem.h> #include <gtk/gtkcombobox.h> #include <gtk/gtkcellrenderertext.h> #include <gtk/gtkcellrendererpixbuf.h> #include <gtk/gtkcelllayout.h> #include <gtk/gtkradioaction.h> #include <gtk/gtkradiomenuitem.h> #include <gtk/gtktable.h> #include "ege-select-one-action.h" enum { CHANGED = 0, LAST_SIGNAL}; static void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ); static void ege_select_one_action_init( EgeSelectOneAction* action ); static void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec ); static void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec ); static void resync_active( EgeSelectOneAction* act, gint active ); static void combo_changed_cb( GtkComboBox* widget, gpointer user_data ); static void menu_toggled_cb( GtkWidget* obj, gpointer data ); static void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, gpointer user_data ); static GtkWidget* create_menu_item( GtkAction* action ); static GtkWidget* create_tool_item( GtkAction* action ); static void connect_proxy( GtkAction *action, GtkWidget *proxy ); static void disconnect_proxy( GtkAction *action, GtkWidget *proxy ); static GtkActionClass* gParentClass = 0; static guint signals[LAST_SIGNAL] = {0}; static GQuark gDataName = 0; enum { APPEARANCE_UNKNOWN = -1, APPEARANCE_NONE = 0, APPEARANCE_FULL, // label, then all choices represented by separate buttons APPEARANCE_COMPACT, // label, then choices in a drop-down menu APPEARANCE_MINIMAL, // no label, just choices in a drop-down menu }; struct _EgeSelectOneActionPrivate { gint active; gint labelColumn; gint iconColumn; gint tooltipColumn; gint appearanceMode; gint iconSize; GType radioActionType; GtkTreeModel* model; gchar* iconProperty; gchar* appearance; }; #define EGE_SELECT_ONE_ACTION_GET_PRIVATE( o ) ( G_TYPE_INSTANCE_GET_PRIVATE( (o), EGE_SELECT_ONE_ACTION_TYPE, EgeSelectOneActionPrivate ) ) enum { PROP_MODEL = 1, PROP_ACTIVE, PROP_LABEL_COLUMN, PROP_ICON_COLUMN, PROP_TOOLTIP_COLUMN, PROP_ICON_PROP, PROP_ICON_SIZE, PROP_APPEARANCE }; GType ege_select_one_action_get_type( void ) { static GType myType = 0; if ( !myType ) { static const GTypeInfo myInfo = { sizeof( EgeSelectOneActionClass ), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc)ege_select_one_action_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof( EgeSelectOneAction ), 0, /* n_preallocs */ (GInstanceInitFunc)ege_select_one_action_init, NULL }; myType = g_type_register_static( GTK_TYPE_ACTION, "EgeSelectOneAction", &myInfo, (GTypeFlags)0 ); } return myType; } GtkTreeModel *ege_select_one_action_get_model(EgeSelectOneAction* action ){ return GTK_TREE_MODEL(action->private_data->model); } void ege_select_one_action_class_init( EgeSelectOneActionClass* klass ) { if ( klass ) { gParentClass = GTK_ACTION_CLASS( g_type_class_peek_parent( klass ) ); GObjectClass* objClass = G_OBJECT_CLASS( klass ); gDataName = g_quark_from_string("ege-select1-action"); objClass->get_property = ege_select_one_action_get_property; objClass->set_property = ege_select_one_action_set_property; klass->parent_class.create_menu_item = create_menu_item; klass->parent_class.create_tool_item = create_tool_item; klass->parent_class.connect_proxy = connect_proxy; klass->parent_class.disconnect_proxy = disconnect_proxy; g_object_class_install_property( objClass, PROP_MODEL, g_param_spec_object( "model", "Tree Model", "Tree model of possible items", GTK_TYPE_TREE_MODEL, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, PROP_ACTIVE, g_param_spec_int( "active", "Active Selection", "The index of the selected item", 0, 20, 0, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, PROP_LABEL_COLUMN, g_param_spec_int( "label-column", "Display Column", "The column of the model that holds display strings", 0, 20, 0, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, PROP_ICON_COLUMN, g_param_spec_int( "icon-column", "Icon Column", "The column of the model that holds display icon name", -1, 20, -1, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, PROP_TOOLTIP_COLUMN, g_param_spec_int( "tooltip-column", "Tooltip Column", "The column of the model that holds tooltip strings", -1, 20, -1, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, PROP_ICON_PROP, g_param_spec_string( "icon-property", "Icon Property", "Target icon property", "", (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, PROP_ICON_SIZE, g_param_spec_int( "icon-size", "Icon Size", "Target icon size", -1, 20, -1, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_object_class_install_property( objClass, PROP_APPEARANCE, g_param_spec_string( "appearance", "Appearance hint", "A hint for how to display", "", (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); signals[CHANGED] = g_signal_new( "changed", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(EgeSelectOneActionClass, changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); g_type_class_add_private( klass, sizeof(EgeSelectOneActionClass) ); } } void ege_select_one_action_init( EgeSelectOneAction* action ) { action->private_data = EGE_SELECT_ONE_ACTION_GET_PRIVATE( action ); action->private_data->active = 0; action->private_data->labelColumn = 0; action->private_data->iconColumn = -1; action->private_data->tooltipColumn = -1; action->private_data->appearanceMode = APPEARANCE_NONE; action->private_data->radioActionType = 0; action->private_data->model = 0; action->private_data->iconProperty = g_strdup("stock-id"); action->private_data->iconSize = -1; action->private_data->appearance = 0; /* g_signal_connect( action, "notify", G_CALLBACK( fixup_labels ), NULL ); */ } EgeSelectOneAction* ege_select_one_action_new( const gchar *name, const gchar *label, const gchar *tooltip, const gchar *stock_id, GtkTreeModel* model ) { GObject* obj = (GObject*)g_object_new( EGE_SELECT_ONE_ACTION_TYPE, "name", name, "label", label, "tooltip", tooltip, "stock_id", stock_id, "model", model, "active", 0, "icon-property", "stock-id", NULL ); EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj ); return action; } gint ege_select_one_action_get_active( EgeSelectOneAction* action ) { g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 ); return action->private_data->active; } void ege_select_one_action_set_active( EgeSelectOneAction* action, gint val ) { g_object_set( G_OBJECT(action), "active", val, NULL ); } gint ege_select_one_action_get_label_column( EgeSelectOneAction* action ) { g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 ); return action->private_data->labelColumn; } void ege_select_one_action_set_label_column( EgeSelectOneAction* action, gint col ) { g_object_set( G_OBJECT(action), "label-column", col, NULL ); } gint ege_select_one_action_get_icon_column( EgeSelectOneAction* action ) { g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 ); return action->private_data->iconColumn; } void ege_select_one_action_set_icon_column( EgeSelectOneAction* action, gint col ) { g_object_set( G_OBJECT(action), "icon-column", col, NULL ); } gint ege_select_one_action_get_icon_size( EgeSelectOneAction* action ) { g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 ); return action->private_data->iconSize; } void ege_select_one_action_set_icon_size( EgeSelectOneAction* action, gint size ) { g_object_set( G_OBJECT(action), "icon-size", size, NULL ); } gint ege_select_one_action_get_tooltip_column( EgeSelectOneAction* action ) { g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 ); return action->private_data->tooltipColumn; } void ege_select_one_action_set_tooltip_column( EgeSelectOneAction* action, gint col ) { g_object_set( G_OBJECT(action), "tooltip-column", col, NULL ); } void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar const* val ) { g_object_set( G_OBJECT(action), "appearance", val, NULL ); } void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec ) { EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj ); switch ( propId ) { case PROP_MODEL: g_value_set_object( value, action->private_data->model ); break; case PROP_ACTIVE: g_value_set_int( value, action->private_data->active ); break; case PROP_LABEL_COLUMN: g_value_set_int( value, action->private_data->labelColumn ); break; case PROP_ICON_COLUMN: g_value_set_int( value, action->private_data->iconColumn ); break; case PROP_TOOLTIP_COLUMN: g_value_set_int( value, action->private_data->tooltipColumn ); break; case PROP_ICON_PROP: g_value_set_string( value, action->private_data->iconProperty ); break; case PROP_ICON_SIZE: g_value_set_int( value, action->private_data->iconSize ); break; case PROP_APPEARANCE: g_value_set_string( value, action->private_data->appearance ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec ); } } void ege_select_one_action_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec ) { EgeSelectOneAction* action = EGE_SELECT_ONE_ACTION( obj ); switch ( propId ) { case PROP_MODEL: { action->private_data->model = GTK_TREE_MODEL( g_value_get_object( value ) ); } break; case PROP_ACTIVE: { resync_active( action, g_value_get_int( value ) ); } break; case PROP_LABEL_COLUMN: { action->private_data->labelColumn = g_value_get_int( value ); } break; case PROP_ICON_COLUMN: { action->private_data->iconColumn = g_value_get_int( value ); } break; case PROP_TOOLTIP_COLUMN: { action->private_data->tooltipColumn = g_value_get_int( value ); } break; case PROP_ICON_PROP: { gchar* tmp = action->private_data->iconProperty; gchar* newVal = g_value_dup_string( value ); action->private_data->iconProperty = newVal; g_free( tmp ); } break; case PROP_ICON_SIZE: { action->private_data->iconSize = g_value_get_int( value ); } break; case PROP_APPEARANCE: { gchar* tmp = action->private_data->appearance; gchar* newVal = g_value_dup_string( value ); action->private_data->appearance = newVal; g_free( tmp ); if ( !action->private_data->appearance || (strcmp("", newVal) == 0) ) { action->private_data->appearanceMode = APPEARANCE_NONE; } else if ( strcmp("full", newVal) == 0 ) { action->private_data->appearanceMode = APPEARANCE_FULL; } else if ( strcmp("compact", newVal) == 0 ) { action->private_data->appearanceMode = APPEARANCE_COMPACT; } else if ( strcmp("minimal", newVal) == 0 ) { action->private_data->appearanceMode = APPEARANCE_MINIMAL; } else { action->private_data->appearanceMode = APPEARANCE_UNKNOWN; } } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID( obj, propId, pspec ); } } GtkWidget* create_menu_item( GtkAction* action ) { GtkWidget* item = 0; if ( IS_EGE_SELECT_ONE_ACTION(action) ) { EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION( action ); gchar* sss = 0; gboolean valid = FALSE; gint index = 0; GtkTreeIter iter; GSList* group = 0; GtkWidget* subby = gtk_menu_new(); g_object_get( G_OBJECT(action), "label", &sss, NULL ); item = gtk_menu_item_new_with_label( sss ); valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter ); while ( valid ) { gchar* str = 0; gtk_tree_model_get( act->private_data->model, &iter, act->private_data->labelColumn, &str, -1 ); GtkWidget *item = gtk_radio_menu_item_new_with_label( group, str ); group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(item) ); gtk_menu_shell_append( GTK_MENU_SHELL(subby), item ); g_object_set_qdata( G_OBJECT(item), gDataName, act ); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), index == act->private_data->active ); g_free(str); g_signal_connect( G_OBJECT(item), "toggled", G_CALLBACK(menu_toggled_cb), GINT_TO_POINTER(index) ); index++; valid = gtk_tree_model_iter_next( act->private_data->model, &iter ); } gtk_menu_item_set_submenu( GTK_MENU_ITEM(item), subby ); gtk_widget_show_all( subby ); g_free(sss); } else { item = gParentClass->create_menu_item( action ); } return item; } void ege_select_one_action_set_radio_action_type( EgeSelectOneAction* action, GType radioActionType ) { (void)action; if ( g_type_is_a( radioActionType, GTK_TYPE_RADIO_ACTION ) ) { action->private_data->radioActionType = radioActionType; } else { g_warning("Passed in type '%s' is not derived from '%s'", g_type_name(radioActionType), g_type_name(GTK_TYPE_RADIO_ACTION) ); } } GtkWidget* create_tool_item( GtkAction* action ) { GtkWidget* item = 0; if ( IS_EGE_SELECT_ONE_ACTION(action) && EGE_SELECT_ONE_ACTION(action)->private_data->model ) { EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(action); item = GTK_WIDGET( gtk_tool_item_new() ); if ( act->private_data->appearanceMode == APPEARANCE_FULL ) { GtkWidget* holder = gtk_hbox_new( FALSE, 0 ); GtkRadioAction* ract = 0; GtkWidget* sub = 0; GSList* group = 0; GtkTreeIter iter; gboolean valid = FALSE; gint index = 0; GtkTooltips* tooltips = gtk_tooltips_new(); gchar* sss = 0; g_object_get( G_OBJECT(action), "short_label", &sss, NULL ); if (sss) { GtkWidget* lbl; lbl = gtk_label_new(sss); gtk_box_pack_start( GTK_BOX(holder), lbl, FALSE, FALSE, 4 ); } valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter ); while ( valid ) { gchar* str = 0; gchar* tip = 0; gchar* iconId = 0; /* gint size = 0; */ gtk_tree_model_get( act->private_data->model, &iter, act->private_data->labelColumn, &str, -1 ); if ( act->private_data->iconColumn >= 0 ) { gtk_tree_model_get( act->private_data->model, &iter, act->private_data->iconColumn, &iconId, -1 ); } if ( act->private_data->tooltipColumn >= 0 ) { gtk_tree_model_get( act->private_data->model, &iter, act->private_data->tooltipColumn, &tip, -1 ); } if ( act->private_data->radioActionType ) { void* obj = g_object_new( act->private_data->radioActionType, "name", "Name 1", "label", str, "tooltip", tip, "value", index, /* "iconId", iconId, "iconSize", size, */ NULL ); if ( iconId ) { g_object_set( G_OBJECT(obj), act->private_data->iconProperty, iconId, NULL ); } if ( act->private_data->iconProperty >= 0 ) { /* TODO get this string to be set instead of hardcoded */ if ( act->private_data->iconSize >= 0 ) { g_object_set( G_OBJECT(obj), "iconSize", act->private_data->iconSize, NULL ); } } ract = GTK_RADIO_ACTION(obj); } else { ract = gtk_radio_action_new( "Name 1", str, tip, iconId, index ); } gtk_radio_action_set_group( ract, group ); group = gtk_radio_action_get_group( ract ); if ( index == act->private_data->active ) { gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(ract), TRUE ); } g_signal_connect( G_OBJECT(ract), "changed", G_CALLBACK( proxy_action_chagned_cb ), act ); sub = gtk_action_create_tool_item( GTK_ACTION(ract) ); gtk_action_connect_proxy( GTK_ACTION(ract), sub ); gtk_tool_item_set_tooltip( GTK_TOOL_ITEM(sub), tooltips, tip, NULL ); gtk_box_pack_start( GTK_BOX(holder), sub, FALSE, FALSE, 0 ); g_free( str ); g_free( tip ); g_free( iconId ); index++; valid = gtk_tree_model_iter_next( act->private_data->model, &iter ); } g_object_set_data( G_OBJECT(holder), "ege-proxy_action-group", group ); g_object_set_data( G_OBJECT(holder), "ege-tooltips", tooltips ); gtk_container_add( GTK_CONTAINER(item), holder ); } else { GtkWidget* holder = gtk_hbox_new( FALSE, 4 ); GtkWidget* normal = gtk_combo_box_new_with_model( act->private_data->model ); GtkCellRenderer * renderer = 0; if ( act->private_data->iconColumn >= 0 ) { renderer = gtk_cell_renderer_pixbuf_new(); gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE ); // "icon-name" gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn ); } renderer = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE ); gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "text", act->private_data->labelColumn ); gtk_combo_box_set_active( GTK_COMBO_BOX(normal), act->private_data->active ); g_signal_connect( G_OBJECT(normal), "changed", G_CALLBACK(combo_changed_cb), action ); g_object_set_data( G_OBJECT(holder), "ege-combo-box", normal ); if (act->private_data->appearanceMode == APPEARANCE_COMPACT) { gchar* sss = 0; g_object_get( G_OBJECT(action), "short_label", &sss, NULL ); if (sss) { GtkWidget* lbl; lbl = gtk_label_new(sss); gtk_box_pack_start( GTK_BOX(holder), lbl, FALSE, FALSE, 4 ); } } gtk_box_pack_start( GTK_BOX(holder), normal, FALSE, FALSE, 0 ); gtk_container_add( GTK_CONTAINER(item), holder ); } gtk_widget_show_all( item ); } else { item = gParentClass->create_tool_item( action ); } return item; } void connect_proxy( GtkAction *action, GtkWidget *proxy ) { gParentClass->connect_proxy( action, proxy ); } void disconnect_proxy( GtkAction *action, GtkWidget *proxy ) { gParentClass->disconnect_proxy( action, proxy ); } void resync_active( EgeSelectOneAction* act, gint active ) { if ( act->private_data->active != active ) { act->private_data->active = active; GSList* proxies = gtk_action_get_proxies( GTK_ACTION(act) ); while ( proxies ) { if ( GTK_IS_TOOL_ITEM(proxies->data) ) { /* Search for the things we built up in create_tool_item() */ GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) ); if ( children && children->data ) { gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" ); if ( GTK_IS_COMBO_BOX(combodata) ) { GtkComboBox* combo = GTK_COMBO_BOX(combodata); if ( gtk_combo_box_get_active(combo) != active ) { gtk_combo_box_set_active( combo, active ); } } else if ( GTK_IS_HBOX(children->data) ) { gpointer data = g_object_get_data( G_OBJECT(children->data), "ege-proxy_action-group" ); if ( data ) { GSList* group = (GSList*)data; GtkRadioAction* oneAction = GTK_RADIO_ACTION(group->data); gint hot = gtk_radio_action_get_current_value( oneAction ); if ( hot != active ) { /*gtk_radio_action_set_current_value( oneAction, active );*/ gint value = 0; while ( group ) { GtkRadioAction* possible = GTK_RADIO_ACTION(group->data); g_object_get( G_OBJECT(possible), "value", &value, NULL ); if ( value == active ) { /* Found the group member to set active */ gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(possible), TRUE ); break; } group = g_slist_next(group); } } } } } } else if ( GTK_IS_MENU_ITEM(proxies->data) ) { GtkWidget* subMenu = gtk_menu_item_get_submenu( GTK_MENU_ITEM(proxies->data) ); GList* children = gtk_container_get_children( GTK_CONTAINER(subMenu) ); if ( children && (g_list_length(children) > (guint)active) ) { gpointer data = g_list_nth_data( children, active ); gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(data), TRUE ); } } proxies = g_slist_next( proxies ); } g_signal_emit( G_OBJECT(act), signals[CHANGED], 0); } } void combo_changed_cb( GtkComboBox* widget, gpointer user_data ) { EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data); gint newActive = gtk_combo_box_get_active(widget); if (newActive != act->private_data->active && newActive != -1) { g_object_set( G_OBJECT(act), "active", newActive, NULL ); } } void menu_toggled_cb( GtkWidget* obj, gpointer data ) { GtkCheckMenuItem* item = GTK_CHECK_MENU_ITEM(obj); EgeSelectOneAction* act = (EgeSelectOneAction*)g_object_get_qdata( G_OBJECT(obj), gDataName ); gint newActive = GPOINTER_TO_INT(data); if ( gtk_check_menu_item_get_active(item) && (newActive != act->private_data->active) ) { g_object_set( G_OBJECT(act), "active", newActive, NULL ); } } void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, gpointer user_data ) { (void)current; if ( gtk_toggle_action_get_active( GTK_TOGGLE_ACTION(action) ) ) { EgeSelectOneAction* act = EGE_SELECT_ONE_ACTION(user_data); gint newActive = gtk_radio_action_get_current_value( action ); if ( newActive != act->private_data->active ) { g_object_set( G_OBJECT(act), "active", newActive, NULL ); } } }