From 1c8a058e82918604c6f4b1b343f6f708e916af4e Mon Sep 17 00:00:00 2001 From: Mohammad AlSaleh Date: Mon, 1 Jan 2024 12:27:51 +0300 Subject: [PATCH] Implement ZoomIn/ZoomOut/ZoomReset with configurable step Implements #14. Signed-off-by: Mohammad AlSaleh --- i18n/en/cosmic_term.ftl | 1 + src/config.rs | 13 ++++++- src/main.rs | 79 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/i18n/en/cosmic_term.ftl b/i18n/en/cosmic_term.ftl index e92b1cc..a7e5787 100644 --- a/i18n/en/cosmic_term.ftl +++ b/i18n/en/cosmic_term.ftl @@ -13,6 +13,7 @@ syntax-dark = Syntax dark syntax-light = Syntax light default-font = Default font default-font-size = Default font size +default-zoom-step = Default zoom step # Context menu copy = Copy diff --git a/src/config.rs b/src/config.rs index 7faa59d..8e8fca3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -31,6 +31,8 @@ pub struct Config { pub app_theme: AppTheme, pub font_name: String, pub font_size: u16, + pub font_size_zoom_adj: i8, + pub font_size_zoom_step_mul_100: u16, pub show_headerbar: bool, pub syntax_theme_dark: String, pub syntax_theme_light: String, @@ -42,6 +44,8 @@ impl Default for Config { app_theme: AppTheme::System, font_name: "Fira Mono".to_string(), font_size: 14, + font_size_zoom_adj: 0, + font_size_zoom_step_mul_100: 100, show_headerbar: true, syntax_theme_dark: "COSMIC Dark".to_string(), syntax_theme_light: "COSMIC Light".to_string(), @@ -50,9 +54,16 @@ impl Default for Config { } impl Config { + fn font_size_adjusted(&self) -> f32 { + let font_size = f32::from(self.font_size).max(1.0); + let adj = f32::from(self.font_size_zoom_adj); + let adj_step = f32::from(self.font_size_zoom_step_mul_100) / 100.0; + (font_size + adj*adj_step).max(1.0) + } + // Calculate metrics from font size pub fn metrics(&self) -> Metrics { - let font_size = self.font_size.max(1) as f32; + let font_size = self.font_size_adjusted(); let line_height = (font_size * 1.4).ceil(); Metrics::new(font_size, line_height) } diff --git a/src/main.rs b/src/main.rs index 4fc0322..6263e82 100644 --- a/src/main.rs +++ b/src/main.rs @@ -140,6 +140,10 @@ pub enum Message { Copy(Option), DefaultFont(usize), DefaultFontSize(usize), + ZoomIn, + ZoomOut, + ZoomReset, + DefaultZoomStep(usize), Paste(Option), PasteValue(Option, String), SelectAll(Option), @@ -179,6 +183,8 @@ pub struct App { font_names: Vec, font_size_names: Vec, font_sizes: Vec, + zoom_step_names: Vec, + zoom_steps: Vec, theme_names: Vec, themes: HashMap, context_page: ContextPage, @@ -251,6 +257,10 @@ impl App { .font_sizes .iter() .position(|font_size| font_size == &self.config.font_size); + let zoom_step_selected = self + .zoom_steps + .iter() + .position(|zoom_step| zoom_step == &self.config.font_size_zoom_step_mul_100); widget::settings::view_column(vec![widget::settings::view_section(fl!("appearance")) .add( widget::settings::item::builder(fl!("theme")).control(widget::dropdown( @@ -293,6 +303,13 @@ impl App { }), ), ) + .add( + widget::settings::item::builder(fl!("default-zoom-step")).control( + widget::dropdown(&self.zoom_step_names, zoom_step_selected, |index| { + Message::DefaultZoomStep(index) + }), + ), + ) .add( widget::settings::item::builder(fl!("show-headerbar")) .toggler(self.config.show_headerbar, Message::ShowHeaderBar), @@ -366,6 +383,13 @@ impl Application for App { font_sizes.push(font_size); } + let mut zoom_step_names = Vec::new(); + let mut zoom_steps = Vec::new(); + for zoom_step in [25, 50, 75, 100, 150, 200] { + zoom_step_names.push(format!("{}px", f32::from(zoom_step) / 100.0)); + zoom_steps.push(zoom_step); + } + let themes = terminal_theme::terminal_themes(); let mut theme_names: Vec<_> = themes.keys().map(|x| x.clone()).collect(); theme_names.sort(); @@ -379,6 +403,8 @@ impl Application for App { font_names, font_size_names, font_sizes, + zoom_step_names, + zoom_steps, theme_names, themes, context_page: ContextPage::Settings, @@ -445,9 +471,32 @@ impl Application for App { } } } + Message::ZoomIn => { + self.config.font_size_zoom_adj = self.config.font_size_zoom_adj.saturating_add(1); + return self.save_config(); + }, + Message::ZoomOut => { + self.config.font_size_zoom_adj = self.config.font_size_zoom_adj.saturating_sub(1); + return self.save_config(); + }, + Message::ZoomReset => { + self.config.font_size_zoom_adj = 0; + return self.save_config(); + }, + Message::DefaultZoomStep(index) => match self.zoom_steps.get(index) { + Some(zoom_step) => { + self.config.font_size_zoom_step_mul_100 = *zoom_step; + self.config.font_size_zoom_adj = 0; // reset zoom + return self.save_config(); + } + None => { + log::warn!("failed to find zoom step with index {}", index); + } + }, Message::DefaultFontSize(index) => match self.font_sizes.get(index) { Some(font_size) => { self.config.font_size = *font_size; + self.config.font_size_zoom_adj = 0; // reset zoom return self.save_config(); } None => { @@ -779,6 +828,36 @@ impl Application for App { None } } + Event::Keyboard(KeyEvent::KeyPressed { + key_code: KeyCode::Equals, + modifiers, + }) => { + if modifiers == Modifiers::CTRL { + Some(Message::ZoomIn) + } else { + None + } + } + Event::Keyboard(KeyEvent::KeyPressed { + key_code: KeyCode::Minus, + modifiers, + }) => { + if modifiers == Modifiers::CTRL { + Some(Message::ZoomOut) + } else { + None + } + } + Event::Keyboard(KeyEvent::KeyPressed { + key_code: KeyCode::Key0, + modifiers, + }) => { + if modifiers == Modifiers::CTRL { + Some(Message::ZoomReset) + } else { + None + } + } _ => None, }), subscription::channel(