Skip to main content

embedded_gui/context/
types.rs

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