1use crate::{Button, EditBox, Filler, Label, adapt::AdaptWidgetAny};
17use kas::event::NamedKey;
18use kas::prelude::*;
19use kas::text::format::FormattableText;
20
21#[derive(Copy, Clone, Debug)]
22struct MessageBoxOk;
23
24#[impl_self]
25mod MessageBox {
26 #[widget]
28 #[layout(column! [self.label, self.button])]
29 pub struct MessageBox<T: FormattableText + 'static> {
30 core: widget_core!(),
31 #[widget]
32 label: Label<T>,
33 #[widget]
34 button: Button<Label<&'static str>>,
35 }
36
37 impl Self {
38 pub fn new(message: T) -> Self {
40 MessageBox {
41 core: Default::default(),
42 label: Label::new(message),
43 button: Button::new_msg(Label::new("Ok"), MessageBoxOk)
44 .with_access_key(NamedKey::Enter.into()),
45 }
46 }
47
48 pub fn into_window<A: 'static>(self, title: impl ToString) -> Window<A> {
50 Window::new(self.map_any(), title).with_restrictions(true, true)
51 }
52 }
53
54 impl Events for Self {
56 type Data = ();
57
58 fn configure(&mut self, cx: &mut ConfigCx) {
59 cx.register_nav_fallback(self.id());
60 }
61
62 fn handle_event(&mut self, cx: &mut EventCx, _: &Self::Data, event: Event) -> IsUsed {
63 match event {
64 Event::Command(Command::Escape, _) | Event::Command(Command::Enter, _) => {
65 cx.window_action(Action::CLOSE);
66 Used
67 }
68 _ => Unused,
69 }
70 }
71
72 fn handle_messages(&mut self, cx: &mut EventCx, _: &Self::Data) {
73 if let Some(MessageBoxOk) = cx.try_pop() {
74 cx.action(self, Action::CLOSE);
75 }
76 }
77 }
78}
79
80#[derive(Debug)]
82pub enum TextEditResult {
83 Cancel,
84 Ok(String),
85}
86
87#[derive(Clone, Debug)]
88struct MsgClose(bool);
89
90#[impl_self]
91mod TextEdit {
92 #[widget]
93 #[layout(grid! {
94 (0..3, 0) => self.edit,
95 (0, 1) => Filler::maximize(),
96 (1, 1) => Button::label_msg("&Cancel", MsgClose(false)),
97 (2, 1) => Button::label_msg("&Save", MsgClose(true)),
98 })]
99 pub struct TextEdit {
105 core: widget_core!(),
106 #[widget]
107 edit: EditBox,
108 }
109
110 impl Self {
111 pub fn new(text: impl ToString, multi_line: bool) -> Self {
113 TextEdit {
114 core: Default::default(),
115 edit: EditBox::text(text).with_multi_line(multi_line),
116 }
117 }
118
119 pub fn set_text(&mut self, cx: &mut EventState, text: impl ToString) {
121 self.edit.set_string(cx, text.to_string());
122 }
123
124 pub fn into_window<A: 'static>(self, title: impl ToString) -> Window<A> {
126 Window::new(self.map_any(), title)
127 }
128
129 fn close(&mut self, cx: &mut EventCx, commit: bool) -> IsUsed {
130 cx.push(if commit {
131 TextEditResult::Ok(self.edit.clone_string())
132 } else {
133 TextEditResult::Cancel
134 });
135 Used
136 }
137 }
138
139 impl Events for Self {
140 type Data = ();
141
142 fn handle_event(&mut self, cx: &mut EventCx, _: &Self::Data, event: Event) -> IsUsed {
153 match event {
154 Event::Command(Command::Escape, _) => self.close(cx, false),
155 Event::Command(Command::Enter, _) => self.close(cx, true),
156 _ => Unused,
157 }
158 }
159
160 fn handle_messages(&mut self, cx: &mut EventCx, _: &Self::Data) {
161 if let Some(MsgClose(commit)) = cx.try_pop() {
162 let _ = self.close(cx, commit);
163 }
164 }
165 }
166}