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}