[gimp] libgimpwidgets: add "layout" property to GimpIntComboBox



commit 47ac6111de4fb77645be257fc4c6820d3ad6cb9c
Author: Ell <ell_se yahoo com>
Date:   Wed Nov 29 16:39:16 2017 -0500

    libgimpwidgets: add "layout" property to GimpIntComboBox
    
    The "layout" proerty controls the combo-box layout (but not its
    menu layout), and can be one of:
    
      - ICON_ONLY:  Only show icons.
    
      - ABBREVIATED:  Show icons and abbreviated labels (or full
        labels, when there is no abbreviation).
    
      - FULL:  Show icons and full labels.  Default.
    
    Avoid reconstructing the combo's cell-layout when the menu is
    shown/hidden, by maintaining the combo's cell-layout and the menu's
    cell-layout separately (probably a terrible hack, but one we already
    use :P).

 libgimpwidgets/gimpintcombobox.c  |  267 ++++++++++++++++++++++++++++---------
 libgimpwidgets/gimpintcombobox.h  |    5 +
 libgimpwidgets/gimpwidgetsenums.c |   32 +++++
 libgimpwidgets/gimpwidgetsenums.h |   20 +++
 4 files changed, 260 insertions(+), 64 deletions(-)
---
diff --git a/libgimpwidgets/gimpintcombobox.c b/libgimpwidgets/gimpintcombobox.c
index 70b5eea..5828748 100644
--- a/libgimpwidgets/gimpintcombobox.c
+++ b/libgimpwidgets/gimpintcombobox.c
@@ -45,7 +45,8 @@ enum
 {
   PROP_0,
   PROP_ELLIPSIZE,
-  PROP_LABEL
+  PROP_LABEL,
+  PROP_LAYOUT
 };
 
 
@@ -54,9 +55,13 @@ typedef struct
   GtkCellRenderer        *pixbuf_renderer;
   GtkCellRenderer        *text_renderer;
 
+  GtkCellRenderer        *menu_pixbuf_renderer;
+  GtkCellRenderer        *menu_text_renderer;
+
   PangoEllipsizeMode      ellipsize;
   gchar                  *label;
   GtkCellRenderer        *label_renderer;
+  GimpIntComboBoxLayout   layout;
 
   GimpIntSensitivityFunc  sensitivity_func;
   gpointer                sensitivity_data;
@@ -130,6 +135,22 @@ gimp_int_combo_box_class_init (GimpIntComboBoxClass *klass)
                                                         NULL,
                                                         GIMP_PARAM_READWRITE));
 
+  /**
+   * GimpIntComboBox:layout:
+   *
+   * Specifies the combo box layout.
+   *
+   * Since: 2.10
+   */
+  g_object_class_install_property (object_class, PROP_LAYOUT,
+                                   g_param_spec_enum ("layout",
+                                                      "Layout",
+                                                      "Combo box layout",
+                                                      GIMP_TYPE_INT_COMBO_BOX_LAYOUT,
+                                                      GIMP_INT_COMBO_BOX_LAYOUT_FULL,
+                                                      GIMP_PARAM_READWRITE |
+                                                      G_PARAM_CONSTRUCT));
+
   g_type_class_add_private (object_class, sizeof (GimpIntComboBoxPrivate));
 }
 
