Code

Indent support for XSLT extensions output.
[inkscape.git] / src / ege-select-one-action.cpp
index bfbd3736ab3f4388df5de385eb4560e95b769d6e..664ffd13d2f0da4c627f7ada5a61e3ab44219781 100644 (file)
@@ -67,6 +67,7 @@ static void ege_select_one_action_set_property( GObject* obj, guint propId, cons
 static gint find_text_index(EgeSelectOneAction *act, gchar const* text);
 static void commit_pending_change(EgeSelectOneAction *act);
 static void resync_active( EgeSelectOneAction* act, gint active, gboolean override );
+static void resync_sensitive( EgeSelectOneAction* act );
 static void combo_entry_changed_cb( GtkEntry* widget, gpointer user_data );
 static gboolean combo_entry_focus_lost_cb( GtkWidget *widget, GdkEventFocus *event, gpointer data );
 static void combo_changed_cb( GtkComboBox* widget, gpointer user_data );
@@ -78,6 +79,8 @@ static GtkWidget* create_tool_item( GtkAction* action );
 static void connect_proxy( GtkAction *action, GtkWidget *proxy );
 static void disconnect_proxy( GtkAction *action, GtkWidget *proxy );
 
+static int scan_max_width( GtkTreeModel *model, gint labelColumn );
+
 static GtkActionClass* gParentClass = 0;
 static guint signals[LAST_SIGNAL] = {0};
 static GQuark gDataName = 0;
@@ -86,9 +89,9 @@ 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
+    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 */
 };
 
 enum {
@@ -103,6 +106,7 @@ struct _EgeSelectOneActionPrivate
     gint labelColumn;
     gint iconColumn;
     gint tooltipColumn;
+    gint sensitiveColumn;
     gint appearanceMode;
     gint selectionMode;
     gint iconSize;
@@ -123,6 +127,7 @@ enum {
     PROP_LABEL_COLUMN,
     PROP_ICON_COLUMN,
     PROP_TOOLTIP_COLUMN,
+    PROP_SENSITIVE_COLUMN,
     PROP_ICON_PROP,
     PROP_ICON_SIZE,
     PROP_APPEARANCE,
@@ -184,7 +189,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
                                          g_param_spec_int( "active",
                                                            "Active Selection",
                                                            "The index of the selected item",
-                                                           -1, 20, 0,
+                                                           -1, G_MAXINT, 0,
                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
 
         g_object_class_install_property( objClass,
@@ -192,7 +197,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
                                          g_param_spec_int( "label-column",
                                                            "Display Column",
                                                            "The column of the model that holds display strings",
-                                                           0, 20, 0,
+                                                           0, G_MAXINT, 0,
                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
 
         g_object_class_install_property( objClass,
@@ -200,7 +205,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
                                          g_param_spec_int( "icon-column",
                                                            "Icon Column",
                                                            "The column of the model that holds display icon name",
-                                                           -1, 20, -1,
+                                                           -1, G_MAXINT, -1,
                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
 
         g_object_class_install_property( objClass,
@@ -208,7 +213,15 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
                                          g_param_spec_int( "tooltip-column",
                                                            "Tooltip Column",
                                                           "The column of the model that holds tooltip strings",
-                                                           -1, 20, -1,
+                                                           -1, G_MAXINT, -1,
+                                                           (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
+
+        g_object_class_install_property( objClass,
+                                         PROP_SENSITIVE_COLUMN,
+                                         g_param_spec_int( "sensitive-column",
+                                                           "Sensitive Column",
+                                                          "The column of the model that holds sensitive state",
+                                                           -1, G_MAXINT, -1,
                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
 
         g_object_class_install_property( objClass,
@@ -224,7 +237,7 @@ void ege_select_one_action_class_init( EgeSelectOneActionClass* klass )
                                          g_param_spec_int( "icon-size",
                                                            "Icon Size",
                                                           "Target icon size",
-                                                           -1, 20, -1,
+                                                           -1, G_MAXINT, -1,
                                                            (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) );
 
         g_object_class_install_property( objClass,
@@ -263,6 +276,7 @@ void ege_select_one_action_init( EgeSelectOneAction* action )
     action->private_data->labelColumn = 0;
     action->private_data->iconColumn = -1;
     action->private_data->tooltipColumn = -1;
+    action->private_data->sensitiveColumn = -1;
     action->private_data->appearanceMode = APPEARANCE_NONE;
     action->private_data->selectionMode = SELECTION_CLOSED;
     action->private_data->radioActionType = 0;
@@ -345,6 +359,15 @@ void ege_select_one_action_set_active( EgeSelectOneAction* action, gint val )
     g_object_set( G_OBJECT(action), "active", val, NULL );
 }
 
+void ege_select_one_action_update_sensitive( EgeSelectOneAction* action )
+{
+    if( action->private_data->sensitiveColumn < 0 ) {
+        g_warning( "ege_select_one_action: Attempt to update sensitivity of item without sensitive column\n" );
+        return;
+    }
+    resync_sensitive( action );
+}
+
 gint ege_select_one_action_get_label_column( EgeSelectOneAction* action )
 {
     g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
@@ -389,6 +412,17 @@ void ege_select_one_action_set_tooltip_column( EgeSelectOneAction* action, gint
     g_object_set( G_OBJECT(action), "tooltip-column", col, NULL );
 }
 
+gint ege_select_one_action_get_sensitive_column( EgeSelectOneAction* action )
+{
+    g_return_val_if_fail( IS_EGE_SELECT_ONE_ACTION(action), 0 );
+    return action->private_data->sensitiveColumn;
+}
+
+void ege_select_one_action_set_sensitive_column( EgeSelectOneAction* action, gint col )
+{
+    g_object_set( G_OBJECT(action), "sensitive-column", col, NULL );
+}
+
 void ege_select_one_action_set_appearance( EgeSelectOneAction* action, gchar const* val )
 {
     g_object_set( G_OBJECT(action), "appearance", val, NULL );
@@ -423,6 +457,10 @@ void ege_select_one_action_get_property( GObject* obj, guint propId, GValue* val
             g_value_set_int( value, action->private_data->tooltipColumn );
             break;
 
+        case PROP_SENSITIVE_COLUMN:
+            g_value_set_int( value, action->private_data->sensitiveColumn );
+            break;
+
         case PROP_ICON_PROP:
             g_value_set_string( value, action->private_data->iconProperty );
             break;
@@ -478,6 +516,12 @@ void ege_select_one_action_set_property( GObject* obj, guint propId, const GValu
         }
         break;
 
+        case PROP_SENSITIVE_COLUMN:
+        {
+            action->private_data->sensitiveColumn = g_value_get_int( value );
+        }
+        break;
+
         case PROP_ICON_PROP:
         {
             gchar* tmp = action->private_data->iconProperty;
@@ -621,7 +665,10 @@ GtkWidget* create_tool_item( GtkAction* action )
 
             gchar*  sss = 0;
             g_object_get( G_OBJECT(action), "short_label", &sss, NULL );
-            if (sss) {
+            // If short_label not defined, g_object_get will return label.
+            // This hack allows a label to be used with a drop-down menu when
+            // no label is used with a set of icons that are self-explanatory.
+            if (sss && strcmp( sss, "NotUsed" ) != 0 ) {
                 GtkWidget* lbl;
                 lbl = gtk_label_new(sss);
                 gtk_box_pack_start( GTK_BOX(holder), lbl, FALSE, FALSE, 4 );
@@ -632,6 +679,7 @@ GtkWidget* create_tool_item( GtkAction* action )
                 gchar* str = 0;
                 gchar* tip = 0;
                 gchar* iconId = 0;
+                gboolean sens = true;
                 /*
                 gint size = 0;
                 */
@@ -648,6 +696,11 @@ GtkWidget* create_tool_item( GtkAction* action )
                                         act->private_data->tooltipColumn, &tip,
                                         -1 );
                 }
+                if ( act->private_data->sensitiveColumn >= 0 ) {
+                    gtk_tree_model_get( act->private_data->model, &iter,
+                                        act->private_data->sensitiveColumn, &sens,
+                                        -1 );
+                }
 
                 if ( act->private_data->radioActionType ) {
                     void* obj = g_object_new( act->private_data->radioActionType,
@@ -676,6 +729,10 @@ GtkWidget* create_tool_item( GtkAction* action )
                     ract = gtk_radio_action_new( "Name 1", str, tip, iconId, index );
                 }
 
+                if ( act->private_data->sensitiveColumn >= 0 ) {
+                    gtk_action_set_sensitive( GTK_ACTION(ract), sens );
+                }
+
                 gtk_radio_action_set_group( ract, group );
                 group = gtk_radio_action_get_group( ract );
 
@@ -712,8 +769,20 @@ GtkWidget* create_tool_item( GtkAction* action )
             if ((act->private_data->selectionMode == SELECTION_OPEN)) {
                 GtkWidget *child = gtk_bin_get_child( GTK_BIN(normal) );
                 if (GTK_IS_ENTRY(child)) {
+                    int maxUsed = scan_max_width( act->private_data->model, act->private_data->labelColumn );
+                    GtkEntryCompletion *complete = 0;
                     entry = GTK_ENTRY(child);
-                    gtk_entry_set_width_chars(entry, 4);
+                    gtk_entry_set_width_chars(entry, maxUsed); /* replace with property */
+
+                    complete = gtk_entry_completion_new();
+                    gtk_entry_completion_set_model( complete, act->private_data->model );
+                    gtk_entry_completion_set_text_column( complete, act->private_data->labelColumn );
+                    gtk_entry_completion_set_inline_completion( complete, FALSE );
+                    gtk_entry_completion_set_inline_selection( complete, FALSE );
+                    gtk_entry_completion_set_popup_completion( complete, TRUE );
+                    gtk_entry_completion_set_popup_set_width( complete, FALSE );
+                    gtk_entry_set_completion( entry, complete );
+
                     g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(combo_entry_changed_cb), act );
                     g_signal_connect( G_OBJECT(child), "focus-out-event", G_CALLBACK(combo_entry_focus_lost_cb), act );
                 }
@@ -722,7 +791,7 @@ GtkWidget* create_tool_item( GtkAction* action )
                     renderer = gtk_cell_renderer_pixbuf_new();
                     gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(normal), renderer, TRUE );
 
-                    // "icon-name"
+                    /* "icon-name" */
                     gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT(normal), renderer, "stock-id", act->private_data->iconColumn );
                 }
 
@@ -841,6 +910,73 @@ void resync_active( EgeSelectOneAction* act, gint active, gboolean override )
     }
 }
 
+void resync_sensitive( EgeSelectOneAction* act )
+{
+    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 (!combodata && GTK_IS_ALIGNMENT(children->data)) {
+                    GList *other = gtk_container_get_children( GTK_CONTAINER(children->data) );
+                    combodata = g_object_get_data( G_OBJECT(other->data), "ege-combo-box" );
+                }
+                if ( GTK_IS_COMBO_BOX(combodata) ) {
+                    /* Not implemented */
+                } 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;
+                        // List is backwards in group as compared to GtkTreeModel, we better do matching.
+                        while ( group ) {
+#if GTK_CHECK_VERSION(2,16,0)
+                            GtkRadioAction* ract = GTK_RADIO_ACTION(group->data);
+                            const gchar* label = gtk_action_get_label( GTK_ACTION( ract ) );
+
+                            // Search for matching GtkTreeModel entry
+                            GtkTreeIter iter;
+                            gboolean valid;
+                            valid = gtk_tree_model_get_iter_first( act->private_data->model, &iter );
+                            gboolean sens = true;
+
+                            while( valid ) {
+
+                                gchar* str = 0;
+                                gtk_tree_model_get( act->private_data->model, &iter,
+                                                    act->private_data->labelColumn, &str,
+                                                    -1 );
+
+                                if( strcmp( label, str ) == 0 ) {
+                                    gtk_tree_model_get( act->private_data->model, &iter,
+                                                        act->private_data->sensitiveColumn, &sens,
+                                                        -1 );
+                                    break;
+                                }
+                                g_free( str );
+
+                                valid = gtk_tree_model_iter_next( act->private_data->model, &iter );
+                            }
+
+                            gtk_action_set_sensitive( GTK_ACTION(ract), sens );
+#endif
+
+                            group = g_slist_next(group);
+                        }
+                    }
+                }
+            }
+        } else if ( GTK_IS_MENU_ITEM(proxies->data) ) {
+            /* Not implemented */
+        }
+
+        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);
@@ -969,3 +1105,25 @@ void proxy_action_chagned_cb( GtkRadioAction* action, GtkRadioAction* current, g
         }
     }
 }
+
+int scan_max_width( GtkTreeModel *model, gint labelColumn )
+{
+    int maxUsed = 0;
+    GtkTreeIter iter;
+    gboolean valid = gtk_tree_model_get_iter_first( model, &iter );
+    while ( valid ) {
+        gchar* str = 0;
+        int count = 0;
+        gtk_tree_model_get( model, &iter,
+                            labelColumn, &str,
+                            -1 );
+        count = strlen(str);
+        if (count > maxUsed) {
+            maxUsed = count;
+        }
+        g_free( str );
+
+        valid = gtk_tree_model_iter_next( model, &iter );
+    }
+    return maxUsed;
+}