1
//! Accessibility types for screen reader support.
2
//!
3
//! Key types:
4
//! - [`AccessibilityInfo`] — full accessibility metadata for a UI element
5
//! - [`SmallAriaInfo`] — lightweight alternative for common cases (label + role + description)
6
//! - [`AccessibilityRole`] — element purpose (button, link, checkbox, etc.)
7
//! - [`AccessibilityState`] — dynamic state (focused, checked, expanded, etc.)
8
//! - [`AccessibilityAction`] — actions performable on an element (click, scroll, etc.)
9
//!
10
//! These types are consumed by `layout/src/managers/a11y.rs` and mapped to
11
//! platform accessibility backends in `dll/src/desktop/shell2/`.
12

            
13
use alloc::vec::Vec;
14
use azul_css::{
15
    AzString, OptionF32, OptionString,
16
    props::basic::length::FloatValue,
17
};
18
use crate::{
19
    dom::OptionDomNodeId,
20
    geom::LogicalPosition,
21
    window::OptionVirtualKeyCodeCombo,
22
};
23

            
24
/// Holds information about a UI element for accessibility purposes (e.g., screen readers).
25
/// This is a wrapper for platform-specific accessibility APIs like MSAA.
26
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
27
#[repr(C)]
28
pub struct AccessibilityInfo {
29
    /// Get the "name" of the `IAccessible`, for example the
30
    /// name of a button, checkbox or menu item. Try to use unique names
31
    /// for each item in a dialog so that voice dictation software doesn't
32
    /// have to deal with extra ambiguity.
33
    pub accessibility_name: OptionString,
34
    /// Get the "value" of the `IAccessible`, for example a number in a slider,
35
    /// a URL for a link, the text a user entered in a field.
36
    pub accessibility_value: OptionString,
37
    /// Optional text description providing additional context about the element.
38
    /// Maps to `aria-description` / accesskit's `set_description()`.
39
    pub description: OptionString,
40
    /// Optional keyboard accelerator.
41
    pub accelerator: OptionVirtualKeyCodeCombo,
42
    /// Optional "default action" description. Only used when there is at least
43
    /// one `ComponentEventFilter::DefaultAction` callback present on this node.
44
    pub default_action: OptionString,
45
    /// Possible on/off states, such as focused, focusable, selected, selectable,
46
    /// visible, protected (for passwords), checked, etc.
47
    pub states: AccessibilityStateVec,
48
    /// A list of actions the user can perform on this element.
49
    /// Maps to accesskit's Action enum.
50
    pub supported_actions: AccessibilityActionVec,
51
    /// ID of another node that labels this one (for `aria-labelledby`).
52
    pub labelled_by: OptionDomNodeId,
53
    /// ID of another node that describes this one (for `aria-describedby`).
54
    pub described_by: OptionDomNodeId,
55
    /// Get an enumerated value representing what this IAccessible is used for,
56
    /// for example is it a link, static text, editable text, a checkbox, or a table cell, etc.
57
    pub role: AccessibilityRole,
58
    /// For live regions that update automatically (e.g., chat messages, timers).
59
    /// Maps to accesskit's `Live` property.
60
    pub is_live_region: bool,
61
}
62

            
63
/// Actions that can be performed on an accessible element.
64
/// This is a simplified version of accesskit::Action to avoid direct dependency in core.
65
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66
#[repr(C, u8)]
67
pub enum AccessibilityAction {
68
    /// The default action for the element (usually a click).
69
    Default,
70
    /// Set focus to this element.
71
    Focus,
72
    /// Remove focus from this element.
73
    Blur,
74
    /// Collapse an expandable element (e.g., tree node, accordion).
75
    Collapse,
76
    /// Expand a collapsible element (e.g., tree node, accordion).
77
    Expand,
78
    /// Scroll this element into view.
79
    ScrollIntoView,
80
    /// Increment a numeric value (e.g., slider, spinner).
81
    Increment,
82
    /// Decrement a numeric value (e.g., slider, spinner).
83
    Decrement,
84
    /// Show a context menu.
85
    ShowContextMenu,
86
    /// Hide a tooltip.
87
    HideTooltip,
88
    /// Show a tooltip.
89
    ShowTooltip,
90
    /// Scroll up.
91
    ScrollUp,
92
    /// Scroll down.
93
    ScrollDown,
94
    /// Scroll left.
95
    ScrollLeft,
96
    /// Scroll right.
97
    ScrollRight,
98
    /// Replace selected text with new text.
99
    ReplaceSelectedText(AzString),
100
    /// Scroll to a specific point.
101
    ScrollToPoint(LogicalPosition),
102
    /// Set scroll offset.
103
    SetScrollOffset(LogicalPosition),
104
    /// Set text selection.
105
    SetTextSelection(TextSelectionStartEnd),
106
    /// Set sequential focus navigation starting point.
107
    SetSequentialFocusNavigationStartingPoint,
108
    /// Set the value of a control.
109
    SetValue(AzString),
110
    /// Set numeric value of a control.
111
    SetNumericValue(FloatValue),
112
    /// Custom action with ID.
113
    CustomAction(i32),
114
}
115

            
116
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
117
#[repr(C)]
118
pub struct TextSelectionStartEnd {
119
    pub selection_start: usize,
120
    pub selection_end: usize,
121
}
122

            
123
impl_vec!(AccessibilityAction, AccessibilityActionVec, AccessibilityActionVecDestructor, AccessibilityActionVecDestructorType, AccessibilityActionVecSlice, OptionAccessibilityAction);
124
impl_vec_debug!(AccessibilityAction, AccessibilityActionVec);
125
impl_vec_clone!(
126
    AccessibilityAction,
127
    AccessibilityActionVec,
128
    AccessibilityActionVecDestructor
129
);
130
impl_vec_partialeq!(AccessibilityAction, AccessibilityActionVec);
131
impl_vec_eq!(AccessibilityAction, AccessibilityActionVec);
132
impl_vec_partialord!(AccessibilityAction, AccessibilityActionVec);
133
impl_vec_ord!(AccessibilityAction, AccessibilityActionVec);
134
impl_vec_hash!(AccessibilityAction, AccessibilityActionVec);
135

            
136
impl_option![
137
    AccessibilityAction,
138
    OptionAccessibilityAction,
139
    copy = false,
140
    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
141
];
142

            
143
impl_option!(
144
    AccessibilityInfo,
145
    OptionAccessibilityInfo,
146
    copy = false,
147
    [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
148
);
149

            
150
/// Defines the element's purpose for accessibility APIs, informing assistive technologies
151
/// like screen readers about the function of a UI element. Each variant corresponds to a
152
/// standard control type or UI structure.
153
///
154
/// For more details, see the [MSDN Role Constants page](https://docs.microsoft.com/en-us/windows/winauto/object-roles).
155
#[repr(C)]
156
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
157
pub enum AccessibilityRole {
158
    /// Represents the title or caption bar of a window.
159
    /// - **Purpose**: To identify the title bar containing the window title and system commands.
160
    /// - **When to use**: This role is typically inserted by the operating system for standard
161
    ///   windows.
162
    /// - **Example**: The bar at the top of an application window displaying its name and the
163
    ///   minimize, maximize, and close buttons.
164
    TitleBar,
165

            
166
    /// Represents a menu bar at the top of a window.
167
    /// - **Purpose**: To contain a set of top-level menus for an application.
168
    /// - **When to use**: For the main menu bar of an application, such as one containing "File,"
169
    ///   "Edit," and "View."
170
    /// - **Example**: The "File", "Edit", "View" menu bar at the top of a text editor.
171
    MenuBar,
172

            
173
    /// Represents a vertical or horizontal scroll bar.
174
    /// - **Purpose**: To enable scrolling through content that is larger than the visible area.
175
    /// - **When to use**: For any scrollable region of content.
176
    /// - **Example**: The bar on the side of a web page that allows the user to scroll up and
177
    ///   down.
178
    ScrollBar,
179

            
180
    /// Represents a handle or grip used for moving or resizing.
181
    /// - **Purpose**: To provide a user interface element for manipulating another element's size
182
    ///   or position.
183
    /// - **When to use**: For handles that allow resizing of windows, panes, or other objects.
184
    /// - **Example**: The small textured area in the bottom-right corner of a window that can be
185
    ///   dragged to resize it.
186
    Grip,
187

            
188
    /// Represents a system sound indicating an event.
189
    /// - **Purpose**: To associate a sound with a UI event, providing an auditory cue.
190
    /// - **When to use**: When a sound is the primary representation of an event.
191
    /// - **Example**: A system notification sound that plays when a new message arrives.
192
    Sound,
193

            
194
    /// Represents the system's mouse pointer or other pointing device.
195
    /// - **Purpose**: To indicate the screen position of the user's pointing device.
196
    /// - **When to use**: This role is managed by the operating system.
197
    /// - **Example**: The arrow that moves on the screen as you move the mouse.
198
    Cursor,
199

            
200
    /// Represents the text insertion point indicator.
201
    /// - **Purpose**: To show the current text entry or editing position.
202
    /// - **When to use**: This role is typically managed by the operating system for text input
203
    ///   fields.
204
    /// - **Example**: The blinking vertical line in a text box that shows where the next character
205
    ///   will be typed.
206
    Caret,
207

            
208
    /// Represents an alert or notification.
209
    /// - **Purpose**: To convey an important, non-modal message to the user.
210
    /// - **When to use**: For non-intrusive notifications that do not require immediate user
211
    ///   interaction.
212
    /// - **Example**: A small, temporary "toast" notification that appears to confirm an action,
213
    ///   like "Email sent."
214
    Alert,
215

            
216
    /// Represents a window frame.
217
    /// - **Purpose**: To serve as the container for other objects like a title bar and client
218
    ///   area.
219
    /// - **When to use**: This is a fundamental role, typically managed by the windowing system.
220
    /// - **Example**: The main window of any application, which contains all other UI elements.
221
    Window,
222

            
223
    /// Represents a window's client area, where the main content is displayed.
224
    /// - **Purpose**: To define the primary content area of a window.
225
    /// - **When to use**: For the main content region of a window. It's often the default role for
226
    ///   a custom control container.
227
    /// - **Example**: The area of a web browser where the web page content is rendered.
228
    Client,
229

            
230
    /// Represents a pop-up menu.
231
    /// - **Purpose**: To display a list of `MenuItem` objects that appears when a user performs an
232
    ///   action.
233
    /// - **When to use**: For context menus (right-click menus) or drop-down menus.
234
    /// - **Example**: The menu that appears when you right-click on a file in a file explorer.
235
    MenuPopup,
236

            
237
    /// Represents an individual item within a menu.
238
    /// - **Purpose**: To represent a single command, option, or separator within a menu.
239
    /// - **When to use**: For individual options inside a `MenuBar` or `MenuPopup`.
240
    /// - **Example**: The "Save" option within the "File" menu.
241
    MenuItem,
242

            
243
    /// Represents a small pop-up window that provides information.
244
    /// - **Purpose**: To offer brief, contextual help or information about a UI element.
245
    /// - **When to use**: For informational pop-ups that appear on mouse hover.
246
    /// - **Example**: The small box of text that appears when you hover over a button in a
247
    ///   toolbar.
248
    Tooltip,
249

            
250
    /// Represents the main window of an application.
251
    /// - **Purpose**: To identify the top-level window of an application.
252
    /// - **When to use**: For the primary window that represents the application itself.
253
    /// - **Example**: The main window of a calculator or notepad application.
254
    Application,
255

            
256
    /// Represents a document window within an application.
257
    /// - **Purpose**: To represent a contained document, typically in a Multiple Document
258
    ///   Interface (MDI) application.
259
    /// - **When to use**: For individual document windows inside a larger application shell.
260
    /// - **Example**: In a photo editor that allows multiple images to be open in separate
261
    ///   windows, each image window would be a `Document`.
262
    Document,
263

            
264
    /// Represents a pane or a distinct section of a window.
265
    /// - **Purpose**: To divide a window into visually and functionally distinct areas.
266
    /// - **When to use**: For sub-regions of a window, like a navigation pane, preview pane, or
267
    ///   sidebar.
268
    /// - **Example**: The preview pane in an email client that shows the content of the selected
269
    ///   email.
270
    Pane,
271

            
272
    /// Represents a graphical chart or graph.
273
    /// - **Purpose**: To display data visually in a chart format.
274
    /// - **When to use**: For any type of chart, such as a bar chart, line chart, or pie chart.
275
    /// - **Example**: A bar chart displaying monthly sales figures.
276
    Chart,
277

            
278
    /// Represents a dialog box or message box.
279
    /// - **Purpose**: To create a secondary window that requires user interaction before returning
280
    ///   to the main application.
281
    /// - **When to use**: For modal or non-modal windows that prompt the user for information or a
282
    ///   response.
283
    /// - **Example**: The "Open File" or "Print" dialog in most applications.
284
    Dialog,
285

            
286
    /// Represents a window's border.
287
    /// - **Purpose**: To identify the border of a window, which is often used for resizing.
288
    /// - **When to use**: This role is typically managed by the windowing system.
289
    /// - **Example**: The decorative and functional frame around a window.
290
    Border,
291

            
292
    /// Represents a group of related controls.
293
    /// - **Purpose**: To logically group other objects that share a common purpose.
294
    /// - **When to use**: For grouping controls like a set of radio buttons or a fieldset with a
295
    ///   legend.
296
    /// - **Example**: A "Settings" group box in a dialog that contains several related checkboxes.
297
    Grouping,
298

            
299
    /// Represents a visual separator.
300
    /// - **Purpose**: To visually divide a space or a group of controls.
301
    /// - **When to use**: For visual separators in menus, toolbars, or between panes.
302
    /// - **Example**: The horizontal line in a menu that separates groups of related menu items.
303
    Separator,
304

            
305
    /// Represents a toolbar containing a group of controls.
306
    /// - **Purpose**: To group controls, typically buttons, for quick access to frequently used
307
    ///   functions.
308
    /// - **When to use**: For a bar of buttons or other controls, usually at the top of a window
309
    ///   or pane.
310
    /// - **Example**: The toolbar at the top of a word processor with buttons for "Bold,"
311
    ///   "Italic," and "Underline."
312
    Toolbar,
313

            
314
    /// Represents a status bar for displaying information.
315
    /// - **Purpose**: To display status information about the current state of the application.
316
    /// - **When to use**: For a bar, typically at the bottom of a window, that displays messages.
317
    /// - **Example**: The bar at the bottom of a web browser that shows the loading status of a
318
    ///   page.
319
    StatusBar,
320

            
321
    /// Represents a data table.
322
    /// - **Purpose**: To present data in a two-dimensional grid of rows and columns.
323
    /// - **When to use**: For grid-like data presentation.
324
    /// - **Example**: A spreadsheet or a table of data in a database application.
325
    Table,
326

            
327
    /// Represents a column header in a table.
328
    /// - **Purpose**: To provide a label for a column of data.
329
    /// - **When to use**: For the headers of columns in a `Table`.
330
    /// - **Example**: The header row in a spreadsheet with labels like "Name," "Date," and
331
    ///   "Amount."
332
    ColumnHeader,
333

            
334
    /// Represents a row header in a table.
335
    /// - **Purpose**: To provide a label for a row of data.
336
    /// - **When to use**: For the headers of rows in a `Table`.
337
    /// - **Example**: The numbered rows on the left side of a spreadsheet.
338
    RowHeader,
339

            
340
    /// Represents a full column of cells in a table.
341
    /// - **Purpose**: To represent an entire column as a single accessible object.
342
    /// - **When to use**: When it is useful to interact with a column as a whole.
343
    /// - **Example**: The "Amount" column in a financial data table.
344
    Column,
345

            
346
    /// Represents a full row of cells in a table.
347
    /// - **Purpose**: To represent an entire row as a single accessible object.
348
    /// - **When to use**: When it is useful to interact with a row as a whole.
349
    /// - **Example**: A row representing a single customer's information in a customer list.
350
    Row,
351

            
352
    /// Represents a single cell within a table.
353
    /// - **Purpose**: To represent a single data point or control within a `Table`.
354
    /// - **When to use**: For individual cells in a grid or table.
355
    /// - **Example**: A single cell in a spreadsheet containing a specific value.
356
    Cell,
357

            
358
    /// Represents a hyperlink to a resource.
359
    /// - **Purpose**: To provide a navigational link to another document or location.
360
    /// - **When to use**: For text or images that, when clicked, navigate to another resource.
361
    /// - **Example**: A clickable link on a web page.
362
    Link,
363

            
364
    /// Represents a help balloon or pop-up.
365
    /// - **Purpose**: To provide more detailed help information than a standard tooltip.
366
    /// - **When to use**: For a pop-up that offers extended help text, often initiated by a help
367
    ///   button.
368
    /// - **Example**: A pop-up balloon with a paragraph of help text that appears when a user
369
    ///   clicks a help icon.
370
    HelpBalloon,
371

            
372
    /// Represents an animated, character-like graphic object.
373
    /// - **Purpose**: To provide an animated agent for user assistance or entertainment.
374
    /// - **When to use**: For animated characters or avatars that provide help or guidance.
375
    /// - **Example**: An animated paperclip that offers tips in a word processor (e.g.,
376
    ///   Microsoft's Clippy).
377
    Character,
378

            
379
    /// Represents a list of items.
380
    /// - **Purpose**: To contain a set of `ListItem` objects.
381
    /// - **When to use**: For list boxes or similar controls that present a list of selectable
382
    ///   items.
383
    /// - **Example**: The list of files in a file selection dialog.
384
    List,
385

            
386
    /// Represents an individual item within a list.
387
    /// - **Purpose**: To represent a single, selectable item within a `List`.
388
    /// - **When to use**: For each individual item in a list box or combo box.
389
    /// - **Example**: A single file name in a list of files.
390
    ListItem,
391

            
392
    /// Represents an outline or tree structure.
393
    /// - **Purpose**: To display a hierarchical view of data.
394
    /// - **When to use**: For tree-view controls that show nested items.
395
    /// - **Example**: A file explorer's folder tree view.
396
    Outline,
397

            
398
    /// Represents an individual item within an outline or tree.
399
    /// - **Purpose**: To represent a single node (which can be a leaf or a branch) in an
400
    ///   `Outline`.
401
    /// - **When to use**: For each node in a tree view.
402
    /// - **Example**: A single folder in a file explorer's tree view.
403
    OutlineItem,
404

            
405
    /// Represents a single tab in a tabbed interface.
406
    /// - **Purpose**: To provide a control for switching between different `PropertyPage` views.
407
    /// - **When to use**: For the individual tabs that the user can click to switch pages.
408
    /// - **Example**: The "General" and "Security" tabs in a file properties dialog.
409
    PageTab,
410

            
411
    /// Represents the content of a page in a property sheet.
412
    /// - **Purpose**: To serve as a container for the controls displayed when a `PageTab` is
413
    ///   selected.
414
    /// - **When to use**: For the content area associated with a specific tab.
415
    /// - **Example**: The set of options displayed when the "Security" tab is active.
416
    PropertyPage,
417

            
418
    /// Represents a visual indicator, like a slider thumb.
419
    /// - **Purpose**: To visually indicate the current value or position of another control.
420
    /// - **When to use**: For a sub-element that indicates status, like the thumb of a scrollbar.
421
    /// - **Example**: The draggable thumb of a scrollbar that indicates the current scroll
422
    ///   position.
423
    Indicator,
424

            
425
    /// Represents a picture or graphical image.
426
    /// - **Purpose**: To display a non-interactive image.
427
    /// - **When to use**: For images and icons that are purely decorative or informational.
428
    /// - **Example**: A company logo displayed in an application's "About" dialog.
429
    Graphic,
430

            
431
    /// Represents read-only text.
432
    /// - **Purpose**: To provide a non-editable text label for another control or for displaying
433
    ///   information.
434
    /// - **When to use**: For text that the user cannot edit.
435
    /// - **Example**: The label "Username:" next to a text input field.
436
    StaticText,
437

            
438
    /// Represents editable text or a text area.
439
    /// - **Purpose**: To allow for user text input or selection.
440
    /// - **When to use**: For text input fields where the user can type.
441
    /// - **Example**: A text box for entering a username or password.
442
    Text,
443

            
444
    /// Represents a standard push button.
445
    /// - **Purpose**: To initiate an immediate action.
446
    /// - **When to use**: For standard buttons that perform an action when clicked.
447
    /// - **Example**: An "OK" or "Cancel" button in a dialog.
448
    PushButton,
449

            
450
    /// Represents a check box control.
451
    /// - **Purpose**: To allow the user to make a binary choice (checked or unchecked).
452
    /// - **When to use**: For options that can be toggled on or off independently.
453
    /// - **Example**: A "Remember me" checkbox on a login form.
454
    CheckButton,
455

            
456
    /// Represents a radio button.
457
    /// - **Purpose**: To allow the user to select one option from a mutually exclusive group.
458
    /// - **When to use**: For a choice where only one option from a `Grouping` can be selected.
459
    /// - **Example**: "Male" and "Female" radio buttons for selecting gender.
460
    RadioButton,
461

            
462
    /// Represents a combination of a text field and a drop-down list.
463
    /// - **Purpose**: To allow the user to either type a value or select one from a list.
464
    /// - **When to use**: For controls that offer a list of suggestions but also allow custom
465
    ///   input.
466
    /// - **Example**: A font selector that allows you to type a font name or choose one from a
467
    ///   list.
468
    ComboBox,
469

            
470
    /// Represents a drop-down list box.
471
    /// - **Purpose**: To allow the user to select an item from a non-editable list that drops
472
    ///   down.
473
    /// - **When to use**: For selecting a single item from a predefined list of options.
474
    /// - **Example**: A country selection drop-down menu.
475
    DropList,
476

            
477
    /// Represents a progress bar.
478
    /// - **Purpose**: To indicate the progress of a lengthy operation.
479
    /// - **When to use**: To provide feedback for tasks like file downloads or installations.
480
    /// - **Example**: The bar that fills up to show the progress of a file copy operation.
481
    ProgressBar,
482

            
483
    /// Represents a dial or knob.
484
    /// - **Purpose**: To allow selecting a value from a continuous or discrete range, often
485
    ///   circularly.
486
    /// - **When to use**: For controls that resemble real-world dials, like a volume knob.
487
    /// - **Example**: A volume control knob in a media player application.
488
    Dial,
489

            
490
    /// Represents a control for entering a keyboard shortcut.
491
    /// - **Purpose**: To capture a key combination from the user.
492
    /// - **When to use**: In settings where users can define their own keyboard shortcuts.
493
    /// - **Example**: A text field in a settings dialog where a user can press a key combination
494
    ///   to assign it to a command.
495
    HotkeyField,
496

            
497
    /// Represents a slider for selecting a value within a range.
498
    /// - **Purpose**: To allow the user to adjust a setting along a continuous or discrete range.
499
    /// - **When to use**: For adjusting values like volume, brightness, or zoom level.
500
    /// - **Example**: A slider to control the volume of a video.
501
    Slider,
502

            
503
    /// Represents a spin button (up/down arrows) for incrementing or decrementing a value.
504
    /// - **Purpose**: To provide fine-tuned adjustment of a value, typically numeric.
505
    /// - **When to use**: For controls that allow stepping through a range of values.
506
    /// - **Example**: The up and down arrows next to a number input for setting the font size.
507
    SpinButton,
508

            
509
    /// Represents a diagram or flowchart.
510
    /// - **Purpose**: To represent data or relationships in a schematic form.
511
    /// - **When to use**: For visual representations of structures that are not charts, like a
512
    ///   database schema diagram.
513
    /// - **Example**: A flowchart illustrating a business process.
514
    Diagram,
515

            
516
    /// Represents an animation control.
517
    /// - **Purpose**: To display a sequence of images or indicate an ongoing process.
518
    /// - **When to use**: For animations that show that an operation is in progress.
519
    /// - **Example**: The animation that plays while files are being copied.
520
    Animation,
521

            
522
    /// Represents a mathematical equation.
523
    /// - **Purpose**: To display a mathematical formula in the correct format.
524
    /// - **When to use**: For displaying mathematical equations.
525
    /// - **Example**: A rendered mathematical equation in a scientific document editor.
526
    Equation,
527

            
528
    /// Represents a button that drops down a list of items.
529
    /// - **Purpose**: To combine a default action button with a list of alternative actions.
530
    /// - **When to use**: For buttons that have a primary action and a secondary list of options.
531
    /// - **Example**: A "Send" button with a dropdown arrow that reveals "Send and Archive."
532
    ButtonDropdown,
533

            
534
    /// Represents a button that drops down a full menu.
535
    /// - **Purpose**: To provide a button that opens a menu of choices rather than performing a
536
    ///   single action.
537
    /// - **When to use**: When a button's primary purpose is to reveal a menu.
538
    /// - **Example**: A "Tools" button that opens a menu with various tool options.
539
    ButtonMenu,
540

            
541
    /// Represents a button that drops down a grid for selection.
542
    /// - **Purpose**: To allow selection from a two-dimensional grid of options.
543
    /// - **When to use**: For buttons that open a grid-based selection UI.
544
    /// - **Example**: A color picker button that opens a grid of color swatches.
545
    ButtonDropdownGrid,
546

            
547
    /// Represents blank space between other objects.
548
    /// - **Purpose**: To represent significant empty areas in a UI that are part of the layout.
549
    /// - **When to use**: Sparingly, to signify that a large area is intentionally blank.
550
    /// - **Example**: A large empty panel in a complex layout might use this role.
551
    Whitespace,
552

            
553
    /// Represents the container for a set of tabs.
554
    /// - **Purpose**: To group a set of `PageTab` elements.
555
    /// - **When to use**: To act as the parent container for a row or column of tabs.
556
    /// - **Example**: The entire row of tabs at the top of a properties dialog.
557
    PageTabList,
558

            
559
    /// Represents a clock control.
560
    /// - **Purpose**: To display the current time.
561
    /// - **When to use**: For any UI element that displays time.
562
    /// - **Example**: The clock in the system tray of the operating system.
563
    Clock,
564

            
565
    /// Represents a button with two parts: a default action and a dropdown.
566
    /// - **Purpose**: To combine a frequently used action with a set of related, less-used
567
    ///   actions.
568
    /// - **When to use**: When a button has a default action and other related actions available
569
    ///   in a dropdown.
570
    /// - **Example**: A "Save" split button where the primary part saves, and the dropdown offers
571
    ///   "Save As."
572
    SplitButton,
573

            
574
    /// Represents a control for entering an IP address.
575
    /// - **Purpose**: To provide a specialized input field for IP addresses, often with formatting
576
    ///   and validation.
577
    /// - **When to use**: For dedicated IP address input fields.
578
    /// - **Example**: A network configuration dialog with a field for entering a static IP
579
    ///   address.
580
    IpAddress,
581

            
582
    /// Represents an element with no specific role.
583
    /// - **Purpose**: To indicate an element that has no semantic meaning for accessibility.
584
    /// - **When to use**: Should be used sparingly for purely decorative elements that should be
585
    ///   ignored by assistive technologies.
586
    /// - **Example**: A decorative graphical flourish that has no function or information to
587
    ///   convey.
588
    Nothing,
589

            
590
    /// Unknown or unspecified role.
591
    /// - **Purpose**: Default fallback when no specific role is assigned.
592
    /// - **When to use**: As a default value or when role information is unavailable.
593
    Unknown,
594
}
595

            
596
impl_option!(
597
    AccessibilityRole,
598
    OptionAccessibilityRole,
599
    [Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]
600
);
601

            
602
/// Defines the current state of an element for accessibility APIs (e.g., focused, checked).
603
/// These states provide dynamic information to assistive technologies about the element's
604
/// condition.
605
///
606
/// See the [MSDN State Constants page](https://docs.microsoft.com/en-us/windows/win32/winauto/object-state-constants) for more details.
607
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
608
#[repr(C)]
609
pub enum AccessibilityState {
610
    /// The element is unavailable and cannot be interacted with.
611
    /// - **Purpose**: To indicate that a control is disabled or grayed out.
612
    /// - **When to use**: For disabled buttons, non-interactive menu items, or any control that is
613
    ///   temporarily non-functional.
614
    /// - **Example**: A "Save" button that is disabled until the user makes changes to a document.
615
    Unavailable,
616

            
617
    /// The element is selected.
618
    /// - **Purpose**: To indicate that an item is currently chosen or highlighted. This is
619
    ///   distinct from having focus.
620
    /// - **When to use**: For selected items in a list, highlighted text, or the currently active
621
    ///   tab in a tab list.
622
    /// - **Example**: A file highlighted in a file explorer, or multiple selected emails in an
623
    ///   inbox.
624
    Selected,
625

            
626
    /// The element has the keyboard focus.
627
    /// - **Purpose**: To identify the single element that will receive keyboard input.
628
    /// - **When to use**: For the control that is currently active and ready to be manipulated by
629
    ///   the keyboard.
630
    /// - **Example**: A text box with a blinking cursor, or a button with a dotted outline around
631
    ///   it.
632
    Focused,
633

            
634
    /// The element is checked, toggled, or in an "on" state.
635
    /// - **Purpose**: To represent checked checkboxes, selected radio buttons, and active toggles.
636
    /// - **Example**: A checked "I agree" checkbox, a selected "Yes" radio button.
637
    CheckedTrue,
638
    /// The element is unchecked, untoggled, or in an "off" state.
639
    /// - **Purpose**: To explicitly represent an unchecked checkbox or unselected radio button.
640
    /// - **Example**: An unchecked checkbox that the user has not yet ticked.
641
    CheckedFalse,
642

            
643
    /// The element's content cannot be edited by the user.
644
    /// - **Purpose**: To indicate that the element's value can be viewed and copied, but not
645
    ///   modified.
646
    /// - **When to use**: For display-only text fields or documents.
647
    /// - **Example**: A text box displaying a license agreement that the user can scroll through
648
    ///   but cannot edit.
649
    Readonly,
650

            
651
    /// The element is the default action in a dialog or form.
652
    /// - **Purpose**: To identify the button that will be activated if the user presses the Enter
653
    ///   key.
654
    /// - **When to use**: For the primary confirmation button in a dialog.
655
    /// - **Example**: The "OK" button in a dialog box, which often has a thicker or colored
656
    ///   border.
657
    Default,
658

            
659
    /// The element is expanded, showing its child items.
660
    /// - **Purpose**: To indicate that a collapsible element is currently open and its contents
661
    ///   are visible.
662
    /// - **When to use**: For tree view nodes, combo boxes with their lists open, or expanded
663
    ///   accordion panels.
664
    /// - **Example**: A folder in a file explorer's tree view that has been clicked to show its
665
    ///   subfolders.
666
    Expanded,
667

            
668
    /// The element is collapsed, hiding its child items.
669
    /// - **Purpose**: To indicate that a collapsible element is closed and its contents are
670
    ///   hidden.
671
    /// - **When to use**: The counterpart to `Expanded` for any collapsible UI element.
672
    /// - **Example**: A closed folder in a file explorer's tree view, hiding its contents.
673
    Collapsed,
674

            
675
    /// The element is busy and cannot respond to user interaction.
676
    /// - **Purpose**: To indicate that the element or application is performing an operation and
677
    ///   is temporarily unresponsive.
678
    /// - **When to use**: When an application is loading, processing data, or otherwise occupied.
679
    /// - **Example**: A window that is grayed out and shows a spinning cursor while saving a large
680
    ///   file.
681
    Busy,
682

            
683
    /// The element is not currently visible on the screen.
684
    /// - **Purpose**: To indicate that an element exists but is currently scrolled out of the
685
    ///   visible area.
686
    /// - **When to use**: For items in a long list or a large document that are not within the
687
    ///   current viewport.
688
    /// - **Example**: A list item in a long dropdown that you would have to scroll down to see.
689
    Offscreen,
690

            
691
    /// The element can accept keyboard focus.
692
    /// - **Purpose**: To indicate that the user can navigate to this element using the keyboard
693
    ///   (e.g., with the Tab key).
694
    /// - **When to use**: On all interactive elements like buttons, links, and input fields,
695
    ///   whether they currently have focus or not.
696
    /// - **Example**: A button that can receive focus, even if it is not the currently focused
697
    ///   element.
698
    Focusable,
699

            
700
    /// The element is a container whose children can be selected.
701
    /// - **Purpose**: To indicate that the element contains items that can be chosen.
702
    /// - **When to use**: On container controls like list boxes, tree views, or text spans where
703
    ///   text can be highlighted.
704
    /// - **Example**: A list box control is `Selectable`, while its individual list items have the
705
    ///   `Selected` state when chosen.
706
    Selectable,
707

            
708
    /// The element is a hyperlink.
709
    /// - **Purpose**: To identify an object that navigates to another resource or location when
710
    ///   activated.
711
    /// - **When to use**: On any object that functions as a hyperlink.
712
    /// - **Example**: Text or an image that, when clicked, opens a web page.
713
    Linked,
714

            
715
    /// The element is a hyperlink that has been visited.
716
    /// - **Purpose**: To indicate that a hyperlink has already been followed by the user.
717
    /// - **When to use**: On a `Linked` object that the user has previously activated.
718
    /// - **Example**: A hyperlink on a web page that has changed color to show it has been
719
    ///   visited.
720
    Traversed,
721

            
722
    /// The element allows multiple of its children to be selected at once.
723
    /// - **Purpose**: To indicate that a container control supports multi-selection.
724
    /// - **When to use**: On container controls like list boxes or file explorers that support
725
    ///   multiple selections (e.g., with Ctrl-click).
726
    /// - **Example**: A file list that allows the user to select several files at once for a copy
727
    ///   operation.
728
    Multiselectable,
729

            
730
    /// The element contains protected content that should not be read aloud.
731
    /// - **Purpose**: To prevent assistive technologies from speaking the content of a sensitive
732
    ///   field.
733
    /// - **When to use**: Primarily for password input fields.
734
    /// - **Example**: A password text box where typed characters are masked with asterisks or
735
    ///   dots.
736
    Protected,
737
}
738

            
739
impl_option!(
740
    AccessibilityState,
741
    OptionAccessibilityState,
742
    [Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash]
743
);
744

            
745
impl_vec!(AccessibilityState, AccessibilityStateVec, AccessibilityStateVecDestructor, AccessibilityStateVecDestructorType, AccessibilityStateVecSlice, OptionAccessibilityState);
746
impl_vec_clone!(
747
    AccessibilityState,
748
    AccessibilityStateVec,
749
    AccessibilityStateVecDestructor
750
);
751
impl_vec_debug!(AccessibilityState, AccessibilityStateVec);
752
impl_vec_partialeq!(AccessibilityState, AccessibilityStateVec);
753
impl_vec_partialord!(AccessibilityState, AccessibilityStateVec);
754
impl_vec_eq!(AccessibilityState, AccessibilityStateVec);
755
impl_vec_ord!(AccessibilityState, AccessibilityStateVec);
756
impl_vec_hash!(AccessibilityState, AccessibilityStateVec);
757

            
758
/// Compact accessibility information for common use cases.
759
///
760
/// This is a lighter-weight alternative to `AccessibilityInfo` for cases where
761
/// only basic accessibility properties are needed. Developers must explicitly
762
/// pass `None` if they choose not to provide accessibility information.
763
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
764
#[repr(C)]
765
pub struct SmallAriaInfo {
766
    /// Accessible label/name
767
    pub label: OptionString,
768
    /// Element's role (button, link, etc.)
769
    pub role: OptionAccessibilityRole,
770
    /// Additional description
771
    pub description: OptionString,
772
}
773

            
774
impl_option!(
775
    SmallAriaInfo,
776
    OptionSmallAriaInfo,
777
    copy = false,
778
    [Debug, Clone, PartialEq, Eq, Hash]
779
);
780

            
781
impl SmallAriaInfo {
782
14
    pub fn label<S: Into<AzString>>(text: S) -> Self {
783
14
        Self {
784
14
            label: OptionString::Some(text.into()),
785
14
            role: OptionAccessibilityRole::None,
786
14
            description: OptionString::None,
787
14
        }
788
14
    }
789

            
790
    pub fn with_role(mut self, role: AccessibilityRole) -> Self {
791
        self.role = OptionAccessibilityRole::Some(role);
792
        self
793
    }
794

            
795
    pub fn with_description<S: Into<AzString>>(mut self, desc: S) -> Self {
796
        self.description = OptionString::Some(desc.into());
797
        self
798
    }
799

            
800
    /// Convert to full `AccessibilityInfo`
801
238
    pub fn to_full_info(&self) -> AccessibilityInfo {
802
        AccessibilityInfo {
803
238
            accessibility_name: self.label.clone(),
804
238
            accessibility_value: OptionString::None,
805
238
            description: self.description.clone(),
806
238
            role: match self.role {
807
                OptionAccessibilityRole::Some(r) => r,
808
238
                OptionAccessibilityRole::None => AccessibilityRole::Unknown,
809
            },
810
238
            states: Vec::new().into(),
811
238
            accelerator: OptionVirtualKeyCodeCombo::None,
812
238
            default_action: OptionString::None,
813
238
            supported_actions: Vec::new().into(),
814
            is_live_region: false,
815
238
            labelled_by: OptionDomNodeId::None,
816
238
            described_by: OptionDomNodeId::None,
817
        }
818
238
    }
819
}
820

            
821
/// Accessibility information for a `<progress>` indicator.
822
///
823
/// Mirrors HTML's `<progress value max>` plus an `indeterminate` flag for
824
/// progress bars whose end is unknown. Maps to `AccessibilityRole::ProgressBar`.
825
#[derive(Debug, Clone, PartialEq)]
826
#[repr(C)]
827
pub struct ProgressAriaInfo {
828
    /// Accessible label describing the task being measured.
829
    pub label: OptionString,
830
    /// Current progress value. `None` for indeterminate progress.
831
    pub current_value: OptionF32,
832
    /// Maximum value the progress bar can reach. `None` falls back to `1.0`.
833
    pub max: OptionF32,
834
    /// `true` for spinners / progress with no known endpoint. Overrides `current_value`.
835
    pub indeterminate: bool,
836
    /// Optional extended description (`aria-describedby` equivalent).
837
    pub description: OptionString,
838
}
839

            
840
impl_option!(
841
    ProgressAriaInfo,
842
    OptionProgressAriaInfo,
843
    copy = false,
844
    [Debug, Clone, PartialEq]
845
);
846

            
847
impl ProgressAriaInfo {
848
    /// Creates a `ProgressAriaInfo` with only an accessible label.
849
    pub fn create(label: AzString) -> Self {
850
        Self {
851
            label: OptionString::Some(label),
852
            current_value: OptionF32::None,
853
            max: OptionF32::None,
854
            indeterminate: false,
855
            description: OptionString::None,
856
        }
857
    }
858

            
859
    /// Returns a copy with the given current value.
860
    pub fn with_current_value(mut self, value: f32) -> Self {
861
        self.current_value = OptionF32::Some(value);
862
        self
863
    }
864

            
865
    /// Returns a copy with the given maximum value.
866
    pub fn with_max(mut self, max: f32) -> Self {
867
        self.max = OptionF32::Some(max);
868
        self
869
    }
870

            
871
    /// Returns a copy with the indeterminate flag set.
872
    pub fn with_indeterminate(mut self, indeterminate: bool) -> Self {
873
        self.indeterminate = indeterminate;
874
        self
875
    }
876

            
877
    /// Returns a copy with the given description.
878
    pub fn with_description(mut self, desc: AzString) -> Self {
879
        self.description = OptionString::Some(desc);
880
        self
881
    }
882

            
883
    /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
884
    pub fn to_full_info(&self) -> AccessibilityInfo {
885
        let value_string = if self.indeterminate {
886
            OptionString::None
887
        } else {
888
            match self.current_value {
889
                OptionF32::Some(v) => OptionString::Some(format!("{}", v).into()),
890
                OptionF32::None => OptionString::None,
891
            }
892
        };
893
        AccessibilityInfo {
894
            accessibility_name: self.label.clone(),
895
            accessibility_value: value_string,
896
            description: self.description.clone(),
897
            role: AccessibilityRole::ProgressBar,
898
            states: Vec::new().into(),
899
            accelerator: OptionVirtualKeyCodeCombo::None,
900
            default_action: OptionString::None,
901
            supported_actions: Vec::new().into(),
902
            is_live_region: false,
903
            labelled_by: OptionDomNodeId::None,
904
            described_by: OptionDomNodeId::None,
905
        }
906
    }
907
}
908

            
909
/// Accessibility information for a `<meter>` gauge.
910
///
911
/// Unlike `<progress>`, `<meter>` always carries a known `value`/`min`/`max`
912
/// triple, so those fields are required at construction time. Maps to
913
/// `AccessibilityRole::Indicator`.
914
#[derive(Debug, Clone, PartialEq)]
915
#[repr(C)]
916
pub struct MeterAriaInfo {
917
    /// Accessible label describing what the meter measures.
918
    pub label: OptionString,
919
    /// Current value of the meter (within `[min, max]`).
920
    pub current_value: f32,
921
    /// Lower bound of the measurement range.
922
    pub min: f32,
923
    /// Upper bound of the measurement range.
924
    pub max: f32,
925
    /// Optional "low" threshold (values below this are considered low).
926
    pub low: OptionF32,
927
    /// Optional "high" threshold (values above this are considered high).
928
    pub high: OptionF32,
929
    /// Optional optimum value within the range.
930
    pub optimum: OptionF32,
931
    /// Optional extended description.
932
    pub description: OptionString,
933
}
934

            
935
impl_option!(
936
    MeterAriaInfo,
937
    OptionMeterAriaInfo,
938
    copy = false,
939
    [Debug, Clone, PartialEq]
940
);
941

            
942
impl MeterAriaInfo {
943
    /// Creates a `MeterAriaInfo` with the required label and value/range triple.
944
    pub fn create(label: AzString, current_value: f32, min: f32, max: f32) -> Self {
945
        Self {
946
            label: OptionString::Some(label),
947
            current_value,
948
            min,
949
            max,
950
            low: OptionF32::None,
951
            high: OptionF32::None,
952
            optimum: OptionF32::None,
953
            description: OptionString::None,
954
        }
955
    }
956

            
957
    /// Returns a copy with the given low threshold.
958
    pub fn with_low(mut self, low: f32) -> Self {
959
        self.low = OptionF32::Some(low);
960
        self
961
    }
962

            
963
    /// Returns a copy with the given high threshold.
964
    pub fn with_high(mut self, high: f32) -> Self {
965
        self.high = OptionF32::Some(high);
966
        self
967
    }
968

            
969
    /// Returns a copy with the given optimum value.
970
    pub fn with_optimum(mut self, optimum: f32) -> Self {
971
        self.optimum = OptionF32::Some(optimum);
972
        self
973
    }
974

            
975
    /// Returns a copy with the given description.
976
    pub fn with_description(mut self, desc: AzString) -> Self {
977
        self.description = OptionString::Some(desc);
978
        self
979
    }
980

            
981
    /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
982
    pub fn to_full_info(&self) -> AccessibilityInfo {
983
        AccessibilityInfo {
984
            accessibility_name: self.label.clone(),
985
            accessibility_value: OptionString::Some(format!("{}", self.current_value).into()),
986
            description: self.description.clone(),
987
            role: AccessibilityRole::Indicator,
988
            states: Vec::new().into(),
989
            accelerator: OptionVirtualKeyCodeCombo::None,
990
            default_action: OptionString::None,
991
            supported_actions: Vec::new().into(),
992
            is_live_region: false,
993
            labelled_by: OptionDomNodeId::None,
994
            described_by: OptionDomNodeId::None,
995
        }
996
    }
997
}
998

            
999
/// Accessibility information for a `<dialog>` element.
///
/// Captures the modal/non-modal distinction and a reference to a separate
/// node that describes the dialog (`aria-describedby`). The `role` defaults
/// to `AccessibilityRole::Dialog` but can be overridden (e.g., for alert
/// dialogs).
#[derive(Debug, Clone, PartialEq)]
#[repr(C)]
pub struct DialogAriaInfo {
    /// Accessible label / title for the dialog.
    pub label: OptionString,
    /// Optional ID of another node that describes the dialog content.
    pub described_by: OptionString,
    /// Optional inline description.
    pub description: OptionString,
    /// Role for the dialog. Defaults to `Dialog`; use `Alert` for urgent dialogs.
    pub role: AccessibilityRole,
    /// `true` if the dialog is modal (focus trapped, background inert).
    pub modal: bool,
}
impl_option!(
    DialogAriaInfo,
    OptionDialogAriaInfo,
    copy = false,
    [Debug, Clone, PartialEq]
);
impl DialogAriaInfo {
    /// Creates a `DialogAriaInfo` with the given accessible label. Defaults
    /// to a non-modal dialog with role `Dialog`.
    pub fn create(label: AzString) -> Self {
        Self {
            label: OptionString::Some(label),
            modal: false,
            described_by: OptionString::None,
            role: AccessibilityRole::Dialog,
            description: OptionString::None,
        }
    }
    /// Returns a copy with the given modality flag.
    pub fn with_modal(mut self, modal: bool) -> Self {
        self.modal = modal;
        self
    }
    /// Returns a copy with `aria-describedby` pointing at the given node ID.
    pub fn with_described_by(mut self, described_by: AzString) -> Self {
        self.described_by = OptionString::Some(described_by);
        self
    }
    /// Returns a copy with the given role (defaults to `Dialog`).
    pub fn with_role(mut self, role: AccessibilityRole) -> Self {
        self.role = role;
        self
    }
    /// Returns a copy with the given inline description.
    pub fn with_description(mut self, desc: AzString) -> Self {
        self.description = OptionString::Some(desc);
        self
    }
    /// Convert to full `AccessibilityInfo` so the value can be installed on a node.
    pub fn to_full_info(&self) -> AccessibilityInfo {
        AccessibilityInfo {
            accessibility_name: self.label.clone(),
            accessibility_value: OptionString::None,
            description: self.description.clone(),
            role: self.role,
            states: Vec::new().into(),
            accelerator: OptionVirtualKeyCodeCombo::None,
            default_action: OptionString::None,
            supported_actions: Vec::new().into(),
            is_live_region: false,
            labelled_by: OptionDomNodeId::None,
            described_by: OptionDomNodeId::None,
        }
    }
}