fltk_accesskit/
accessible.rs

1use accesskit::{Action, Affine, Node, NodeId, Rect, Role, TextPosition, TextSelection, Toggled};
2use fltk::{
3    button, enums::*, frame, input, menu, output, prelude::*, text, utils, widget, window, *,
4};
5
6pub trait Accessible {
7    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node);
8}
9
10fn node_widget_common(builder: &mut Node, wid: &impl WidgetExt, children: &[NodeId]) -> NodeId {
11    let node_id = NodeId(wid.as_widget_ptr() as usize as u64);
12    if wid.parent().is_some() && wid.as_window().is_none() {
13        builder.set_bounds(Rect {
14            x0: wid.x() as f64,
15            y0: wid.y() as f64,
16            x1: (wid.w() + wid.x()) as f64,
17            y1: (wid.h() + wid.y()) as f64,
18        });
19    } else {
20        builder.set_bounds(Rect {
21            x0: 0.0,
22            y0: 0.0,
23            x1: wid.w() as f64,
24            y1: wid.h() as f64,
25        });
26    }
27    builder.set_label(&*wid.label());
28    if wid.trigger().contains(CallbackTrigger::Release) {
29        builder.add_action(Action::Click);
30    }
31    for c in children {
32        builder.push_child(*c);
33    }
34    node_id
35}
36
37/// Try to build an accessibility node for a given widget pointer.
38/// Returns None for unsupported widget types. Window nodes are handled separately.
39pub fn node_for_widget(w: &widget::Widget, children: &[NodeId]) -> Option<(NodeId, Node)> {
40    let ptr = w.as_widget_ptr();
41    macro_rules! try_type {
42        ($t:ty) => {
43            if utils::is_ptr_of::<$t>(ptr) {
44                let typed = unsafe { <$t>::from_widget_ptr(ptr as _) };
45                let (id, node) = typed.make_node(children);
46                return Some((id, node));
47            }
48        };
49    }
50
51    // Buttons (more specific first)
52    try_type!(button::RadioButton);
53    try_type!(button::RadioRoundButton);
54    try_type!(button::CheckButton);
55    try_type!(button::ToggleButton);
56    try_type!(button::Button);
57
58    // Inputs/Outputs/Text
59    try_type!(input::IntInput);
60    try_type!(input::FloatInput);
61    try_type!(input::MultilineInput);
62    try_type!(input::Input);
63    try_type!(text::TextEditor);
64    try_type!(output::MultilineOutput);
65    try_type!(output::Output);
66    try_type!(text::TextDisplay);
67
68    // Frames (image/label)
69    try_type!(frame::Frame);
70
71    // Windows (non-root windows will be discovered)
72    try_type!(window::Window);
73
74    None
75}
76
77/// Build one or more nodes for a widget. Some complex widgets (menus, choices)
78/// expand to multiple nodes to expose their items.
79pub fn nodes_for_widget(w: &widget::Widget) -> Vec<(NodeId, Node)> {
80    let mut out = Vec::new();
81    let ptr = w.as_widget_ptr();
82
83    // Choice -> ComboBox with options
84    if utils::is_ptr_of::<menu::Choice>(ptr) {
85        let choice = unsafe { menu::Choice::from_widget_ptr(ptr as _) };
86        let mut parent = Node::new(Role::ComboBox);
87        if let Some(val) = choice.choice() {
88            parent.set_value(&*val);
89        }
90        parent.add_action(Action::Focus);
91        parent.add_action(Action::SetValue);
92        parent.set_has_popup(accesskit::HasPopup::Menu);
93        let parent_id = node_widget_common(&mut parent, &choice, &[]);
94
95        let total = choice.size();
96        for i in 0..choice.size() {
97            if let Some(item) = choice.at(i) {
98                let mut node = Node::new(Role::ListBoxOption);
99                if let Some(lbl) = item.label() {
100                    node.set_label(&*lbl);
101                }
102                if i == choice.value() {
103                    node.set_selected(true);
104                }
105                node.set_position_in_set((i + 1) as usize);
106                node.set_size_of_set(total as usize);
107                let item_id = NodeId(unsafe { item.as_ptr() } as usize as u64);
108                parent.push_child(item_id);
109                out.push((item_id, node));
110            }
111        }
112
113        parent.set_size_of_set(total as usize);
114        out.push((parent_id, parent));
115        return out;
116    }
117
118    // MenuBar -> MenuBar with menu/menuitems
119    if utils::is_ptr_of::<menu::MenuBar>(ptr) {
120        let bar = unsafe { menu::MenuBar::from_widget_ptr(ptr as _) };
121        let mut bar_node = Node::new(Role::MenuBar);
122        bar_node.add_action(Action::Focus);
123        let bar_id = node_widget_common(&mut bar_node, &bar, &[]);
124
125        for i in 0..bar.size() {
126            if let Some(item) = bar.at(i) {
127                if item.is_submenu() {
128                    // Submenu as Role::Menu
129                    let mut menu_node = Node::new(Role::Menu);
130                    if let Some(lbl) = item.label() {
131                        menu_node.set_label(&*lbl);
132                    }
133                    let menu_id = NodeId(unsafe { item.as_ptr() } as usize as u64);
134                    bar_node.push_child(menu_id);
135
136                    // Add submenu items
137                    let count = item.size();
138                    for j in 0..count {
139                        if let Some(sub) = item.at(j) {
140                            let mut sub_node = Node::new(Role::MenuItem);
141                            if let Some(lbl) = sub.label() {
142                                sub_node.set_label(&*lbl);
143                            }
144                            if (sub.is_radio() || sub.is_checkbox()) && sub.value() {
145                                sub_node.set_selected(true);
146                            }
147                            let sub_id = NodeId(unsafe { sub.as_ptr() } as usize as u64);
148                            menu_node.push_child(sub_id);
149                            out.push((sub_id, sub_node));
150                        }
151                    }
152                    out.push((menu_id, menu_node));
153                } else {
154                    // Top-level item
155                    let mut node = Node::new(Role::MenuItem);
156                    if let Some(lbl) = item.label() {
157                        node.set_label(&*lbl);
158                    }
159                    if (item.is_radio() || item.is_checkbox()) && item.value() {
160                        node.set_selected(true);
161                    }
162                    let item_id = NodeId(unsafe { item.as_ptr() } as usize as u64);
163                    bar_node.push_child(item_id);
164                    out.push((item_id, node));
165                }
166            }
167        }
168        out.push((bar_id, bar_node));
169        return out;
170    }
171
172    // SysMenuBar -> MenuBar representation
173    if utils::is_ptr_of::<menu::SysMenuBar>(ptr) {
174        let bar = unsafe { menu::SysMenuBar::from_widget_ptr(ptr as _) };
175        let mut bar_node = Node::new(Role::MenuBar);
176        bar_node.add_action(Action::Focus);
177        let bar_id = node_widget_common(&mut bar_node, &bar, &[]);
178
179        for i in 0..bar.size() {
180            if let Some(item) = bar.at(i) {
181                if item.is_submenu() {
182                    let mut menu_node = Node::new(Role::Menu);
183                    if let Some(lbl) = item.label() {
184                        menu_node.set_label(&*lbl);
185                    }
186                    let menu_id = NodeId(unsafe { item.as_ptr() } as usize as u64);
187                    bar_node.push_child(menu_id);
188                    let count = item.size();
189                    for j in 0..count {
190                        if let Some(sub) = item.at(j) {
191                            let mut sub_node = Node::new(Role::MenuItem);
192                            if let Some(lbl) = sub.label() {
193                                sub_node.set_label(&*lbl);
194                            }
195                            if (sub.is_radio() || sub.is_checkbox()) && sub.value() {
196                                sub_node.set_selected(true);
197                            }
198                            let sub_id = NodeId(unsafe { sub.as_ptr() } as usize as u64);
199                            menu_node.push_child(sub_id);
200                            out.push((sub_id, sub_node));
201                        }
202                    }
203                    out.push((menu_id, menu_node));
204                } else {
205                    let mut node = Node::new(Role::MenuItem);
206                    if let Some(lbl) = item.label() {
207                        node.set_label(&*lbl);
208                    }
209                    if (item.is_radio() || item.is_checkbox()) && item.value() {
210                        node.set_selected(true);
211                    }
212                    let item_id = NodeId(unsafe { item.as_ptr() } as usize as u64);
213                    bar_node.push_child(item_id);
214                    out.push((item_id, node));
215                }
216            }
217        }
218        out.push((bar_id, bar_node));
219        return out;
220    }
221
222    // MenuButton -> Button with popup menu items
223    if utils::is_ptr_of::<menu::MenuButton>(ptr) {
224        let btn = unsafe { menu::MenuButton::from_widget_ptr(ptr as _) };
225        let mut btn_node = Node::new(Role::Button);
226        btn_node.add_action(Action::Focus);
227        btn_node.add_action(Action::Click);
228        btn_node.set_has_popup(accesskit::HasPopup::Menu);
229        btn_node.set_label(&*btn.label());
230        let btn_id = node_widget_common(&mut btn_node, &btn, &[]);
231
232        // Expose menu items as children
233        for i in 0..btn.size() {
234            if let Some(item) = btn.at(i) {
235                if item.is_submenu() {
236                    let mut menu_node = Node::new(Role::Menu);
237                    if let Some(lbl) = item.label() {
238                        menu_node.set_label(&*lbl);
239                    }
240                    let menu_id = NodeId(unsafe { item.as_ptr() } as usize as u64);
241                    btn_node.push_child(menu_id);
242                    let count = item.size();
243                    for j in 0..count {
244                        if let Some(sub) = item.at(j) {
245                            let mut sub_node = Node::new(Role::MenuItem);
246                            if let Some(lbl) = sub.label() {
247                                sub_node.set_label(&*lbl);
248                            }
249                            if (sub.is_radio() || sub.is_checkbox()) && sub.value() {
250                                sub_node.set_selected(true);
251                            }
252                            let sub_id = NodeId(unsafe { sub.as_ptr() } as usize as u64);
253                            menu_node.push_child(sub_id);
254                            out.push((sub_id, sub_node));
255                        }
256                    }
257                    out.push((menu_id, menu_node));
258                } else {
259                    let mut node = Node::new(Role::MenuItem);
260                    if let Some(lbl) = item.label() {
261                        node.set_label(&*lbl);
262                    }
263                    if (item.is_radio() || item.is_checkbox()) && item.value() {
264                        node.set_selected(true);
265                    }
266                    let item_id = NodeId(unsafe { item.as_ptr() } as usize as u64);
267                    btn_node.push_child(item_id);
268                    out.push((item_id, node));
269                }
270            }
271        }
272        out.push((btn_id, btn_node));
273        return out;
274    }
275
276    if let Some(n) = node_for_widget(w, &[]) {
277        out.push(n);
278    }
279    out
280}
281
282impl Accessible for button::Button {
283    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
284        let mut builder = Node::new(Role::Button);
285        builder.add_action(Action::Focus);
286        let id = node_widget_common(&mut builder, self, children);
287        (id, builder)
288    }
289}
290
291impl Accessible for button::RadioButton {
292    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
293        let mut builder = Node::new(Role::RadioButton);
294        builder.set_toggled(if self.value() {
295            Toggled::True
296        } else {
297            Toggled::False
298        });
299        builder.add_action(Action::Focus);
300        let id = node_widget_common(&mut builder, self, children);
301        (id, builder)
302    }
303}
304
305impl Accessible for button::RadioRoundButton {
306    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
307        let mut builder = Node::new(Role::RadioButton);
308        builder.set_toggled(if self.value() {
309            Toggled::True
310        } else {
311            Toggled::False
312        });
313        builder.add_action(Action::Focus);
314        let id = node_widget_common(&mut builder, self, children);
315        (id, builder)
316    }
317}
318
319impl Accessible for button::CheckButton {
320    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
321        let mut builder = Node::new(Role::CheckBox);
322        builder.set_toggled(if self.value() {
323            Toggled::True
324        } else {
325            Toggled::False
326        });
327        builder.add_action(Action::Focus);
328        let id = node_widget_common(&mut builder, self, children);
329        (id, builder)
330    }
331}
332
333impl Accessible for button::ToggleButton {
334    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
335        let mut builder = Node::new(Role::Button);
336        builder.set_toggled(if self.value() {
337            Toggled::True
338        } else {
339            Toggled::False
340        });
341        builder.add_action(Action::Focus);
342        let id = node_widget_common(&mut builder, self, children);
343        (id, builder)
344    }
345}
346
347impl Accessible for window::Window {
348    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
349        let mut builder = Node::new(Role::Window);
350        let sn = app::screen_num(self.x(), self.y());
351        builder.set_transform(Affine::scale(app::screen_scale(sn) as f64));
352        let id = node_widget_common(&mut builder, self, children);
353        (id, builder)
354    }
355}
356
357impl Accessible for frame::Frame {
358    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
359        let mut builder = Node::default();
360        let id = node_widget_common(&mut builder, self, children);
361        if self.image().is_some() {
362            builder.set_role(Role::Image);
363        } else {
364            builder.set_role(Role::Label);
365        }
366        (id, builder)
367    }
368}
369
370impl Accessible for output::Output {
371    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
372        let mut builder = Node::new(Role::Label);
373        builder.set_value(&*self.value());
374        let id = node_widget_common(&mut builder, self, children);
375        (id, builder)
376    }
377}
378
379impl Accessible for input::Input {
380    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
381        let mut builder = Node::new(Role::TextInput);
382        builder.set_value(&*self.value());
383        builder.add_action(Action::Focus);
384        builder.add_action(Action::SetValue);
385        let id = node_widget_common(&mut builder, self, children);
386        (id, builder)
387    }
388}
389
390impl Accessible for input::IntInput {
391    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
392        let mut builder = Node::new(Role::TextInput);
393        builder.set_value(&*self.value());
394        builder.add_action(Action::Focus);
395        builder.add_action(Action::SetValue);
396        let id = node_widget_common(&mut builder, self, children);
397        (id, builder)
398    }
399}
400
401impl Accessible for input::FloatInput {
402    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
403        let mut builder = Node::new(Role::TextInput);
404        builder.set_value(&*self.value());
405        builder.add_action(Action::Focus);
406        builder.add_action(Action::SetValue);
407        let id = node_widget_common(&mut builder, self, children);
408        (id, builder)
409    }
410}
411
412impl Accessible for input::MultilineInput {
413    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
414        let mut builder = Node::new(Role::MultilineTextInput);
415        builder.set_value(&*self.value());
416        builder.add_action(Action::Focus);
417        builder.add_action(Action::SetValue);
418        let id = node_widget_common(&mut builder, self, children);
419        (id, builder)
420    }
421}
422
423impl Accessible for output::MultilineOutput {
424    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
425        let mut builder = Node::new(Role::Paragraph);
426        builder.set_value(&*self.value());
427        let id = node_widget_common(&mut builder, self, children);
428        (id, builder)
429    }
430}
431
432impl Accessible for text::TextDisplay {
433    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
434        let mut builder = Node::new(Role::Paragraph);
435        let id = node_widget_common(&mut builder, self, children);
436        if let Some(buf) = self.buffer() {
437            builder.set_value(&*buf.text());
438            if let Some((s, e)) = buf.selection_position() {
439                builder.set_text_selection(TextSelection {
440                    anchor: TextPosition {
441                        node: id,
442                        character_index: s as _,
443                    },
444                    focus: TextPosition {
445                        node: id,
446                        character_index: e as _,
447                    },
448                });
449            }
450        }
451        (id, builder)
452    }
453}
454
455impl Accessible for text::TextEditor {
456    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
457        let mut builder = Node::new(Role::MultilineTextInput);
458
459        // Value and selection
460        if let Some(buf) = self.buffer() {
461            builder.set_value(&*buf.text());
462        }
463        builder.add_action(Action::Focus);
464        builder.add_action(Action::SetValue);
465        let id = node_widget_common(&mut builder, self, children);
466        if let Some(buf) = self.buffer() {
467            builder.set_value(&*buf.text());
468            if let Some((s, e)) = buf.selection_position() {
469                builder.set_text_selection(TextSelection {
470                    anchor: TextPosition {
471                        node: id,
472                        character_index: s as _,
473                    },
474                    focus: TextPosition {
475                        node: id,
476                        character_index: e as _,
477                    },
478                });
479            }
480        }
481        (id, builder)
482    }
483}
484
485#[allow(deprecated)]
486impl Accessible for text::SimpleTerminal {
487    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
488        let mut builder = Node::new(Role::Terminal);
489        builder.add_action(Action::Focus);
490        let id = node_widget_common(&mut builder, self, children);
491        if let Some(buf) = self.buffer() {
492            builder.set_value(&*buf.text());
493            if let Some((s, e)) = buf.selection_position() {
494                builder.set_text_selection(TextSelection {
495                    anchor: TextPosition {
496                        node: id,
497                        character_index: s as _,
498                    },
499                    focus: TextPosition {
500                        node: id,
501                        character_index: e as _,
502                    },
503                });
504            }
505        }
506        (id, builder)
507    }
508}
509
510impl Accessible for valuator::Slider {
511    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
512        let mut builder = Node::new(Role::Slider);
513        builder.set_numeric_value(self.value());
514        builder.set_min_numeric_value(self.minimum());
515        builder.set_max_numeric_value(self.maximum());
516        builder.set_numeric_value_step(self.step());
517        builder.add_action(Action::SetValue);
518        let id = node_widget_common(&mut builder, self, children);
519        (id, builder)
520    }
521}
522
523impl Accessible for valuator::NiceSlider {
524    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
525        let mut builder = Node::new(Role::Slider);
526        builder.set_numeric_value(self.value());
527        builder.set_min_numeric_value(self.minimum());
528        builder.set_max_numeric_value(self.maximum());
529        builder.set_numeric_value_step(self.step());
530        builder.add_action(Action::SetValue);
531        let id = node_widget_common(&mut builder, self, children);
532        (id, builder)
533    }
534}
535
536impl Accessible for valuator::ValueSlider {
537    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
538        let mut builder = Node::new(Role::Slider);
539        builder.set_numeric_value(self.value());
540        builder.set_min_numeric_value(self.minimum());
541        builder.set_max_numeric_value(self.maximum());
542        builder.set_numeric_value_step(self.step());
543        builder.add_action(Action::SetValue);
544        let id = node_widget_common(&mut builder, self, children);
545        (id, builder)
546    }
547}
548
549impl Accessible for valuator::FillSlider {
550    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
551        let mut builder = Node::new(Role::Slider);
552        builder.set_numeric_value(self.value());
553        builder.set_min_numeric_value(self.minimum());
554        builder.set_max_numeric_value(self.maximum());
555        builder.set_numeric_value_step(self.step());
556        builder.add_action(Action::SetValue);
557        let id = node_widget_common(&mut builder, self, children);
558        (id, builder)
559    }
560}
561
562impl Accessible for valuator::HorSlider {
563    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
564        let mut builder = Node::new(Role::Slider);
565        builder.set_numeric_value(self.value());
566        builder.set_min_numeric_value(self.minimum());
567        builder.set_max_numeric_value(self.maximum());
568        builder.set_numeric_value_step(self.step());
569        builder.add_action(Action::SetValue);
570        let id = node_widget_common(&mut builder, self, children);
571        (id, builder)
572    }
573}
574
575impl Accessible for valuator::HorFillSlider {
576    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
577        let mut builder = Node::new(Role::Slider);
578        builder.set_numeric_value(self.value());
579        builder.set_min_numeric_value(self.minimum());
580        builder.set_max_numeric_value(self.maximum());
581        builder.set_numeric_value_step(self.step());
582        builder.add_action(Action::SetValue);
583        let id = node_widget_common(&mut builder, self, children);
584        (id, builder)
585    }
586}
587
588impl Accessible for valuator::HorNiceSlider {
589    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
590        let mut builder = Node::new(Role::Slider);
591        builder.set_numeric_value(self.value());
592        builder.set_min_numeric_value(self.minimum());
593        builder.set_max_numeric_value(self.maximum());
594        builder.set_numeric_value_step(self.step());
595        builder.add_action(Action::SetValue);
596        let id = node_widget_common(&mut builder, self, children);
597        (id, builder)
598    }
599}
600
601impl Accessible for valuator::HorValueSlider {
602    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
603        let mut builder = Node::new(Role::Slider);
604        builder.set_numeric_value(self.value());
605        builder.set_min_numeric_value(self.minimum());
606        builder.set_max_numeric_value(self.maximum());
607        builder.set_numeric_value_step(self.step());
608        builder.add_action(Action::SetValue);
609        let id = node_widget_common(&mut builder, self, children);
610        (id, builder)
611    }
612}
613
614impl Accessible for valuator::Dial {
615    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
616        let mut builder = Node::new(Role::Slider);
617        builder.set_numeric_value(self.value());
618        builder.set_min_numeric_value(self.minimum());
619        builder.set_max_numeric_value(self.maximum());
620        builder.set_numeric_value_step(self.step());
621        builder.add_action(Action::SetValue);
622        let id = node_widget_common(&mut builder, self, children);
623        (id, builder)
624    }
625}
626
627impl Accessible for valuator::FillDial {
628    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
629        let mut builder = Node::new(Role::Slider);
630        builder.set_numeric_value(self.value());
631        builder.set_min_numeric_value(self.minimum());
632        builder.set_max_numeric_value(self.maximum());
633        builder.set_numeric_value_step(self.step());
634        builder.add_action(Action::SetValue);
635        let id = node_widget_common(&mut builder, self, children);
636        (id, builder)
637    }
638}
639
640impl Accessible for valuator::LineDial {
641    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
642        let mut builder = Node::new(Role::Slider);
643        builder.set_numeric_value(self.value());
644        builder.set_min_numeric_value(self.minimum());
645        builder.set_max_numeric_value(self.maximum());
646        builder.set_numeric_value_step(self.step());
647        builder.add_action(Action::SetValue);
648        let id = node_widget_common(&mut builder, self, children);
649        (id, builder)
650    }
651}
652
653impl Accessible for valuator::Counter {
654    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
655        let mut builder = Node::new(Role::Slider);
656        builder.set_numeric_value(self.value());
657        builder.set_min_numeric_value(self.minimum());
658        builder.set_max_numeric_value(self.maximum());
659        builder.set_numeric_value_step(self.step());
660        builder.add_action(Action::SetValue);
661        let id = node_widget_common(&mut builder, self, children);
662        (id, builder)
663    }
664}
665
666impl Accessible for valuator::Roller {
667    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
668        let mut builder = Node::new(Role::Slider);
669        builder.set_numeric_value(self.value());
670        builder.set_min_numeric_value(self.minimum());
671        builder.set_max_numeric_value(self.maximum());
672        builder.set_numeric_value_step(self.step());
673        builder.add_action(Action::SetValue);
674        let id = node_widget_common(&mut builder, self, children);
675        (id, builder)
676    }
677}
678
679impl Accessible for valuator::ValueInput {
680    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
681        let mut builder = Node::new(Role::Slider);
682        builder.set_numeric_value(self.value());
683        builder.set_min_numeric_value(self.minimum());
684        builder.set_max_numeric_value(self.maximum());
685        builder.set_numeric_value_step(self.step());
686        builder.add_action(Action::SetValue);
687        let id = node_widget_common(&mut builder, self, children);
688        (id, builder)
689    }
690}
691
692impl Accessible for valuator::ValueOutput {
693    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
694        let mut builder = Node::new(Role::Slider);
695        builder.set_numeric_value(self.value());
696        builder.set_min_numeric_value(self.minimum());
697        builder.set_max_numeric_value(self.maximum());
698        builder.set_numeric_value_step(self.step());
699        builder.add_action(Action::SetValue);
700        let id = node_widget_common(&mut builder, self, children);
701        (id, builder)
702    }
703}
704
705impl Accessible for valuator::Scrollbar {
706    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
707        let mut builder = Node::new(Role::ScrollBar);
708        builder.set_numeric_value(self.value());
709        builder.set_min_numeric_value(self.minimum());
710        builder.set_max_numeric_value(self.maximum());
711        builder.set_numeric_value_step(self.step());
712        let id = node_widget_common(&mut builder, self, children);
713        (id, builder)
714    }
715}
716
717impl Accessible for menu::MenuBar {
718    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
719        let mut builder = Node::new(Role::MenuBar);
720        let id = node_widget_common(&mut builder, self, children);
721        (id, builder)
722    }
723}
724
725impl Accessible for menu::Choice {
726    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
727        let mut builder = Node::new(Role::MenuListPopup);
728        let id = node_widget_common(&mut builder, self, children);
729        (id, builder)
730    }
731}
732
733impl Accessible for table::Table {
734    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
735        let mut builder = Node::new(Role::Table);
736        let id = node_widget_common(&mut builder, self, children);
737        (id, builder)
738    }
739}
740
741impl Accessible for tree::Tree {
742    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
743        let mut builder = Node::new(Role::Tree);
744        let id = node_widget_common(&mut builder, self, children);
745        (id, builder)
746    }
747}
748
749impl Accessible for group::Scroll {
750    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
751        let mut builder = Node::new(Role::ScrollView);
752        builder.add_action(Action::ScrollDown);
753        builder.add_action(Action::ScrollUp);
754        let id = node_widget_common(&mut builder, self, children);
755        (id, builder)
756    }
757}
758
759impl Accessible for group::Flex {
760    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
761        let mut builder = Node::new(Role::Group);
762        let id = node_widget_common(&mut builder, self, children);
763        (id, builder)
764    }
765}
766
767impl Accessible for group::Group {
768    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
769        let mut builder = Node::new(Role::Group);
770        let id = node_widget_common(&mut builder, self, children);
771        (id, builder)
772    }
773}
774
775impl Accessible for misc::Progress {
776    fn make_node(&self, children: &[NodeId]) -> (NodeId, Node) {
777        let mut builder = Node::new(Role::ProgressIndicator);
778        builder.set_numeric_value(self.value());
779        builder.set_min_numeric_value(self.minimum());
780        builder.set_max_numeric_value(self.maximum());
781        let id = node_widget_common(&mut builder, self, children);
782        (id, builder)
783    }
784}