1#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
2pub enum Role {
3 #[default]
4 Generic,
5 Window,
6 Group,
7 Navigation,
8 Text,
9 Heading,
10 Image,
11 Link,
12 Button,
13 CheckBox,
14 RadioButton,
15 Switch,
16 TextInput,
17 TextArea,
18 SearchInput,
19 Table,
20 Grid,
21 Row,
22 ColumnHeader,
23 Cell,
24 List,
25 ListItem,
26 Tree,
27 TreeItem,
28 ListBox,
29 Option,
30 Menu,
31 MenuItem,
32 MenuBar,
33 MenuItemCheckBox,
34 MenuItemRadio,
35 ComboBox,
36 Tooltip,
37 Status,
38 AlertDialog,
39 Slider,
40 Progress,
41 Tab,
42 TabList,
43 TabPanel,
44 Dialog,
45 Alert,
46 Separator,
47}
48
49#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
50pub enum SemanticAction {
51 Click,
52 Focus,
53 Blur,
54 Increment,
55 Decrement,
56 Expand,
57 Collapse,
58 SetValue,
59 ScrollIntoView,
60}
61
62#[derive(Clone, Debug, PartialEq)]
63pub enum SemanticValue {
64 Text(String),
65 Number {
66 value: f64,
67 minimum: Option<f64>,
68 maximum: Option<f64>,
69 step: Option<f64>,
70 },
71}
72
73#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
74pub enum LiveRegion {
75 #[default]
76 Off,
77 Polite,
78 Assertive,
79}
80
81#[derive(Clone, Copy, Debug, Eq, PartialEq)]
82pub enum Orientation {
83 Horizontal,
84 Vertical,
85}
86
87#[derive(Clone, Debug, Default, Eq, PartialEq)]
88pub struct SemanticState {
89 pub protected: bool,
90 pub disabled: bool,
91 pub selected: bool,
92 pub multiselectable: bool,
93 pub checked: Option<CheckedState>,
94 pub pressed: Option<bool>,
96 pub expanded: Option<bool>,
97 pub required: bool,
98 pub read_only: bool,
99 pub invalid: bool,
100 pub modal: bool,
101 pub busy: bool,
102}
103
104#[derive(Clone, Debug, Default, PartialEq)]
105pub struct Semantics {
106 pub role: Role,
107 pub label: Option<String>,
108 pub description: Option<String>,
109 pub value: Option<SemanticValue>,
110 pub state: SemanticState,
111 pub actions: Vec<SemanticAction>,
112 pub live: LiveRegion,
113 pub orientation: Option<Orientation>,
114 pub level: Option<u32>,
115 pub position_in_set: Option<u32>,
116 pub set_size: Option<u32>,
117 pub relations: crate::SemanticRelations,
118 pub grid: crate::GridPosition,
119 pub sort: Option<crate::SortDirection>,
120 pub popup: Option<crate::PopupKind>,
121 pub focus_policy: FocusPolicy,
122}
123
124#[derive(Clone, Debug, PartialEq)]
125pub struct SemanticRequest {
126 pub target: crate::SemanticNodeId,
127 pub action: SemanticAction,
128 pub value: Option<SemanticValue>,
129}
130
131impl Semantics {
132 #[must_use]
133 pub const fn new(role: Role) -> Self {
134 Self {
135 role,
136 label: None,
137 description: None,
138 value: None,
139 state: SemanticState {
140 protected: false,
141 disabled: false,
142 selected: false,
143 multiselectable: false,
144 checked: None,
145 pressed: None,
146 expanded: None,
147 required: false,
148 read_only: false,
149 invalid: false,
150 modal: false,
151 busy: false,
152 },
153 actions: Vec::new(),
154 live: LiveRegion::Off,
155 orientation: None,
156 level: None,
157 position_in_set: None,
158 set_size: None,
159 relations: crate::SemanticRelations::new(),
160 grid: crate::GridPosition {
161 row_count: None,
162 column_count: None,
163 row_index: None,
164 column_index: None,
165 },
166 sort: None,
167 popup: None,
168 focus_policy: FocusPolicy::None,
169 }
170 }
171
172 #[must_use]
173 pub fn label(mut self, label: impl Into<String>) -> Self {
174 self.label = Some(label.into());
175 self
176 }
177
178 #[must_use]
179 pub fn description(mut self, description: impl Into<String>) -> Self {
180 self.description = Some(description.into());
181 self
182 }
183
184 #[must_use]
185 pub fn value(mut self, value: SemanticValue) -> Self {
186 self.value = Some(value);
187 self
188 }
189
190 #[must_use]
191 pub fn action(mut self, action: SemanticAction) -> Self {
192 if !self.actions.contains(&action) {
193 self.actions.push(action);
194 }
195 self
196 }
197
198 #[must_use]
199 pub fn state(mut self, state: SemanticState) -> Self {
200 self.state = state;
201 self
202 }
203
204 #[must_use]
205 pub const fn live(mut self, live: LiveRegion) -> Self {
206 self.live = live;
207 self
208 }
209
210 #[must_use]
211 pub const fn orientation(mut self, orientation: Orientation) -> Self {
212 self.orientation = Some(orientation);
213 self
214 }
215
216 #[must_use]
217 pub const fn level(mut self, level: u32) -> Self {
218 self.level = Some(level);
219 self
220 }
221
222 #[must_use]
223 pub const fn position_in_set(mut self, position: u32, size: u32) -> Self {
224 self.position_in_set = Some(position);
225 self.set_size = Some(size);
226 self
227 }
228}
229
230#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
232pub enum CheckedState {
233 #[default]
234 Unchecked,
235 Checked,
236 Mixed,
237}
238
239impl CheckedState {
240 #[must_use]
241 pub const fn toggled(self) -> Self {
242 match self {
243 Self::Checked => Self::Unchecked,
244 Self::Unchecked | Self::Mixed => Self::Checked,
245 }
246 }
247}
248
249#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
251pub enum FocusPolicy {
252 #[default]
253 None,
254 Programmatic,
255 TabStop,
256}
257
258impl FocusPolicy {
259 #[must_use]
260 pub const fn is_focusable(self) -> bool {
261 !matches!(self, Self::None)
262 }
263
264 #[must_use]
265 pub const fn is_tab_stop(self) -> bool {
266 matches!(self, Self::TabStop)
267 }
268}