[gnome-text-editor] page: add zoom in/out controls to primary menu button



commit 83db32134e61d408fe1fe6b2bcb5a1e12fbf9fd5
Author: Christian Hergert <chergert redhat com>
Date:   Fri Nov 19 18:24:10 2021 -0800

    page: add zoom in/out controls to primary menu button
    
    Fixes #96

 src/editor-page-private.h   |  3 +++
 src/editor-page.c           | 63 ++++++++++++++++++++++++++++++++++++++++++++-
 src/editor-page.ui          |  1 +
 src/editor-source-view.c    | 52 +++++++++++++++++++++++++++++++++++++
 src/editor-source-view.h    |  7 ++---
 src/editor-window-actions.c | 34 ++++++++++++++++++++++++
 src/editor-window-private.h |  1 +
 src/editor-window.c         | 37 ++++++++++++++++++++++++++
 src/menus.ui                |  5 ++++
 9 files changed, 199 insertions(+), 4 deletions(-)
---
diff --git a/src/editor-page-private.h b/src/editor-page-private.h
index 1d4548f..1692ce6 100644
--- a/src/editor-page-private.h
+++ b/src/editor-page-private.h
@@ -98,5 +98,8 @@ void          _editor_page_move_previous_search   (EditorPage           *self,
 void          _editor_page_begin_move             (EditorPage           *self);
 void          _editor_page_end_move               (EditorPage           *self);
 void          _editor_page_vim_init               (EditorPage           *self);
+void          _editor_page_zoom_in                (EditorPage           *self);
+void          _editor_page_zoom_out               (EditorPage           *self);
+char         *_editor_page_get_zoom_label         (EditorPage           *self);
 
 G_END_DECLS
diff --git a/src/editor-page.c b/src/editor-page.c
index e256dd3..5e8caf8 100644
--- a/src/editor-page.c
+++ b/src/editor-page.c
@@ -39,10 +39,11 @@ enum {
   PROP_CAN_SAVE,
   PROP_DOCUMENT,
   PROP_IS_MODIFIED,
+  PROP_POSITION_LABEL,
   PROP_SETTINGS,
   PROP_SUBTITLE,
   PROP_TITLE,
-  PROP_POSITION_LABEL,
+  PROP_ZOOM_LABEL,
   N_PROPS
 };
 
@@ -453,6 +454,17 @@ get_child_position_cb (GtkOverlay    *overlay,
   return TRUE;
 }
 
+static void
+font_scale_changed_cb (EditorPage       *self,
+                       GParamSpec       *pspec,
+                       EditorSourceView *view)
+{
+  g_assert (EDITOR_IS_PAGE (self));
+  g_assert (EDITOR_IS_SOURCE_VIEW (view));
+
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ZOOM_LABEL]);
+}
+
 static void
 editor_page_dispose (GObject *object)
 {
@@ -520,6 +532,10 @@ editor_page_get_property (GObject    *object,
       g_value_set_object (value, self->settings);
       break;
 
+    case PROP_ZOOM_LABEL:
+      g_value_take_string (value, _editor_page_get_zoom_label (self));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -612,6 +628,13 @@ editor_page_class_init (EditorPageClass *klass)
                          EDITOR_TYPE_PAGE_SETTINGS,
                          (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
+  properties [PROP_ZOOM_LABEL] =
+    g_param_spec_string ("zoom-label",
+                         "Zoom Label",
+                         "Zoom Label",
+                         NULL,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
   _editor_page_class_actions_init (klass);
@@ -635,6 +658,7 @@ editor_page_class_init (EditorPageClass *klass)
   gtk_widget_class_bind_template_child (widget_class, EditorPage, vim_command);
   gtk_widget_class_bind_template_callback (widget_class, get_child_position_cb);
   gtk_widget_class_bind_template_callback (widget_class, goto_line_entry_activate_cb);
+  gtk_widget_class_bind_template_callback (widget_class, font_scale_changed_cb);
 
   gtk_widget_class_add_binding_action (widget_class, GDK_KEY_Escape, 0, "search.hide", NULL);
   gtk_widget_class_add_binding_action (widget_class, GDK_KEY_i, GDK_CONTROL_MASK, "page.show-goto-line", 
NULL);
@@ -1351,3 +1375,40 @@ _editor_page_end_move (EditorPage *self)
   self->moving = FALSE;
   g_object_unref (self);
 }
+
+char *
+_editor_page_get_zoom_label (EditorPage *self)
+{
+  double level;
+
+  g_return_val_if_fail (EDITOR_IS_PAGE (self), NULL);
+
+  level = editor_source_view_get_zoom_level (EDITOR_SOURCE_VIEW (self->view));
+
+  if (level == 1.0)
+    return g_strdup ("100%");
+
+  return g_strdup_printf ("%.0lf%%", level * 100.0);
+}
+
+void
+_editor_page_zoom_in (EditorPage *self)
+{
+  int font_scale = 0;
+
+  g_return_if_fail (EDITOR_IS_PAGE (self));
+
+  g_object_get (self->view, "font-scale", &font_scale, NULL);
+  g_object_set (self->view, "font-scale", font_scale + 1, NULL);
+}
+
+void
+_editor_page_zoom_out (EditorPage *self)
+{
+  int font_scale = 0;
+
+  g_return_if_fail (EDITOR_IS_PAGE (self));
+
+  g_object_get (self->view, "font-scale", &font_scale, NULL);
+  g_object_set (self->view, "font-scale", font_scale - 1, NULL);
+}
diff --git a/src/editor-page.ui b/src/editor-page.ui
index 1bdd63c..74c2fbd 100644
--- a/src/editor-page.ui
+++ b/src/editor-page.ui
@@ -25,6 +25,7 @@
                         <style>
                           <class name="editor"/>
                         </style>
+                        <signal name="notify::font-scale" handler="font_scale_changed_cb" swapped="true"/>
                         <property name="auto-indent">true</property>
                         <property name="top-margin">12</property>
                         <property name="bottom-margin">12</property>
diff --git a/src/editor-source-view.c b/src/editor-source-view.c
index 974f977..ebb622c 100644
--- a/src/editor-source-view.c
+++ b/src/editor-source-view.c
@@ -41,6 +41,8 @@ G_DEFINE_TYPE (EditorSourceView, editor_source_view, GTK_SOURCE_TYPE_VIEW)
 enum {
   PROP_0,
   PROP_FONT_DESC,
+  PROP_FONT_SCALE,
+  PROP_ZOOM_LEVEL,
   N_PROPS
 };
 
@@ -61,6 +63,9 @@ editor_source_view_update_css (EditorSourceView *self)
       pango_font_description_get_set_fields (self->font_desc) & PANGO_FONT_MASK_SIZE)
     size = pango_font_description_get_size (self->font_desc) / PANGO_SCALE;
 
+  if (size + self->font_scale < 1)
+    self->font_scale = -size + 1;
+
   size = MAX (1, size + self->font_scale);
 
   font_desc = self->font_desc;
@@ -456,6 +461,14 @@ editor_source_view_get_property (GObject    *object,
       g_value_set_boxed (value, editor_source_view_get_font_desc (self));
       break;
 
+    case PROP_FONT_SCALE:
+      g_value_set_int (value, self->font_scale);
+      break;
+
+    case PROP_ZOOM_LEVEL:
+      g_value_set_double (value, editor_source_view_get_zoom_level (self));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -475,6 +488,12 @@ editor_source_view_set_property (GObject      *object,
       editor_source_view_set_font_desc (self, g_value_get_boxed (value));
       break;
 
+    case PROP_FONT_SCALE:
+      self->font_scale = g_value_get_int (value);
+      editor_source_view_update_css (self);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ZOOM_LEVEL]);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -498,6 +517,20 @@ editor_source_view_class_init (EditorSourceViewClass *klass)
                          PANGO_TYPE_FONT_DESCRIPTION,
                          (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  properties [PROP_FONT_SCALE] =
+    g_param_spec_int ("font-scale",
+                      "Font Scale",
+                      "The font scale",
+                      G_MININT, G_MAXINT, 0,
+                      (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_ZOOM_LEVEL] =
+    g_param_spec_double ("zoom-level",
+                         "Zoom Level",
+                         "Zoom Level",
+                         -G_MAXDOUBLE, G_MAXDOUBLE, 1.0,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
   gtk_widget_class_install_action (widget_class, "page.zoom-in", NULL, editor_source_view_action_zoom);
@@ -603,4 +636,23 @@ editor_source_view_set_font_desc (EditorSourceView           *self,
   editor_source_view_update_css (self);
 
   g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FONT_DESC]);
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FONT_SCALE]);
+  g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ZOOM_LEVEL]);
+}
+
+double
+editor_source_view_get_zoom_level (EditorSourceView *self)
+{
+  int alt_size;
+  int size = 11; /* 11pt */
+
+  g_return_val_if_fail (EDITOR_IS_SOURCE_VIEW (self), 0);
+
+  if (self->font_desc != NULL &&
+      pango_font_description_get_set_fields (self->font_desc) & PANGO_FONT_MASK_SIZE)
+    size = pango_font_description_get_size (self->font_desc) / PANGO_SCALE;
+
+  alt_size = MAX (1, size + self->font_scale);
+
+  return (double)alt_size / (double)size;
 }
