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}