]> Pileus Git - ~andy/gtk/commitdiff
Implemented basic child list handling on GtkCellAreaBox
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Sun, 24 Oct 2010 11:01:04 +0000 (20:01 +0900)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Sun, 24 Oct 2010 11:01:04 +0000 (20:01 +0900)
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
gtk/gtkcellareabox.c
gtk/gtkcellareabox.h

index be474232b071d4fd22c757acb2f7e54d59df8b2b..c8a2c3e71d0b9cc50e0f6184e8611ef84c521e7e 100644 (file)
@@ -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)
 {
index a635df233ec00ba56e6d6beec086ff6c516591e1..75e004a9db87e27bbe2a54a4c6fd7d20a29897d6 100644 (file)
@@ -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 
@@ -134,6 +163,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                         *
  *************************************************************/
@@ -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);
+}
index 1e188cecb2c76aee08ab5cce6c177ebc3f99d185..1913995ce4437f8b169cd8e04f3cbcd8f3125e79 100644 (file)
@@ -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