Merge branch 'wip/otte/listview-inert' into 'main'

listview: Add concept of inertness

See merge request GNOME/gtk!5731
This commit is contained in:
Benjamin Otte 2023-03-27 05:48:12 +00:00
commit 3008f4babc
5 changed files with 218 additions and 62 deletions

View File

@ -20,6 +20,7 @@
<object class="GtkScrolledWindow">
<child>
<object class="GtkListView" id="listview">
<property name="tab-behavior">item</property>
<style>
<class name="navigation-sidebar"/>
</style>
@ -76,6 +77,7 @@
<property name="vexpand">1</property>
<child>
<object class="GtkColumnView" id="columnview">
<property name="tab-behavior">cell</property>
<style>
<class name="data-table"/>
</style>

View File

@ -257,13 +257,58 @@ gtk_grid_view_split (GtkListBase *base,
return split;
}
/* We define the listview as **inert** when the factory isn't used. */
static gboolean
gtk_grid_view_is_inert (GtkGridView *self)
{
GtkWidget *widget = GTK_WIDGET (self);
return !gtk_widget_get_visible (widget) ||
gtk_widget_get_root (widget) == NULL ||
self->factory == NULL;
}
static void
gtk_grid_view_update_factories_with (GtkGridView *self,
GtkListItemFactory *factory)
{
GtkListTile *tile;
for (tile = gtk_list_item_manager_get_first (self->item_manager);
tile != NULL;
tile = gtk_rb_tree_node_get_next (tile))
{
if (tile->widget)
gtk_list_factory_widget_set_factory (GTK_LIST_FACTORY_WIDGET (tile->widget), factory);
}
}
static void
gtk_grid_view_update_factories (GtkGridView *self)
{
gtk_grid_view_update_factories_with (self,
gtk_grid_view_is_inert (self) ? NULL : self->factory);
}
static void
gtk_grid_view_clear_factories (GtkGridView *self)
{
gtk_grid_view_update_factories_with (self, NULL);
}
static GtkListItemBase *
gtk_grid_view_create_list_widget (GtkListBase *base)
{
GtkGridView *self = GTK_GRID_VIEW (base);
GtkListItemFactory *factory;
GtkWidget *result;
result = gtk_list_item_widget_new (self->factory,
if (gtk_grid_view_is_inert (self))
factory = NULL;
else
factory = self->factory;
result = gtk_list_item_widget_new (factory,
"child",
GTK_ACCESSIBLE_ROLE_GRID_CELL);
@ -856,6 +901,50 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
gtk_list_base_allocate (GTK_LIST_BASE (self));
}
static void
gtk_grid_view_root (GtkWidget *widget)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
GTK_WIDGET_CLASS (gtk_grid_view_parent_class)->root (widget);
if (!gtk_grid_view_is_inert (self))
gtk_grid_view_update_factories (self);
}
static void
gtk_grid_view_unroot (GtkWidget *widget)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
if (!gtk_grid_view_is_inert (self))
gtk_grid_view_clear_factories (self);
GTK_WIDGET_CLASS (gtk_grid_view_parent_class)->unroot (widget);
}
static void
gtk_grid_view_show (GtkWidget *widget)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
GTK_WIDGET_CLASS (gtk_grid_view_parent_class)->show (widget);
if (!gtk_grid_view_is_inert (self))
gtk_grid_view_update_factories (self);
}
static void
gtk_grid_view_hide (GtkWidget *widget)
{
GtkGridView *self = GTK_GRID_VIEW (widget);
if (!gtk_grid_view_is_inert (self))
gtk_grid_view_clear_factories (self);
GTK_WIDGET_CLASS (gtk_grid_view_parent_class)->hide (widget);
}
static void
gtk_grid_view_dispose (GObject *object)
{
@ -989,6 +1078,10 @@ gtk_grid_view_class_init (GtkGridViewClass *klass)
widget_class->measure = gtk_grid_view_measure;
widget_class->size_allocate = gtk_grid_view_size_allocate;
widget_class->root = gtk_grid_view_root;
widget_class->unroot = gtk_grid_view_unroot;
widget_class->show = gtk_grid_view_show;
widget_class->hide = gtk_grid_view_hide;
gobject_class->dispose = gtk_grid_view_dispose;
gobject_class->get_property = gtk_grid_view_get_property;
@ -1237,22 +1330,18 @@ void
gtk_grid_view_set_factory (GtkGridView *self,
GtkListItemFactory *factory)
{
GtkListTile *tile;
gboolean was_inert;
g_return_if_fail (GTK_IS_GRID_VIEW (self));
g_return_if_fail (factory == NULL || GTK_IS_LIST_ITEM_FACTORY (factory));
was_inert = gtk_grid_view_is_inert (self);
if (!g_set_object (&self->factory, factory))
return;
for (tile = gtk_list_item_manager_get_first (self->item_manager);
tile != NULL;
tile = gtk_rb_tree_node_get_next (tile))
{
if (tile->widget)
gtk_list_factory_widget_set_factory (GTK_LIST_FACTORY_WIDGET (tile->widget), factory);
}
if (!was_inert || !gtk_grid_view_is_inert (self))
gtk_grid_view_update_factories (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]);
}

