[gtk+/treeview-refactor: 80/102] Implemented basic child list handling on GtkCellAreaBox



commit 468a1d3e7c51a7b1964ccfcc680c24a04322338e
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Sun Oct 24 20:01:04 2010 +0900

    Implemented basic child list handling on GtkCellAreaBox
    
    Added the child list to GtkCellAreaBox, added _pack_start() and
    _pack_end() apis to GtkCellAreaBox since they are appropriate there
    and implemented GtkCellLayoutIface to override the _pack_start()/end()
    methods (since the base GtkCellArea class simply forwards these apis
    to the generic ->add() api on the base class).

 gtk/gtkcellarea.c    |  121 ++++++++++++++++++-----------------
 gtk/gtkcellareabox.c |  174 +++++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkcellareabox.h |   12 +++-
 3 files changed, 244 insertions(+), 63 deletions(-)
---
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index be47423..c8a2c3e 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -84,6 +84,8 @@ static CellAttribute  *cell_attribute_new  (GtkCellRenderer       *renderer,
 					    const gchar           *attribute,
 					    gint                   column);
 static void            cell_attribute_free (CellAttribute         *attribute);
+static gint            cell_attribute_find (CellAttribute         *cell_attribute,
+					    const gchar           *attribute);
 
 /* Struct to pass data along while looping over 
  * cell renderers to apply attributes
@@ -145,65 +147,8 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
   g_type_class_add_private (object_class, sizeof (GtkCellAreaPrivate));
 }
 
-
 /*************************************************************
- *                      GObjectClass                         *
- *************************************************************/
-static void
-gtk_cell_area_finalize (GObject *object)
-{
-  GtkCellArea        *area   = GTK_CELL_AREA (object);
-  GtkCellAreaPrivate *priv   = area->priv;
-
-  /* All cell renderers should already be removed at this point,
-   * just kill our hash table here. 
-   */
-  g_hash_table_destroy (priv->cell_info);
-
-  G_OBJECT_CLASS (gtk_cell_area_parent_class)->finalize (object);
-}
-
-
-static void
-gtk_cell_area_dispose (GObject *object)
-{
-  /* This removes every cell renderer that may be added to the GtkCellArea,
-   * subclasses should be breaking references to the GtkCellRenderers 
-   * at this point.
-   */
-  gtk_cell_layout_clear (GTK_CELL_LAYOUT (object));
-
-  G_OBJECT_CLASS (gtk_cell_area_parent_class)->dispose (object);
-}
-
-
-/*************************************************************
- *                    GtkCellAreaClass                       *
- *************************************************************/
-static void
-gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea        *area,
-						   GtkWidget          *widget,
-						   gint                width,
-						   gint               *minimum_height,
-						   gint               *natural_height)
-{
-  /* If the area doesnt do height-for-width, fallback on base preferred height */
-  GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, widget, minimum_height, natural_height);
-}
-
-static void
-gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea        *area,
-						   GtkWidget          *widget,
-						   gint                height,
-						   gint               *minimum_width,
-						   gint               *natural_width)
-{
-  /* If the area doesnt do width-for-height, fallback on base preferred width */
-  GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, widget, minimum_width, natural_width);
-}
-
-/*************************************************************
- *                   GtkCellLayoutIface                      *
+ *                    CellInfo Basics                        *
  *************************************************************/
 static CellInfo *
 cell_info_new (GtkCellLayoutDataFunc  func,
@@ -264,6 +209,7 @@ cell_attribute_free (CellAttribute *attribute)
   g_slice_free (CellAttribute, attribute);
 }
 
+/* GCompareFunc for g_slist_find_custom() */
 static gint
 cell_attribute_find (CellAttribute *cell_attribute,
 		     const gchar   *attribute)
@@ -271,6 +217,65 @@ cell_attribute_find (CellAttribute *cell_attribute,
   return g_strcmp0 (cell_attribute->attribute, attribute);
 }
 
