Skip to main content

embedded_gui/context/
types.rs

1use crate::{
2    geometry::{DirtyError, DirtyTracker, Rect},
3    haptics::HapticSequencer,
4    input::{UiEvent, UiEventFilter, WidgetDispatchPolicy},
5    render::RenderQuality,
6    style::{Theme, VisualState, WidgetStyle},
7    widget::{FocusGroupId, MenuContract, StyleClassId, WidgetId},
8    widgets::{TEXTAREA_CAPACITY, WidgetNode},
9};
10use heapless::Vec;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum GuiError {
14    WidgetsFull,
15    EventsFull,
16    DirtyFull,
17    NotFound,
18}
19
20impl From<DirtyError> for GuiError {
21    fn from(_: DirtyError) -> Self {
22        Self::DirtyFull
23    }
24}
25
26#[derive(Clone, Copy, Debug, PartialEq)]
27pub(crate) struct PressTracker {
28    pub(crate) id: WidgetId,
29    pub(crate) start_x: i32,
30    pub(crate) start_y: i32,
31    pub(crate) last_x: i32,
32    pub(crate) last_y: i32,
33    pub(crate) elapsed_ms: u32,
34    pub(crate) long_emitted: bool,
35    pub(crate) gesture_emitted: bool,
36    pub(crate) repeat_elapsed_ms: u32,
37    pub(crate) scroll_velocity: f32,
38}
39
40#[derive(Clone, Copy, Debug, PartialEq)]
41pub(crate) struct InertiaScroll {
42    pub(crate) id: WidgetId,
43    pub(crate) velocity: f32,
44}
45
46#[derive(Clone, Copy, Debug, PartialEq)]
47pub struct ScrollPhysics {
48    pub velocity_threshold: f32,
49    pub velocity_decay: f32,
50    pub drag_velocity_blend: f32,
51}
52
53impl Default for ScrollPhysics {
54    fn default() -> Self {
55        Self {
56            velocity_threshold: 0.05,
57            velocity_decay: 0.86,
58            drag_velocity_blend: 0.4,
59        }
60    }
61}
62
63#[derive(Clone, Copy, Debug, PartialEq, Eq)]
64pub struct PressTiming {
65    pub long_press_ms: u32,
66    pub repeat_delay_ms: u32,
67    pub repeat_interval_ms: u32,
68}
69
70impl PressTiming {
71    pub const fn new(long_press_ms: u32, repeat_delay_ms: u32, repeat_interval_ms: u32) -> Self {
72        Self {
73            long_press_ms,
74            repeat_delay_ms,
75            repeat_interval_ms,
76        }
77    }
78}
79
80#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
81pub struct WidgetKeyInputPolicy {
82    pub raw_select: bool,
83    pub raw_back: bool,
84}
85
86#[derive(Clone, Copy, Debug, PartialEq, Eq)]
87pub enum KeyBindingAction {
88    Default,
89    Ignore,
90    Activate,
91    Back,
92}
93
94#[derive(Clone, Copy, Debug, PartialEq, Eq)]
95pub struct WidgetKeyBindings {
96    pub select: KeyBindingAction,
97    pub back: KeyBindingAction,
98}
99
100impl Default for WidgetKeyBindings {
101    fn default() -> Self {
102        Self {
103            select: KeyBindingAction::Default,
104            back: KeyBindingAction::Default,
105        }
106    }
107}
108
109#[derive(Clone, Copy, Debug, PartialEq, Eq)]
110pub(crate) struct TextareaSnapshot {
111    pub(crate) text_buf: [u8; TEXTAREA_CAPACITY],
112    pub(crate) text_len: u8,
113    pub(crate) cursor: usize,
114    pub(crate) selection: Option<(usize, usize)>,
115}
116
117#[derive(Clone, Copy, Debug, PartialEq, Eq)]
118pub(crate) struct TextareaHistoryEntry {
119    pub(crate) id: WidgetId,
120    pub(crate) snapshot: TextareaSnapshot,
121}
122
123#[derive(Clone, Copy, Debug, PartialEq, Eq)]
124pub(crate) struct StateTransition {
125    pub(crate) id: WidgetId,
126    pub(crate) from: VisualState,
127    pub(crate) to: VisualState,
128    pub(crate) elapsed_ms: u32,
129}
130
131pub struct GuiContext<'a, const NODES: usize, const EVENTS: usize, const DIRTY: usize> {
132    pub(crate) viewport: Rect,
133    pub(crate) widgets: Vec<WidgetNode<'a>, NODES>,
134    pub(crate) subscriptions: Vec<(WidgetId, UiEventFilter), NODES>,
135    pub(crate) dispatch_policies: Vec<(WidgetId, WidgetDispatchPolicy), NODES>,
136    pub(crate) class_styles: Vec<(StyleClassId, WidgetStyle), NODES>,
137    pub(crate) events: Vec<UiEvent, EVENTS>,
138    pub(crate) dirty: DirtyTracker<DIRTY>,
139    pub(crate) theme: Theme,
140    pub(crate) focus: Option<WidgetId>,
141    pub(crate) active_focus_group: Option<FocusGroupId>,
142    pub(crate) render_quality: RenderQuality,
143    pub(crate) long_press_ms: u32,
144    pub(crate) textarea_cursor_blink_ms: u32,
145    pub(crate) textarea_cursor_blink_elapsed_ms: u32,
146    pub(crate) press_repeat_delay_ms: u32,
147    pub(crate) press_repeat_interval_ms: u32,
148    pub(crate) select_double_window_ms: u32,
149    pub(crate) select_elapsed_ms: u32,
150    pub(crate) last_select_id: Option<WidgetId>,
151    pub(crate) pointer_double_window_ms: u32,
152    pub(crate) pointer_elapsed_ms: u32,
153    pub(crate) last_pointer_id: Option<WidgetId>,
154    pub(crate) pressed: Option<PressTracker>,
155    pub(crate) inertia_scroll: Option<InertiaScroll>,
156    pub(crate) scroll_physics: ScrollPhysics,
157    pub(crate) state_transition_ms: u32,
158    pub(crate) state_transitions: Vec<StateTransition, NODES>,
159    pub(crate) widget_press_timings: Vec<(WidgetId, PressTiming), NODES>,
160    pub(crate) widget_key_policies: Vec<(WidgetId, WidgetKeyInputPolicy), NODES>,
161    pub(crate) widget_key_bindings: Vec<(WidgetId, WidgetKeyBindings), NODES>,
162    pub(crate) menu_contract: MenuContract,
163    pub(crate) textarea_undo: Vec<TextareaHistoryEntry, NODES>,
164    pub(crate) textarea_redo: Vec<TextareaHistoryEntry, NODES>,
165    pub(crate) theme_transition_from: Option<Theme>,
166    pub(crate) theme_transition_to: Option<Theme>,
167    pub(crate) theme_transition_duration_ms: u32,
168    pub(crate) theme_transition_elapsed_ms: u32,
169    pub(crate) haptic_sequencer: HapticSequencer,
170    pub(crate) next_id: u16,
171}