diff options
author | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2010-11-10 19:17:06 +0900 |
---|---|---|
committer | Tristan Van Berkom <tristan.van.berkom@gmail.com> | 2010-11-10 19:17:06 +0900 |
commit | 4643d90c5faaeacbd099359082b366e86e8d6de2 (patch) | |
tree | 61e129de00f6c668d5efdf3eba60664bcf324ef2 /gtk/gtkcellarea.c | |
parent | c51bfe87570fa1b3b9750468bbd0ec7789aaec8f (diff) | |
download | gtk+-4643d90c5faaeacbd099359082b366e86e8d6de2.tar.gz |
Committing new (and simplified) focus handling approach for GtkCellArea.
Also adding missing file cellareascaffold.h
Diffstat (limited to 'gtk/gtkcellarea.c')
-rw-r--r-- | gtk/gtkcellarea.c | 244 |
1 files changed, 94 insertions, 150 deletions
diff --git a/gtk/gtkcellarea.c b/gtk/gtkcellarea.c index 4032369131..81d6f826d1 100644 --- a/gtk/gtkcellarea.c +++ b/gtk/gtkcellarea.c @@ -68,7 +68,12 @@ static void gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea gint height, gint *minimum_width, gint *natural_width); -static void gtk_cell_area_real_update_focus (GtkCellArea *area); +static gboolean gtk_cell_area_real_can_focus (GtkCellArea *area); +static gboolean gtk_cell_area_real_activate (GtkCellArea *area, + GtkCellAreaIter *iter, + GtkWidget *widget, + const GdkRectangle *cell_area, + GtkCellRendererState flags); /* GtkCellLayoutIface */ static void gtk_cell_area_cell_layout_init (GtkCellLayoutIface *iface); @@ -168,8 +173,6 @@ struct _GtkCellAreaPrivate /* Currently focused cell */ GtkCellRenderer *focus_cell; - guint can_focus : 1; - }; enum { @@ -184,7 +187,6 @@ enum { }; enum { - SIGNAL_FOCUS_LEAVE, SIGNAL_EDITING_STARTED, SIGNAL_EDITING_CANCELED, SIGNAL_EDITING_DONE, @@ -228,7 +230,6 @@ gtk_cell_area_init (GtkCellArea *area) 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; @@ -261,20 +262,11 @@ gtk_cell_area_class_init (GtkCellAreaClass *class) class->get_preferred_width_for_height = gtk_cell_area_real_get_preferred_width_for_height; /* focus */ - class->grab_focus = NULL; - class->update_focus = gtk_cell_area_real_update_focus; + class->can_focus = gtk_cell_area_real_can_focus; + class->focus = NULL; + class->activate = gtk_cell_area_real_activate; /* Signals */ - cell_area_signals[SIGNAL_FOCUS_LEAVE] = - g_signal_new (I_("focus-leave"), - G_TYPE_FROM_CLASS (object_class), - G_SIGNAL_RUN_LAST, - 0, /* Class offset (just a notification, no class handler) */ - NULL, NULL, - _gtk_marshal_VOID__ENUM_STRING, - 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), @@ -591,32 +583,14 @@ gtk_cell_area_real_event (GtkCellArea *area, const GdkRectangle *cell_area, GtkCellRendererState flags) { + GtkCellAreaPrivate *priv = area->priv; + 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 && - (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)) - { - 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); + GdkEventKey *key_event = (GdkEventKey *)event; - /* 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 any edits in progress */ + if (priv->edited_cell && (key_event->keyval == GDK_KEY_Escape)) { gtk_cell_area_stop_editing (area, TRUE); return TRUE; @@ -651,32 +625,57 @@ gtk_cell_area_real_get_preferred_width_for_height (GtkCellArea *area, } static void -update_can_focus (GtkCellRenderer *renderer, - gboolean *can_focus) +get_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) +static gboolean +gtk_cell_area_real_can_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. + /* Checks if any renderer can focus for the currently applied + * attributes. * * 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); + gtk_cell_area_forall (area, (GtkCellCallback)get_can_focus, &can_focus); + + return can_focus; +} + +static gboolean +gtk_cell_area_real_activate (GtkCellArea *area, + GtkCellAreaIter *iter, + GtkWidget *widget, + const GdkRectangle *cell_area, + GtkCellRendererState flags) +{ + GtkCellAreaPrivate *priv = area->priv; + GdkRectangle background_area; - /* 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); + if (priv->focus_cell) + { + /* Get the allocation of the focused cell. + */ + gtk_cell_area_get_cell_allocation (area, iter, widget, priv->focus_cell, + cell_area, &background_area); + + /* Activate or Edit the currently focused cell + * + * Currently just not sending an event, renderers afaics dont use + * the event argument anyway, worst case is we can synthesize one. + */ + if (gtk_cell_area_activate_cell (area, widget, priv->focus_cell, NULL, + &background_area, flags)) + return TRUE; + } + return FALSE; } /************************************************************* @@ -1687,134 +1686,80 @@ gtk_cell_area_cell_get_property (GtkCellArea *area, *************************************************************/ /** - * gtk_cell_area_grab_focus: + * gtk_cell_area_can_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. + * Returns whether the area can receive keyboard focus, + * after applying new attributes to @area. * - * Implementing #GtkCellArea classes should implement this - * method to receive focus in it's own way particular to - * how it lays out cells. + * Returns: whether @area can receive focus. */ -void -gtk_cell_area_grab_focus (GtkCellArea *area, - GtkDirectionType direction) +gboolean +gtk_cell_area_can_focus (GtkCellArea *area) { - GtkCellAreaClass *class; - - g_return_if_fail (GTK_IS_CELL_AREA (area)); - - class = GTK_CELL_AREA_GET_CLASS (area); + g_return_val_if_fail (GTK_IS_CELL_AREA (area), FALSE); - if (class->grab_focus) - class->grab_focus (area, direction); - else - g_warning ("GtkCellAreaClass::grab_focus not implemented for `%s'", - g_type_name (G_TYPE_FROM_INSTANCE (area))); + return GTK_CELL_AREA_GET_CLASS (area)->can_focus (area); } /** - * gtk_cell_area_focus_leave: + * gtk_cell_area_focus: * @area: a #GtkCellArea - * @direction: the #GtkDirectionType in which focus - * is to leave @area + * @direction: the #GtkDirectionType * - * 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) -{ - GtkCellAreaPrivate *priv; - - g_return_if_fail (GTK_IS_CELL_AREA (area)); - - priv = area->priv; - - g_signal_emit (area, cell_area_signals[SIGNAL_FOCUS_LEAVE], 0, direction, priv->current_path); -} - -/** - * gtk_cell_area_update_focus: - * @area: a #GtkCellArea + * This should be called by the @area's owning layout widget + * when focus is to be passed to @area, or moved within @area + * for a given @direction and row data. * - * Updates focus information on @area for a given - * row of data. + * Implementing #GtkCellArea classes should implement this + * method to receive and navigate focus in it's own way particular + * to how it lays out cells. * - * 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. + * Returns: %TRUE if focus remains inside @area as a result of this call. */ -void -gtk_cell_area_update_focus (GtkCellArea *area) +gboolean +gtk_cell_area_focus (GtkCellArea *area, + GtkDirectionType direction) { - g_return_if_fail (GTK_IS_CELL_AREA (area)); + GtkCellAreaClass *class; - GTK_CELL_AREA_GET_CLASS (area)->update_focus (area); -} + g_return_val_if_fail (GTK_IS_CELL_AREA (area), FALSE); -/** - * 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) -{ - GtkCellAreaPrivate *priv; + class = GTK_CELL_AREA_GET_CLASS (area); - g_return_if_fail (GTK_IS_CELL_AREA (area)); + if (class->focus) + return class->focus (area, direction); - priv = area->priv; + g_warning ("GtkCellAreaClass::focus not implemented for `%s'", + g_type_name (G_TYPE_FROM_INSTANCE (area))); - if (priv->can_focus != can_focus) - { - priv->can_focus = can_focus; - } + return FALSE; } /** - * gtk_cell_area_get_can_focus: + * gtk_cell_area_activate: * @area: a #GtkCellArea + * @iter: the #GtkCellAreaIter in context with the current row data + * @widget: the #GtkWidget that @area is rendering on + * @cell_area: the size and location of @area relative to @widget's allocation + * @flags: the #GtkCellRendererState flags for @area for this row of data. * - * 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. + * Activates @area, usually by activating the currently focused + * cell, however some subclasses which embed widgets in the area + * can also activate a widget if it currently has the focus. * - * Returns: whether @area can receive focus. + * Returns: Whether @area was successfully activated. */ gboolean -gtk_cell_area_get_can_focus (GtkCellArea *area) +gtk_cell_area_activate (GtkCellArea *area, + GtkCellAreaIter *iter, + GtkWidget *widget, + const GdkRectangle *cell_area, + GtkCellRendererState flags) { - GtkCellAreaPrivate *priv; - g_return_val_if_fail (GTK_IS_CELL_AREA (area), FALSE); - priv = area->priv; - - return priv->can_focus; + return GTK_CELL_AREA_GET_CLASS (area)->activate (area, iter, widget, cell_area, flags); } @@ -2042,7 +1987,6 @@ gtk_cell_area_activate_cell (GtkCellArea *area, 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; |