[gnome-text-editor] popover: use GtkListBox instead of GtkListView



commit 130144e7b0104421f06ed11d9c8c04a3bdb3d652
Author: Christian Hergert <chergert redhat com>
Date:   Thu Oct 28 15:28:24 2021 -0700

    popover: use GtkListBox instead of GtkListView
    
    There appears to be a lot of cycling of widgetry in GtkListView which
    results in extra action muxer work. Instead, we can go with something
    much simpler since we have relatively small lists of recents.
    
    Related #192

 src/editor-open-popover.c        | 160 +++++++++++++--------------------------
 src/editor-open-popover.ui       |  14 +---
 src/editor-sidebar-row-private.h |   2 +-
 src/editor-sidebar-row.c         |   4 +-
 src/editor-sidebar-row.ui        |   2 +-
 5 files changed, 61 insertions(+), 121 deletions(-)
---
diff --git a/src/editor-open-popover.c b/src/editor-open-popover.c
index 26b2ad6..070fb96 100644
--- a/src/editor-open-popover.c
+++ b/src/editor-open-popover.c
@@ -34,8 +34,9 @@ struct _EditorOpenPopover
   GtkPopover      parent_instance;
 
   GListModel     *model;
+  GListModel     *filtered_model;
 
-  GtkListView    *list_view;
+  GtkListBox     *list_box;
   GtkWidget      *box;
   GtkSearchEntry *search_entry;
   GtkStack       *stack;
@@ -59,6 +60,17 @@ _editor_open_popover_new (void)
   return g_object_new (EDITOR_TYPE_OPEN_POPOVER, NULL);
 }
 
+static GListModel *
+editor_open_popover_get_model (EditorOpenPopover *self)
+{
+  g_assert (EDITOR_IS_OPEN_POPOVER (self));
+
+  if (self->filtered_model)
+    return self->filtered_model;
+
+  return self->model;
+}
+
 static void
 popover_hide (GtkWidget  *widget,
               const char *action_name,
@@ -72,67 +84,37 @@ popover_hide (GtkWidget  *widget,
   gtk_menu_button_popdown (GTK_MENU_BUTTON (parent));
 }
 
-static void
-on_list_item_bind_cb (EditorOpenPopover        *self,
-                      GtkListItem              *list_item,
-                      GtkSignalListItemFactory *factory)
-{
-  EditorSidebarItem *item;
-  GtkWidget *child;
-
-  g_assert (EDITOR_IS_OPEN_POPOVER (self));
-  g_assert (GTK_IS_LIST_ITEM (list_item));
-  g_assert (GTK_IS_SIGNAL_LIST_ITEM_FACTORY (factory));
-
-  if (!(child = gtk_list_item_get_child (list_item)))
-    {
-      child = _editor_sidebar_row_new ();
-      gtk_list_item_set_child (list_item, child);
-    }
-
-  item = gtk_list_item_get_item (list_item);
-  _editor_sidebar_row_set_item (EDITOR_SIDEBAR_ROW (child), item);
-}
-
-static void
-on_list_item_unbind_cb (EditorOpenPopover        *self,
-                        GtkListItem              *list_item,
-                        GtkSignalListItemFactory *factory)
+static GtkWidget *
+create_row (gpointer itemptr,
+            gpointer user_data)
 {
-  GtkWidget *child;
+  EditorSidebarItem *item = itemptr;
 
-  g_assert (EDITOR_IS_OPEN_POPOVER (self));
-  g_assert (GTK_IS_LIST_ITEM (list_item));
-  g_assert (GTK_IS_SIGNAL_LIST_ITEM_FACTORY (factory));
+  g_assert (EDITOR_IS_SIDEBAR_ITEM (item));
 
-  child = gtk_list_item_get_child (list_item);
-  _editor_sidebar_row_set_item (EDITOR_SIDEBAR_ROW (child), NULL);
+  return g_object_new (EDITOR_TYPE_SIDEBAR_ROW,
+                       "item", item,
+                       NULL);
 }
 
 static void
-on_list_view_activate_cb (EditorOpenPopover *self,
-                          guint              position,
-                          GtkListView       *list_view)
+on_list_box_row_activated_cb (EditorOpenPopover *self,
+                              EditorSidebarRow  *row,
+                              GtkListBox        *list_box)
 {
-  GtkSelectionModel *model;
-  EditorSession *session;
+  EditorSidebarItem *item;
   EditorWindow *window;
 
   g_assert (EDITOR_IS_OPEN_POPOVER (self));
-  g_assert (GTK_IS_LIST_VIEW (list_view));
+  g_assert (EDITOR_IS_SIDEBAR_ROW (row));
+  g_assert (GTK_IS_LIST_BOX (list_box));
 
-  session = editor_application_get_session (EDITOR_APPLICATION_DEFAULT);
   window = EDITOR_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
-  model = gtk_list_view_get_model (list_view);
+  item = _editor_sidebar_row_get_item (row);
 
-  if (position < g_list_model_get_n_items (G_LIST_MODEL (model)))
-    {
-      g_autoptr(EditorSidebarItem) item = g_list_model_get_item (G_LIST_MODEL (model), position);
-
-      gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
-      _editor_sidebar_item_open (item, session, window);
-      popover_hide (GTK_WIDGET (self), NULL, NULL);
-    }
+  gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
+  _editor_sidebar_item_open (item, EDITOR_SESSION_DEFAULT, window);
+  popover_hide (GTK_WIDGET (self), NULL, NULL);
 }
 
 static gboolean
@@ -183,23 +165,33 @@ on_search_entry_changed_cb (EditorOpenPopover *self,
   g_assert (model != NULL);
   g_assert (G_IS_LIST_MODEL (model));
 
-  selection = gtk_single_selection_new (g_object_ref (model));
-  gtk_list_view_set_model (self->list_view, GTK_SELECTION_MODEL (selection));
+  gtk_list_box_bind_model (self->list_box, model, create_row, NULL, NULL);
+
+  g_set_object (&self->filtered_model, model);
 }
 
 static void
 on_search_entry_activate_cb (EditorOpenPopover *self,
                              GtkSearchEntry    *search_entry)
 {
-  GtkSelectionModel *model;
-  EditorSidebarItem *item;
+  GListModel *model;
 
   g_assert (EDITOR_IS_OPEN_POPOVER (self));
   g_assert (GTK_IS_SEARCH_ENTRY (search_entry));
 
-  if ((model = gtk_list_view_get_model (self->list_view)) &&
-      (item = gtk_single_selection_get_selected_item (GTK_SINGLE_SELECTION (model))))
-    on_list_view_activate_cb (self, 0, self->list_view);
+  if ((model = editor_open_popover_get_model (self)) &&
+      g_list_model_get_n_items (model) > 0)
+    {
+      g_autoptr(EditorSidebarItem) item = g_list_model_get_item (model, 0);
+      EditorWindow *window;
+
+      gtk_editable_set_text (GTK_EDITABLE (self->search_entry), "");
+
+      window = EDITOR_WINDOW (gtk_widget_get_root (GTK_WIDGET (self)));
+      _editor_sidebar_item_open (item, EDITOR_SESSION_DEFAULT, window);
+
+      popover_hide (GTK_WIDGET (self), NULL, NULL);
+    }
 }
 
 static void
@@ -223,44 +215,6 @@ on_search_entry_stop_search_cb (EditorOpenPopover *self,
     }
 }
 
