[gtk+/treeview-refactor] Committing half-way done focus work.



commit 1ad5fa3e7a8f41e95057bd8e9ff8c32a5c8b8459
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Fri Nov 5 13:05:20 2010 +0900

    Committing half-way done focus work.

 gtk/gtkcellarea.c     |  183 +++++++++++++++++++++++++++++++++++++++++++++----
 gtk/gtkcellarea.h     |    4 +
 gtk/gtkcellareabox.c  |   13 +---
 gtk/gtkcellrenderer.c |   26 +++++++
 gtk/gtkcellrenderer.h |    2 +
 5 files changed, 205 insertions(+), 23 deletions(-)
---
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index 634ff49..fc30fb8 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -50,18 +50,25 @@ static void      gtk_cell_area_get_property                        (GObject
 								    GParamSpec         *pspec);
 
 /* GtkCellAreaClass */
-static void      gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea        *area,
-								    GtkCellAreaIter    *iter,
-								    GtkWidget          *widget,
-								    gint                width,
-								    gint               *minimum_height,
-								    gint               *natural_height);
-static void      gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea        *area,
-								    GtkCellAreaIter    *iter,
-								    GtkWidget          *widget,
-								    gint                height,
-								    gint               *minimum_width,
-								    gint               *natural_width);
+static gint      gtk_cell_area_real_event                          (GtkCellArea          *area,
+								    GtkCellAreaIter      *iter,
+								    GtkWidget            *widget,
+								    GdkEvent             *event,
+								    const GdkRectangle   *cell_area,
+								    GtkCellRendererState  flags);
+static void      gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea           *area,
+								    GtkCellAreaIter       *iter,
+								    GtkWidget             *widget,
+								    gint                   width,
+								    gint                  *minimum_height,
+								    gint                  *natural_height);
+static void      gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea           *area,
+								    GtkCellAreaIter       *iter,
+								    GtkWidget             *widget,
+								    gint                   height,
+								    gint                  *minimum_width,
+								    gint                  *natural_width);
+static void      gtk_cell_area_real_update_focus                   (GtkCellArea           *area);
 
 /* GtkCellLayoutIface */
 static void      gtk_cell_area_cell_layout_init              (GtkCellLayoutIface    *iface);
@@ -196,7 +203,7 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
   class->add     = NULL;
   class->remove  = NULL;
   class->forall  = NULL;
-  class->event   = NULL;
+  class->event   = gtk_cell_area_real_event;
   class->render  = NULL;
 
   /* geometry */
@@ -209,6 +216,7 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
 
   /* focus */
   class->grab_focus = NULL;
+  class->update_focus = gtk_cell_area_real_update_focus;
 
   /* Signals */
   cell_area_signals[SIGNAL_FOCUS_LEAVE] =
