pdfluent_forms/
actions.rs1use crate::tree::*;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum ActionTrigger {
8 Keystroke,
9 Validate,
10 Format,
11 Calculate,
12 CursorEnter,
13 CursorExit,
14 Focus,
15 Blur,
16 PageOpen,
17 PageClose,
18}
19
20#[derive(Debug, Clone)]
22pub struct FieldAction {
23 pub trigger: ActionTrigger,
25 pub javascript: Option<String>,
27}
28
29pub trait JsActionHandler {
31 fn on_keystroke(
33 &mut self,
34 tree: &mut FieldTree,
35 field_id: FieldId,
36 change: &str,
37 js: &str,
38 ) -> bool;
39 fn on_validate(&mut self, tree: &mut FieldTree, field_id: FieldId, js: &str) -> bool;
41 fn on_format(&mut self, tree: &FieldTree, field_id: FieldId, js: &str) -> Option<String>;
43 fn on_calculate(&mut self, tree: &mut FieldTree, field_id: FieldId, js: &str)
45 -> Option<String>;
46}
47
48pub fn run_calculations(tree: &mut FieldTree, handler: &mut dyn JsActionHandler) {
50 let order: Vec<FieldId> = tree.calculation_order.clone();
51 for field_id in order {
52 if !tree.get(field_id).has_actions {
53 continue;
54 }
55 let _ = (field_id, &mut *handler);
57 }
58}
59
60pub fn field_action_triggers(tree: &FieldTree, id: FieldId) -> Vec<ActionTrigger> {
62 if !tree.get(id).has_actions {
63 return vec![];
64 }
65 vec![
66 ActionTrigger::Keystroke,
67 ActionTrigger::Validate,
68 ActionTrigger::Format,
69 ActionTrigger::Calculate,
70 ActionTrigger::CursorEnter,
71 ActionTrigger::CursorExit,
72 ActionTrigger::Focus,
73 ActionTrigger::Blur,
74 ]
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::flags::FieldFlags;
81 fn make_field(has_actions: bool) -> (FieldTree, FieldId) {
82 let mut tree = FieldTree::new();
83 let id = tree.alloc(FieldNode {
84 partial_name: "f".into(),
85 alternate_name: None,
86 mapping_name: None,
87 field_type: Some(FieldType::Text),
88 flags: FieldFlags::empty(),
89 value: None,
90 default_value: None,
91 default_appearance: None,
92 quadding: None,
93 max_len: None,
94 options: vec![],
95 top_index: None,
96 rect: None,
97 appearance_state: None,
98 page_index: None,
99 parent: None,
100 children: vec![],
101 object_id: None,
102 has_actions,
103 mk: None,
104 border_style: None,
105 });
106 (tree, id)
107 }
108 #[test]
109 fn triggers_empty() {
110 let (tree, id) = make_field(false);
111 assert!(field_action_triggers(&tree, id).is_empty());
112 }
113 #[test]
114 fn triggers_present() {
115 let (tree, id) = make_field(true);
116 assert!(!field_action_triggers(&tree, id).is_empty());
117 }
118}