gtk_macros/
lib.rs

1///
2/// Retrieve a widget from a gtk::Builder
3///
4/// - Before:
5///
6///     Example:
7///
8///     ```no_run
9///     let builder = gtk::Builder::new_frm_resource("/org/gnome/App/ui/widget.ui");
10///     let widget: gtk::Label = builder.object("my_label").expect("Failed to find my_label object");
11///     widget.set_text("Hello world!");
12///
13///     ```
14///
15/// - After:
16///
17///     Example 1:
18///
19///     ```no_run
20///     let builder = gtk::Builder::new_from_resource("/org/gnome/App/ui/widget.ui");
21///     get_widget!(builder, gtk::Label, my_label);
22///     my_label.set_text("Hello world!");
23///     ```
24///     Example 2:
25///
26///     ```no_run
27///     let builder = gtk::Builder::new_from_resource("/org/gnome/App/ui/widget.ui");
28///     get_widget!(builder, gtk::Label, @my_label).set_text("Hello world!");
29///     ```
30#[macro_export]
31macro_rules! get_widget {
32    ($builder:expr, $wtype:ty, @$name:ident) => {{
33        let $name: $wtype = $builder
34            .object(stringify!($name))
35            .expect(&format!("Could not find widget \"{}\" of type \"{}\"", stringify!($name), stringify!($wtype)));
36        $name
37    }};
38    ($builder:expr, $wtype:ty, $name:ident) => {
39        let $name: $wtype = $builder
40            .object(stringify!($name))
41            .expect(&format!("Could not find widget \"{}\" of type \"{}\"", stringify!($name), stringify!($wtype)));
42    };
43}
44
45/// Spawn a future
46///
47/// - Before:
48///
49///     Example:
50///
51///     ```no_run
52///     let ctx = glib::MainContext::default();
53///     ctx.spawn_local(async {
54///         something.await;
55///     });
56///     ```
57///
58/// - After:
59///
60///     Example:
61///
62///     ```no_run
63///     spawn!(async {
64///         something.await;
65///     });
66///     ```
67#[macro_export]
68macro_rules! spawn {
69    ($future:expr) => {
70        let ctx = glib::MainContext::default();
71        ctx.spawn_local($future);
72    };
73}
74
75/// Send an event through a glib::Sender
76///
77/// - Before:
78///
79///     Example:
80///
81///     ```no_run
82///     sender.send(Action::DoThing).expect("Failed to send DoThing through the glib channel?");
83///     ```
84///
85/// - After:
86///
87///     Example:
88///
89///     ```no_run
90///     send!(self.sender, Action::DoThing);
91///     ```
92#[macro_export]
93macro_rules! send {
94    ($sender:expr, $action:expr) => {
95        if let Err(err) = $sender.send($action) {
96            error!("Failed to send \"{}\" action due to {}", stringify!($action), err);
97        }
98    };
99}
100
101/// Create a new action
102///
103/// - Before:
104///
105///     Example:
106///
107///     ```no_run
108///     let widget = get_widget!(builder, gtk::Window, widget);
109///     let actions = gio::SimpleActionGroup::new();
110///     widget.insert_action_group("export", Some(&actions));
111///
112///     let action = gio::SimpleAction::new("do", None);
113///     action.connect_activate(move |action, _| {
114///         // Do something
115///     });
116///     actions.add_action(&action);
117///     ```
118///
119/// - After:
120///
121///     Example:
122///
123///     ```no_run
124///     let widget = get_widget!(builder, gtk::Window, widget);
125///     let actions = gio::SimpleActionGroup::new();
126///     widget.insert_action_group("export", Some(&actions));
127///     action!(
128///         actions,
129///         "do",
130///         move |action, _| {
131///             // Do something
132///         },
133///     );
134///     ```
135#[macro_export]
136macro_rules! action {
137    ($actions_group:expr, $name:expr, $callback:expr) => {
138        let simple_action = gio::SimpleAction::new($name, None);
139        simple_action.connect_activate($callback);
140        $actions_group.add_action(&simple_action);
141    };
142    ($actions_group:expr, $name:expr, $param_type:expr, $callback:expr) => {
143        let simple_action = gio::SimpleAction::new($name, $param_type);
144        simple_action.connect_activate($callback);
145        $actions_group.add_action(&simple_action);
146    };
147}
148
149/// Create a new stateful action
150///
151/// - Before:
152///
153///     Example:
154///
155///     ```no_run
156///     let actions = gio::SimpleActionGroup::new();
157///
158///     let is_dark_mode = false;
159///     let action = gio::SimpleAction::new_stateful("dark-mode", None, &is_dark_mode.to_variant());
160///     action.connect_activate(move |action, _| {
161///         let state = action.state().unwrap();
162///         let action_state: bool = state.get().unwrap();
163///         let is_dark_mode = !action_state;
164///         action.set_state(&is_dark_mode.to_variant());
165///     });
166///     actions.add_action(&action);
167///     ```
168///
169/// - After:
170///
171///     Example:
172///     ```no_run
173///     let actions = gio::SimpleActionGroup::new();
174///     let is_dark_mode = false;
175///     stateful_action!(actions, "dark-mode", is_dark_mode, move |action, _| {
176///         let state = action.state().unwrap();
177///         let action_state: bool = state.get().unwrap();
178///         let is_dark_mode = !action_state;
179///         action.set_state(&is_dark_mode.to_variant());
180///
181///         // Store the state using gsettings for example
182///     });
183///     ```
184#[macro_export]
185macro_rules! stateful_action {
186    ($actions_group:expr, $name:expr, $state:expr, $callback:expr) => {
187        let simple_action = gio::SimpleAction::new_stateful($name, None, &$state.to_variant());
188        simple_action.connect_activate($callback);
189        $actions_group.add_action(&simple_action);
190    };
191    ($actions_group:expr, $name:expr, $param_type:expr, $state:expr, $callback:expr) => {
192        let simple_action = gio::SimpleAction::new_stateful($name, $param_type, &$state.to_variant());
193        simple_action.connect_activate($callback);
194        $actions_group.add_action(&simple_action);
195    };
196}
197
198/// Retrieve an action from a gio::ActionGroup
199///
200/// - Before:
201///
202///     Example:
203///
204///     ```no_run
205///     let actions = gio::SimpleActionGroup::new();
206///     action!(
207///         actions,
208///         "delete",
209///         move |action, _| {
210///             // Do something
211///         },
212///     );
213///     let action = actions.lookup_action("delete")
214///                     .unwrap()
215///                     .downcast::<gio::SimpleAction>()
216///                     .unwrap();
217///     action.set_enabled(false);
218///     ```
219///
220/// - After:
221///
222///     Example:
223///
224///     ```no_run
225///     let actions = gio::SimpleActionGroup::new();
226///     action!(
227///         actions,
228///         "delete",
229///         move |action, _| {
230///             // Do something
231///         },
232///     );
233///     get_action!(actions, @delete).set_enabled(false);
234///     ```
235#[macro_export]
236macro_rules! get_action {
237    ($actions:expr, @$name:ident) => {{
238        let $name = $actions
239            .lookup_action(stringify!($name))
240            .expect(&format!("Could not find action \"{}\"", stringify!($name)))
241            .downcast::<gio::SimpleAction>()
242            .unwrap();
243        $name
244    }};
245
246    ($actions:expr, $name:ident) => {
247        let $name = $actions
248            .lookup_action(stringify!($name))
249            .expect(&format!("Could not find action \"{}\"", stringify!($name)))
250            .downcast::<gio::SimpleAction>()
251            .unwrap();
252    };
253}
254
255/// Add a style class or list of style classes to a widget
256///
257/// - Before:
258///
259///     Example 1:
260///
261///     ```no_run
262///     let button = gtk::Button::new();
263///     let ctx = button.style_context();
264///     ctx.add_class("foo");
265///     ```
266///
267///     Example 2:
268///
269///     ```no_run
270///     let button = gtk::Button::new();
271///     let ctx = button.style_context();
272///     ctx.add_class("foo");
273///     ctx.add_class("bar");
274///     ```
275///
276/// - After:
277///
278///     Example 1:
279///
280///     ```no_run
281///     let button = gtk::Button::new();
282///     add_style_class!(button, @foo);
283///     ```
284///
285///     Example 2:
286///
287///     ```no_run
288///     let button = gtk::Button::new();
289///     add_style_class!(button, &["foo", "bar"]);
290///     ```
291#[macro_export]
292macro_rules! add_style_class {
293    ($widget:expr, @$name:ident) => {{
294        let ctx = $widget.style_context();
295        ctx.add_class(stringify!($name));
296    }};
297    ($widget:expr, $names:expr) => {{
298        let ctx = $widget.style_context();
299        for name in $names {
300            ctx.add_class(name);
301        }
302    }};
303}