listview: Add selection properties to ListItem

This just brings the infrastructure into place, we're not using the
properties yet.
This commit is contained in:
Benjamin Otte 2018-09-29 22:34:43 +02:00 committed by Matthias Clasen
parent 5b69fd535d
commit b3fb80c608
7 changed files with 160 additions and 8 deletions

View File

@ -400,6 +400,9 @@ gtk_list_item_get_item
gtk_list_item_get_position
gtk_list_item_get_child
gtk_list_item_set_child
gtk_list_item_get_selected
gtk_list_item_get_selectable
gtk_list_item_set_selectable
<SUBSECTION Standard>
GTK_LIST_ITEM
GTK_LIST_ITEM_CLASS

View File

@ -55,6 +55,9 @@ struct _GtkListItem
GObject *item;
GtkWidget *child;
guint position;
guint selectable : 1;
guint selected : 1;
};
struct _GtkListItemClass
@ -68,6 +71,8 @@ enum
PROP_CHILD,
PROP_ITEM,
PROP_POSITION,
PROP_SELECTABLE,
PROP_SELECTED,
N_PROPS
};
@ -109,6 +114,14 @@ gtk_list_item_get_property (GObject *object,
g_value_set_uint (value, self->position);
break;
case PROP_SELECTABLE:
g_value_set_boolean (value, self->selectable);
break;
case PROP_SELECTED:
g_value_set_boolean (value, self->selected);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -129,6 +142,10 @@ gtk_list_item_set_property (GObject *object,
gtk_list_item_set_child (self, g_value_get_object (value));
break;
case PROP_SELECTABLE:
gtk_list_item_set_selectable (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -181,6 +198,30 @@ gtk_list_item_class_init (GtkListItemClass *klass)
0, G_MAXUINT, GTK_INVALID_LIST_POSITION,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkListItem:selectable:
*
* If the item can be selected by the user
*/
properties[PROP_SELECTABLE] =
g_param_spec_boolean ("selectable",
P_("Selectable"),
P_("If the item can be selected by the user"),
TRUE,
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
/**
* GtkListItem:selected:
*
* If the item is currently selected
*/
properties[PROP_SELECTED] =
g_param_spec_boolean ("selected",
P_("Selected"),
P_("If the item is currently selected"),
FALSE,
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 */
@ -191,6 +232,7 @@ gtk_list_item_class_init (GtkListItemClass *klass)
static void
gtk_list_item_init (GtkListItem *self)
{
self->selectable = TRUE;
}
GtkWidget *
@ -317,3 +359,89 @@ gtk_list_item_set_position (GtkListItem *self,
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_POSITION]);
}
/**
* gtk_list_item_get_selected:
* @self: a #GtkListItem
*
* Checks if the item is displayed as selected. The selected state is
* maintained by the container and its list model and cannot be set
* otherwise.
*
* Returns: %TRUE if the item is selected.
**/
gboolean
gtk_list_item_get_selected (GtkListItem *self)
{
g_return_val_if_fail (GTK_IS_LIST_ITEM (self), FALSE);
return self->selected;
}
void
gtk_list_item_set_selected (GtkListItem *self,
gboolean selected)
{
g_return_if_fail (GTK_IS_LIST_ITEM (self));
if (self->selected == selected)
return;
self->selected = selected;
if (selected)
gtk_widget_set_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED, FALSE);
else
gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_SELECTED);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTED]);
}
/**
* gtk_list_item_get_selectable:
* @self: a #GtkListItem
*
* Checks if a list item has been set to be selectable via
* gtk_list_item_set_selectable().
*
* Do not confuse this function with gtk_list_item_get_selected().
*
* Returns: %TRUE if the item is selectable
**/
gboolean
gtk_list_item_get_selectable (GtkListItem *self)
{
g_return_val_if_fail (GTK_IS_LIST_ITEM (self), FALSE);
return self->selectable;
}
/**
* gtk_list_item_set_selectable:
* @self: a #GtkListItem
* @selectable: if the item should be selectable
*
* Sets @self to be selectable. If an item is selectable, clicking
* on the item or using the keyboard will try to select or unselect
* the item. If this succeeds is up to the model to determine, as
* it is managing the selected state.
*
* Note that this means that making an item non-selectable has no
* influence on the selected state at all. A non-selectable item
* may still be selected.
*
* By default, list items are selectable. When rebinding them to
* a new item, they will also be reset to be selectable by GTK.
**/
void
gtk_list_item_set_selectable (GtkListItem *self,
gboolean selectable)
{
g_return_if_fail (GTK_IS_LIST_ITEM (self));
if (self->selectable == selectable)
return;
self->selectable = selectable;
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTABLE]);
}

