[gtk+/treeview-refactor] Added gtk_cell_area_activate_cell() and some cell editing management
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/treeview-refactor] Added gtk_cell_area_activate_cell() and some cell editing management
- Date: Mon, 8 Nov 2010 02:28:54 +0000 (UTC)
commit cbe1154e519a98877f40c67a9f2e686eb3f7bbef
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sat Nov 6 15:29:27 2010 +0900
Added gtk_cell_area_activate_cell() and some cell editing management
Now:
- The current edit cell and editable widget in use can be fetched
with properties and accessors
- gtk_cell_area_activate_cell() handles bookkeeping of the currently
edited cell, starting the editing of a cell, activating a cell etc
- Exported signals are available on GtkCellArea: "editing-started",
"editing-canceled", "editing-done", "remove-editable".
- Upon receiving GDK_KEY_Escape current editing gets canceled.
gtk/gtkcellarea.c | 354 +++++++++++++++++++++++++++++++++++++++++++----------
gtk/gtkcellarea.h | 23 ++--
2 files changed, 303 insertions(+), 74 deletions(-)
---
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c
index ccc1b71..f9485aa 100644
--- a/gtk/gtkcellarea.c
+++ b/gtk/gtkcellarea.c
@@ -117,6 +117,20 @@ static void cell_attribute_free (CellAttribute *attribute);
static gint cell_attribute_find (CellAttribute *cell_attribute,
const gchar *attribute);
+/* Internal signal emissions */
+static void gtk_cell_area_editing_started (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GtkCellEditable *editable);
+static void gtk_cell_area_editing_canceled (GtkCellArea *area,
+ GtkCellRenderer *renderer);
+static void gtk_cell_area_editing_done (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GtkCellEditable *editable);
+static void gtk_cell_area_remove_editable (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GtkCellEditable *editable);
+
+
/* Struct to pass data along while looping over
* cell renderers to apply attributes
*/
@@ -144,7 +158,15 @@ struct _GtkCellAreaPrivate
* of gtk_cell_area_apply_attributes() */
gchar *current_path;
+ /* Current cell being edited and editable widget used */
+ GtkCellEditable *edit_widget;
GtkCellRenderer *edited_cell;
+
+ /* Signal connections to the editable widget */
+ gulong editing_done_id;
+ gulong remove_widget_id;
+
+ /* Currently focused cell */
GtkCellRenderer *focus_cell;
guint can_focus : 1;
@@ -157,12 +179,16 @@ enum {
PROP_CELL_MARGIN_TOP,
PROP_CELL_MARGIN_BOTTOM,
PROP_FOCUS_CELL,
- PROP_EDITED_CELL
+ PROP_EDITED_CELL,
+ PROP_EDIT_WIDGET
};
enum {
SIGNAL_FOCUS_LEAVE,
SIGNAL_EDITING_STARTED,
+ SIGNAL_EDITING_CANCELED,
+ SIGNAL_EDITING_DONE,
+ SIGNAL_REMOVE_EDITABLE,
LAST_SIGNAL
};
@@ -200,6 +226,12 @@ gtk_cell_area_init (GtkCellArea *area)
priv->cell_border.bottom = 0;
priv->focus_cell = NULL;
+ priv->edited_cell = NULL;
+ priv->edit_widget = NULL;
+ priv->can_focus = FALSE;
+
+ priv->editing_done_id = 0;
+ priv->remove_widget_id = 0;
}
static void
@@ -255,6 +287,38 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
GTK_TYPE_CELL_EDITABLE,
G_TYPE_STRING);
+ cell_area_signals[SIGNAL_EDITING_CANCELED] =
+ g_signal_new (I_("editing-canceled"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0, /* No class closure here */
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_CELL_RENDERER);
+
+ cell_area_signals[SIGNAL_EDITING_DONE] =
+ g_signal_new (I_("editing-done"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0, /* No class closure here */
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_CELL_RENDERER,
+ GTK_TYPE_CELL_EDITABLE);
+
+ cell_area_signals[SIGNAL_REMOVE_EDITABLE] =
+ g_signal_new (I_("remove-editable"),
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0, /* No class closure here */
+ NULL, NULL,
+ _gtk_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE, 2,
+ GTK_TYPE_CELL_RENDERER,
+ GTK_TYPE_CELL_EDITABLE);
+
/* Properties */
g_object_class_install_property (object_class,
PROP_CELL_MARGIN_LEFT,
@@ -318,6 +382,15 @@ gtk_cell_area_class_init (GtkCellAreaClass *class)
GTK_TYPE_CELL_RENDERER,
GTK_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_EDIT_WIDGET,
+ g_param_spec_object
+ ("edit-widget",
+ P_("Edit Widget"),
+ P_("The widget currently editing the edited cell"),
+ GTK_TYPE_CELL_RENDERER,
+ GTK_PARAM_READWRITE));
+
/* Pool for Cell Properties */
if (!cell_property_pool)
cell_property_pool = g_param_spec_pool_new (FALSE);
@@ -427,6 +500,7 @@ gtk_cell_area_dispose (GObject *object)
/* 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);
+ gtk_cell_area_set_edit_widget (GTK_CELL_AREA (object), NULL);
G_OBJECT_CLASS (gtk_cell_area_parent_class)->dispose (object);
}
@@ -456,6 +530,12 @@ gtk_cell_area_set_property (GObject *object,
case PROP_FOCUS_CELL:
gtk_cell_area_set_focus_cell (area, (GtkCellRenderer *)g_value_get_object (value));
break;
+ case PROP_EDITED_CELL:
+ gtk_cell_area_set_edited_cell (area, (GtkCellRenderer *)g_value_get_object (value));
+ break;
+ case PROP_EDIT_WIDGET:
+ gtk_cell_area_set_edit_widget (area, (GtkCellEditable *)g_value_get_object (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -488,6 +568,12 @@ gtk_cell_area_get_property (GObject *object,
case PROP_FOCUS_CELL:
g_value_set_object (value, priv->focus_cell);
break;
+ case PROP_EDITED_CELL:
+ g_value_set_object (value, priv->edited_cell);
+ break;
+ case PROP_EDIT_WIDGET:
+ g_value_set_object (value, priv->edit_widget);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -517,61 +603,30 @@ gtk_cell_area_real_event (GtkCellArea *area,
key_event->keyval == GDK_KEY_ISO_Enter ||
key_event->keyval == GDK_KEY_KP_Enter))
{
- /* Activate or Edit the currently focused cell */
- GtkCellRendererMode mode;
- GdkRectangle background_area;
- GdkRectangle inner_area;
+ GdkRectangle background_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);
+ /* Activate or Edit the currently focused cell */
+ if (gtk_cell_area_activate_cell (area, widget, priv->focus_cell, event,
+ &background_area, flags))
+ return TRUE;
+ }
+ else if (priv->edited_cell &&
+ (key_event->keyval == GDK_KEY_Escape))
+ {
+ /* Cancel editing of the cell renderer */
+ gtk_cell_renderer_stop_editing (priv->edited_cell, TRUE);
- /* XXX Need to do some extra right-to-left casing either here
- * or inside the above called apis.
- */
+ /* Signal that editing has been canceled */
+ gtk_cell_area_editing_canceled (area, priv->edited_cell);
- 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;
- }
- }
+ /* Remove any references to the editable widget */
+ gtk_cell_area_set_edited_cell (area, NULL);
+ gtk_cell_area_set_edit_widget (area, NULL);
}
}
@@ -1825,6 +1880,71 @@ gtk_cell_area_get_focus_cell (GtkCellArea *area)
return priv->focus_cell;
}
+
+/*************************************************************
+ * API: Cell Activation/Editing *
+ *************************************************************/
+static void
+gtk_cell_area_editing_started (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GtkCellEditable *editable)
+{
+ g_signal_emit (area, cell_area_signals[SIGNAL_EDITING_STARTED], 0,
+ renderer, editable, area->priv->current_path);
+}
+
+static void
+gtk_cell_area_editing_canceled (GtkCellArea *area,
+ GtkCellRenderer *renderer)
+{
+ g_signal_emit (area, cell_area_signals[SIGNAL_EDITING_CANCELED], 0, renderer);
+}
+
+static void
+gtk_cell_area_editing_done (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GtkCellEditable *editable)
+{
+ g_signal_emit (area, cell_area_signals[SIGNAL_EDITING_DONE], 0, renderer, editable);
+}
+
+static void
+gtk_cell_area_remove_editable (GtkCellArea *area,
+ GtkCellRenderer *renderer,
+ GtkCellEditable *editable)
+{
+ g_signal_emit (area, cell_area_signals[SIGNAL_REMOVE_EDITABLE], 0, renderer, editable);
+}
+
+static void
+cell_area_editing_done_cb (GtkCellEditable *editable,
+ GtkCellArea *area)
+{
+ GtkCellAreaPrivate *priv = area->priv;
+
+ g_assert (priv->edit_widget == editable);
+ g_assert (priv->edited_cell != NULL);
+
+ gtk_cell_area_editing_done (area, priv->edited_cell, priv->edit_widget);
+}
+
+static void
+cell_area_remove_widget_cb (GtkCellEditable *editable,
+ GtkCellArea *area)
+{
+ GtkCellAreaPrivate *priv = area->priv;
+
+ g_assert (priv->edit_widget == editable);
+ g_assert (priv->edited_cell != NULL);
+
+ gtk_cell_area_remove_editable (area, priv->edited_cell, priv->edit_widget);
+
+ /* Now that we're done with editing the widget and it can be removed,
+ * remove our references to the widget and disconnect handlers */
+ gtk_cell_area_set_edited_cell (area, NULL);
+ gtk_cell_area_set_edit_widget (area, NULL);
+}
+
void
gtk_cell_area_set_edited_cell (GtkCellArea *area,
GtkCellRenderer *renderer)
@@ -1862,6 +1982,126 @@ gtk_cell_area_get_edited_cell (GtkCellArea *area)
return priv->edited_cell;
}
+void
+gtk_cell_area_set_edit_widget (GtkCellArea *area,
+ GtkCellEditable *editable)
+{
+ GtkCellAreaPrivate *priv;
+
+ g_return_if_fail (GTK_IS_CELL_AREA (area));
+ g_return_if_fail (editable == NULL || GTK_IS_CELL_EDITABLE (editable));
+
+ priv = area->priv;
+
+ if (priv->edit_widget != editable)
+ {
+ if (priv->edit_widget)
+ {
+ g_signal_handler_disconnect (priv->edit_widget, priv->editing_done_id);
+ g_signal_handler_disconnect (priv->edit_widget, priv->remove_widget_id);
+
+ g_object_unref (priv->edit_widget);
+ }
+
+ priv->edit_widget = editable;
+
+ if (priv->edit_widget)
+ {
+ priv->editing_done_id =
+ g_signal_connect (priv->edit_widget, "editing-done",
+ G_CALLBACK (cell_area_editing_done_cb), area);
+ priv->remove_widget_id =
+ g_signal_connect (priv->edit_widget, "remove-widget",
+ G_CALLBACK (cell_area_remove_widget_cb), area);
+
+ g_object_ref (priv->edit_widget);
+ }
+
+ g_object_notify (G_OBJECT (area), "edit-widget");
+ }
+}
+
+GtkCellEditable *
+gtk_cell_area_get_edit_widget (GtkCellArea *area)
+{
+ GtkCellAreaPrivate *priv;
+
+ g_return_val_if_fail (GTK_IS_CELL_AREA (area), NULL);
+
+ priv = area->priv;
+
+ return priv->edit_widget;
+}
+
+gboolean
+gtk_cell_area_activate_cell (GtkCellArea *area,
+ GtkWidget *widget,
+ GtkCellRenderer *renderer,
+ GdkEvent *event,
+ const GdkRectangle *cell_area,
+ GtkCellRendererState flags)
+{
+ GtkCellRendererMode mode;
+ GdkRectangle inner_area;
+ GtkCellAreaPrivate *priv;
+
+ g_return_val_if_fail (GTK_IS_CELL_AREA (area), FALSE);
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (GTK_IS_CELL_RENDERER (renderer), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+ g_return_val_if_fail (cell_area != NULL, FALSE);
+
+ priv = area->priv;
+
+ /* Remove margins from the background area to produce the cell area.
+ *
+ * XXX Maybe have to do some rtl mode treatment here...
+ */
+ gtk_cell_area_inner_cell_area (area, cell_area, &inner_area);
+
+ g_object_get (renderer, "mode", &mode, NULL);
+
+ if (mode == GTK_CELL_RENDERER_MODE_ACTIVATABLE)
+ {
+ if (gtk_cell_renderer_activate (renderer,
+ event, widget,
+ priv->current_path,
+ cell_area,
+ &inner_area,
+ flags))
+ return TRUE;
+ }
+ else if (mode == GTK_CELL_RENDERER_MODE_EDITABLE)
+ {
+ GtkCellEditable *editable_widget;
+
+ editable_widget =
+ gtk_cell_renderer_start_editing (renderer,
+ event, widget,
+ priv->current_path,
+ cell_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, renderer);
+ gtk_cell_area_set_edit_widget (area, editable_widget);
+
+ /* 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;
+ }
+ }
+
+ return FALSE;
+}
+
+
/*************************************************************
* API: Margins *
*************************************************************/
@@ -1969,25 +2209,9 @@ 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,
+ const GdkRectangle *background_area,
GdkRectangle *cell_area)
{
GtkCellAreaPrivate *priv;
diff --git a/gtk/gtkcellarea.h b/gtk/gtkcellarea.h
index 0e806df..7fc450d 100644
--- a/gtk/gtkcellarea.h
+++ b/gtk/gtkcellarea.h
@@ -277,11 +277,21 @@ 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);
+/* Cell Activation/Editing */
+void gtk_cell_area_set_edited_cell (GtkCellArea *area,
+ GtkCellRenderer *renderer);
+GtkCellRenderer *gtk_cell_area_get_edited_cell (GtkCellArea *area);
+void gtk_cell_area_set_edit_widget (GtkCellArea *area,
+ GtkCellEditable *editable);
+GtkCellEditable *gtk_cell_area_get_edit_widget (GtkCellArea *area);
+gboolean gtk_cell_area_activate_cell (GtkCellArea *area,
+ GtkWidget *widget,
+ GtkCellRenderer *renderer,
+ GdkEvent *event,
+ const GdkRectangle *cell_area,
+ GtkCellRendererState flags);
/* Margins */
gint gtk_cell_area_get_cell_margin_left (GtkCellArea *area);
@@ -299,14 +309,9 @@ 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,
+ const GdkRectangle *cell_area,
GdkRectangle *inner_cell_area);
/* Request the size of a cell while respecting the cell margins (requests are margin inclusive) */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]