From b3e64a485b389af39a991480c6089e12b8506034 Mon Sep 17 00:00:00 2001 From: yggverse Date: Sun, 15 Dec 2024 18:30:36 +0200 Subject: [PATCH] implement self update --- .../page/content/text/gemini/reader/widget.rs | 2 +- .../content/text/gemini/reader/widget/find.rs | 45 +++++-------- .../text/gemini/reader/widget/find/entry.rs | 39 ----------- .../text/gemini/reader/widget/find/input.rs | 66 +++++++++++++++++++ .../gemini/reader/widget/find/navigation.rs | 36 +++++++--- .../reader/widget/find/navigation/back.rs | 40 +++++++---- .../reader/widget/find/navigation/forward.rs | 40 +++++++---- 7 files changed, 170 insertions(+), 98 deletions(-) delete mode 100644 src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/entry.rs create mode 100644 src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/input.rs diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget.rs index b9a1f041..02198d5c 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget.rs @@ -52,7 +52,7 @@ impl Widget { let text_view = text_view.clone(); move |_| { text_view.set_gutter(TextWindowType::Bottom, Some(&find.g_box)); - find.entry.grab_focus(); + find.input.entry.grab_focus(); } }); diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find.rs index 1644e288..9e53cea2 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find.rs @@ -1,21 +1,22 @@ mod close; -mod entry; +mod input; mod match_case; mod navigation; mod tag; +use input::Input; use navigation::Navigation; use tag::Tag; use gtk::{ - prelude::{BoxExt, ButtonExt, CheckButtonExt, EditableExt, TextBufferExt, WidgetExt}, - Box, Button, Entry, Orientation, TextBuffer, TextIter, TextSearchFlags, TextTag, + prelude::{BoxExt, ButtonExt, CheckButtonExt, EditableExt, TextBufferExt}, + Box, Button, Orientation, TextBuffer, TextIter, TextSearchFlags, TextTag, }; use std::rc::Rc; pub struct Find { pub close: Button, - pub entry: Entry, + pub input: Rc, pub g_box: Box, } @@ -24,7 +25,7 @@ impl Find { pub fn new(text_buffer: &TextBuffer) -> Self { // Init components let close = close::new(); - let entry = entry::new(); + let input = Rc::new(Input::new()); let match_case = match_case::new(); let navigation = Rc::new(Navigation::new()); let tag = Rc::new(Tag::new(text_buffer.tag_table())); @@ -35,19 +36,19 @@ impl Find { .orientation(Orientation::Horizontal) .build(); - g_box.append(&entry); + g_box.append(&input.entry); g_box.append(&navigation.g_box); g_box.append(&match_case); g_box.append(&close); // Connect events close.connect_clicked({ - let entry = entry.clone(); - move |_| entry.delete_text(0, -1) + let input = input.clone(); + move |_| input.clean() }); - entry.connect_changed({ - let entry = entry.clone(); + input.entry.connect_changed({ + let input = input.clone(); let match_case = match_case.clone(); let navigation = navigation.clone(); let tag = tag.clone(); @@ -56,15 +57,15 @@ impl Find { navigation.update(find( &text_buffer, &tag.found, - entry.text().as_str(), + input.entry.text().as_str(), match_case.is_active(), )); - update(&entry, &navigation); + input.update(navigation.is_match()); } }); match_case.connect_toggled({ - let entry = entry.clone(); + let input = input.clone(); let navigation = navigation.clone(); let tag = tag.clone(); let text_buffer = text_buffer.clone(); @@ -72,17 +73,17 @@ impl Find { navigation.update(find( &text_buffer, &tag.found, - entry.text().as_str(), + input.entry.text().as_str(), this.is_active(), )); - update(&entry, &navigation); + input.update(navigation.is_match()); } }); // Done Self { close, - entry, + input, g_box, } } @@ -122,15 +123,3 @@ fn find( } result } - -fn update(entry: &Entry, navigation: &Rc) { - if navigation.matches.borrow().is_empty() { - entry.add_css_class("error"); - navigation.back.set_sensitive(false); - navigation.forward.set_sensitive(false); - } else { - entry.remove_css_class("error"); - navigation.back.set_sensitive(false); - navigation.forward.set_sensitive(true); - } -} diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/entry.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/entry.rs deleted file mode 100644 index 54d2bf9f..00000000 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/entry.rs +++ /dev/null @@ -1,39 +0,0 @@ -use gtk::{ - prelude::{EditableExt, EntryExt}, - Entry, EntryIconPosition, -}; - -const MARGIN: i32 = 6; - -pub fn new() -> Entry { - // Init widget - let entry = Entry::builder() - .hexpand(true) - .margin_bottom(MARGIN) - .margin_end(MARGIN) - .margin_start(MARGIN) - .margin_top(MARGIN) - .placeholder_text("Find in text..") - .primary_icon_activatable(false) - .primary_icon_sensitive(false) - .primary_icon_name("system-search-symbolic") - .build(); - - // Connect events - entry.connect_icon_release(|this, position| match position { - EntryIconPosition::Secondary => this.delete_text(0, -1), - _ => todo!(), // unexpected - }); - - entry.connect_changed(|this| { - // toggle entry clear button - if this.text().is_empty() { - this.set_secondary_icon_name(None); - } else { - this.set_secondary_icon_name(Some("edit-clear-symbolic")); - } - }); - - // Done - entry -} diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/input.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/input.rs new file mode 100644 index 00000000..d72b7081 --- /dev/null +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/input.rs @@ -0,0 +1,66 @@ +use gtk::{ + prelude::{EditableExt, EntryExt, WidgetExt}, + Entry, EntryIconPosition, +}; + +const MARGIN: i32 = 6; + +pub struct Input { + pub entry: Entry, +} + +impl Input { + // Constructors + + /// Create new `Self` + pub fn new() -> Self { + // Init widget + let entry = Entry::builder() + .hexpand(true) + .margin_bottom(MARGIN) + .margin_end(MARGIN) + .margin_start(MARGIN) + .margin_top(MARGIN) + .placeholder_text("Find in text..") + .primary_icon_activatable(false) + .primary_icon_sensitive(false) + .primary_icon_name("system-search-symbolic") + .build(); + + // Connect events + entry.connect_icon_release(|this, position| match position { + EntryIconPosition::Secondary => clean(this), + _ => todo!(), // unexpected + }); + + entry.connect_changed(|this| { + // toggle entry clear button + if this.text().is_empty() { + this.set_secondary_icon_name(None); + } else { + this.set_secondary_icon_name(Some("edit-clear-symbolic")); + } + }); + + // Done + Self { entry } + } + + // Actions + + pub fn clean(&self) { + clean(&self.entry) + } + + pub fn update(&self, is_match: bool) { + if is_match { + self.entry.remove_css_class("error"); + } else { + self.entry.add_css_class("error"); + } + } +} + +fn clean(entry: &Entry) { + entry.delete_text(0, -1) +} diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation.rs index ffae654e..9d2062da 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation.rs @@ -1,16 +1,19 @@ mod back; mod forward; -use gtk::{prelude::BoxExt, Box, Button, Orientation, TextIter}; +use back::Back; +use forward::Forward; + +use gtk::{prelude::BoxExt, Box, Orientation, TextIter}; use std::{cell::RefCell, rc::Rc}; const MARGIN: i32 = 6; pub struct Navigation { - pub back: Button, - pub forward: Button, + pub back: Back, + pub forward: Forward, pub g_box: Box, - pub matches: Rc>>, + matches: Rc>>, } impl Navigation { @@ -22,8 +25,8 @@ impl Navigation { let matches = Rc::new(RefCell::new(Vec::new())); // Init components - let back = back::new(); - let forward = forward::new(); + let back = Back::new(); + let forward = Forward::new(); // Init main container let g_box = Box::builder() @@ -34,8 +37,8 @@ impl Navigation { .orientation(Orientation::Horizontal) .build(); - g_box.append(&back); - g_box.append(&forward); + g_box.append(&back.button); + g_box.append(&forward.button); Self { back, @@ -45,7 +48,24 @@ impl Navigation { } } + // Actions + pub fn update(&self, matches: Vec<(TextIter, TextIter)>) { + // Update self self.matches.replace(matches); + + // Update child components + self.back.update(self.is_match()); + self.forward.update(self.is_match()); + } + + // pub fn back(&self) {} + + // pub fn forward(&self) {} + + // Getters + + pub fn is_match(&self) -> bool { + !self.matches.borrow().is_empty() } } diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/back.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/back.rs index 4c803943..43caec21 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/back.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/back.rs @@ -1,13 +1,31 @@ -use super::MARGIN; -use gtk::{gdk::Cursor, Button}; +use gtk::{gdk::Cursor, prelude::WidgetExt, Button}; -pub fn new() -> Button { - Button::builder() - .cursor(&Cursor::from_name("default", None).unwrap()) - .icon_name("go-previous-symbolic") - .margin_bottom(MARGIN) - .margin_top(MARGIN) - .sensitive(false) - .tooltip_text("Back") - .build() +const MARGIN: i32 = 6; + +pub struct Back { + pub button: Button, +} + +impl Back { + // Constructors + + /// Create new `Self` + pub fn new() -> Self { + Self { + button: Button::builder() + .cursor(&Cursor::from_name("default", None).unwrap()) + .icon_name("go-previous-symbolic") + .margin_bottom(MARGIN) + .margin_top(MARGIN) + .sensitive(false) + .tooltip_text("Back") + .build(), + } + } + + // Actions + + pub fn update(&self, is_sensitive: bool) { + self.button.set_sensitive(is_sensitive); + } } diff --git a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/forward.rs b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/forward.rs index 3862e0d0..8bf355f1 100644 --- a/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/forward.rs +++ b/src/app/browser/window/tab/item/page/content/text/gemini/reader/widget/find/navigation/forward.rs @@ -1,13 +1,31 @@ -use super::MARGIN; -use gtk::{gdk::Cursor, Button}; +use gtk::{gdk::Cursor, prelude::WidgetExt, Button}; -pub fn new() -> Button { - Button::builder() - .cursor(&Cursor::from_name("default", None).unwrap()) - .icon_name("go-next-symbolic") - .margin_bottom(MARGIN) - .margin_top(MARGIN) - .sensitive(false) - .tooltip_text("Forward") - .build() +const MARGIN: i32 = 6; + +pub struct Forward { + pub button: Button, +} + +impl Forward { + // Constructors + + /// Create new `Self` + pub fn new() -> Self { + Self { + button: Button::builder() + .cursor(&Cursor::from_name("default", None).unwrap()) + .icon_name("go-next-symbolic") + .margin_bottom(MARGIN) + .margin_top(MARGIN) + .sensitive(false) + .tooltip_text("Forward") + .build(), + } + } + + // Actions + + pub fn update(&self, is_sensitive: bool) { + self.button.set_sensitive(is_sensitive); + } }