[gtk+] gtk_entry_completion_set_text_column: reuse old renderer



commit f6a0debdd9d4f90b9d6b54c263b10926ba530c7e
Author: Lars Uebernickel <lars uebernic de>
Date:   Sat Nov 2 14:22:33 2013 +0100

    gtk_entry_completion_set_text_column: reuse old renderer
    
    gtk_entry_completion_set_text_column() always added a cell renderer,
    regardless of whether there was an existing one already installed.  This
    patch reuses an old renderer if it exists, but only if it was added by a
    previous call to this function.
    
    To avoid conflicts, all renderers that were added manually are removed
    when calling this function. Also, the renderer added by this function is
    removed when manually adding new renderers. This effectively gives
    GtkEntryCompletion two modes (managed and manual cell renderers) and
    allows seamless switching between the two.
    
    This is a minor API break. However, this shouldn't be an issue in
    practice as applications couldn't call set_text_column() more than once
    because of this bug. Also, it is unlikely that many applications mix
    set_text_column() and custom cell renderers. The interaction between the
    two modes was erratic and not documented well.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=635499

 gtk/gtkentrycompletion.c |  128 +++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 116 insertions(+), 12 deletions(-)
---
diff --git a/gtk/gtkentrycompletion.c b/gtk/gtkentrycompletion.c
index 0d77663..61a3249 100644
--- a/gtk/gtkentrycompletion.c
+++ b/gtk/gtkentrycompletion.c
@@ -117,6 +117,14 @@ enum
 
 
 static void     gtk_entry_completion_cell_layout_init    (GtkCellLayoutIface      *iface);
+static GList *  gtk_entry_completion_get_cells           (GtkCellLayout           *cell_layout);
+static void     gtk_entry_completion_clear               (GtkCellLayout           *cell_layout);
+static void     gtk_entry_completion_pack_start          (GtkCellLayout           *cell_layout,
+                                                          GtkCellRenderer         *cell,
+                                                          gboolean                 expand);
+static void     gtk_entry_completion_pack_end            (GtkCellLayout           *cell_layout,
+                                                          GtkCellRenderer         *cell,
+                                                          gboolean                 expand);
 static GtkCellArea* gtk_entry_completion_get_area        (GtkCellLayout           *cell_layout);
 
 static GObject *gtk_entry_completion_constructor         (GType                    type,
@@ -478,6 +486,10 @@ gtk_entry_completion_buildable_init (GtkBuildableIface *iface)
 static void
 gtk_entry_completion_cell_layout_init (GtkCellLayoutIface *iface)
 {
+  iface->get_cells = gtk_entry_completion_get_cells;
+  iface->clear = gtk_entry_completion_clear;
+  iface->pack_start = gtk_entry_completion_pack_start;
+  iface->pack_end = gtk_entry_completion_pack_end;
   iface->get_area = gtk_entry_completion_get_area;
 }
 
@@ -814,7 +826,73 @@ gtk_entry_completion_dispose (GObject *object)
   G_OBJECT_CLASS (gtk_entry_completion_parent_class)->dispose (object);
 }
 
-/* implement cell layout interface (only need to return the underlying cell area) */
+static void
+gtk_entry_completion_clear_text_column_renderer (GtkEntryCompletion *completion)
+{
+  if (completion->priv->text_column != -1)
+    {
+      gtk_cell_layout_clear (GTK_CELL_LAYOUT (completion));
+      completion->priv->text_column = -1;
+      g_object_notify (G_OBJECT (completion), "text_column");
+    }
+}
+
+static GList *
+gtk_entry_completion_get_cells (GtkCellLayout *cell_layout)
+{
+  GtkEntryCompletion *completion = GTK_ENTRY_COMPLETION (cell_layout);
+
+  if (completion->priv->text_column == -1)
+    {
+      GtkCellArea *area;
+
+      area = gtk_entry_completion_get_area (cell_layout);
+      return gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (area));
+    }
+  else
+    {
+      /* Don't expose the internally created cell renderer */
+      return NULL;
+    }
+}
+
+static void
+gtk_entry_completion_clear (GtkCellLayout *cell_layout)
+{
+  GtkCellArea *area;
+
+  gtk_entry_completion_clear_text_column_renderer (GTK_ENTRY_COMPLETION (cell_layout));
+
+  area = gtk_entry_completion_get_area (cell_layout);
+  gtk_cell_layout_clear (GTK_CELL_LAYOUT (area));
+}
+
+static void
+gtk_entry_completion_pack_start (GtkCellLayout   *cell_layout,
+                                 GtkCellRenderer *cell,
+                                 gboolean         expand)
+{
+  GtkCellArea *area;
+
+  gtk_entry_completion_clear_text_column_renderer (GTK_ENTRY_COMPLETION (cell_layout));
+
+  area = gtk_entry_completion_get_area (cell_layout);
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (area), cell, expand);
+}
+
+static void
+gtk_entry_completion_pack_end (GtkCellLayout   *cell_layout,
+                               GtkCellRenderer *cell,
+                               gboolean         expand)
+{
+  GtkCellArea *area;
+
+  gtk_entry_completion_clear_text_column_renderer (GTK_ENTRY_COMPLETION (cell_layout));
+
+  area = gtk_entry_completion_get_area (cell_layout);
+  gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (area), cell, expand);
+}
+
 static GtkCellArea*
 gtk_entry_completion_get_area (GtkCellLayout *cell_layout)
 {
@@ -1393,10 +1471,12 @@ gtk_entry_completion_delete_action (GtkEntryCompletion *completion,
  * to have a list displaying all (and just) strings in the completion list,
  * and to get those strings from @column in the model of @completion.
  *
- * This functions creates and adds a #GtkCellRendererText for the selected
- * column. If you need to set the text column, but don't want the cell
- * renderer, use g_object_set() to set the #GtkEntryCompletion:text-column
- * property directly.
+ * Any cell renderers that were added to @completion before calling this
+ * function will be removed.
+ *
+ * Conversely, the cell renderer created by this function will be
+ * removed when new renderers are added to @completion with
+ * gtk_cell_layout_pack_start() or gtk_cell_layout_pack_end().
  *
  * Since: 2.4
  */
@@ -1409,15 +1489,39 @@ gtk_entry_completion_set_text_column (GtkEntryCompletion *completion,
   g_return_if_fail (GTK_IS_ENTRY_COMPLETION (completion));
   g_return_if_fail (column >= 0);
 
-  completion->priv->text_column = column;
+  /* clear manually set cell renderers */
+  if (completion->priv->text_column == -1)
+    gtk_cell_layout_clear (GTK_CELL_LAYOUT (completion));
 
-  cell = gtk_cell_renderer_text_new ();
-  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
-                              cell, TRUE);
-  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
-                                 cell,
-                                 "text", column);
+  if (completion->priv->text_column >= 0)
+    {
+      GtkCellArea *area;
+      GList *cells;
+
+      /* Call get_cells() on the internal area instead of on completion,
+       * because completion returns NULL for when the renderer is
+       * internal (i.e., was added by this function).
+       */
+      area = gtk_cell_layout_get_area (GTK_CELL_LAYOUT (completion));
+      cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (area));
+      g_assert (cells);
+
+      cell = cells->data;
+
+      g_list_free (cells);
+    }
+  else
+    {
+      cell = gtk_cell_renderer_text_new ();
+      gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
+                                  cell, TRUE);
+    }
+
+  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (completion), cell,
+                                  "text", column,
+                                  NULL);
 
+  completion->priv->text_column = column;
   g_object_notify (G_OBJECT (completion), "text-column");
 }
 


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