[gnome-text-editor] tab-menu: implement tab menus for tab bar



commit 4f0aa0a0a09725f932e7a72d147313012f1427c9
Author: Christian Hergert <chergert redhat com>
Date:   Tue Oct 26 15:15:03 2021 -0700

    tab-menu: implement tab menus for tab bar
    
    These were lost during the transition from notebook back to AdwTabBar. We
    also handle the cases with modified pages a bit better now by joining them
    together into a single dialog request.
    
    Fixes #199

 src/editor-page-private.h   |   3 ++
 src/editor-page.c           |  18 ++++++++
 src/editor-session.c        |  15 ++++---
 src/editor-window-actions.c |  23 ++++++++++
 src/editor-window-private.h |   3 ++
 src/editor-window.c         | 102 +++++++++++++++++++++++++++++++++++---------
 src/editor-window.ui        |   1 +
 src/menus.ui                |  10 ++---
 8 files changed, 144 insertions(+), 31 deletions(-)
---
diff --git a/src/editor-page-private.h b/src/editor-page-private.h
index 6a3b936..43f6b61 100644
--- a/src/editor-page-private.h
+++ b/src/editor-page-private.h
@@ -59,6 +59,7 @@ struct _EditorPage
   GtkInfoBar              *infobar;
 
   guint                    close_requested : 1;
+  guint                    moving : 1;
 };
 
 void          _editor_page_class_actions_init     (EditorPageClass      *klass);
@@ -89,5 +90,7 @@ void          _editor_page_move_next_search       (EditorPage           *self,
                                                    gboolean              hide_after_search);
 void          _editor_page_move_previous_search   (EditorPage           *self,
                                                    gboolean              hide_after_search);
+void          _editor_page_begin_move             (EditorPage           *self);
+void          _editor_page_end_move               (EditorPage           *self);
 
 G_END_DECLS
diff --git a/src/editor-page.c b/src/editor-page.c
index a132898..69a3b59 100644
--- a/src/editor-page.c
+++ b/src/editor-page.c
@@ -1285,3 +1285,21 @@ editor_page_grab_focus (EditorPage *self)
   _editor_page_raise (self);
   gtk_widget_grab_focus (GTK_WIDGET (self->view));
 }