View File

@ -204,30 +204,6 @@ gtk_list_factory_widget_update (GtkListItemBase *base,
}
}
static void
gtk_list_factory_widget_root (GtkWidget *widget)
{
GtkListFactoryWidget *self = GTK_LIST_FACTORY_WIDGET (widget);
GtkListFactoryWidgetPrivate *priv = gtk_list_factory_widget_get_instance_private (self);
GTK_WIDGET_CLASS (gtk_list_factory_widget_parent_class)->root (widget);
if (priv->factory)
gtk_list_factory_widget_setup_factory (self);
}
static void
gtk_list_factory_widget_unroot (GtkWidget *widget)
{
GtkListFactoryWidget *self = GTK_LIST_FACTORY_WIDGET (widget);
GtkListFactoryWidgetPrivate *priv = gtk_list_factory_widget_get_instance_private (self);
GTK_WIDGET_CLASS (gtk_list_factory_widget_parent_class)->unroot (widget);
if (priv->object)
gtk_list_factory_widget_teardown_factory (self);
}
static void
gtk_list_factory_widget_set_property (GObject *object,
guint property_id,
@ -260,15 +236,25 @@ gtk_list_factory_widget_set_property (GObject *object,
}
}
static void
gtk_list_factory_widget_clear_factory (GtkListFactoryWidget *self)
{
GtkListFactoryWidgetPrivate *priv = gtk_list_factory_widget_get_instance_private (self);
if (priv->factory == NULL)
return;
if (priv->object)
gtk_list_factory_widget_teardown_factory (self);
g_clear_object (&priv->factory);
}
static void
gtk_list_factory_widget_dispose (GObject *object)
{
GtkListFactoryWidget *self = GTK_LIST_FACTORY_WIDGET (object);
GtkListFactoryWidgetPrivate *priv = gtk_list_factory_widget_get_instance_private (self);
g_assert (priv->object == NULL);
g_clear_object (&priv->factory);
gtk_list_factory_widget_clear_factory (self);
G_OBJECT_CLASS (gtk_list_factory_widget_parent_class)->dispose (object);
}
@ -319,9 +305,6 @@ gtk_list_factory_widget_class_init (GtkListFactoryWidgetClass *klass)
base_class->update = gtk_list_factory_widget_update;
widget_class->root = gtk_list_factory_widget_root;
widget_class->unroot = gtk_list_factory_widget_unroot;
gobject_class->set_property = gtk_list_factory_widget_set_property;
gobject_class->dispose = gtk_list_factory_widget_dispose;
@ -553,19 +536,13 @@ gtk_list_factory_widget_set_factory (GtkListFactoryWidget *self,
if (priv->factory == factory)
return;
if (priv->factory)
{
if (priv->object)
gtk_list_factory_widget_teardown_factory (self);
g_clear_object (&priv->factory);
}
gtk_list_factory_widget_clear_factory (self);
if (factory)
{
priv->factory = g_object_ref (factory);
if (gtk_widget_get_root (GTK_WIDGET (self)))
gtk_list_factory_widget_setup_factory (self);
gtk_list_factory_widget_setup_factory (self);
}
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]);

View File

