[gtk/wip/otte/listview: 118/133] listview: Add ::focus-position and ::focus-item




commit 958ce1924469d1ba1d40374f1b7d027d6bd5e087
Author: Benjamin Otte <otte redhat com>
Date:   Mon Feb 14 00:29:32 2022 +0100

    listview: Add ::focus-position and ::focus-item
    
    Hands out the row that gets/would get keyboard focus and allows setting
    it.

 gtk/gtklistbase.c               |  12 ++++-
 gtk/gtklistbaseprivate.h        |   1 +
 gtk/gtklistitemmanager.c        |  10 ++++
 gtk/gtklistitemmanagerprivate.h |   2 +
 gtk/gtklistview.c               | 116 ++++++++++++++++++++++++++++++++++++++++
 gtk/gtklistview.h               |   8 +++
 6 files changed, 148 insertions(+), 1 deletion(-)
---
diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c
index f29ffec23a..1b1995a261 100644
--- a/gtk/gtklistbase.c
+++ b/gtk/gtklistbase.c
@@ -483,6 +483,14 @@ gtk_list_base_get_focus_position (GtkListBase *self)
   return gtk_list_item_tracker_get_position (priv->item_manager, priv->focus);
 }
 
+gpointer
+gtk_list_base_get_focus_item (GtkListBase *self)
+{
+  GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self);
+
+  return gtk_list_item_tracker_get_item (priv->item_manager, priv->focus);
+}
+
 static gboolean
 gtk_list_base_focus (GtkWidget        *widget,
                      GtkDirectionType  direction)
