tessera_components/list_item/
selection.rs1use tessera_ui::{
8 AccessibilityActionHandler, AccessibilityNode, Callback, CallbackWith, SemanticsModifierNode,
9 accesskit::{Role, Toggled},
10};
11
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
14pub enum ListItemSelectionMode {
15 #[default]
17 Action,
18 Single,
20 Multiple,
22}
23
24impl ListItemSelectionMode {
25 pub(super) fn role(self) -> Role {
26 match self {
27 Self::Action => Role::ListItem,
28 Self::Single => Role::RadioButton,
29 Self::Multiple => Role::CheckBox,
30 }
31 }
32}
33
34#[derive(Clone, PartialEq)]
35pub(super) struct ListItemActivation {
36 pub mode: ListItemSelectionMode,
37 pub selected: bool,
38 pub on_click: Option<Callback>,
39 pub on_selection_change: Option<CallbackWith<bool>>,
40}
41
42impl ListItemActivation {
43 pub fn has_handler(&self) -> bool {
44 self.on_click.is_some()
45 || (self.mode != ListItemSelectionMode::Action && self.on_selection_change.is_some())
46 }
47
48 pub fn activate(self) {
49 if self.mode != ListItemSelectionMode::Action
50 && let Some(callback) = self.on_selection_change
51 {
52 callback.call(self.mode == ListItemSelectionMode::Single || !self.selected);
53 } else if let Some(callback) = self.on_click {
54 callback.call();
55 }
56 }
57}
58
59#[derive(Clone)]
60pub(super) struct ListItemSelectionSemantics {
61 pub mode: ListItemSelectionMode,
62 pub selected: Option<bool>,
63}
64
65impl SemanticsModifierNode for ListItemSelectionSemantics {
66 fn apply(&self, node: &mut AccessibilityNode, _: &mut Option<AccessibilityActionHandler>) {
67 let selected = self.selected.unwrap_or(false);
68 match self.mode {
69 ListItemSelectionMode::Action => {
70 if self.selected.is_some() {
71 node.selected = self.selected;
72 }
73 node.toggled = None;
74 }
75 ListItemSelectionMode::Single => {
76 node.selected = Some(selected);
77 node.toggled = Some(if selected {
78 Toggled::True
79 } else {
80 Toggled::False
81 });
82 }
83 ListItemSelectionMode::Multiple => {
84 node.selected = None;
85 node.toggled = Some(if selected {
86 Toggled::True
87 } else {
88 Toggled::False
89 });
90 }
91 }
92 }
93}