From 2e7f6e701d5eab808064e1506a791bab180243fd Mon Sep 17 00:00:00 2001 From: Gabriele Musco Date: Mon, 8 Jan 2024 18:39:33 +0000 Subject: [PATCH] feat: wrap vte in its own struct to simplify the api --- src/ui/debug_view.rs | 64 ++++++++++++---------------------------- src/ui/mod.rs | 1 + src/ui/term_widget.rs | 68 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 46 deletions(-) create mode 100644 src/ui/term_widget.rs diff --git a/src/ui/debug_view.rs b/src/ui/debug_view.rs index f205af6..88b707c 100644 --- a/src/ui/debug_view.rs +++ b/src/ui/debug_view.rs @@ -6,7 +6,9 @@ use gtk::glib::clone; use gtk::prelude::*; use relm4::prelude::*; use relm4::{ComponentSender, SimpleComponent}; -use zoha_vte4::{Terminal, TerminalExt}; +use zoha_vte4::TerminalExt; + +use super::term_widget::TermWidget; #[derive(Debug)] pub enum SearchDirection { @@ -37,13 +39,11 @@ pub struct DebugView { #[tracker::do_not_track] log_level: LogLevel, #[tracker::do_not_track] - vte_terminal: Terminal, + term: TermWidget, } pub struct DebugViewInit {} -const MAX_SCROLLBACK: u32 = 2000; - #[relm4::component(pub)] impl SimpleComponent for DebugView { type Init = DebugViewInit; @@ -115,16 +115,11 @@ impl SimpleComponent for DebugView { }, connect_entry: &search_entry, }, - #[wrap(Some)] - set_content: sw = >k::ScrolledWindow { - set_hexpand: true, - set_vexpand: true, - model.vte_terminal.clone(), - } + set_content: Some(&model.term.container), } } - fn update(&mut self, message: Self::Input, sender: ComponentSender) { + fn update(&mut self, message: Self::Input, _sender: ComponentSender) { self.reset(); match message { @@ -142,19 +137,17 @@ impl SimpleComponent for DebugView { let search_entry = self.search_entry.as_ref().unwrap().clone(); let search_text = search_entry.text().to_string(); if searchbar.is_search_mode() && !search_text.is_empty() { - if let Ok(regex) = zoha_vte4::Regex::for_search(&search_text, 0) { - self.vte_terminal.search_set_regex(Some(®ex), 0); - } + self.term.set_search_term(Some(&search_text)); } else { - self.vte_terminal.search_set_regex(None, 0); + self.term.set_search_term(None); } } Self::Input::SearchFindMatch(direction) => match direction { SearchDirection::Forward => { - self.vte_terminal.search_find_next(); + self.term.search_next(); } SearchDirection::Backward => { - self.vte_terminal.search_find_previous(); + self.term.search_prev(); } }, Self::Input::LogUpdated(n_log) => { @@ -173,15 +166,15 @@ impl SimpleComponent for DebugView { None => Some(row), }; if let Some(t) = txt { - self.vte_terminal.feed(t.as_bytes()) + self.term.feed(&t); } } } Self::Input::ClearLog => { - self.vte_terminal.feed("\x1bc".as_bytes()); + self.term.clear(); } Self::Input::SetColorScheme => { - Self::set_color_scheme(&self.vte_terminal); + self.term.set_color_scheme(); } } } @@ -223,24 +216,13 @@ impl SimpleComponent for DebugView { search_entry: None, dropdown: None, log_level: LogLevel::Trace, - vte_terminal: { - let t = Terminal::builder() - .scroll_on_output(true) - .scrollback_lines(MAX_SCROLLBACK) - .scroll_unit_is_pixels(true) - .vexpand(true) - .hexpand(true) - .build(); - t.set_clear_background(false); - t.search_set_wrap_around(true); - Self::set_color_scheme(&t); - t - }, + term: TermWidget::new(), }; + model.term.set_color_scheme(); { let sc = gtk::ShortcutController::new(); - let term = model.vte_terminal.clone(); + let term = model.term.term.clone(); sc.add_shortcut(gtk::Shortcut::new( gtk::ShortcutTrigger::parse_string("c"), Some(gtk::CallbackAction::new(move |_, _| { @@ -250,7 +232,7 @@ impl SimpleComponent for DebugView { true })), )); - let term = model.vte_terminal.clone(); + let term = model.term.term.clone(); sc.add_shortcut(gtk::Shortcut::new( gtk::ShortcutTrigger::parse_string("a"), Some(gtk::CallbackAction::new(move |_, _| { @@ -258,7 +240,7 @@ impl SimpleComponent for DebugView { true })), )); - model.vte_terminal.add_controller(sc); + model.term.term.add_controller(sc); } let widgets = view_output!(); @@ -269,13 +251,3 @@ impl SimpleComponent for DebugView { ComponentParts { model, widgets } } } - -impl DebugView { - fn set_color_scheme(term: &Terminal) { - if adw::StyleManager::default().is_dark() { - term.set_color_foreground(>k::gdk::RGBA::new(1.0, 1.0, 1.0, 1.0)); - } else { - term.set_color_foreground(>k::gdk::RGBA::new(0.0, 0.0, 0.0, 1.0)); - } - } -} diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 009259e..2f49e2b 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -15,5 +15,6 @@ pub mod preference_rows; pub mod profile_editor; pub mod steam_launch_options_box; mod steamvr_calibration_box; +pub mod term_widget; pub mod util; pub mod wivrn_conf_editor; diff --git a/src/ui/term_widget.rs b/src/ui/term_widget.rs new file mode 100644 index 0000000..adaf2a2 --- /dev/null +++ b/src/ui/term_widget.rs @@ -0,0 +1,68 @@ +use gtk4::gdk; +use relm4::adw; +use zoha_vte4::{Terminal, TerminalExt}; + +const MAX_SCROLLBACK: u32 = 2000; + +#[derive(Debug, Clone)] +pub struct TermWidget { + pub container: gtk4::ScrolledWindow, + pub term: Terminal, +} + +impl TermWidget { + pub fn new() -> Self { + let term = Terminal::builder() + .scroll_on_output(true) + .scrollback_lines(MAX_SCROLLBACK) + .scroll_unit_is_pixels(true) + .vexpand(true) + .hexpand(true) + .build(); + term.set_clear_background(false); + term.search_set_wrap_around(true); + let container = gtk4::ScrolledWindow::builder() + .hexpand(true) + .vexpand(true) + .child(&term) + .build(); + let this = Self { container, term }; + this + } + + pub fn set_color_scheme(&self) { + // TODO: use theme colors + if adw::StyleManager::default().is_dark() { + self.term + .set_color_foreground(&gdk::RGBA::new(1.0, 1.0, 1.0, 1.0)); + } else { + self.term + .set_color_foreground(&gdk::RGBA::new(0.0, 0.0, 0.0, 1.0)); + } + } + + pub fn feed(&self, txt: &str) { + self.term.feed(txt.replace('\n', "\r\n").as_bytes()) + } + + pub fn clear(&self) { + self.term.feed("\x1bc".as_bytes()); + } + + pub fn set_search_term(&self, term: Option<&str>) { + self.term.search_set_regex( + term.map(|txt| zoha_vte4::Regex::for_search(txt, 0).ok()) + .flatten() + .as_ref(), + 0, + ); + } + + pub fn search_next(&self) { + self.term.search_find_next(); + } + + pub fn search_prev(&self) { + self.term.search_find_previous(); + } +}