@@ -179,13 +200,20 @@ gimp_int_combo_box_set_property (GObject      *object,
     {
     case PROP_ELLIPSIZE:
       priv->ellipsize = g_value_get_enum (value);
-      g_object_set_property (G_OBJECT (priv->text_renderer),
-                             pspec->name, value);
+      if (priv->text_renderer)
+        {
+          g_object_set_property (G_OBJECT (priv->text_renderer),
+                                 pspec->name, value);
+        }
       break;
     case PROP_LABEL:
       gimp_int_combo_box_set_label (GIMP_INT_COMBO_BOX (object),
                                     g_value_get_string (value));
       break;
+    case PROP_LAYOUT:
+      gimp_int_combo_box_set_layout (GIMP_INT_COMBO_BOX (object),
+                                     g_value_get_enum (value));
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -209,6 +237,9 @@ gimp_int_combo_box_get_property (GObject    *object,
     case PROP_LABEL:
       g_value_set_string (value, priv->label);
       break;
+    case PROP_LAYOUT:
+      g_value_set_enum (value, priv->layout);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -601,24 +632,9 @@ gimp_int_combo_box_set_label (GimpIntComboBox *combo_box,
   if (label == priv->label)
     return;
 
-  if (priv->label)
-    {
-      g_free (priv->label);
-      priv->label = NULL;
-
-      g_signal_handlers_disconnect_by_func (combo_box,
-                                            gimp_int_combo_box_create_cells,
-                                            NULL);
-    }
+  g_free (priv->label);
 
-  if (label)
-    {
-      priv->label = g_strdup (label);
-
-      g_signal_connect (combo_box, "notify::popup-shown",
-                        G_CALLBACK (gimp_int_combo_box_create_cells),
-                        NULL);
-    }
+  priv->label = g_strdup (label);
 
   gimp_int_combo_box_create_cells (combo_box);
 
@@ -645,6 +661,53 @@ gimp_int_combo_box_get_label (GimpIntComboBox *combo_box)
 }
 
 /**
+ * gimp_int_combo_box_set_layout:
+ * @combo_box: a #GimpIntComboBox
+ * @layout:    the combo box layout
+ *
+ * Sets the layout of @combo_box to @layout.
+ *
+ * Since: 2.10
+ **/
+void
+gimp_int_combo_box_set_layout (GimpIntComboBox       *combo_box,
+                               GimpIntComboBoxLayout  layout)
+{
+  GimpIntComboBoxPrivate *priv;
+
+  g_return_if_fail (GIMP_IS_INT_COMBO_BOX (combo_box));
+
+  priv = GIMP_INT_COMBO_BOX_GET_PRIVATE (combo_box);
+
+  if (layout == priv->layout)
+    return;
+
+  priv->layout = layout;
+
+  gimp_int_combo_box_create_cells (combo_box);
+
+  g_object_notify (G_OBJECT (combo_box), "layout");
+}
+
+/**
+ * gimp_int_combo_box_get_layout:
+ * @combo_box: a #GimpIntComboBox
+ *
+ * Returns the layout of @combo_box
+ *
+ * Return value: the @combo_box's layout.
+ *
+ * Since: 2.10
+ **/
+GimpIntComboBoxLayout
+gimp_int_combo_box_get_layout (GimpIntComboBox *combo_box)
+{
+  g_return_val_if_fail (GIMP_IS_INT_COMBO_BOX (combo_box), GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED);
+
+  return GIMP_INT_COMBO_BOX_GET_PRIVATE (combo_box)->layout;
+}
+
+/**
  * gimp_int_combo_box_set_sensitivity:
  * @combo_box: a #GimpIntComboBox
  * @func: a function that returns a boolean value, or %NULL to unset
@@ -684,17 +747,7 @@ gimp_int_combo_box_set_sensitivity (GimpIntComboBox        *combo_box,
   priv->sensitivity_data    = data;
   priv->sensitivity_destroy = destroy;
 
-  gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo_box),
-                                      priv->pixbuf_renderer,
-                                      func ?
-                                      gimp_int_combo_box_data_func : NULL,
-                                      priv, NULL);
-
-  gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo_box),
-                                      priv->text_renderer,
-                                      func ?
-                                      gimp_int_combo_box_data_func : NULL,
-                                      priv, NULL);
+  gimp_int_combo_box_create_cells (combo_box);
 }
 
 
@@ -726,72 +779,139 @@ static void
 gimp_int_combo_box_create_cells (GimpIntComboBox *combo_box)
 {
   GimpIntComboBoxPrivate *priv = GIMP_INT_COMBO_BOX_GET_PRIVATE (combo_box);
-  gboolean                shown;
+  GtkCellLayout          *layout;
 
-  g_object_get (combo_box, "popup-shown", &shown, NULL);
+  /*  menu layout  */
 
-  gtk_cell_layout_clear (GTK_CELL_LAYOUT (combo_box));
+  layout = GTK_CELL_LAYOUT (combo_box);
 
-  priv->pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();
-  g_object_set (priv->pixbuf_renderer,
+  gtk_cell_layout_clear (layout);
+
+  priv->menu_pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();
+  g_object_set (priv->menu_pixbuf_renderer,
                 "xpad", 2,
                 NULL);
 
-  priv->text_renderer = gtk_cell_renderer_text_new ();
+  priv->menu_text_renderer = gtk_cell_renderer_text_new ();
 
-  if (! shown)
-    g_object_set (priv->text_renderer,
-                  "ellipsize", priv->ellipsize,
-                  NULL);
+  gtk_cell_layout_pack_start (layout,
+                              priv->menu_pixbuf_renderer, FALSE);
+  gtk_cell_layout_pack_start (layout,
+                              priv->menu_text_renderer, TRUE);
 
-  if (priv->label && ! shown)
+  gtk_cell_layout_set_attributes (layout,
+                                  priv->menu_pixbuf_renderer,
+                                  "icon-name", GIMP_INT_STORE_ICON_NAME,
+                                  "pixbuf",    GIMP_INT_STORE_PIXBUF,
+                                  NULL);
+  gtk_cell_layout_set_attributes (layout,
+                                  priv->menu_text_renderer,
+                                  "text", GIMP_INT_STORE_LABEL,
+                                  NULL);
+
+  if (priv->sensitivity_func)
+    {
+      gtk_cell_layout_set_cell_data_func (layout,
+                                          priv->menu_pixbuf_renderer,
+                                          gimp_int_combo_box_data_func,
+                                          priv, NULL);
+
+      gtk_cell_layout_set_cell_data_func (layout,
+                                          priv->menu_text_renderer,
+                                          gimp_int_combo_box_data_func,
+                                          priv, NULL);
+    }
+
+  /*  combo box layout  */
+
+  layout = GTK_CELL_LAYOUT (gtk_bin_get_child (GTK_BIN (combo_box)));
+
+  gtk_cell_layout_clear (layout);
+
+  if (priv->layout != GIMP_INT_COMBO_BOX_LAYOUT_ICON_ONLY)
+    {
+      priv->text_renderer = gtk_cell_renderer_text_new ();
+      g_object_set (priv->text_renderer,
+                    "ellipsize", priv->ellipsize,
+                    NULL);
+    }
+  else
+    {
+      priv->text_renderer = NULL;
+    }
+
+  priv->pixbuf_renderer = gtk_cell_renderer_pixbuf_new ();
+
+  if (priv->text_renderer)
+    {
+      g_object_set (priv->pixbuf_renderer,
+                    "xpad", 2,
+                    NULL);
+    }
+
+  if (priv->label)
     {
       priv->label_renderer = gtk_cell_renderer_text_new ();
       g_object_set (priv->label_renderer,
                     "text", priv->label,
                     NULL);
 
-      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box),
+      gtk_cell_layout_pack_start (layout,
                                   priv->label_renderer, FALSE);
 
-      gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (combo_box),
+      gtk_cell_layout_pack_end (layout,
                                 priv->pixbuf_renderer, FALSE);
-      gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (combo_box),
-                                priv->text_renderer, TRUE);
 
-      g_object_set (priv->text_renderer,
-                    "xalign", 1.0,
-                    NULL);
+      if (priv->text_renderer)
+        {
+          gtk_cell_layout_pack_end (layout,
+                                    priv->text_renderer, TRUE);
+
+          g_object_set (priv->text_renderer,
+                        "xalign", 1.0,
+                        NULL);
+        }
     }
   else
     {
-      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box),
+      gtk_cell_layout_pack_start (layout,
                                   priv->pixbuf_renderer, FALSE);
-      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box),
-                                  priv->text_renderer, TRUE);
+
+      if (priv->text_renderer)
+        {
+          gtk_cell_layout_pack_start (layout,
+                                      priv->text_renderer, TRUE);
+        }
     }
 
