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}