columnviewcellwidget: Untangle from GtkListItemWidget

This is step 1 in switching cells to their own ListItem subclass.
This commit is contained in:
Benjamin Otte
2023-03-30 11:40:05 +02:00
parent 00cb4c66cf
commit c74ab7aaec
4 changed files with 185 additions and 9 deletions

View File

@@ -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)
@@ -63,13 +128,81 @@ gtk_column_view_cell_widget_create_object (GtkListFactoryWidget *fw)
return list_item;
}
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));
}

View File

@@ -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);

View File

@@ -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]);
}

View File

@@ -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;