+/*************************************************************
+ *                      GObjectClass                         *
+ *************************************************************/
+static void
+gtk_cell_area_finalize (GObject *object)
+{
+  GtkCellArea        *area   = GTK_CELL_AREA (object);
+  GtkCellAreaPrivate *priv   = area->priv;
+
+  /* All cell renderers should already be removed at this point,
+   * just kill our hash table here. 
+   */
+  g_hash_table_destroy (priv->cell_info);
+
+  G_OBJECT_CLASS (gtk_cell_area_parent_class)->finalize (object);
+}
+
+
+static void
+gtk_cell_area_dispose (GObject *object)
+{
+  /* This removes every cell renderer that may be added to the GtkCellArea,
+   * subclasses should be breaking references to the GtkCellRenderers 
+   * at this point.
+   */
+  gtk_cell_layout_clear (GTK_CELL_LAYOUT (object));
+
+  G_OBJECT_CLASS (gtk_cell_area_parent_class)->dispose (object);
+}
+
+
+/*************************************************************
+ *                    GtkCellAreaClass                       *
+ *************************************************************/
+static void
+gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea        *area,
+						   GtkWidget          *widget,
+						   gint                width,
+						   gint               *minimum_height,
+						   gint               *natural_height)
+{
+  /* If the area doesnt do height-for-width, fallback on base preferred height */
+  GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, widget, minimum_height, natural_height);
+}
+
+static void
+gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea        *area,
+						   GtkWidget          *widget,
+						   gint                height,
+						   gint               *minimum_width,
+						   gint               *natural_width)
+{
+  /* If the area doesnt do width-for-height, fallback on base preferred width */
+  GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, widget, minimum_width, natural_width);
+}
+
+/*************************************************************
+ *                   GtkCellLayoutIface                      *
+ *************************************************************/
 static void
 gtk_cell_area_cell_layout_init (GtkCellLayoutIface *iface)
 {
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index a635df2..75e004a 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -22,6 +22,7 @@
  */
 
 #include "gtkorientable.h"
+#include "gtkcelllayout.h"
 #include "gtkcellareabox.h"
 
 /* GObjectClass */
@@ -73,11 +74,37 @@ static void      gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea
 								   gint               *minimum_width,
 								   gint               *natural_width);
 
+/* GtkCellLayoutIface */
+static void      gtk_cell_area_box_cell_layout_init               (GtkCellLayoutIface *iface);
+static void      gtk_cell_area_box_layout_pack_start              (GtkCellLayout      *cell_layout,
+								   GtkCellRenderer    *renderer,
+								   gboolean            expand);
+static void      gtk_cell_area_box_layout_pack_end                (GtkCellLayout      *cell_layout,
+								   GtkCellRenderer    *renderer,
+								   gboolean            expand);
+
+
+/* CellInfo metadata handling */
+typedef struct {
+  GtkCellRenderer *renderer;
+
+  guint            expand : 1;
+  guint            pack   : 1;
+} CellInfo;
+
+static CellInfo  *cell_info_new  (GtkCellRenderer *renderer, 
+				  gboolean         expand,
+				  GtkPackType      pack);
+static void       cell_info_free (CellInfo        *info);
+static gint       cell_info_find (CellInfo        *info,
+				  GtkCellRenderer *renderer);
+
 
 struct _GtkCellAreaBoxPrivate
 {
   GtkOrientation orientation;
 
+  GList *cells;
 };
 
 enum {
@@ -86,9 +113,10 @@ enum {
 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkCellAreaBox, gtk_cell_area_box, GTK_TYPE_CELL_AREA,
+			 G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_LAYOUT,
+						gtk_cell_area_box_cell_layout_init)
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL));
 
-
 static void
 gtk_cell_area_box_init (GtkCellAreaBox *box)
 {
@@ -100,6 +128,7 @@ gtk_cell_area_box_init (GtkCellAreaBox *box)
   priv = box->priv;
 
   priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+  priv->cells       = NULL;
 }
 
 static void 
@@ -135,6 +164,38 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
 
 
 /*************************************************************
+ *                    CellInfo Basics                        *
+ *************************************************************/
+static CellInfo *
+cell_info_new  (GtkCellRenderer *renderer, 
+		gboolean         expand,
+		GtkPackType      pack)
+{
+  CellInfo *info = g_slice_new (CellInfo);
+  
+  info->renderer = g_object_ref_sink (renderer);
+  info->expand   = expand;
+  info->pack     = pack;
+
+  return info;
+}
+
+static void
+cell_info_free (CellInfo *info)
+{
+  g_object_unref (info->renderer);
+
+  g_slice_free (CellInfo, info);
+}
+
+static gint
+cell_info_find (CellInfo        *info,
+		GtkCellRenderer *renderer)
+{
+  return (info->renderer == renderer) ? 0 : -1;
+}
+
+/*************************************************************
  *                      GObjectClass                         *
  *************************************************************/
 static void
@@ -174,14 +235,31 @@ static void
 gtk_cell_area_box_add (GtkCellArea        *area,
 		       GtkCellRenderer    *renderer)
 {
-
+  gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area),
+				renderer, FALSE);
 }
 
 static void
 gtk_cell_area_box_remove (GtkCellArea        *area,
 			  GtkCellRenderer    *renderer)
 {
+  GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
+  GtkCellAreaBoxPrivate *priv = box->priv;
+  GList                 *node;
+
+  node = g_list_find_custom (priv->cells, renderer, 
+			     (GCompareFunc)cell_info_find);
+
+  if (node)
+    {
+      CellInfo *info = node->data;
 
+      cell_info_free (info);
+
+      priv->cells = g_list_delete_link (priv->cells, node);
+    }
+  else
+    g_warning ("Trying to remove a cell renderer that is not present GtkCellAreaBox");
 }
 
 static void
