Skip to main content

lgui_core/core/component/runtime/
action.rs

1use super::{
2    input::{event_target_ids, interaction_state_target_ids},
3    *,
4};
5
6impl UiRuntime {
7    pub fn handle_default_action(
8        &mut self,
9        tree: &HostTree,
10        pending: UiDefaultAction,
11    ) -> RuntimeOutput {
12        if pending.action.id().as_str() == FOCUS_TRAVERSAL_ACTION {
13            let events = self
14                .events
15                .focus_adjacent(tree, pending.action.payload_value() == Some("reverse"));
16            let handler_events = events
17                .iter()
18                .flat_map(|event| tree.handler_events(event))
19                .collect();
20            for event in events.iter().cloned() {
21                self.dirty.mark_event(event);
22            }
23            self.mark_component_owners(tree, events.iter().flat_map(interaction_state_target_ids));
24            let animation_changed =
25                apply_events_to_animations(tree, &mut self.animations, events.iter().cloned());
26            if animation_changed {
27                self.mark_component_owners(tree, events.iter().flat_map(event_target_ids));
28            }
29            let dirty_bounds = self.dirty.take().bounds(tree);
30            return RuntimeOutput {
31                events,
32                handler_events,
33                action_events: Vec::new(),
34                default_actions: Vec::new(),
35                dirty_bounds,
36                animation_changed,
37                route_changed: false,
38            };
39        }
40        let mut action_events = Vec::new();
41        let (_, changed, route_changed) = self.apply_component_action(
42            tree,
43            &pending.action_target,
44            &pending.action,
45            &mut action_events,
46        );
47        let handler_events = changed
48            .then(|| {
49                tree.handler_event(
50                    &pending.action_target,
51                    UiEventPayload::Change {
52                        value: pending.action.payload_value().map(str::to_owned),
53                    },
54                )
55            })
56            .flatten()
57            .into_iter()
58            .collect();
59        let dirty_bounds = self.dirty.take().bounds(tree);
60        RuntimeOutput {
61            events: Vec::new(),
62            handler_events,
63            action_events,
64            default_actions: Vec::new(),
65            dirty_bounds,
66            animation_changed: changed,
67            route_changed,
68        }
69    }
70
71    fn apply_component_action(
72        &mut self,
73        tree: &HostTree,
74        target: &UiId,
75        action: &UiAction,
76        action_events: &mut Vec<UiActionEvent>,
77    ) -> (bool, bool, bool) {
78        let outcome = self.component_states.handle_action(target, action);
79        if outcome.changed {
80            self.mark_component_owners(tree, std::iter::once(target));
81            self.dirty.mark_id(target.clone());
82        }
83        for action in outcome.events {
84            let Some(handler) = tree.action_handler(target, action.id()) else {
85                continue;
86            };
87            action_events.push(UiActionEvent {
88                target: target.clone(),
89                action,
90                handler,
91            });
92        }
93        let route_changed =
94            outcome.changed && self.component_states.take_route_invalidation(target);
95        (outcome.handled, outcome.changed, route_changed)
96    }
97}