-  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box),
+  gtk_cell_layout_set_attributes (layout,
                                   priv->pixbuf_renderer,
                                   "icon-name", GIMP_INT_STORE_ICON_NAME,
-                                  "pixbuf",    GIMP_INT_STORE_PIXBUF,
-                                  NULL);
-  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box),
-                                  priv->text_renderer,
-                                  "text", GIMP_INT_STORE_LABEL,
                                   NULL);
 
-  if (priv->sensitivity_func)
+  if (priv->text_renderer)
+    {
+      gtk_cell_layout_set_attributes (layout,
+                                      priv->text_renderer,
+                                      "text", GIMP_INT_STORE_LABEL,
+                                      NULL);
+    }
+
+  if (priv->layout == GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED ||
+      priv->sensitivity_func)
     {
-      gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo_box),
+      gtk_cell_layout_set_cell_data_func (layout,
                                           priv->pixbuf_renderer,
                                           gimp_int_combo_box_data_func,
                                           priv, NULL);
 
-      gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (combo_box),
-                                          priv->text_renderer,
-                                          gimp_int_combo_box_data_func,
-                                          priv, NULL);
+      if (priv->text_renderer)
+        {
+          gtk_cell_layout_set_cell_data_func (layout,
+                                              priv->text_renderer,
+                                              gimp_int_combo_box_data_func,
+                                              priv, NULL);
+        }
     }
 
   /* HACK: GtkCellView doesn't invalidate itself when stuff is
@@ -821,6 +941,25 @@ gimp_int_combo_box_data_func (GtkCellLayout   *layout,
 {
   GimpIntComboBoxPrivate *priv = data;
 
+  if (priv->layout == GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED &&
+      cell == priv->text_renderer)
+    {
+      gchar *abbrev;
+
+      gtk_tree_model_get (model, iter,
+                          GIMP_INT_STORE_ABBREV, &abbrev,
+                          -1);
+
+      if (abbrev)
+        {
+          g_object_set (cell,
+                        "text", abbrev,
+                        NULL);
+
+          g_free (abbrev);
+        }
+    }
+
   if (priv->sensitivity_func)
     {
       gint      value;
diff --git a/libgimpwidgets/gimpintcombobox.h b/libgimpwidgets/gimpintcombobox.h
index 809f57d..20ca78a 100644
--- a/libgimpwidgets/gimpintcombobox.h
+++ b/libgimpwidgets/gimpintcombobox.h
@@ -101,6 +101,11 @@ void          gimp_int_combo_box_set_label       (GimpIntComboBox *combo_box,
                                                   const gchar     *label);
 const gchar * gimp_int_combo_box_get_label       (GimpIntComboBox *combo_box);
 
+void          gimp_int_combo_box_set_layout      (GimpIntComboBox       *combo_box,
+                                                  GimpIntComboBoxLayout  layout);
+const GimpIntComboBoxLayout
+              gimp_int_combo_box_get_layout      (GimpIntComboBox       *combo_box);
+
 void          gimp_int_combo_box_set_sensitivity (GimpIntComboBox        *combo_box,
                                                   GimpIntSensitivityFunc  func,
                                                   gpointer                data,
diff --git a/libgimpwidgets/gimpwidgetsenums.c b/libgimpwidgets/gimpwidgetsenums.c
index 829c284..0269275 100644
--- a/libgimpwidgets/gimpwidgetsenums.c
+++ b/libgimpwidgets/gimpwidgetsenums.c
@@ -244,6 +244,38 @@ gimp_zoom_type_get_type (void)
   return type;
 }
 
+GType
+gimp_int_combo_box_layout_get_type (void)
+{
+  static const GEnumValue values[] =
+  {
+    { GIMP_INT_COMBO_BOX_LAYOUT_ICON_ONLY, "GIMP_INT_COMBO_BOX_LAYOUT_ICON_ONLY", "icon-only" },
+    { GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED, "GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED", "abbreviated" },
+    { GIMP_INT_COMBO_BOX_LAYOUT_FULL, "GIMP_INT_COMBO_BOX_LAYOUT_FULL", "full" },
+    { 0, NULL, NULL }
+  };
+
+  static const GimpEnumDesc descs[] =
+  {
+    { GIMP_INT_COMBO_BOX_LAYOUT_ICON_ONLY, "GIMP_INT_COMBO_BOX_LAYOUT_ICON_ONLY", NULL },
+    { GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED, "GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED", NULL },
+    { GIMP_INT_COMBO_BOX_LAYOUT_FULL, "GIMP_INT_COMBO_BOX_LAYOUT_FULL", NULL },
+    { 0, NULL, NULL }
+  };
+
+  static GType type = 0;
+
+  if (G_UNLIKELY (! type))
+    {
+      type = g_enum_register_static ("GimpIntComboBoxLayout", values);
+      gimp_type_set_translation_domain (type, GETTEXT_PACKAGE "-libgimp");
+      gimp_type_set_translation_context (type, "int-combo-box-layout");
+      gimp_enum_set_value_descriptions (type, descs);
+    }
+
+  return type;
+}
+
 
 /* Generated data ends here */
 
