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
53 .push(Command::BeginContainer(Box::new(BeginContainerArgs {
54 direction: Direction::Row,
55 gap: 2,
56 align: Align::Start,
57 align_self: None,
58 justify: Justify::Start,
59 border: None,
60 border_sides: BorderSides::all(),
61 border_style: Style::new().fg(self.theme.border),
62 bg_color: None,
63 padding: Padding::default(),
64 margin: Margin::default(),
65 constraints: Constraints::default(),
66 title: None,
67 grow: 0,
68 group_name: None,
69 })));
70 for (idx, (key, action)) in bindings.iter().enumerate() {
71 if idx > 0 {
72 self.styled("·", Style::new().fg(self.theme.text_dim));
73 }
74 self.styled(*key, Style::new().bold().fg(self.theme.primary));
75 self.styled(*action, Style::new().fg(self.theme.text_dim));
76 }
77 self.commands.push(Command::EndContainer);
78 self.rollback.last_text_idx = None;
79
80 Response::none()
81 }
82
83 pub fn help_colored(
85 &mut self,
86 bindings: &[(&str, &str)],
87 key_color: Color,
88 text_color: Color,
89 ) -> Response {
90 if bindings.is_empty() {
91 return Response::none();
92 }
93
94 self.skip_interaction_slot();
95 self.commands
96 .push(Command::BeginContainer(Box::new(BeginContainerArgs {
97 direction: Direction::Row,
98 gap: 2,
99 align: Align::Start,
100 align_self: None,
101 justify: Justify::Start,
102 border: None,
103 border_sides: BorderSides::all(),
104 border_style: Style::new().fg(self.theme.border),
105 bg_color: None,
106 padding: Padding::default(),
107 margin: Margin::default(),
108 constraints: Constraints::default(),
109 title: None,
110 grow: 0,
111 group_name: None,
112 })));
113 for (idx, (key, action)) in bindings.iter().enumerate() {
114 if idx > 0 {
115 self.styled("·", Style::new().fg(text_color));
116 }
117 self.styled(*key, Style::new().bold().fg(key_color));
118 self.styled(*action, Style::new().fg(text_color));
119 }
120 self.commands.push(Command::EndContainer);
121 self.rollback.last_text_idx = None;
122
123 Response::none()
124 }
125
126 pub fn key(&self, c: char) -> bool {
132 if (self.rollback.modal_active || self.prev_modal_active)
133 && self.rollback.overlay_depth == 0
134 {
135 return false;
136 }
137 self.events.iter().enumerate().any(|(i, e)| {
138 !self.consumed[i]
139 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c))
140 })
141 }
142
143 pub fn key_code(&self, code: KeyCode) -> bool {
150 if (self.rollback.modal_active || self.prev_modal_active)
151 && self.rollback.overlay_depth == 0
152 {
153 return false;
154 }
155 self.events.iter().enumerate().any(|(i, e)| {
156 !self.consumed[i]
157 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == code)
158 })
159 }
160
161 pub fn raw_key_code(&self, code: KeyCode) -> bool {
169 self.events.iter().enumerate().any(|(i, e)| {
170 !self.consumed[i]
171 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == code)
172 })
173 }
174
175 pub fn key_release(&self, c: char) -> bool {
179 if (self.rollback.modal_active || self.prev_modal_active)
180 && self.rollback.overlay_depth == 0
181 {
182 return false;
183 }
184 self.events.iter().enumerate().any(|(i, e)| {
185 !self.consumed[i]
186 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Release && k.code == KeyCode::Char(c))
187 })
188 }
189
190 pub fn key_code_release(&self, code: KeyCode) -> bool {
194 if (self.rollback.modal_active || self.prev_modal_active)
195 && self.rollback.overlay_depth == 0
196 {
197 return false;
198 }
199 self.events.iter().enumerate().any(|(i, e)| {
200 !self.consumed[i]
201 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Release && k.code == code)
202 })
203 }
204
205 pub fn consume_key(&mut self, c: char) -> bool {
215 if (self.rollback.modal_active || self.prev_modal_active)
216 && self.rollback.overlay_depth == 0
217 {
218 return false;
219 }
220 let index = self.available_key_presses().find_map(|(i, key)| {
221 if key.code == KeyCode::Char(c) {
222 Some(i)
223 } else {
224 None
225 }
226 });
227 if let Some(index) = index {
228 self.consume_indices([index]);
229 true
230 } else {
231 false
232 }
233 }
234
235 pub fn consume_key_code(&mut self, code: KeyCode) -> bool {
245 if (self.rollback.modal_active || self.prev_modal_active)
246 && self.rollback.overlay_depth == 0
247 {
248 return false;
249 }
250 let index =
251 self.available_key_presses().find_map(
252 |(i, key)| {
253 if key.code == code {
254 Some(i)
255 } else {
256 None
257 }
258 },
259 );
260 if let Some(index) = index {
261 self.consume_indices([index]);
262 true
263 } else {
264 false
265 }
266 }
267
268 pub fn key_mod(&self, c: char, modifiers: KeyModifiers) -> bool {
272 if (self.rollback.modal_active || self.prev_modal_active)
273 && self.rollback.overlay_depth == 0
274 {
275 return false;
276 }
277 self.events.iter().enumerate().any(|(i, e)| {
278 !self.consumed[i]
279 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c) && k.modifiers.contains(modifiers))
280 })
281 }
282
283 pub fn raw_key_mod(&self, c: char, modifiers: KeyModifiers) -> bool {
285 self.events.iter().enumerate().any(|(i, e)| {
286 !self.consumed[i]
287 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c) && k.modifiers.contains(modifiers))
288 })
289 }
290
291 pub fn mouse_down(&self) -> Option<(u32, u32)> {
295 if (self.rollback.modal_active || self.prev_modal_active)
296 && self.rollback.overlay_depth == 0
297 {
298 return None;
299 }
300 self.events.iter().enumerate().find_map(|(i, event)| {
301 if self.consumed[i] {
302 return None;
303 }
304 if let Event::Mouse(mouse) = event {
305 if matches!(mouse.kind, MouseKind::Down(MouseButton::Left)) {
306 return Some((mouse.x, mouse.y));
307 }
308 }
309 None
310 })
311 }
312
313 pub fn mouse_drag(&self) -> Option<(u32, u32)> {
318 if (self.rollback.modal_active || self.prev_modal_active)
319 && self.rollback.overlay_depth == 0
320 {
321 return None;
322 }
323 self.events.iter().enumerate().find_map(|(i, event)| {
324 if self.consumed[i] {
325 return None;
326 }
327 if let Event::Mouse(mouse) = event {
328 if matches!(mouse.kind, MouseKind::Drag(MouseButton::Left)) {
329 return Some((mouse.x, mouse.y));
330 }
331 }
332 None
333 })
334 }
335
336 pub fn mouse_up(&self) -> Option<(u32, u32)> {
340 if (self.rollback.modal_active || self.prev_modal_active)
341 && self.rollback.overlay_depth == 0
342 {
343 return None;
344 }
345 self.events.iter().enumerate().find_map(|(i, event)| {
346 if self.consumed[i] {
347 return None;
348 }
349 if let Event::Mouse(mouse) = event {
350 if matches!(mouse.kind, MouseKind::Up(MouseButton::Left)) {
351 return Some((mouse.x, mouse.y));
352 }
353 }
354 None
355 })
356 }
357
358 pub fn mouse_down_button(&self, button: MouseButton) -> Option<(u32, u32)> {
363 if (self.rollback.modal_active || self.prev_modal_active)
364 && self.rollback.overlay_depth == 0
365 {
366 return None;
367 }
368 self.events.iter().enumerate().find_map(|(i, event)| {
369 if self.consumed[i] {
370 return None;
371 }
372 if let Event::Mouse(mouse) = event {
373 if matches!(&mouse.kind, MouseKind::Down(b) if *b == button) {
374 return Some((mouse.x, mouse.y));
375 }
376 }
377 None
378 })
379 }
380
381 pub fn mouse_drag_button(&self, button: MouseButton) -> Option<(u32, u32)> {
383 if (self.rollback.modal_active || self.prev_modal_active)
384 && self.rollback.overlay_depth == 0
385 {
386 return None;
387 }
388 self.events.iter().enumerate().find_map(|(i, event)| {
389 if self.consumed[i] {
390 return None;
391 }
392 if let Event::Mouse(mouse) = event {
393 if matches!(&mouse.kind, MouseKind::Drag(b) if *b == button) {
394 return Some((mouse.x, mouse.y));
395 }
396 }
397 None
398 })
399 }
400
401 pub fn mouse_up_button(&self, button: MouseButton) -> Option<(u32, u32)> {
403 if (self.rollback.modal_active || self.prev_modal_active)
404 && self.rollback.overlay_depth == 0
405 {
406 return None;
407 }
408 self.events.iter().enumerate().find_map(|(i, event)| {
409 if self.consumed[i] {
410 return None;
411 }
412 if let Event::Mouse(mouse) = event {
413 if matches!(&mouse.kind, MouseKind::Up(b) if *b == button) {
414 return Some((mouse.x, mouse.y));
415 }
416 }
417 None
418 })
419 }
420
421 pub fn mouse_pos(&self) -> Option<(u32, u32)> {
426 self.mouse_pos
427 }
428
429 pub fn paste(&self) -> Option<&str> {
431 if (self.rollback.modal_active || self.prev_modal_active)
432 && self.rollback.overlay_depth == 0
433 {
434 return None;
435 }
436 self.events.iter().enumerate().find_map(|(i, event)| {
437 if self.consumed[i] {
438 return None;
439 }
440 if let Event::Paste(ref text) = event {
441 return Some(text.as_str());
442 }
443 None
444 })
445 }
446
447 pub fn scroll_up(&self) -> bool {
449 if (self.rollback.modal_active || self.prev_modal_active)
450 && self.rollback.overlay_depth == 0
451 {
452 return false;
453 }
454 self.events.iter().enumerate().any(|(i, event)| {
455 !self.consumed[i]
456 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollUp))
457 })
458 }
459
460 pub fn scroll_down(&self) -> bool {
462 if (self.rollback.modal_active || self.prev_modal_active)
463 && self.rollback.overlay_depth == 0
464 {
465 return false;
466 }
467 self.events.iter().enumerate().any(|(i, event)| {
468 !self.consumed[i]
469 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollDown))
470 })
471 }
472
473 pub fn scroll_left(&self) -> bool {
475 if (self.rollback.modal_active || self.prev_modal_active)
476 && self.rollback.overlay_depth == 0
477 {
478 return false;
479 }
480 self.events.iter().enumerate().any(|(i, event)| {
481 !self.consumed[i]
482 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollLeft))
483 })
484 }
485
486 pub fn scroll_right(&self) -> bool {
488 if (self.rollback.modal_active || self.prev_modal_active)
489 && self.rollback.overlay_depth == 0
490 {
491 return false;
492 }
493 self.events.iter().enumerate().any(|(i, event)| {
494 !self.consumed[i]
495 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollRight))
496 })
497 }
498
499 pub fn events(&self) -> impl Iterator<Item = &Event> {
519 let blocked = (self.rollback.modal_active || self.prev_modal_active)
520 && self.rollback.overlay_depth == 0;
521 self.events.iter().enumerate().filter_map(move |(i, e)| {
522 if blocked || self.consumed[i] {
523 None
524 } else {
525 Some(e)
526 }
527 })
528 }
529
530 pub fn raw_events(&self) -> impl Iterator<Item = &Event> + '_ {
535 self.events
536 .iter()
537 .enumerate()
538 .filter_map(|(i, e)| if self.consumed[i] { None } else { Some(e) })
539 }
540
541 pub fn quit(&mut self) {
543 self.should_quit = true;
544 }
545
546 pub fn copy_to_clipboard(&mut self, text: impl Into<String>) {
554 self.clipboard_text = Some(text.into());
555 }
556
557 pub fn theme(&self) -> &Theme {
559 &self.theme
560 }
561
562 pub fn color(&self, token: ThemeColor) -> Color {
564 self.theme.resolve(token)
565 }
566
567 pub fn spacing(&self) -> Spacing {
569 self.theme.spacing
570 }
571
572 pub fn set_theme(&mut self, theme: Theme) {
576 self.theme = theme;
577 }
578
579 pub fn is_dark_mode(&self) -> bool {
581 self.rollback.dark_mode
582 }
583
584 pub fn set_dark_mode(&mut self, dark: bool) {
586 self.rollback.dark_mode = dark;
587 }
588
589 pub fn width(&self) -> u32 {
593 self.area_width
594 }
595
596 pub fn breakpoint(&self) -> Breakpoint {
620 let w = self.area_width;
621 if w < 40 {
622 Breakpoint::Xs
623 } else if w < 80 {
624 Breakpoint::Sm
625 } else if w < 120 {
626 Breakpoint::Md
627 } else if w < 160 {
628 Breakpoint::Lg
629 } else {
630 Breakpoint::Xl
631 }
632 }
633
634 pub fn height(&self) -> u32 {
636 self.area_height
637 }
638
639 pub fn tick(&self) -> u64 {
644 self.tick
645 }
646
647 pub fn debug_enabled(&self) -> bool {
651 self.debug
652 }
653}