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 page_index: None,
108 parent: None,
109 children: vec![],
110 object_id: None,
111 has_actions: false,
112 mk: None,
113 border_style: None,
114 });
115 (tree, id)
116 }
117
118 #[test]
119 fn get_value() {
120 let (tree, id) = make_text_tree();
121 assert_eq!(get_text_value(&tree, id), Some("hello".into()));
122 }
123 #[test]
124 fn set_value() {
125 let (mut tree, id) = make_text_tree();
126 assert!(set_text_value(&mut tree, id, "world"));
127 assert_eq!(get_text_value(&tree, id), Some("world".into()));
128 }
129 #[test]
130 fn set_value_readonly() {
131 let (mut tree, id) = make_text_tree();
132 tree.get_mut(id).flags = FieldFlags::from_bits(1);
133 assert!(!set_text_value(&mut tree, id, "nope"));
134 }
135 #[test]
136 fn set_value_maxlen() {
137 let (mut tree, id) = make_text_tree();
138 tree.get_mut(id).max_len = Some(3);
139 assert!(set_text_value(&mut tree, id, "abcdef"));
140 assert_eq!(get_text_value(&tree, id), Some("abc".into()));
141 }
142 #[test]
143 fn kind_detection() {
144 assert_eq!(text_field_kind(FieldFlags::empty()), TextFieldKind::Normal);
145 assert_eq!(
146 text_field_kind(FieldFlags::from_bits(1 << 12)),
147 TextFieldKind::Multiline
148 );
149 assert_eq!(
150 text_field_kind(FieldFlags::from_bits(1 << 13)),
151 TextFieldKind::Password
152 );
153 assert_eq!(
154 text_field_kind(FieldFlags::from_bits(1 << 24)),
155 TextFieldKind::Comb
156 );
157 }
158 #[test]
159 fn comb_width() {
160 let (mut tree, id) = make_text_tree();
161 tree.get_mut(id).max_len = Some(10);
162 assert_eq!(comb_cell_width(&tree, id), Some(20.0));
163 }
164}