-static void
-editor_open_popover_show (GtkWidget *widget)
-{
-  EditorOpenPopover *self = (EditorOpenPopover *)widget;
-  GtkSelectionModel *model;
-
-  g_assert (EDITOR_IS_OPEN_POPOVER (self));
-
-  if ((model = gtk_list_view_get_model (self->list_view)))
-    gtk_single_selection_set_selected (GTK_SINGLE_SELECTION (model), 0);
-
-  GTK_WIDGET_CLASS (editor_open_popover_parent_class)->show (widget);
-}
-
-static void
-on_remove_row_cb (GtkWidget  *widget,
-                  const char *action_name,
-                  GVariant   *param)
-{
-  EditorOpenPopover *self = (EditorOpenPopover *)widget;
-  g_autoptr(GFile) file = NULL;
-  const char *uri;
-  const char *draft_id;
-
-  g_assert (EDITOR_IS_OPEN_POPOVER (self));
-  g_assert (g_variant_is_of_type (param, G_VARIANT_TYPE ("(ss)")));
-
-  g_variant_get (param, "(&s&s)", &uri, &draft_id);
-
-  if (uri[0] != 0)
-    file = g_file_new_for_uri (uri);
-
-  if (draft_id[0] == 0)
-    draft_id = NULL;
-
-  _editor_session_forget (EDITOR_SESSION_DEFAULT, file, draft_id);
-}
-
 static void
 editor_open_popover_dispose (GObject *object)
 {
@@ -268,6 +222,7 @@ editor_open_popover_dispose (GObject *object)
 
   g_clear_pointer (&self->box, gtk_widget_unparent);
   g_clear_object (&self->model);
+  g_clear_object (&self->filtered_model);
 
   G_OBJECT_CLASS (editor_open_popover_parent_class)->dispose (object);
 }
@@ -320,8 +275,6 @@ editor_open_popover_class_init (EditorOpenPopoverClass *klass)
   object_class->get_property = editor_open_popover_get_property;
   object_class->set_property = editor_open_popover_set_property;
 
-  widget_class->show = editor_open_popover_show;
-
   properties [PROP_MODEL] =
     g_param_spec_object ("model",
                          "Model",
@@ -335,17 +288,13 @@ editor_open_popover_class_init (EditorOpenPopoverClass *klass)
   gtk_widget_class_bind_template_child (widget_class, EditorOpenPopover, box);
   gtk_widget_class_bind_template_child (widget_class, EditorOpenPopover, empty);
   gtk_widget_class_bind_template_child (widget_class, EditorOpenPopover, search_entry);
-  gtk_widget_class_bind_template_child (widget_class, EditorOpenPopover, list_view);
+  gtk_widget_class_bind_template_child (widget_class, EditorOpenPopover, list_box);
   gtk_widget_class_bind_template_child (widget_class, EditorOpenPopover, recent);
   gtk_widget_class_bind_template_child (widget_class, EditorOpenPopover, stack);
-  gtk_widget_class_bind_template_callback (widget_class, on_list_item_bind_cb);
-  gtk_widget_class_bind_template_callback (widget_class, on_list_item_unbind_cb);
-  gtk_widget_class_bind_template_callback (widget_class, on_list_view_activate_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_list_box_row_activated_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_search_entry_activate_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_search_entry_changed_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_search_entry_stop_search_cb);
-
-  gtk_widget_class_install_action (widget_class, "row.remove", "(ss)", on_remove_row_cb);
 }
 
 static void
