[gnome-text-editor] window: move from GtkNotebook to AdwTabView



commit be489f7a88a3289516ab5551a888960a5422dcae
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jun 22 14:17:07 2021 -0700

    window: move from GtkNotebook to AdwTabView
    
    We are already using libadwaita, so we might as well use the new tabs too
    so that we stay consistent.
    
    Currently there are two sort of oddities:
    
     * We have to use "document-modified-symbolic" icon instead of the bullet
       for modified tracking, so we can use AdwTabPage:icon. This is not great
       currently in that it is only shown for the selected page.
     * Sometimes switching pages results in an empty frame until a size request
       comes in (at least on xorg/nvidia here). The gtk_widget_queue_resize()
       appears to make that go away, but maybe I'm just not hitting it now.
    
    Possibly other issues, but better to test those now.

 src/editor-window-private.h |   6 +-
 src/editor-window.c         | 163 +++++++++++++++++++++-----------------------
 src/editor-window.ui        |  19 ++++--
 3 files changed, 96 insertions(+), 92 deletions(-)
---
diff --git a/src/editor-window-private.h b/src/editor-window-private.h
index f8c7185..5b3a995 100644
--- a/src/editor-window-private.h
+++ b/src/editor-window-private.h
@@ -20,6 +20,8 @@
 
 #pragma once
 
+#include <adwaita.h>
+
 #include "editor-window.h"
 #include "editor-open-popover-private.h"
 #include "editor-position-label-private.h"
@@ -35,7 +37,9 @@ struct _EditorWindow
 
   /* Template Widgets */
   GtkWidget            *empty;
-  GtkNotebook          *notebook;
+  GtkWidget            *pages;
+  AdwTabView           *tab_view;
+  AdwTabBar            *tab_bar;
   GtkLabel             *title;
   GtkLabel             *subtitle;
   GtkLabel             *is_modified;
diff --git a/src/editor-window.c b/src/editor-window.c
index 8e21dd3..3d95856 100644
--- a/src/editor-window.c
+++ b/src/editor-window.c
@@ -133,19 +133,18 @@ editor_window_update_actions (EditorWindow *self)
 }
 
 static void
-editor_window_notify_current_page_cb (EditorWindow *self,
-                                      GParamSpec   *pspec,
-                                      GtkNotebook  *notebook)
+editor_window_notify_selected_page_cb (EditorWindow *self,
+                                       GParamSpec   *pspec,
+                                       AdwTabView   *tab_view)
 {
   EditorPage *page = NULL;
-  gint page_num;
+  AdwTabPage *tab_page;
 
   g_assert (EDITOR_IS_WINDOW (self));
-  g_assert (GTK_IS_NOTEBOOK (notebook));
+  g_assert (ADW_IS_TAB_VIEW (tab_view));
 
-  page_num = gtk_notebook_get_current_page (notebook);
-  if (page_num > -1)
-    page = EDITOR_PAGE (gtk_notebook_get_nth_page (self->notebook, page_num));
+  if ((tab_page = adw_tab_view_get_selected_page (self->tab_view)))
+    page = EDITOR_PAGE (adw_tab_page_get_child (tab_page));
 
   if (self->visible_page == page)
     return;
@@ -170,43 +169,27 @@ editor_window_notify_current_page_cb (EditorWindow *self,
     gtk_widget_grab_focus (GTK_WIDGET (page));
 
   g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_VISIBLE_PAGE]);
-}
-
-static void
-editor_window_page_added_cb (EditorWindow *self,
-                             EditorPage   *page,
-                             guint         page_num,
-                             GtkNotebook  *notebook)
-{
-  gint n_pages;
-
-  g_assert (EDITOR_IS_WINDOW (self));
-  g_assert (EDITOR_IS_PAGE (page));
-  g_assert (GTK_IS_NOTEBOOK (notebook));
 
-  n_pages = gtk_notebook_get_n_pages (notebook);
-  gtk_notebook_set_show_tabs (notebook, n_pages > 1);
-  gtk_widget_queue_resize (GTK_WIDGET (notebook));
-
-  gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->notebook));
+  /* FIXME: Sometimes we get "empty" contents for a tab page when
+   *        switching with the accelerators. This seems to make that
+   *        go away.
+   */
+  gtk_widget_queue_resize (GTK_WIDGET (self->tab_view));
 }
 
 static void
-editor_window_page_removed_cb (EditorWindow *self,
-                               EditorPage   *page,
-                               guint         page_num,
-                               GtkNotebook  *notebook)
+editor_window_items_changed_cb (EditorWindow      *self,
+                                guint              position,
+                                guint              removed,
+                                guint              added,
+                                GtkSelectionModel *model)
 {
-  gint n_pages;
-
   g_assert (EDITOR_IS_WINDOW (self));
-  g_assert (EDITOR_IS_PAGE (page));
-  g_assert (GTK_IS_NOTEBOOK (notebook));
-
-  n_pages = gtk_notebook_get_n_pages (notebook);
-  gtk_notebook_set_show_tabs (notebook, n_pages > 1);
+  g_assert (GTK_IS_SELECTION_MODEL (model));
 
-  if (n_pages == 0)
+  if (editor_window_get_n_pages (self) > 0)
+    gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->pages));
+  else
     gtk_stack_set_visible_child (self->stack, GTK_WIDGET (self->empty));
 }
 
