Skip to main content

freya_core/events/
measurer.rs

1use crate::{
2    data::Interactive,
3    element::EventMeasurementContext,
4    events::{
5        emittable::EmmitableEvent,
6        name::EventName,
7        platform::PlatformEvent,
8    },
9    node_id::NodeId,
10    tree::Tree,
11};
12
13pub struct EventsMeasurerAdapter<'a> {
14    pub tree: &'a mut Tree,
15    pub scale_factor: f64,
16}
17
18impl ragnarok::EventsMeasurer for EventsMeasurerAdapter<'_> {
19    type Key = NodeId;
20    type Name = EventName;
21    type Source = PlatformEvent;
22    type Emmitable = EmmitableEvent;
23
24    fn get_listeners_of(&self, name: &Self::Name) -> impl Iterator<Item = &Self::Key> {
25        self.tree
26            .listeners
27            .get(name)
28            .map(|l| l.iter())
29            .unwrap_or_else(|| [].iter())
30    }
31
32    fn is_listening_to(&self, key: &Self::Key, name: &Self::Name) -> bool {
33        self.tree
34            .listeners
35            .get(name)
36            .map(|listeners| listeners.contains(key))
37            .unwrap_or_default()
38    }
39
40    fn get_layers(&self) -> impl Iterator<Item = (&i16, impl Iterator<Item = &Self::Key>)> {
41        self.tree
42            .layers
43            .iter()
44            .map(|(layer, nodes)| (layer, nodes.iter()))
45    }
46
47    fn is_point_inside(&self, key: &Self::Key, cursor: ragnarok::CursorPoint) -> bool {
48        let element = self.tree.elements.get(key).unwrap();
49        let Some(layout_node) = self.tree.layout.get(key) else {
50            return false;
51        };
52
53        if layout_node.hidden {
54            return false;
55        }
56
57        // Make sure the cursor is inside the element
58        if !element.is_point_inside(EventMeasurementContext {
59            cursor,
60            layout_node,
61            scale_factor: self.scale_factor,
62        }) {
63            return false;
64        }
65
66        let effect_state = self.tree.effect_state.get(key);
67
68        if let Some(effect_state) = effect_state {
69            // Make sure the cursor is inside all the inherited clips of the element
70            for node_id in effect_state.clips.iter() {
71                let element = self.tree.elements.get(node_id).unwrap();
72                let layout_node = self.tree.layout.get(node_id).unwrap();
73                if !element.is_point_inside(EventMeasurementContext {
74                    cursor,
75                    layout_node,
76                    scale_factor: self.scale_factor,
77                }) {
78                    return false;
79                }
80            }
81        }
82
83        true
84    }
85
86    fn is_node_parent_of(&self, key: &Self::Key, parent: Self::Key) -> bool {
87        let mut head = Some(key);
88        while let Some(id) = head.take() {
89            if let Some(parent_id) = self.tree.parents.get(id) {
90                if *parent_id == parent {
91                    return true;
92                }
93
94                head = Some(parent_id)
95            }
96        }
97        false
98    }
99
100    fn is_node_transparent(&self, key: &Self::Key) -> bool {
101        let element = self.tree.elements.get(key).unwrap();
102        element.is_transparent()
103    }
104
105    fn is_node_interactive(&self, key: &Self::Key) -> bool {
106        self.tree
107            .effect_state
108            .get(key)
109            .map(|effect_state| effect_state.interactive == Interactive::Yes)
110            .unwrap_or(true)
111    }
112
113    fn try_area_of(&self, key: &Self::Key) -> Option<ragnarok::Area> {
114        self.tree
115            .layout
116            .get(key)
117            .map(|layout| layout.visible_area())
118    }
119
120    fn new_emmitable_event(
121        &self,
122        key: Self::Key,
123        name: Self::Name,
124        source: Self::Source,
125        area: Option<ragnarok::Area>,
126    ) -> Self::Emmitable {
127        EmmitableEvent::new(key, name, source, area, self.scale_factor)
128    }
129}