From b3b0892d62d6b252a6d3a3984b2048b1458a8c79 Mon Sep 17 00:00:00 2001 From: yggverse Date: Wed, 16 Oct 2024 17:36:12 +0300 Subject: [PATCH] implement response counter --- src/app/browser/window/tab/item/page.rs | 6 +- src/app/browser/window/tab/item/page/input.rs | 23 +++---- .../window/tab/item/page/input/content.rs | 52 ---------------- .../page/input/content/response/widget.rs | 31 ---------- .../window/tab/item/page/input/default.rs | 61 +++++++++++++++++++ .../input/{content => default}/control.rs | 18 +++--- .../title.rs => default/control/left.rs} | 8 +-- .../limit => default/control/left}/widget.rs | 13 ++-- .../{content => default}/control/send.rs | 6 ++ .../control/send/widget.rs | 7 ++- .../{content => default}/control/widget.rs | 2 + .../input/{content => default}/response.rs | 14 +++-- .../page/input/default/response/widget.rs | 45 ++++++++++++++ .../control/limit.rs => default/title.rs} | 13 ++-- .../{content => default}/title/widget.rs | 20 ++---- .../page/input/{content => default}/widget.rs | 0 .../window/tab/item/page/input/widget.rs | 21 +++++-- 17 files changed, 193 insertions(+), 147 deletions(-) delete mode 100644 src/app/browser/window/tab/item/page/input/content.rs delete mode 100644 src/app/browser/window/tab/item/page/input/content/response/widget.rs create mode 100644 src/app/browser/window/tab/item/page/input/default.rs rename src/app/browser/window/tab/item/page/input/{content => default}/control.rs (66%) rename src/app/browser/window/tab/item/page/input/{content/title.rs => default/control/left.rs} (77%) rename src/app/browser/window/tab/item/page/input/{content/control/limit => default/control/left}/widget.rs (59%) rename src/app/browser/window/tab/item/page/input/{content => default}/control/send.rs (74%) rename src/app/browser/window/tab/item/page/input/{content => default}/control/send/widget.rs (71%) rename src/app/browser/window/tab/item/page/input/{content => default}/control/widget.rs (91%) rename src/app/browser/window/tab/item/page/input/{content => default}/response.rs (52%) create mode 100644 src/app/browser/window/tab/item/page/input/default/response/widget.rs rename src/app/browser/window/tab/item/page/input/{content/control/limit.rs => default/title.rs} (55%) rename src/app/browser/window/tab/item/page/input/{content => default}/title/widget.rs (57%) rename src/app/browser/window/tab/item/page/input/{content => default}/widget.rs (100%) diff --git a/src/app/browser/window/tab/item/page.rs b/src/app/browser/window/tab/item/page.rs index bc8abf99..1a04b882 100644 --- a/src/app/browser/window/tab/item/page.rs +++ b/src/app/browser/window/tab/item/page.rs @@ -279,8 +279,10 @@ impl Page { let title = gformat!("Input expected"); let description = gformat!("{placeholder}"); - // Show input request - input.show(Some(&description), Some(&1024)); + // Make input form + input.use_default(uri, Some(&description), Some(1024)); + input.show(); + // @TODO hide // Update meta meta.borrow_mut().status = Some(status); diff --git a/src/app/browser/window/tab/item/page/input.rs b/src/app/browser/window/tab/item/page/input.rs index ca4e4936..984fa83f 100644 --- a/src/app/browser/window/tab/item/page/input.rs +++ b/src/app/browser/window/tab/item/page/input.rs @@ -1,34 +1,35 @@ -mod content; +mod default; mod widget; -use content::Content; +use default::Default; +use gtk::glib::Uri; use widget::Widget; use adw::Clamp; use std::sync::Arc; pub struct Input { - content: Arc, widget: Arc, } impl Input { // Construct pub fn new_arc() -> Arc { - // Init components - let content = Content::new_arc(); - // Init widget - let widget = Widget::new_arc(content.gobject()); + let widget = Widget::new_arc(); // Result - Arc::new(Self { content, widget }) + Arc::new(Self { widget }) } // Actions - pub fn show(&self, title: Option<&str>, limit: Option<&i32>) { - self.content.update(title, limit); - self.widget.show(true); + pub fn use_default(&self, base: Uri, title: Option<&str>, size_limit: Option) { + self.widget + .update(Some(&Default::new_arc(base, title, size_limit).gobject())); + } + + pub fn show(&self) { + self.widget.show(); } // Getters diff --git a/src/app/browser/window/tab/item/page/input/content.rs b/src/app/browser/window/tab/item/page/input/content.rs deleted file mode 100644 index ba5f1234..00000000 --- a/src/app/browser/window/tab/item/page/input/content.rs +++ /dev/null @@ -1,52 +0,0 @@ -mod control; -mod response; -mod title; -mod widget; - -use control::Control; -use response::Response; -use title::Title; -use widget::Widget; - -use gtk::Box; -use std::sync::Arc; - -pub struct Content { - control: Arc, - response: Arc, - title: Arc, - widget: Arc<Widget>, -} - -impl Content { - // Construct - pub fn new_arc() -> Arc<Self> { - // Init components - let control = Control::new_arc(); - let response = Response::new_arc(); - let title = Title::new_arc(); - - // Init widget - let widget = Widget::new_arc(title.gobject(), response.gobject(), control.gobject()); - - // Return activated struct - Arc::new(Self { - control, - response, - title, - widget, - }) - } - - // Actions - pub fn update(&self, title: Option<&str>, count_limit: Option<&i32>) { - self.control.update(&0, count_limit); // @TODO - self.title.update(title); - self.response.grab_focus(); - } - - // Getters - pub fn gobject(&self) -> &Box { - &self.widget.gobject() - } -} diff --git a/src/app/browser/window/tab/item/page/input/content/response/widget.rs b/src/app/browser/window/tab/item/page/input/content/response/widget.rs deleted file mode 100644 index 5741142f..00000000 --- a/src/app/browser/window/tab/item/page/input/content/response/widget.rs +++ /dev/null @@ -1,31 +0,0 @@ -use gtk::{prelude::WidgetExt, TextView, WrapMode}; -use std::sync::Arc; - -pub struct Widget { - gobject: TextView, -} - -impl Widget { - // Construct - pub fn new_arc() -> Arc<Self> { - let gobject = TextView::builder() - .left_margin(8) - .pixels_above_lines(8) - .pixels_below_lines(8) - .right_margin(8) - .wrap_mode(WrapMode::Word) - .build(); - - Arc::new(Self { gobject }) - } - - // Actions - pub fn grab_focus(&self) { - self.gobject.grab_focus(); - } - - // Getters - pub fn gobject(&self) -> &TextView { - &self.gobject - } -} diff --git a/src/app/browser/window/tab/item/page/input/default.rs b/src/app/browser/window/tab/item/page/input/default.rs new file mode 100644 index 00000000..a5540765 --- /dev/null +++ b/src/app/browser/window/tab/item/page/input/default.rs @@ -0,0 +1,61 @@ +mod control; +mod response; +mod title; +mod widget; + +use control::Control; +use response::Response; +use title::Title; +use widget::Widget; + +use gtk::{ + gio::SimpleAction, + glib::{uuid_string_random, Uri, UriHideFlags}, + Box, +}; +use std::sync::Arc; + +pub struct Default { + // Components + widget: Arc<Widget>, +} + +impl Default { + // Construct + pub fn new_arc(base: Uri, title: Option<&str>, size_limit: Option<usize>) -> Arc<Self> { + // Init local action group + let action_update = Arc::new(SimpleAction::new(&uuid_string_random(), None)); + + // Init components + let control = Control::new_arc(); + let response = Response::new_arc(action_update.clone()); + let title = Title::new_arc(title); + + // Init widget + let widget = Widget::new_arc(title.gobject(), response.gobject(), control.gobject()); + + // Init events + action_update.connect_activate({ + let control = control.clone(); + let response = response.clone(); + move |_, _| { + control.update(match size_limit { + Some(limit_value) => Some( + limit_value + - (base.to_string_partial(UriHideFlags::QUERY).len() + + Uri::escape_string(response.text().as_str(), None, false).len()), + ), + None => None, + }); + } + }); + + // Return activated struct + Arc::new(Self { widget }) + } + + // Getters + pub fn gobject(&self) -> &Box { + &self.widget.gobject() + } +} diff --git a/src/app/browser/window/tab/item/page/input/content/control.rs b/src/app/browser/window/tab/item/page/input/default/control.rs similarity index 66% rename from src/app/browser/window/tab/item/page/input/content/control.rs rename to src/app/browser/window/tab/item/page/input/default/control.rs index 3fa033eb..3d3f6c48 100644 --- a/src/app/browser/window/tab/item/page/input/content/control.rs +++ b/src/app/browser/window/tab/item/page/input/default/control.rs @@ -1,8 +1,8 @@ -mod limit; +mod left; mod send; mod widget; -use limit::Limit; +use left::Left; use send::Send; use widget::Widget; @@ -10,7 +10,7 @@ use gtk::Box; use std::sync::Arc; pub struct Control { - limit: Arc<Limit>, + limit: Arc<Left>, send: Arc<Send>, widget: Arc<Widget>, } @@ -19,7 +19,7 @@ impl Control { // Construct pub fn new_arc() -> Arc<Self> { // Init components - let limit = Limit::new_arc(); + let limit = Left::new_arc(); let send = Send::new_arc(); // Init widget @@ -34,9 +34,13 @@ impl Control { } // Actions - pub fn update(&self, count: &i32, count_limit: Option<&i32>) { - self.limit.update(count, count_limit); - // @TODO self.send.update(limit); + pub fn update(&self, left: Option<usize>) { + // Update children components + self.limit.update(left); + self.send.update(match left { + Some(value) => value > 0, + None => false, + }); } // Getters diff --git a/src/app/browser/window/tab/item/page/input/content/title.rs b/src/app/browser/window/tab/item/page/input/default/control/left.rs similarity index 77% rename from src/app/browser/window/tab/item/page/input/content/title.rs rename to src/app/browser/window/tab/item/page/input/default/control/left.rs index 768a7128..8c9ce6b6 100644 --- a/src/app/browser/window/tab/item/page/input/content/title.rs +++ b/src/app/browser/window/tab/item/page/input/default/control/left.rs @@ -5,11 +5,11 @@ use widget::Widget; use gtk::Label; use std::sync::Arc; -pub struct Title { +pub struct Left { widget: Arc<Widget>, } -impl Title { +impl Left { // Construct pub fn new_arc() -> Arc<Self> { // Init widget @@ -20,8 +20,8 @@ impl Title { } // Actions - pub fn update(&self, text: Option<&str>) { - self.widget.update(text); + pub fn update(&self, left: Option<usize>) { + self.widget.update(left); } // Getters diff --git a/src/app/browser/window/tab/item/page/input/content/control/limit/widget.rs b/src/app/browser/window/tab/item/page/input/default/control/left/widget.rs similarity index 59% rename from src/app/browser/window/tab/item/page/input/content/control/limit/widget.rs rename to src/app/browser/window/tab/item/page/input/default/control/left/widget.rs index ebbbe198..3035b521 100644 --- a/src/app/browser/window/tab/item/page/input/content/control/limit/widget.rs +++ b/src/app/browser/window/tab/item/page/input/default/control/left/widget.rs @@ -8,22 +8,21 @@ pub struct Widget { impl Widget { // Construct pub fn new_arc() -> Arc<Self> { - let gobject = Label::builder().use_markup(true).build(); + let gobject = Label::builder().build(); Arc::new(Self { gobject }) } // Actions - pub fn update(&self, count: &i32, count_limit: Option<&i32>) { - match count_limit { - Some(limit) => { + pub fn update(&self, left: Option<usize>) { + match left { + Some(value) => { // Update color on limit reached self.gobject - .set_css_classes(&[if count < limit { "success" } else { "error" }]); // @TODO add warning step? + .set_css_classes(&[if value > 0 { "success" } else { "error" }]); // @TODO add warning step? // Update text - self.gobject - .set_markup(&format!("{count} <sup>/ {limit}</sup>")); + self.gobject.set_label(&value.to_string()); // Toggle visibility if limit provided self.gobject.set_visible(true); diff --git a/src/app/browser/window/tab/item/page/input/content/control/send.rs b/src/app/browser/window/tab/item/page/input/default/control/send.rs similarity index 74% rename from src/app/browser/window/tab/item/page/input/content/control/send.rs rename to src/app/browser/window/tab/item/page/input/default/control/send.rs index 72265012..b760c542 100644 --- a/src/app/browser/window/tab/item/page/input/content/control/send.rs +++ b/src/app/browser/window/tab/item/page/input/default/control/send.rs @@ -10,6 +10,7 @@ pub struct Send { } impl Send { + // Construct pub fn new_arc() -> Arc<Self> { // Init widget let widget = Widget::new_arc(); @@ -18,6 +19,11 @@ impl Send { Arc::new(Self { widget }) } + // Actions + pub fn update(&self, is_sensitive: bool) { + self.widget.update(is_sensitive); + } + // Getters pub fn gobject(&self) -> &Button { &self.widget.gobject() diff --git a/src/app/browser/window/tab/item/page/input/content/control/send/widget.rs b/src/app/browser/window/tab/item/page/input/default/control/send/widget.rs similarity index 71% rename from src/app/browser/window/tab/item/page/input/content/control/send/widget.rs rename to src/app/browser/window/tab/item/page/input/default/control/send/widget.rs index 0b383234..e4a17b91 100644 --- a/src/app/browser/window/tab/item/page/input/content/control/send/widget.rs +++ b/src/app/browser/window/tab/item/page/input/default/control/send/widget.rs @@ -1,4 +1,4 @@ -use gtk::Button; +use gtk::{prelude::WidgetExt, Button}; use std::sync::Arc; pub struct Widget { @@ -16,6 +16,11 @@ impl Widget { Arc::new(Self { gobject }) } + // Actions + pub fn update(&self, is_sensitive: bool) { + self.gobject.set_sensitive(is_sensitive); + } + // Getters pub fn gobject(&self) -> &Button { &self.gobject diff --git a/src/app/browser/window/tab/item/page/input/content/control/widget.rs b/src/app/browser/window/tab/item/page/input/default/control/widget.rs similarity index 91% rename from src/app/browser/window/tab/item/page/input/content/control/widget.rs rename to src/app/browser/window/tab/item/page/input/default/control/widget.rs index ec3c6878..da639d5a 100644 --- a/src/app/browser/window/tab/item/page/input/content/control/widget.rs +++ b/src/app/browser/window/tab/item/page/input/default/control/widget.rs @@ -10,6 +10,7 @@ pub struct Widget { impl Widget { // Construct pub fn new_arc(limit: &Label, send: &Button) -> Arc<Self> { + // Init gobject let gobject = Box::builder() .halign(Align::End) .orientation(Orientation::Horizontal) @@ -19,6 +20,7 @@ impl Widget { gobject.append(limit); gobject.append(send); + // Return new struct Arc::new(Self { gobject }) } diff --git a/src/app/browser/window/tab/item/page/input/content/response.rs b/src/app/browser/window/tab/item/page/input/default/response.rs similarity index 52% rename from src/app/browser/window/tab/item/page/input/content/response.rs rename to src/app/browser/window/tab/item/page/input/default/response.rs index dc524467..132647a3 100644 --- a/src/app/browser/window/tab/item/page/input/content/response.rs +++ b/src/app/browser/window/tab/item/page/input/default/response.rs @@ -2,7 +2,7 @@ mod widget; use widget::Widget; -use gtk::TextView; +use gtk::{gio::SimpleAction, glib::GString, TextView}; use std::sync::Arc; pub struct Response { @@ -11,20 +11,24 @@ pub struct Response { impl Response { // Construct - pub fn new_arc() -> Arc<Self> { + pub fn new_arc(action_update: Arc<SimpleAction>) -> Arc<Self> { // Init widget - let widget = Widget::new_arc(); + let widget = Widget::new_arc(action_update); // Result Arc::new(Self { widget }) } // Actions - pub fn grab_focus(&self) { - self.widget.grab_focus(); + pub fn focus(&self) { + self.widget.focus(); } // Getters + pub fn text(&self) -> GString { + self.widget.text() + } + pub fn gobject(&self) -> &TextView { &self.widget.gobject() } diff --git a/src/app/browser/window/tab/item/page/input/default/response/widget.rs b/src/app/browser/window/tab/item/page/input/default/response/widget.rs new file mode 100644 index 00000000..4f4c116f --- /dev/null +++ b/src/app/browser/window/tab/item/page/input/default/response/widget.rs @@ -0,0 +1,45 @@ +use gtk::{ + gio::SimpleAction, glib::GString, prelude::{ActionExt, TextBufferExt, TextViewExt, WidgetExt}, TextView, WrapMode +}; +use std::sync::Arc; + +pub struct Widget { + gobject: TextView, +} + +impl Widget { + // Construct + pub fn new_arc(action_update: Arc<SimpleAction>) -> Arc<Self> { + // Init gobject + let gobject = TextView::builder() + .left_margin(8) + .pixels_above_lines(8) + .pixels_below_lines(8) + .right_margin(8) + .wrap_mode(WrapMode::Word) + .build(); + + // Init events + gobject.buffer().connect_changed(move |_| { + action_update.activate(None); + }); + + // Return activated struct + Arc::new(Self { gobject }) + } + + // Actions + pub fn focus(&self) { + self.gobject.grab_focus(); + } + + // Getters + pub fn text(&self) -> GString { + let buffer = self.gobject.buffer(); + buffer.text(&buffer.start_iter(), &buffer.end_iter(), true) + } + + pub fn gobject(&self) -> &TextView { + &self.gobject + } +} diff --git a/src/app/browser/window/tab/item/page/input/content/control/limit.rs b/src/app/browser/window/tab/item/page/input/default/title.rs similarity index 55% rename from src/app/browser/window/tab/item/page/input/content/control/limit.rs rename to src/app/browser/window/tab/item/page/input/default/title.rs index 93cdb1e0..9f40fa44 100644 --- a/src/app/browser/window/tab/item/page/input/content/control/limit.rs +++ b/src/app/browser/window/tab/item/page/input/default/title.rs @@ -5,25 +5,20 @@ use widget::Widget; use gtk::Label; use std::sync::Arc; -pub struct Limit { +pub struct Title { widget: Arc<Widget>, } -impl Limit { +impl Title { // Construct - pub fn new_arc() -> Arc<Self> { + pub fn new_arc(title: Option<&str>) -> Arc<Self> { // Init widget - let widget = Widget::new_arc(); + let widget = Widget::new_arc(title); // Result Arc::new(Self { widget }) } - // Actions - pub fn update(&self, count: &i32, limit: Option<&i32>) { - self.widget.update(count, limit); - } - // Getters pub fn gobject(&self) -> &Label { &self.widget.gobject() diff --git a/src/app/browser/window/tab/item/page/input/content/title/widget.rs b/src/app/browser/window/tab/item/page/input/default/title/widget.rs similarity index 57% rename from src/app/browser/window/tab/item/page/input/content/title/widget.rs rename to src/app/browser/window/tab/item/page/input/default/title/widget.rs index 5877f5cd..d5adf7b3 100644 --- a/src/app/browser/window/tab/item/page/input/content/title/widget.rs +++ b/src/app/browser/window/tab/item/page/input/default/title/widget.rs @@ -7,7 +7,7 @@ pub struct Widget { impl Widget { // Construct - pub fn new_arc() -> Arc<Self> { + pub fn new_arc(title: Option<&str>) -> Arc<Self> { let gobject = Label::builder() .css_classes(["heading"]) .halign(Align::Start) @@ -16,20 +16,12 @@ impl Widget { .visible(false) .build(); - Arc::new(Self { gobject }) - } - - // Actions - pub fn update(&self, text: Option<&str>) { - match text { - Some(value) => { - self.gobject.set_label(value); - self.gobject.set_visible(!value.is_empty()); - } - None => { - self.gobject.set_visible(false); - } + match title { + Some(value) => gobject.set_label(value), + None => gobject.set_visible(false), } + + Arc::new(Self { gobject }) } // Getters diff --git a/src/app/browser/window/tab/item/page/input/content/widget.rs b/src/app/browser/window/tab/item/page/input/default/widget.rs similarity index 100% rename from src/app/browser/window/tab/item/page/input/content/widget.rs rename to src/app/browser/window/tab/item/page/input/default/widget.rs diff --git a/src/app/browser/window/tab/item/page/input/widget.rs b/src/app/browser/window/tab/item/page/input/widget.rs index 0da008ef..8017ce5a 100644 --- a/src/app/browser/window/tab/item/page/input/widget.rs +++ b/src/app/browser/window/tab/item/page/input/widget.rs @@ -8,9 +8,8 @@ pub struct Widget { impl Widget { // Construct - pub fn new_arc(child: &Box) -> Arc<Self> { + pub fn new_arc() -> Arc<Self> { let gobject = Clamp::builder() - .child(child) .css_classes(["app-notification"]) .maximum_size(800) .visible(false) @@ -20,8 +19,22 @@ impl Widget { } // Actions - pub fn show(&self, visible: bool) { - self.gobject.set_visible(visible); + pub fn show(&self) { + self.gobject.set_visible(true) + } + + /* not in use + pub fn hide(&self) { + self.gobject.set_visible(false) + } */ + + pub fn update(&self, child: Option<&Box>) { + if child.is_some() { + self.gobject.set_child(child); + self.gobject.set_visible(true); + } else { + self.gobject.set_visible(false) + } } // Getters