[gtk+/treeview-refactor] Made progress on focus handling.



commit 631bdc438c67debf5d7fab51cd655ac296ab32d3
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Fri Nov 5 22:16:32 2010 +0900

    Made progress on focus handling.
    
     - Added vfunc to get the allocation of a cell inside an area
     - Superclass GtkCellArea handles activation of focused cells
       by handling key events (as well as editing of editable cells)
     - Added signal "editing-started" to GtkCellArea to signal that
       editing has started (generally signaled from inside event handling)
     - Added properties "focus-cell" and "edited-cell"

 gtk/gtkcellarea.c      |  300 +++++++++++++++++++++++++++++++++++++++++++++++-
 gtk/gtkcellarea.h      |   22 ++++
 gtk/gtkcellareabox.c   |   86 +++++++++++++-
 gtk/gtkmarshalers.list |    1 +
 4 files changed, 396 insertions(+), 13 deletions(-)
---
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index fc30fb8..ccc1b71 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -130,10 +130,21 @@ typedef struct {
 
 struct _GtkCellAreaPrivate
 {
+  /* The GtkCellArea bookkeeps any connected 
+   * attributes in this hash table.
+   */
   GHashTable      *cell_info;
 
+  /* The cell border decides how much space to reserve
+   * around each cell for the background_area
+   */
   GtkBorder        cell_border;
 
+  /* Current path is saved as a side-effect
+   * of gtk_cell_area_apply_attributes() */
+  gchar           *current_path;
+
+  GtkCellRenderer *edited_cell;
   GtkCellRenderer *focus_cell;
   guint            can_focus : 1;
 
@@ -144,11 +155,14 @@ enum {
   PROP_CELL_MARGIN_LEFT,
   PROP_CELL_MARGIN_RIGHT,
   PROP_CELL_MARGIN_TOP,
-  PROP_CELL_MARGIN_BOTTOM
+  PROP_CELL_MARGIN_BOTTOM,
+  PROP_FOCUS_CELL,
+  PROP_EDITED_CELL
 };
 
 enum {
   SIGNAL_FOCUS_LEAVE,
+  SIGNAL_EDITING_STARTED,
   LAST_SIGNAL
 };
 
@@ -229,6 +243,17 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
 		  G_TYPE_NONE, 2,
 		  GTK_TYPE_DIRECTION_TYPE, G_TYPE_STRING);
 
+  cell_area_signals[SIGNAL_EDITING_STARTED] =
+    g_signal_new (I_("editing-started"),
+		  G_OBJECT_CLASS_TYPE (object_class),
+		  G_SIGNAL_RUN_FIRST,
+		  0, /* No class closure here */
+		  NULL, NULL,
+		  _gtk_marshal_VOID__OBJECT_OBJECT_STRING,
+		  G_TYPE_NONE, 3,
+		  GTK_TYPE_CELL_RENDERER,
+		  GTK_TYPE_CELL_EDITABLE,
+		  G_TYPE_STRING);
 
   /* Properties */
   g_object_class_install_property (object_class,
@@ -275,6 +300,24 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
 				    0,
 				    GTK_PARAM_READWRITE));
 
+  g_object_class_install_property (object_class,
+                                   PROP_FOCUS_CELL,
+                                   g_param_spec_object
+				   ("focus-cell",
+				    P_("Focus Cell"),
+				    P_("The cell which currently has focus"),
+				    GTK_TYPE_CELL_RENDERER,
+				    GTK_PARAM_READWRITE));
+
+  g_object_class_install_property (object_class,
+                                   PROP_EDITED_CELL,
+                                   g_param_spec_object
+				   ("edited-cell",
+				    P_("Edited Cell"),
+				    P_("The cell which is currently being edited"),
+				    GTK_TYPE_CELL_RENDERER,
+				    GTK_PARAM_READWRITE));
+
   /* Pool for Cell Properties */
   if (!cell_property_pool)
     cell_property_pool = g_param_spec_pool_new (FALSE);
@@ -366,6 +409,8 @@ gtk_cell_area_finalize (GObject *object)
    */
   g_hash_table_destroy (priv->cell_info);
 
+  g_free (priv->current_path);
+
   G_OBJECT_CLASS (gtk_cell_area_parent_class)->finalize (object);
 }
 
@@ -379,8 +424,9 @@ gtk_cell_area_dispose (GObject *object)
    */
   gtk_cell_layout_clear (GTK_CELL_LAYOUT (object));
 