diff --git a/src/editor-source-view.h b/src/editor-source-view.h
index 8a0cac2..fd30ef0 100644
--- a/src/editor-source-view.h
+++ b/src/editor-source-view.h
@@ -28,8 +28,9 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (EditorSourceView, editor_source_view, EDITOR, SOURCE_VIEW, GtkSourceView)
 
-const PangoFontDescription *editor_source_view_get_font_desc (EditorSourceView           *self);
-void                        editor_source_view_set_font_desc (EditorSourceView           *self,
-                                                              const PangoFontDescription *font_desc);
+const PangoFontDescription *editor_source_view_get_font_desc  (EditorSourceView           *self);
+void                        editor_source_view_set_font_desc  (EditorSourceView           *self,
+                                                               const PangoFontDescription *font_desc);
+double                      editor_source_view_get_zoom_level (EditorSourceView           *self);
 
 G_END_DECLS
diff --git a/src/editor-window-actions.c b/src/editor-window-actions.c
index 2d1b2c0..ea37067 100644
--- a/src/editor-window-actions.c
+++ b/src/editor-window-actions.c
@@ -557,6 +557,30 @@ editor_window_actions_close_other_pages_cb (GtkWidget  *widget,
   g_list_free (pages);
 }
 
+static void
+editor_window_actions_page_zoom_in_cb (GtkWidget  *widget,
+                                       const char *action_name,
+                                       GVariant   *param)
+{
+  EditorWindow *self = (EditorWindow *)widget;
+
+  g_assert (EDITOR_IS_WINDOW (self));
+
+  _editor_page_zoom_in (editor_window_get_visible_page (self));
+}
+
+static void
+editor_window_actions_page_zoom_out_cb (GtkWidget  *widget,
+                                        const char *action_name,
+                                        GVariant   *param)
+{
+  EditorWindow *self = (EditorWindow *)widget;
+
+  g_assert (EDITOR_IS_WINDOW (self));
+
+  _editor_page_zoom_out (editor_window_get_visible_page (self));
+}
+
 void
 _editor_window_class_actions_init (EditorWindowClass *klass)
 {
@@ -658,6 +682,14 @@ _editor_window_class_actions_init (EditorWindowClass *klass)
                                    "win.show-preferences",
                                    NULL,
                                    editor_window_actions_show_preferences_cb);
