1#[cfg(feature = "pyo3")]
12use pyo3::pyclass;
13#[cfg(feature = "schemars")]
14use schemars::{
15 gen::SchemaGenerator,
16 schema::{InstanceType, ObjectValidation, Schema, SchemaObject},
17 JsonSchema, Map as SchemaMap,
18};
19#[cfg(feature = "serde")]
20use serde::{
21 de::{Deserializer, IgnoredAny, MapAccess, Visitor},
22 ser::{SerializeMap, Serializer},
23 Deserialize, Serialize,
24};
25#[cfg(feature = "serde")]
26use std::fmt;
27
28mod geometry;
29pub use geometry::{Affine, Point, Rect, Size, Vec2};
30
31#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
42#[cfg_attr(feature = "enumn", derive(enumn::N))]
43#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
44#[cfg_attr(feature = "schemars", derive(JsonSchema))]
45#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
46#[cfg_attr(
47 feature = "pyo3",
48 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
49)]
50#[repr(u8)]
51pub enum Role {
52 #[default]
53 Unknown,
54 InlineTextBox,
55 Cell,
56 Label,
57 Image,
58 Link,
59 Row,
60 ListItem,
61
62 ListMarker,
64
65 TreeItem,
66 ListBoxOption,
67 MenuItem,
68 MenuListOption,
69 Paragraph,
70
71 GenericContainer,
75
76 CheckBox,
77 RadioButton,
78 TextInput,
79 Button,
80 DefaultButton,
81 Pane,
82 RowHeader,
83 ColumnHeader,
84 RowGroup,
85 List,
86 Table,
87 LayoutTableCell,
88 LayoutTableRow,
89 LayoutTable,
90 Switch,
91 Menu,
92
93 MultilineTextInput,
94 SearchInput,
95 DateInput,
96 DateTimeInput,
97 WeekInput,
98 MonthInput,
99 TimeInput,
100 EmailInput,
101 NumberInput,
102 PasswordInput,
103 PhoneNumberInput,
104 UrlInput,
105
106 Abbr,
107 Alert,
108 AlertDialog,
109 Application,
110 Article,
111 Audio,
112 Banner,
113 Blockquote,
114 Canvas,
115 Caption,
116 Caret,
117 Code,
118 ColorWell,
119 ComboBox,
120 EditableComboBox,
121 Complementary,
122 Comment,
123 ContentDeletion,
124 ContentInsertion,
125 ContentInfo,
126 Definition,
127 DescriptionList,
128 DescriptionListDetail,
129 DescriptionListTerm,
130 Details,
131 Dialog,
132 Directory,
133 DisclosureTriangle,
134 Document,
135 EmbeddedObject,
136 Emphasis,
137 Feed,
138 FigureCaption,
139 Figure,
140 Footer,
141 FooterAsNonLandmark,
142 Form,
143 Grid,
144 Group,
145 Header,
146 HeaderAsNonLandmark,
147 Heading,
148 Iframe,
149 IframePresentational,
150 ImeCandidate,
151 Keyboard,
152 Legend,
153 LineBreak,
154 ListBox,
155 Log,
156 Main,
157 Mark,
158 Marquee,
159 Math,
160 MenuBar,
161 MenuItemCheckBox,
162 MenuItemRadio,
163 MenuListPopup,
164 Meter,
165 Navigation,
166 Note,
167 PluginObject,
168 Portal,
169 Pre,
170 ProgressIndicator,
171 RadioGroup,
172 Region,
173 RootWebArea,
174 Ruby,
175 RubyAnnotation,
176 ScrollBar,
177 ScrollView,
178 Search,
179 Section,
180 Slider,
181 SpinButton,
182 Splitter,
183 Status,
184 Strong,
185 Suggestion,
186 SvgRoot,
187 Tab,
188 TabList,
189 TabPanel,
190 Term,
191 Time,
192 Timer,
193 TitleBar,
194 Toolbar,
195 Tooltip,
196 Tree,
197 TreeGrid,
198 Video,
199 WebView,
200 Window,
201
202 PdfActionableHighlight,
203 PdfRoot,
204
205 GraphicsDocument,
208 GraphicsObject,
209 GraphicsSymbol,
210
211 DocAbstract,
214 DocAcknowledgements,
215 DocAfterword,
216 DocAppendix,
217 DocBackLink,
218 DocBiblioEntry,
219 DocBibliography,
220 DocBiblioRef,
221 DocChapter,
222 DocColophon,
223 DocConclusion,
224 DocCover,
225 DocCredit,
226 DocCredits,
227 DocDedication,
228 DocEndnote,
229 DocEndnotes,
230 DocEpigraph,
231 DocEpilogue,
232 DocErrata,
233 DocExample,
234 DocFootnote,
235 DocForeword,
236 DocGlossary,
237 DocGlossRef,
238 DocIndex,
239 DocIntroduction,
240 DocNoteRef,
241 DocNotice,
242 DocPageBreak,
243 DocPageFooter,
244 DocPageHeader,
245 DocPageList,
246 DocPart,
247 DocPreface,
248 DocPrologue,
249 DocPullquote,
250 DocQna,
251 DocSubtitle,
252 DocTip,
253 DocToc,
254
255 ListGrid,
259
260 Terminal,
264}
265
266#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
271#[cfg_attr(feature = "enumn", derive(enumn::N))]
272#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
273#[cfg_attr(feature = "schemars", derive(JsonSchema))]
274#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
275#[cfg_attr(
276 feature = "pyo3",
277 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
278)]
279#[repr(u8)]
280pub enum Action {
281 Default,
283
284 Focus,
285 Blur,
286
287 Collapse,
288 Expand,
289
290 CustomAction,
292
293 Decrement,
295 Increment,
297
298 HideTooltip,
299 ShowTooltip,
300
301 ReplaceSelectedText,
305
306 ScrollBackward,
310 ScrollDown,
311 ScrollForward,
312 ScrollLeft,
313 ScrollRight,
314 ScrollUp,
315
316 ScrollIntoView,
320
321 ScrollToPoint,
325
326 SetScrollOffset,
328
329 SetTextSelection,
331
332 SetSequentialFocusNavigationStartingPoint,
336
337 SetValue,
341
342 ShowContextMenu,
343}
344
345impl Action {
346 fn mask(self) -> u32 {
347 1 << (self as u8)
348 }
349}
350
351#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
352#[cfg_attr(feature = "enumn", derive(enumn::N))]
353#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
354#[cfg_attr(feature = "schemars", derive(JsonSchema))]
355#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
356#[cfg_attr(
357 feature = "pyo3",
358 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
359)]
360#[repr(u8)]
361pub enum Orientation {
362 Horizontal,
364 Vertical,
366}
367
368#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
369#[cfg_attr(feature = "enumn", derive(enumn::N))]
370#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
371#[cfg_attr(feature = "schemars", derive(JsonSchema))]
372#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
373#[cfg_attr(
374 feature = "pyo3",
375 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
376)]
377#[repr(u8)]
378pub enum TextDirection {
379 LeftToRight,
380 RightToLeft,
381 TopToBottom,
382 BottomToTop,
383}
384
385#[derive(Clone, Copy, Debug, PartialEq, Eq)]
390#[cfg_attr(feature = "enumn", derive(enumn::N))]
391#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
392#[cfg_attr(feature = "schemars", derive(JsonSchema))]
393#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
394#[cfg_attr(
395 feature = "pyo3",
396 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
397)]
398#[repr(u8)]
399pub enum Invalid {
400 True,
401 Grammar,
402 Spelling,
403}
404
405#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
406#[cfg_attr(feature = "enumn", derive(enumn::N))]
407#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
408#[cfg_attr(feature = "schemars", derive(JsonSchema))]
409#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
410#[cfg_attr(
411 feature = "pyo3",
412 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
413)]
414#[repr(u8)]
415pub enum Toggled {
416 False,
417 True,
418 Mixed,
419}
420
421#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
428#[cfg_attr(feature = "enumn", derive(enumn::N))]
429#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
430#[cfg_attr(feature = "schemars", derive(JsonSchema))]
431#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
432#[cfg_attr(
433 feature = "pyo3",
434 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
435)]
436#[repr(u8)]
437pub enum DefaultActionVerb {
438 Click,
439 Focus,
440 Check,
441 Uncheck,
442 ClickAncestor,
447 Jump,
448 Open,
449 Press,
450 Select,
451 Unselect,
452}
453
454#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
455#[cfg_attr(feature = "enumn", derive(enumn::N))]
456#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
457#[cfg_attr(feature = "schemars", derive(JsonSchema))]
458#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
459#[cfg_attr(
460 feature = "pyo3",
461 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
462)]
463#[repr(u8)]
464pub enum SortDirection {
465 Ascending,
466 Descending,
467 Other,
468}
469
470#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
471#[cfg_attr(feature = "enumn", derive(enumn::N))]
472#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
473#[cfg_attr(feature = "schemars", derive(JsonSchema))]
474#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
475#[cfg_attr(
476 feature = "pyo3",
477 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
478)]
479#[repr(u8)]
480pub enum AriaCurrent {
481 False,
482 True,
483 Page,
484 Step,
485 Location,
486 Date,
487 Time,
488}
489
490#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
491#[cfg_attr(feature = "enumn", derive(enumn::N))]
492#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
493#[cfg_attr(feature = "schemars", derive(JsonSchema))]
494#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
495#[cfg_attr(
496 feature = "pyo3",
497 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
498)]
499#[repr(u8)]
500pub enum AutoComplete {
501 Inline,
502 List,
503 Both,
504}
505
506#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
507#[cfg_attr(feature = "enumn", derive(enumn::N))]
508#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
509#[cfg_attr(feature = "schemars", derive(JsonSchema))]
510#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
511#[cfg_attr(
512 feature = "pyo3",
513 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
514)]
515#[repr(u8)]
516pub enum Live {
517 Off,
518 Polite,
519 Assertive,
520}
521
522#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
523#[cfg_attr(feature = "enumn", derive(enumn::N))]
524#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
525#[cfg_attr(feature = "schemars", derive(JsonSchema))]
526#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
527#[cfg_attr(
528 feature = "pyo3",
529 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
530)]
531#[repr(u8)]
532pub enum HasPopup {
533 True,
534 Menu,
535 Listbox,
536 Tree,
537 Grid,
538 Dialog,
539}
540
541#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
542#[cfg_attr(feature = "enumn", derive(enumn::N))]
543#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
544#[cfg_attr(feature = "schemars", derive(JsonSchema))]
545#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
546#[cfg_attr(
547 feature = "pyo3",
548 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
549)]
550#[repr(u8)]
551pub enum ListStyle {
552 Circle,
553 Disc,
554 Image,
555 Numeric,
556 Square,
557 Other,
559}
560
561#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
562#[cfg_attr(feature = "enumn", derive(enumn::N))]
563#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
564#[cfg_attr(feature = "schemars", derive(JsonSchema))]
565#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
566#[cfg_attr(
567 feature = "pyo3",
568 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
569)]
570#[repr(u8)]
571pub enum TextAlign {
572 Left,
573 Right,
574 Center,
575 Justify,
576}
577
578#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
579#[cfg_attr(feature = "enumn", derive(enumn::N))]
580#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
581#[cfg_attr(feature = "schemars", derive(JsonSchema))]
582#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
583#[cfg_attr(
584 feature = "pyo3",
585 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
586)]
587#[repr(u8)]
588pub enum VerticalOffset {
589 Subscript,
590 Superscript,
591}
592
593#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
594#[cfg_attr(feature = "enumn", derive(enumn::N))]
595#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
596#[cfg_attr(feature = "schemars", derive(JsonSchema))]
597#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
598#[cfg_attr(
599 feature = "pyo3",
600 pyclass(module = "accesskit", rename_all = "SCREAMING_SNAKE_CASE")
601)]
602#[repr(u8)]
603pub enum TextDecoration {
604 Solid,
605 Dotted,
606 Dashed,
607 Double,
608 Wavy,
609}
610
611pub type NodeIdContent = u64;
612
613#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
615#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
616#[cfg_attr(feature = "schemars", derive(JsonSchema))]
617#[repr(transparent)]
618pub struct NodeId(pub NodeIdContent);
619
620impl From<NodeIdContent> for NodeId {
621 #[inline]
622 fn from(inner: NodeIdContent) -> Self {
623 Self(inner)
624 }
625}
626
627impl From<NodeId> for NodeIdContent {
628 #[inline]
629 fn from(outer: NodeId) -> Self {
630 outer.0
631 }
632}
633
634#[derive(Clone, Debug, PartialEq, Eq)]
639#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
640#[cfg_attr(feature = "schemars", derive(JsonSchema))]
641#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
642#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
643pub struct CustomAction {
644 pub id: i32,
645 pub description: Box<str>,
646}
647
648#[derive(Clone, Copy, Debug, PartialEq, Eq)]
649#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
650#[cfg_attr(feature = "schemars", derive(JsonSchema))]
651#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
652#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
653pub struct TextPosition {
654 pub node: NodeId,
656 pub character_index: usize,
659}
660
661#[derive(Clone, Copy, Debug, PartialEq, Eq)]
662#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
663#[cfg_attr(feature = "schemars", derive(JsonSchema))]
664#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
665#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
666pub struct TextSelection {
667 pub anchor: TextPosition,
672 pub focus: TextPosition,
676}
677
678#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
679#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, enumn::N))]
680#[cfg_attr(feature = "schemars", derive(JsonSchema))]
681#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
682#[repr(u8)]
683enum Flag {
684 Hovered,
685 Hidden,
686 Linked,
687 Multiselectable,
688 Required,
689 Visited,
690 Busy,
691 LiveAtomic,
692 Modal,
693 TouchTransparent,
694 ReadOnly,
695 Disabled,
696 Bold,
697 Italic,
698 ClipsChildren,
699 IsLineBreakingObject,
700 IsPageBreakingObject,
701 IsSpellingError,
702 IsGrammarError,
703 IsSearchMatch,
704 IsSuggestion,
705}
706
707impl Flag {
708 fn mask(self) -> u32 {
709 1 << (self as u8)
710 }
711}
712
713#[derive(Clone, Debug, PartialEq)]
717enum PropertyValue {
718 None,
719 NodeIdVec(Vec<NodeId>),
720 NodeId(NodeId),
721 String(Box<str>),
722 F64(f64),
723 Usize(usize),
724 Color(u32),
725 TextDecoration(TextDecoration),
726 LengthSlice(Box<[u8]>),
727 CoordSlice(Box<[f32]>),
728 Bool(bool),
729 Invalid(Invalid),
730 Toggled(Toggled),
731 Live(Live),
732 DefaultActionVerb(DefaultActionVerb),
733 TextDirection(TextDirection),
734 Orientation(Orientation),
735 SortDirection(SortDirection),
736 AriaCurrent(AriaCurrent),
737 AutoComplete(AutoComplete),
738 HasPopup(HasPopup),
739 ListStyle(ListStyle),
740 TextAlign(TextAlign),
741 VerticalOffset(VerticalOffset),
742 Affine(Box<Affine>),
743 Rect(Rect),
744 TextSelection(Box<TextSelection>),
745 CustomActionVec(Vec<CustomAction>),
746}
747
748#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
749#[cfg_attr(feature = "serde", derive(Serialize, Deserialize, enumn::N))]
750#[cfg_attr(feature = "schemars", derive(JsonSchema))]
751#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
752#[repr(u8)]
753enum PropertyId {
754 Children,
756 Controls,
757 Details,
758 DescribedBy,
759 FlowTo,
760 LabelledBy,
761 Owns,
762 RadioGroup,
763
764 ActiveDescendant,
766 ErrorMessage,
767 InPageLinkTarget,
768 MemberOf,
769 NextOnLine,
770 PreviousOnLine,
771 PopupFor,
772
773 Name,
775 Description,
776 Value,
777 AccessKey,
778 AuthorId,
779 ClassName,
780 FontFamily,
781 HtmlTag,
782 InnerHtml,
783 KeyboardShortcut,
784 Language,
785 Placeholder,
786 RoleDescription,
787 StateDescription,
788 Tooltip,
789 Url,
790 RowIndexText,
791 ColumnIndexText,
792
793 ScrollX,
795 ScrollXMin,
796 ScrollXMax,
797 ScrollY,
798 ScrollYMin,
799 ScrollYMax,
800 NumericValue,
801 MinNumericValue,
802 MaxNumericValue,
803 NumericValueStep,
804 NumericValueJump,
805 FontSize,
806 FontWeight,
807
808 RowCount,
810 ColumnCount,
811 RowIndex,
812 ColumnIndex,
813 RowSpan,
814 ColumnSpan,
815 Level,
816 SizeOfSet,
817 PositionInSet,
818
819 ColorValue,
821 BackgroundColor,
822 ForegroundColor,
823
824 Overline,
826 Strikethrough,
827 Underline,
828
829 CharacterLengths,
831 WordLengths,
832
833 CharacterPositions,
835 CharacterWidths,
836
837 Expanded,
839 Selected,
840
841 Invalid,
843 Toggled,
844 Live,
845 DefaultActionVerb,
846 TextDirection,
847 Orientation,
848 SortDirection,
849 AriaCurrent,
850 AutoComplete,
851 HasPopup,
852 ListStyle,
853 TextAlign,
854 VerticalOffset,
855
856 Transform,
858 Bounds,
859 TextSelection,
860 CustomActions,
861
862 Unset,
864}
865
866#[derive(Clone, Copy, Debug, PartialEq, Eq)]
867#[repr(transparent)]
868struct PropertyIndices([u8; PropertyId::Unset as usize]);
869
870impl Default for PropertyIndices {
871 fn default() -> Self {
872 Self([PropertyId::Unset as u8; PropertyId::Unset as usize])
873 }
874}
875
876#[derive(Clone, Debug, PartialEq)]
877struct Properties {
878 indices: PropertyIndices,
879 values: Box<[PropertyValue]>,
880}
881
882#[derive(Clone, Debug, PartialEq)]
889#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
890#[cfg_attr(feature = "schemars", derive(JsonSchema))]
891#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
892#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
893pub struct Node {
894 role: Role,
895 actions: u32,
896 flags: u32,
897 properties: Properties,
898}
899
900#[derive(Clone, Debug, Default, PartialEq)]
901struct PropertiesBuilder {
902 indices: PropertyIndices,
903 values: Vec<PropertyValue>,
904}
905
906#[derive(Clone, Debug, Default, PartialEq)]
908pub struct NodeBuilder {
909 role: Role,
910 actions: u32,
911 flags: u32,
912 properties: PropertiesBuilder,
913}
914
915impl PropertyIndices {
916 fn get<'a>(&self, values: &'a [PropertyValue], id: PropertyId) -> &'a PropertyValue {
917 let index = self.0[id as usize];
918 if index == PropertyId::Unset as u8 {
919 &PropertyValue::None
920 } else {
921 &values[index as usize]
922 }
923 }
924}
925
926fn unexpected_property_type() -> ! {
927 panic!();
928}
929
930impl PropertiesBuilder {
931 fn get_mut(&mut self, id: PropertyId, default: PropertyValue) -> &mut PropertyValue {
932 let index = self.indices.0[id as usize] as usize;
933 if index == PropertyId::Unset as usize {
934 self.values.push(default);
935 let index = self.values.len() - 1;
936 self.indices.0[id as usize] = index as u8;
937 &mut self.values[index]
938 } else {
939 if matches!(self.values[index], PropertyValue::None) {
940 self.values[index] = default;
941 }
942 &mut self.values[index]
943 }
944 }
945
946 fn set(&mut self, id: PropertyId, value: PropertyValue) {
947 let index = self.indices.0[id as usize];
948 if index == PropertyId::Unset as u8 {
949 self.values.push(value);
950 self.indices.0[id as usize] = (self.values.len() - 1) as u8;
951 } else {
952 self.values[index as usize] = value;
953 }
954 }
955
956 fn clear(&mut self, id: PropertyId) {
957 let index = self.indices.0[id as usize];
958 if index != PropertyId::Unset as u8 {
959 self.values[index as usize] = PropertyValue::None;
960 }
961 }
962
963 fn build(self) -> Properties {
964 Properties {
965 indices: self.indices,
966 values: self.values.into_boxed_slice(),
967 }
968 }
969}
970
971macro_rules! flag_methods {
972 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
973 impl Node {
974 $($(#[$doc])*
975 #[inline]
976 pub fn $getter(&self) -> bool {
977 (self.flags & (Flag::$id).mask()) != 0
978 })*
979 }
980 impl NodeBuilder {
981 $($(#[$doc])*
982 #[inline]
983 pub fn $getter(&self) -> bool {
984 (self.flags & (Flag::$id).mask()) != 0
985 }
986 #[inline]
987 pub fn $setter(&mut self) {
988 self.flags |= (Flag::$id).mask();
989 }
990 #[inline]
991 pub fn $clearer(&mut self) {
992 self.flags &= !((Flag::$id).mask());
993 })*
994 }
995 }
996}
997
998macro_rules! option_ref_type_getters {
999 ($(($method:ident, $type:ty, $variant:ident)),+) => {
1000 impl PropertyIndices {
1001 $(fn $method<'a>(&self, values: &'a [PropertyValue], id: PropertyId) -> Option<&'a $type> {
1002 match self.get(values, id) {
1003 PropertyValue::None => None,
1004 PropertyValue::$variant(value) => Some(value),
1005 _ => unexpected_property_type(),
1006 }
1007 })*
1008 }
1009 }
1010}
1011
1012macro_rules! slice_type_getters {
1013 ($(($method:ident, $type:ty, $variant:ident)),+) => {
1014 impl PropertyIndices {
1015 $(fn $method<'a>(&self, values: &'a [PropertyValue], id: PropertyId) -> &'a [$type] {
1016 match self.get(values, id) {
1017 PropertyValue::None => &[],
1018 PropertyValue::$variant(value) => value,
1019 _ => unexpected_property_type(),
1020 }
1021 })*
1022 }
1023 }
1024}
1025
1026macro_rules! copy_type_getters {
1027 ($(($method:ident, $type:ty, $variant:ident)),+) => {
1028 impl PropertyIndices {
1029 $(fn $method(&self, values: &[PropertyValue], id: PropertyId) -> Option<$type> {
1030 match self.get(values, id) {
1031 PropertyValue::None => None,
1032 PropertyValue::$variant(value) => Some(*value),
1033 _ => unexpected_property_type(),
1034 }
1035 })*
1036 }
1037 }
1038}
1039
1040macro_rules! box_type_setters {
1041 ($(($method:ident, $type:ty, $variant:ident)),+) => {
1042 impl NodeBuilder {
1043 $(fn $method(&mut self, id: PropertyId, value: impl Into<Box<$type>>) {
1044 self.properties.set(id, PropertyValue::$variant(value.into()));
1045 })*
1046 }
1047 }
1048}
1049
1050macro_rules! copy_type_setters {
1051 ($(($method:ident, $type:ty, $variant:ident)),+) => {
1052 impl NodeBuilder {
1053 $(fn $method(&mut self, id: PropertyId, value: $type) {
1054 self.properties.set(id, PropertyValue::$variant(value));
1055 })*
1056 }
1057 }
1058}
1059
1060macro_rules! vec_type_methods {
1061 ($(($type:ty, $variant:ident, $getter:ident, $setter:ident, $pusher:ident)),+) => {
1062 $(slice_type_getters! {
1063 ($getter, $type, $variant)
1064 })*
1065 impl NodeBuilder {
1066 $(fn $setter(&mut self, id: PropertyId, value: impl Into<Vec<$type>>) {
1067 self.properties.set(id, PropertyValue::$variant(value.into()));
1068 }
1069 fn $pusher(&mut self, id: PropertyId, item: $type) {
1070 match self.properties.get_mut(id, PropertyValue::$variant(Vec::new())) {
1071 PropertyValue::$variant(v) => {
1072 v.push(item);
1073 }
1074 _ => unexpected_property_type(),
1075 }
1076 })*
1077 }
1078 }
1079}
1080
1081macro_rules! property_methods {
1082 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $type_getter:ident, $getter_result:ty, $setter:ident, $type_setter:ident, $setter_param:ty, $clearer:ident)),+) => {
1083 impl Node {
1084 $($(#[$doc])*
1085 #[inline]
1086 pub fn $getter(&self) -> $getter_result {
1087 self.properties.indices.$type_getter(&self.properties.values, PropertyId::$id)
1088 })*
1089 }
1090 impl NodeBuilder {
1091 $($(#[$doc])*
1092 #[inline]
1093 pub fn $getter(&self) -> $getter_result {
1094 self.properties.indices.$type_getter(&self.properties.values, PropertyId::$id)
1095 }
1096 #[inline]
1097 pub fn $setter(&mut self, value: $setter_param) {
1098 self.$type_setter(PropertyId::$id, value);
1099 }
1100 #[inline]
1101 pub fn $clearer(&mut self) {
1102 self.properties.clear(PropertyId::$id);
1103 })*
1104 }
1105 }
1106}
1107
1108macro_rules! vec_property_methods {
1109 ($($(#[$doc:meta])* ($id:ident, $item_type:ty, $getter:ident, $type_getter:ident, $setter:ident, $type_setter:ident, $pusher:ident, $type_pusher:ident, $clearer:ident)),+) => {
1110 $(property_methods! {
1111 $(#[$doc])*
1112 ($id, $getter, $type_getter, &[$item_type], $setter, $type_setter, impl Into<Vec<$item_type>>, $clearer)
1113 }
1114 impl NodeBuilder {
1115 #[inline]
1116 pub fn $pusher(&mut self, item: $item_type) {
1117 self.$type_pusher(PropertyId::$id, item);
1118 }
1119 })*
1120 }
1121}
1122
1123macro_rules! node_id_vec_property_methods {
1124 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $pusher:ident, $clearer:ident)),+) => {
1125 $(vec_property_methods! {
1126 $(#[$doc])*
1127 ($id, NodeId, $getter, get_node_id_vec, $setter, set_node_id_vec, $pusher, push_to_node_id_vec, $clearer)
1128 })*
1129 }
1130}
1131
1132macro_rules! node_id_property_methods {
1133 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1134 $(property_methods! {
1135 $(#[$doc])*
1136 ($id, $getter, get_node_id_property, Option<NodeId>, $setter, set_node_id_property, NodeId, $clearer)
1137 })*
1138 }
1139}
1140
1141macro_rules! string_property_methods {
1142 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1143 $(property_methods! {
1144 $(#[$doc])*
1145 ($id, $getter, get_string_property, Option<&str>, $setter, set_string_property, impl Into<Box<str>>, $clearer)
1146 })*
1147 }
1148}
1149
1150macro_rules! f64_property_methods {
1151 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1152 $(property_methods! {
1153 $(#[$doc])*
1154 ($id, $getter, get_f64_property, Option<f64>, $setter, set_f64_property, f64, $clearer)
1155 })*
1156 }
1157}
1158
1159macro_rules! usize_property_methods {
1160 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1161 $(property_methods! {
1162 $(#[$doc])*
1163 ($id, $getter, get_usize_property, Option<usize>, $setter, set_usize_property, usize, $clearer)
1164 })*
1165 }
1166}
1167
1168macro_rules! color_property_methods {
1169 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1170 $(property_methods! {
1171 $(#[$doc])*
1172 ($id, $getter, get_color_property, Option<u32>, $setter, set_color_property, u32, $clearer)
1173 })*
1174 }
1175}
1176
1177macro_rules! text_decoration_property_methods {
1178 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1179 $(property_methods! {
1180 $(#[$doc])*
1181 ($id, $getter, get_text_decoration_property, Option<TextDecoration>, $setter, set_text_decoration_property, TextDecoration, $clearer)
1182 })*
1183 }
1184}
1185
1186macro_rules! length_slice_property_methods {
1187 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1188 $(property_methods! {
1189 $(#[$doc])*
1190 ($id, $getter, get_length_slice_property, &[u8], $setter, set_length_slice_property, impl Into<Box<[u8]>>, $clearer)
1191 })*
1192 }
1193}
1194
1195macro_rules! coord_slice_property_methods {
1196 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1197 $(property_methods! {
1198 $(#[$doc])*
1199 ($id, $getter, get_coord_slice_property, Option<&[f32]>, $setter, set_coord_slice_property, impl Into<Box<[f32]>>, $clearer)
1200 })*
1201 }
1202}
1203
1204macro_rules! bool_property_methods {
1205 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1206 $(property_methods! {
1207 $(#[$doc])*
1208 ($id, $getter, get_bool_property, Option<bool>, $setter, set_bool_property, bool, $clearer)
1209 })*
1210 }
1211}
1212
1213macro_rules! unique_enum_property_methods {
1214 ($($(#[$doc:meta])* ($id:ident, $getter:ident, $setter:ident, $clearer:ident)),+) => {
1215 impl Node {
1216 $($(#[$doc])*
1217 #[inline]
1218 pub fn $getter(&self) -> Option<$id> {
1219 match self.properties.indices.get(&self.properties.values, PropertyId::$id) {
1220 PropertyValue::None => None,
1221 PropertyValue::$id(value) => Some(*value),
1222 _ => unexpected_property_type(),
1223 }
1224 })*
1225 }
1226 impl NodeBuilder {
1227 $($(#[$doc])*
1228 #[inline]
1229 pub fn $getter(&self) -> Option<$id> {
1230 match self.properties.indices.get(&self.properties.values, PropertyId::$id) {
1231 PropertyValue::None => None,
1232 PropertyValue::$id(value) => Some(*value),
1233 _ => unexpected_property_type(),
1234 }
1235 }
1236 #[inline]
1237 pub fn $setter(&mut self, value: $id) {
1238 self.properties.set(PropertyId::$id, PropertyValue::$id(value));
1239 }
1240 #[inline]
1241 pub fn $clearer(&mut self) {
1242 self.properties.clear(PropertyId::$id);
1243 })*
1244 }
1245 }
1246}
1247
1248impl NodeBuilder {
1249 #[inline]
1250 pub fn new(role: Role) -> Self {
1251 Self {
1252 role,
1253 ..Default::default()
1254 }
1255 }
1256
1257 pub fn build(self) -> Node {
1258 Node {
1259 role: self.role,
1260 actions: self.actions,
1261 flags: self.flags,
1262 properties: self.properties.build(),
1263 }
1264 }
1265}
1266
1267impl Node {
1268 #[inline]
1269 pub fn role(&self) -> Role {
1270 self.role
1271 }
1272}
1273
1274impl NodeBuilder {
1275 #[inline]
1276 pub fn role(&self) -> Role {
1277 self.role
1278 }
1279 #[inline]
1280 pub fn set_role(&mut self, value: Role) {
1281 self.role = value;
1282 }
1283}
1284
1285impl Node {
1286 #[inline]
1287 pub fn supports_action(&self, action: Action) -> bool {
1288 (self.actions & action.mask()) != 0
1289 }
1290}
1291
1292impl NodeBuilder {
1293 #[inline]
1294 pub fn supports_action(&self, action: Action) -> bool {
1295 (self.actions & action.mask()) != 0
1296 }
1297 #[inline]
1298 pub fn add_action(&mut self, action: Action) {
1299 self.actions |= action.mask();
1300 }
1301 #[inline]
1302 pub fn remove_action(&mut self, action: Action) {
1303 self.actions &= !(action.mask());
1304 }
1305 #[inline]
1306 pub fn clear_actions(&mut self) {
1307 self.actions = 0;
1308 }
1309}
1310
1311flag_methods! {
1312 (Hovered, is_hovered, set_hovered, clear_hovered),
1313 (Hidden, is_hidden, set_hidden, clear_hidden),
1316 (Linked, is_linked, set_linked, clear_linked),
1317 (Multiselectable, is_multiselectable, set_multiselectable, clear_multiselectable),
1318 (Required, is_required, set_required, clear_required),
1319 (Visited, is_visited, set_visited, clear_visited),
1320 (Busy, is_busy, set_busy, clear_busy),
1321 (LiveAtomic, is_live_atomic, set_live_atomic, clear_live_atomic),
1322 (Modal, is_modal, set_modal, clear_modal),
1324 (TouchTransparent, is_touch_transparent, set_touch_transparent, clear_touch_transparent),
1328 (ReadOnly, is_read_only, set_read_only, clear_read_only),
1330 (Disabled, is_disabled, set_disabled, clear_disabled),
1332 (Bold, is_bold, set_bold, clear_bold),
1333 (Italic, is_italic, set_italic, clear_italic),
1334 (ClipsChildren, clips_children, set_clips_children, clear_clips_children),
1337 (IsLineBreakingObject, is_line_breaking_object, set_is_line_breaking_object, clear_is_line_breaking_object),
1340 (IsPageBreakingObject, is_page_breaking_object, set_is_page_breaking_object, clear_is_page_breaking_object),
1342 (IsSpellingError, is_spelling_error, set_is_spelling_error, clear_is_spelling_error),
1343 (IsGrammarError, is_grammar_error, set_is_grammar_error, clear_is_grammar_error),
1344 (IsSearchMatch, is_search_match, set_is_search_match, clear_is_search_match),
1345 (IsSuggestion, is_suggestion, set_is_suggestion, clear_is_suggestion)
1346}
1347
1348option_ref_type_getters! {
1349 (get_affine_property, Affine, Affine),
1350 (get_string_property, str, String),
1351 (get_coord_slice_property, [f32], CoordSlice),
1352 (get_text_selection_property, TextSelection, TextSelection)
1353}
1354
1355slice_type_getters! {
1356 (get_length_slice_property, u8, LengthSlice)
1357}
1358
1359copy_type_getters! {
1360 (get_rect_property, Rect, Rect),
1361 (get_node_id_property, NodeId, NodeId),
1362 (get_f64_property, f64, F64),
1363 (get_usize_property, usize, Usize),
1364 (get_color_property, u32, Color),
1365 (get_text_decoration_property, TextDecoration, TextDecoration),
1366 (get_bool_property, bool, Bool)
1367}
1368
1369box_type_setters! {
1370 (set_affine_property, Affine, Affine),
1371 (set_string_property, str, String),
1372 (set_length_slice_property, [u8], LengthSlice),
1373 (set_coord_slice_property, [f32], CoordSlice),
1374 (set_text_selection_property, TextSelection, TextSelection)
1375}
1376
1377copy_type_setters! {
1378 (set_rect_property, Rect, Rect),
1379 (set_node_id_property, NodeId, NodeId),
1380 (set_f64_property, f64, F64),
1381 (set_usize_property, usize, Usize),
1382 (set_color_property, u32, Color),
1383 (set_text_decoration_property, TextDecoration, TextDecoration),
1384 (set_bool_property, bool, Bool)
1385}
1386
1387vec_type_methods! {
1388 (NodeId, NodeIdVec, get_node_id_vec, set_node_id_vec, push_to_node_id_vec),
1389 (CustomAction, CustomActionVec, get_custom_action_vec, set_custom_action_vec, push_to_custom_action_vec)
1390}
1391
1392node_id_vec_property_methods! {
1393 (Children, children, set_children, push_child, clear_children),
1394 (Controls, controls, set_controls, push_controlled, clear_controls),
1395 (Details, details, set_details, push_detail, clear_details),
1396 (DescribedBy, described_by, set_described_by, push_described_by, clear_described_by),
1397 (FlowTo, flow_to, set_flow_to, push_flow_to, clear_flow_to),
1398 (LabelledBy, labelled_by, set_labelled_by, push_labelled_by, clear_labelled_by),
1399 (Owns, owns, set_owns, push_owned, clear_owns),
1405 (RadioGroup, radio_group, set_radio_group, push_to_radio_group, clear_radio_group)
1408}
1409
1410node_id_property_methods! {
1411 (ActiveDescendant, active_descendant, set_active_descendant, clear_active_descendant),
1412 (ErrorMessage, error_message, set_error_message, clear_error_message),
1413 (InPageLinkTarget, in_page_link_target, set_in_page_link_target, clear_in_page_link_target),
1414 (MemberOf, member_of, set_member_of, clear_member_of),
1415 (NextOnLine, next_on_line, set_next_on_line, clear_next_on_line),
1416 (PreviousOnLine, previous_on_line, set_previous_on_line, clear_previous_on_line),
1417 (PopupFor, popup_for, set_popup_for, clear_popup_for)
1418}
1419
1420string_property_methods! {
1421 (Name, name, set_name, clear_name),
1422 (Description, description, set_description, clear_description),
1423 (Value, value, set_value, clear_value),
1424 (AccessKey, access_key, set_access_key, clear_access_key),
1432 (AuthorId, author_id, set_author_id, clear_author_id),
1435 (ClassName, class_name, set_class_name, clear_class_name),
1436 (FontFamily, font_family, set_font_family, clear_font_family),
1438 (HtmlTag, html_tag, set_html_tag, clear_html_tag),
1439 (InnerHtml, inner_html, set_inner_html, clear_inner_html),
1442 (KeyboardShortcut, keyboard_shortcut, set_keyboard_shortcut, clear_keyboard_shortcut),
1446 (Language, language, set_language, clear_language),
1448 (Placeholder, placeholder, set_placeholder, clear_placeholder),
1453 (RoleDescription, role_description, set_role_description, clear_role_description),
1457 (StateDescription, state_description, set_state_description, clear_state_description),
1462 (Tooltip, tooltip, set_tooltip, clear_tooltip),
1467 (Url, url, set_url, clear_url),
1468 (RowIndexText, row_index_text, set_row_index_text, clear_row_index_text),
1469 (ColumnIndexText, column_index_text, set_column_index_text, clear_column_index_text)
1470}
1471
1472f64_property_methods! {
1473 (ScrollX, scroll_x, set_scroll_x, clear_scroll_x),
1474 (ScrollXMin, scroll_x_min, set_scroll_x_min, clear_scroll_x_min),
1475 (ScrollXMax, scroll_x_max, set_scroll_x_max, clear_scroll_x_max),
1476 (ScrollY, scroll_y, set_scroll_y, clear_scroll_y),
1477 (ScrollYMin, scroll_y_min, set_scroll_y_min, clear_scroll_y_min),
1478 (ScrollYMax, scroll_y_max, set_scroll_y_max, clear_scroll_y_max),
1479 (NumericValue, numeric_value, set_numeric_value, clear_numeric_value),
1480 (MinNumericValue, min_numeric_value, set_min_numeric_value, clear_min_numeric_value),
1481 (MaxNumericValue, max_numeric_value, set_max_numeric_value, clear_max_numeric_value),
1482 (NumericValueStep, numeric_value_step, set_numeric_value_step, clear_numeric_value_step),
1483 (NumericValueJump, numeric_value_jump, set_numeric_value_jump, clear_numeric_value_jump),
1484 (FontSize, font_size, set_font_size, clear_font_size),
1486 (FontWeight, font_weight, set_font_weight, clear_font_weight)
1489}
1490
1491usize_property_methods! {
1492 (RowCount, row_count, set_row_count, clear_row_count),
1493 (ColumnCount, column_count, set_column_count, clear_column_count),
1494 (RowIndex, row_index, set_row_index, clear_row_index),
1495 (ColumnIndex, column_index, set_column_index, clear_column_index),
1496 (RowSpan, row_span, set_row_span, clear_row_span),
1497 (ColumnSpan, column_span, set_column_span, clear_column_span),
1498 (Level, level, set_level, clear_level),
1499 (SizeOfSet, size_of_set, set_size_of_set, clear_size_of_set),
1500 (PositionInSet, position_in_set, set_position_in_set, clear_position_in_set)
1501}
1502
1503color_property_methods! {
1504 (ColorValue, color_value, set_color_value, clear_color_value),
1506 (BackgroundColor, background_color, set_background_color, clear_background_color),
1508 (ForegroundColor, foreground_color, set_foreground_color, clear_foreground_color)
1510}
1511
1512text_decoration_property_methods! {
1513 (Overline, overline, set_overline, clear_overline),
1514 (Strikethrough, strikethrough, set_strikethrough, clear_strikethrough),
1515 (Underline, underline, set_underline, clear_underline)
1516}
1517
1518length_slice_property_methods! {
1519 (CharacterLengths, character_lengths, set_character_lengths, clear_character_lengths),
1538
1539 (WordLengths, word_lengths, set_word_lengths, clear_word_lengths)
1562}
1563
1564coord_slice_property_methods! {
1565 (CharacterPositions, character_positions, set_character_positions, clear_character_positions),
1582
1583 (CharacterWidths, character_widths, set_character_widths, clear_character_widths)
1602}
1603
1604bool_property_methods! {
1605 (Expanded, is_expanded, set_expanded, clear_expanded),
1610
1611 (Selected, is_selected, set_selected, clear_selected)
1621}
1622
1623unique_enum_property_methods! {
1624 (Invalid, invalid, set_invalid, clear_invalid),
1625 (Toggled, toggled, set_toggled, clear_toggled),
1626 (Live, live, set_live, clear_live),
1627 (DefaultActionVerb, default_action_verb, set_default_action_verb, clear_default_action_verb),
1628 (TextDirection, text_direction, set_text_direction, clear_text_direction),
1629 (Orientation, orientation, set_orientation, clear_orientation),
1630 (SortDirection, sort_direction, set_sort_direction, clear_sort_direction),
1631 (AriaCurrent, aria_current, set_aria_current, clear_aria_current),
1632 (AutoComplete, auto_complete, set_auto_complete, clear_auto_complete),
1633 (HasPopup, has_popup, set_has_popup, clear_has_popup),
1634 (ListStyle, list_style, set_list_style, clear_list_style),
1636 (TextAlign, text_align, set_text_align, clear_text_align),
1637 (VerticalOffset, vertical_offset, set_vertical_offset, clear_vertical_offset)
1638}
1639
1640property_methods! {
1641 (Transform, transform, get_affine_property, Option<&Affine>, set_transform, set_affine_property, impl Into<Box<Affine>>, clear_transform),
1654
1655 (Bounds, bounds, get_rect_property, Option<Rect>, set_bounds, set_rect_property, Rect, clear_bounds),
1666
1667 (TextSelection, text_selection, get_text_selection_property, Option<&TextSelection>, set_text_selection, set_text_selection_property, impl Into<Box<TextSelection>>, clear_text_selection)
1668}
1669
1670vec_property_methods! {
1671 (CustomActions, CustomAction, custom_actions, get_custom_action_vec, set_custom_actions, set_custom_action_vec, push_custom_action, push_to_custom_action_vec, clear_custom_actions)
1672}
1673
1674#[cfg(feature = "serde")]
1675macro_rules! serialize_property {
1676 ($self:ident, $map:ident, $index:ident, $id:ident, { $($variant:ident),+ }) => {
1677 match &$self.values[$index as usize] {
1678 PropertyValue::None => (),
1679 $(PropertyValue::$variant(value) => {
1680 $map.serialize_entry(&$id, &value)?;
1681 })*
1682 }
1683 }
1684}
1685
1686#[cfg(feature = "serde")]
1687macro_rules! deserialize_property {
1688 ($builder:ident, $map:ident, $key:ident, { $($type:ident { $($id:ident),+ }),+ }) => {
1689 match $key {
1690 $($(PropertyId::$id => {
1691 let value = $map.next_value()?;
1692 $builder.set(PropertyId::$id, PropertyValue::$type(value));
1693 })*)*
1694 PropertyId::Unset => {
1695 let _ = $map.next_value::<IgnoredAny>()?;
1696 }
1697 }
1698 }
1699}
1700
1701#[cfg(feature = "serde")]
1702impl Serialize for Properties {
1703 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1704 where
1705 S: Serializer,
1706 {
1707 let mut len = 0;
1708 for value in &*self.values {
1709 if !matches!(*value, PropertyValue::None) {
1710 len += 1;
1711 }
1712 }
1713 let mut map = serializer.serialize_map(Some(len))?;
1714 for (id, index) in self.indices.0.iter().copied().enumerate() {
1715 if index == PropertyId::Unset as u8 {
1716 continue;
1717 }
1718 let id = PropertyId::n(id as _).unwrap();
1719 serialize_property!(self, map, index, id, {
1720 NodeIdVec,
1721 NodeId,
1722 String,
1723 F64,
1724 Usize,
1725 Color,
1726 TextDecoration,
1727 LengthSlice,
1728 CoordSlice,
1729 Bool,
1730 Invalid,
1731 Toggled,
1732 Live,
1733 DefaultActionVerb,
1734 TextDirection,
1735 Orientation,
1736 SortDirection,
1737 AriaCurrent,
1738 AutoComplete,
1739 HasPopup,
1740 ListStyle,
1741 TextAlign,
1742 VerticalOffset,
1743 Affine,
1744 Rect,
1745 TextSelection,
1746 CustomActionVec
1747 });
1748 }
1749 map.end()
1750 }
1751}
1752
1753#[cfg(feature = "serde")]
1754struct PropertiesVisitor;
1755
1756#[cfg(feature = "serde")]
1757impl<'de> Visitor<'de> for PropertiesVisitor {
1758 type Value = Properties;
1759
1760 #[inline]
1761 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1762 formatter.write_str("property map")
1763 }
1764
1765 fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
1766 where
1767 V: MapAccess<'de>,
1768 {
1769 let mut builder = PropertiesBuilder::default();
1770 while let Some(id) = map.next_key()? {
1771 deserialize_property!(builder, map, id, {
1772 NodeIdVec {
1773 Children,
1774 Controls,
1775 Details,
1776 DescribedBy,
1777 FlowTo,
1778 LabelledBy,
1779 Owns,
1780 RadioGroup
1781 },
1782 NodeId {
1783 ActiveDescendant,
1784 ErrorMessage,
1785 InPageLinkTarget,
1786 MemberOf,
1787 NextOnLine,
1788 PreviousOnLine,
1789 PopupFor
1790 },
1791 String {
1792 Name,
1793 Description,
1794 Value,
1795 AccessKey,
1796 AuthorId,
1797 ClassName,
1798 FontFamily,
1799 HtmlTag,
1800 InnerHtml,
1801 KeyboardShortcut,
1802 Language,
1803 Placeholder,
1804 RoleDescription,
1805 StateDescription,
1806 Tooltip,
1807 Url,
1808 RowIndexText,
1809 ColumnIndexText
1810 },
1811 F64 {
1812 ScrollX,
1813 ScrollXMin,
1814 ScrollXMax,
1815 ScrollY,
1816 ScrollYMin,
1817 ScrollYMax,
1818 NumericValue,
1819 MinNumericValue,
1820 MaxNumericValue,
1821 NumericValueStep,
1822 NumericValueJump,
1823 FontSize,
1824 FontWeight
1825 },
1826 Usize {
1827 RowCount,
1828 ColumnCount,
1829 RowIndex,
1830 ColumnIndex,
1831 RowSpan,
1832 ColumnSpan,
1833 Level,
1834 SizeOfSet,
1835 PositionInSet
1836 },
1837 Color {
1838 ColorValue,
1839 BackgroundColor,
1840 ForegroundColor
1841 },
1842 TextDecoration {
1843 Overline,
1844 Strikethrough,
1845 Underline
1846 },
1847 LengthSlice {
1848 CharacterLengths,
1849 WordLengths
1850 },
1851 CoordSlice {
1852 CharacterPositions,
1853 CharacterWidths
1854 },
1855 Bool {
1856 Expanded,
1857 Selected
1858 },
1859 Invalid { Invalid },
1860 Toggled { Toggled },
1861 Live { Live },
1862 DefaultActionVerb { DefaultActionVerb },
1863 TextDirection { TextDirection },
1864 Orientation { Orientation },
1865 SortDirection { SortDirection },
1866 AriaCurrent { AriaCurrent },
1867 AutoComplete { AutoComplete },
1868 HasPopup { HasPopup },
1869 ListStyle { ListStyle },
1870 TextAlign { TextAlign },
1871 VerticalOffset { VerticalOffset },
1872 Affine { Transform },
1873 Rect { Bounds },
1874 TextSelection { TextSelection },
1875 CustomActionVec { CustomActions }
1876 });
1877 }
1878
1879 Ok(builder.build())
1880 }
1881}
1882
1883#[cfg(feature = "serde")]
1884impl<'de> Deserialize<'de> for Properties {
1885 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1886 where
1887 D: Deserializer<'de>,
1888 {
1889 deserializer.deserialize_map(PropertiesVisitor)
1890 }
1891}
1892
1893#[cfg(feature = "schemars")]
1894macro_rules! add_schema_property {
1895 ($gen:ident, $properties:ident, $enum_value:expr, $type:ty) => {{
1896 let name = format!("{:?}", $enum_value);
1897 let name = name[..1].to_ascii_lowercase() + &name[1..];
1898 let subschema = $gen.subschema_for::<$type>();
1899 $properties.insert(name, subschema);
1900 }};
1901}
1902
1903#[cfg(feature = "schemars")]
1904macro_rules! add_properties_to_schema {
1905 ($gen:ident, $properties:ident, { $($type:ty { $($id:ident),+ }),+ }) => {
1906 $($(add_schema_property!($gen, $properties, PropertyId::$id, $type);)*)*
1907 }
1908}
1909
1910#[cfg(feature = "schemars")]
1911impl JsonSchema for Properties {
1912 #[inline]
1913 fn schema_name() -> String {
1914 "Properties".into()
1915 }
1916
1917 fn json_schema(gen: &mut SchemaGenerator) -> Schema {
1918 let mut properties = SchemaMap::<String, Schema>::new();
1919 add_properties_to_schema!(gen, properties, {
1920 Vec<NodeId> {
1921 Children,
1922 Controls,
1923 Details,
1924 DescribedBy,
1925 FlowTo,
1926 LabelledBy,
1927 Owns,
1928 RadioGroup
1929 },
1930 NodeId {
1931 ActiveDescendant,
1932 ErrorMessage,
1933 InPageLinkTarget,
1934 MemberOf,
1935 NextOnLine,
1936 PreviousOnLine,
1937 PopupFor
1938 },
1939 Box<str> {
1940 Name,
1941 Description,
1942 Value,
1943 AccessKey,
1944 AuthorId,
1945 ClassName,
1946 FontFamily,
1947 HtmlTag,
1948 InnerHtml,
1949 KeyboardShortcut,
1950 Language,
1951 Placeholder,
1952 RoleDescription,
1953 StateDescription,
1954 Tooltip,
1955 Url,
1956 RowIndexText,
1957 ColumnIndexText
1958 },
1959 f64 {
1960 ScrollX,
1961 ScrollXMin,
1962 ScrollXMax,
1963 ScrollY,
1964 ScrollYMin,
1965 ScrollYMax,
1966 NumericValue,
1967 MinNumericValue,
1968 MaxNumericValue,
1969 NumericValueStep,
1970 NumericValueJump,
1971 FontSize,
1972 FontWeight
1973 },
1974 usize {
1975 RowCount,
1976 ColumnCount,
1977 RowIndex,
1978 ColumnIndex,
1979 RowSpan,
1980 ColumnSpan,
1981 Level,
1982 SizeOfSet,
1983 PositionInSet
1984 },
1985 u32 {
1986 ColorValue,
1987 BackgroundColor,
1988 ForegroundColor
1989 },
1990 TextDecoration {
1991 Overline,
1992 Strikethrough,
1993 Underline
1994 },
1995 Box<[u8]> {
1996 CharacterLengths,
1997 WordLengths
1998 },
1999 Box<[f32]> {
2000 CharacterPositions,
2001 CharacterWidths
2002 },
2003 bool {
2004 Expanded,
2005 Selected
2006 },
2007 Invalid { Invalid },
2008 Toggled { Toggled },
2009 Live { Live },
2010 DefaultActionVerb { DefaultActionVerb },
2011 TextDirection { TextDirection },
2012 Orientation { Orientation },
2013 SortDirection { SortDirection },
2014 AriaCurrent { AriaCurrent },
2015 AutoComplete { AutoComplete },
2016 HasPopup { HasPopup },
2017 ListStyle { ListStyle },
2018 TextAlign { TextAlign },
2019 VerticalOffset { VerticalOffset },
2020 Affine { Transform },
2021 Rect { Bounds },
2022 TextSelection { TextSelection },
2023 Vec<CustomAction> { CustomActions }
2024 });
2025 SchemaObject {
2026 instance_type: Some(InstanceType::Object.into()),
2027 object: Some(
2028 ObjectValidation {
2029 properties,
2030 ..Default::default()
2031 }
2032 .into(),
2033 ),
2034 ..Default::default()
2035 }
2036 .into()
2037 }
2038}
2039
2040#[derive(Clone, Debug, PartialEq, Eq)]
2043#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2044#[cfg_attr(feature = "schemars", derive(JsonSchema))]
2045#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
2046#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2047pub struct Tree {
2048 pub root: NodeId,
2050 pub app_name: Option<String>,
2052 pub toolkit_name: Option<String>,
2054 pub toolkit_version: Option<String>,
2056}
2057
2058impl Tree {
2059 #[inline]
2060 pub fn new(root: NodeId) -> Tree {
2061 Tree {
2062 root,
2063 app_name: None,
2064 toolkit_name: None,
2065 toolkit_version: None,
2066 }
2067 }
2068}
2069
2070#[derive(Clone, Debug, PartialEq)]
2082#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2083#[cfg_attr(feature = "schemars", derive(JsonSchema))]
2084#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
2085#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2086pub struct TreeUpdate {
2087 pub nodes: Vec<(NodeId, Node)>,
2108
2109 pub tree: Option<Tree>,
2114
2115 pub focus: NodeId,
2121}
2122
2123#[derive(Clone, Debug, PartialEq)]
2124#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2125#[cfg_attr(feature = "schemars", derive(JsonSchema))]
2126#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2127#[repr(C)]
2128pub enum ActionData {
2129 CustomAction(i32),
2130 Value(Box<str>),
2131 NumericValue(f64),
2132 ScrollTargetRect(Rect),
2135 ScrollToPoint(Point),
2138 SetScrollOffset(Point),
2141 SetTextSelection(TextSelection),
2142}
2143
2144#[derive(Clone, Debug, PartialEq)]
2145#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2146#[cfg_attr(feature = "schemars", derive(JsonSchema))]
2147#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
2148#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
2149pub struct ActionRequest {
2150 pub action: Action,
2151 pub target: NodeId,
2152 pub data: Option<ActionData>,
2153}
2154
2155pub trait ActivationHandler {
2157 fn request_initial_tree(&mut self) -> Option<TreeUpdate>;
2179}
2180
2181pub trait ActionHandler {
2183 fn do_action(&mut self, request: ActionRequest);
2193}
2194
2195pub trait DeactivationHandler {
2197 fn deactivate_accessibility(&mut self);
2205}