-  /* Remove any ref to a focused cell */
+  /* Remove any ref to a focused/edited cell */
   gtk_cell_area_set_focus_cell (GTK_CELL_AREA (object), NULL);
+  gtk_cell_area_set_edited_cell (GTK_CELL_AREA (object), NULL);
 
   G_OBJECT_CLASS (gtk_cell_area_parent_class)->dispose (object);
 }
@@ -407,6 +453,9 @@ gtk_cell_area_set_property (GObject       *object,
     case PROP_CELL_MARGIN_BOTTOM:
       gtk_cell_area_set_cell_margin_bottom (area, g_value_get_int (value));
       break;
+    case PROP_FOCUS_CELL:
+      gtk_cell_area_set_focus_cell (area, (GtkCellRenderer *)g_value_get_object (value));
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -436,6 +485,9 @@ gtk_cell_area_get_property (GObject     *object,
     case PROP_CELL_MARGIN_BOTTOM:
       g_value_set_int (value, priv->cell_border.bottom);
       break;
+    case PROP_FOCUS_CELL:
+      g_value_set_object (value, priv->focus_cell);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -453,16 +505,73 @@ gtk_cell_area_real_event (GtkCellArea          *area,
 			  const GdkRectangle   *cell_area,
 			  GtkCellRendererState  flags)
 {
-  if (event->type == GDK_KEY_PRESS)
+  if (event->type == GDK_KEY_PRESS && (flags & GTK_CELL_RENDERER_FOCUSED) != 0)
     {
+      GdkEventKey        *key_event = (GdkEventKey *)event;
       GtkCellAreaPrivate *priv = area->priv;
 
-      if (priv->focus_cell)
+      if (priv->focus_cell && 
+	  (key_event->keyval == GDK_KEY_space ||
+	   key_event->keyval == GDK_KEY_KP_Space ||
+	   key_event->keyval == GDK_KEY_Return ||
+	   key_event->keyval == GDK_KEY_ISO_Enter ||
+	   key_event->keyval == GDK_KEY_KP_Enter))
 	{
-	  /* Activate of Edit the currently focused cell */
+	  /* Activate or Edit the currently focused cell */
+	  GtkCellRendererMode mode;
+	  GdkRectangle        background_area;
+	  GdkRectangle        inner_area;
+
+	  /* Get the allocation of the focused cell.
+	   */
+	  gtk_cell_area_get_cell_allocation (area, iter, widget, priv->focus_cell,
+					     cell_area, &background_area);
+
+	  /* Remove margins from the background area to produce the cell area.
+	   */
+	  gtk_cell_area_inner_cell_area (area, &background_area, &inner_area);
 
+	  /* XXX Need to do some extra right-to-left casing either here 
+	   * or inside the above called apis.
+	   */
 
-	  return TRUE;
+	  g_object_get (priv->focus_cell, "mode", &mode, NULL);
+
+	  if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
+	    {
+	      if (gtk_cell_renderer_activate (priv->focus_cell,
+					      event, widget,
+					      priv->current_path,
+					      &background_area,
+					      &inner_area,
+					      flags))
+		  return TRUE;
+	    }
+	  else if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
+	    {
+	      GtkCellEditable *editable_widget;
+
+	      editable_widget =
+		gtk_cell_renderer_start_editing (priv->focus_cell,
+						 event, widget,
+						 priv->current_path,
+						 &background_area,
+						 &inner_area,
+						 flags);
+
+	      if (editable_widget != NULL)
+		{
+		  g_return_val_if_fail (GTK_IS_CELL_EDITABLE (editable_widget), FALSE);
+
+		  gtk_cell_area_set_edited_cell (area, priv->focus_cell);
+
+		  /* Signal that editing started so that callers can get 
+		   * a handle on the editable_widget */
+		  gtk_cell_area_editing_started (area, priv->focus_cell, editable_widget);
+		  
+		  return TRUE;
+		}
+	    }
 	}
     }
 
@@ -662,6 +771,14 @@ gtk_cell_area_get_cells (GtkCellLayout *cell_layout)
 /*************************************************************
  *                            API                            *
  *************************************************************/
+
+/**
+ * gtk_cell_area_add:
+ * @area: a #GtkCellArea
+ * @renderer: the #GtkCellRenderer to add to @area
+ *
+ * Adds @renderer to @area with the default child cell properties.
+ */
 void
 gtk_cell_area_add (GtkCellArea        *area,
 		   GtkCellRenderer    *renderer)
@@ -680,6 +797,13 @@ gtk_cell_area_add (GtkCellArea        *area,
 	       g_type_name (G_TYPE_FROM_INSTANCE (area)));
 }
 
+/**
+ * gtk_cell_area_remove:
+ * @area: a #GtkCellArea
+ * @renderer: the #GtkCellRenderer to add to @area
+ *
+ * Removes @renderer from @area.
+ */
 void
 gtk_cell_area_remove (GtkCellArea        *area,
 		      GtkCellRenderer    *renderer)
@@ -703,6 +827,14 @@ gtk_cell_area_remove (GtkCellArea        *area,
 	       g_type_name (G_TYPE_FROM_INSTANCE (area)));
 }
 
+/**
+ * gtk_cell_area_forall
+ * @area: a #GtkCellArea
+ * @callback: the #GtkCellCallback to call
+ * @callback_data: user provided data pointer
+ *
+ * Calls @callback for every #GtkCellRenderer in @area.
+ */
 void
 gtk_cell_area_forall (GtkCellArea        *area,
 		      GtkCellCallback     callback,
@@ -722,6 +854,45 @@ gtk_cell_area_forall (GtkCellArea        *area,
 	       g_type_name (G_TYPE_FROM_INSTANCE (area)));
 }
 
+/**
+ * gtk_cell_area_get_cell_allocation:
+ * @area: a #GtkCellArea
+ * @iter: the #GtkCellAreaIter used to hold sizes for @area.
+ * @widget: the #GtkWidget that @area is rendering on
+ * @renderer: the #GtkCellRenderer to get the allocation for
+ * @cell_area: the whole allocated area for @area in @widget
+ *             for this row
+ * @allocation: where to store the allocation for @renderer
+ *
+ * Derives the allocation of @renderer inside @area if @area
+ * were to be renderered in @cell_area.
+ */
+void
+gtk_cell_area_get_cell_allocation (GtkCellArea          *area,
+				   GtkCellAreaIter      *iter,	
+				   GtkWidget            *widget,
+				   GtkCellRenderer      *renderer,
+				   const GdkRectangle   *cell_area,
+				   GdkRectangle         *allocation)
+{
+  GtkCellAreaClass *class;
+
+  g_return_if_fail (GTK_IS_CELL_AREA (area));
+  g_return_if_fail (GTK_IS_CELL_AREA_ITER (iter));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+  g_return_if_fail (cell_area != NULL);
+  g_return_if_fail (allocation != NULL);
+
+  class = GTK_CELL_AREA_GET_CLASS (area);
+
+  if (class->get_cell_allocation)
+    class->get_cell_allocation (area, iter, widget, renderer, cell_area, allocation);
+  else
+    g_warning ("GtkCellAreaClass::get_cell_allocation not implemented for `%s'", 
+	       g_type_name (G_TYPE_FROM_INSTANCE (area)));
+}
+
 gint
 gtk_cell_area_event (GtkCellArea          *area,
 		     GtkCellAreaIter      *iter,
@@ -893,6 +1064,17 @@ gtk_cell_area_get_preferred_width_for_height (GtkCellArea        *area,
 /*************************************************************
  *                      API: Attributes                      *
  *************************************************************/
+
+/**
+ * gtk_cell_area_attribute_connect:
+ * @area: a #GtkCellArea
+ * @renderer: the #GtkCellRenderer to connect an attribute for
+ * @attribute: the attribute name
+ * @column: the #GtkTreeModel column to fetch attribute values from
+ *
+ * Connects an @attribute to apply values from @column for the
+ * #GtkTreeModel in use.
+ */
 void
 gtk_cell_area_attribute_connect (GtkCellArea        *area,
 				 GtkCellRenderer    *renderer,
@@ -949,6 +1131,16 @@ gtk_cell_area_attribute_connect (GtkCellArea        *area,
   info->attributes = g_slist_prepend (info->attributes, cell_attribute);
 }
 
+/**
+ * gtk_cell_area_attribute_disconnect:
+ * @area: a #GtkCellArea
+ * @renderer: the #GtkCellRenderer to disconnect an attribute for
+ * @attribute: the attribute name
+ *
+ * Disconnects @attribute for the @renderer in @area so that
+ * attribute will no longer be updated with values from the
+ * model.
+ */
 void 
 gtk_cell_area_attribute_disconnect (GtkCellArea        *area,
 				    GtkCellRenderer    *renderer,
@@ -1025,6 +1217,18 @@ apply_cell_attributes (GtkCellRenderer *renderer,
   g_object_thaw_notify (G_OBJECT (renderer));
 }
 
+/**
+ * gtk_cell_area_apply_attributes
+ * @area: a #GtkCellArea
+ * @tree_model: a #GtkTreeModel to pull values from
+ * @iter: the #GtkTreeIter in @tree_model to apply values for
+ * @is_expander: whether @iter has children
+ * @is_expanded: whether @iter is expanded in the view and
+ *               children are visible
+ *
+ * Applies any connected attributes to the renderers in 
+ * @area by pulling the values from @tree_model.
+ */
 void
 gtk_cell_area_apply_attributes (GtkCellArea  *area,
 				GtkTreeModel *tree_model,
@@ -1034,6 +1238,7 @@ gtk_cell_area_apply_attributes (GtkCellArea  *area,
 {
   GtkCellAreaPrivate *priv;
   AttributeData       data;
+  GtkTreePath        *path;
 
   g_return_if_fail (GTK_IS_CELL_AREA (area));
   g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
@@ -1051,8 +1256,37 @@ gtk_cell_area_apply_attributes (GtkCellArea  *area,
   /* Go over any cells that have attributes or custom GtkCellLayoutDataFuncs and
    * apply the data from the treemodel */
   g_hash_table_foreach (priv->cell_info, (GHFunc)apply_cell_attributes, &data);
+
+  /* Update the currently applied path */
+  g_free (priv->current_path);
+  path               = gtk_tree_model_get_path (tree_model, iter);
+  priv->current_path = gtk_tree_path_to_string (path);
+  gtk_tree_path_free (path);
 }
 
+/**
+ * gtk_cell_area_get_current_path_string:
+ * @area: a #GtkCellArea
+ *
+ * Gets the current #GtkTreePath string for the currently
+ * applied #GtkTreeIter, this is implicitly updated when
+ * gtk_cell_area_apply_attributes() is called and can be
+ * used to interact with renderers from #GtkCellArea
+ * subclasses.
+ */
+const gchar *
+gtk_cell_area_get_current_path_string (GtkCellArea *area)
+{
+  GtkCellAreaPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL);
+
+  priv = area->priv;
+
+  return priv->current_path;
+}
+
+
 /*************************************************************
  *                    API: Cell Properties                   *
  *************************************************************/
@@ -1566,6 +1800,8 @@ gtk_cell_area_set_focus_cell (GtkCellArea     *area,
 
       if (priv->focus_cell)
 	g_object_ref (priv->focus_cell);
+
+      g_object_notify (G_OBJECT (area), "focus-cell");
     }
 }
 
@@ -1589,6 +1825,43 @@ gtk_cell_area_get_focus_cell (GtkCellArea *area)
   return priv->focus_cell;
 }
 
+void
+gtk_cell_area_set_edited_cell (GtkCellArea     *area,
+			       GtkCellRenderer *renderer)
+{
+  GtkCellAreaPrivate *priv;
+
+  g_return_if_fail (GTK_IS_CELL_AREA (area));
+  g_return_if_fail (renderer == NULL || GTK_IS_CELL_RENDERER (renderer));
+
+  priv = area->priv;
+
+  if (priv->edited_cell != renderer)
+    {
+      if (priv->edited_cell)
+	g_object_unref (priv->edited_cell);
+
+      priv->edited_cell = renderer;
+
+      if (priv->edited_cell)
+	g_object_ref (priv->edited_cell);
+
+      g_object_notify (G_OBJECT (area), "edited-cell");
+    }
+}
+
+GtkCellRenderer   *
+gtk_cell_area_get_edited_cell (GtkCellArea *area)
+{
+  GtkCellAreaPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL);
+
+  priv = area->priv;
+
+  return priv->edited_cell;
+}
+
 /*************************************************************
  *                        API: Margins                       *
  *************************************************************/
@@ -1698,6 +1971,21 @@ gtk_cell_area_set_cell_margin_bottom (GtkCellArea *area,
 
 /* For convenience in area implementations */
 void
+gtk_cell_area_editing_started (GtkCellArea        *area,
+			       GtkCellRenderer    *renderer,
+			       GtkCellEditable    *editable)
+{
+  GtkCellAreaPrivate *priv;
+
+  g_return_if_fail (GTK_IS_CELL_AREA (area));
+
+  priv = area->priv;
+
+  g_signal_emit (area, cell_area_signals[SIGNAL_EDITING_STARTED], 0, 
+		 renderer, editable, priv->current_path);
+}
+
+void
 gtk_cell_area_inner_cell_area (GtkCellArea        *area,
 			       GdkRectangle       *background_area,
 			       GdkRectangle       *cell_area)
diff --git a/gtk/gtkcellarea.h b/gtk/gtkcellarea.h
index 9c09553..0e806df 100644
--- a/gtk/gtkcellarea.h
+++ b/gtk/gtkcellarea.h
@@ -79,6 +79,12 @@ struct _GtkCellAreaClass
   void               (* forall)                          (GtkCellArea             *area,
 							  GtkCellCallback          callback,
 							  gpointer                 callback_data);
+  void               (* get_cell_allocation)             (GtkCellArea             *area,
+							  GtkCellAreaIter         *iter,
+							  GtkWidget               *widget,
+							  GtkCellRenderer         *renderer,
+							  const GdkRectangle      *cell_area,
+							  GdkRectangle            *allocation);
   gint               (* event)                           (GtkCellArea             *area,
 							  GtkCellAreaIter         *iter,
 							  GtkWidget               *widget,
@@ -156,6 +162,12 @@ void               gtk_cell_area_remove                         (GtkCellArea
 void               gtk_cell_area_forall                         (GtkCellArea          *area,
 								 GtkCellCallback       callback,
 								 gpointer              callback_data);
+void               gtk_cell_area_get_cell_allocation            (GtkCellArea          *area,
+								 GtkCellAreaIter      *iter,
+								 GtkWidget            *widget,
+								 GtkCellRenderer      *renderer,
+								 const GdkRectangle   *cell_area,
+								 GdkRectangle         *allocation);
 gint               gtk_cell_area_event                          (GtkCellArea          *area,
 								 GtkCellAreaIter      *iter,
 								 GtkWidget            *widget,
@@ -194,6 +206,8 @@ void               gtk_cell_area_get_preferred_width_for_height (GtkCellArea
 								 gint                height,
 								 gint               *minimum_width,
 								 gint               *natural_width);
+G_CONST_RETURN gchar *gtk_cell_area_get_current_path_string     (GtkCellArea        *area);
+
 
 /* Attributes */
 void               gtk_cell_area_apply_attributes               (GtkCellArea        *area,
@@ -263,6 +277,9 @@ gboolean           gtk_cell_area_get_can_focus                  (GtkCellArea
 void               gtk_cell_area_set_focus_cell                 (GtkCellArea        *area,
 								 GtkCellRenderer    *renderer);
 GtkCellRenderer   *gtk_cell_area_get_focus_cell                 (GtkCellArea        *area);
+void               gtk_cell_area_set_edited_cell                (GtkCellArea        *area,
+								 GtkCellRenderer    *renderer);
+GtkCellRenderer   *gtk_cell_area_get_edited_cell                (GtkCellArea        *area);
 
 
 
@@ -282,6 +299,11 @@ void               gtk_cell_area_set_cell_margin_bottom         (GtkCellArea
 
 /* Functions for area implementations */
 
+/* Signal that editing started on the area (fires the "editing-started" signal) */
+void               gtk_cell_area_editing_started                (GtkCellArea        *area,
+								 GtkCellRenderer    *renderer,
+								 GtkCellEditable    *editable);
+
 /* Distinguish the inner cell area from the whole requested area including margins */
 void               gtk_cell_area_inner_cell_area                (GtkCellArea        *area,
 								 GdkRectangle       *cell_area,
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index ad2f6ee..a2f73bd 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -50,6 +50,12 @@ static void      gtk_cell_area_box_remove                         (GtkCellArea
 static void      gtk_cell_area_box_forall                         (GtkCellArea          *area,
 								   GtkCellCallback       callback,
 								   gpointer              callback_data);
+static void      gtk_cell_area_box_get_cell_allocation            (GtkCellArea          *area,
+								   GtkCellAreaIter      *iter,	
+								   GtkWidget            *widget,
+								   GtkCellRenderer      *renderer,
+								   const GdkRectangle   *cell_area,
+								   GdkRectangle         *allocation);
 static gint      gtk_cell_area_box_event                          (GtkCellArea          *area,
 								   GtkCellAreaIter      *iter,
 								   GtkWidget            *widget,
@@ -225,13 +231,14 @@ gtk_cell_area_box_class_init (GtkCellAreaBoxClass *class)
   object_class->get_property = gtk_cell_area_box_get_property;
 
   /* GtkCellAreaClass */
-  area_class->add               = gtk_cell_area_box_add;
-  area_class->remove            = gtk_cell_area_box_remove;
-  area_class->forall            = gtk_cell_area_box_forall;
-  area_class->event             = gtk_cell_area_box_event;
-  area_class->render            = gtk_cell_area_box_render;
-  area_class->set_cell_property = gtk_cell_area_box_set_cell_property;
-  area_class->get_cell_property = gtk_cell_area_box_get_cell_property;
+  area_class->add                 = gtk_cell_area_box_add;
+  area_class->remove              = gtk_cell_area_box_remove;
+  area_class->forall              = gtk_cell_area_box_forall;
+  area_class->get_cell_allocation = gtk_cell_area_box_get_cell_allocation;
+  area_class->event               = gtk_cell_area_box_event;
+  area_class->render              = gtk_cell_area_box_render;
+  area_class->set_cell_property   = gtk_cell_area_box_set_cell_property;
+  area_class->get_cell_property   = gtk_cell_area_box_get_cell_property;
   
   area_class->create_iter                    = gtk_cell_area_box_create_iter;
   area_class->get_request_mode               = gtk_cell_area_box_get_request_mode;
@@ -811,6 +818,50 @@ gtk_cell_area_box_forall (GtkCellArea        *area,
     }
 }
 
+static void
+gtk_cell_area_box_get_cell_allocation (GtkCellArea          *area,
+				       GtkCellAreaIter      *iter,	
+				       GtkWidget            *widget,
+				       GtkCellRenderer      *renderer,
+				       const GdkRectangle   *cell_area,
+				       GdkRectangle         *allocation)
+{
+  GtkCellAreaBox        *box      = GTK_CELL_AREA_BOX (area);
+  GtkCellAreaBoxPrivate *priv     = box->priv;
+  GtkCellAreaBoxIter    *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
+  GSList                *allocated_cells, *l;
+
+  *allocation = *cell_area;
+
+  /* Get a list of cells with allocation sizes decided regardless
+   * of alignments and pack order etc. */
+  allocated_cells = get_allocated_cells (box, box_iter, widget);
+
+  for (l = allocated_cells; l; l = l->next)
+    {
+      AllocatedCell *cell = l->data;
+
+      if (cell->renderer == renderer)
+	{
+	  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+	    {
+	      allocation->x     = cell_area->x + cell->position;
+	      allocation->width = cell->size;
+	    }
+	  else
+	    {
+	      allocation->y      = cell_area->y + cell->position;
+	      allocation->height = cell->size;
+	    }
+
+	  break;
+	}
+    }
+
+  g_slist_foreach (allocated_cells, (GFunc)allocated_cell_free, NULL);
+  g_slist_free (allocated_cells);
+}
+
 static gint
 gtk_cell_area_box_event (GtkCellArea          *area,
 			 GtkCellAreaIter      *iter,
@@ -819,6 +870,27 @@ gtk_cell_area_box_event (GtkCellArea          *area,
 			 const GdkRectangle   *cell_area,
 			 GtkCellRendererState  flags)
 {
+  gint retval;
+
+  /* First let the parent class handle activation of cells via keystrokes */
+  retval = 
+    GTK_CELL_AREA_CLASS (gtk_cell_area_box_parent_class)->event (area, iter, widget,
+								 event, cell_area, flags);
+  
+  if (retval)
+    return retval;
+
+  /* Now detect keystrokes that move focus directionally inside the area
+   * or signal that focus should leave the area in a given direction.
+   *
+   * To navigate focus we only need to loop through the groups and 
+   * observe the orientation and push focus along to the next cell
+   * or signal that focus should leave the area.
+   */
+
+  /* Also detect mouse events, for mouse events we need to allocate the renderers
+   * and find which renderer needs to be activated.
+   */
 
 
   return 0;
diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list
index 88e870f..9332f3a 100644
--- a/gtk/gtkmarshalers.list
+++ b/gtk/gtkmarshalers.list
@@ -90,6 +90,7 @@ VOID:OBJECT,STRING,STRING
 VOID:OBJECT,UINT
 VOID:OBJECT,UINT,FLAGS
 VOID:OBJECT,STRING
+VOID:OBJECT,OBJECT,STRING
 VOID:OBJECT,OBJECT,OBJECT
 VOID:POINTER
 VOID:POINTER,INT



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