ragnarok/
measurement.rs

1use itertools::Itertools;
2
3use crate::{
4    EmmitableEvent,
5    EventsMeasurer,
6    NameOfEvent,
7    NodeKey,
8    PotentialEvent,
9    PotentialEvents,
10    SourceEvent,
11};
12
13/// For every source event and its derivated events, a global equivalent event is emitted.
14pub fn measure_source_global_events<
15    Key: NodeKey,
16    Name: NameOfEvent,
17    Source: SourceEvent<Name = Name>,
18    Emmitable: EmmitableEvent<Key = Key, Name = Name>,
19>(
20    events_measurer: &impl EventsMeasurer<
21        Key = Key,
22        Name = Name,
23        Emmitable = Emmitable,
24        Source = Source,
25    >,
26    source_events: &Vec<Source>,
27    emmitable_events: &mut Vec<Emmitable>,
28) {
29    for source_event in source_events {
30        let event_name = source_event.as_event_name();
31        let derived_events_names = event_name.get_derived_events();
32
33        for derived_event_name in derived_events_names {
34            for global_event_name in derived_event_name.get_global_events() {
35                let listeners = events_measurer.get_listeners_of(&global_event_name);
36
37                for listener in listeners {
38                    let event = events_measurer.new_emmitable_event(
39                        *listener,
40                        global_event_name,
41                        source_event.clone(),
42                        None,
43                    );
44                    emmitable_events.push(event)
45                }
46            }
47        }
48    }
49}
50
51/// Measure what event listeners could potentially be triggered
52pub fn measure_potential_events<
53    Key: NodeKey,
54    Name: NameOfEvent,
55    Source: SourceEvent<Name = Name>,
56    Emmitable: EmmitableEvent<Key = Key, Name = Name>,
57>(
58    source_events: &Vec<Source>,
59    events_measurer: &impl EventsMeasurer<
60        Key = Key,
61        Name = Name,
62        Emmitable = Emmitable,
63        Source = Source,
64    >,
65    focus_id: Option<Key>,
66) -> PotentialEvents<Key, Name, Source> {
67    let mut potential_events = PotentialEvents::default();
68
69    // Walk layer by layer from the bottom to the top
70    for (layer, layer_nodes) in events_measurer
71        .get_layers()
72        .sorted_by(|(layer, _), (layer_b, _)| layer.cmp(layer_b))
73    {
74        for node_id in layer_nodes {
75            for source_event in source_events {
76                let Some(cursor) = source_event.try_location() else {
77                    if focus_id == Some(*node_id) {
78                        let potential_event = PotentialEvent {
79                            node_key: *node_id,
80                            layer: *layer,
81                            name: source_event.as_event_name(),
82                            source_event: source_event.clone(),
83                        };
84                        potential_events
85                            .entry(source_event.as_event_name())
86                            .or_default()
87                            .push(potential_event);
88                    }
89                    continue;
90                };
91
92                if !events_measurer.is_point_inside(node_id, cursor) {
93                    continue;
94                }
95
96                let potential_event = PotentialEvent {
97                    node_key: *node_id,
98                    layer: *layer,
99                    name: source_event.as_event_name(),
100                    source_event: source_event.clone(),
101                };
102
103                potential_events
104                    .entry(source_event.as_event_name())
105                    .or_insert_with(Vec::new)
106                    .push(potential_event);
107            }
108        }
109    }
110
111    potential_events
112}
113
114/// Measure what events could be emitted
115pub fn measure_emmitable_events<
116    Key: NodeKey,
117    Name: NameOfEvent,
118    Source: SourceEvent<Name = Name>,
119    Emmitable: EmmitableEvent,
120>(
121    potential_events: &PotentialEvents<Key, Name, Source>,
122    events_measurer: &impl EventsMeasurer<
123        Key = Key,
124        Name = Name,
125        Emmitable = Emmitable,
126        Source = Source,
127    >,
128) -> Vec<Emmitable> {
129    let mut emmitable_events = Vec::new();
130
131    for (event, potential_events) in potential_events {
132        // Get the derived events, but exclude globals like some file events
133        let derived_events_names = event
134            .get_derived_events()
135            .into_iter()
136            .filter(|event| !event.is_global());
137
138        // Iterate over the derived events (including the source)
139        'event: for derived_event_name in derived_events_names {
140            let mut child_node: Option<Key> = None;
141
142            // Iterate over the potential events in reverse so the ones in higher layers appeat first
143            for PotentialEvent {
144                node_key,
145                name,
146                source_event,
147                ..
148            } in potential_events.iter().rev()
149            {
150                if let Some(child_node) = child_node
151                    && !events_measurer.is_node_parent_of(&child_node, *node_key)
152                {
153                    continue;
154                }
155
156                if events_measurer.is_listening_to(node_key, &derived_event_name) {
157                    let area = events_measurer.try_area_of(node_key);
158                    if let Some(area) = area {
159                        let emmitable_event = events_measurer.new_emmitable_event(
160                            *node_key,
161                            derived_event_name,
162                            source_event.clone(),
163                            Some(area),
164                        );
165                        emmitable_events.push(emmitable_event);
166
167                        // Events that bubble will only be emitted once
168                        // Those that don't will be stacked
169                        if name.does_bubble() {
170                            continue 'event;
171                        }
172                    }
173                }
174
175                if !events_measurer.is_node_transparent(node_key) && !name.does_go_through_solid() {
176                    // If the background isn't transparent,
177                    // we must make sure that next nodes are parent of it
178                    // This only matters for events that bubble up (e.g. cursor click events)
179                    child_node = Some(*node_key);
180                }
181            }
182        }
183    }
184
185    emmitable_events
186}