[gtk+/treeview-refactor] Committing half-way done focus work.
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/treeview-refactor] Committing half-way done focus work.
- Date: Fri, 5 Nov 2010 13:16:05 +0000 (UTC)
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]