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

View File

@ -257,13 +257,58 @@ gtk_grid_view_split (GtkListBase *base,
return split; 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 * static GtkListItemBase *
gtk_grid_view_create_list_widget (GtkListBase *base) gtk_grid_view_create_list_widget (GtkListBase *base)
{ {
GtkGridView *self = GTK_GRID_VIEW (base); GtkGridView *self = GTK_GRID_VIEW (base);
GtkListItemFactory *factory;
GtkWidget *result; 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", "child",
GTK_ACCESSIBLE_ROLE_GRID_CELL); GTK_ACCESSIBLE_ROLE_GRID_CELL);
@ -856,6 +901,50 @@ gtk_grid_view_size_allocate (GtkWidget *widget,
gtk_list_base_allocate (GTK_LIST_BASE (self)); 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 static void
gtk_grid_view_dispose (GObject *object) 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->measure = gtk_grid_view_measure;
widget_class->size_allocate = gtk_grid_view_size_allocate; 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->dispose = gtk_grid_view_dispose;
gobject_class->get_property = gtk_grid_view_get_property; gobject_class->get_property = gtk_grid_view_get_property;
@ -1237,22 +1330,18 @@ void
gtk_grid_view_set_factory (GtkGridView *self, gtk_grid_view_set_factory (GtkGridView *self,
GtkListItemFactory *factory) GtkListItemFactory *factory)
{ {
GtkListTile *tile; gboolean was_inert;
g_return_if_fail (GTK_IS_GRID_VIEW (self)); g_return_if_fail (GTK_IS_GRID_VIEW (self));
g_return_if_fail (factory == NULL || GTK_IS_LIST_ITEM_FACTORY (factory)); 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)) if (!g_set_object (&self->factory, factory))
return; return;
for (tile = gtk_list_item_manager_get_first (self->item_manager); if (!was_inert || !gtk_grid_view_is_inert (self))
tile != NULL; gtk_grid_view_update_factories (self);
tile = gtk_rb_tree_node_get_next (tile))
{
if (tile->widget)
gtk_list_factory_widget_set_factory (GTK_LIST_FACTORY_WIDGET (tile->widget), factory);
}
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]); 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 static void
gtk_list_factory_widget_set_property (GObject *object, gtk_list_factory_widget_set_property (GObject *object,
guint property_id, 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 static void
gtk_list_factory_widget_dispose (GObject *object) gtk_list_factory_widget_dispose (GObject *object)
{ {
GtkListFactoryWidget *self = GTK_LIST_FACTORY_WIDGET (object); GtkListFactoryWidget *self = GTK_LIST_FACTORY_WIDGET (object);
GtkListFactoryWidgetPrivate *priv = gtk_list_factory_widget_get_instance_private (self);
g_assert (priv->object == NULL); gtk_list_factory_widget_clear_factory (self);
g_clear_object (&priv->factory);
G_OBJECT_CLASS (gtk_list_factory_widget_parent_class)->dispose (object); 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; 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->set_property = gtk_list_factory_widget_set_property;
gobject_class->dispose = gtk_list_factory_widget_dispose; gobject_class->dispose = gtk_list_factory_widget_dispose;
@ -553,19 +536,13 @@ gtk_list_factory_widget_set_factory (GtkListFactoryWidget *self,
if (priv->factory == factory) if (priv->factory == factory)
return; return;
if (priv->factory) gtk_list_factory_widget_clear_factory (self);
{
if (priv->object)
gtk_list_factory_widget_teardown_factory (self);
g_clear_object (&priv->factory);
}
if (factory) if (factory)
{ {
priv->factory = g_object_ref (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]); 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; 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 * static GtkListItemBase *
gtk_list_view_create_list_widget (GtkListBase *base) gtk_list_view_create_list_widget (GtkListBase *base)
{ {
GtkListView *self = GTK_LIST_VIEW (base); GtkListView *self = GTK_LIST_VIEW (base);
GtkListItemFactory *factory;
GtkWidget *result; 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", "row",
GTK_ACCESSIBLE_ROLE_LIST_ITEM); GTK_ACCESSIBLE_ROLE_LIST_ITEM);
@ -606,6 +651,50 @@ gtk_list_view_size_allocate (GtkWidget *widget,
gtk_list_base_allocate (GTK_LIST_BASE (self)); 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 static void
gtk_list_view_dispose (GObject *object) 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->measure = gtk_list_view_measure;
widget_class->size_allocate = gtk_list_view_size_allocate; 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->dispose = gtk_list_view_dispose;
gobject_class->get_property = gtk_list_view_get_property; gobject_class->get_property = gtk_list_view_get_property;
@ -961,21 +1054,18 @@ void
gtk_list_view_set_factory (GtkListView *self, gtk_list_view_set_factory (GtkListView *self,
GtkListItemFactory *factory) GtkListItemFactory *factory)
{ {
GtkListTile *tile; gboolean was_inert;
g_return_if_fail (GTK_IS_LIST_VIEW (self)); g_return_if_fail (GTK_IS_LIST_VIEW (self));
g_return_if_fail (factory == NULL || GTK_IS_LIST_ITEM_FACTORY (factory)); 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)) if (!g_set_object (&self->factory, factory))
return; return;
for (tile = gtk_list_item_manager_get_first (self->item_manager); if (!was_inert || !gtk_list_view_is_inert (self))
tile != NULL; gtk_list_view_update_factories (self);
tile = gtk_rb_tree_node_get_next (tile))
{
if (tile->widget)
gtk_list_factory_widget_set_factory (GTK_LIST_FACTORY_WIDGET (tile->widget), factory);
}
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]); 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->x = x;
magnifier->y = y; 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 void
@ -303,8 +302,7 @@ _gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
if (magnifier->resize) if (magnifier->resize)
gtk_widget_queue_resize (GTK_WIDGET (magnifier)); 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 double