slt/context/widgets_interactive/
events.rs1use super::*;
2
3impl Context {
4 pub fn separator(&mut self) -> &mut Self {
9 self.commands.push(Command::Text {
10 content: "─".repeat(200),
11 cursor_offset: None,
12 style: Style::new().fg(self.theme.border).dim(),
13 grow: 0,
14 align: Align::Start,
15 wrap: false,
16 truncate: false,
17 margin: Margin::default(),
18 constraints: Constraints::default(),
19 });
20 self.rollback.last_text_idx = Some(self.commands.len() - 1);
21 self
22 }
23
24 pub fn separator_colored(&mut self, color: Color) -> &mut Self {
26 self.commands.push(Command::Text {
27 content: "─".repeat(200),
28 cursor_offset: None,
29 style: Style::new().fg(color),
30 grow: 0,
31 align: Align::Start,
32 wrap: false,
33 truncate: false,
34 margin: Margin::default(),
35 constraints: Constraints::default(),
36 });
37 self.rollback.last_text_idx = Some(self.commands.len() - 1);
38 self
39 }
40
41 pub fn help(&mut self, bindings: &[(&str, &str)]) -> Response {
47 if bindings.is_empty() {
48 return Response::none();
49 }
50
51 self.skip_interaction_slot();
52 self.commands.push(Command::BeginContainer {
53 direction: Direction::Row,
54 gap: 2,
55 align: Align::Start,
56 align_self: None,
57 justify: Justify::Start,
58 border: None,
59 border_sides: BorderSides::all(),
60 border_style: Style::new().fg(self.theme.border),
61 bg_color: None,
62 padding: Padding::default(),
63 margin: Margin::default(),
64 constraints: Constraints::default(),
65 title: None,
66 grow: 0,
67 group_name: None,
68 });
69 for (idx, (key, action)) in bindings.iter().enumerate() {
70 if idx > 0 {
71 self.styled("·", Style::new().fg(self.theme.text_dim));
72 }
73 self.styled(*key, Style::new().bold().fg(self.theme.primary));
74 self.styled(*action, Style::new().fg(self.theme.text_dim));
75 }
76 self.commands.push(Command::EndContainer);
77 self.rollback.last_text_idx = None;
78
79 Response::none()
80 }
81
82 pub fn help_colored(
84 &mut self,
85 bindings: &[(&str, &str)],
86 key_color: Color,
87 text_color: Color,
88 ) -> Response {
89 if bindings.is_empty() {
90 return Response::none();
91 }
92
93 self.skip_interaction_slot();
94 self.commands.push(Command::BeginContainer {
95 direction: Direction::Row,
96 gap: 2,
97 align: Align::Start,
98 align_self: None,
99 justify: Justify::Start,
100 border: None,
101 border_sides: BorderSides::all(),
102 border_style: Style::new().fg(self.theme.border),
103 bg_color: None,
104 padding: Padding::default(),
105 margin: Margin::default(),
106 constraints: Constraints::default(),
107 title: None,
108 grow: 0,
109 group_name: None,
110 });
111 for (idx, (key, action)) in bindings.iter().enumerate() {
112 if idx > 0 {
113 self.styled("·", Style::new().fg(text_color));
114 }
115 self.styled(*key, Style::new().bold().fg(key_color));
116 self.styled(*action, Style::new().fg(text_color));
117 }
118 self.commands.push(Command::EndContainer);
119 self.rollback.last_text_idx = None;
120
121 Response::none()
122 }
123
124 pub fn key(&self, c: char) -> bool {
130 if (self.rollback.modal_active || self.prev_modal_active)
131 && self.rollback.overlay_depth == 0
132 {
133 return false;
134 }
135 self.events.iter().enumerate().any(|(i, e)| {
136 !self.consumed[i]
137 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c))
138 })
139 }
140
141 pub fn key_code(&self, code: KeyCode) -> bool {
148 if (self.rollback.modal_active || self.prev_modal_active)
149 && self.rollback.overlay_depth == 0
150 {
151 return false;
152 }
153 self.events.iter().enumerate().any(|(i, e)| {
154 !self.consumed[i]
155 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == code)
156 })
157 }
158
159 pub fn raw_key_code(&self, code: KeyCode) -> bool {
167 self.events.iter().enumerate().any(|(i, e)| {
168 !self.consumed[i]
169 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == code)
170 })
171 }
172
173 pub fn key_release(&self, c: char) -> bool {
177 if (self.rollback.modal_active || self.prev_modal_active)
178 && self.rollback.overlay_depth == 0
179 {
180 return false;
181 }
182 self.events.iter().enumerate().any(|(i, e)| {
183 !self.consumed[i]
184 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Release && k.code == KeyCode::Char(c))
185 })
186 }
187
188 pub fn key_code_release(&self, code: KeyCode) -> bool {
192 if (self.rollback.modal_active || self.prev_modal_active)
193 && self.rollback.overlay_depth == 0
194 {
195 return false;
196 }
197 self.events.iter().enumerate().any(|(i, e)| {
198 !self.consumed[i]
199 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Release && k.code == code)
200 })
201 }
202
203 pub fn consume_key(&mut self, c: char) -> bool {
213 if (self.rollback.modal_active || self.prev_modal_active)
214 && self.rollback.overlay_depth == 0
215 {
216 return false;
217 }
218 let index = self.available_key_presses().find_map(|(i, key)| {
219 if key.code == KeyCode::Char(c) {
220 Some(i)
221 } else {
222 None
223 }
224 });
225 if let Some(index) = index {
226 self.consume_indices([index]);
227 true
228 } else {
229 false
230 }
231 }
232
233 pub fn consume_key_code(&mut self, code: KeyCode) -> bool {
243 if (self.rollback.modal_active || self.prev_modal_active)
244 && self.rollback.overlay_depth == 0
245 {
246 return false;
247 }
248 let index =
249 self.available_key_presses().find_map(
250 |(i, key)| {
251 if key.code == code {
252 Some(i)
253 } else {
254 None
255 }
256 },
257 );
258 if let Some(index) = index {
259 self.consume_indices([index]);
260 true
261 } else {
262 false
263 }
264 }
265
266 pub fn key_mod(&self, c: char, modifiers: KeyModifiers) -> bool {
270 if (self.rollback.modal_active || self.prev_modal_active)
271 && self.rollback.overlay_depth == 0
272 {
273 return false;
274 }
275 self.events.iter().enumerate().any(|(i, e)| {
276 !self.consumed[i]
277 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c) && k.modifiers.contains(modifiers))
278 })
279 }
280
281 pub fn raw_key_mod(&self, c: char, modifiers: KeyModifiers) -> bool {
283 self.events.iter().enumerate().any(|(i, e)| {
284 !self.consumed[i]
285 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c) && k.modifiers.contains(modifiers))
286 })
287 }
288
289 pub fn mouse_down(&self) -> Option<(u32, u32)> {
293 if (self.rollback.modal_active || self.prev_modal_active)
294 && self.rollback.overlay_depth == 0
295 {
296 return None;
297 }
298 self.events.iter().enumerate().find_map(|(i, event)| {
299 if self.consumed[i] {
300 return None;
301 }
302 if let Event::Mouse(mouse) = event {
303 if matches!(mouse.kind, MouseKind::Down(MouseButton::Left)) {
304 return Some((mouse.x, mouse.y));
305 }
306 }
307 None
308 })
309 }
310
311 pub fn mouse_pos(&self) -> Option<(u32, u32)> {
316 self.mouse_pos
317 }
318
319 pub fn paste(&self) -> Option<&str> {
321 if (self.rollback.modal_active || self.prev_modal_active)
322 && self.rollback.overlay_depth == 0
323 {
324 return None;
325 }
326 self.events.iter().enumerate().find_map(|(i, event)| {
327 if self.consumed[i] {
328 return None;
329 }
330 if let Event::Paste(ref text) = event {
331 return Some(text.as_str());
332 }
333 None
334 })
335 }
336
337 pub fn scroll_up(&self) -> bool {
339 if (self.rollback.modal_active || self.prev_modal_active)
340 && self.rollback.overlay_depth == 0
341 {
342 return false;
343 }
344 self.events.iter().enumerate().any(|(i, event)| {
345 !self.consumed[i]
346 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollUp))
347 })
348 }
349
350 pub fn scroll_down(&self) -> bool {
352 if (self.rollback.modal_active || self.prev_modal_active)
353 && self.rollback.overlay_depth == 0
354 {
355 return false;
356 }
357 self.events.iter().enumerate().any(|(i, event)| {
358 !self.consumed[i]
359 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollDown))
360 })
361 }
362
363 pub fn scroll_left(&self) -> bool {
365 if (self.rollback.modal_active || self.prev_modal_active)
366 && self.rollback.overlay_depth == 0
367 {
368 return false;
369 }
370 self.events.iter().enumerate().any(|(i, event)| {
371 !self.consumed[i]
372 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollLeft))
373 })
374 }
375
376 pub fn scroll_right(&self) -> bool {
378 if (self.rollback.modal_active || self.prev_modal_active)
379 && self.rollback.overlay_depth == 0
380 {
381 return false;
382 }
383 self.events.iter().enumerate().any(|(i, event)| {
384 !self.consumed[i]
385 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollRight))
386 })
387 }
388
389 pub fn quit(&mut self) {
391 self.should_quit = true;
392 }
393
394 pub fn copy_to_clipboard(&mut self, text: impl Into<String>) {
402 self.clipboard_text = Some(text.into());
403 }
404
405 pub fn theme(&self) -> &Theme {
407 &self.theme
408 }
409
410 pub fn set_theme(&mut self, theme: Theme) {
414 self.theme = theme;
415 }
416
417 pub fn is_dark_mode(&self) -> bool {
419 self.rollback.dark_mode
420 }
421
422 pub fn set_dark_mode(&mut self, dark: bool) {
424 self.rollback.dark_mode = dark;
425 }
426
427 pub fn width(&self) -> u32 {
431 self.area_width
432 }
433
434 pub fn breakpoint(&self) -> Breakpoint {
458 let w = self.area_width;
459 if w < 40 {
460 Breakpoint::Xs
461 } else if w < 80 {
462 Breakpoint::Sm
463 } else if w < 120 {
464 Breakpoint::Md
465 } else if w < 160 {
466 Breakpoint::Lg
467 } else {
468 Breakpoint::Xl
469 }
470 }
471
472 pub fn height(&self) -> u32 {
474 self.area_height
475 }
476
477 pub fn tick(&self) -> u64 {
482 self.tick
483 }
484
485 pub fn debug_enabled(&self) -> bool {
489 self.debug
490 }
491}