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