1use crate::{
2 hlayout,
3 views::{LoadingAnimation, Spacer}
4};
5use std::fmt::Display;
6use cursive_core::{
7 Cursive, With,
8 view::Nameable,
9 event::{Event, Key},
10 views::{
11 EditView,
12 Dialog,
13 OnEventView,
14 NamedView,
15 Checkbox,
16 LinearLayout,
17 TextView,
18 DummyView,
19 ResizedView
20 },
21 utils::markup::StyledString,
22 theme::{
23 PaletteColor,
24 Color,
25 BaseColor,
26 ColorType,
27 ColorStyle,
28 BorderStyle,
29 Theme
30 }
31};
32
33pub fn better_theme() -> Theme {
41 let mut theme_def = Theme {
42 shadow: false,
43 .. Theme::default()
44 };
45 theme_def.palette[PaletteColor::Background] = Color::TerminalDefault;
46 theme_def.palette[PaletteColor::Primary] = Color::Light(BaseColor::White);
47 theme_def.palette[PaletteColor::View] = Color::TerminalDefault;
48 theme_def.palette[PaletteColor::Highlight] = Color::Light(BaseColor::Blue);
49 theme_def.palette[PaletteColor::HighlightText] = Color::Dark(BaseColor::White);
50 theme_def.palette[PaletteColor::Secondary] = Color::Dark(BaseColor::Blue);
51 theme_def.palette[PaletteColor::TitlePrimary] = Color::Light(BaseColor::Blue);
52 theme_def.palette[PaletteColor::TitleSecondary] = Color::Dark(BaseColor::Blue);
53 theme_def.borders = BorderStyle::Outset;
54 theme_def
55}
56
57pub fn confirm_dialog<T, U, C>(title: T, text: U, cb: C) -> OnEventView<Dialog>
67where
68 T: Display,
69 U: Into<StyledString>,
70 C: Fn(&mut Cursive) + Send + Sync + 'static
71{
72 Dialog::text(text)
73 .dismiss_button("No")
74 .button("Yes", cb)
75 .title(title.to_string())
76 .wrap_with(OnEventView::new)
77 .on_event(Event::Key(Key::Esc), |r| {
78 if r.screen().len() <= 1 { r.quit(); }
79 else { r.pop_layer(); }
80 })
81}
82
83pub fn info_dialog<T: Display, U: Into<StyledString>>(title: T, text: U) -> OnEventView<Dialog> {
93 Dialog::text(text)
94 .dismiss_button("Back")
95 .title(title.to_string())
96 .wrap_with(OnEventView::new)
97 .on_event(Event::Key(Key::Esc), |r| {
98 if r.screen().len() <= 1 { r.quit(); }
99 else { r.pop_layer(); }
100 })
101}
102
103pub fn styled_editview<C: Display>(content: C, view_name: &str, password: bool) -> NamedView<EditView> {
117 styled_editview_color(content, view_name, password, PaletteColor::TitlePrimary)
118}
119
120pub fn styled_editview_color<T: Display, C: Into<ColorType>>(content: T, view_name: &str, password: bool, color: C) -> NamedView<EditView> {
122 let input_style = ColorStyle::new(
123 Color::Light(BaseColor::White),
124 color
125 );
126 let view = EditView::new().content(content.to_string()).style(input_style).filler(" ");
127
128 if password { view.secret() }
129 else { view }
130 .with_name(view_name)
131}
132
133pub fn get_checkbox_option(root: &mut Cursive, name: &str) -> bool {
138 if let Some(cbox) = root.find_name::<Checkbox>(name) {
139 cbox.is_checked()
140 }
141 else { false }
142}
143
144pub fn labeled_checkbox(text: &str, name: &str, checked: bool) -> LinearLayout {
146 labeled_checkbox_cb(text, name, checked, |_, _| { })
147}
148
149pub fn labeled_checkbox_cb<C: Fn(&mut Cursive, bool) + Send + Sync + 'static>(text: &str, name: &str, checked: bool, callback: C) -> LinearLayout {
151 hlayout!(
152 Checkbox::new()
153 .with_checked(checked)
154 .on_change(callback)
155 .with_name(name),
156 TextView::new(format!(" {text}"))
157 )
158}
159
160pub fn load_resource<T, D, M, R, F>(root: &mut Cursive, title: D, msg: M, task: R, finish_task: F)
181where
182 T: Send + Sync + 'static,
183 D: Display,
184 M: Into<StyledString>,
185 R: FnOnce() -> T + Send + Sync + 'static,
186 F: FnOnce(&mut Cursive, T) + Send + Sync + 'static,
187{
188 let loader = LoadingAnimation::new(msg, move || (task(), finish_task));
189 if root.fps().is_none() { root.set_fps(30); }
190 root.add_layer(
191 Dialog::around(loader.with_name("load")).title(title.to_string())
192 .wrap_with(OnEventView::new)
193 .on_event(Event::Refresh, |root: &mut Cursive| {
194 let mut loader = root.find_name::<LoadingAnimation<(T, F)>>("load").unwrap();
195 if loader.is_done() {
196 root.pop_layer();
197 let (val, finish_func) = loader.finish().unwrap();
198 finish_func(root, val);
199 }
200 })
201 );
202}
203
204pub fn fixed_hspacer(width: usize) -> Spacer { ResizedView::with_fixed_width(width, DummyView) }
206
207pub fn filled_hspacer() -> Spacer { ResizedView::with_full_width(DummyView) }
209
210pub fn fixed_vspacer(height: usize) -> Spacer { ResizedView::with_fixed_height(height, DummyView) }
212
213pub fn filled_vspacer() -> Spacer { ResizedView::with_full_height(DummyView) }