diff --git a/libgimpwidgets/gimpwidgetsenums.h b/libgimpwidgets/gimpwidgetsenums.h
index 471fcfd..1b3fa15 100644
--- a/libgimpwidgets/gimpwidgetsenums.h
+++ b/libgimpwidgets/gimpwidgetsenums.h
@@ -188,6 +188,26 @@ typedef enum
 } GimpZoomType;
 
 
+/**
+ * GimpIntComboBoxLayout:
+ * @GIMP_INT_COMBO_BOX_LAYOUT_ICON_ONLY:   show icons only
+ * @GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED: show abbreviated labels
+ * @GIMP_INT_COMBO_BOX_LAYOUT_FULL:        show full labels
+ *
+ * Possible layouts for #GimpIntComboBox.
+ **/
+#define GIMP_TYPE_INT_COMBO_BOX_LAYOUT (gimp_int_combo_box_layout_get_type ())
+
+GType gimp_int_combo_box_layout_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+  GIMP_INT_COMBO_BOX_LAYOUT_ICON_ONLY,
+  GIMP_INT_COMBO_BOX_LAYOUT_ABBREVIATED,
+  GIMP_INT_COMBO_BOX_LAYOUT_FULL
+} GimpIntComboBoxLayout;
+
+
 G_END_DECLS
 
 #endif  /* __GIMP_WIDGETS_ENUMS_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]