cursive_extras/macros.rs
1/// Convenience macro that updates the specified `StatusView` reference with an error message and returns
2/// from the current callback if an error happens, returns the `Ok` value otherwise
3///
4/// # Example
5/// ```
6/// let mut root = cursive::default();
7/// root.add_fullscreen_layer(
8/// hlayout!(
9/// Dialog::text("Yes")
10/// .button("Quit", Cursive::quit)
11/// .title("Error Reporting example")
12/// StatusView::new().with_name("status")
13/// )
14/// );
15/// root.set_fps(30);
16/// root.set_global_callback(Event::Refresh, |root| {
17/// let error: Result<&str, &str> = Err("Error: Houston, we have a problem!");
18/// let mut status = root.find_name::<StatusView>("status").expect("StatusView does not exist!");
19/// report_error!(status, error);
20/// status.update();
21/// });
22/// root.run();
23/// ```
24#[macro_export]
25macro_rules! report_error {
26 ($status_view:expr, $res_val:expr) => {
27 match $res_val {
28 Ok(v) => v,
29 Err(error) => {
30 $status_view.report_error(error);
31 return;
32 }
33 }
34 }
35}
36
37/// Convenience macro that makes `SelectView`s easier to create
38///
39/// # Example
40/// ```
41/// let sv = select_view! {
42/// "yes" => true,
43/// "no" => false
44/// }.on_submit(|r, _| r.quit());
45///
46/// let mut root = cursive::default();
47/// root.add_fullscreen_layer(Dialog::around(sv).title("Select View"));
48/// root.run();
49/// ```
50#[macro_export]
51macro_rules! select_view {
52 ($($label:expr => $item:expr), *) => {
53 {
54 let mut temp_sv = $crate::siv::views::SelectView::new();
55 $( temp_sv.add_item($label, $item); )*
56 temp_sv
57 }
58 };
59
60 ($($label:expr), *) => {
61 select_view!($($label => $label), *)
62 }
63}
64
65/// Convenience macro that makes `AdvancedSelectView`s easier to create
66///
67/// # Example
68/// ```
69/// let adv_sv = adv_select_view! {
70/// "yes" => true,
71/// "no" => false
72/// }.on_submit(|r, _| r.quit());
73///
74/// let mut root = cursive::default();
75/// root.add_fullscreen_layer(Dialog::around(adv_sv).title("Advanced Select View"));
76/// root.run();
77/// ```
78#[cfg(feature = "advanced")]
79#[macro_export]
80macro_rules! adv_select_view {
81 ($($label:expr => $item:expr), *) => {
82 {
83 let mut temp_sv = $crate::AdvancedSelectView::new();
84 $( temp_sv.add_item($label, $item); )*
85 temp_sv
86 }
87 };
88
89 ($($label:expr), *) => {
90 adv_select_view!($($label => $label), *)
91 }
92}
93
94/// Convenience macro to generate a `TabDialog` view
95#[cfg(feature = "tabs")]
96#[macro_export]
97macro_rules! tabs {
98 ($($title:expr => $view:expr), *) => {
99 $crate::TabDialog::new()
100 $( .tab($title, $view) ) *
101 }
102}
103
104/// Convenience macro to generate a `TabLayer` view
105#[cfg(feature = "tabs")]
106#[macro_export]
107macro_rules! tab_layer {
108 ($($title:expr => $view:expr), *) => {
109 $crate::TabLayer::new()
110 $( .tab($title, $view) ) *
111 }
112}
113
114/// Convenience macro that creates a horizontal layout of views
115///
116/// # Example
117/// ```
118/// let mut root = cursive::default();
119/// root.add_fullscreen_layer(
120/// Dialog::around(
121/// hlayout!(
122/// TextView::new("Yes "),
123/// TextView::new("No")
124/// )
125/// )
126/// .button("Quit", Cursive::quit)
127/// );
128/// root.run();
129/// ```
130#[macro_export]
131macro_rules! hlayout {
132 ($($view:expr), *) => {
133 $crate::siv::views::LinearLayout::horizontal()
134 $( .child($view) )*
135 };
136}
137
138/// Convenience macro that creates a vertical layout of views
139///
140/// # Example
141/// ```
142/// let mut root = cursive::default();
143/// root.add_fullscreen_layer(
144/// Dialog::around(
145/// vlayout!(
146/// TextView::new("Yes "),
147/// TextView::new("No")
148/// )
149/// )
150/// .button("Quit", Cursive::quit)
151/// );
152/// root.run();
153/// ```
154#[macro_export]
155macro_rules! vlayout {
156 ($($view:expr), *) => {
157 $crate::siv::views::LinearLayout::vertical()
158 $( .child($view) )*
159 };
160}
161
162/// Convenience macro that wraps a view in a `CircularFocus` that wraps the arrow keys
163#[macro_export]
164macro_rules! c_focus {
165 ($view:expr) => {
166 $crate::siv::views::CircularFocus::new($view).wrap_arrows()
167 }
168}
169
170/// Convenience macro that generates a settings view using sub-views wrapped in a `Dialog` view
171///
172/// # Example
173/// ```
174/// let mut root = cursive::default();
175/// root.add_fullscreen_layer(
176/// settings!(
177/// "Settings Example", // title
178/// Cursive::quit, // callback if "Save" is selected
179/// TextView::new("Option:"), // views
180/// EditView::new()
181/// )
182/// );
183/// root.run();
184/// ```
185#[macro_export]
186macro_rules! settings {
187 ($title:expr, $save_cb:expr, $($view:expr), *) => {
188 $crate::__settings_internal!($title, "Save", $save_cb $(, $view)*)
189 };
190}
191
192/// Same as the `settings!` macro, but allows for a custom confirmation text to be defined as well
193#[macro_export]
194macro_rules! settings_cb {
195 ($title:expr, $c_bt:expr, $save_cb:expr, $($view:expr), *) => {
196 $crate::__settings_internal!($title, $c_bt, $save_cb $(, $view)*)
197 };
198}
199
200#[macro_export(local_inner_macros)]
201#[doc(hidden)]
202macro_rules! __settings_internal {
203 ($title:expr, $c_bt:expr, $save_cb:expr, $($view:expr), *) => {
204 {
205 use $crate::siv::{
206 traits::{With as _, Scrollable as _},
207 views::{Dialog, OnEventView},
208 event::{Key, Event}
209 };
210
211 $crate::c_focus!(
212 Dialog::around(
213 $crate::vlayout!($($view), *)
214 .scrollable()
215 .scroll_x(true)
216 )
217 .dismiss_button("Back")
218 .button($c_bt, $save_cb)
219 .title($title)
220 .wrap_with(OnEventView::new)
221 .on_event(Event::Key(Key::Esc), |r| {
222 if r.screen().len() <= 1 {
223 r.quit();
224 }
225 else {
226 r.pop_layer();
227 }
228 })
229 )
230 }
231 };
232}