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