1use crate::flags::FieldFlags;
10use crate::tree::*;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum ChoiceKind {
20 ComboBox,
23 EditableCombo,
27 ListBox,
30 MultiSelectListBox,
34}
35
36pub fn choice_kind(flags: FieldFlags) -> ChoiceKind {
38 if flags.combo() {
39 if flags.edit() {
40 ChoiceKind::EditableCombo
41 } else {
42 ChoiceKind::ComboBox
43 }
44 } else if flags.multi_select() {
45 ChoiceKind::MultiSelectListBox
46 } else {
47 ChoiceKind::ListBox
48 }
49}
50
51pub fn get_selection(tree: &FieldTree, id: FieldId) -> Vec<String> {
53 match tree.effective_value(id) {
54 Some(FieldValue::Text(s)) => vec![s.clone()],
55 Some(FieldValue::StringArray(arr)) => arr.clone(),
56 None => vec![],
57 }
58}
59
60pub fn get_options(tree: &FieldTree, id: FieldId) -> &[ChoiceOption] {
62 &tree.get(id).options
63}
64
65pub fn set_selection(tree: &mut FieldTree, id: FieldId, value: &str) -> bool {
68 let flags = tree.effective_flags(id);
69 if flags.read_only() {
70 return false;
71 }
72 if choice_kind(flags) == ChoiceKind::ComboBox
73 && !tree
74 .get(id)
75 .options
76 .iter()
77 .any(|o| o.export == value || o.display == value)
78 {
79 return false;
80 }
81 tree.get_mut(id).value = Some(FieldValue::Text(value.to_string()));
82 true
83}
84
85pub fn set_multi_selection(tree: &mut FieldTree, id: FieldId, values: Vec<String>) -> bool {
87 let flags = tree.effective_flags(id);
88 if flags.read_only() || !flags.multi_select() {
89 return false;
90 }
91 tree.get_mut(id).value = Some(FieldValue::StringArray(values));
92 true
93}
94
95pub fn selected_index(tree: &FieldTree, id: FieldId) -> Option<usize> {
97 let first = get_selection(tree, id).into_iter().next()?;
98 tree.get(id)
99 .options
100 .iter()
101 .position(|o| o.export == first || o.display == first)
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 fn make_choice_tree() -> (FieldTree, FieldId) {
108 let mut tree = FieldTree::new();
109 let id = tree.alloc(FieldNode {
110 partial_name: "dd".into(),
111 alternate_name: None,
112 mapping_name: None,
113 field_type: Some(FieldType::Choice),
114 flags: FieldFlags::from_bits(1 << 17),
115 value: None,
116 default_value: None,
117 default_appearance: None,
118 quadding: None,
119 max_len: None,
120 options: vec![
121 ChoiceOption {
122 export: "a".into(),
123 display: "Alpha".into(),
124 },
125 ChoiceOption {
126 export: "b".into(),
127 display: "Beta".into(),
128 },
129 ChoiceOption {
130 export: "c".into(),
131 display: "Gamma".into(),
132 },
133 ],
134 top_index: None,
135 rect: Some([0.0, 0.0, 150.0, 20.0]),
136 appearance_state: None,
137 on_state: None,
138 page_index: None,
139 parent: None,
140 children: vec![],
141 object_id: None,
142 has_actions: false,
143 mk: None,
144 border_style: None,
145 });
146 (tree, id)
147 }
148 #[test]
149 fn kind_combo() {
150 assert_eq!(
151 choice_kind(FieldFlags::from_bits(1 << 17)),
152 ChoiceKind::ComboBox
153 );
154 }
155 #[test]
156 fn kind_editable() {
157 assert_eq!(
158 choice_kind(FieldFlags::from_bits((1 << 17) | (1 << 18))),
159 ChoiceKind::EditableCombo
160 );
161 }
162 #[test]
163 fn kind_listbox() {
164 assert_eq!(choice_kind(FieldFlags::empty()), ChoiceKind::ListBox);
165 }
166 #[test]
167 fn kind_multi() {
168 assert_eq!(
169 choice_kind(FieldFlags::from_bits(1 << 21)),
170 ChoiceKind::MultiSelectListBox
171 );
172 }
173 #[test]
174 fn set_valid() {
175 let (mut tree, id) = make_choice_tree();
176 assert!(set_selection(&mut tree, id, "a"));
177 assert_eq!(get_selection(&tree, id), vec!["a"]);
178 }
179 #[test]
180 fn set_invalid() {
181 let (mut tree, id) = make_choice_tree();
182 assert!(!set_selection(&mut tree, id, "nope"));
183 }
184 #[test]
185 fn sel_index() {
186 let (mut tree, id) = make_choice_tree();
187 set_selection(&mut tree, id, "b");
188 assert_eq!(selected_index(&tree, id), Some(1));
189 }
190}