use crate::tree::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActionTrigger {
Keystroke,
Validate,
Format,
Calculate,
CursorEnter,
CursorExit,
Focus,
Blur,
PageOpen,
PageClose,
}
#[derive(Debug, Clone)]
pub struct FieldAction {
pub trigger: ActionTrigger,
pub javascript: Option<String>,
}
pub trait JsActionHandler {
fn on_keystroke(
&mut self,
tree: &mut FieldTree,
field_id: FieldId,
change: &str,
js: &str,
) -> bool;
fn on_validate(&mut self, tree: &mut FieldTree, field_id: FieldId, js: &str) -> bool;
fn on_format(&mut self, tree: &FieldTree, field_id: FieldId, js: &str) -> Option<String>;
fn on_calculate(&mut self, tree: &mut FieldTree, field_id: FieldId, js: &str)
-> Option<String>;
}
pub fn run_calculations(tree: &mut FieldTree, handler: &mut dyn JsActionHandler) {
let order: Vec<FieldId> = tree.calculation_order.clone();
for field_id in order {
if !tree.get(field_id).has_actions {
continue;
}
let _ = (field_id, &mut *handler);
}
}
pub fn field_action_triggers(tree: &FieldTree, id: FieldId) -> Vec<ActionTrigger> {
if !tree.get(id).has_actions {
return vec![];
}
vec![
ActionTrigger::Keystroke,
ActionTrigger::Validate,
ActionTrigger::Format,
ActionTrigger::Calculate,
ActionTrigger::CursorEnter,
ActionTrigger::CursorExit,
ActionTrigger::Focus,
ActionTrigger::Blur,
]
}
#[cfg(test)]
mod tests {
use super::*;
use crate::flags::FieldFlags;
fn make_field(has_actions: bool) -> (FieldTree, FieldId) {
let mut tree = FieldTree::new();
let id = tree.alloc(FieldNode {
partial_name: "f".into(),
alternate_name: None,
mapping_name: None,
field_type: Some(FieldType::Text),
flags: FieldFlags::empty(),
value: None,
default_value: None,
default_appearance: None,
quadding: None,
max_len: None,
options: vec![],
top_index: None,
rect: None,
appearance_state: None,
page_index: None,
parent: None,
children: vec![],
object_id: None,
has_actions,
mk: None,
border_style: None,
});
(tree, id)
}
#[test]
fn triggers_empty() {
let (tree, id) = make_field(false);
assert!(field_action_triggers(&tree, id).is_empty());
}
#[test]
fn triggers_present() {
let (tree, id) = make_field(true);
assert!(!field_action_triggers(&tree, id).is_empty());
}
}