@@ -215,14 +198,11 @@ editor_window_do_close (EditorWindow *self)
 {
   g_assert (EDITOR_IS_WINDOW (self));
 
-  g_signal_handlers_disconnect_by_func (self->notebook,
-                                        G_CALLBACK (editor_window_page_added_cb),
+  g_signal_handlers_disconnect_by_func (adw_tab_view_get_pages (self->tab_view),
+                                        G_CALLBACK (editor_window_items_changed_cb),
                                         self);
-  g_signal_handlers_disconnect_by_func (self->notebook,
-                                        G_CALLBACK (editor_window_page_removed_cb),
-                                        self);
-  g_signal_handlers_disconnect_by_func (self->notebook,
-                                        G_CALLBACK (editor_window_notify_current_page_cb),
+  g_signal_handlers_disconnect_by_func (self->tab_view,
+                                        G_CALLBACK (editor_window_notify_selected_page_cb),
                                         self);
 
   _editor_session_remove_window (EDITOR_SESSION_DEFAULT, self);
@@ -258,10 +238,10 @@ editor_window_close_request (GtkWindow *window)
    * ask the user what they'd like us to do with them.
    */
   unsaved = g_ptr_array_new_with_free_func (g_object_unref);
-  n_pages = gtk_notebook_get_n_pages (self->notebook);
+  n_pages = adw_tab_view_get_n_pages (self->tab_view);
   for (guint i = 0; i < n_pages; i++)
     {
-      EditorPage *page = EDITOR_PAGE (gtk_notebook_get_nth_page (self->notebook, i));
+      EditorPage *page = editor_window_get_nth_page (self, i);
 
       if (editor_page_get_is_modified (page))
         g_ptr_array_add (unsaved, g_object_ref (page));
@@ -419,14 +399,16 @@ editor_window_class_init (EditorWindowClass *klass)
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, empty);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, export_menu);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, is_modified);
-  gtk_widget_class_bind_template_child (widget_class, EditorWindow, notebook);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, open_menu_button);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, open_menu_popover);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, options_menu);
+  gtk_widget_class_bind_template_child (widget_class, EditorWindow, pages);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, position_box);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, position_label);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, primary_menu);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, subtitle);
+  gtk_widget_class_bind_template_child (widget_class, EditorWindow, tab_bar);
+  gtk_widget_class_bind_template_child (widget_class, EditorWindow, tab_view);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, title);
   gtk_widget_class_bind_template_child (widget_class, EditorWindow, stack);
 
@@ -476,17 +458,13 @@ editor_window_init (EditorWindow *self)
                            self,
                            G_CONNECT_SWAPPED);
 
