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 page_index: None,
132 parent: None,
133 children: vec![],
134 object_id: None,
135 has_actions: false,
136 mk: None,
137 border_style: None,
138 });
139 (tree, id)
140 }
141 #[test]
142 fn kind_combo() {
143 assert_eq!(
144 choice_kind(FieldFlags::from_bits(1 << 17)),
145 ChoiceKind::ComboBox
146 );
147 }
148 #[test]
149 fn kind_editable() {
150 assert_eq!(
151 choice_kind(FieldFlags::from_bits((1 << 17) | (1 << 18))),
152 ChoiceKind::EditableCombo
153 );
154 }
155 #[test]
156 fn kind_listbox() {
157 assert_eq!(choice_kind(FieldFlags::empty()), ChoiceKind::ListBox);
158 }
159 #[test]
160 fn kind_multi() {
161 assert_eq!(
162 choice_kind(FieldFlags::from_bits(1 << 21)),
163 ChoiceKind::MultiSelectListBox
164 );
165 }
166 #[test]
167 fn set_valid() {
168 let (mut tree, id) = make_choice_tree();
169 assert!(set_selection(&mut tree, id, "a"));
170 assert_eq!(get_selection(&tree, id), vec!["a"]);
171 }
172 #[test]
173 fn set_invalid() {
174 let (mut tree, id) = make_choice_tree();
175 assert!(!set_selection(&mut tree, id, "nope"));
176 }
177 #[test]
178 fn sel_index() {
179 let (mut tree, id) = make_choice_tree();
180 set_selection(&mut tree, id, "b");
181 assert_eq!(selected_index(&tree, id), Some(1));
182 }
183}