@@ -385,7 +334,7 @@ _editor_open_popover_set_model (EditorOpenPopover *self,
 
   if (g_set_object (&self->model, model))
     {
-      g_autoptr(GtkSingleSelection) selection = NULL;
+      g_clear_object (&self->filtered_model);
 
       if (model != NULL)
         {
@@ -395,13 +344,10 @@ _editor_open_popover_set_model (EditorOpenPopover *self,
                                    self,
                                    G_CONNECT_SWAPPED);
 
-          selection = gtk_single_selection_new (g_object_ref (model));
-          gtk_single_selection_set_autoselect (selection, FALSE);
-
           editor_open_popover_items_changed_cb (self, 0, 0, 0, model);
         }
 
-      gtk_list_view_set_model (self->list_view, GTK_SELECTION_MODEL (selection));
+      gtk_list_box_bind_model (self->list_box, model, create_row, NULL, NULL);
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MODEL]);
     }
 }
diff --git a/src/editor-open-popover.ui b/src/editor-open-popover.ui
index fce5680..34bd410 100644
--- a/src/editor-open-popover.ui
+++ b/src/editor-open-popover.ui
@@ -59,16 +59,10 @@
                     <property name="propagate-natural-width">True</property>
                     <property name="vexpand">True</property>
                     <child>
-                      <object class="GtkListView" id="list_view">
-                        <signal name="activate" handler="on_list_view_activate_cb" swapped="true" 
object="EditorOpenPopover"/>
-                        <property name="orientation">vertical</property>
-                        <property name="single-click-activate">True</property>
-                        <property name="factory">
-                          <object class="GtkSignalListItemFactory">
-                            <signal name="bind" handler="on_list_item_bind_cb" swapped="true" 
object="EditorOpenPopover"/>
-                            <signal name="unbind" handler="on_list_item_unbind_cb" swapped="true" 
object="EditorOpenPopover"/>
-                          </object>
-                        </property>
+                      <object class="GtkListBox" id="list_box">
+                        <signal name="row-activated" handler="on_list_box_row_activated_cb" swapped="true" 
object="EditorOpenPopover"/>
+                        <property name="activate-on-single-click">True</property>
+                        <property name="selection-mode">none</property>
                       </object>
                     </child>
                   </object>
diff --git a/src/editor-sidebar-row-private.h b/src/editor-sidebar-row-private.h
index 9f0289e..88f6c80 100644
--- a/src/editor-sidebar-row-private.h
+++ b/src/editor-sidebar-row-private.h
@@ -26,7 +26,7 @@ G_BEGIN_DECLS
 
 #define EDITOR_TYPE_SIDEBAR_ROW (editor_sidebar_row_get_type())
 
-G_DECLARE_FINAL_TYPE (EditorSidebarRow, editor_sidebar_row, EDITOR, SIDEBAR_ROW, GtkWidget)
+G_DECLARE_FINAL_TYPE (EditorSidebarRow, editor_sidebar_row, EDITOR, SIDEBAR_ROW, GtkListBoxRow)
 
 GtkWidget         *_editor_sidebar_row_new      (void);
 void               _editor_sidebar_row_set_item (EditorSidebarRow  *self,
diff --git a/src/editor-sidebar-row.c b/src/editor-sidebar-row.c
index e3e8996..323eced 100644
--- a/src/editor-sidebar-row.c
+++ b/src/editor-sidebar-row.c
@@ -32,7 +32,7 @@
 
 struct _EditorSidebarRow
 {
-  GtkWidget          parent_instance;
+  GtkListBoxRow      parent_instance;
 
   EditorSidebarItem *item;
 
@@ -58,7 +58,7 @@ enum {
   N_PROPS
 };
 
-G_DEFINE_TYPE (EditorSidebarRow, editor_sidebar_row, GTK_TYPE_WIDGET)
+G_DEFINE_TYPE (EditorSidebarRow, editor_sidebar_row, GTK_TYPE_LIST_BOX_ROW)
 
 static GParamSpec *properties [N_PROPS];
 
diff --git a/src/editor-sidebar-row.ui b/src/editor-sidebar-row.ui
index dd1571b..014b03c 100644
--- a/src/editor-sidebar-row.ui
+++ b/src/editor-sidebar-row.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="4.0"/>
-  <template class="EditorSidebarRow" parent="GtkWidget">
+  <template class="EditorSidebarRow" parent="GtkListBoxRow">
     <child>
       <object class="GtkGrid" id="grid">
         <property name="margin-top">3</property>


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