+  gtk_widget_class_install_action (widget_class,
+                                   "page.zoom-in",
+                                   NULL,
+                                   editor_window_actions_page_zoom_in_cb);
+  gtk_widget_class_install_action (widget_class,
+                                   "page.zoom-out",
+                                   NULL,
+                                   editor_window_actions_page_zoom_out_cb);
 }
 
 void
@@ -730,5 +762,7 @@ _editor_window_actions_update (EditorWindow *self,
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.copy-all", has_page);
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.begin-replace", has_page);
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.begin-search", has_page);
+  gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.zoom-in", has_page);
+  gtk_widget_action_set_enabled (GTK_WIDGET (self), "page.zoom-out", has_page);
   gtk_widget_action_set_enabled (GTK_WIDGET (self), "win.focus-neighbor", has_page);
 }
diff --git a/src/editor-window-private.h b/src/editor-window-private.h
index f2a5722..0010133 100644
--- a/src/editor-window-private.h
+++ b/src/editor-window-private.h
@@ -53,6 +53,7 @@ struct _EditorWindow
   GtkMenuButton        *export_menu;
   GtkGrid              *scheme_group;
   AdwFlap              *flap;
+  GtkWidget            *zoom_label;
 
   /* Borrowed References */
   EditorPage           *visible_page;
