[gtk+/treeview-refactor] Ironed out the kinks in editing apis for GtkCellArea



commit 38666b406fe8b2f08e0d67014daea951c6efea73
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Fri Nov 12 19:25:07 2010 +0900

    Ironed out the kinks in editing apis for GtkCellArea
    
     - Added gtk_cell_area_aligned_cell_area() to get the aligned
       internal area use by a cell (for focus painting and for
       event areas).
    
     - Provide the event area in "editing-started" signal
    
     - Fire "remove-editable" when editing is canceled by the user,
       an implementing layouting widget need only catch "editing-started"
       and "remove-editable" now.
    
     - CellAreaScaffold/testcellarea now edit textrenderers.

 gtk/gtkcellarea.c        |   96 ++++++++++++++++++++----
 gtk/gtkcellarea.h        |   10 ++-
 gtk/gtkcellareabox.c     |   65 +++++-----------
 gtk/gtkmarshalers.list   |    1 +
 tests/cellareascaffold.c |  187 ++++++++++++++++++++++++++++++++++++++--------
 tests/cellareascaffold.h |    4 +-
 tests/testcellarea.c     |   23 +++++-
 7 files changed, 290 insertions(+), 96 deletions(-)
---
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index 95eca93..7427254 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -132,7 +132,8 @@ static gint            cell_attribute_find (CellAttribute         *cell_attribut
 /* Internal signal emissions */
 static void            gtk_cell_area_editing_started  (GtkCellArea        *area,
 						       GtkCellRenderer    *renderer,
-						       GtkCellEditable    *editable);
+						       GtkCellEditable    *editable,
+						       GdkRectangle       *cell_area);
 static void            gtk_cell_area_editing_canceled (GtkCellArea        *area,
 						       GtkCellRenderer    *renderer);
 static void            gtk_cell_area_editing_done     (GtkCellArea        *area,
@@ -292,10 +293,11 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
 		  G_SIGNAL_RUN_FIRST,
 		  0, /* No class closure here */
 		  NULL, NULL,
-		  _gtk_marshal_VOID__OBJECT_OBJECT_STRING,
-		  G_TYPE_NONE, 3,
+		  _gtk_marshal_VOID__OBJECT_OBJECT_BOXED_STRING,
+		  G_TYPE_NONE, 4,
 		  GTK_TYPE_CELL_RENDERER,
 		  GTK_TYPE_CELL_EDITABLE,
+		  GDK_TYPE_RECTANGLE,
 		  G_TYPE_STRING);
 
   cell_area_signals[SIGNAL_EDITING_CANCELED] =
@@ -2079,10 +2081,11 @@ gtk_cell_area_get_focus_from_sibling (GtkCellArea          *area,
 static void
 gtk_cell_area_editing_started (GtkCellArea        *area,
 			       GtkCellRenderer    *renderer,
-			       GtkCellEditable    *editable)
+			       GtkCellEditable    *editable,
+			       GdkRectangle       *cell_area)
 {
   g_signal_emit (area, cell_area_signals[SIGNAL_EDITING_STARTED], 0, 
-		 renderer, editable, area->priv->current_path);
+		 renderer, editable, cell_area, area->priv->current_path);
 }
 
 static void