@@ -437,6 +445,30 @@ gtk_cell_area_get_property (GObject     *object,
 /*************************************************************
  *                    GtkCellAreaClass                       *
  *************************************************************/
+static gint
+gtk_cell_area_real_event (GtkCellArea          *area,
+			  GtkCellAreaIter      *iter,
+			  GtkWidget            *widget,
+			  GdkEvent             *event,
+			  const GdkRectangle   *cell_area,
+			  GtkCellRendererState  flags)
+{
+  if (event->type == GDK_KEY_PRESS)
+    {
+      GtkCellAreaPrivate *priv = area->priv;
+
+      if (priv->focus_cell)
+	{
+	  /* Activate of Edit the currently focused cell */
+
+
+	  return TRUE;
+	}
+    }
+
+  return FALSE;
+}
+
 static void
 gtk_cell_area_real_get_preferred_height_for_width (GtkCellArea        *area,
 						   GtkCellAreaIter    *iter,
@@ -461,6 +493,35 @@ gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea        *area,
   GTK_CELL_AREA_GET_CLASS (area)->get_preferred_width (area, iter, widget, minimum_width, natural_width);
 }
 
+static void
+update_can_focus (GtkCellRenderer *renderer,
+		  gboolean        *can_focus)
+{
+
+  if (gtk_cell_renderer_can_focus (renderer))
+    *can_focus = TRUE;
+}
+
+static void
+gtk_cell_area_real_update_focus (GtkCellArea *area)
+{
+  gboolean can_focus = FALSE;
+
+  /* Update the area's can focus flag, if any of the renderers can
+   * focus then the area can focus.
+   *
+   * Subclasses can override this in the case that they are also
+   * rendering widgets as well as renderers.
+   */
+  gtk_cell_area_forall (area, (GtkCellCallback)update_can_focus, &can_focus);
+  gtk_cell_area_set_can_focus (area, can_focus);
+
+  /* Unset the currently focused cell if the area can not receive
+   * focus for the given row data */
+  if (!can_focus)
+    gtk_cell_area_set_focus_cell (area, NULL);
+}
+
 /*************************************************************
  *                   GtkCellLayoutIface                      *
  *************************************************************/
@@ -1342,6 +1403,24 @@ gtk_cell_area_cell_get_property (GtkCellArea        *area,
 /*************************************************************
  *                         API: Focus                        *
  *************************************************************/
+
+/**
+ * gtk_cell_area_grab_focus:
+ * @area: a #GtkCellArea
+ * @direction: the #GtkDirectionType from which focus came
+ *
+ * This should be called by the @area's owning layout widget
+ * when focus should be passed to @area for a given row data.
+ *
+ * Note that after applying new attributes for @area that
+ * gtk_cell_area_update_focus() should be called and
+ * gtk_cell_area_can_focus() should be checked before trying
+ * to pass focus to @area.
+ *
+ * Implementing #GtkCellArea classes should implement this
+ * method to receive focus in it's own way particular to
+ * how it lays out cells.
+ */
 void
 gtk_cell_area_grab_focus (GtkCellArea      *area,
 			  GtkDirectionType  direction)
@@ -1359,6 +1438,24 @@ gtk_cell_area_grab_focus (GtkCellArea      *area,
 	       g_type_name (G_TYPE_FROM_INSTANCE (area)));
 }
 
+/**
+ * gtk_cell_area_focus_leave:
+ * @area: a #GtkCellArea
+ * @direction: the #GtkDirectionType in which focus
+ *             is to leave @area
+ * @path: the current #GtkTreePath string for the 
+ *        event which was handled by @area
+ *
+ * Notifies that focus is to leave @area in the
+ * given @direction.
+ *
+ * This is called by #GtkCellArea implementations upon
+ * handling a key event that caused focus to leave the
+ * cell. The resulting signal can be handled by the
+ * owning layouting widget to decide which new @area
+ * to pass focus to and from what @direction. Or to
+ * pass focus along to an entirely new data row.
+ */
 void
 gtk_cell_area_focus_leave (GtkCellArea        *area,
 			   GtkDirectionType    direction,
@@ -1369,6 +1466,35 @@ gtk_cell_area_focus_leave (GtkCellArea        *area,
   g_signal_emit (area, cell_area_signals[SIGNAL_FOCUS_LEAVE], 0, direction, path);
 }
 
+/**
+ * gtk_cell_area_update_focus:
+ * @area: a #GtkCellArea
+ *
+ * Updates focus information on @area for a given 
+ * row of data.
+ *
+ * After calling gtk_cell_area_apply_attributes() to
+ * the @area this method should be called to update
+ * information about whether the @area can focus and
+ * which is the cell currently in focus.
+ */
+void
+gtk_cell_area_update_focus (GtkCellArea *area)
+{
+  g_return_if_fail (GTK_IS_CELL_AREA (area));
+
+  GTK_CELL_AREA_GET_CLASS (area)->update_focus (area);
+}
+
+/**
+ * gtk_cell_area_set_can_focus:
+ * @area: a #GtkCellArea
+ * @can_focus: whether @area can receive focus
+ *
+ * This is generally called from GtkCellArea::update_focus() 
+ * implementations to update if the @area can focus after
+ * applying new row data attributes.
+ */
 void
 gtk_cell_area_set_can_focus (GtkCellArea *area,
 			     gboolean     can_focus)
@@ -1385,6 +1511,17 @@ gtk_cell_area_set_can_focus (GtkCellArea *area,
     }
 }
 
+/**
+ * gtk_cell_area_get_can_focus:
+ * @area: a #GtkCellArea
+ *
+ * Returns whether the area can receive keyboard focus,
+ * after applying new attributes to @area, 
+ * gtk_cell_area_update_focus() needs to be called before
+ * calling this method.
+ *
+ * Returns: whether @area can receive focus.
+ */
 gboolean
 gtk_cell_area_get_can_focus (GtkCellArea *area)
 {
@@ -1397,6 +1534,18 @@ gtk_cell_area_get_can_focus (GtkCellArea *area)
   return priv->can_focus;
 }
 
+
+/**
+ * gtk_cell_area_set_focus_cell:
+ * @area: a #GtkCellArea
+ * @focus_cell: the #GtkCellRenderer to give focus to
+ *
+ * This is generally called from #GtkCellArea implementations
+ * either gtk_cell_area_grab_focus() or gtk_cell_area_update_focus()
+ * is called. It's also up to the #GtkCellArea implementation
+ * to update the focused cell when receiving events from
+ * gtk_cell_area_event() appropriately.
+ */
 void
 gtk_cell_area_set_focus_cell (GtkCellArea     *area,
 			      GtkCellRenderer *renderer)
@@ -1420,6 +1569,14 @@ gtk_cell_area_set_focus_cell (GtkCellArea     *area,
     }
 }
 
