create separated wrappers for history, close action group

This commit is contained in:
yggverse 2024-11-10 11:53:43 +02:00
parent 4afa2c204c
commit 8113022cd4
22 changed files with 557 additions and 335 deletions

View file

@ -7,11 +7,8 @@ use database::Database;
use crate::profile::Profile; use crate::profile::Profile;
use adw::Application; use adw::Application;
use gtk::{ use gtk::{
gio::SimpleAction, glib::ExitCode,
glib::{uuid_string_random, ExitCode}, prelude::{ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt},
prelude::{
ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt, ToVariant,
},
}; };
use sqlite::Transaction; use sqlite::Transaction;
use std::rc::Rc; use std::rc::Rc;
@ -29,30 +26,13 @@ impl App {
// Init profile // Init profile
let profile = Rc::new(Profile::new()); let profile = Rc::new(Profile::new());
// @TODO
let default_state = (-1).to_variant();
let action_page_close =
SimpleAction::new_stateful(&uuid_string_random(), None, &default_state);
let action_page_close_all = SimpleAction::new(&uuid_string_random(), None);
let action_page_history_back =
SimpleAction::new_stateful(&uuid_string_random(), None, &default_state);
let action_page_history_forward =
SimpleAction::new_stateful(&uuid_string_random(), None, &default_state);
// Init GTK // Init GTK
let gobject = Application::builder() let gobject = Application::builder()
.application_id(APPLICATION_ID) .application_id(APPLICATION_ID)
.build(); .build();
// Init components // Init components
let browser = Rc::new(Browser::new( let browser = Rc::new(Browser::new(profile.clone()));
profile.clone(),
action_page_close.clone(),
action_page_close_all.clone(),
action_page_history_back.clone(),
action_page_history_forward.clone(),
));
// Init events // Init events
gobject.connect_activate({ gobject.connect_activate({
@ -219,16 +199,30 @@ impl App {
), ),
&["<Primary>h"], &["<Primary>h"],
), ),
// @TODO
( (
format!("win.{}", action_page_history_back.name()), format!(
"{}.{}",
browser.window().action().id(),
browser.window().action().history_back().id()
),
&["<Primary>Left"], &["<Primary>Left"],
), ),
( (
format!("win.{}", action_page_history_forward.name()), format!(
"{}.{}",
browser.window().action().id(),
browser.window().action().history_forward().id()
),
&["<Primary>Right"], &["<Primary>Right"],
), ),
// @TODO page close missed (
format!(
"{}.{}",
browser.window().action().id(),
browser.window().action().close().id()
),
&["<Primary>q"],
),
] { ] {
gobject.set_accels_for_action(detailed_action_name, &accels); gobject.set_accels_for_action(detailed_action_name, &accels);
} }

View file

