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