diff options
author | Benjamin Otte <otte@redhat.com> | 2023-03-30 11:40:05 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2023-04-01 20:49:40 +0200 |
commit | c74ab7aaec9880726de7548789e06b9b5fdcee7b (patch) | |
tree | ea3b3b75da7ec388760abda2c2bc791f94a10ee4 | |
parent | 00cb4c66cfb48b4dee5568be6ac6d60505ef88cf (diff) | |
download | gtk+-c74ab7aaec9880726de7548789e06b9b5fdcee7b.tar.gz |
columnviewcellwidget: Untangle from GtkListItemWidget
This is step 1 in switching cells to their own ListItem subclass.
-rw-r--r-- | gtk/gtkcolumnviewcellwidget.c | 158 | ||||
-rw-r--r-- | gtk/gtkcolumnviewcellwidgetprivate.h | 3 | ||||
-rw-r--r-- | gtk/gtklistitem.c | 31 | ||||
-rw-r--r-- | gtk/gtklistitemprivate.h | 2 |
4 files changed, 185 insertions, 9 deletions
diff --git a/gtk/gtkcolumnviewcellwidget.c b/gtk/gtkcolumnviewcellwidget.c index 82bd843bb4..fcb7b8b6b7 100644 --- a/gtk/gtkcolumnviewcellwidget.c +++ b/gtk/gtkcolumnviewcellwidget.c @@ -25,8 +25,8 @@ #include "gtkcolumnviewrowwidgetprivate.h" #include "gtkcssboxesprivate.h" #include "gtkcssnodeprivate.h" +#include "gtklistfactorywidgetprivate.h" #include "gtklistitemprivate.h" -#include "gtklistitemwidgetprivate.h" #include "gtkprivate.h" #include "gtkwidgetprivate.h" @@ -47,7 +47,72 @@ struct _GtkColumnViewCellWidgetClass GtkListItemWidgetClass parent_class; }; -G_DEFINE_TYPE (GtkColumnViewCellWidget, gtk_column_view_cell_widget, GTK_TYPE_LIST_ITEM_WIDGET) +G_DEFINE_TYPE (GtkColumnViewCellWidget, gtk_column_view_cell_widget, GTK_TYPE_LIST_FACTORY_WIDGET) + +static gboolean +gtk_column_view_cell_widget_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + GtkWidget *child = gtk_widget_get_first_child (widget); + + if (gtk_widget_get_focus_child (widget)) + { + /* focus is in the child */ + if (direction == GTK_DIR_TAB_BACKWARD) + return gtk_widget_grab_focus_self (widget); + else + return FALSE; + } + else if (gtk_widget_is_focus (widget)) + { + /* The widget has focus */ + if (direction == GTK_DIR_TAB_FORWARD) + { + if (child) + return gtk_widget_child_focus (child, direction); + } + + return FALSE; + } + else + { + /* focus coming in from the outside */ + if (direction == GTK_DIR_TAB_BACKWARD) + { + if (child && + gtk_widget_child_focus (child, direction)) + return TRUE; + + return gtk_widget_grab_focus_self (widget); + } + else + { + if (gtk_widget_grab_focus_self (widget)) + return TRUE; + + if (child && + gtk_widget_child_focus (child, direction)) + return TRUE; + + return FALSE; + } + } +} + +static gboolean +gtk_column_view_cell_widget_grab_focus (GtkWidget *widget) +{ + GtkWidget *child; + + if (GTK_WIDGET_CLASS (gtk_column_view_cell_widget_parent_class)->grab_focus (widget)) + return TRUE; + + child = gtk_widget_get_first_child (widget); + if (child && gtk_widget_grab_focus (child)) + return TRUE; + + return FALSE; +} static gpointer gtk_column_view_cell_widget_create_object (GtkListFactoryWidget *fw) @@ -64,12 +129,80 @@ gtk_column_view_cell_widget_create_object (GtkListFactoryWidget *fw) } static void +gtk_column_view_cell_widget_setup_object (GtkListFactoryWidget *fw, + gpointer object) +{ + GtkColumnViewCellWidget *self = GTK_COLUMN_VIEW_CELL_WIDGET (fw); + GtkListItem *list_item = object; + + GTK_LIST_FACTORY_WIDGET_CLASS (gtk_column_view_cell_widget_parent_class)->setup_object (fw, object); + + list_item->cell = self; + + gtk_list_factory_widget_set_activatable (fw, list_item->activatable); + gtk_list_factory_widget_set_selectable (fw, list_item->selectable); + gtk_column_view_cell_widget_set_child (GTK_COLUMN_VIEW_CELL_WIDGET (self), list_item->child); + + gtk_widget_set_focusable (GTK_WIDGET (self), list_item->focusable); + + gtk_list_item_do_notify (list_item, + gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL, + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)) != GTK_INVALID_LIST_POSITION, + gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self))); +} + +static void gtk_column_view_cell_widget_teardown_object (GtkListFactoryWidget *fw, gpointer object) { + GtkColumnViewCellWidget *self = GTK_COLUMN_VIEW_CELL_WIDGET (fw); + GtkListItem *list_item = object; + GTK_LIST_FACTORY_WIDGET_CLASS (gtk_column_view_cell_widget_parent_class)->teardown_object (fw, object); - gtk_widget_set_focusable (GTK_WIDGET (fw), FALSE); + list_item->cell = NULL; + + gtk_column_view_cell_widget_set_child (GTK_COLUMN_VIEW_CELL_WIDGET (self), NULL); + + gtk_list_factory_widget_set_activatable (fw, FALSE); + gtk_list_factory_widget_set_selectable (fw, FALSE); + gtk_widget_set_focusable (GTK_WIDGET (self), FALSE); + + gtk_list_item_do_notify (list_item, + gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self)) != NULL, + gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self)) != GTK_INVALID_LIST_POSITION, + gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self))); + + /* FIXME: This is technically not correct, the child is user code, isn't it? */ + gtk_list_item_set_child (list_item, NULL); +} + +static void +gtk_column_view_cell_widget_update_object (GtkListFactoryWidget *fw, + gpointer object, + guint position, + gpointer item, + gboolean selected) +{ + GtkColumnViewCellWidget *self = GTK_COLUMN_VIEW_CELL_WIDGET (fw); + GtkListItemBase *base = GTK_LIST_ITEM_BASE (self); + GtkListItem *list_item = object; + /* Track notify manually instead of freeze/thaw_notify for performance reasons. */ + gboolean notify_item = FALSE, notify_position = FALSE, notify_selected = FALSE; + + /* FIXME: It's kinda evil to notify external objects from here... */ + notify_item = gtk_list_item_base_get_item (base) != item; + notify_position = gtk_list_item_base_get_position (base) != position; + notify_selected = gtk_list_item_base_get_selected (base) != selected; + + GTK_LIST_FACTORY_WIDGET_CLASS (gtk_column_view_cell_widget_parent_class)->update_object (fw, + object, + position, + item, + selected); + + if (list_item) + gtk_list_item_do_notify (list_item, notify_item, notify_position, notify_selected); } static int @@ -193,8 +326,12 @@ gtk_column_view_cell_widget_class_init (GtkColumnViewCellWidgetClass *klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); factory_class->create_object = gtk_column_view_cell_widget_create_object; + factory_class->setup_object = gtk_column_view_cell_widget_setup_object; + factory_class->update_object = gtk_column_view_cell_widget_update_object; factory_class->teardown_object = gtk_column_view_cell_widget_teardown_object; + widget_class->focus = gtk_column_view_cell_widget_focus; + widget_class->grab_focus = gtk_column_view_cell_widget_grab_focus; widget_class->measure = gtk_column_view_cell_widget_measure; widget_class->size_allocate = gtk_column_view_cell_widget_size_allocate; widget_class->get_request_mode = gtk_column_view_cell_widget_get_request_mode; @@ -272,3 +409,18 @@ gtk_column_view_cell_widget_get_column (GtkColumnViewCellWidget *self) { return self->column; } + +void +gtk_column_view_cell_widget_set_child (GtkColumnViewCellWidget *self, + GtkWidget *child) +{ + GtkWidget *cur_child = gtk_widget_get_first_child (GTK_WIDGET (self)); + + if (cur_child == child) + return; + + g_clear_pointer (&cur_child, gtk_widget_unparent); + + if (child) + gtk_widget_set_parent (child, GTK_WIDGET (self)); +} diff --git a/gtk/gtkcolumnviewcellwidgetprivate.h b/gtk/gtkcolumnviewcellwidgetprivate.h index b50e69e477..57632adf9b 100644 --- a/gtk/gtkcolumnviewcellwidgetprivate.h +++ b/gtk/gtkcolumnviewcellwidgetprivate.h @@ -38,6 +38,9 @@ GType gtk_column_view_cell_widget_get_type ( GtkWidget * gtk_column_view_cell_widget_new (GtkColumnViewColumn *column, gboolean inert); +void gtk_column_view_cell_widget_set_child (GtkColumnViewCellWidget *self, + GtkWidget *child); + void gtk_column_view_cell_widget_remove (GtkColumnViewCellWidget *self); GtkColumnViewCellWidget * gtk_column_view_cell_widget_get_next (GtkColumnViewCellWidget *self); diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c index 59f450f97b..8890641a4a 100644 --- a/gtk/gtklistitem.c +++ b/gtk/gtklistitem.c @@ -70,6 +70,7 @@ gtk_list_item_dispose (GObject *object) GtkListItem *self = GTK_LIST_ITEM (object); g_assert (self->owner == NULL); /* would hold a reference */ + g_assert (self->cell == NULL); /* would hold a reference */ g_clear_object (&self->child); G_OBJECT_CLASS (gtk_list_item_parent_class)->dispose (object); @@ -100,11 +101,15 @@ gtk_list_item_get_property (GObject *object, case PROP_ITEM: if (self->owner) g_value_set_object (value, gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->owner))); + else if (self->cell) + g_value_set_object (value, gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->cell))); break; case PROP_POSITION: if (self->owner) g_value_set_uint (value, gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->owner))); + else if (self->cell) + g_value_set_uint (value, gtk_list_item_base_get_position (GTK_LIST_ITEM_BASE (self->cell))); else g_value_set_uint (value, GTK_INVALID_LIST_POSITION); break; @@ -116,6 +121,8 @@ gtk_list_item_get_property (GObject *object, case PROP_SELECTED: if (self->owner) g_value_set_boolean (value, gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->owner))); + if (self->cell) + g_value_set_boolean (value, gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->cell))); else g_value_set_boolean (value, FALSE); break; @@ -287,10 +294,12 @@ gtk_list_item_get_item (GtkListItem *self) { g_return_val_if_fail (GTK_IS_LIST_ITEM (self), NULL); - if (self->owner == NULL) + if (self->owner) + return gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->owner)); + else if (self->cell) + return gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->cell)); + else return NULL; - - return gtk_list_item_base_get_item (GTK_LIST_ITEM_BASE (self->owner)); } /** @@ -347,6 +356,8 @@ gtk_list_item_set_child (GtkListItem *self, if (self->owner) gtk_list_item_widget_set_child (self->owner, child); + else if (self->cell) + gtk_column_view_cell_widget_set_child (self->cell, child); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHILD]); } @@ -388,10 +399,12 @@ gtk_list_item_get_selected (GtkListItem *self) { g_return_val_if_fail (GTK_IS_LIST_ITEM (self), FALSE); - if (self->owner == NULL) + if (self->owner) + return gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->owner)); + if (self->cell) + return gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->cell)); + else return FALSE; - - return gtk_list_item_base_get_selected (GTK_LIST_ITEM_BASE (self->owner)); } /** @@ -444,6 +457,8 @@ gtk_list_item_set_selectable (GtkListItem *self, if (self->owner) gtk_list_factory_widget_set_selectable (GTK_LIST_FACTORY_WIDGET (self->owner), selectable); + if (self->cell) + gtk_list_factory_widget_set_selectable (GTK_LIST_FACTORY_WIDGET (self->cell), selectable); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTABLE]); } @@ -493,6 +508,8 @@ gtk_list_item_set_activatable (GtkListItem *self, if (self->owner) gtk_list_factory_widget_set_activatable (GTK_LIST_FACTORY_WIDGET (self->owner), activatable); + if (self->cell) + gtk_list_factory_widget_set_activatable (GTK_LIST_FACTORY_WIDGET (self->cell), activatable); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIVATABLE]); } @@ -548,6 +565,8 @@ gtk_list_item_set_focusable (GtkListItem *self, if (self->owner) gtk_widget_set_focusable (GTK_WIDGET (self->owner), focusable); + if (self->cell) + gtk_widget_set_focusable (GTK_WIDGET (self->cell), focusable); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FOCUSABLE]); } diff --git a/gtk/gtklistitemprivate.h b/gtk/gtklistitemprivate.h index 99adbeee4c..6858419821 100644 --- a/gtk/gtklistitemprivate.h +++ b/gtk/gtklistitemprivate.h @@ -22,6 +22,7 @@ #include "gtklistitem.h" #include "gtklistitemwidgetprivate.h" +#include "gtkcolumnviewcellwidgetprivate.h" #include "gtkversion.h" G_BEGIN_DECLS @@ -31,6 +32,7 @@ struct _GtkListItem GObject parent_instance; GtkListItemWidget *owner; /* has a reference */ + GtkColumnViewCellWidget *cell; /* has a reference */ GtkWidget *child; |