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        // Make sure the cursor is inside the element
56        if !element.is_point_inside(EventMeasurementContext {
57            cursor,
58            layout_node,
59            scale_factor: self.scale_factor,
60        }) {
61            return false;
62        }
63
64        let effect_state = self.tree.effect_state.get(key);
65
66        if let Some(effect_state) = effect_state {
67            // Make sure the cursor is inside all the inherited clips of the element
68            for node_id in effect_state.clips.iter() {
69                let element = self.tree.elements.get(node_id).unwrap();
70                let layout_node = self.tree.layout.get(node_id).unwrap();
71                if !element.is_point_inside(EventMeasurementContext {
72                    cursor,
73                    layout_node,
74                    scale_factor: self.scale_factor,
75                }) {
76                    return false;
77                }
78            }
79        }
80
81        true
82    }
83
84    fn is_node_parent_of(&self, key: &Self::Key, parent: Self::Key) -> bool {
85        let mut head = Some(key);
86        while let Some(id) = head.take() {
87            if let Some(parent_id) = self.tree.parents.get(id) {
88                if *parent_id == parent {
89                    return true;
90                }
91
92                head = Some(parent_id)
93            }
94        }
95        false
96    }
97
98    fn is_node_transparent(&self, key: &Self::Key) -> bool {
99        let element = self.tree.elements.get(key).unwrap();
100        if element.style().background == Fill::Color(Color::TRANSPARENT) {
101            return true;
102        }
103        if let Some(effect_state) = self.tree.effect_state.get(key) {
104            return effect_state.interactive == Interactive::No;
105        }
106        false
107    }
108
109    fn try_area_of(&self, key: &Self::Key) -> Option<ragnarok::Area> {
110        self.tree
111            .layout
112            .get(key)
113            .map(|layout| layout.visible_area())
114    }
115
116    fn new_emmitable_event(
117        &self,
118        key: Self::Key,
119        name: Self::Name,
120        source: Self::Source,
121        area: Option<ragnarok::Area>,
122    ) -> Self::Emmitable {
123        EmmitableEvent::new(key, name, source, area, self.scale_factor)
124    }
125}