forked from AuroraMiddleware/gtk
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.
This commit is contained in:
parent
378a573cf4
commit
fe14181d4e
@ -397,6 +397,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>
|
||||
|
@ -54,6 +54,7 @@ struct _GtkListItem
|
||||
|
||||
GObject *item;
|
||||
GtkWidget *child;
|
||||
guint position;
|
||||
};
|
||||
|
||||
struct _GtkListItemClass
|
||||
@ -66,6 +67,7 @@ enum
|
||||
PROP_0,
|
||||
PROP_CHILD,
|
||||
PROP_ITEM,
|
||||
PROP_POSITION,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@ -103,6 +105,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;
|
||||
@ -163,6 +169,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 */
|
||||
@ -189,10 +207,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)
|
||||
@ -252,28 +270,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]);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -153,14 +153,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
|
||||
@ -170,5 +187,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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user