+
+void
+_editor_page_begin_move (EditorPage *self)
+{
+  g_return_if_fail (!self->moving);
+
+  g_object_ref (self);
+  self->moving = TRUE;
+}
+
+void
+_editor_page_end_move (EditorPage *self)
+{
+  g_return_if_fail (self->moving);
+
+  self->moving = FALSE;
+  g_object_unref (self);
+}
diff --git a/src/editor-session.c b/src/editor-session.c
index 6b3caf3..f7bc2f0 100644
--- a/src/editor-session.c
+++ b/src/editor-session.c
@@ -2018,23 +2018,24 @@ _editor_session_remove_draft (EditorSession *self,
 
 void
 _editor_session_move_page_to_window (EditorSession *self,
-                                     EditorPage    *page,
+                                     EditorPage    *epage,
                                      EditorWindow  *window)
 {
   EditorWindow *old_window;
 
   g_return_if_fail (EDITOR_IS_SESSION (self));
-  g_return_if_fail (EDITOR_IS_PAGE (page));
+  g_return_if_fail (EDITOR_IS_PAGE (epage));
   g_return_if_fail (EDITOR_IS_WINDOW (window));
 
-  old_window = _editor_page_get_window (page);
+  old_window = _editor_page_get_window (epage);
 
   if (window != old_window)
     {
-      g_object_ref (page);
-      _editor_window_remove_page (old_window, page);
-      _editor_window_add_page (window, page);
-      g_object_unref (page);
+      AdwTabPage *page = adw_tab_view_get_page (old_window->tab_view, GTK_WIDGET (epage));
+
+      _editor_page_begin_move (epage);
+      adw_tab_view_transfer_page (old_window->tab_view, page, window->tab_view, 0);
+      _editor_page_end_move (epage);
     }
 }
 
diff --git a/src/editor-window-actions.c b/src/editor-window-actions.c
index 77184b5..cde11c0 100644
--- a/src/editor-window-actions.c
+++ b/src/editor-window-actions.c
@@ -539,6 +539,24 @@ editor_window_actions_hide_preferences_cb (GtkWidget  *widget,
   adw_flap_set_reveal_flap (self->flap, FALSE);
 }
 
+static void
+editor_window_actions_close_other_pages_cb (GtkWidget  *widget,
+                                            const char *action_name,
+                                            GVariant   *param)
+{
+  EditorWindow *self = (EditorWindow *)widget;
+  EditorPage *current_page;
+  GList *pages;
+
+  g_assert (EDITOR_IS_WINDOW (self));
+
+  current_page = editor_window_get_visible_page (self);
+  pages = _editor_window_get_pages (self);
+  pages = g_list_remove (pages, current_page);
+  _editor_window_request_close_pages (self, pages, TRUE);
+  g_list_free (pages);
+}
+
 void
 _editor_window_class_actions_init (EditorWindowClass *klass)
 {
@@ -556,6 +574,10 @@ _editor_window_class_actions_init (EditorWindowClass *klass)
                                    "win.close-page-or-window",
                                    NULL,
                                    editor_window_actions_close_page_cb);
+  gtk_widget_class_install_action (widget_class,
+                                   "win.close-other-pages",
+                                   NULL,
+                                   editor_window_actions_close_other_pages_cb);
   gtk_widget_class_install_action (widget_class,
                                    "win.open",
                                    NULL,
@@ -699,6 +721,7 @@ _editor_window_actions_update (EditorWindow *self,
     }
 
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.close-current-page", has_page);
+  gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.close-other-pages", has_page);
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.change-language", has_page);
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.discard-changes", externally_modified || (modified 
&& !draft));
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.print", has_page);
diff --git a/src/editor-window-private.h b/src/editor-window-private.h
index b28b0d4..f2a5722 100644
--- a/src/editor-window-private.h
+++ b/src/editor-window-private.h
@@ -79,5 +79,8 @@ void          _editor_window_remove_page          (EditorWindow      *self,
 void          _editor_window_focus_search         (EditorWindow      *self);
 gboolean      _editor_window_request_close_page   (EditorWindow      *self,
                                                    EditorPage        *page);
+gboolean      _editor_window_request_close_pages  (EditorWindow      *self,
+                                                   GList             *pages,
+                                                   gboolean           close_saved);
 
 G_END_DECLS
diff --git a/src/editor-window.c b/src/editor-window.c
index 29bcf22..bafc2d6 100644
--- a/src/editor-window.c
+++ b/src/editor-window.c
@@ -306,6 +306,7 @@ editor_window_constructed (GObject *object)
   GtkPopover *popover;
   GMenu *options_menu;
   GMenu *primary_menu;
+  GMenu *tab_menu;
 
   g_assert (EDITOR_IS_WINDOW (self));
 
@@ -314,6 +315,9 @@ editor_window_constructed (GObject *object)
   app = GTK_APPLICATION (EDITOR_APPLICATION_DEFAULT);
   session = editor_application_get_session (EDITOR_APPLICATION_DEFAULT);
 
+  tab_menu = gtk_application_get_menu_by_id (app, "tab-menu");
+  adw_tab_view_set_menu_model (self->tab_view, G_MENU_MODEL (tab_menu));
+
   /* Set the recents list for the open popover */
   g_object_bind_property (session, "recents",
                           self->open_menu_popover, "model",
@@ -364,15 +368,17 @@ on_tab_view_close_page_cb (EditorWindow *self,
   if (page != adw_tab_view_get_selected_page (view))
     adw_tab_view_set_selected_page (view, page);
 
-  if ((epage = EDITOR_PAGE (adw_tab_page_get_child (page))))
-    {
-      epage->close_requested = TRUE;
+  epage = EDITOR_PAGE (adw_tab_page_get_child (page));
 
-      if (_editor_window_request_close_page (self, epage))
-        {
-          editor_session_remove_page (EDITOR_SESSION_DEFAULT, epage);
-          return FALSE;
-        }
+  if (epage->moving)
+    return TRUE;
+
+  epage->close_requested = TRUE;
+
+  if (_editor_window_request_close_page (self, epage))
+    {
+      editor_session_remove_page (EDITOR_SESSION_DEFAULT, epage);
+      return FALSE;
     }
 
   return TRUE;
@@ -428,23 +434,80 @@ gboolean
 _editor_window_request_close_page (EditorWindow *self,
                                    EditorPage   *page)
 {
+  GList *list;
+  gboolean ret;
+
   g_return_val_if_fail (EDITOR_IS_WINDOW (self), FALSE);
   g_return_val_if_fail (EDITOR_IS_PAGE (page), FALSE);
 
-  /* If this document has changes, then request the user to save them. */
-  if (editor_page_get_is_modified (page))
+  if (page->moving)
+    return TRUE;
+
+  list = g_list_append (NULL, page);
+  ret = _editor_window_request_close_pages (self, list, FALSE);
+  g_list_free (list);
+
+  return ret;
+}
+
+gboolean
+_editor_window_request_close_pages (EditorWindow *self,
+                                    GList        *pages,
+                                    gboolean      close_saved)
+{
+  g_autoptr(GPtrArray) ar = NULL;
+
+  g_return_val_if_fail (EDITOR_IS_WINDOW (self), FALSE);
+
+  if (pages == NULL)
+    return TRUE;
+
+  ar = g_ptr_array_new_with_free_func (g_object_unref);
+
+  for (const GList *iter = pages; iter; iter = iter->next)
     {
-      g_autoptr(GPtrArray) pages = g_ptr_array_new_with_free_func (g_object_unref);
-      g_ptr_array_add (pages, g_object_ref (page));
-      _editor_save_changes_dialog_run_async (GTK_WINDOW (self),
-                                             pages,
-                                             NULL,
-                                             editor_window_actions_close_page_confirm_cb,
-                                             g_ptr_array_ref (pages));
-      return FALSE;
+      EditorPage *page = iter->data;
+
+      if (editor_page_get_is_modified (page))
+        g_ptr_array_add (ar, g_object_ref (page));
+      else if (close_saved)
+        editor_session_remove_page (EDITOR_SESSION_DEFAULT, page);
     }
 
-  return TRUE;
+  if (ar->len == 0)
+    return TRUE;
+
+  _editor_save_changes_dialog_run_async (GTK_WINDOW (self),
+                                         ar,
+                                         NULL,
+                                         editor_window_actions_close_page_confirm_cb,
+                                         g_ptr_array_ref (ar));
+
+  return FALSE;
+}
+
+static void
+on_tab_view_setup_menu_cb (EditorWindow *self,
+                           AdwTabPage   *page,
+                           AdwTabView   *view)
+{
+  EditorPage *epage;
+
+  g_assert (EDITOR_IS_WINDOW (self));
+  g_assert (!page || ADW_IS_TAB_PAGE (page));
+  g_assert (ADW_IS_TAB_VIEW (view));
+
+  if (page == NULL)
+    return;
+
+  /* If the tab is not the current page, change to it so that
+   * win/page actions apply to the proper page.
+   */
+
+  epage = EDITOR_PAGE (adw_tab_page_get_child (page));
+
+  if (epage != self->visible_page)
+    editor_window_set_visible_page (self, epage);
 }
 
 static void
@@ -574,6 +637,7 @@ editor_window_class_init (EditorWindowClass *klass)
 
   gtk_widget_class_bind_template_callback (widget_class, on_tab_view_close_page_cb);
   gtk_widget_class_bind_template_callback (widget_class, on_notify_reveal_flap_cb);
+  gtk_widget_class_bind_template_callback (widget_class, on_tab_view_setup_menu_cb);
 
   gtk_widget_class_add_binding_action (widget_class, GDK_KEY_w, GDK_CONTROL_MASK, 
"win.close-page-or-window", NULL);
   gtk_widget_class_add_binding_action (widget_class, GDK_KEY_o, GDK_CONTROL_MASK, "win.open", NULL);
diff --git a/src/editor-window.ui b/src/editor-window.ui
index d538045..2428fc4 100644
--- a/src/editor-window.ui
+++ b/src/editor-window.ui
@@ -150,6 +150,7 @@
                         <property name="hexpand">true</property>
                         <property name="vexpand">true</property>
                         <signal name="close-page" handler="on_tab_view_close_page_cb" swapped="true"/>
+                        <signal name="setup-menu" handler="on_tab_view_setup_menu_cb" swapped="true"/>
                       </object>
                     </child>
                   </object>
diff --git a/src/menus.ui b/src/menus.ui
index 34de1cb..d6c04d7 100644
--- a/src/menus.ui
+++ b/src/menus.ui
@@ -149,30 +149,30 @@
     <section>
       <item>
         <attribute name="label" translatable="yes">Move _Left</attribute>
-        <attribute name="action">tab.move-left</attribute>
+        <attribute name="action">page.move-left</attribute>
         <attribute name="accel">&lt;control&gt;&lt;shift&gt;&lt;alt&gt;Page_Up</attribute>
       </item>
       <item>
         <attribute name="label" translatable="yes">Move _Right</attribute>
-        <attribute name="action">tab.move-right</attribute>
+        <attribute name="action">page.move-right</attribute>
         <attribute name="accel">&lt;control&gt;&lt;shift&gt;&lt;alt&gt;Page_Down</attribute>
       </item>
     </section>
     <section>
       <item>
         <attribute name="label" translatable="yes">_Move to New Window</attribute>
-        <attribute name="action">tab.move-to-new-window</attribute>
+        <attribute name="action">page.move-to-new-window</attribute>
         <attribute name="accel">&lt;control&gt;&lt;shift&gt;n</attribute>
       </item>
     </section>
     <section>
       <item>
         <attribute name="label" translatable="yes">Close _Other Tabs</attribute>
-        <attribute name="action">tab.close-other-tabs</attribute>
+        <attribute name="action">win.close-other-pages</attribute>
       </item>
       <item>
         <attribute name="label" translatable="yes">_Close</attribute>
-        <attribute name="action">tab.close</attribute>
+        <attribute name="action">win.close-current-page</attribute>
         <attribute name="accel">&lt;control&gt;w</attribute>
       </item>
     </section>


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