@ -13,8 +13,8 @@ use window::Window;
use crate::profile::Profile; use crate::profile::Profile;
use adw::ApplicationWindow; use adw::ApplicationWindow;
use gtk::{ use gtk::{
gio::{Cancellable, File, SimpleAction}, gio::{Cancellable, File},
prelude::{ActionExt, GtkWindowExt, WidgetExt}, prelude::GtkWindowExt,
FileLauncher, FileLauncher,
}; };
use sqlite::Transaction; use sqlite::Transaction;
@ -28,48 +28,22 @@ pub struct Browser {
impl Browser { impl Browser {
// Construct // Construct
pub fn new( pub fn new(profile: Rc<Profile>) -> Browser {
profile: Rc<Profile>,
action_page_close: SimpleAction,
action_page_close_all: SimpleAction,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Browser {
// Init components // Init components
let action = Rc::new(Action::new()); let action = Rc::new(Action::new());
let window = Rc::new(Window::new( let window = Rc::new(Window::new(action.clone()));
action.clone(),
action_page_close.clone(),
action_page_close_all.clone(),
action_page_history_back.clone(),
action_page_history_forward.clone(),
));
// Init widget // Init widget
let widget = Rc::new(Widget::new( let widget = Rc::new(Widget::new(
window.gobject(), window.gobject(),
&[ &[
action_page_close.clone(), // Connect action groups
action_page_close_all.clone(), (action.id(), action.gobject()),
action_page_history_back.clone(), (window.action().id(), window.action().gobject()),
action_page_history_forward.clone(), (window.tab().action().id(), window.tab().action().gobject()),
], ],
)); ));
// Connect actions (window required for accels)
widget
.gobject()
.insert_action_group(action.id(), Some(action.gobject()));
widget
.gobject()
.insert_action_group(window.action().id(), Some(window.action().gobject()));
widget.gobject().insert_action_group(
window.tab().action().id(),
Some(window.tab().action().gobject()),
);
// Connect events // Connect events
action.about().connect_activate({ action.about().connect_activate({
let window = window.clone(); let window = window.clone();
@ -109,35 +83,6 @@ impl Browser {
move |tab_item_id| window.update(tab_item_id) move |tab_item_id| window.update(tab_item_id)
}); });
// @TODO
action_page_close.connect_activate({
let window = window.clone();
move |this, _| {
window.tab_close(page_position_from_action_state(this));
}
});
action_page_close_all.connect_activate({
let window = window.clone();
move |_, _| {
window.tab_close_all();
}
});
action_page_history_back.connect_activate({
let window = window.clone();
move |this, _| {
window.tab_page_history_back(page_position_from_action_state(this));
}
});
action_page_history_forward.connect_activate({
let window = window.clone();
move |this, _| {
window.tab_page_history_forward(page_position_from_action_state(this));
}
});
// Return new activated `Self` // Return new activated `Self`
Self { Self {
action, action,
@ -246,21 +191,3 @@ pub fn migrate(tx: &Transaction) -> Result<(), String> {
// Success // Success
Ok(()) Ok(())
} }
// Private helpers @TODO move outside
/// Extract `Optional` page position from C-based
/// [SimpleAction state](https://docs.gtk.org/gio/property.SimpleAction.state.html)
fn page_position_from_action_state(action: &SimpleAction) -> Option<i32> {
let page_position = action
.state()
.expect("Page position required for this action")
.get::<i32>()
.expect("Parameter type does not match `i32`");
if page_position > -1 {
Some(page_position)
} else {
None
}
}

View file

@ -3,8 +3,9 @@ use database::Database;
use adw::ApplicationWindow; use adw::ApplicationWindow;
use gtk::{ use gtk::{
gio::SimpleAction, gio::SimpleActionGroup,
prelude::{ActionMapExt, GtkWindowExt, IsA}, glib::GString,
prelude::{GtkWindowExt, IsA, WidgetExt},
}; };
use sqlite::Transaction; use sqlite::Transaction;
@ -19,7 +20,10 @@ pub struct Widget {
impl Widget { impl Widget {
// Construct // Construct
pub fn new(content: &impl IsA<gtk::Widget>, actions: &[SimpleAction]) -> Self { pub fn new(
content: &impl IsA<gtk::Widget>,
action_groups: &[(&GString, &SimpleActionGroup)],
) -> Self {
// Init GTK // Init GTK
let gobject = ApplicationWindow::builder() let gobject = ApplicationWindow::builder()
.content(content) .content(content)
@ -29,8 +33,8 @@ impl Widget {
.build(); .build();
// Register actions // Register actions
for action in actions { for (name, group) in action_groups {
gobject.add_action(action); gobject.insert_action_group(name, Some(group.clone()));
} }
// Return new struct // Return new struct

View file

@ -12,7 +12,7 @@ use tab::Tab;
use widget::Widget; use widget::Widget;
use crate::app::browser::action::Action as BrowserAction; use crate::app::browser::action::Action as BrowserAction;
use gtk::{gio::SimpleAction, glib::GString, Box}; use gtk::{glib::GString, Box};
use std::rc::Rc; use std::rc::Rc;
pub struct Window { pub struct Window {
@ -27,35 +27,13 @@ impl Window {
pub fn new( pub fn new(
// Actions // Actions
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
action_page_close: SimpleAction,
action_page_close_all: SimpleAction,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Self { ) -> Self {
// Init local actions // Init local actions
let action = Rc::new(Action::new()); let action = Rc::new(Action::new());
// Init components // Init components
let tab = Tab::new_rc( let tab = Tab::new_rc(browser_action.clone(), action.clone());
browser_action.clone(), let header = Header::new_rc(browser_action, action.clone(), tab.gobject());
action.clone(),
action_page_close.clone(),
action_page_close_all.clone(),
action_page_history_back.clone(),
action_page_history_forward.clone(),
);
let header = Header::new_rc(
// Actions
browser_action,
action.clone(),
action_page_close,
action_page_close_all,
action_page_history_back,
action_page_history_forward,
// Widgets
tab.gobject(),
);
// GTK // GTK
let widget = Rc::new(Widget::new(header.gobject(), tab.gobject())); let widget = Rc::new(Widget::new(header.gobject(), tab.gobject()));
@ -83,6 +61,34 @@ impl Window {
move |position| tab.page_home(position) move |position| tab.page_home(position)
}); });
action.close().connect_activate({
let tab = tab.clone();
move |position| {
tab.close(position);
}
});
action.close_all().connect_activate({
let tab = tab.clone();
move |_| {
tab.close_all();
} // @TODO position not in use
});
action.history_back().connect_activate({
let tab = tab.clone();
move |position| {
tab.page_history_back(position);
} // @TODO rename destination method
});
action.history_forward().connect_activate({
let tab = tab.clone();
move |position| {
tab.page_history_forward(position);
} // @TODO rename destination method
});
// Init struct // Init struct
Self { Self {
//header, //header,
@ -93,23 +99,6 @@ impl Window {
} }
// Actions // Actions
pub fn tab_page_history_back(&self, page_position: Option<i32>) {
self.tab.page_history_back(page_position);
}
pub fn tab_page_history_forward(&self, page_position: Option<i32>) {
self.tab.page_history_forward(page_position);
}
/// Close page at given position or selected page on `None` given
pub fn tab_close(&self, page_position: Option<i32>) {
self.tab.close(page_position);
}
pub fn tab_close_all(&self) {
self.tab.close_all();
}
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,9 +1,17 @@
mod append; mod append;
mod close;
mod close_all;
mod history_back;
mod history_forward;
mod home; mod home;
mod pin; mod pin;
mod reload; mod reload;
use append::Append; use append::Append;
use close::Close;
use close_all::CloseAll;
use history_back::HistoryBack;
use history_forward::HistoryForward;
use home::Home; use home::Home;
use pin::Pin; use pin::Pin;
use reload::Reload; use reload::Reload;
@ -19,6 +27,10 @@ use std::rc::Rc;
pub struct Action { pub struct Action {
// Actions // Actions
append: Rc<Append>, append: Rc<Append>,
close_all: Rc<CloseAll>,
close: Rc<Close>,
history_back: Rc<HistoryBack>,
history_forward: Rc<HistoryForward>,
home: Rc<Home>, home: Rc<Home>,
pin: Rc<Pin>, pin: Rc<Pin>,
reload: Rc<Reload>, reload: Rc<Reload>,
@ -34,6 +46,10 @@ 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 close = Rc::new(Close::new());
let close_all = Rc::new(CloseAll::new());
let history_back = Rc::new(HistoryBack::new());
let history_forward = Rc::new(HistoryForward::new());
let home = Rc::new(Home::new()); let home = Rc::new(Home::new());
let pin = Rc::new(Pin::new()); let pin = Rc::new(Pin::new());
let reload = Rc::new(Reload::new()); let reload = Rc::new(Reload::new());
@ -46,6 +62,10 @@ 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(close_all.gobject());
gobject.add_action(close.gobject());
gobject.add_action(history_back.gobject());
gobject.add_action(history_forward.gobject());
gobject.add_action(home.gobject()); gobject.add_action(home.gobject());
gobject.add_action(pin.gobject()); gobject.add_action(pin.gobject());
gobject.add_action(reload.gobject()); gobject.add_action(reload.gobject());
@ -53,6 +73,10 @@ impl Action {
// Done // Done
Self { Self {
append, append,
close_all,
close,
history_back,
history_forward,
home, home,
pin, pin,
reload, reload,
@ -68,6 +92,26 @@ impl Action {
&self.append &self.append
} }
/// Get reference `CloseAll` action
pub fn close_all(&self) -> &Rc<CloseAll> {
&self.close_all
}
/// Get reference `Close` action
pub fn close(&self) -> &Rc<Close> {
&self.close
}
/// Get reference `HistoryBack` action
pub fn history_back(&self) -> &Rc<HistoryBack> {
&self.history_back
}
/// Get reference `HistoryForward` action
pub fn history_forward(&self) -> &Rc<HistoryForward> {
&self.history_forward
}
/// Get reference `Home` action /// Get reference `Home` action
pub fn home(&self) -> &Rc<Home> { pub fn home(&self) -> &Rc<Home> {
&self.home &self.home

View file

@ -0,0 +1,85 @@
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 `Close` action of `Window` group
pub struct Close {
gobject: SimpleAction,
}
impl Close {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
gobject: SimpleAction::new_stateful(
&uuid_string_random(),
None,
&DEFAULT_STATE.to_variant(),
),
}
}
// Actions
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
pub fn activate(&self) {
self.gobject.activate(None);
}
/// 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")
.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

@ -0,0 +1,85 @@
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 `CloseAll` action of `Window` group
pub struct CloseAll {
gobject: SimpleAction,
}
impl CloseAll {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
gobject: SimpleAction::new_stateful(
&uuid_string_random(),
None,
&DEFAULT_STATE.to_variant(),
),
}
}
// Actions
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
pub fn activate(&self) {
self.gobject.activate(None);
}
/// 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")
.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

@ -0,0 +1,85 @@
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 `HistoryBack` action of `Window` group
pub struct HistoryBack {
gobject: SimpleAction,
}
impl HistoryBack {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
gobject: SimpleAction::new_stateful(
&uuid_string_random(),
None,
&DEFAULT_STATE.to_variant(),
),
}
}
// Actions
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
pub fn activate(&self) {
self.gobject.activate(None);
}
/// 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")
.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

@ -0,0 +1,85 @@
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 `HistoryForward` action of `Window` group
pub struct HistoryForward {
gobject: SimpleAction,
}
impl HistoryForward {
// Constructors
/// Create new `Self`
pub fn new() -> Self {
Self {
gobject: SimpleAction::new_stateful(
&uuid_string_random(),
None,
&DEFAULT_STATE.to_variant(),
),
}
}
// Actions
/// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal
pub fn activate(&self) {
self.gobject.activate(None);
}
/// 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")
.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

@ -7,7 +7,6 @@ use widget::Widget;
use crate::app::browser::action::Action as BrowserAction; 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 adw::{TabView, ToolbarView}; use adw::{TabView, ToolbarView};
use gtk::gio::SimpleAction;
use std::rc::Rc; use std::rc::Rc;
pub struct Header { pub struct Header {
@ -20,23 +19,11 @@ impl Header {
// Actions // Actions
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
action_page_close: SimpleAction,
action_page_close_all: SimpleAction,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
// Widgets // Widgets
tab_view: &TabView, tab_view: &TabView,
) -> Rc<Self> { ) -> Rc<Self> {
// Init components // Init components
let bar = Bar::new_rc( let bar = Bar::new_rc(browser_action, window_action, tab_view);
browser_action,
window_action,
action_page_close,
action_page_close_all,
action_page_history_back,
action_page_history_forward,
tab_view,
);
// Return new struct // Return new struct
Rc::new(Self { Rc::new(Self {

View file

@ -11,7 +11,7 @@ use widget::Widget;
use crate::app::browser::action::Action as BrowserAction; 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 adw::TabView; use adw::TabView;
use gtk::{gio::SimpleAction, Box}; use gtk::Box;
use std::rc::Rc; use std::rc::Rc;
pub struct Bar { pub struct Bar {
@ -23,23 +23,12 @@ impl Bar {
pub fn new_rc( pub fn new_rc(
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
action_page_close: SimpleAction,
action_page_close_all: SimpleAction,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
view: &TabView, view: &TabView,
) -> Rc<Self> { ) -> Rc<Self> {
// Init components // Init components
let control = Control::new_rc(); let control = Control::new_rc();
let tab = Tab::new_rc(window_action.clone(), view); let tab = Tab::new_rc(window_action.clone(), view);
let menu = Menu::new_rc( let menu = Menu::new_rc(browser_action, window_action);
browser_action,
window_action,
action_page_close,
action_page_close_all,
action_page_history_back,
action_page_history_forward,
);
// Build result // Build result
Rc::new(Self { Rc::new(Self {

View file

@ -5,8 +5,7 @@ use widget::Widget;
use crate::app::browser::action::Action as BrowserAction; 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},
prelude::ActionExt,
MenuButton, MenuButton,
}; };
use std::rc::Rc; use std::rc::Rc;
@ -19,10 +18,6 @@ impl Menu {
pub fn new_rc( pub fn new_rc(
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
action_page_close: SimpleAction,
action_page_close_all: SimpleAction,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Rc<Self> { ) -> Rc<Self> {
// Main // Main
let main = gio::Menu::new(); let main = gio::Menu::new();
@ -58,8 +53,18 @@ impl Menu {
// Main > Page > Navigation > History // Main > Page > Navigation > History
let main_page_navigation_history = gio::Menu::new(); let main_page_navigation_history = gio::Menu::new();
main_page_navigation_history.append(Some("Back"), Some(&detailed_action_name(&action_page_history_back)));
main_page_navigation_history.append(Some("Forward"), Some(&detailed_action_name(&action_page_history_forward))); main_page_navigation_history.append(Some("Back"), Some(&format!(
"{}.{}",
window_action.id(),
window_action.history_back().id()
)));
main_page_navigation_history.append(Some("Forward"), Some(&format!(
"{}.{}",
window_action.id(),
window_action.history_forward().id()
)));
main_page_navigation.append_submenu(Some("History"), &main_page_navigation_history); main_page_navigation.append_submenu(Some("History"), &main_page_navigation_history);
@ -67,8 +72,18 @@ impl Menu {
// Main > Page > Close // Main > Page > Close
let main_page_close = gio::Menu::new(); let main_page_close = gio::Menu::new();
main_page_close.append(Some("Current"), Some(&detailed_action_name(&action_page_close)));
main_page_close.append(Some("All"), Some(&detailed_action_name(&action_page_close_all))); main_page_close.append(Some("Current"), Some(&format!(
"{}.{}",
window_action.id(),
window_action.close().id()
)));
main_page_close.append(Some("All"), Some(&format!(
"{}.{}",
window_action.id(),
window_action.close_all().id()
)));
main_page.append_submenu(Some("Close"), &main_page_close); main_page.append_submenu(Some("Close"), &main_page_close);
@ -113,10 +128,3 @@ impl Menu {
self.widget.gobject() self.widget.gobject()
} }
} }
// Private helpers
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
}

View file

@ -13,22 +13,15 @@ use widget::Widget;
use crate::app::browser::action::Action as BrowserAction; 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 adw::TabView; use adw::TabView;
use gtk::{ use gtk::glib::{GString, Propagation};
gio::SimpleAction,
glib::{GString, Propagation},
prelude::{ActionExt, ToVariant},
};
use sqlite::Transaction; use sqlite::Transaction;
use std::{cell::RefCell, collections::HashMap, rc::Rc}; use std::{cell::RefCell, collections::HashMap, rc::Rc};
// Main // Main
pub struct Tab { pub struct Tab {
// Global actions // Actions
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
// Page actions
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
// Dynamically allocated reference index // Dynamically allocated reference index
index: Rc<RefCell<HashMap<GString, Rc<Item>>>>, index: Rc<RefCell<HashMap<GString, Rc<Item>>>>,
action: Rc<Action>, action: Rc<Action>,
@ -37,14 +30,7 @@ pub struct Tab {
impl Tab { impl Tab {
// Construct // Construct
pub fn new_rc( pub fn new_rc(browser_action: Rc<BrowserAction>, window_action: Rc<WindowAction>) -> Rc<Self> {
browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>,
action_page_close: SimpleAction,
action_page_close_all: SimpleAction,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Rc<Self> {
// Init local actions // Init local actions
let action = Rc::new(Action::new()); let action = Rc::new(Action::new());
@ -52,13 +38,7 @@ impl Tab {
let index = Rc::new(RefCell::new(HashMap::new())); let index = Rc::new(RefCell::new(HashMap::new()));
// Init context menu // Init context menu
let menu = Menu::new( let menu = Menu::new(window_action.clone());
window_action.clone(),
action_page_close_all.clone(),
action_page_close.clone(),
action_page_history_back.clone(),
action_page_history_forward.clone(),
);
// Init widget // Init widget
let widget = Rc::new(Widget::new(menu.gobject())); let widget = Rc::new(Widget::new(menu.gobject()));
@ -73,20 +53,14 @@ impl Tab {
let window_action = window_action.clone(); let window_action = window_action.clone();
let action = action.clone(); let action = action.clone();
let action_page_history_back = action_page_history_back.clone();
let action_page_history_forward = action_page_history_forward.clone();
move |request| { move |request| {
// Init new tab item // Init new tab item
let item = Item::new_rc( let item = Item::new_rc(
&gobject, &gobject,
// Global actions // Actions
browser_action.clone(), browser_action.clone(),
window_action.clone(), window_action.clone(),
action.clone(), action.clone(),
// Page actions
action_page_history_back.clone(),
action_page_history_forward.clone(),
// Options // Options
gobject gobject
.selected_page() .selected_page()
@ -107,36 +81,23 @@ impl Tab {
}); });
widget.gobject().connect_setup_menu({ widget.gobject().connect_setup_menu({
// Clone actions to update
let action_page_close = action_page_close.clone();
let action_page_history_back = action_page_history_back.clone();
let action_page_history_forward = action_page_history_forward.clone();
let window_action = window_action.clone(); let window_action = window_action.clone();
move |tab_view, tab_page| { move |tab_view, tab_page| {
// Update actions // Set state
let state_v2 = match tab_page { let state = match tab_page {
// Context menu opened // Context menu opened
Some(this) => Some(tab_view.page_position(this)), Some(this) => Some(tab_view.page_position(this)),
// Context menu closed (reset state to defaults) // Context menu closed (reset state to defaults)
None => None, None => None,
}; // @TODO
window_action.pin().change_state(state_v2);
window_action.reload().change_state(state_v2);
window_action.home().change_state(state_v2);
// @TODO old version requires update
// Setup state for selected page
let state = match tab_page {
// Context menu opened
Some(this) => tab_view.page_position(this).to_variant(),
// Context menu closed (reset state to defaults)
None => (-1).to_variant(),
}; };
// Update actions with new state value
action_page_close.change_state(&state); window_action.close_all().change_state(state);
action_page_history_back.change_state(&state); window_action.close().change_state(state);
action_page_history_forward.change_state(&state); window_action.history_back().change_state(state);
window_action.history_forward().change_state(state);
window_action.home().change_state(state);
window_action.pin().change_state(state);
window_action.reload().change_state(state);
} }
}); });
@ -176,10 +137,6 @@ impl Tab {
Rc::new(Self { Rc::new(Self {
browser_action, browser_action,
window_action, window_action,
// Global actions
action_page_history_back,
action_page_history_forward,
// Init empty HashMap index as no tabs appended yet
index, index,
action, action,
widget, widget,
@ -193,11 +150,8 @@ impl Tab {
self.gobject(), self.gobject(),
self.browser_action.clone(), self.browser_action.clone(),
self.window_action.clone(), self.window_action.clone(),
// Local actions // Actions
self.action.clone(), self.action.clone(),
// Global actions
self.action_page_history_back.clone(),
self.action_page_history_forward.clone(),
// Options // Options
position, position,
false, false,
@ -338,8 +292,6 @@ impl Tab {
self.browser_action.clone(), self.browser_action.clone(),
self.window_action.clone(), self.window_action.clone(),
self.action.clone(), self.action.clone(),
self.action_page_history_back.clone(),
self.action_page_history_forward.clone(),
) { ) {
Ok(items) => { Ok(items) => {
for item in items { for item in items {

View file

@ -10,10 +10,7 @@ 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 crate::app::browser::window::tab::action::Action as TabAction; use crate::app::browser::window::tab::action::Action as TabAction;
use adw::{TabPage, TabView}; use adw::{TabPage, TabView};
use gtk::{ use gtk::glib::{uuid_string_random, GString};
gio::SimpleAction,
glib::{uuid_string_random, GString},
};
use sqlite::Transaction; use sqlite::Transaction;
use std::rc::Rc; use std::rc::Rc;
@ -30,13 +27,10 @@ impl Item {
// Construct // Construct
pub fn new_rc( pub fn new_rc(
tab_view: &TabView, tab_view: &TabView,
// Global actions // Actions
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
tab_action: Rc<TabAction>, tab_action: Rc<TabAction>,
// @TODO
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
// Options // Options
position: Option<i32>, position: Option<i32>,
is_pinned: bool, is_pinned: bool,
@ -52,8 +46,6 @@ impl Item {
browser_action, browser_action,
window_action, window_action,
tab_action, tab_action,
action_page_history_back.clone(),
action_page_history_forward.clone(),
); );
let widget = Widget::new_rc( let widget = Widget::new_rc(
@ -133,8 +125,6 @@ impl Item {
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
tab_action: Rc<TabAction>, tab_action: Rc<TabAction>,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Result<Vec<Rc<Item>>, String> { ) -> Result<Vec<Rc<Item>>, String> {
let mut items = Vec::new(); let mut items = Vec::new();
@ -148,8 +138,6 @@ impl Item {
browser_action.clone(), browser_action.clone(),
window_action.clone(), window_action.clone(),
tab_action.clone(), tab_action.clone(),
action_page_history_back.clone(),
action_page_history_forward.clone(),
// Options // Options
None, None,
record.is_pinned, record.is_pinned,

View file

@ -60,8 +60,6 @@ impl Page {
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
tab_action: Rc<TabAction>, tab_action: Rc<TabAction>,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Rc<Self> { ) -> Rc<Self> {
// Init local actions // Init local actions
let action_page_load = SimpleAction::new(&uuid_string_random(), None); let action_page_load = SimpleAction::new(&uuid_string_random(), None);
@ -74,8 +72,6 @@ impl Page {
let navigation = Navigation::new_rc( let navigation = Navigation::new_rc(
browser_action.clone(), browser_action.clone(),
window_action.clone(), window_action.clone(),
action_page_history_back.clone(),
action_page_history_forward.clone(),
action_page_open.clone(), action_page_open.clone(),
); );

View file

@ -33,13 +33,11 @@ impl Navigation {
pub fn new_rc( pub fn new_rc(
browser_action: Rc<BrowserAction>, browser_action: Rc<BrowserAction>,
window_action: Rc<WindowAction>, window_action: Rc<WindowAction>,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
action_page_open: SimpleAction, action_page_open: SimpleAction,
) -> Rc<Self> { ) -> Rc<Self> {
// Init components // Init components
let home = Home::new_rc(window_action.clone()); let home = Home::new_rc(window_action.clone());
let history = History::new_rc(action_page_history_back, action_page_history_forward); let history = History::new_rc(window_action.clone());
let reload = Reload::new_rc(window_action); let reload = Reload::new_rc(window_action);
let request = Request::new_rc(browser_action, action_page_open.clone()); let request = Request::new_rc(browser_action, action_page_open.clone());
let bookmark = Bookmark::new_rc(); let bookmark = Bookmark::new_rc();

View file

@ -6,7 +6,8 @@ use back::Back;
use forward::Forward; use forward::Forward;
use widget::Widget; use widget::Widget;
use gtk::{gio::SimpleAction, glib::GString, Box}; use crate::app::browser::window::action::Action as WindowAction;
use gtk::{glib::GString, Box};
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
struct Memory { struct Memory {
@ -27,13 +28,10 @@ pub struct History {
impl History { impl History {
// Construct // Construct
pub fn new_rc( pub fn new_rc(window_action: Rc<WindowAction>) -> Rc<Self> {
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Rc<Self> {
// init components // init components
let back = Back::new_rc(action_page_history_back); let back = Back::new_rc(window_action.clone());
let forward = Forward::new_rc(action_page_history_forward); let forward = Forward::new_rc(window_action);
// Init widget // Init widget
let widget = Widget::new_rc(back.gobject(), forward.gobject()); let widget = Widget::new_rc(back.gobject(), forward.gobject());

View file

@ -2,28 +2,32 @@ mod widget;
use widget::Widget; use widget::Widget;
use gtk::{gio::SimpleAction, Button}; use crate::app::browser::window::action::Action as WindowAction;
use gtk::Button;
use std::rc::Rc; use std::rc::Rc;
pub struct Back { pub struct Back {
action_page_history_back: SimpleAction, window_action: Rc<WindowAction>,
widget: Rc<Widget>, widget: Rc<Widget>,
} }
impl Back { impl Back {
// Construct // Construct
pub fn new_rc(action_page_history_back: SimpleAction) -> Rc<Self> { pub fn new_rc(window_action: Rc<WindowAction>) -> Rc<Self> {
// Return activated struct // Return activated struct
Rc::new(Self { Rc::new(Self {
action_page_history_back: action_page_history_back.clone(), window_action: window_action.clone(),
widget: Widget::new_rc(action_page_history_back), widget: Widget::new_rc(window_action),
}) })
} }
// Actions // Actions
pub fn update(&self, status: bool) { pub fn update(&self, status: bool) {
// Update actions // Update actions
self.action_page_history_back.set_enabled(status); self.window_action
.history_back()
.gobject()
.set_enabled(status);
// Update child components // Update child components
self.widget.update(status); self.widget.update(status);

View file

@ -1,6 +1,6 @@
use crate::app::browser::window::action::Action as WindowAction;
use gtk::{ use gtk::{
gio::SimpleAction, prelude::{ButtonExt, WidgetExt},
prelude::{ActionExt, ButtonExt, WidgetExt},
Button, Button,
}; };
use std::rc::Rc; use std::rc::Rc;
@ -11,7 +11,7 @@ pub struct Widget {
impl Widget { impl Widget {
// Construct // Construct
pub fn new_rc(action_page_history_back: SimpleAction) -> Rc<Self> { pub fn new_rc(window_action: Rc<WindowAction>) -> Rc<Self> {
// Init gobject // Init gobject
let gobject = Button::builder() let gobject = Button::builder()
.icon_name("go-previous-symbolic") .icon_name("go-previous-symbolic")
@ -21,9 +21,9 @@ impl Widget {
// Init events // Init events
gobject.connect_clicked({ gobject.connect_clicked({
let action_page_history_back = action_page_history_back.clone(); let window_action = window_action.clone();
move |_| { move |_| {
action_page_history_back.activate(None); window_action.history_back().activate();
} }
}); });

View file

@ -2,28 +2,32 @@ mod widget;
use widget::Widget; use widget::Widget;
use gtk::{gio::SimpleAction, Button}; use crate::app::browser::window::action::Action as WindowAction;
use gtk::Button;
use std::rc::Rc; use std::rc::Rc;
pub struct Forward { pub struct Forward {
action_page_history_forward: SimpleAction, window_action: Rc<WindowAction>,
widget: Rc<Widget>, widget: Rc<Widget>,
} }
impl Forward { impl Forward {
// Construct // Construct
pub fn new_rc(action_page_history_forward: SimpleAction) -> Rc<Self> { pub fn new_rc(window_action: Rc<WindowAction>) -> Rc<Self> {
// Return activated struct // Return activated struct
Rc::new(Self { Rc::new(Self {
action_page_history_forward: action_page_history_forward.clone(), window_action: window_action.clone(),
widget: Widget::new_rc(action_page_history_forward), widget: Widget::new_rc(window_action),
}) })
} }
// Actions // Actions
pub fn update(&self, status: bool) { pub fn update(&self, status: bool) {
// Update actions // Update actions
self.action_page_history_forward.set_enabled(status); self.window_action
.history_forward()
.gobject()
.set_enabled(status);
// Update child components // Update child components
self.widget.update(status); self.widget.update(status);

View file

@ -1,6 +1,6 @@
use crate::app::browser::window::action::Action as WindowAction;
use gtk::{ use gtk::{
gio::SimpleAction, prelude::{ButtonExt, WidgetExt},
prelude::{ActionExt, ButtonExt, WidgetExt},
Button, Button,
}; };
use std::rc::Rc; use std::rc::Rc;
@ -11,7 +11,7 @@ pub struct Widget {
impl Widget { impl Widget {
// Construct // Construct
pub fn new_rc(action_page_history_forward: SimpleAction) -> Rc<Self> { pub fn new_rc(window_action: Rc<WindowAction>) -> Rc<Self> {
// Init gobject // Init gobject
let gobject = Button::builder() let gobject = Button::builder()
.icon_name("go-next-symbolic") .icon_name("go-next-symbolic")
@ -21,9 +21,9 @@ impl Widget {
// Init events // Init events
gobject.connect_clicked({ gobject.connect_clicked({
let action_page_history_forward = action_page_history_forward.clone(); let window_action = window_action.clone();
move |_| { move |_| {
action_page_history_forward.activate(None); window_action.history_forward().activate();
} }
}); });

View file

@ -1,7 +1,5 @@
use std::rc::Rc;
use crate::app::browser::window::action::Action as WindowAction; use crate::app::browser::window::action::Action as WindowAction;
use gtk::{gio::SimpleAction, prelude::ActionExt}; use std::rc::Rc;
/// Context menu wrapper /// Context menu wrapper
/// ///
@ -14,13 +12,7 @@ impl Menu {
// Constructors // Constructors
/// Create new `Self` /// Create new `Self`
pub fn new( pub fn new(window_action: Rc<WindowAction>) -> Self {
window_action: Rc<WindowAction>,
action_page_close_all: SimpleAction,
action_page_close: SimpleAction,
action_page_history_back: SimpleAction,
action_page_history_forward: SimpleAction,
) -> Self {
let main = gtk::gio::Menu::new(); let main = gtk::gio::Menu::new();
main.append( main.append(
@ -58,12 +50,20 @@ impl Menu {
history.append( history.append(
Some("Back"), Some("Back"),
Some(&detailed_action_name(action_page_history_back)), Some(&format!(
"{}.{}",
window_action.id(),
window_action.history_back().id()
)),
); );
history.append( history.append(
Some("Forward"), Some("Forward"),
Some(&detailed_action_name(action_page_history_forward)), Some(&format!(
"{}.{}",
window_action.id(),
window_action.history_forward().id()
)),
); );
main.append_submenu(Some("History"), &history); main.append_submenu(Some("History"), &history);
@ -72,12 +72,20 @@ impl Menu {
close.append( close.append(
Some("Current"), Some("Current"),
Some(&detailed_action_name(action_page_close)), Some(&format!(
"{}.{}",
window_action.id(),
window_action.close().id()
)),
); );
close.append( close.append(
Some("All"), Some("All"),
Some(&detailed_action_name(action_page_close_all)), Some(&format!(
"{}.{}",
window_action.id(),
window_action.close_all().id()
)),
); );
main.append_submenu(Some("Close"), &close); main.append_submenu(Some("Close"), &close);
@ -90,11 +98,3 @@ impl Menu {
&self.gobject &self.gobject
} }
} }
// Private helpers
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
}