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.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.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.interaction_count += 1;
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.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.interaction_count += 1;
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.last_text_idx = None;
120
121 Response::none()
122 }
123
124 pub fn key(&self, c: char) -> bool {
130 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
131 return false;
132 }
133 self.events.iter().enumerate().any(|(i, e)| {
134 !self.consumed[i]
135 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c))
136 })
137 }
138
139 pub fn key_code(&self, code: KeyCode) -> bool {
146 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
147 return false;
148 }
149 self.events.iter().enumerate().any(|(i, e)| {
150 !self.consumed[i]
151 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == code)
152 })
153 }
154
155 pub fn raw_key_code(&self, code: KeyCode) -> bool {
163 self.events.iter().enumerate().any(|(i, e)| {
164 !self.consumed[i]
165 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == code)
166 })
167 }
168
169 pub fn key_release(&self, c: char) -> bool {
173 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
174 return false;
175 }
176 self.events.iter().enumerate().any(|(i, e)| {
177 !self.consumed[i]
178 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Release && k.code == KeyCode::Char(c))
179 })
180 }
181
182 pub fn key_code_release(&self, code: KeyCode) -> bool {
186 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
187 return false;
188 }
189 self.events.iter().enumerate().any(|(i, e)| {
190 !self.consumed[i]
191 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Release && k.code == code)
192 })
193 }
194
195 pub fn consume_key(&mut self, c: char) -> bool {
205 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
206 return false;
207 }
208 for (i, event) in self.events.iter().enumerate() {
209 if self.consumed[i] {
210 continue;
211 }
212 if matches!(event, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c))
213 {
214 self.consumed[i] = true;
215 return true;
216 }
217 }
218 false
219 }
220
221 pub fn consume_key_code(&mut self, code: KeyCode) -> bool {
231 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
232 return false;
233 }
234 for (i, event) in self.events.iter().enumerate() {
235 if self.consumed[i] {
236 continue;
237 }
238 if matches!(event, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == code) {
239 self.consumed[i] = true;
240 return true;
241 }
242 }
243 false
244 }
245
246 pub fn key_mod(&self, c: char, modifiers: KeyModifiers) -> bool {
250 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
251 return false;
252 }
253 self.events.iter().enumerate().any(|(i, e)| {
254 !self.consumed[i]
255 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c) && k.modifiers.contains(modifiers))
256 })
257 }
258
259 pub fn raw_key_mod(&self, c: char, modifiers: KeyModifiers) -> bool {
261 self.events.iter().enumerate().any(|(i, e)| {
262 !self.consumed[i]
263 && matches!(e, Event::Key(k) if k.kind == KeyEventKind::Press && k.code == KeyCode::Char(c) && k.modifiers.contains(modifiers))
264 })
265 }
266
267 pub fn mouse_down(&self) -> Option<(u32, u32)> {
271 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
272 return None;
273 }
274 self.events.iter().enumerate().find_map(|(i, event)| {
275 if self.consumed[i] {
276 return None;
277 }
278 if let Event::Mouse(mouse) = event {
279 if matches!(mouse.kind, MouseKind::Down(MouseButton::Left)) {
280 return Some((mouse.x, mouse.y));
281 }
282 }
283 None
284 })
285 }
286
287 pub fn mouse_pos(&self) -> Option<(u32, u32)> {
292 self.mouse_pos
293 }
294
295 pub fn paste(&self) -> Option<&str> {
297 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
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::Paste(ref text) = event {
305 return Some(text.as_str());
306 }
307 None
308 })
309 }
310
311 pub fn scroll_up(&self) -> bool {
313 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
314 return false;
315 }
316 self.events.iter().enumerate().any(|(i, event)| {
317 !self.consumed[i]
318 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollUp))
319 })
320 }
321
322 pub fn scroll_down(&self) -> bool {
324 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
325 return false;
326 }
327 self.events.iter().enumerate().any(|(i, event)| {
328 !self.consumed[i]
329 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollDown))
330 })
331 }
332
333 pub fn scroll_left(&self) -> bool {
335 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
336 return false;
337 }
338 self.events.iter().enumerate().any(|(i, event)| {
339 !self.consumed[i]
340 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollLeft))
341 })
342 }
343
344 pub fn scroll_right(&self) -> bool {
346 if (self.modal_active || self.prev_modal_active) && self.overlay_depth == 0 {
347 return false;
348 }
349 self.events.iter().enumerate().any(|(i, event)| {
350 !self.consumed[i]
351 && matches!(event, Event::Mouse(mouse) if matches!(mouse.kind, MouseKind::ScrollRight))
352 })
353 }
354
355 pub fn quit(&mut self) {
357 self.should_quit = true;
358 }
359
360 pub fn copy_to_clipboard(&mut self, text: impl Into<String>) {
368 self.clipboard_text = Some(text.into());
369 }
370
371 pub fn theme(&self) -> &Theme {
373 &self.theme
374 }
375
376 pub fn set_theme(&mut self, theme: Theme) {
380 self.theme = theme;
381 }
382
383 pub fn is_dark_mode(&self) -> bool {
385 self.dark_mode
386 }
387
388 pub fn set_dark_mode(&mut self, dark: bool) {
390 self.dark_mode = dark;
391 }
392
393 pub fn width(&self) -> u32 {
397 self.area_width
398 }
399
400 pub fn breakpoint(&self) -> Breakpoint {
424 let w = self.area_width;
425 if w < 40 {
426 Breakpoint::Xs
427 } else if w < 80 {
428 Breakpoint::Sm
429 } else if w < 120 {
430 Breakpoint::Md
431 } else if w < 160 {
432 Breakpoint::Lg
433 } else {
434 Breakpoint::Xl
435 }
436 }
437
438 pub fn height(&self) -> u32 {
440 self.area_height
441 }
442
443 pub fn tick(&self) -> u64 {
448 self.tick
449 }
450
451 pub fn debug_enabled(&self) -> bool {
455 self.debug
456 }
457}