+/**
+ * gtk_cell_area_get_focus_cell:
+ * @area: a #GtkCellArea
+ *
+ * Retrieves the currently focused cell for @area
+ *
+ * Returns: the currently focused cell in @area.
+ */
 GtkCellRenderer *
 gtk_cell_area_get_focus_cell (GtkCellArea *area)
 {
diff --git a/gtk/gtkcellarea.h b/gtk/gtkcellarea.h
index 2e80471..9c09553 100644
--- a/gtk/gtkcellarea.h
+++ b/gtk/gtkcellarea.h
@@ -133,6 +133,7 @@ struct _GtkCellAreaClass
   /* Focus */
   void               (* grab_focus)                      (GtkCellArea             *area,
 							  GtkDirectionType         direction);
+  void               (* update_focus)                    (GtkCellArea             *area);
 
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
@@ -255,6 +256,7 @@ void               gtk_cell_area_grab_focus                     (GtkCellArea
 void               gtk_cell_area_focus_leave                    (GtkCellArea        *area,
 								 GtkDirectionType    direction,
 								 const gchar        *path);
+void               gtk_cell_area_update_focus                   (GtkCellArea        *area);
 void               gtk_cell_area_set_can_focus                  (GtkCellArea        *area,
 								 gboolean            can_focus);
 gboolean           gtk_cell_area_get_can_focus                  (GtkCellArea        *area);
@@ -262,6 +264,8 @@ void               gtk_cell_area_set_focus_cell                 (GtkCellArea
 								 GtkCellRenderer    *renderer);
 GtkCellRenderer   *gtk_cell_area_get_focus_cell                 (GtkCellArea        *area);
 
+
+
 /* Margins */
 gint               gtk_cell_area_get_cell_margin_left           (GtkCellArea        *area);
 void               gtk_cell_area_set_cell_margin_left           (GtkCellArea        *area,
diff --git a/gtk/gtkcellareabox.c b/gtk/gtkcellareabox.c
index 60e4b3a..ad2f6ee 100644
--- a/gtk/gtkcellareabox.c
+++ b/gtk/gtkcellareabox.c
@@ -1465,16 +1465,9 @@ gtk_cell_area_box_grab_focus (GtkCellArea      *area,
       for (list = first_cell ? g_list_first (group->cells) : g_list_last (group->cells); 
 	   list; list = first_cell ? list->next : list->prev)
 	{
-	  GtkCellRendererMode  mode;
-	  CellInfo            *info = list->data;
-
-	  /* XXX This does not handle cases where the cell
-	   * is not visible as it is not row specific, 
-	   * that's a problem.
-	   */
-	  g_object_get (info->renderer, "mode", &mode, NULL);
-	  if (mode == GTK_CELL_RENDERER_MODE_EDITABLE ||
-	      mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
+	  CellInfo *info = list->data;
+	  
+	  if (gtk_cell_renderer_can_focus (info->renderer))
 	    {
 	      gtk_cell_area_set_focus_cell (area, info->renderer);
 	      break;
diff --git a/gtk/gtkcellrenderer.c b/gtk/gtkcellrenderer.c
index 3656599..da6c77c 100644
--- a/gtk/gtkcellrenderer.c
+++ b/gtk/gtkcellrenderer.c
@@ -1058,6 +1058,32 @@ gtk_cell_renderer_get_sensitive (GtkCellRenderer *cell)
   return cell->priv->sensitive;
 }
 
+
+/**
+ * gtk_cell_renderer_can_focus:
+ * @cell: A #GtkCellRenderer
+ *
+ * Checks whether the cell renderer can receive focus.
+ *
+ * Returns: %TRUE if the cell renderer can do anything with keyboard focus
+ *
+ * Since: 3.0
+ */
+gboolean
+gtk_cell_renderer_can_focus (GtkCellRenderer *cell)
+{
+  GtkCellRendererPrivate *priv;
+
+  g_return_val_if_fail (GTK_IS_CELL_RENDERER (cell), FALSE);
+
+  priv = cell->priv;
+
+  return (cell->priv->visible &&
+	  (cell->priv->mode == GTK_CELL_RENDERER_MODE_EDITABLE ||
+	   cell->priv->mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE));
+}
+
+
 /**
  * gtk_cell_renderer_stop_editing:
  * @cell: A #GtkCellRenderer
diff --git a/gtk/gtkcellrenderer.h b/gtk/gtkcellrenderer.h
index 4436277..407d357 100644
--- a/gtk/gtkcellrenderer.h
+++ b/gtk/gtkcellrenderer.h
@@ -213,6 +213,8 @@ void             gtk_cell_renderer_set_sensitive  (GtkCellRenderer      *cell,
                                                    gboolean              sensitive);
 gboolean         gtk_cell_renderer_get_sensitive  (GtkCellRenderer      *cell);
 
+gboolean         gtk_cell_renderer_can_focus      (GtkCellRenderer      *cell);
+
 /* For use by cell renderer implementations only */
 void             gtk_cell_renderer_stop_editing   (GtkCellRenderer      *cell,
                                                    gboolean              canceled);



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