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