diff --git a/src/app.rs b/src/app.rs index b7eb7970..90a1d8d9 100644 --- a/src/app.rs +++ b/src/app.rs @@ -200,6 +200,14 @@ impl App { ), &["s"], ), + ( + format!( + "{}.{}", + browser.window.action.id, + browser.window.action.open.simple_action.name() + ), + &["o"], + ), ( format!( "{}.{}", diff --git a/src/app/browser/window/action.rs b/src/app/browser/window/action.rs index f799ad82..0ec2f340 100644 --- a/src/app/browser/window/action.rs +++ b/src/app/browser/window/action.rs @@ -7,6 +7,7 @@ mod history_back; mod history_forward; mod home; mod load; +mod open; mod pin; mod reload; mod save_as; @@ -21,6 +22,7 @@ use history_back::HistoryBack; use history_forward::HistoryForward; use home::Home; use load::Load; +use open::Open; use pin::Pin; use reload::Reload; use save_as::SaveAs; @@ -47,6 +49,7 @@ pub struct Action { pub history_forward: Rc, pub home: Rc, pub load: Rc, + pub open: Rc, pub pin: Rc, pub reload: Rc, pub save_as: Rc, @@ -77,6 +80,7 @@ impl Action { let history_forward = Rc::new(HistoryForward::new()); let home = Rc::new(Home::new()); let load = Rc::new(Load::new()); + let open = Rc::new(Open::new()); let pin = Rc::new(Pin::new()); let reload = Rc::new(Reload::new()); let save_as = Rc::new(SaveAs::new()); @@ -98,6 +102,7 @@ impl Action { simple_action_group.add_action(&history_forward.simple_action); simple_action_group.add_action(&home.simple_action); simple_action_group.add_action(&load.simple_action); + simple_action_group.add_action(&open.simple_action); simple_action_group.add_action(&pin.simple_action); simple_action_group.add_action(&reload.simple_action); simple_action_group.add_action(&save_as.simple_action); @@ -113,13 +118,14 @@ impl Action { history_back, history_forward, home, + id, load, + open, pin, reload, save_as, - source, - id, simple_action_group, + source, } } @@ -133,6 +139,7 @@ impl Action { self.history_back.change_state(state); self.history_forward.change_state(state); self.home.change_state(state); + self.open.change_state(state); self.pin.change_state(state); self.reload.change_state(state); self.save_as.change_state(state); diff --git a/src/app/browser/window/action/open.rs b/src/app/browser/window/action/open.rs new file mode 100644 index 00000000..f1a39256 --- /dev/null +++ b/src/app/browser/window/action/open.rs @@ -0,0 +1,70 @@ +use gtk::{ + gio::SimpleAction, + glib::uuid_string_random, + prelude::{ActionExt, ToVariant}, +}; + +// Defaults + +/// C-compatible variant type +const DEFAULT_STATE: i32 = -1; + +/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Open` action +pub struct Open { + pub simple_action: SimpleAction, +} + +impl Default for Open { + fn default() -> Self { + Self::new() + } +} + +impl Open { + // Constructors + + /// Create new `Self` + pub fn new() -> Self { + Self { + simple_action: 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.simple_action.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) { + self.simple_action.connect_activate(move |this, _| { + let state = this + .state() + .expect("State value required") + .get::() + .expect("Parameter type does not match `i32`"); + + callback(if state == DEFAULT_STATE { + None + } else { + Some(state) + }) + }); + } +} diff --git a/src/app/browser/window/header/bar/menu.rs b/src/app/browser/window/header/bar/menu.rs index 7cac6152..106e2903 100644 --- a/src/app/browser/window/header/bar/menu.rs +++ b/src/app/browser/window/header/bar/menu.rs @@ -47,11 +47,22 @@ impl Menu for MenuButton { window_action.find.simple_action.name() ))); - main_page.append(Some("Save as.."), Some(&format!( - "{}.{}", - window_action.id, - window_action.save_as.simple_action.name() - ))); + // Main > Page > File + let main_page_file = gio::Menu::new(); + + main_page_file.append(Some("Open.."), Some(&format!( + "{}.{}", + window_action.id, + window_action.open.simple_action.name() + ))); + + main_page_file.append(Some("Save as.."), Some(&format!( + "{}.{}", + window_action.id, + window_action.save_as.simple_action.name() + ))); + + main_page.append_submenu(Some("File"), &main_page_file); // Main > Page > Mark let main_page_mark = gio::Menu::new(); diff --git a/src/app/browser/window/tab/menu.rs b/src/app/browser/window/tab/menu.rs index 5023b8d7..5c1ff3db 100644 --- a/src/app/browser/window/tab/menu.rs +++ b/src/app/browser/window/tab/menu.rs @@ -34,7 +34,18 @@ impl Menu for gtk::gio::Menu { )), ); - main.append( + let main_file = gtk::gio::Menu::new(); + + main_file.append( + Some("Open.."), + Some(&format!( + "{}.{}", + window_action.id, + window_action.open.simple_action.name() + )), + ); + + main_file.append( Some("Save as.."), Some(&format!( "{}.{}", @@ -43,6 +54,8 @@ impl Menu for gtk::gio::Menu { )), ); + main.append_submenu(Some("File"), &main_file); + let main_mark = gtk::gio::Menu::new(); main_mark.append(