View File

@ -73,6 +73,14 @@ 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
gboolean gtk_list_item_get_selected (GtkListItem *self);
GDK_AVAILABLE_IN_ALL
gboolean gtk_list_item_get_selectable (GtkListItem *self);
GDK_AVAILABLE_IN_ALL
void gtk_list_item_set_selectable (GtkListItem *self,
gboolean selectable);
GDK_AVAILABLE_IN_ALL
void gtk_list_item_set_child (GtkListItem *self,

View File

@ -152,7 +152,8 @@ void
gtk_list_item_factory_bind (GtkListItemFactory *self,
GtkListItem *list_item,
guint position,
gpointer item)
gpointer item,
gboolean selected)
{
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
@ -161,6 +162,7 @@ gtk_list_item_factory_bind (GtkListItemFactory *self,
gtk_list_item_set_item (list_item, item);
gtk_list_item_set_position (list_item, position);
gtk_list_item_set_selected (list_item, selected);
if (self->bind_func)
self->bind_func (list_item, self->user_data);
@ -171,12 +173,18 @@ gtk_list_item_factory_bind (GtkListItemFactory *self,
void
gtk_list_item_factory_update (GtkListItemFactory *self,
GtkListItem *list_item,
guint position)
guint position,
gboolean selected)
{
g_return_if_fail (GTK_IS_LIST_ITEM_FACTORY (self));
g_return_if_fail (GTK_IS_LIST_ITEM (list_item));
g_object_freeze_notify (G_OBJECT (list_item));
gtk_list_item_set_position (list_item, position);
gtk_list_item_set_selected (list_item, selected);
g_object_thaw_notify (G_OBJECT (list_item));
}
void
@ -190,6 +198,7 @@ gtk_list_item_factory_unbind (GtkListItemFactory *self,
gtk_list_item_set_item (list_item, NULL);
gtk_list_item_set_position (list_item, 0);
gtk_list_item_set_selected (list_item, FALSE);
g_object_thaw_notify (G_OBJECT (list_item));
}

View File

@ -48,10 +48,12 @@ GtkListItem * gtk_list_item_factory_create (GtkListItemFact
void gtk_list_item_factory_bind (GtkListItemFactory *self,
GtkListItem *list_item,
guint position,
gpointer item);
gpointer item,
gboolean selected);
void gtk_list_item_factory_update (GtkListItemFactory *self,
GtkListItem *list_item,
guint position);
guint position,
gboolean selected);
void gtk_list_item_factory_unbind (GtkListItemFactory *self,
GtkListItem *list_item);

View File

@ -262,7 +262,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, position, item);
gtk_list_item_factory_bind (self->factory, result, position, item, FALSE);
g_object_unref (item);
gtk_widget_insert_after (GTK_WIDGET (result), self->widget, prev_sibling);
@ -300,7 +300,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_list_item_factory_update (self->factory, result, position, FALSE);
gtk_widget_insert_after (GTK_WIDGET (result), self->widget, prev_sibling);
/* XXX: Should we let the listview do this? */
gtk_widget_queue_resize (GTK_WIDGET (result));
@ -336,7 +336,7 @@ gtk_list_item_manager_move_list_item (GtkListItemManager *self,
gpointer item;
item = g_list_model_get_item (self->model, position);
gtk_list_item_factory_bind (self->factory, GTK_LIST_ITEM (list_item), position, item);
gtk_list_item_factory_bind (self->factory, GTK_LIST_ITEM (list_item), position, item, FALSE);
gtk_widget_insert_after (list_item, _gtk_widget_get_parent (list_item), prev_sibling);
g_object_unref (item);
}
@ -358,7 +358,7 @@ gtk_list_item_manager_update_list_item (GtkListItemManager *self,
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_factory_update (self->factory, GTK_LIST_ITEM (item), position, FALSE);
}
/*

View File

@ -30,6 +30,8 @@ void gtk_list_item_set_item (GtkListItem
gpointer item);
void gtk_list_item_set_position (GtkListItem *self,
guint position);
void gtk_list_item_set_selected (GtkListItem *self,
gboolean selected);
G_END_DECLS