From 33b22ca30aeaf20ef3ea97540a83f3db33205153 Mon Sep 17 00:00:00 2001 From: yggverse Date: Sun, 10 Nov 2024 10:07:16 +0200 Subject: [PATCH] create separated wrapper for pin action --- src/app.rs | 30 +++++---- src/app/browser.rs | 10 --- src/app/browser/window.rs | 12 ++-- src/app/browser/window/action.rs | 11 ++++ src/app/browser/window/action/append.rs | 2 +- src/app/browser/window/action/pin.rs | 80 +++++++++++++++++++++++ src/app/browser/window/header.rs | 2 - src/app/browser/window/header/bar.rs | 2 - src/app/browser/window/header/bar/menu.rs | 26 ++++---- src/app/browser/window/tab.rs | 17 +++-- src/app/browser/window/tab/menu.rs | 14 +++- 11 files changed, 152 insertions(+), 54 deletions(-) create mode 100644 src/app/browser/window/action/pin.rs diff --git a/src/app.rs b/src/app.rs index 70f8c872..9f4f9536 100644 --- a/src/app.rs +++ b/src/app.rs @@ -8,7 +8,7 @@ use crate::profile::Profile; use adw::Application; use gtk::{ gio::SimpleAction, - glib::{gformat, uuid_string_random, ExitCode}, + glib::{uuid_string_random, ExitCode}, prelude::{ ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt, ToVariant, }, @@ -43,8 +43,6 @@ impl App { SimpleAction::new_stateful(&uuid_string_random(), None, &default_state); let action_page_reload = SimpleAction::new_stateful(&uuid_string_random(), None, &default_state); - let action_page_pin = - SimpleAction::new_stateful(&uuid_string_random(), None, &default_state); // Init GTK let gobject = Application::builder() @@ -60,7 +58,6 @@ impl App { action_page_history_back.clone(), action_page_history_forward.clone(), action_page_reload.clone(), - action_page_pin.clone(), )); // Init events @@ -172,7 +169,7 @@ impl App { for (detailed_action_name, &accels) in &[ // Browser actions ( - gformat!( + format!( "{}.{}", browser.action().id(), browser.action().close().id() @@ -180,7 +177,7 @@ impl App { &["Escape"], ), ( - gformat!( + format!( "{}.{}", browser.action().id(), browser.action().debug().id() @@ -188,7 +185,7 @@ impl App { &["i"], ), ( - gformat!( + format!( "{}.{}", browser.action().id(), browser.action().update().id() @@ -197,28 +194,35 @@ impl App { ), // Tab actions ( - gformat!( + format!( "{}.{}", browser.window().action().id(), browser.window().action().append().id() ), &["t"], ), + ( + format!( + "{}.{}", + browser.window().action().id(), + browser.window().action().pin().id() + ), + &["p"], + ), // @TODO ( - gformat!("win.{}", action_page_reload.name()), + format!("win.{}", action_page_reload.name()), &["r"], ), ( - gformat!("win.{}", action_page_history_back.name()), + format!("win.{}", action_page_history_back.name()), &["Left"], ), ( - gformat!("win.{}", action_page_history_forward.name()), + format!("win.{}", action_page_history_forward.name()), &["Right"], ), - (gformat!("win.{}", action_page_home.name()), &["h"]), - (gformat!("win.{}", action_page_pin.name()), &["p"]), + (format!("win.{}", action_page_home.name()), &["h"]), // @TODO page close missed ] { gobject.set_accels_for_action(detailed_action_name, &accels); diff --git a/src/app/browser.rs b/src/app/browser.rs index f29ce037..185a30a7 100644 --- a/src/app/browser.rs +++ b/src/app/browser.rs @@ -36,7 +36,6 @@ impl Browser { action_page_history_back: SimpleAction, action_page_history_forward: SimpleAction, action_page_reload: SimpleAction, - action_page_pin: SimpleAction, ) -> Browser { // Init components let action = Rc::new(Action::new()); @@ -48,7 +47,6 @@ impl Browser { action_page_history_back.clone(), action_page_history_forward.clone(), action_page_reload.clone(), - action_page_pin.clone(), )); // Init widget @@ -61,7 +59,6 @@ impl Browser { action_page_history_back.clone(), action_page_history_forward.clone(), action_page_reload.clone(), - action_page_pin.clone(), ], )); @@ -159,13 +156,6 @@ impl Browser { move |this, _| window.tab_page_reload(page_position_from_action_state(this)) }); - action_page_pin.connect_activate({ - let window = window.clone(); - move |this, _| { - window.tab_pin(page_position_from_action_state(this)); - } - }); - // Return new activated `Self` Self { action, diff --git a/src/app/browser/window.rs b/src/app/browser/window.rs index 36e8680e..60cedb40 100644 --- a/src/app/browser/window.rs +++ b/src/app/browser/window.rs @@ -33,7 +33,6 @@ impl Window { action_page_history_back: SimpleAction, action_page_history_forward: SimpleAction, action_page_reload: SimpleAction, - action_page_pin: SimpleAction, ) -> Self { // Init local actions let action = Rc::new(Action::new()); @@ -47,7 +46,6 @@ impl Window { action_page_home.clone(), action_page_history_back.clone(), action_page_history_forward.clone(), - action_page_pin.clone(), action_page_reload.clone(), ); @@ -61,7 +59,6 @@ impl Window { action_page_history_back, action_page_history_forward, action_page_reload, - action_page_pin, // Widgets tab.gobject(), ); @@ -77,6 +74,11 @@ impl Window { } }); + action.pin().connect_activate({ + let tab = tab.clone(); + move |page_position| tab.pin(page_position) + }); + // Init struct Self { //header, @@ -113,10 +115,6 @@ impl Window { self.tab.close_all(); } - pub fn tab_pin(&self, page_position: Option) { - self.tab.pin(page_position); - } - pub fn update(&self, tab_item_id: Option) { self.tab.update(tab_item_id); } diff --git a/src/app/browser/window/action.rs b/src/app/browser/window/action.rs index bc65c8dd..b1480721 100644 --- a/src/app/browser/window/action.rs +++ b/src/app/browser/window/action.rs @@ -1,6 +1,8 @@ mod append; +mod pin; use append::Append; +use pin::Pin; use gtk::{ gio::SimpleActionGroup, @@ -13,6 +15,7 @@ use std::rc::Rc; pub struct Action { // Actions append: Rc, + pin: Rc, // Group id: GString, gobject: SimpleActionGroup, @@ -25,6 +28,7 @@ impl Action { pub fn new() -> Self { // Init actions let append = Rc::new(Append::new()); + let pin = Rc::new(Pin::new()); // Generate unique group ID let id = uuid_string_random(); @@ -34,10 +38,12 @@ impl Action { // Add action to given group gobject.add_action(append.gobject()); + gobject.add_action(pin.gobject()); // Done Self { append, + pin, id, gobject, } @@ -50,6 +56,11 @@ impl Action { &self.append } + /// Get reference `Pin` action + pub fn pin(&self) -> &Rc { + &self.pin + } + /// Get auto-generated name for action group /// * useful for manual relationship with GObjects or as the `detailed_name` /// for [Accels](https://docs.gtk.org/gtk4/method.Application.set_accels_for_action.html) or diff --git a/src/app/browser/window/action/append.rs b/src/app/browser/window/action/append.rs index 102a8f47..0448145c 100644 --- a/src/app/browser/window/action/append.rs +++ b/src/app/browser/window/action/append.rs @@ -4,7 +4,7 @@ use gtk::{ prelude::ActionExt, }; -/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Append` action of `Browser` group +/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Append` action of `Window` group pub struct Append { gobject: SimpleAction, } diff --git a/src/app/browser/window/action/pin.rs b/src/app/browser/window/action/pin.rs new file mode 100644 index 00000000..91755314 --- /dev/null +++ b/src/app/browser/window/action/pin.rs @@ -0,0 +1,80 @@ +use gtk::{ + gio::SimpleAction, + glib::{uuid_string_random, GString}, + prelude::{ActionExt, ToVariant}, +}; + +// Defaults + +/// C-compatible variant type +const DEFAULT_STATE: i32 = -1; + +/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Pin` action of `Window` group +pub struct Pin { + gobject: SimpleAction, +} + +impl Pin { + // Constructors + + /// Create new `Self` + pub fn new() -> Self { + Self { + gobject: SimpleAction::new_stateful( + &uuid_string_random(), + None, + &DEFAULT_STATE.to_variant(), + ), + } + } + + // Actions + + /// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html) + /// * set `DEFAULT_STATE` on `None` + pub fn change_state(&self, state: Option) { + self.gobject.change_state( + &match state { + Some(value) => value, + None => DEFAULT_STATE, + } + .to_variant(), + ) + } + + // Events + + /// Define callback function for + /// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal + pub fn connect_activate(&self, callback: impl Fn(Option) + 'static) { + let state = self.state(); + self.gobject.connect_activate(move |_, _| callback(state)); + } + + // Getters + + pub fn state(&self) -> Option { + let state = self + .gobject + .state() + .expect("State value required for this action") + .get::() + .expect("Parameter type does not match `i32`"); + + if state != DEFAULT_STATE { + Some(state) + } else { + None + } + } + + /// Get reference to [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) GObject + pub fn gobject(&self) -> &SimpleAction { + &self.gobject + } + + /// Get auto-generated [action name](https://docs.gtk.org/gio/property.SimpleAction.name.html) + pub fn id(&self) -> GString { + self.gobject.name() + } +} diff --git a/src/app/browser/window/header.rs b/src/app/browser/window/header.rs index ca96ecd6..5324d58c 100644 --- a/src/app/browser/window/header.rs +++ b/src/app/browser/window/header.rs @@ -26,7 +26,6 @@ impl Header { action_page_history_back: SimpleAction, action_page_history_forward: SimpleAction, action_page_reload: SimpleAction, - action_page_pin: SimpleAction, // Widgets tab_view: &TabView, ) -> Rc { @@ -40,7 +39,6 @@ impl Header { action_page_history_back, action_page_history_forward, action_page_reload, - action_page_pin, tab_view, ); diff --git a/src/app/browser/window/header/bar.rs b/src/app/browser/window/header/bar.rs index 104569b7..5259007f 100644 --- a/src/app/browser/window/header/bar.rs +++ b/src/app/browser/window/header/bar.rs @@ -29,7 +29,6 @@ impl Bar { action_page_history_back: SimpleAction, action_page_history_forward: SimpleAction, action_page_reload: SimpleAction, - action_page_pin: SimpleAction, view: &TabView, ) -> Rc { // Init components @@ -44,7 +43,6 @@ impl Bar { action_page_history_back, action_page_history_forward, action_page_reload, - action_page_pin, ); // Build result diff --git a/src/app/browser/window/header/bar/menu.rs b/src/app/browser/window/header/bar/menu.rs index ac84a327..2a48bc04 100644 --- a/src/app/browser/window/header/bar/menu.rs +++ b/src/app/browser/window/header/bar/menu.rs @@ -6,7 +6,6 @@ use crate::app::browser::action::Action as BrowserAction; use crate::app::browser::window::action::Action as WindowAction; use gtk::{ gio::{self, SimpleAction}, - glib::{gformat, GString}, prelude::ActionExt, MenuButton, }; @@ -26,21 +25,24 @@ impl Menu { action_page_history_back: SimpleAction, action_page_history_forward: SimpleAction, action_page_reload: SimpleAction, - action_page_pin: SimpleAction, ) -> Rc { // Main let main = gio::Menu::new(); // Main > Page let main_page = gio::Menu::new(); - main_page.append(Some("New"), Some(&gformat!( + main_page.append(Some("New"), Some(&format!( "{}.{}", window_action.id(), window_action.append().id() ))); main_page.append(Some("Reload"), Some(&detailed_action_name(&action_page_reload))); - main_page.append(Some("Pin"), Some(&detailed_action_name(&action_page_pin))); + main_page.append(Some("Pin"), Some(&format!( + "{}.{}", + window_action.id(), + window_action.pin().id() + ))); // Main > Page > Navigation let main_page_navigation = gio::Menu::new(); @@ -68,19 +70,19 @@ impl Menu { let main_tool = gio::Menu::new(); // Debug - main_tool.append(Some("Debug"), Some(&gformat!( + main_tool.append(Some("Debug"), Some(&format!( "{}.{}", browser_action.id(), browser_action.debug().id() ))); - main_tool.append(Some("Profile"), Some(&gformat!( + main_tool.append(Some("Profile"), Some(&format!( "{}.{}", browser_action.id(), browser_action.profile().id() ))); - main_tool.append(Some("About"), Some(&gformat!( + main_tool.append(Some("About"), Some(&format!( "{}.{}", browser_action.id(), browser_action.about().id() @@ -88,7 +90,7 @@ impl Menu { main.append_submenu(Some("Tool"), &main_tool); - main.append(Some("Quit"), Some(&gformat!( + main.append(Some("Quit"), Some(&format!( "{}.{}", browser_action.id(), browser_action.close().id() @@ -105,8 +107,8 @@ impl Menu { } // Private helpers -fn detailed_action_name(action: &SimpleAction) -> GString { - gformat!("win.{}", action.name()) // @TODO find the way to ident parent group - // without application-wide dependencies import - // see also src/app/action.rs +fn detailed_action_name(action: &SimpleAction) -> String { + format!("win.{}", action.name()) // @TODO find the way to ident parent group + // without application-wide dependencies import + // see also src/app/action.rs } diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index 3dd52898..43660d17 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -47,7 +47,6 @@ impl Tab { action_page_home: SimpleAction, action_page_history_back: SimpleAction, action_page_history_forward: SimpleAction, - action_page_pin: SimpleAction, action_page_reload: SimpleAction, ) -> Rc { // Init local actions @@ -58,12 +57,12 @@ impl Tab { // Init context menu let menu = Menu::new( + window_action.clone(), action_page_close_all.clone(), action_page_close.clone(), action_page_history_back.clone(), action_page_history_forward.clone(), action_page_home.clone(), - action_page_pin.clone(), action_page_reload.clone(), ); @@ -123,9 +122,19 @@ impl Tab { let action_page_history_back = action_page_history_back.clone(); let action_page_history_forward = action_page_history_forward.clone(); let action_page_home = action_page_home.clone(); - let action_page_pin = action_page_pin.clone(); + let window_action = window_action.clone(); let action_page_reload = action_page_reload.clone(); move |tab_view, tab_page| { + // Update actions + let state_v2 = match tab_page { + // Context menu opened + Some(this) => Some(tab_view.page_position(this)), + // Context menu closed (reset state to defaults) + None => None, + }; // @TODO + window_action.pin().change_state(state_v2); + + // @TODO old version requires update // Setup state for selected page let state = match tab_page { // Context menu opened @@ -134,12 +143,10 @@ impl Tab { None => (-1).to_variant(), }; - // Update actions action_page_close.change_state(&state); action_page_history_back.change_state(&state); action_page_history_forward.change_state(&state); action_page_home.change_state(&state); - action_page_pin.change_state(&state); action_page_reload.change_state(&state); } }); diff --git a/src/app/browser/window/tab/menu.rs b/src/app/browser/window/tab/menu.rs index 9b34f013..36a21fa1 100644 --- a/src/app/browser/window/tab/menu.rs +++ b/src/app/browser/window/tab/menu.rs @@ -1,3 +1,6 @@ +use std::rc::Rc; + +use crate::app::browser::window::action::Action as WindowAction; use gtk::{gio::SimpleAction, prelude::ActionExt}; /// Context menu wrapper @@ -12,12 +15,12 @@ impl Menu { /// Create new `Self` pub fn new( + window_action: Rc, action_page_close_all: SimpleAction, action_page_close: SimpleAction, action_page_history_back: SimpleAction, action_page_history_forward: SimpleAction, action_page_home: SimpleAction, - action_page_pin: SimpleAction, action_page_reload: SimpleAction, ) -> Self { let main = gtk::gio::Menu::new(); @@ -27,7 +30,14 @@ impl Menu { Some(&detailed_action_name(action_page_reload)), ); - main.append(Some("Pin"), Some(&detailed_action_name(action_page_pin))); + main.append( + Some("Pin"), + Some(&format!( + "{}.{}", + window_action.id(), + window_action.pin().id() + )), + ); let navigation = gtk::gio::Menu::new();