Skip to main content

slt/context/
core.rs

1use super::*;
2
3/// The main rendering context passed to your closure each frame.
4///
5/// Provides all methods for building UI: text, containers, widgets, and event
6/// handling. You receive a `&mut Context` on every frame and describe what to
7/// render by calling its methods. SLT collects those calls, lays them out with
8/// flexbox, diffs against the previous frame, and flushes only changed cells.
9///
10/// # Example
11///
12/// ```no_run
13/// slt::run(|ui: &mut slt::Context| {
14///     if ui.key('q') { ui.quit(); }
15///     ui.text("Hello, world!").bold();
16/// });
17/// ```
18pub struct Context {
19    pub(crate) commands: Vec<Command>,
20    pub(crate) events: Vec<Event>,
21    pub(crate) consumed: Vec<bool>,
22    pub(crate) should_quit: bool,
23    pub(crate) area_width: u32,
24    pub(crate) area_height: u32,
25    pub(crate) tick: u64,
26    pub(crate) focus_index: usize,
27    pub(crate) hook_states: Vec<Box<dyn std::any::Any>>,
28    pub(crate) prev_focus_count: usize,
29    pub(crate) prev_modal_focus_start: usize,
30    pub(crate) prev_modal_focus_count: usize,
31    pub(crate) prev_scroll_infos: Vec<(u32, u32)>,
32    pub(crate) prev_scroll_rects: Vec<Rect>,
33    pub(crate) prev_hit_map: Vec<Rect>,
34    pub(crate) prev_group_rects: Vec<(String, Rect)>,
35    pub(crate) prev_focus_groups: Vec<Option<String>>,
36    pub(crate) _prev_focus_rects: Vec<(usize, Rect)>,
37    pub(crate) mouse_pos: Option<(u32, u32)>,
38    pub(crate) click_pos: Option<(u32, u32)>,
39    pub(crate) prev_modal_active: bool,
40    pub(crate) clipboard_text: Option<String>,
41    pub(crate) debug: bool,
42    pub(crate) theme: Theme,
43    pub(crate) is_real_terminal: bool,
44    pub(crate) deferred_draws: Vec<Option<RawDrawCallback>>,
45    pub(crate) rollback: ContextRollbackState,
46    pub(crate) scroll_lines_per_event: u32,
47}
48
49type RawDrawCallback = Box<dyn FnOnce(&mut crate::buffer::Buffer, Rect)>;
50
51#[derive(Debug, Clone)]
52pub(crate) struct PendingTooltip {
53    pub anchor_rect: Rect,
54    pub lines: Vec<String>,
55}
56
57#[derive(Clone)]
58pub(crate) struct ContextRollbackState {
59    pub(crate) last_text_idx: Option<usize>,
60    pub(crate) focus_count: usize,
61    pub(crate) interaction_count: usize,
62    pub(crate) scroll_count: usize,
63    pub(crate) group_count: usize,
64    pub(crate) group_stack: Vec<String>,
65    pub(crate) overlay_depth: usize,
66    pub(crate) modal_active: bool,
67    pub(crate) modal_focus_start: usize,
68    pub(crate) modal_focus_count: usize,
69    pub(crate) hook_cursor: usize,
70    pub(crate) dark_mode: bool,
71    pub(crate) notification_queue: Vec<(String, ToastLevel, u64)>,
72    pub(crate) pending_tooltips: Vec<PendingTooltip>,
73    pub(crate) text_color_stack: Vec<Option<Color>>,
74}
75
76pub(super) struct ContextCheckpoint {
77    commands_len: usize,
78    hook_states_len: usize,
79    deferred_draws_len: usize,
80    rollback: ContextRollbackState,
81}
82
83impl ContextCheckpoint {
84    pub(super) fn capture(ctx: &Context) -> Self {
85        Self {
86            commands_len: ctx.commands.len(),
87            hook_states_len: ctx.hook_states.len(),
88            deferred_draws_len: ctx.deferred_draws.len(),
89            rollback: ctx.rollback.clone(),
90        }
91    }
92
93    pub(super) fn restore(&self, ctx: &mut Context) {
94        ctx.commands.truncate(self.commands_len);
95        ctx.hook_states.truncate(self.hook_states_len);
96        ctx.deferred_draws.truncate(self.deferred_draws_len);
97        ctx.rollback = self.rollback.clone();
98    }
99}