diff options
Diffstat (limited to 'src/ink-comboboxentry-action.cpp')
| -rw-r--r-- | src/ink-comboboxentry-action.cpp | 463 |
1 files changed, 324 insertions, 139 deletions
diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp index 6b5266709..06ccc3739 100644 --- a/src/ink-comboboxentry-action.cpp +++ b/src/ink-comboboxentry-action.cpp @@ -25,23 +25,27 @@ #include <iostream> #include <string.h> +#include <glibmm/ustring.h> #include <gtk/gtk.h> +#include <gdk/gdkkeysyms.h> #include "ink-comboboxentry-action.h" +#include "ui/icon-names.h" // Must handle both tool and menu items! static GtkWidget* create_tool_item( GtkAction* action ); static GtkWidget* create_menu_item( GtkAction* action ); // Internal -static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text ); -static gint check_comma_separated_text( Ink_ComboBoxEntry_Action* action ); +static gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude = false ); +static Glib::ustring check_comma_separated_text( Ink_ComboBoxEntry_Action* action ); // Callbacks static void combo_box_changed_cb( GtkComboBox* widget, gpointer data ); static void entry_activate_cb( GtkEntry* widget, gpointer data ); static gboolean match_selected_cb( GtkEntryCompletion* widget, GtkTreeModel* model, GtkTreeIter* iter, gpointer data ); +static gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data ); enum { PROP_MODEL = 1, @@ -50,7 +54,9 @@ enum { PROP_ENTRY_WIDTH, PROP_EXTRA_WIDTH, PROP_CELL_DATA_FUNC, - PROP_POPUP + PROP_SEPARATOR_FUNC, + PROP_POPUP, + PROP_FOCUS_WIDGET }; enum { @@ -60,9 +66,13 @@ enum { }; static guint signals[N_SIGNALS] = {0}; -static GtkActionClass *ink_comboboxentry_action_parent_class = NULL; static GQuark gDataName = 0; +static void ink_comboboxentry_action_init (Ink_ComboBoxEntry_Action *action); +static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass *klass); + +G_DEFINE_TYPE(Ink_ComboBoxEntry_Action, ink_comboboxentry_action, GTK_TYPE_ACTION); + static void ink_comboboxentry_action_finalize (GObject *object) { // Free any allocated resources. @@ -101,10 +111,19 @@ static void ink_comboboxentry_action_set_property (GObject *object, guint proper action->cell_data_func = g_value_get_pointer( value ); break; + case PROP_SEPARATOR_FUNC: + action->separator_func = g_value_get_pointer( value ); + break; + case PROP_POPUP: action->popup = g_value_get_boolean( value ); break; + case PROP_FOCUS_WIDGET: + action->focusWidget = (GtkWidget*)g_value_get_pointer( value ); + break; + + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -141,10 +160,19 @@ static void ink_comboboxentry_action_get_property (GObject *object, guint proper g_value_set_pointer (value, action->cell_data_func); break; + case PROP_SEPARATOR_FUNC: + g_value_set_pointer (value, action->separator_func); + break; + case PROP_POPUP: g_value_set_boolean (value, action->popup); break; + case PROP_FOCUS_WIDGET: + g_value_set_pointer (value, action->focusWidget); + break; + + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -161,8 +189,8 @@ ink_comboboxentry_action_connect_proxy (GtkAction *action, GTK_ACTION_CLASS (ink_comboboxentry_action_parent_class)->connect_proxy (action, proxy); } - -static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass *klass) +static void +ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); @@ -179,8 +207,6 @@ static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass * klass->parent_class.create_tool_item = create_tool_item; klass->parent_class.create_menu_item = create_menu_item; - ink_comboboxentry_action_parent_class = GTK_ACTION_CLASS(g_type_class_peek_parent (klass) ); - g_object_class_install_property ( gobject_class, PROP_MODEL, @@ -233,6 +259,14 @@ static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass * g_object_class_install_property ( gobject_class, + PROP_SEPARATOR_FUNC, + g_param_spec_pointer ("separator_func", + "Separator Func", + "Separator Function", + (GParamFlags)G_PARAM_READWRITE)); + + g_object_class_install_property ( + gobject_class, PROP_POPUP, g_param_spec_boolean ("popup", "Entry Popup", @@ -240,6 +274,13 @@ static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass * false, (GParamFlags)G_PARAM_READWRITE)); + g_object_class_install_property( gobject_class, + PROP_FOCUS_WIDGET, + g_param_spec_pointer( "focus-widget", + "Focus Widget", + "The widget to return focus to", + (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); + // We need to know when GtkComboBoxEvent or Menu ready for reading signals[CHANGED] = g_signal_new( "changed", G_TYPE_FROM_CLASS(klass), @@ -263,42 +304,22 @@ static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass * static void ink_comboboxentry_action_init (Ink_ComboBoxEntry_Action *action) { action->active = -1; - action->text = NULL; + action->text = strdup(""); action->entry_completion = NULL; action->indicator = NULL; action->popup = false; + action->info = NULL; + action->info_cb = NULL; + action->info_cb_id = 0; + action->info_cb_blocked = false; action->warning = NULL; + action->warning_cb = NULL; + action->warning_cb_id = 0; + action->warning_cb_blocked = false; action->altx_name = NULL; + action->focusWidget = NULL; } -GType ink_comboboxentry_action_get_type () -{ - static GType ink_comboboxentry_action_type = 0; - - if (!ink_comboboxentry_action_type) { - static const GTypeInfo ink_comboboxentry_action_info = { - sizeof(Ink_ComboBoxEntry_ActionClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) ink_comboboxentry_action_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof(Ink_ComboBoxEntry_Action), - 0, /* n_preallocs */ - (GInstanceInitFunc)ink_comboboxentry_action_init, /* instance_init */ - NULL /* value_table */ - }; - - ink_comboboxentry_action_type = g_type_register_static (GTK_TYPE_ACTION, - "Ink_ComboBoxEntry_Action", - &ink_comboboxentry_action_info, - (GTypeFlags)0 ); - } - - return ink_comboboxentry_action_type; -} - - Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name, const gchar *label, const gchar *tooltip, @@ -306,7 +327,9 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name, GtkTreeModel *model, gint entry_width, gint extra_width, - void *cell_data_func ) + void *cell_data_func, + void *separator_func, + GtkWidget *focusWidget) { g_return_val_if_fail (name != NULL, NULL); @@ -319,6 +342,8 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name, "entry_width", entry_width, "extra_width", extra_width, "cell_data_func", cell_data_func, + "separator_func", separator_func, + "focus-widget", focusWidget, NULL); } @@ -338,16 +363,8 @@ GtkWidget* create_tool_item( GtkAction* action ) item = GTK_WIDGET( gtk_tool_item_new() ); - GtkWidget* comboBoxEntry; - -// Backward-compatibility: GtkComboBoxEntry is deprecated in GTK+ >= 2.24 -// gtk_combo_box_set_entry_text_column is unavailable in earlier versions -#if GTK_CHECK_VERSION (2, 24, 0) - comboBoxEntry = gtk_combo_box_new_with_model_and_entry (ink_comboboxentry_action->model); + GtkWidget* comboBoxEntry = gtk_combo_box_new_with_model_and_entry (ink_comboboxentry_action->model); gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (comboBoxEntry), 0); -#else - comboBoxEntry = gtk_combo_box_entry_new_with_model( ink_comboboxentry_action->model, 0 ); -#endif // Name it so we can muck with it using an RC file gtk_widget_set_name( comboBoxEntry, combobox_name ); @@ -361,7 +378,8 @@ GtkWidget* create_tool_item( GtkAction* action ) ink_comboboxentry_action->combobox = GTK_COMBO_BOX (comboBoxEntry); - gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), ink_comboboxentry_action->active ); + //gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), ink_comboboxentry_action->active ); + gtk_combo_box_set_active( GTK_COMBO_BOX( comboBoxEntry ), 0 ); g_signal_connect( G_OBJECT(comboBoxEntry), "changed", G_CALLBACK(combo_box_changed_cb), action ); @@ -375,6 +393,13 @@ GtkWidget* create_tool_item( GtkAction* action ) NULL, NULL ); } + // Optionally add separator function... + if( ink_comboboxentry_action->separator_func != NULL ) { + gtk_combo_box_set_row_separator_func( ink_comboboxentry_action->combobox, + GtkTreeViewRowSeparatorFunc (ink_comboboxentry_action->separator_func), + NULL, NULL ); + } + // Optionally widen the combobox width... which widens the drop-down list in list mode. if( ink_comboboxentry_action->extra_width > 0 ) { GtkRequisition req; @@ -415,7 +440,7 @@ GtkWidget* create_tool_item( GtkAction* action ) // Add signal for GtkEntry to check if finished typing. g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(entry_activate_cb), action ); - + g_signal_connect( G_OBJECT(child), "key-press-event", G_CALLBACK(keypress_cb), action ); } gtk_activatable_set_related_action( GTK_ACTIVATABLE (item), GTK_ACTION( action ) ); @@ -423,7 +448,7 @@ GtkWidget* create_tool_item( GtkAction* action ) } else { - item = ink_comboboxentry_action_parent_class->create_tool_item( action ); + item = GTK_ACTION_CLASS(ink_comboboxentry_action_parent_class)->create_tool_item( action ); } @@ -435,7 +460,7 @@ GtkWidget* create_menu_item( GtkAction* action ) { GtkWidget* item = 0; - item = ink_comboboxentry_action_parent_class->create_menu_item( action ); + item = GTK_ACTION_CLASS(ink_comboboxentry_action_parent_class)->create_menu_item( action ); g_warning( "ink_comboboxentry_action: create_menu_item not implemented" ); // One can easily modify ege-select-one-action routine to implement this. return item; @@ -459,58 +484,126 @@ gchar* ink_comboboxentry_action_get_active_text( Ink_ComboBoxEntry_Action* actio return text; } -gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* ink_comboboxentry_action, const gchar* text ) { +/* + * For the font-family list we need to handle two cases: + * Text is in list store: + * In this case we use row number as the font-family list can have duplicate + * entries, one in the document font part and one in the system font part. In + * order that scrolling through the list works properly we must distinguish + * between the two. + * Text is not in the list store (i.e. default font-family is not on system): + * In this case we have a row number of -1, and the text must be set by hand. + */ +gboolean ink_comboboxentry_action_set_active_text( Ink_ComboBoxEntry_Action* action, const gchar* text, int row ) { - g_free( ink_comboboxentry_action->text ); - ink_comboboxentry_action->text = g_strdup( text ); + if( strcmp( action->text, text ) != 0 ) { + g_free( action->text ); + action->text = g_strdup( text ); + } // Get active row or -1 if none - ink_comboboxentry_action->active = get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text ); + if( row < 0 ) { + row = get_active_row_from_text( action, action->text ); + } + action->active = row; // Set active row, check that combobox has been created. - if( ink_comboboxentry_action->combobox ) { - gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox ), ink_comboboxentry_action->active ); + if( action->combobox ) { + gtk_combo_box_set_active( GTK_COMBO_BOX( action->combobox ), action->active ); } // Fiddle with entry - if( ink_comboboxentry_action->entry ) { + if( action->entry ) { // Explicitly set text in GtkEntry box (won't be set if text not in list). - gtk_entry_set_text( ink_comboboxentry_action->entry, text ); - - // Show or hide warning - if( ink_comboboxentry_action->active == -1 && - ink_comboboxentry_action->warning != NULL && - check_comma_separated_text( ink_comboboxentry_action ) ) { - { - GtkStockItem item; - gboolean isStock = gtk_stock_lookup( GTK_STOCK_DIALOG_WARNING, &item ); - if (isStock) { - gtk_entry_set_icon_from_stock( ink_comboboxentry_action->entry, + gtk_entry_set_text( action->entry, text ); + + // Show or hide warning -- this might be better moved to text-toolbox.cpp + if( action->info_cb_id != 0 && + !action->info_cb_blocked ) { + g_signal_handler_block (G_OBJECT(action->entry), + action->info_cb_id ); + action->info_cb_blocked = true; + } + if( action->warning_cb_id != 0 && + !action->warning_cb_blocked ) { + g_signal_handler_block (G_OBJECT(action->entry), + action->warning_cb_id ); + action->warning_cb_blocked = true; + } + + bool set = false; + if( action->warning != NULL ) { + Glib::ustring missing = check_comma_separated_text( action ); + if( !missing.empty() ) { + gtk_entry_set_icon_from_icon_name( action->entry, GTK_ENTRY_ICON_SECONDARY, - GTK_STOCK_DIALOG_WARNING ); - } else { - gtk_entry_set_icon_from_icon_name( ink_comboboxentry_action->entry, - GTK_ENTRY_ICON_SECONDARY, - GTK_STOCK_DIALOG_WARNING ); + INKSCAPE_ICON("dialog-warning") ); + // Can't add tooltip until icon set + Glib::ustring warning = action->warning; + warning += ": "; + warning += missing; + gtk_entry_set_icon_tooltip_text( action->entry, + GTK_ENTRY_ICON_SECONDARY, + warning.c_str() ); + + if( action->warning_cb ) { + + // Add callback if we haven't already + if( action->warning_cb_id == 0 ) { + action->warning_cb_id = + g_signal_connect( G_OBJECT(action->entry), + "icon-press", + G_CALLBACK(action->warning_cb), + action); } + // Unblock signal + if( action->warning_cb_blocked ) { + g_signal_handler_unblock (G_OBJECT(action->entry), + action->warning_cb_id ); + action->warning_cb_blocked = false; + } + } + set = true; + } + } + + if( !set && action->info != NULL ) { + gtk_entry_set_icon_from_icon_name( GTK_ENTRY(action->entry), + GTK_ENTRY_ICON_SECONDARY, + INKSCAPE_ICON("edit-select-all") ); + gtk_entry_set_icon_tooltip_text( action->entry, + GTK_ENTRY_ICON_SECONDARY, + action->info ); + + if( action->info_cb ) { + // Add callback if we haven't already + if( action->info_cb_id == 0 ) { + action->info_cb_id = + g_signal_connect( G_OBJECT(action->entry), + "icon-press", + G_CALLBACK(action->info_cb), + action); + } + // Unblock signal + if( action->info_cb_blocked ) { + g_signal_handler_unblock (G_OBJECT(action->entry), + action->info_cb_id ); + action->info_cb_blocked = false; + } } - // Can't add tooltip until icon set - gtk_entry_set_icon_tooltip_text( ink_comboboxentry_action->entry, - GTK_ENTRY_ICON_SECONDARY, - ink_comboboxentry_action->warning ); - } else { - gtk_entry_set_icon_from_icon_name( GTK_ENTRY(ink_comboboxentry_action->entry), - GTK_ENTRY_ICON_SECONDARY, - NULL ); - gtk_entry_set_icon_from_stock( GTK_ENTRY(ink_comboboxentry_action->entry), - GTK_ENTRY_ICON_SECONDARY, - NULL ); + set = true; + } + + if( !set ) { + gtk_entry_set_icon_from_icon_name( GTK_ENTRY(action->entry), + GTK_ENTRY_ICON_SECONDARY, + NULL ); } } // Return if active text in list - gboolean found = ( ink_comboboxentry_action->active != -1 ); + gboolean found = ( action->active != -1 ); return found; } @@ -561,6 +654,7 @@ void ink_comboboxentry_action_popup_enable( Ink_ComboBoxEntry_Action* action ) { g_signal_connect (G_OBJECT (action->entry_completion), "match-selected", G_CALLBACK (match_selected_cb), action ); + } } @@ -569,10 +663,39 @@ void ink_comboboxentry_action_popup_disable( Ink_ComboBoxEntry_Action* action ) action->popup = false; if( action->entry_completion ) { - gtk_object_destroy( GTK_OBJECT( action->entry_completion ) ); + gtk_widget_destroy(GTK_WIDGET(action->entry_completion)); action->entry_completion = 0; } } +void ink_comboboxentry_action_set_tooltip( Ink_ComboBoxEntry_Action* action, const gchar* tooltip ) { + + // Widget may not have been created.... + if( action->entry ) { + gtk_widget_set_tooltip_text ( GTK_WIDGET(action->entry), tooltip); + } + if( action->combobox ) { + gtk_widget_set_tooltip_text ( GTK_WIDGET(action->combobox), tooltip); + } + +} + +void ink_comboboxentry_action_set_info( Ink_ComboBoxEntry_Action* action, const gchar* info ) { + + g_free( action->info ); + action->info = g_strdup( info ); + + // Widget may not have been created.... + if( action->entry ) { + gtk_entry_set_icon_tooltip_text( GTK_ENTRY(action->entry), + GTK_ENTRY_ICON_SECONDARY, + action->info ); + } +} + +void ink_comboboxentry_action_set_info_cb( Ink_ComboBoxEntry_Action* action, gpointer info_cb ) { + + action->info_cb = info_cb; +} void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, const gchar* warning ) { @@ -587,6 +710,11 @@ void ink_comboboxentry_action_set_warning( Ink_ComboBoxEntry_Action* action, } } +void ink_comboboxentry_action_set_warning_cb( Ink_ComboBoxEntry_Action* action, gpointer warning_cb ) { + + action->warning_cb = warning_cb; +} + void ink_comboboxentry_action_set_altx_name( Ink_ComboBoxEntry_Action* action, const gchar* altx_name ) { g_free( action->altx_name ); @@ -600,8 +728,11 @@ void ink_comboboxentry_action_set_altx_name( Ink_ComboBoxEntry_Action* actio // Internal --------------------------------------------------- -// Return row of active text or -1 if not found. -gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text ) { +// Return row of active text or -1 if not found. If exclude is true, +// use 3d colunm if available to exclude row from checking (useful to +// skip rows added for font-families included in doc and not on +// system) +gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* target_text, gboolean exclude ) { // Check if text in list gint row = 0; @@ -610,15 +741,24 @@ gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* ta gboolean valid = gtk_tree_model_get_iter_first( action->model, &iter ); while ( valid ) { - // Get text from list entry - gchar* text = 0; - gtk_tree_model_get( action->model, &iter, 0, &text, -1 ); // Column 0 + // See if we should exclude a row + gboolean check = true; // If true, font-family is on system. + if( exclude && gtk_tree_model_get_n_columns( action->model ) > 2 ) { + gtk_tree_model_get( action->model, &iter, 2, &check, -1 ); + } + + if( check ) { + // Get text from list entry + gchar* text = 0; + gtk_tree_model_get( action->model, &iter, 0, &text, -1 ); // Column 0 - // Check for match - if( strcmp( target_text, text ) == 0 ){ - found = true; - break; + // Check for match + if( strcmp( target_text, text ) == 0 ){ + found = true; + break; + } } + ++row; valid = gtk_tree_model_iter_next( action->model, &iter ); } @@ -629,18 +769,21 @@ gint get_active_row_from_text( Ink_ComboBoxEntry_Action* action, const gchar* ta } -// Checks if all comma separated text fragments are in the list. +// Checks if all comma separated text fragments are in the list and +// returns a ustring with a list of missing fragments. // This is useful for checking if all fonts in a font-family fallback // list are available on the system. -// The return value is set to the number of missing text fragments. +// // This routine could also create a Pango Markup string to show which -// fragments are invalid. -// It is envisioned that one can construct a Pango Markup String here -// so that individual text fragments can be flagged as not being in the -// list. -static gint check_comma_separated_text( Ink_ComboBoxEntry_Action* action ) { +// fragments are invalid in the entry box itself. See: +// http://developer.gnome.org/pango/stable/PangoMarkupFormat.html +// However... it appears that while one can retrieve the PangoLayout +// for a GtkEntry box, it is only a copy and changing it has no effect. +// PangoLayout * pl = gtk_entry_get_layout( entry ); +// pango_layout_set_markup( pl, "NEW STRING", -1 ); // DOESN'T WORK +static Glib::ustring check_comma_separated_text( Ink_ComboBoxEntry_Action* action ) { - gint ret_val = 0; + Glib::ustring missing; // Parse fallback_list using a comma as deliminator gchar** tokens = g_strsplit( action->text, ",", 0 ); @@ -651,22 +794,19 @@ static gint check_comma_separated_text( Ink_ComboBoxEntry_Action* action ) { // Remove any surrounding white space. g_strstrip( tokens[i] ); - if( get_active_row_from_text( action, tokens[i] ) == -1 ) { - ret_val += 1; + if( get_active_row_from_text( action, tokens[i], true ) == -1 ) { + missing += tokens[i]; + missing += ", "; } ++i; } g_strfreev( tokens ); - // Pango Markup notes: - // GString* Pango_Markup = g_string_new(""); - // if not present: - // g_string_sprintfa( Pango_Markup, "<span strikethrough=\"true\" strikethrough_color=\"#880000\">%s</span>", tokens[i] ); - // PangoLayout * pl = gtk_entry_get_layout( entry ); - // pango_layout_set_markup( pl, Pango_Markup->str, -1 ); - // g_string_free( Pango_Markup, TRUE ); - - return ret_val; + // Remove extra comma and space from end. + if( missing.size() >= 2 ) { + missing.resize( missing.size()-2 ); + } + return missing; } // Callbacks --------------------------------------------------- @@ -679,22 +819,27 @@ static void combo_box_changed_cb( GtkComboBox* widget, gpointer data ) { // We only react here if an item is selected. // Get action - Ink_ComboBoxEntry_Action *act = INK_COMBOBOXENTRY_ACTION( data ); + Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION( data ); // Check if item selected: gint newActive = gtk_combo_box_get_active(widget); - if( newActive >= 0 ) { + if( newActive >= 0 && newActive != action->active ) { + + action->active = newActive; - if( newActive != act->active ) { - act->active = newActive; - g_free( act->text ); - GtkWidget *entry = gtk_bin_get_child (GTK_BIN (widget)); - act->text = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry))); + GtkTreeIter iter; + if( gtk_combo_box_get_active_iter( GTK_COMBO_BOX( action->combobox ), &iter ) ) { - // Now let the world know - g_signal_emit( G_OBJECT(act), signals[CHANGED], 0 ); + gchar* text = 0; + gtk_tree_model_get( action->model, &iter, 0, &text, -1 ); + gtk_entry_set_text( action->entry, text ); + g_free( action->text ); + action->text = text; } + + // Now let the world know + g_signal_emit( G_OBJECT(action), signals[CHANGED], 0 ); } } @@ -703,29 +848,29 @@ static void entry_activate_cb( GtkEntry* widget, gpointer data ) { // Get text from entry box.. check if it matches a menu entry. // Get action - Ink_ComboBoxEntry_Action *ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( data ); + Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION( data ); // Get text - g_free( ink_comboboxentry_action->text ); - ink_comboboxentry_action->text = g_strdup( gtk_entry_get_text( widget ) ); + g_free( action->text ); + action->text = g_strdup( gtk_entry_get_text( widget ) ); // Get row - ink_comboboxentry_action->active = - get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text ); + action->active = + get_active_row_from_text( action, action->text ); // Set active row - gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active ); + gtk_combo_box_set_active( GTK_COMBO_BOX( action->combobox), action->active ); // Now let the world know - g_signal_emit( G_OBJECT(ink_comboboxentry_action), signals[CHANGED], 0 ); + g_signal_emit( G_OBJECT(action), signals[CHANGED], 0 ); } static gboolean match_selected_cb( GtkEntryCompletion* /*widget*/, GtkTreeModel* model, GtkTreeIter* iter, gpointer data ) { // Get action - Ink_ComboBoxEntry_Action *ink_comboboxentry_action = INK_COMBOBOXENTRY_ACTION( data ); - GtkEntry *entry = ink_comboboxentry_action->entry; + Ink_ComboBoxEntry_Action *action = INK_COMBOBOXENTRY_ACTION( data ); + GtkEntry *entry = action->entry; if( entry) { gchar *family = 0; @@ -735,21 +880,61 @@ static gboolean match_selected_cb( GtkEntryCompletion* /*widget*/, GtkTreeModel* gtk_entry_set_text (GTK_ENTRY (entry), family ); // Set text in GtkAction - g_free( ink_comboboxentry_action->text ); - ink_comboboxentry_action->text = family; + g_free( action->text ); + action->text = family; // Get row - ink_comboboxentry_action->active = - get_active_row_from_text( ink_comboboxentry_action, ink_comboboxentry_action->text ); + action->active = + get_active_row_from_text( action, action->text ); // Set active row - gtk_combo_box_set_active( GTK_COMBO_BOX( ink_comboboxentry_action->combobox), ink_comboboxentry_action->active ); + gtk_combo_box_set_active( GTK_COMBO_BOX( action->combobox), action->active ); // Now let the world know - g_signal_emit( G_OBJECT(ink_comboboxentry_action), signals[CHANGED], 0 ); + g_signal_emit( G_OBJECT(action), signals[CHANGED], 0 ); return true; } return false; } +static void ink_comboboxentry_action_defocus( Ink_ComboBoxEntry_Action* action ) +{ + if ( action->focusWidget ) { + gtk_widget_grab_focus( action->focusWidget ); + } +} + +gboolean keypress_cb( GtkWidget * /*widget*/, GdkEventKey *event, gpointer data ) +{ + gboolean wasConsumed = FALSE; /* default to report event not consumed */ + guint key = 0; + Ink_ComboBoxEntry_Action* action = INK_COMBOBOXENTRY_ACTION( data ); + gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display( gdk_display_get_default() ), + event->hardware_keycode, (GdkModifierType)event->state, + 0, &key, 0, 0, 0 ); + + switch ( key ) { + + // TODO Add bindings for Tab/LeftTab + case GDK_KEY_Escape: + { + //gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), action->private_data->lastVal ); + ink_comboboxentry_action_defocus( action ); + wasConsumed = TRUE; + } + break; + + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + { + ink_comboboxentry_action_defocus( action ); + //wasConsumed = TRUE; + } + break; + + + } + + return wasConsumed; +} |
