[gtk/wip/otte/listview: 47/158] listview: Add selection properties to ListItem



commit 2df5ef4840ea16fa7c138b0e09024deed8b35669
Author: Benjamin Otte <otte redhat com>
Date:   Sat Sep 29 22:34:43 2018 +0200

    listview: Add selection properties to ListItem
    
    This just brings the infrastructure into place, we're not using the
    properties yet.

 docs/reference/gtk/gtk4-sections.txt |   3 +
 gtk/gtklistitem.c                    | 128 +++++++++++++++++++++++++++++++++++
 gtk/gtklistitem.h                    |   8 +++
 gtk/gtklistitemfactory.c             |  13 +++-
 gtk/gtklistitemfactoryprivate.h      |   6 +-
 gtk/gtklistitemmanager.c             |   8 +--
 gtk/gtklistitemprivate.h             |   2 +
 7 files changed, 160 insertions(+), 8 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 7e0dc421d6..b15b65f5dd 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -498,6 +498,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
diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c
index ac4fda6737..a11b8b3cc8 100644
--- a/gtk/gtklistitem.c
+++ b/gtk/gtklistitem.c
@@ -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]);
+}
diff --git a/gtk/gtklistitem.h b/gtk/gtklistitem.h
index dff9c889ee..4cfadd8996 100644
--- a/gtk/gtklistitem.h
+++ b/gtk/gtklistitem.h
@@ -72,6 +72,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,
diff --git a/gtk/gtklistitemfactory.c b/gtk/gtklistitemfactory.c
index 7b22920b87..4a84776fc5 100644
--- a/gtk/gtklistitemfactory.c
+++ b/gtk/gtklistitemfactory.c
@@ -154,7 +154,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));
@@ -163,6 +164,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);
@@ -173,12 +175,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
@@ -192,6 +200,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));
 }
diff --git a/gtk/gtklistitemfactoryprivate.h b/gtk/gtklistitemfactoryprivate.h
index 779251344b..3e815fa131 100644
--- a/gtk/gtklistitemfactoryprivate.h
+++ b/gtk/gtklistitemfactoryprivate.h
@@ -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);
 
diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c
index 62888f366a..1e74c8d8e1 100644
--- a/gtk/gtklistitemmanager.c
+++ b/gtk/gtklistitemmanager.c
@@ -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);
 }
 
 /*
diff --git a/gtk/gtklistitemprivate.h b/gtk/gtklistitemprivate.h
index f238685c76..08ed82f162 100644
--- a/gtk/gtklistitemprivate.h
+++ b/gtk/gtklistitemprivate.h
@@ -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
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]