create separated wrapper for pin action

This commit is contained in:
yggverse 2024-11-10 10:07:16 +02:00
parent e47c22ac92
commit 33b22ca30a
11 changed files with 152 additions and 54 deletions

View File

@ -8,7 +8,7 @@ use crate::profile::Profile;
use adw::Application; use adw::Application;
use gtk::{ use gtk::{
gio::SimpleAction, gio::SimpleAction,
glib::{gformat, uuid_string_random, ExitCode}, glib::{uuid_string_random, ExitCode},
prelude::{ prelude::{
ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt, ToVariant, ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt, ToVariant,
}, },
@ -43,8 +43,6 @@ impl App {
SimpleAction::new_stateful(&uuid_string_random(), None, &default_state); SimpleAction::new_stateful(&uuid_string_random(), None, &default_state);
let action_page_reload = let action_page_reload =
SimpleAction::new_stateful(&uuid_string_random(), None, &default_state); SimpleAction::new_stateful(&uuid_string_random(), None, &default_state);
let action_page_pin =
SimpleAction::new_stateful(&uuid_string_random(), None, &default_state);
// Init GTK // Init GTK
let gobject = Application::builder() let gobject = Application::builder()
@ -60,7 +58,6 @@ impl App {
action_page_history_back.clone(), action_page_history_back.clone(),
action_page_history_forward.clone(), action_page_history_forward.clone(),
action_page_reload.clone(), action_page_reload.clone(),
action_page_pin.clone(),
)); ));
// Init events // Init events
@ -172,7 +169,7 @@ impl App {
for (detailed_action_name, &accels) in &[ for (detailed_action_name, &accels) in &[
// Browser actions // Browser actions
( (
gformat!( format!(
"{}.{}", "{}.{}",
browser.action().id(), browser.action().id(),
browser.action().close().id() browser.action().close().id()
@ -180,7 +177,7 @@ impl App {
&["<Primary>Escape"], &["<Primary>Escape"],
), ),
( (
gformat!( format!(
"{}.{}", "{}.{}",
browser.action().id(), browser.action().id(),
browser.action().debug().id() browser.action().debug().id()
@ -188,7 +185,7 @@ impl App {
&["<Primary>i"], &["<Primary>i"],
), ),
( (
gformat!( format!(
"{}.{}", "{}.{}",
browser.action().id(), browser.action().id(),
browser.action().update().id() browser.action().update().id()
@ -197,28 +194,35 @@ impl App {
), ),
// Tab actions // Tab actions
( (
gformat!( format!(
"{}.{}", "{}.{}",
browser.window().action().id(), browser.window().action().id(),
browser.window().action().append().id() browser.window().action().append().id()
), ),
&["<Primary>t"], &["<Primary>t"],
), ),
(
format!(
"{}.{}",
browser.window().action().id(),
browser.window().action().pin().id()
),
&["<Primary>p"],
),
// @TODO // @TODO
( (
gformat!("win.{}", action_page_reload.name()), format!("win.{}", action_page_reload.name()),
&["<Primary>r"], &["<Primary>r"],
), ),
( (
gformat!("win.{}", action_page_history_back.name()), format!("win.{}", action_page_history_back.name()),
&["<Primary>Left"], &["<Primary>Left"],
), ),
( (
gformat!("win.{}", action_page_history_forward.name()), format!("win.{}", action_page_history_forward.name()),
&["<Primary>Right"], &["<Primary>Right"],
), ),
(gformat!("win.{}", action_page_home.name()), &["<Primary>h"]), (format!("win.{}", action_page_home.name()), &["<Primary>h"]),
(gformat!("win.{}", action_page_pin.name()), &["<Primary>p"]),
// @TODO page close missed // @TODO page close missed
] { ] {
gobject.set_accels_for_action(detailed_action_name, &accels); gobject.set_accels_for_action(detailed_action_name, &accels);

View File

@ -36,7 +36,6 @@ impl Browser {
action_page_history_back: SimpleAction, action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction, action_page_history_forward: SimpleAction,
action_page_reload: SimpleAction, action_page_reload: SimpleAction,
action_page_pin: SimpleAction,
) -> Browser { ) -> Browser {
// Init components // Init components
let action = Rc::new(Action::new()); let action = Rc::new(Action::new());
@ -48,7 +47,6 @@ impl Browser {
action_page_history_back.clone(), action_page_history_back.clone(),
action_page_history_forward.clone(), action_page_history_forward.clone(),
action_page_reload.clone(), action_page_reload.clone(),
action_page_pin.clone(),
)); ));
// Init widget // Init widget
@ -61,7 +59,6 @@ impl Browser {
action_page_history_back.clone(), action_page_history_back.clone(),
action_page_history_forward.clone(), action_page_history_forward.clone(),
action_page_reload.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)) 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` // Return new activated `Self`
Self { Self {
action, action,

View File

@ -33,7 +33,6 @@ impl Window {
action_page_history_back: SimpleAction, action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction, action_page_history_forward: SimpleAction,
action_page_reload: SimpleAction, action_page_reload: SimpleAction,
action_page_pin: SimpleAction,
) -> Self { ) -> Self {
// Init local actions // Init local actions
let action = Rc::new(Action::new()); let action = Rc::new(Action::new());
@ -47,7 +46,6 @@ impl Window {
action_page_home.clone(), action_page_home.clone(),
action_page_history_back.clone(), action_page_history_back.clone(),
action_page_history_forward.clone(), action_page_history_forward.clone(),
action_page_pin.clone(),
action_page_reload.clone(), action_page_reload.clone(),
); );
@ -61,7 +59,6 @@ impl Window {
action_page_history_back, action_page_history_back,
action_page_history_forward, action_page_history_forward,
action_page_reload, action_page_reload,
action_page_pin,
// Widgets // Widgets
tab.gobject(), 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 // Init struct
Self { Self {
//header, //header,
@ -113,10 +115,6 @@ impl Window {
self.tab.close_all(); self.tab.close_all();
} }
pub fn tab_pin(&self, page_position: Option<i32>) {
self.tab.pin(page_position);
}
pub fn update(&self, tab_item_id: Option<GString>) { pub fn update(&self, tab_item_id: Option<GString>) {
self.tab.update(tab_item_id); self.tab.update(tab_item_id);
} }

View File

@ -1,6 +1,8 @@
mod append; mod append;
mod pin;
use append::Append; use append::Append;
use pin::Pin;
use gtk::{ use gtk::{
gio::SimpleActionGroup, gio::SimpleActionGroup,
@ -13,6 +15,7 @@ use std::rc::Rc;
pub struct Action { pub struct Action {
// Actions // Actions
append: Rc<Append>, append: Rc<Append>,
pin: Rc<Pin>,
// Group // Group
id: GString, id: GString,
gobject: SimpleActionGroup, gobject: SimpleActionGroup,
@ -25,6 +28,7 @@ impl Action {
pub fn new() -> Self { pub fn new() -> Self {
// Init actions // Init actions
let append = Rc::new(Append::new()); let append = Rc::new(Append::new());
let pin = Rc::new(Pin::new());
// Generate unique group ID // Generate unique group ID
let id = uuid_string_random(); let id = uuid_string_random();
@ -34,10 +38,12 @@ impl Action {
// Add action to given group // Add action to given group
gobject.add_action(append.gobject()); gobject.add_action(append.gobject());
gobject.add_action(pin.gobject());
// Done // Done
Self { Self {
append, append,
pin,
id, id,
gobject, gobject,
} }
@ -50,6 +56,11 @@ impl Action {
&self.append &self.append
} }
/// Get reference `Pin` action
pub fn pin(&self) -> &Rc<Pin> {
&self.pin
}
/// Get auto-generated name for action group /// Get auto-generated name for action group
/// * useful for manual relationship with GObjects or as the `detailed_name` /// * 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 /// for [Accels](https://docs.gtk.org/gtk4/method.Application.set_accels_for_action.html) or

View File

@ -4,7 +4,7 @@ use gtk::{
prelude::ActionExt, 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 { pub struct Append {
gobject: SimpleAction, gobject: SimpleAction,
} }

View File

@ -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<i32>) {
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<i32>) + 'static) {
let state = self.state();
self.gobject.connect_activate(move |_, _| callback(state));
}
// Getters
pub fn state(&self) -> Option<i32> {
let state = self
.gobject
.state()
.expect("State value required for this action")
.get::<i32>()
.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()
}
}

View File

@ -26,7 +26,6 @@ impl Header {
action_page_history_back: SimpleAction, action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction, action_page_history_forward: SimpleAction,
action_page_reload: SimpleAction, action_page_reload: SimpleAction,
action_page_pin: SimpleAction,
// Widgets // Widgets
tab_view: &TabView, tab_view: &TabView,
) -> Rc<Self> { ) -> Rc<Self> {
@ -40,7 +39,6 @@ impl Header {
action_page_history_back, action_page_history_back,
action_page_history_forward, action_page_history_forward,
action_page_reload, action_page_reload,
action_page_pin,
tab_view, tab_view,
); );

View File

@ -29,7 +29,6 @@ impl Bar {
action_page_history_back: SimpleAction, action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction, action_page_history_forward: SimpleAction,
action_page_reload: SimpleAction, action_page_reload: SimpleAction,
action_page_pin: SimpleAction,
view: &TabView, view: &TabView,
) -> Rc<Self> { ) -> Rc<Self> {
// Init components // Init components
@ -44,7 +43,6 @@ impl Bar {
action_page_history_back, action_page_history_back,
action_page_history_forward, action_page_history_forward,
action_page_reload, action_page_reload,
action_page_pin,
); );
// Build result // Build result

View File

@ -6,7 +6,6 @@ use crate::app::browser::action::Action as BrowserAction;
use crate::app::browser::window::action::Action as WindowAction; use crate::app::browser::window::action::Action as WindowAction;
use gtk::{ use gtk::{
gio::{self, SimpleAction}, gio::{self, SimpleAction},
glib::{gformat, GString},
prelude::ActionExt, prelude::ActionExt,
MenuButton, MenuButton,
}; };
@ -26,21 +25,24 @@ impl Menu {
action_page_history_back: SimpleAction, action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction, action_page_history_forward: SimpleAction,
action_page_reload: SimpleAction, action_page_reload: SimpleAction,
action_page_pin: SimpleAction,
) -> Rc<Self> { ) -> Rc<Self> {
// Main // Main
let main = gio::Menu::new(); let main = gio::Menu::new();
// Main > Page // Main > Page
let main_page = gio::Menu::new(); 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.id(),
window_action.append().id() window_action.append().id()
))); )));
main_page.append(Some("Reload"), Some(&detailed_action_name(&action_page_reload))); 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 // Main > Page > Navigation
let main_page_navigation = gio::Menu::new(); let main_page_navigation = gio::Menu::new();
@ -68,19 +70,19 @@ impl Menu {
let main_tool = gio::Menu::new(); let main_tool = gio::Menu::new();
// Debug // Debug
main_tool.append(Some("Debug"), Some(&gformat!( main_tool.append(Some("Debug"), Some(&format!(
"{}.{}", "{}.{}",
browser_action.id(), browser_action.id(),
browser_action.debug().id() browser_action.debug().id()
))); )));
main_tool.append(Some("Profile"), Some(&gformat!( main_tool.append(Some("Profile"), Some(&format!(
"{}.{}", "{}.{}",
browser_action.id(), browser_action.id(),
browser_action.profile().id() browser_action.profile().id()
))); )));
main_tool.append(Some("About"), Some(&gformat!( main_tool.append(Some("About"), Some(&format!(
"{}.{}", "{}.{}",
browser_action.id(), browser_action.id(),
browser_action.about().id() browser_action.about().id()
@ -88,7 +90,7 @@ impl Menu {
main.append_submenu(Some("Tool"), &main_tool); main.append_submenu(Some("Tool"), &main_tool);
main.append(Some("Quit"), Some(&gformat!( main.append(Some("Quit"), Some(&format!(
"{}.{}", "{}.{}",
browser_action.id(), browser_action.id(),
browser_action.close().id() browser_action.close().id()
@ -105,8 +107,8 @@ impl Menu {
} }
// Private helpers // Private helpers
fn detailed_action_name(action: &SimpleAction) -> GString { fn detailed_action_name(action: &SimpleAction) -> String {
gformat!("win.{}", action.name()) // @TODO find the way to ident parent group format!("win.{}", action.name()) // @TODO find the way to ident parent group
// without application-wide dependencies import // without application-wide dependencies import
// see also src/app/action.rs // see also src/app/action.rs
} }

View File

@ -47,7 +47,6 @@ impl Tab {
action_page_home: SimpleAction, action_page_home: SimpleAction,
action_page_history_back: SimpleAction, action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction, action_page_history_forward: SimpleAction,
action_page_pin: SimpleAction,
action_page_reload: SimpleAction, action_page_reload: SimpleAction,
) -> Rc<Self> { ) -> Rc<Self> {
// Init local actions // Init local actions
@ -58,12 +57,12 @@ impl Tab {
// Init context menu // Init context menu
let menu = Menu::new( let menu = Menu::new(
window_action.clone(),
action_page_close_all.clone(), action_page_close_all.clone(),
action_page_close.clone(), action_page_close.clone(),
action_page_history_back.clone(), action_page_history_back.clone(),
action_page_history_forward.clone(), action_page_history_forward.clone(),
action_page_home.clone(), action_page_home.clone(),
action_page_pin.clone(),
action_page_reload.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_back = action_page_history_back.clone();
let action_page_history_forward = action_page_history_forward.clone(); let action_page_history_forward = action_page_history_forward.clone();
let action_page_home = action_page_home.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(); let action_page_reload = action_page_reload.clone();
move |tab_view, tab_page| { 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 // Setup state for selected page
let state = match tab_page { let state = match tab_page {
// Context menu opened // Context menu opened
@ -134,12 +143,10 @@ impl Tab {
None => (-1).to_variant(), None => (-1).to_variant(),
}; };
// Update actions
action_page_close.change_state(&state); action_page_close.change_state(&state);
action_page_history_back.change_state(&state); action_page_history_back.change_state(&state);
action_page_history_forward.change_state(&state); action_page_history_forward.change_state(&state);
action_page_home.change_state(&state); action_page_home.change_state(&state);
action_page_pin.change_state(&state);
action_page_reload.change_state(&state); action_page_reload.change_state(&state);
} }
}); });

View File

@ -1,3 +1,6 @@
use std::rc::Rc;
use crate::app::browser::window::action::Action as WindowAction;
use gtk::{gio::SimpleAction, prelude::ActionExt}; use gtk::{gio::SimpleAction, prelude::ActionExt};
/// Context menu wrapper /// Context menu wrapper
@ -12,12 +15,12 @@ impl Menu {
/// Create new `Self` /// Create new `Self`
pub fn new( pub fn new(
window_action: Rc<WindowAction>,
action_page_close_all: SimpleAction, action_page_close_all: SimpleAction,
action_page_close: SimpleAction, action_page_close: SimpleAction,
action_page_history_back: SimpleAction, action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction, action_page_history_forward: SimpleAction,
action_page_home: SimpleAction, action_page_home: SimpleAction,
action_page_pin: SimpleAction,
action_page_reload: SimpleAction, action_page_reload: SimpleAction,
) -> Self { ) -> Self {
let main = gtk::gio::Menu::new(); let main = gtk::gio::Menu::new();
@ -27,7 +30,14 @@ impl Menu {
Some(&detailed_action_name(action_page_reload)), 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(); let navigation = gtk::gio::Menu::new();