@@ -189,7 +267,16 @@ gtk_cell_area_box_forall (GtkCellArea        *area,
 			  GtkCellCallback     callback,
 			  gpointer            callback_data)
 {
+  GtkCellAreaBox        *box  = GTK_CELL_AREA_BOX (area);
+  GtkCellAreaBoxPrivate *priv = box->priv;
+  GList                 *list;
+
+  for (list = priv->cells; list; list = list->next)
+    {
+      CellInfo *info = list->data;
 
+      callback (info->renderer, callback_data);
+    }
 }
 
 static gint
@@ -262,6 +349,89 @@ gtk_cell_area_box_get_preferred_width_for_height (GtkCellArea        *area,
 
 }
 
+
+
+/*************************************************************
+ *                    GtkCellLayoutIface                     *
+ *************************************************************/
+static void
+gtk_cell_area_box_cell_layout_init (GtkCellLayoutIface *iface)
+{
+  iface->pack_start = gtk_cell_area_box_layout_pack_start;
+  iface->pack_end   = gtk_cell_area_box_layout_pack_end;
+}
+
+static void
+gtk_cell_area_box_layout_pack_start (GtkCellLayout      *cell_layout,
+				     GtkCellRenderer    *renderer,
+				     gboolean            expand)
+{
+  gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
+}
+
+static void
+gtk_cell_area_box_layout_pack_end (GtkCellLayout      *cell_layout,
+				   GtkCellRenderer    *renderer,
+				   gboolean            expand)
+{
+  gtk_cell_area_box_pack_end (GTK_CELL_AREA_BOX (cell_layout), renderer, expand);
+}
+
 /*************************************************************
  *                            API                            *
  *************************************************************/
+GtkCellArea *
+gtk_cell_area_box_new (void)
+{
+  return (GtkCellArea *)g_object_new (GTK_TYPE_CELL_AREA_BOX, NULL);
+}
+
+void
+gtk_cell_area_box_pack_start  (GtkCellAreaBox  *box,
+			       GtkCellRenderer *renderer,
+			       gboolean         expand)
+{
+  GtkCellAreaBoxPrivate *priv;
+  CellInfo              *info;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+
+  priv = box->priv;
+
+  if (g_list_find_custom (priv->cells, renderer, 
+			  (GCompareFunc)cell_info_find))
+    {
+      g_warning ("Refusing to add the same cell renderer to a GtkCellAreaBox twice");
+      return;
+    }
+
+  info = cell_info_new (renderer, expand, GTK_PACK_START);
+
+  priv->cells = g_list_append (priv->cells, info);
+}
+
+void
+gtk_cell_area_box_pack_end (GtkCellAreaBox  *box,
+			    GtkCellRenderer *renderer,
+			    gboolean         expand)
+{
+  GtkCellAreaBoxPrivate *priv;
+  CellInfo              *info;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_BOX (box));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+
+  priv = box->priv;
+
+  if (g_list_find_custom (priv->cells, renderer, 
+			  (GCompareFunc)cell_info_find))
+    {
+      g_warning ("Refusing to add the same cell renderer to a GtkCellArea twice");
+      return;
+    }
+
+  info = cell_info_new (renderer, expand, GTK_PACK_END);
+
+  priv->cells = g_list_append (priv->cells, info);
+}
diff --git a/gtk/gtkcellareabox.h b/gtk/gtkcellareabox.h
index 1e188ce..1913995 100644
--- a/gtk/gtkcellareabox.h
+++ b/gtk/gtkcellareabox.h
@@ -62,9 +62,15 @@ struct _GtkCellAreaBoxClass
   void (*_gtk_reserved4) (void);
 };
 
-GType              gtk_cell_area_box_get_type                       (void) G_GNUC_CONST;
-
-
+GType              gtk_cell_area_box_get_type    (void) G_GNUC_CONST;
+
+GtkCellArea       *gtk_cell_area_box_new         (void);
+void               gtk_cell_area_box_pack_start  (GtkCellAreaBox  *box,
+						  GtkCellRenderer *renderer,
+						  gboolean         expand);
+void               gtk_cell_area_box_pack_end    (GtkCellAreaBox  *box,
+						  GtkCellRenderer *renderer,
+						  gboolean         expand);
 
 G_END_DECLS
 



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