diff --git a/src/editor-window.c b/src/editor-window.c
index c92fe45..7e091fe 100644
--- a/src/editor-window.c
+++ b/src/editor-window.c
@@ -183,6 +183,8 @@ editor_window_notify_selected_page_cb (EditorWindow *self,
 
   gtk_label_set_label (self->title, _(PACKAGE_NAME));
   gtk_label_set_label (self->subtitle, NULL);
+  gtk_label_set_label (GTK_LABEL (self->zoom_label), "100%");
+  gtk_widget_set_sensitive (self->zoom_label, page != NULL);
   gtk_widget_set_visible (GTK_WIDGET (self->is_modified), FALSE);
   gtk_widget_set_visible (GTK_WIDGET (self->subtitle), FALSE);
   gtk_widget_set_visible (GTK_WIDGET (self->position_box),
@@ -307,6 +309,9 @@ editor_window_constructed (GObject *object)
   GMenu *options_menu;
   GMenu *primary_menu;
   GMenu *tab_menu;
+  GtkWidget *zoom_box;
+  GtkWidget *zoom_out;
+  GtkWidget *zoom_in;
 
   g_assert (EDITOR_IS_WINDOW (self));
 
@@ -332,6 +337,38 @@ editor_window_constructed (GObject *object)
                               _editor_theme_selector_new (),
                               "theme");
 
+  /* Add zoom controls */
+  zoom_box = g_object_new (GTK_TYPE_BOX,
+                           "spacing", 12,
+                           "margin-start", 18,
+                           "margin-end", 18,
+                           NULL);
+  zoom_in = g_object_new (GTK_TYPE_BUTTON,
+                          "action-name", "page.zoom-in",
+                          "child", g_object_new (GTK_TYPE_IMAGE,
+                                                 "icon-name", "list-add-symbolic",
+                                                 "pixel-size", 14,
+                                                 NULL),
+                          NULL);
+  gtk_widget_add_css_class (zoom_in, "circular");
+  zoom_out = g_object_new (GTK_TYPE_BUTTON,
+                           "action-name", "page.zoom-out",
+                          "child", g_object_new (GTK_TYPE_IMAGE,
+                                                 "icon-name", "list-remove-symbolic",
+                                                 "pixel-size", 14,
+                                                 NULL),
+                           NULL);
+  gtk_widget_add_css_class (zoom_out, "circular");
+  self->zoom_label = g_object_new (GTK_TYPE_LABEL,
+                                   "hexpand", TRUE,
+                                   "label", "100%",
+                                   NULL);
+  editor_binding_group_bind (self->page_bindings, "zoom-label", self->zoom_label, "label", 0);
+  gtk_box_append (GTK_BOX (zoom_box), zoom_out);
+  gtk_box_append (GTK_BOX (zoom_box), self->zoom_label);
+  gtk_box_append (GTK_BOX (zoom_box), zoom_in);
+  gtk_popover_menu_add_child (GTK_POPOVER_MENU (popover), zoom_box, "zoom");
+
   options_menu = gtk_application_get_menu_by_id (GTK_APPLICATION (app), "options-menu");
   gtk_menu_button_set_menu_model (self->options_menu, G_MENU_MODEL (options_menu));
 
diff --git a/src/menus.ui b/src/menus.ui
index d6c04d7..417ae8c 100644
--- a/src/menus.ui
+++ b/src/menus.ui
@@ -6,6 +6,11 @@
         <attribute name="custom">theme</attribute>
       </item>
     </section>
+    <section>
+      <item>
+        <attribute name="custom">zoom</attribute>
+      </item>
+    </section>
     <section>
       <item>
         <attribute name="label" translatable="yes">_New Window</attribute>


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