workflow_nw/
shortcut.rs

1//!
2//! Builder for application shortcuts.
3//!
4//! # Synopsis
5//! ```rust
6//! use workflow_nw::prelude::*;
7//! use workflow_nw::result::Result;
8//! use workflow_dom::utils::window;
9//!
10//! # fn test()->Result<()>{
11//!
12//! let shortcut = ShortcutBuilder::new()
13//!     .key("Ctrl+Shift+Q")
14//!     .active(|_|{
15//!         window().alert_with_message("Ctrl+Shift+Q pressed, App will close")?;
16//!         //nw_sys::app::quit();
17//!         nw_sys::app::close_all_windows();
18//!         Ok(())
19//!     })
20//!     .build()?;
21//!     
22//! nw_sys::app::register_global_hot_key(&shortcut);
23//!
24//! # Ok(())
25//! # }
26//! ```
27//!
28
29use crate::application::app;
30use crate::result::Result;
31use nw_sys::prelude::*;
32use wasm_bindgen::prelude::*;
33use workflow_wasm::prelude::*;
34
35/// Shortcut Info Object returned by [`ShortcutBuilder.finalize`](ShortcutBuilder#method.finalize) method
36pub struct ShortcutInfo {
37    pub shortcut: nw_sys::Shortcut,
38    pub active_callback: Option<Callback<CallbackClosure<JsValue>>>,
39    pub failed_callback: Option<Callback<CallbackClosure<JsValue>>>,
40}
41
42/// Provides a builder pattern for building application
43/// keyboard shortcuts.
44///
45/// For usage example please refer to [Examples](self)
46pub struct ShortcutBuilder {
47    pub options: nw_sys::shortcut::Options,
48    pub active_callback: Option<Callback<CallbackClosure<JsValue>>>,
49    pub failed_callback: Option<Callback<CallbackClosure<JsValue>>>,
50}
51
52impl Default for ShortcutBuilder {
53    fn default() -> Self {
54        Self::new()
55    }
56}
57
58impl ShortcutBuilder {
59    pub fn new() -> Self {
60        Self {
61            options: nw_sys::shortcut::Options::new(),
62            active_callback: None,
63            failed_callback: None,
64        }
65    }
66
67    fn set(mut self, key: &str, value: JsValue) -> Self {
68        self.options = self.options.set(key, value);
69        self
70    }
71
72    /// Set the `key` of a `Shortcut`.
73    /// It is a string to specify the shortcut key, like "Ctrl+Alt+A".
74    /// The key is consisted of zero or more modifiers and a key on your keyboard.
75    /// Only one key code is supported. Key code is case insensitive.
76    ///
77    /// ### List of supported modifiers:
78    ///
79    /// - Ctrl
80    /// - Alt
81    /// - Shift
82    /// - Command: Command modifier maps to Apple key (⌘) on Mac,
83    ///   and maps to the Windows key on Windows and Linux.
84    ///
85    /// ### List of supported keys:
86    ///
87    /// - Alphabet: `A`-`Z`
88    /// - Digits: `0`-`9`
89    /// - Function Keys: `F1`-`F24`
90    /// - Home / End / PageUp / PageDown / Insert / Delete
91    /// - Up / Down / Left / Right
92    /// - MediaNextTrack / MediaPlayPause / MediaPrevTrack / MediaStop
93    /// - Comma or `,`
94    /// - Period or `.`
95    /// - Tab or `\t`
96    /// - Backquote or `` ` ``
97    /// - Enter or `\n`
98    /// - Minus or `-`
99    /// - Equal or `=`
100    /// - Backslash or `\`
101    /// - Semicolon or `;`
102    /// - Quote or `'`
103    /// - BracketLeft or `[`
104    /// - BracketRight or `]`
105    /// - Escape
106    ///
107    ///
108    /// ⧉ [NWJS Documentation](https://docs.nwjs.io/en/latest/References/Shortcut/#shortcutkey)
109    pub fn key(self, key: &str) -> Self {
110        self.set("key", JsValue::from(key))
111    }
112
113    /// Set the active callback of a Shortcut.
114    /// It will be called when user presses the shortcut.
115    ///
116    /// ⧉ [NWJS Documentation](https://docs.nwjs.io/en/latest/References/Shortcut/#shortcutactive)
117    pub fn active<F>(mut self, callback: F) -> Self
118    where
119        F: FnMut(JsValue) -> std::result::Result<(), JsValue> + 'static,
120    {
121        let callback = Callback::new(callback);
122        self = self.set("active", callback.clone().into());
123        self.active_callback = Some(callback);
124
125        self
126    }
127
128    /// Set the failed callback of a Shortcut.
129    /// It will be called when application passes an invalid key,
130    /// or failed to register the key.
131    ///
132    /// ⧉ [NWJS Documentation](https://docs.nwjs.io/en/latest/References/Shortcut/#shortcutfailed)
133    pub fn failed<F>(mut self, callback: F) -> Self
134    where
135        F: FnMut(JsValue) -> std::result::Result<(), JsValue> + 'static,
136    {
137        let callback = Callback::new(callback);
138        self = self.set("failed", callback.clone().into());
139        self.failed_callback = Some(callback);
140
141        self
142    }
143
144    /// create [nw_sys::Shortcut](nw_sys::Shortcut) and
145    /// return it
146    ///
147    pub fn build(self) -> Result<nw_sys::Shortcut> {
148        if let Some(callback) = self.active_callback {
149            let app = match app() {
150                Some(app) => app,
151                None => return Err("app is not initialized".to_string().into()),
152            };
153            app.callbacks.retain(callback)?;
154        }
155        if let Some(callback) = self.failed_callback {
156            let app = match app() {
157                Some(app) => app,
158                None => return Err("app is not initialized".to_string().into()),
159            };
160            app.callbacks.retain(callback)?;
161        }
162
163        let shortcut = nw_sys::Shortcut::new(&self.options);
164        Ok(shortcut)
165    }
166
167    /// create [nw_sys::Shortcut](nw_sys::Shortcut) and
168    /// return it with
169    /// [active_callback](Self#structfield.active_callback),
170    /// [failed_callback](Self#structfield.failed_callback) handlers
171    ///
172    pub fn finalize(self) -> Result<ShortcutInfo> {
173        let shortcut = nw_sys::Shortcut::new(&self.options);
174        Ok(ShortcutInfo {
175            shortcut,
176            active_callback: self.active_callback,
177            failed_callback: self.failed_callback,
178        })
179    }
180}