From aee972e171f230b84e473d1d465e273a11649bd0 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 1 Nov 2023 14:19:39 -0600 Subject: [PATCH] Add settings page with support for vim bindings toggle --- Cargo.lock | 2 +- Cargo.toml | 4 -- i18n/en/cosmic_edit.ftl | 13 ++++++- src/config.rs | 31 +++++++++------ src/main.rs | 86 ++++++++++++++++++++++++++++++++++------- src/menu.rs | 9 +++-- src/tab.rs | 3 +- 7 files changed, 111 insertions(+), 37 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e255327..93cb8b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -851,7 +851,7 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.10.0" -source = "git+https://github.com/pop-os/cosmic-text?branch=vi-editor#7855dce09d457ea6d516f621fdaafaa7ce78d9d4" +source = "git+https://github.com/pop-os/cosmic-text?branch=vi-editor#ca35e1f429af2ac3121f8afb0991963820dbd1bf" dependencies = [ "fontdb 0.15.0", "libm", diff --git a/Cargo.toml b/Cargo.toml index a720fdc..745ba85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,9 +29,5 @@ default-features = false features = ["winit"] #path = "../libcosmic" -[features] -default = [] -vi = [] - [patch.crates-io] smithay-client-toolkit = { git = "https://github.com/pop-os/client-toolkit", branch = "wayland-resize" } diff --git a/i18n/en/cosmic_edit.ftl b/i18n/en/cosmic_edit.ftl index 8005ba4..70d67bd 100644 --- a/i18n/en/cosmic_edit.ftl +++ b/i18n/en/cosmic_edit.ftl @@ -1,6 +1,15 @@ new-document = New document open-project = Open project +# Context Pages + +## Settings +settings = Settings + +### Keyboard shortcuts +keyboard-shortcuts = Keyboard shortcuts +enable-vim-bindings = Enable Vim bindings + # Menu ## File @@ -44,6 +53,6 @@ word-wrap = Word wrap show-line-numbers = Show line numbers highlight-current-line = Highlight current line syntax-highlighting = Syntax highlighting... -settings = Settings... -keyboard-shortcuts = Keyboard shortcuts... +menu-settings = Settings... +menu-keyboard-shortcuts = Keyboard shortcuts... about-cosmic-text-editor = About COSMIC Text Editor diff --git a/src/config.rs b/src/config.rs index 50fc288..f23caf5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,7 @@ use cosmic::iced::keyboard::{KeyCode, Modifiers}; use std::{collections::HashMap, fmt}; -use crate::Message; +use crate::{ContextPage, Message}; // Makes key binding definitions simpler const CTRL: Modifiers = Modifiers::CTRL; @@ -20,26 +20,31 @@ impl KeyBind { let mut keybinds = HashMap::new(); macro_rules! bind { - ($modifiers:expr, $key_code:ident, $message:ident) => {{ + ($modifiers:expr, $key_code:ident, $message:expr) => {{ keybinds.insert( KeyBind { modifiers: $modifiers, key_code: KeyCode::$key_code, }, - Message::$message, + $message, ); }}; } - bind!(CTRL, X, Cut); - bind!(CTRL, C, Copy); - bind!(CTRL, V, Paste); - bind!(CTRL, N, NewFile); - bind!(CTRL | SHIFT, N, NewWindow); - bind!(CTRL, O, OpenFileDialog); - bind!(CTRL, S, Save); - bind!(CTRL, Q, Quit); - bind!(ALT, Z, ToggleWordWrap); + bind!(CTRL, X, Message::Cut); + bind!(CTRL, C, Message::Copy); + bind!(CTRL, V, Message::Paste); + bind!(CTRL, N, Message::NewFile); + bind!(CTRL | SHIFT, N, Message::NewWindow); + bind!(CTRL, O, Message::OpenFileDialog); + bind!(CTRL, S, Message::Save); + bind!(CTRL, Q, Message::Quit); + bind!( + CTRL, + Comma, + Message::ToggleContextPage(ContextPage::Settings) + ); + bind!(ALT, Z, Message::ToggleWordWrap); keybinds } @@ -65,6 +70,7 @@ impl fmt::Display for KeyBind { #[derive(Clone, Debug)] pub struct Config { + pub vim_bindings: bool, pub word_wrap: bool, pub keybinds: HashMap, } @@ -73,6 +79,7 @@ impl Config { //TODO: load from cosmic-config pub fn load() -> Self { Self { + vim_bindings: false, word_wrap: false, keybinds: KeyBind::load(), } diff --git a/src/main.rs b/src/main.rs index 3113b5c..bf2598c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,13 +60,6 @@ fn main() -> Result<(), Box> { Ok(()) } -pub struct App { - core: Core, - nav_model: segmented_button::SingleSelectModel, - tab_model: segmented_button::SingleSelectModel, - config: Config, -} - #[allow(dead_code)] #[derive(Clone, Debug, Eq, PartialEq)] pub enum Message { @@ -86,7 +79,30 @@ pub enum Message { TabActivate(segmented_button::Entity), TabClose(segmented_button::Entity), Todo, + ToggleContextPage(ContextPage), ToggleWordWrap, + VimBindings(bool), +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum ContextPage { + Settings, +} + +impl ContextPage { + fn title(&self) -> String { + match self { + Self::Settings => fl!("settings"), + } + } +} + +pub struct App { + core: Core, + nav_model: segmented_button::SingleSelectModel, + tab_model: segmented_button::SingleSelectModel, + config: Config, + context_page: ContextPage, } impl App { @@ -204,6 +220,16 @@ impl App { .activate(); } + fn update_config(&mut self) { + //TODO: provide iterator over data + let entities: Vec<_> = self.tab_model.iter().collect(); + for entity in entities { + if let Some(tab) = self.tab_model.data_mut::(entity) { + tab.set_config(&self.config); + } + } + } + fn update_nav_bar_active(&mut self) { let tab_path_opt = match self.active_tab() { Some(tab) => tab.path_opt.clone(), @@ -301,6 +327,7 @@ impl cosmic::Application for App { nav_model: nav_bar::Model::builder().build(), tab_model: segmented_button::Model::builder().build(), config: Config::load(), + context_page: ContextPage::Settings, }; for arg in env::args().skip(1) { @@ -539,21 +566,52 @@ impl cosmic::Application for App { Message::Todo => { log::warn!("TODO"); } + Message::ToggleContextPage(context_page) => { + if self.context_page == context_page { + self.core.window.show_context = !self.core.window.show_context; + } else { + self.context_page = context_page; + self.core.window.show_context = true; + } + self.set_context_title(context_page.title()); + + // Hack to ensure tab redraws. + //TODO: tab does not redraw when using Close button! + return self.update_tab(); + } Message::ToggleWordWrap => { self.config.word_wrap = !self.config.word_wrap; - //TODO: provide iterator over data - let entities: Vec<_> = self.tab_model.iter().collect(); - for entity in entities { - if let Some(tab) = self.tab_model.data_mut::(entity) { - tab.set_config(&self.config); - } - } + self.update_config(); + } + Message::VimBindings(vim_bindings) => { + self.config.vim_bindings = vim_bindings; + self.update_config(); } } Command::none() } + fn context_drawer(&self) -> Option> { + if !self.core.window.show_context { + return None; + } + + Some(match self.context_page { + ContextPage::Settings => { + widget::settings::view_column(vec![widget::settings::view_section(fl!( + "keyboard-shortcuts" + )) + .add( + widget::settings::item::builder(fl!("enable-vim-bindings")) + .toggler(self.config.vim_bindings, Message::VimBindings), + ) + .into()]) + .into() + } + }) + } + fn header_start(&self) -> Vec> { vec![menu_bar(&self.config)] } diff --git a/src/menu.rs b/src/menu.rs index 1fbeced..05cee82 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -11,7 +11,7 @@ use cosmic::{ Element, }; -use crate::{fl, Config, Message}; +use crate::{fl, Config, ContextPage, Message}; pub fn menu_bar<'a>(config: &Config) -> Element<'a, Message> { //TODO: port to libcosmic @@ -157,9 +157,12 @@ pub fn menu_bar<'a>(config: &Config) -> Element<'a, Message> { menu_checkbox(fl!("highlight-current-line"), false, Message::Todo), menu_item(fl!("syntax-highlighting"), Message::Todo), MenuTree::new(horizontal_rule(1)), - menu_key(fl!("settings"), "Ctrl + ,", Message::Todo), + menu_item( + fl!("menu-settings"), + Message::ToggleContextPage(ContextPage::Settings), + ), MenuTree::new(horizontal_rule(1)), - menu_item(fl!("keyboard-shortcuts"), Message::Todo), + menu_item(fl!("menu-keyboard-shortcuts"), Message::Todo), MenuTree::new(horizontal_rule(1)), menu_item(fl!("about-cosmic-text-editor"), Message::Todo), ], diff --git a/src/tab.rs b/src/tab.rs index a57d359..27133d4 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -32,7 +32,7 @@ impl Tab { .unwrap(); let mut editor = ViEditor::new(editor); - editor.set_passthrough(!cfg!(feature = "vi")); + editor.set_passthrough(true); Self { path_opt: None, @@ -45,6 +45,7 @@ impl Tab { let mut editor = self.editor.lock().unwrap(); let mut font_system = FONT_SYSTEM.lock().unwrap(); let mut editor = editor.borrow_with(&mut font_system); + editor.set_passthrough(!config.vim_bindings); editor.buffer_mut().set_wrap(if config.word_wrap { Wrap::Word } else {