[gtk/wip/otte/listview: 48/159] listitem: Add gtk_list_item_get_position()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/listview: 48/159] listitem: Add gtk_list_item_get_position()
- Date: Wed, 11 Dec 2019 03:14:37 +0000 (UTC)
commit 8eaa1fa8222d4062c2702b3205ad4566e60f46de
Author: Benjamin Otte <otte redhat com>
Date: Mon Sep 24 04:01:37 2018 +0200
listitem: Add gtk_list_item_get_position()
Also refactor the whole list item management yet again.
Now, list item APIs doesn't have bind/unbind functions anymore, but only
property setters.
The item factory is the only one doing the binding.
As before, the item manager manages when items need to be bound.
docs/reference/gtk/gtk4-sections.txt | 1 +
gtk/gtklistitem.c | 67 +++++++++++++++++++++++++++++-------
gtk/gtklistitem.h | 2 ++
gtk/gtklistitemfactory.c | 26 ++++++++++++--
gtk/gtklistitemfactoryprivate.h | 4 +++
gtk/gtklistitemmanager.c | 23 ++++++++++++-
gtk/gtklistitemmanagerprivate.h | 3 ++
gtk/gtklistitemprivate.h | 5 +--
gtk/gtklistview.c | 18 ++++++++++
9 files changed, 131 insertions(+), 18 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 3a746333ee..9027500fd6 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -498,6 +498,7 @@ gtk_single_selection_get_type
<TITLE>GtkListItem</TITLE>
GtkListItem
gtk_list_item_get_item
+gtk_list_item_get_position
gtk_list_item_get_child
gtk_list_item_set_child
<SUBSECTION Standard>
diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c
index bb9f019ad6..7bc294ca33 100644
--- a/gtk/gtklistitem.c
+++ b/gtk/gtklistitem.c
@@ -23,6 +23,7 @@
#include "gtkbinlayout.h"
#include "gtkintl.h"
+#include "gtkselectionmodel.h" /* for GTK_INVALID_LIST_POSITION */
#include "gtkwidget.h"
/**
@@ -55,6 +56,7 @@ struct _GtkListItem
GObject *item;
GtkWidget *child;
+ guint position;
};
struct _GtkListItemClass
@@ -67,6 +69,7 @@ enum
PROP_0,
PROP_CHILD,
PROP_ITEM,
+ PROP_POSITION,
N_PROPS
};
@@ -104,6 +107,10 @@ gtk_list_item_get_property (GObject *object,
g_value_set_object (value, self->item);
break;
+ case PROP_POSITION:
+ g_value_set_uint (value, self->position);
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -164,6 +171,18 @@ gtk_list_item_class_init (GtkListItemClass *klass)
G_TYPE_OBJECT,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+ /**
+ * GtkListItem:position:
+ *
+ * Position of the item
+ */
+ properties[PROP_POSITION] =
+ g_param_spec_uint ("position",
+ P_("Position"),
+ P_("Position of the item"),
+ 0, G_MAXUINT, GTK_INVALID_LIST_POSITION,
+ G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties (gobject_class, N_PROPS, properties);
/* This gets overwritten by gtk_list_item_new() but better safe than sorry */
@@ -190,10 +209,10 @@ gtk_list_item_new (const char *css_name)
* gtk_list_item_get_item:
* @self: a #GtkListItem
*
- * Gets the item that is currently displayed or model that @self is
+ * Gets the item that is currently displayed in model that @self is
* currently bound to or %NULL if @self is unbound.
*
- * Returns: (nullable) (transfer none) (type GObject): The model in use
+ * Returns: (nullable) (transfer none) (type GObject): The item displayed
**/
gpointer
gtk_list_item_get_item (GtkListItem *self)
@@ -253,28 +272,50 @@ gtk_list_item_set_child (GtkListItem *self,
}
void
-gtk_list_item_bind (GtkListItem *self,
- gpointer item)
+gtk_list_item_set_item (GtkListItem *self,
+ gpointer item)
{
g_return_if_fail (GTK_IS_LIST_ITEM (self));
- g_return_if_fail (G_IS_OBJECT (item));
- /* Must unbind before rebinding */
- g_return_if_fail (self->item == NULL);
+ g_return_if_fail (item == NULL || G_IS_OBJECT (item));
- self->item = g_object_ref (item);
+ if (self->item == item)
+ return;
+
+ g_clear_object (&self->item);
+ if (item)
+ self->item = g_object_ref (item);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
}
+/**
+ * gtk_list_item_get_position:
+ * @self: a #GtkListItem
+ *
+ * Gets the position in the model that @self currently displays.
+ * If @self is unbound, 0 is returned.
+ *
+ * Returns: The position of this item
+ **/
+guint
+gtk_list_item_get_position (GtkListItem *self)
+{
+ g_return_val_if_fail (GTK_IS_LIST_ITEM (self), 0);
+
+ return self->position;
+}
+
void
-gtk_list_item_unbind (GtkListItem *self)
+gtk_list_item_set_position (GtkListItem *self,
+ guint position)
{
g_return_if_fail (GTK_IS_LIST_ITEM (self));
- /* Must be bound */
- g_return_if_fail (self->item != NULL);
- g_clear_object (&self->item);
+ if (self->position == position)
+ return;
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ITEM]);
+ self->position = position;
+
+ g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_POSITION]);
}
diff --git a/gtk/gtklistitem.h b/gtk/gtklistitem.h
index 3af77cb14e..ed7f21c45f 100644
--- a/gtk/gtklistitem.h
+++ b/gtk/gtklistitem.h
@@ -44,6 +44,8 @@ GType gtk_list_item_get_type (void) G_GNUC_CO
GDK_AVAILABLE_IN_ALL
gpointer gtk_list_item_get_item (GtkListItem *self);
+GDK_AVAILABLE_IN_ALL
+guint gtk_list_item_get_position (GtkListItem *self);
GDK_AVAILABLE_IN_ALL
void gtk_list_item_set_child (GtkListItem *self,
diff --git a/gtk/gtklistitemfactory.c b/gtk/gtklistitemfactory.c
index a9a58689a0..684380f3b1 100644
--- a/gtk/gtklistitemfactory.c
+++ b/gtk/gtklistitemfactory.c
@@ -105,14 +105,31 @@ gtk_list_item_factory_create (GtkListItemFactory *self)
void
gtk_list_item_factory_bind (GtkListItemFactory *self,
GtkListItem *list_item,
+ guint position,
gpointer item)
{
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
- gtk_list_item_bind (list_item, item);
+ g_object_freeze_notify (G_OBJECT (list_item));
+
+ gtk_list_item_set_item (list_item, item);
+ gtk_list_item_set_position (list_item, position);
self->bind_func (gtk_list_item_get_child (list_item), item, self->user_data);
+
+ g_object_thaw_notify (G_OBJECT (list_item));
+}
+
+void
+gtk_list_item_factory_update (GtkListItemFactory *self,
+ GtkListItem *list_item,
+ guint position)
+{
+ g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
+ g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
+
+ gtk_list_item_set_position (list_item, position);
}
void
@@ -122,5 +139,10 @@ gtk_list_item_factory_unbind (GtkListItemFactory *self,
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
- gtk_list_item_unbind (list_item);
+ g_object_freeze_notify (G_OBJECT (list_item));
+
+ gtk_list_item_set_item (list_item, NULL);
+ gtk_list_item_set_position (list_item, 0);
+
+ g_object_thaw_notify (G_OBJECT (list_item));
}
diff --git a/gtk/gtklistitemfactoryprivate.h b/gtk/gtklistitemfactoryprivate.h
index a6bec12faf..21bc5b5586 100644
--- a/gtk/gtklistitemfactoryprivate.h
+++ b/gtk/gtklistitemfactoryprivate.h
@@ -47,7 +47,11 @@ GtkListItem * gtk_list_item_factory_create (GtkListItemFact
void gtk_list_item_factory_bind (GtkListItemFactory *self,
GtkListItem *list_item,
+ guint position,
gpointer item);
+void gtk_list_item_factory_update (GtkListItemFactory *self,
+ GtkListItem *list_item,
+ guint position);
void gtk_list_item_factory_unbind (GtkListItemFactory *self,
GtkListItem *list_item);
diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c
index a88502efbb..d365137d18 100644
--- a/gtk/gtklistitemmanager.c
+++ b/gtk/gtklistitemmanager.c
@@ -236,7 +236,7 @@ gtk_list_item_manager_acquire_list_item (GtkListItemManager *self,
result = gtk_list_item_factory_create (self->factory);
item = g_list_model_get_item (self->model, position);
- gtk_list_item_factory_bind (self->factory, result, item);
+ gtk_list_item_factory_bind (self->factory, result, position, item);
g_object_unref (item);
gtk_widget_insert_before (GTK_WIDGET (result), self->widget, next_sibling);
@@ -274,6 +274,7 @@ gtk_list_item_manager_try_reacquire_list_item (GtkListItemManager *self,
item = g_list_model_get_item (self->model, position);
if (g_hash_table_steal_extended (change->items, item, NULL, (gpointer *) &result))
{
+ gtk_list_item_factory_update (self->factory, result, position);
gtk_widget_insert_before (GTK_WIDGET (result), self->widget, next_sibling);
/* XXX: Should we let the listview do this? */
gtk_widget_queue_resize (GTK_WIDGET (result));
@@ -287,6 +288,26 @@ gtk_list_item_manager_try_reacquire_list_item (GtkListItemManager *self,
return GTK_WIDGET (result);
}
+/**
+ * gtk_list_item_manager_update_list_item:
+ * @self: a #GtkListItemManager
+ * @item: a #GtkListItem that has been acquired
+ * @position: the new position of that list item
+ *
+ * Updates the position of the given @item. This function must be called whenever
+ * the position of an item changes, like when new items are added before it.
+ **/
+void
+gtk_list_item_manager_update_list_item (GtkListItemManager *self,
+ GtkWidget *item,
+ guint position)
+{
+ g_return_if_fail (GTK_IS_LIST_ITEM_MANAGER (self));
+ g_return_if_fail (GTK_IS_LIST_ITEM (item));
+
+ gtk_list_item_factory_update (self->factory, GTK_LIST_ITEM (item), position);
+}
+
/*
* gtk_list_item_manager_release_list_item:
* @self: a #GtkListItemManager
diff --git a/gtk/gtklistitemmanagerprivate.h b/gtk/gtklistitemmanagerprivate.h
index 2af8e8fae7..d1cdfaf819 100644
--- a/gtk/gtklistitemmanagerprivate.h
+++ b/gtk/gtklistitemmanagerprivate.h
@@ -63,6 +63,9 @@ GtkWidget * gtk_list_item_manager_try_reacquire_list_item
GtkListItemManagerChange *change,
guint position,
GtkWidget *next_sibling);
+void gtk_list_item_manager_update_list_item (GtkListItemManager *self,
+ GtkWidget *item,
+ guint position);
void gtk_list_item_manager_release_list_item (GtkListItemManager *self,
GtkListItemManagerChange *change,
GtkWidget *widget);
diff --git a/gtk/gtklistitemprivate.h b/gtk/gtklistitemprivate.h
index a0a90f7d79..f238685c76 100644
--- a/gtk/gtklistitemprivate.h
+++ b/gtk/gtklistitemprivate.h
@@ -26,9 +26,10 @@ G_BEGIN_DECLS
GtkWidget * gtk_list_item_new (const char *css_name);
-void gtk_list_item_bind (GtkListItem *self,
+void gtk_list_item_set_item (GtkListItem *self,
gpointer item);
-void gtk_list_item_unbind (GtkListItem *self);
+void gtk_list_item_set_position (GtkListItem *self,
+ guint position);
G_END_DECLS
diff --git a/gtk/gtklistview.c b/gtk/gtklistview.c
index f5c36e55fc..1539a2a530 100644
--- a/gtk/gtklistview.c
+++ b/gtk/gtklistview.c
@@ -509,6 +509,22 @@ gtk_list_view_add_rows (GtkListView *self,
gtk_widget_queue_resize (GTK_WIDGET (self));
}
+static void
+gtk_list_view_update_rows (GtkListView *self,
+ guint position)
+{
+ ListRow *row;
+
+ for (row = gtk_list_view_get_row (self, position, NULL);
+ row;
+ row = gtk_rb_tree_node_get_next (row))
+ {
+ gtk_list_item_manager_update_list_item (self->item_manager, row->widget, position);
+
+ position++;
+ }
+}
+
static void
gtk_list_view_model_items_changed_cb (GListModel *model,
guint position,
@@ -522,6 +538,8 @@ gtk_list_view_model_items_changed_cb (GListModel *model,
gtk_list_view_remove_rows (self, change, position, removed);
gtk_list_view_add_rows (self, change, position, added);
+ if (removed != added)
+ gtk_list_view_update_rows (self, position + added);
gtk_list_item_manager_end_change (self->item_manager, change);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]