@@ -2276,14 +2279,18 @@ gtk_cell_area_activate_cell (GtkCellArea          *area,
       
       if (editable_widget != NULL)
 	{
+	  GdkRectangle edit_area;
+
 	  g_return_val_if_fail (GTK_IS_CELL_EDITABLE (editable_widget), FALSE);
 	  
 	  gtk_cell_area_set_edited_cell (area, renderer);
 	  gtk_cell_area_set_edit_widget (area, editable_widget);
+
+	  gtk_cell_area_aligned_cell_area (area, widget, renderer, &inner_area, &edit_area);
 	  
 	  /* 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);
+	  gtk_cell_area_editing_started (area, priv->focus_cell, editable_widget, &edit_area);
 	  
 	  return TRUE;
 	}
@@ -2304,9 +2311,12 @@ gtk_cell_area_stop_editing (GtkCellArea *area,
 
   if (priv->edited_cell)
     {
+      GtkCellEditable *edit_widget = g_object_ref (priv->edit_widget);
+      GtkCellRenderer *edit_cell   = g_object_ref (priv->edited_cell);
+
       /* Stop editing of the cell renderer */
       gtk_cell_renderer_stop_editing (priv->edited_cell, canceled);
-      
+
       /* Signal that editing has been canceled */
       if (canceled)
 	gtk_cell_area_editing_canceled (area, priv->edited_cell);	
@@ -2314,6 +2324,13 @@ gtk_cell_area_stop_editing (GtkCellArea *area,
       /* Remove any references to the editable widget */
       gtk_cell_area_set_edited_cell (area, NULL);
       gtk_cell_area_set_edit_widget (area, NULL);
+
+      /* Send the remove-widget signal explicitly (this is done after setting
+       * the edit cell/widget NULL to avoid feedback)
+       */
+      gtk_cell_area_remove_editable (area, edit_cell, edit_widget);
+      g_object_unref (edit_cell);
+      g_object_unref (edit_widget);
     }
 }
 
@@ -2426,23 +2443,72 @@ gtk_cell_area_set_cell_margin_bottom (GtkCellArea *area,
 
 void
 gtk_cell_area_inner_cell_area (GtkCellArea        *area,
-			       const GdkRectangle *background_area,
-			       GdkRectangle       *cell_area)
+			       const GdkRectangle *cell_area,
+			       GdkRectangle       *inner_area)
 {
   GtkCellAreaPrivate *priv;
 
   g_return_if_fail (GTK_IS_CELL_AREA (area));
-  g_return_if_fail (background_area != NULL);
   g_return_if_fail (cell_area != NULL);
+  g_return_if_fail (inner_area != NULL);
 
   priv = area->priv;
 
-  *cell_area = *background_area;
+  *inner_area = *cell_area;
+
+  inner_area->x      += priv->cell_border.left;
+  inner_area->width  -= (priv->cell_border.left + priv->cell_border.right);
+  inner_area->y      += priv->cell_border.top;
+  inner_area->height -= (priv->cell_border.top + priv->cell_border.bottom);
+}
+
+void
+gtk_cell_area_aligned_cell_area (GtkCellArea        *area,
+				 GtkWidget          *widget,
+				 GtkCellRenderer    *renderer,
+				 const GdkRectangle *cell_area,
+				 GdkRectangle       *aligned_area)
+{
+  GtkCellAreaPrivate *priv;
+  gint                opposite_size, x_offset, y_offset;
+
+  g_return_if_fail (GTK_IS_CELL_AREA (area));
+  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (cell_area != NULL);
+  g_return_if_fail (aligned_area != NULL);
+
+  priv = area->priv;
+
+  *aligned_area = *cell_area;
+
+  /* Trim up the aligned size */
+  if (gtk_cell_renderer_get_request_mode (renderer) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+    {
+      gtk_cell_renderer_get_preferred_height_for_width (renderer, widget, 
+							aligned_area->width, 
+							NULL, &opposite_size);
+
+      aligned_area->height = MIN (opposite_size, aligned_area->height);
+    }
+  else
+    {
+      gtk_cell_renderer_get_preferred_width_for_height (renderer, widget, 
+							aligned_area->height, 
+							NULL, &opposite_size);
+
+      aligned_area->width = MIN (opposite_size, aligned_area->width);
+    }
+
+  /* offset the cell position */
+  _gtk_cell_renderer_calc_offset (renderer, cell_area, 
+				  gtk_widget_get_direction (widget),
+				  aligned_area->width, 
+				  aligned_area->height,
+				  &x_offset, &y_offset);
 
-  cell_area->x      += priv->cell_border.left;
-  cell_area->width  -= (priv->cell_border.left + priv->cell_border.right);
-  cell_area->y      += priv->cell_border.top;
-  cell_area->height -= (priv->cell_border.top + priv->cell_border.bottom);
+  aligned_area->x += x_offset;
+  aligned_area->y += y_offset;
 }
 
 void
diff --git a/gtk/gtkcellarea.h b/gtk/gtkcellarea.h
index 6688451..2ef9178 100644
--- a/gtk/gtkcellarea.h
+++ b/gtk/gtkcellarea.h
@@ -343,7 +343,15 @@ void                  gtk_cell_area_set_cell_margin_bottom         (GtkCellArea
 /* Distinguish the inner cell area from the whole requested area including margins */
 void                  gtk_cell_area_inner_cell_area                (GtkCellArea        *area,
 								    const GdkRectangle *cell_area,
-								    GdkRectangle       *inner_cell_area);
+								    GdkRectangle       *inner_area);
+
+/* Aligns a cell renderer into cell_area by requesting it's size ... used for focus and cell edit areas */
+void                  gtk_cell_area_aligned_cell_area              (GtkCellArea        *area,
+								    GtkWidget          *widget,
+								    GtkCellRenderer    *renderer,
+								    const GdkRectangle *cell_area,
+								    GdkRectangle       *aligned_area);
+
 
 /* Request the size of a cell while respecting the cell margins (requests are margin inclusive) */
 void                  gtk_cell_area_request_renderer               (GtkCellArea        *area,
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index 7fbcf9b..a6f6acd 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -903,11 +903,8 @@ gtk_cell_area_box_event (GtkCellArea          *area,
 	  GtkCellAreaBoxIter    *box_iter = GTK_CELL_AREA_BOX_ITER (iter);
 	  GSList                *allocated_cells, *l;
 	  GdkRectangle           cell_background, inner_area;
-	  GtkAllocation          allocation;
 	  gint                   event_x, event_y;
 
-	  gtk_widget_get_allocation (widget, &allocation);
-
 	  /* We may need some semantics to tell us the offset of the event
 	   * window we are handling events for (i.e. GtkTreeView has a bin_window) */
 	  event_x = button_event->x;
@@ -1025,6 +1022,7 @@ gtk_cell_area_box_render (GtkCellArea          *area,
     {
       AllocatedCell       *cell = l->data;
       GtkCellRendererState cell_fields = 0;
+      GdkRectangle         render_background;
 
       if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
 	{
@@ -1041,37 +1039,39 @@ gtk_cell_area_box_render (GtkCellArea          *area,
        */
       gtk_cell_area_inner_cell_area (area, &cell_background, &inner_area);
 
-      /* Here after getting the inner area of the cell background,
-       * add portions of the background area to the cell background */
+      /* Add portions of the background_area to the cell_background
+       * to create the render_background */
+      render_background = cell_background;
+
       if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
 	{
 	  if (l == allocated_cells)
 	    {
-	      cell_background.width += cell_background.x - background_area->x;
-	      cell_background.x      = background_area->x;
+	      render_background.width += render_background.x - background_area->x;
+	      render_background.x      = background_area->x;
 	    }
 
 	  if (l->next == NULL)
-	      cell_background.width = 
-		background_area->width - (cell_background.x - background_area->x);
+	      render_background.width = 
+		background_area->width - (render_background.x - background_area->x);
 
-	  cell_background.y      = background_area->y;
-	  cell_background.height = background_area->height;
+	  render_background.y      = background_area->y;
+	  render_background.height = background_area->height;
 	}
       else
 	{
 	  if (l == allocated_cells)
 	    {
-	      cell_background.height += cell_background.y - background_area->y;
-	      cell_background.y       = background_area->y;
+	      render_background.height += render_background.y - background_area->y;
+	      render_background.y       = background_area->y;
 	    }
 
 	  if (l->next == NULL)
-	      cell_background.height = 
-		background_area->height - (cell_background.y - background_area->y);
+	      render_background.height = 
+		background_area->height - (render_background.y - background_area->y);
 
-	  cell_background.x     = background_area->x;
-	  cell_background.width = background_area->width;
+	  render_background.x     = background_area->x;
+	  render_background.width = background_area->width;
 	}
 
       if (focus_cell && 
@@ -1083,35 +1083,8 @@ gtk_cell_area_box_render (GtkCellArea          *area,
 	  if (paint_focus)
 	    {
 	      GdkRectangle cell_focus;
-	      gint         opposite_size, x_offset, y_offset;
-
-	      cell_focus = inner_area;
-
-	      /* Trim up the focus size */
-	      if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
-		{
-		  gtk_cell_renderer_get_preferred_height_for_width (cell->renderer, widget, 
-								    cell_focus.width, 
-								    NULL, &opposite_size);
-
-		  cell_focus.height = MIN (opposite_size, cell_focus.height);
-		}
-	      else
-		{
-		  gtk_cell_renderer_get_preferred_width_for_height (cell->renderer, widget, 
-								    cell_focus.height, 
-								    NULL, &opposite_size);
-
-		  cell_focus.width = MIN (opposite_size, cell_focus.width);
-		}
-
-	      /* offset the cell position */
-	      _gtk_cell_renderer_calc_offset (cell->renderer, &inner_area, GTK_TEXT_DIR_LTR,
-					      cell_focus.width, cell_focus.height,
-					      &x_offset, &y_offset);
 
-	      cell_focus.x += x_offset;
-	      cell_focus.y += y_offset;
+	      gtk_cell_area_aligned_cell_area (area, widget, cell->renderer, &inner_area, &cell_focus);
 
 	      /* Accumulate the focus rectangle for all focus siblings */
 	      if (first_focus_cell)
@@ -1127,7 +1100,7 @@ gtk_cell_area_box_render (GtkCellArea          *area,
       /* We have to do some per-cell considerations for the 'flags'
        * for focus handling */
       gtk_cell_renderer_render (cell->renderer, cr, widget,
-				&cell_background, &inner_area,
+				&render_background, &inner_area,
 				flags | cell_fields);
     }
 
diff --git a/gtk/gtkmarshalers.list b/gtk/gtkmarshalers.list
index 9332f3a..248bd6e 100644
--- a/gtk/gtkmarshalers.list
+++ b/gtk/gtkmarshalers.list
@@ -92,6 +92,7 @@ VOID:OBJECT,UINT,FLAGS
 VOID:OBJECT,STRING
 VOID:OBJECT,OBJECT,STRING
 VOID:OBJECT,OBJECT,OBJECT
+VOID:OBJECT,OBJECT,BOXED,STRING
 VOID:POINTER
 VOID:POINTER,INT
 VOID:POINTER,BOOLEAN
diff --git a/tests/cellareascaffold.c b/tests/cellareascaffold.c
index 3e3787a..66750b0 100644
--- a/tests/cellareascaffold.c
+++ b/tests/cellareascaffold.c
@@ -64,6 +64,19 @@ static gint      cell_area_scaffold_focus                          (GtkWidget
 static gboolean  cell_area_scaffold_button_press                   (GtkWidget       *widget,
 								    GdkEventButton  *event);
 
+/* GtkContainerClass */
+static void      cell_area_scaffold_forall                         (GtkContainer    *container,
+								    gboolean         include_internals,
+								    GtkCallback      callback,
+								    gpointer         callback_data);
+static void      cell_area_scaffold_remove                         (GtkContainer    *container,
+								    GtkWidget       *child);
+static void      cell_area_scaffold_put_edit_widget                (CellAreaScaffold *scaffold,
+								    GtkWidget        *edit_widget,
+								    gint              x,
+								    gint              y,
+								    gint              width,
+								    gint              height);
 
 /* CellAreaScaffoldClass */
 static void      cell_area_scaffold_activate                       (CellAreaScaffold *scaffold);
@@ -76,22 +89,32 @@ static void      focus_changed_cb                                  (GtkCellArea
 								    GtkCellRenderer  *renderer,
 								    const gchar      *path,
 								    CellAreaScaffold *scaffold);
+static void      editing_started_cb                                (GtkCellArea      *area,
+								    GtkCellRenderer  *renderer,
+								    GtkCellEditable  *edit_widget,
+								    GdkRectangle     *cell_area,
+								    const gchar      *path,
+								    CellAreaScaffold *scaffold);
+static void      remove_editable_cb                                (GtkCellArea      *area,
+								    GtkCellRenderer  *renderer,
+								    GtkCellEditable  *edit_widget,
+								    CellAreaScaffold *scaffold);
 static void      row_changed_cb                                    (GtkTreeModel     *model,
 								    GtkTreePath      *path,
 								    GtkTreeIter      *iter,
 								    CellAreaScaffold *scaffold);
-static void      row_inserted_cb                                    (GtkTreeModel     *model,
-								     GtkTreePath      *path,
-								     GtkTreeIter      *iter,
-								     CellAreaScaffold *scaffold);
-static void      row_deleted_cb                                     (GtkTreeModel     *model,
-								     GtkTreePath      *path,
-								     CellAreaScaffold *scaffold);
-static void      rows_reordered_cb                                  (GtkTreeModel     *model,
-								     GtkTreePath      *parent,
-								     GtkTreeIter      *iter,
-								     gint             *new_order,
-								     CellAreaScaffold *scaffold);
+static void      row_inserted_cb                                   (GtkTreeModel     *model,
+								    GtkTreePath      *path,
+								    GtkTreeIter      *iter,
+								    CellAreaScaffold *scaffold);
+static void      row_deleted_cb                                    (GtkTreeModel     *model,
+								    GtkTreePath      *path,
+								    CellAreaScaffold *scaffold);
+static void      rows_reordered_cb                                 (GtkTreeModel     *model,
+								    GtkTreePath      *parent,
+								    GtkTreeIter      *iter,
+								    gint             *new_order,
+								    CellAreaScaffold *scaffold);
 
 typedef struct {
   gint    size; /* The size of the row in the scaffold's opposing orientation */
@@ -124,7 +147,11 @@ struct _CellAreaScaffoldPrivate {
    * we need to queue a redraw */
   gulong           size_changed_id;
 
-
+  /* Currently edited widget */
+  GtkWidget       *edit_widget;
+  GdkRectangle     edit_rect;
+  gulong           editing_started_id;
+  gulong           remove_editable_id;
 };
 
 enum {
@@ -149,7 +176,7 @@ static guint scaffold_signals[N_SIGNALS] = { 0 };
    (dir) == GTK_DIR_LEFT         ? "left" :		\
    (dir) == GTK_DIR_RIGHT        ? "right" : "invalid")
 
-G_DEFINE_TYPE_WITH_CODE (CellAreaScaffold, cell_area_scaffold, GTK_TYPE_WIDGET,
+G_DEFINE_TYPE_WITH_CODE (CellAreaScaffold, cell_area_scaffold, GTK_TYPE_CONTAINER,
 			 G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL));
 
 
@@ -171,28 +198,39 @@ cell_area_scaffold_init (CellAreaScaffold *scaffold)
   gtk_widget_set_has_window (GTK_WIDGET (scaffold), FALSE);
   gtk_widget_set_can_focus (GTK_WIDGET (scaffold), TRUE);
 
+  priv->size_changed_id = 
+    g_signal_connect (priv->iter, "notify",
+		      G_CALLBACK (size_changed_cb), scaffold);
+
   priv->focus_changed_id =
     g_signal_connect (priv->area, "focus-changed",
 		      G_CALLBACK (focus_changed_cb), scaffold);
 
-  priv->size_changed_id = 
-    g_signal_connect (priv->iter, "notify",
-		      G_CALLBACK (size_changed_cb), scaffold);
+  priv->editing_started_id =
+    g_signal_connect (priv->area, "editing-started",
+		      G_CALLBACK (editing_started_cb), scaffold);
+
+  priv->remove_editable_id =
+    g_signal_connect (priv->area, "remove-editable",
+		      G_CALLBACK (remove_editable_cb), scaffold);
+
+
 }
 
 static void
 cell_area_scaffold_class_init (CellAreaScaffoldClass *class)
 {
-  GObjectClass   *gobject_class;
-  GtkWidgetClass *widget_class;
+  GObjectClass      *gobject_class;
+  GtkWidgetClass    *widget_class;
+  GtkContainerClass *container_class;
 
-  gobject_class = G_OBJECT_CLASS(class);
+  gobject_class = G_OBJECT_CLASS (class);
   gobject_class->dispose = cell_area_scaffold_dispose;
   gobject_class->finalize = cell_area_scaffold_finalize;
   gobject_class->get_property = cell_area_scaffold_get_property;
   gobject_class->set_property = cell_area_scaffold_set_property;
 
-  widget_class = GTK_WIDGET_CLASS(class);
+  widget_class = GTK_WIDGET_CLASS (class);
   widget_class->realize = cell_area_scaffold_realize;
   widget_class->unrealize = cell_area_scaffold_unrealize;
   widget_class->draw = cell_area_scaffold_draw;
@@ -206,6 +244,10 @@ cell_area_scaffold_class_init (CellAreaScaffoldClass *class)
   widget_class->focus = cell_area_scaffold_focus;
   widget_class->button_press_event = cell_area_scaffold_button_press;
 
+  container_class = GTK_CONTAINER_CLASS (class);
+  container_class->forall = cell_area_scaffold_forall;
+  container_class->remove = cell_area_scaffold_remove;
+
   class->activate = cell_area_scaffold_activate;
 
   g_object_class_override_property (gobject_class, PROP_ORIENTATION, "orientation");
@@ -264,6 +306,8 @@ cell_area_scaffold_dispose (GObject *object)
     {
       /* Disconnect signals */
       g_signal_handler_disconnect (priv->area, priv->focus_changed_id);
+      g_signal_handler_disconnect (priv->area, priv->editing_started_id);
+      g_signal_handler_disconnect (priv->area, priv->remove_editable_id);
 
       g_object_unref (priv->area);
       priv->area = NULL;
@@ -443,6 +487,9 @@ cell_area_scaffold_draw (GtkWidget       *widget,
       valid = gtk_tree_model_iter_next (priv->model, &iter);
     }
 
+  /* Draw the edit widget after drawing everything else */
+  GTK_WIDGET_CLASS (cell_area_scaffold_parent_class)->draw (widget, cr);
+
   return FALSE;
 }
 
@@ -538,6 +585,10 @@ cell_area_scaffold_size_allocate (GtkWidget           *widget,
                             allocation->width,
                             allocation->height);
 
+  /* Allocate the child GtkCellEditable widget if one is currently editing a row */
+  if (priv->edit_widget)
+    gtk_widget_size_allocate (priv->edit_widget, &priv->edit_rect);
+
   if (!priv->model)
     return;
 
@@ -546,13 +597,13 @@ cell_area_scaffold_size_allocate (GtkWidget           *widget,
   /* Cache the per-row sizes and allocate the iter */
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
-      get_row_sizes (scaffold, priv->row_data, allocation->width);
       gtk_cell_area_iter_allocate_width (priv->iter, allocation->width);
+      get_row_sizes (scaffold, priv->row_data, allocation->width);
     }
   else
     {
-      get_row_sizes (scaffold, priv->row_data, allocation->height);
       gtk_cell_area_iter_allocate_height (priv->iter, allocation->height);
+      get_row_sizes (scaffold, priv->row_data, allocation->height);
     }
 }
 
@@ -892,8 +943,8 @@ cell_area_scaffold_button_press (GtkWidget       *widget,
 	{
 	  event_area.height = data->size;
 
-	  if (event->y >= allocation.y + event_area.y && 
-	      event->y <= allocation.y + event_area.y + event_area.height)
+	  if (event->y >= event_area.y && 
+	      event->y <= event_area.y + event_area.height)
 	    {
 	      /* XXX A real implementation would assemble GtkCellRendererState flags here */
 	      gtk_cell_area_apply_attributes (priv->area, priv->model, &iter, FALSE, FALSE);
@@ -909,8 +960,8 @@ cell_area_scaffold_button_press (GtkWidget       *widget,
 	{
 	  event_area.width = data->size;
 
-	  if (event->x >= allocation.x + event_area.x && 
-	      event->x <= allocation.x + event_area.x + event_area.width)
+	  if (event->x >= event_area.x && 
+	      event->x <= event_area.x + event_area.width)
 	    {
 	      /* XXX A real implementation would assemble GtkCellRendererState flags here */
 	      gtk_cell_area_apply_attributes (priv->area, priv->model, &iter, FALSE, FALSE);
@@ -930,6 +981,55 @@ cell_area_scaffold_button_press (GtkWidget       *widget,
   return handled;
 }
 
+
+/*********************************************************
+ *                   GtkContainerClass                   *
+ *********************************************************/
+static void
+cell_area_scaffold_put_edit_widget (CellAreaScaffold *scaffold,
+				    GtkWidget        *edit_widget,
+				    gint              x,
+				    gint              y,
+				    gint              width,
+				    gint              height)
+{
+  CellAreaScaffoldPrivate *priv = scaffold->priv;
+
+  priv->edit_rect.x      = x;
+  priv->edit_rect.y      = y;
+  priv->edit_rect.width  = width;
+  priv->edit_rect.height = height;
+  priv->edit_widget      = edit_widget;
+
+  gtk_widget_set_parent (edit_widget, GTK_WIDGET (scaffold));
+}
+
+static void
+cell_area_scaffold_forall (GtkContainer    *container,
+			   gboolean         include_internals,
+			   GtkCallback      callback,
+			   gpointer         callback_data)
+{
+  CellAreaScaffold        *scaffold = CELL_AREA_SCAFFOLD (container);
+  CellAreaScaffoldPrivate *priv     = scaffold->priv;
+
+  if (priv->edit_widget)
+    (* callback) (priv->edit_widget, callback_data);
+}
+
+static void
+cell_area_scaffold_remove (GtkContainer    *container,
+			   GtkWidget       *child)
+{
+  CellAreaScaffold        *scaffold = CELL_AREA_SCAFFOLD (container);
+  CellAreaScaffoldPrivate *priv     = scaffold->priv;
+
+  g_return_if_fail (child == priv->edit_widget);
+
+  gtk_widget_unparent (priv->edit_widget);
+  priv->edit_widget = NULL;
+}
+
 /*********************************************************
  *                CellAreaScaffoldClass                  *
  *********************************************************/
@@ -1005,7 +1105,6 @@ focus_changed_cb (GtkCellArea      *area,
   CellAreaScaffoldPrivate *priv = scaffold->priv;
   GtkWidget               *widget = GTK_WIDGET (scaffold);
   GtkTreePath             *treepath;
-  gboolean                 found = FALSE;
   gint                    *indices;
 
   if (!priv->model)
@@ -1023,8 +1122,6 @@ focus_changed_cb (GtkCellArea      *area,
 
   gtk_tree_path_free (treepath);
 
-  g_print ("Focus changed signal, new focus row %d\n", priv->focus_row);
-
   /* Make sure we have focus now */
   if (!gtk_widget_has_focus (widget))
     gtk_widget_grab_focus (widget);
@@ -1032,6 +1129,36 @@ focus_changed_cb (GtkCellArea      *area,
   gtk_widget_queue_draw (widget);
 }
 
+static void
+editing_started_cb (GtkCellArea      *area,
+		    GtkCellRenderer  *renderer,
+		    GtkCellEditable  *edit_widget,
+		    GdkRectangle     *cell_area,
+		    const gchar      *path,
+		    CellAreaScaffold *scaffold)
+{
+  GtkAllocation allocation;
+
+  gtk_widget_get_allocation (GTK_WIDGET (scaffold), &allocation);
+
+  cell_area_scaffold_put_edit_widget (scaffold, GTK_WIDGET (edit_widget),
+				      allocation.x + cell_area->x, 
+				      allocation.y + cell_area->y, 
+				      cell_area->width, cell_area->height);
+
+  gtk_cell_editable_start_editing (edit_widget, NULL);
+  gtk_widget_grab_focus (GTK_WIDGET (edit_widget));
+}
+
+static void
+remove_editable_cb (GtkCellArea      *area,
+		    GtkCellRenderer  *renderer,
+		    GtkCellEditable  *edit_widget,
+		    CellAreaScaffold *scaffold)
+{
+  gtk_container_remove (GTK_CONTAINER (scaffold), GTK_WIDGET (edit_widget));
+}
+
 static void 
 rebuild_and_flush_internals (CellAreaScaffold *scaffold)
 {
diff --git a/tests/cellareascaffold.h b/tests/cellareascaffold.h
index 411ecf8..cf9fa06 100644
--- a/tests/cellareascaffold.h
+++ b/tests/cellareascaffold.h
@@ -43,14 +43,14 @@ typedef struct _CellAreaScaffoldPrivate  CellAreaScaffoldPrivate;
 
 struct _CellAreaScaffold
 {
-  GtkWidget widget;
+  GtkContainer widget;
 
   CellAreaScaffoldPrivate *priv;
 };
 
 struct _CellAreaScaffoldClass
 {
-  GtkWidgetClass parent_class;
+  GtkContainerClass parent_class;
 
   void  (* activate) (CellAreaScaffold *scaffold);
 };
diff --git a/tests/testcellarea.c b/tests/testcellarea.c
index 0acf2eb..c6db6ae 100644
--- a/tests/testcellarea.c
+++ b/tests/testcellarea.c
@@ -291,7 +291,7 @@ focus_list_model (void)
 
 static void
 cell_toggled (GtkCellRendererToggle *cell_renderer,
-	      gchar                 *path,
+	      const gchar           *path,
 	      CellAreaScaffold      *scaffold)
 {
   GtkTreeModel *model = cell_area_scaffold_get_model (scaffold);
@@ -307,6 +307,23 @@ cell_toggled (GtkCellRendererToggle *cell_renderer,
   gtk_list_store_set (GTK_LIST_STORE (model), &iter, FOCUS_COLUMN_CHECK, !active, -1);
 }
 
+static void
+cell_edited (GtkCellRendererToggle *cell_renderer,
+	     const gchar           *path,
+	     const gchar           *new_text,
+	     CellAreaScaffold      *scaffold)
+{
+  GtkTreeModel *model = cell_area_scaffold_get_model (scaffold);
+  GtkTreeIter   iter;
+
+  g_print ("Cell edited with new text '%s' !\n", new_text);
+
+  if (!gtk_tree_model_get_iter_from_string (model, &iter, path))
+    return;
+
+  gtk_list_store_set (GTK_LIST_STORE (model), &iter, FOCUS_COLUMN_NAME, new_text, -1);
+}
+
 static GtkWidget *
 focus_scaffold (void)
 {
@@ -329,7 +346,9 @@ focus_scaffold (void)
   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area), renderer, TRUE, FALSE);
   gtk_cell_area_attribute_connect (area, renderer, "text", FOCUS_COLUMN_NAME);
 
-  /* Catch signal ... */
+  g_signal_connect (G_OBJECT (renderer), "edited",
+		    G_CALLBACK (cell_edited), scaffold);
+
   focus_renderer = renderer = gtk_cell_renderer_toggle_new ();
   g_object_set (G_OBJECT (renderer), "xalign", 0.0F, NULL);
   gtk_cell_area_box_pack_start (GTK_CELL_AREA_BOX (area), renderer, FALSE, TRUE);



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