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