-  g_signal_connect_swapped (self->notebook,
-                            "page-added",
-                            G_CALLBACK (editor_window_page_added_cb),
-                            self);
-  g_signal_connect_swapped (self->notebook,
-                            "page-removed",
-                            G_CALLBACK (editor_window_page_removed_cb),
+  g_signal_connect_swapped (adw_tab_view_get_pages (self->tab_view),
+                            "items-changed",
+                            G_CALLBACK (editor_window_items_changed_cb),
                             self);
-  g_signal_connect_swapped (self->notebook,
-                            "notify::page",
-                            G_CALLBACK (editor_window_notify_current_page_cb),
+  g_signal_connect_swapped (self->tab_view,
+                            "notify::selected-page",
+                            G_CALLBACK (editor_window_notify_selected_page_cb),
                             self);
 
   self->page_signals = editor_signal_group_new (EDITOR_TYPE_PAGE);
@@ -560,53 +538,68 @@ _editor_window_get_pages (EditorWindow *self)
 
   g_return_val_if_fail (EDITOR_IS_WINDOW (self), NULL);
 
-  n_pages = gtk_notebook_get_n_pages (self->notebook);
+  n_pages = editor_window_get_n_pages (self);
 
   for (guint i = 0; i < n_pages; i++)
-    {
-      GtkWidget *child = gtk_notebook_get_nth_page (self->notebook, i);
-      g_queue_push_tail (&queue, EDITOR_PAGE (child));
-    }
+    g_queue_push_tail (&queue, editor_window_get_nth_page (self, i));
 
   return g_steal_pointer (&queue.head);
 }
 
+static gboolean
+modified_to_icon (GBinding     *binding,
+                  const GValue *from_value,
+                  GValue       *to_value,
+                  gpointer      user_data)
+{
+  static GIcon *icon;
+
+  if (icon == NULL)
+    icon = g_themed_icon_new ("document-modified-symbolic");
+
+  if (g_value_get_boolean (from_value))
+    g_value_set_object (to_value, icon);
+
+  return TRUE;
+}
+
 void
 _editor_window_add_page (EditorWindow *self,
                          EditorPage   *page)
 {
-  EditorTab *tab;
+  AdwTabPage *tab_page;
 
   g_return_if_fail (EDITOR_IS_WINDOW (self));
   g_return_if_fail (EDITOR_IS_PAGE (page));
 
-  tab = _editor_tab_new (page);
+  tab_page = adw_tab_view_append (self->tab_view, GTK_WIDGET (page));
 
-  gtk_notebook_append_page (self->notebook,
-                            GTK_WIDGET (page),
-                            GTK_WIDGET (tab));
+  g_object_bind_property (page, "title", tab_page, "title", G_BINDING_SYNC_CREATE);
+  g_object_bind_property (page, "busy", tab_page, "loading", G_BINDING_SYNC_CREATE);
+  g_object_bind_property_full (page, "is-modified",
+                               tab_page, "icon",
+                               G_BINDING_SYNC_CREATE,
+                               modified_to_icon, NULL,
+                               NULL, NULL);
 
-  g_object_set (gtk_notebook_get_page (self->notebook, GTK_WIDGET (page)),
-                "reorderable", TRUE,
-                NULL);
+  adw_tab_view_set_selected_page (self->tab_view, tab_page);
 }
 
 void
 _editor_window_remove_page (EditorWindow *self,
                             EditorPage   *page)
 {
-  gint page_num;
+  AdwTabPage *tab_page;
 
   g_return_if_fail (EDITOR_IS_WINDOW (self));
   g_return_if_fail (EDITOR_IS_PAGE (page));
 
-  page_num = gtk_notebook_page_num (self->notebook, GTK_WIDGET (page));
-  if (page_num >= 0)
-    gtk_notebook_remove_page (self->notebook, page_num);
+  tab_page = adw_tab_view_get_page (self->tab_view, GTK_WIDGET (page));
+  adw_tab_view_close_page (self->tab_view, tab_page);
 
   if (self->visible_page == page)
     {
-      editor_window_notify_current_page_cb (self, NULL, self->notebook);
+      editor_window_notify_selected_page_cb (self, NULL, self->tab_view);
 
       if (self->visible_page != NULL)
         gtk_widget_grab_focus (GTK_WIDGET (self->visible_page));
@@ -640,15 +633,13 @@ void
 editor_window_set_visible_page (EditorWindow *self,
                                 EditorPage   *page)
 {
-  gint page_num;
+  AdwTabPage *tab_page;
 
   g_return_if_fail (EDITOR_IS_WINDOW (self));
   g_return_if_fail (EDITOR_IS_PAGE (page));
 
-  page_num = gtk_notebook_page_num (self->notebook, GTK_WIDGET (page));
-
-  if (page_num >= 0)
-    gtk_notebook_set_current_page (self->notebook, page_num);
+  if ((tab_page = adw_tab_view_get_page (self->tab_view, GTK_WIDGET (page))))
+    adw_tab_view_set_selected_page (self->tab_view, tab_page);
 }
 
 /**
@@ -664,12 +655,14 @@ EditorPage *
 editor_window_get_nth_page (EditorWindow *self,
                             guint         nth)
 {
+  AdwTabPage *tab_page;
+
   g_return_val_if_fail (EDITOR_IS_WINDOW (self), NULL);
 
-  if (nth >= gtk_notebook_get_n_pages (self->notebook))
-    return NULL;
+  if ((tab_page = adw_tab_view_get_nth_page (self->tab_view, nth)))
+    return EDITOR_PAGE (adw_tab_page_get_child (tab_page));
 
-  return EDITOR_PAGE (gtk_notebook_get_nth_page (self->notebook, nth));
+  return NULL;
 }
 
 /**
@@ -685,7 +678,7 @@ editor_window_get_n_pages (EditorWindow *self)
 {
   g_return_val_if_fail (EDITOR_IS_WINDOW (self), 0);
 
-  return gtk_notebook_get_n_pages (self->notebook);
+  return adw_tab_view_get_n_pages (self->tab_view);
 }
 
 void
diff --git a/src/editor-window.ui b/src/editor-window.ui
index 0bc74e9..6e26097 100644
--- a/src/editor-window.ui
+++ b/src/editor-window.ui
@@ -120,12 +120,19 @@
               <class name="view"/>
             </style>
             <child>
-              <object class="GtkNotebook" id="notebook">
-                <property name="scrollable">true</property>
-                <property name="show-border">false</property>
-                <property name="show-tabs">false</property>
-                <property name="hexpand">true</property>
-                <property name="vexpand">true</property>
+              <object class="GtkBox" id="pages">
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="AdwTabBar" id="tab_bar">
+                    <property name="view">tab_view</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="AdwTabView" id="tab_view">
+                    <property name="hexpand">true</property>
+                    <property name="vexpand">true</property>
+                  </object>
+                </child>
               </object>
             </child>
             <child>


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