@ -215,13 +215,58 @@ gtk_list_view_split (GtkListBase *base,
return new_tile;
}
/* We define the listview as **inert** when the factory isn't used. */
static gboolean
gtk_list_view_is_inert (GtkListView *self)
{
GtkWidget *widget = GTK_WIDGET (self);
return !gtk_widget_get_visible (widget) ||
gtk_widget_get_root (widget) == NULL ||
self->factory == NULL;
}
static void
gtk_list_view_update_factories_with (GtkListView *self,
GtkListItemFactory *factory)
{
GtkListTile *tile;
for (tile = gtk_list_item_manager_get_first (self->item_manager);
tile != NULL;
tile = gtk_rb_tree_node_get_next (tile))
{
if (tile->widget)
gtk_list_factory_widget_set_factory (GTK_LIST_FACTORY_WIDGET (tile->widget), factory);
}
}
static void
gtk_list_view_update_factories (GtkListView *self)
{
gtk_list_view_update_factories_with (self,
gtk_list_view_is_inert (self) ? NULL : self->factory);
}
static void
gtk_list_view_clear_factories (GtkListView *self)
{
gtk_list_view_update_factories_with (self, NULL);
}
static GtkListItemBase *
gtk_list_view_create_list_widget (GtkListBase *base)
{
GtkListView *self = GTK_LIST_VIEW (base);
GtkListItemFactory *factory;
GtkWidget *result;
result = gtk_list_item_widget_new (self->factory,
if (gtk_list_view_is_inert (self))
factory = NULL;
else
factory = self->factory;
result = gtk_list_item_widget_new (factory,
"row",
GTK_ACCESSIBLE_ROLE_LIST_ITEM);
@ -606,6 +651,50 @@ gtk_list_view_size_allocate (GtkWidget *widget,
gtk_list_base_allocate (GTK_LIST_BASE (self));
}
static void
gtk_list_view_root (GtkWidget *widget)
{
GtkListView *self = GTK_LIST_VIEW (widget);
GTK_WIDGET_CLASS (gtk_list_view_parent_class)->root (widget);
if (!gtk_list_view_is_inert (self))
gtk_list_view_update_factories (self);
}
static void
gtk_list_view_unroot (GtkWidget *widget)
{
GtkListView *self = GTK_LIST_VIEW (widget);
if (!gtk_list_view_is_inert (self))
gtk_list_view_clear_factories (self);
GTK_WIDGET_CLASS (gtk_list_view_parent_class)->unroot (widget);
}
static void
gtk_list_view_show (GtkWidget *widget)
{
GtkListView *self = GTK_LIST_VIEW (widget);
GTK_WIDGET_CLASS (gtk_list_view_parent_class)->show (widget);
if (!gtk_list_view_is_inert (self))
gtk_list_view_update_factories (self);
}
static void
gtk_list_view_hide (GtkWidget *widget)
{
GtkListView *self = GTK_LIST_VIEW (widget);
if (!gtk_list_view_is_inert (self))
gtk_list_view_clear_factories (self);
GTK_WIDGET_CLASS (gtk_list_view_parent_class)->hide (widget);
}
static void
gtk_list_view_dispose (GObject *object)
{
@ -731,6 +820,10 @@ gtk_list_view_class_init (GtkListViewClass *klass)
widget_class->measure = gtk_list_view_measure;
widget_class->size_allocate = gtk_list_view_size_allocate;
widget_class->root = gtk_list_view_root;
widget_class->unroot = gtk_list_view_unroot;
widget_class->show = gtk_list_view_show;
widget_class->hide = gtk_list_view_hide;
gobject_class->dispose = gtk_list_view_dispose;
gobject_class->get_property = gtk_list_view_get_property;
@ -961,21 +1054,18 @@ void
gtk_list_view_set_factory (GtkListView *self,
GtkListItemFactory *factory)
{
GtkListTile *tile;
gboolean was_inert;
g_return_if_fail (GTK_IS_LIST_VIEW (self));
g_return_if_fail (factory == NULL || GTK_IS_LIST_ITEM_FACTORY (factory));
was_inert = gtk_list_view_is_inert (self);
if (!g_set_object (&self->factory, factory))
return;
for (tile = gtk_list_item_manager_get_first (self->item_manager);
tile != NULL;
tile = gtk_rb_tree_node_get_next (tile))
{
if (tile->widget)
gtk_list_factory_widget_set_factory (GTK_LIST_FACTORY_WIDGET (tile->widget), factory);
}
if (!was_inert || !gtk_list_view_is_inert (self))
gtk_list_view_update_factories (self);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]);
}

View File

@ -270,8 +270,7 @@ _gtk_magnifier_set_coords (GtkMagnifier *magnifier,
magnifier->x = x;
magnifier->y = y;
if (gtk_widget_is_visible (GTK_WIDGET (magnifier)))
gtk_widget_queue_draw (GTK_WIDGET (magnifier));
gtk_widget_queue_draw (GTK_WIDGET (magnifier));
}
void
@ -303,8 +302,7 @@ _gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
if (magnifier->resize)
gtk_widget_queue_resize (GTK_WIDGET (magnifier));
if (gtk_widget_is_visible (GTK_WIDGET (magnifier)))
gtk_widget_queue_draw (GTK_WIDGET (magnifier));
gtk_widget_queue_draw (GTK_WIDGET (magnifier));
}
double