Skip to content

Commit

Permalink
textview: Allow zooming the text
Browse files Browse the repository at this point in the history
This allows the user to change the text size via keyboard, scrolling,
zoom gesture and from the primary menu.
  • Loading branch information
jsparber committed Jan 15, 2025
1 parent 1ac4aba commit bcbf2ad
Show file tree
Hide file tree
Showing 7 changed files with 288 additions and 33 deletions.
2 changes: 2 additions & 0 deletions aardvark-app/src/aardvark.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
<gresources>
<gresource prefix="/org/p2panda/aardvark">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">zoom_level_selector.ui</file>
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
<file compressed="true" alias="style.css">style.css</file>
</gresource>
</gresources>

2 changes: 2 additions & 0 deletions aardvark-app/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ mod config;
mod document;
mod textbuffer;
mod window;
mod zoom_level_selector;

use std::path::PathBuf;

Expand All @@ -36,6 +37,7 @@ use self::application::AardvarkApplication;
use self::config::{GETTEXT_PACKAGE, LOCALEDIR, PKGDATADIR};
use self::textbuffer::AardvarkTextBuffer;
use self::window::AardvarkWindow;
use self::zoom_level_selector::ZoomLevelSelector;

fn main() -> glib::ExitCode {
setup_logging();
Expand Down
4 changes: 0 additions & 4 deletions aardvark-app/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,3 @@
.user-counter {
font-weight: bold;
}

.editor {
font-size: 24px;
}
109 changes: 106 additions & 3 deletions aardvark-app/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,23 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/

use std::cell;

use adw::prelude::AdwDialogExt;
use adw::subclass::prelude::*;
use gtk::prelude::*;
use gtk::{gio, glib};
use gtk::{gio, glib, gdk};
use sourceview::*;

use crate::AardvarkTextBuffer;
use crate::{AardvarkTextBuffer, ZoomLevelSelector};

const BASE_TEXT_FONT_SIZE: f64 = 24.0;

mod imp {
use super::*;

#[derive(Debug, Default, gtk::CompositeTemplate)]
#[derive(Debug, Default, glib::Properties, gtk::CompositeTemplate)]
#[properties(wrapper_type = super::AardvarkWindow)]
#[template(resource = "/org/p2panda/aardvark/window.ui")]
pub struct AardvarkWindow {
// Template widgets
Expand All @@ -41,6 +46,12 @@ mod imp {
pub open_document_dialog: TemplateChild<adw::Dialog>,
#[template_child]
pub toast_overlay: TemplateChild<adw::ToastOverlay>,
pub css_provider: gtk::CssProvider,
pub font_size: cell::Cell<f64>,
#[property(get, set = Self::set_font_scale, default = 0.0)]
pub font_scale: cell::Cell<f64>,
#[property(get, default = 1.0)]
pub zoom_level: cell::Cell<f64>,
}

#[glib::object_subclass]
Expand All @@ -50,21 +61,99 @@ mod imp {
type ParentType = adw::ApplicationWindow;

fn class_init(klass: &mut Self::Class) {
ZoomLevelSelector::static_type();

klass.bind_template();

klass.install_action("window.zoom-in", None, |window, _, _| {
window.set_font_scale(window.font_scale() + 1.0);
});
klass.install_action("window.zoom-out", None, |window, _, _| {
window.set_font_scale(window.font_scale() - 1.0);
});
klass.install_action("window.zoom-one", None, |window, _, _| {
window.set_font_scale(0.0);
});

klass.add_binding_action(gdk::Key::plus,
gdk::ModifierType::CONTROL_MASK,
"window.zoom-in");
klass.add_binding_action(gdk::Key::KP_Add,
gdk::ModifierType::CONTROL_MASK,
"window.zoom-in");
klass.add_binding_action(gdk::Key::minus,
gdk::ModifierType::CONTROL_MASK,
"window.zoom-out");
// gnome-text-editor uses this as well: probably to make it
// nicer for the US keyboard layout
klass.add_binding_action(gdk::Key::equal,
gdk::ModifierType::CONTROL_MASK,
"window.zoom-out");
klass.add_binding_action(gdk::Key::KP_Subtract,
gdk::ModifierType::CONTROL_MASK,
"window.zoom-out");
klass.add_binding_action(gdk::Key::_0,
gdk::ModifierType::CONTROL_MASK,
"window.zoom-one");
klass.add_binding_action(gdk::Key::KP_0,
gdk::ModifierType::CONTROL_MASK,
"window.zoom-one");
}

fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}

#[glib::derived_properties]
impl ObjectImpl for AardvarkWindow {
fn constructed(&self) {
self.parent_constructed();

let buffer = AardvarkTextBuffer::new();
self.text_view.set_buffer(Some(&buffer));

self.font_size.set(BASE_TEXT_FONT_SIZE);
self.obj().set_font_scale(0.0);
gtk::style_context_add_provider_for_display (
&self.obj().display(),
&self.css_provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION);

let scroll_controller = gtk::EventControllerScroll::new(gtk::EventControllerScrollFlags::VERTICAL);
scroll_controller.set_propagation_phase(gtk::PropagationPhase::Capture);
let window = self.obj().clone();
scroll_controller.connect_scroll(move |scroll, _dx, dy| {
if scroll.current_event_state().contains(gdk::ModifierType::CONTROL_MASK) {
if dy < 0.0 {
window.set_font_scale(window.font_scale() + 1.0);
} else {
window.set_font_scale(window.font_scale() - 1.0);
}
glib::Propagation::Stop
} else {
glib::Propagation::Proceed
}
});
self.obj().add_controller(scroll_controller);

let zoom_gesture = gtk::GestureZoom::new();
let window = self.obj().clone();
let prev_delta = std::cell::Cell::new(0.0);
zoom_gesture.connect_scale_changed(move |_, delta| {
if prev_delta.get() == delta {
return;
}

if prev_delta.get() < delta {
window.set_font_scale(window.font_scale() + delta);
} else {
window.set_font_scale(window.font_scale() - delta);
}
prev_delta.set(delta);
});
self.obj().add_controller(zoom_gesture);

let window = self.obj().clone();
let dialog = self.open_document_dialog.clone();
self.open_document_button.connect_clicked(move |_| {
Expand All @@ -73,6 +162,20 @@ mod imp {
}
}

impl AardvarkWindow {
fn set_font_scale(&self, value: f64) {
let font_size = self.font_size.get();

self.font_scale.set(value);

let size = (font_size + self.obj().font_scale()).max(1.0);
self.zoom_level.set(size / font_size);
self.obj().notify_zoom_level();
self.css_provider.load_from_string(&format!( ".sourceview {{ font-size: {size}px; }}"));
self.obj().action_set_enabled("window.zoom-out", size > 1.0);
}
}

impl WidgetImpl for AardvarkWindow {}
impl WindowImpl for AardvarkWindow {}
impl ApplicationWindowImpl for AardvarkWindow {}
Expand Down
66 changes: 40 additions & 26 deletions aardvark-app/src/window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,33 @@
<interface>
<requires lib="gtk" version="4.0"/>
<requires lib="Adw" version="1.0"/>
<menu id="primary_menu">
<section>
<item>
<attribute name="custom">focus-level</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About Aardvark</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
<template class="AardvarkWindow" parent="AdwApplicationWindow">
<property name="title" translatable="yes">Aardvark</property>
<property name="default-width">800</property>
<property name="default-height">600</property>
<style>
<class name="view" />
<class name="view"/>
</style>
<property name="content">
<object class="AdwToolbarView">
Expand All @@ -30,7 +51,16 @@
<property name="primary">True</property>
<property name="icon-name">open-menu-symbolic</property>
<property name="tooltip-text" translatable="yes">Main Menu</property>
<property name="menu-model">primary_menu</property>
<property name="popover">
<object class="GtkPopoverMenu">
<property name="menu-model">primary_menu</property>
<child type="focus-level">
<object class="ZoomLevelSelector">
<property name="zoom-level" bind-source="AardvarkWindow" bind-property="zoom-level" bind-flags="sync-create"/>
</object>
</child>
</object>
</property>
</object>
</child>
<child type="end">
Expand Down Expand Up @@ -107,7 +137,7 @@
<object class="GtkLabel">
<property name="label" translatable="true">Share Document</property>
<style>
<class name="title-2" />
<class name="title-2"/>
</style>
</object>
</child>
Expand All @@ -128,8 +158,8 @@
<property name="max-width-chars">25</property>
<property name="label" translatable="true">356702</property>
<style>
<class name="invite-code" />
<class name="monospace" />
<class name="invite-code"/>
<class name="monospace"/>
</style>
</object>
</child>
Expand All @@ -141,7 +171,7 @@
<child>
<object class="GtkButton">
<style>
<class name="pill" />
<class name="pill"/>
</style>

<property name="child">
Expand All @@ -158,22 +188,6 @@
</object>
</property>
</object>
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About Aardvark</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
<object class="AdwDialog" id="open_document_dialog">
<property name="can-close">true</property>
<property name="width-request">320</property>
Expand All @@ -182,7 +196,7 @@
<child>
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar"></object>
<object class="AdwHeaderBar"/>
</child>


Expand All @@ -199,7 +213,7 @@
<object class="GtkLabel">
<property name="label" translatable="true">Open Document</property>
<style>
<class name="title-2" />
<class name="title-2"/>
</style>
</object>
</child>
Expand Down Expand Up @@ -241,8 +255,8 @@
<property name="label" translatable="true">Open</property>
<property name="width-request">140</property>
<style>
<class name="pill" />
<class name="suggested-action" />
<class name="pill"/>
<class name="suggested-action"/>
</style>
</object>
</child>
Expand Down
Loading

0 comments on commit bcbf2ad

Please sign in to comment.