1use crate::flags::FieldFlags;
10use crate::tree::*;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum TextFieldKind {
21 Normal,
24 Multiline,
27 Password,
30 Comb,
34 RichText,
37 FileSelect,
40}
41
42pub fn text_field_kind(flags: FieldFlags) -> TextFieldKind {
44 if flags.file_select() {
45 TextFieldKind::FileSelect
46 } else if flags.comb() {
47 TextFieldKind::Comb
48 } else if flags.rich_text() {
49 TextFieldKind::RichText
50 } else if flags.password() {
51 TextFieldKind::Password
52 } else if flags.multiline() {
53 TextFieldKind::Multiline
54 } else {
55 TextFieldKind::Normal
56 }
57}
58
59pub fn get_text_value(tree: &FieldTree, id: FieldId) -> Option<String> {
61 match tree.effective_value(id)? {
62 FieldValue::Text(s) => Some(s.clone()),
63 FieldValue::StringArray(arr) => arr.first().cloned(),
64 }
65}
66
67pub fn set_text_value(tree: &mut FieldTree, id: FieldId, text: &str) -> bool {
70 if tree.effective_flags(id).read_only() {
71 return false;
72 }
73 let max_len = tree.effective_max_len(id);
74 let value = if let Some(ml) = max_len {
75 text.chars().take(ml as usize).collect()
76 } else {
77 text.to_string()
78 };
79 tree.get_mut(id).value = Some(FieldValue::Text(value));
80 true
81}
82
83pub fn comb_cell_width(tree: &FieldTree, id: FieldId) -> Option<f32> {
85 let max_len = tree.effective_max_len(id)?;
86 if max_len == 0 {
87 return None;
88 }
89 let rect = tree.get(id).rect?;
90 Some((rect[2] - rect[0]) / max_len as f32)
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96 fn make_text_tree() -> (FieldTree, FieldId) {
97 let mut tree = FieldTree::new();
98 let id = tree.alloc(FieldNode {
99 partial_name: "text1".into(),
100 alternate_name: None,
101 mapping_name: None,
102 field_type: Some(FieldType::Text),
103 flags: FieldFlags::empty(),
104 value: Some(FieldValue::Text("hello".into())),
105 default_value: None,
106 default_appearance: None,
107 quadding: None,
108 max_len: None,
109 options: vec![],
110 top_index: None,
111 rect: Some([0.0, 0.0, 200.0, 20.0]),
112 appearance_state: None,
113 on_state: None,
114 page_index: None,
115 parent: None,
116 children: vec![],
117 object_id: None,
118 has_actions: false,
119 mk: None,
120 border_style: None,
121 });
122 (tree, id)
123 }
124
125 #[test]
126 fn get_value() {
127 let (tree, id) = make_text_tree();
128 assert_eq!(get_text_value(&tree, id), Some("hello".into()));
129 }
130 #[test]
131 fn set_value() {
132 let (mut tree, id) = make_text_tree();
133 assert!(set_text_value(&mut tree, id, "world"));
134 assert_eq!(get_text_value(&tree, id), Some("world".into()));
135 }
136 #[test]
137 fn set_value_readonly() {
138 let (mut tree, id) = make_text_tree();
139 tree.get_mut(id).flags = FieldFlags::from_bits(1);
140 assert!(!set_text_value(&mut tree, id, "nope"));
141 }
142 #[test]
143 fn set_value_maxlen() {
144 let (mut tree, id) = make_text_tree();
145 tree.get_mut(id).max_len = Some(3);
146 assert!(set_text_value(&mut tree, id, "abcdef"));
147 assert_eq!(get_text_value(&tree, id), Some("abc".into()));
148 }
149 #[test]
150 fn kind_detection() {
151 assert_eq!(text_field_kind(FieldFlags::empty()), TextFieldKind::Normal);
152 assert_eq!(
153 text_field_kind(FieldFlags::from_bits(1 << 12)),
154 TextFieldKind::Multiline
155 );
156 assert_eq!(
157 text_field_kind(FieldFlags::from_bits(1 << 13)),
158 TextFieldKind::Password
159 );
160 assert_eq!(
161 text_field_kind(FieldFlags::from_bits(1 << 24)),
162 TextFieldKind::Comb
163 );
164 }
165 #[test]
166 fn comb_width() {
167 let (mut tree, id) = make_text_tree();
168 tree.get_mut(id).max_len = Some(10);
169 assert_eq!(comb_cell_width(&tree, id), Some(20.0));
170 }
171}