@@ -1805,7 +1813,9 @@ gtk_list_base_init_real (GtkListBase      *self,
   priv->anchor_side_along = GTK_PACK_START;
   priv->anchor_side_across = GTK_PACK_START;
   priv->selected = gtk_list_item_tracker_new (priv->item_manager, NULL, NULL);
-  priv->focus = gtk_list_item_tracker_new (priv->item_manager, NULL, NULL);
+  priv->focus = gtk_list_item_tracker_new (priv->item_manager,
+                                           g_object_class_find_property (G_OBJECT_CLASS (g_class), 
"focus-position"),
+                                           g_object_class_find_property (G_OBJECT_CLASS (g_class), 
"focus-item"));
 
   priv->adjustment[GTK_ORIENTATION_HORIZONTAL] = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
   g_object_ref_sink (priv->adjustment[GTK_ORIENTATION_HORIZONTAL]);
diff --git a/gtk/gtklistbaseprivate.h b/gtk/gtklistbaseprivate.h
index 75d7466784..55782df153 100644
--- a/gtk/gtklistbaseprivate.h
+++ b/gtk/gtklistbaseprivate.h
@@ -68,6 +68,7 @@ struct _GtkListBaseClass
 GtkOrientation         gtk_list_base_get_orientation            (GtkListBase            *self);
 #define gtk_list_base_get_opposite_orientation(self) 
OPPOSITE_ORIENTATION(gtk_list_base_get_orientation(self))
 guint                  gtk_list_base_get_focus_position         (GtkListBase            *self);
+gpointer               gtk_list_base_get_focus_item             (GtkListBase            *self);
 GtkListItemManager *   gtk_list_base_get_manager                (GtkListBase            *self);
 GtkScrollablePolicy    gtk_list_base_get_scroll_policy          (GtkListBase            *self,
                                                                  GtkOrientation          orientation);
diff --git a/gtk/gtklistitemmanager.c b/gtk/gtklistitemmanager.c
index b623dbd9f9..a4e84733eb 100644
--- a/gtk/gtklistitemmanager.c
+++ b/gtk/gtklistitemmanager.c
@@ -1269,3 +1269,13 @@ gtk_list_item_tracker_get_position (GtkListItemManager *self,
 {
   return tracker->position;
 }
+
+gpointer
+gtk_list_item_tracker_get_item (GtkListItemManager *self,
+                                GtkListItemTracker *tracker)
+{
+  if (tracker->widget == NULL)
+    return NULL;
+
+  return gtk_list_item_widget_get_item (tracker->widget);
+}
diff --git a/gtk/gtklistitemmanagerprivate.h b/gtk/gtklistitemmanagerprivate.h
index cb4655e3fc..57f760bd09 100644
--- a/gtk/gtklistitemmanagerprivate.h
+++ b/gtk/gtklistitemmanagerprivate.h
@@ -113,6 +113,8 @@ void                    gtk_list_item_tracker_set_position      (GtkListItemMana
                                                                  guint                   n_after);
 guint                   gtk_list_item_tracker_get_position      (GtkListItemManager     *self,
                                                                  GtkListItemTracker     *tracker);
+gpointer                gtk_list_item_tracker_get_item          (GtkListItemManager     *self,
+                                                                 GtkListItemTracker     *tracker);
 
 
 G_END_DECLS
diff --git a/gtk/gtklistview.c b/gtk/gtklistview.c
index fc56960fdc..c7884a465e 100644
--- a/gtk/gtklistview.c
+++ b/gtk/gtklistview.c
@@ -161,6 +161,8 @@ enum
 {
   PROP_0,
   PROP_FACTORY,
+  PROP_FOCUS_ITEM,
+  PROP_FOCUS_POSITION,
   PROP_MODEL,
   PROP_SHOW_SEPARATORS,
   PROP_SINGLE_CLICK_ACTIVATE,
@@ -708,6 +710,14 @@ gtk_list_view_get_property (GObject    *object,
       g_value_set_object (value, gtk_list_item_manager_get_factory (self->item_manager));
       break;
 
+    case PROP_FOCUS_ITEM:
+      g_value_set_object (value, gtk_list_base_get_focus_item (GTK_LIST_BASE (self)));
+      break;
+
+    case PROP_FOCUS_POSITION:
+      g_value_set_uint (value, gtk_list_base_get_focus_position (GTK_LIST_BASE (self)));
+      break;
+
     case PROP_MODEL:
       g_value_set_object (value, gtk_list_base_get_model (GTK_LIST_BASE (self)));
       break;
@@ -744,6 +754,10 @@ gtk_list_view_set_property (GObject      *object,
       gtk_list_view_set_factory (self, g_value_get_object (value));
       break;
 
+    case PROP_FOCUS_POSITION:
+      gtk_list_view_set_focus_position (self, g_value_get_uint (value));
+      break;
+
     case PROP_MODEL:
       gtk_list_view_set_model (self, g_value_get_object (value));
       break;
@@ -822,6 +836,35 @@ gtk_list_view_class_init (GtkListViewClass *klass)
                          GTK_TYPE_LIST_ITEM_FACTORY,
                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
 
+  /**
+   * GtkListView:focus-position: (attributes org.gtk.Property.get=gtk_list_view_get_focus_position 
org.gtk.Property.set=gtk_list_view_set_focus_position)
+   *
+   * The position of the focused item.
+   *
+   * If no item is in focus, the property has the value
+   * %GTK_INVALID_LIST_POSITION.
+   */
+  properties[PROP_FOCUS_POSITION] =
+    g_param_spec_uint ("focus-position",
+                         P_("Focus position"),
+                         P_("Position of the focused item"),
+                         0, G_MAXUINT, GTK_INVALID_LIST_POSITION,
+                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+  /**
+   * GtkListView:focus-item: (attributes org.gtk.Property.get=gtk_list_view_get_focus_item)
+   *
+   * The focused item.
+   *
+   * If the list is empty, %NULL is returned.
+   */
+  properties[PROP_FOCUS_ITEM] =
+    g_param_spec_object ("focus-item",
+                       P_("Focused Item"),
+                       P_("The focused item"),
+                       G_TYPE_OBJECT,
+                       G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
   /**
    * GtkListView:model: (attributes org.gtk.Property.get=gtk_list_view_get_model 
org.gtk.Property.set=gtk_list_view_set_model)
    *
@@ -1043,6 +1086,78 @@ gtk_list_view_set_factory (GtkListView        *self,
   g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FACTORY]);
 }
 
+/**
+ * gtk_list_view_set_focus_position: (attributes org.gtk.Method.set_property=focus-position)
+ * @self: a `GtkListView`
+ * @position: position of item to focus
+ *
+ * Sets focus to be given to the item at the given position.
+ * If position is larger than the number of items, this call is ignored.
+ * 
+ * Moving keyboard focus will select the new item and scroll it into view.
+ *
+ * The operation will be performed even if the listview is hidden.
+ * 
+ * If keyboard focus is not currently inside the listview, the application's
+ * keyboard focus will not change. Call gtk_widget_grab_focus() on the listview
+ * afterwards to move application keyboard focus.
+ *
+ * Since: 4.8
+ */
+void
+gtk_list_view_set_focus_position (GtkListView *self,
+                                  guint        position)
+{
+  g_return_if_fail (GTK_IS_LIST_VIEW (self));
+
+  gtk_list_base_grab_focus_on_item (GTK_LIST_BASE (self), position, TRUE, FALSE, FALSE);
+}
+
+/**
+ * gtk_list_view_get_focus_position: (attributes org.gtk.Method.get_property=focus-position)
+ * @self: a `GtkListView`
+ *
+ * Gets the position of the item that currently has keyboard focus - or that
+ * would have keyboard focus if the listview was focused.
+ *
+ * Note that the focused item might not be in the visible region, for example when
+ * the visible region was scrolled with the mouse.
+ *
+ * Returns: the position of the focused item, or %GTK_INVALID_LIST_POSITION
+ *   if the listview is empty
+ *
+ * Since: 4.8
+ */
+guint
+gtk_list_view_get_focus_position (GtkListView *self)
+{
+  g_return_val_if_fail (GTK_IS_LIST_VIEW (self), GTK_INVALID_LIST_POSITION);
+
+  return gtk_list_base_get_focus_position (GTK_LIST_BASE (self));
+}
+
+/**
+ * gtk_list_view_get_focus_item: (attributes org.gtk.Method.get_property=focus-item)
+ * @self: a `GtkListView`
+ *
+ * Gets the item that currently has keyboard focus - or that would have keyboard
+ * focus if the listview was focused.
+ *
+ * Note that the focused item might not be in the visible region, for example when
+ * the visible region was scrolled with the mouse.
+ *
+ * Returns: (transfer none) (type GObject) (nullable): The fcoused item
+ *
+ * Since: 4.8
+ **/
+gpointer
+gtk_list_view_get_focus_item (GtkListView *self)
+{
+  g_return_val_if_fail (GTK_IS_LIST_VIEW (self), NULL);
+
+  return gtk_list_base_get_focus_item (GTK_LIST_BASE (self));
+}
+
 /**
  * gtk_list_view_set_show_separators: (attributes org.gtk.Method.set_property=show-separators)
  * @self: a `GtkListView`
@@ -1162,3 +1277,4 @@ gtk_list_view_get_enable_rubberband (GtkListView *self)
 
   return gtk_list_base_get_enable_rubberband (GTK_LIST_BASE (self));
 }
+
diff --git a/gtk/gtklistview.h b/gtk/gtklistview.h
index 2664b07afb..8b1bdf7663 100644
--- a/gtk/gtklistview.h
+++ b/gtk/gtklistview.h
@@ -58,6 +58,14 @@ GDK_AVAILABLE_IN_ALL
 GtkListItemFactory *
                 gtk_list_view_get_factory                       (GtkListView            *self);
 
+GDK_AVAILABLE_IN_4_8
+void            gtk_list_view_set_focus_position                (GtkListView            *self,
+                                                                 guint                   position);
+GDK_AVAILABLE_IN_4_8
+guint           gtk_list_view_get_focus_position                (GtkListView            *self);
+GDK_AVAILABLE_IN_4_8
+gpointer        gtk_list_view_get_focus_item                    (GtkListView            *self);
+
 GDK_AVAILABLE_IN_ALL
 void            gtk_list_view_set_show_separators               (GtkListView            *self,
                                                                  gboolean                show_separators);


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