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