1use crate::{
2 group_bounds, AnyElement, DispatchPhase, Element, IntoAnyElement, MouseMoveEvent, SharedString,
3 Style, StyleCascade, StyleRefinement,
4};
5use refineable::{CascadeSlot, Refineable};
6use smallvec::SmallVec;
7use std::sync::{
8 atomic::{AtomicBool, Ordering::SeqCst},
9 Arc,
10};
11
12trait LayoutNode<V: 'static + Send + Sync> {
13 fn state(&mut self) -> &mut LayoutNodeState<V>;
14
15 fn child(mut self, child: impl IntoAnyElement<V>) -> Self
16 where
17 Self: Sized,
18 {
19 self.state().children.push(child.into_any());
20 self
21 }
22
23 fn children<C, E>(mut self, children: C) -> Self
24 where
25 C: IntoIterator<Item = E>,
26 E: IntoAnyElement<V>,
27 Self: Sized,
28 {
29 for child in children {
30 self.state().children.push(child.into_any());
31 }
32 self
33 }
34}
35
36struct LayoutNodeState<V: 'static + Send + Sync> {
37 style_cascade: StyleCascade,
38 computed_style: Option<Style>,
39 children: SmallVec<[AnyElement<V>; 2]>,
40}
41
42impl<V> IntoAnyElement<V> for LayoutNodeState<V>
43where
44 V: 'static + Send + Sync,
45{
46 fn into_any(self) -> AnyElement<V> {
47 AnyElement::new(self)
48 }
49}
50
51impl<V: 'static + Send + Sync> Element for LayoutNodeState<V> {
52 type ViewState = V;
53 type ElementState = ();
54
55 fn element_id(&self) -> Option<crate::ElementId> {
56 None
57 }
58
59 fn layout(
60 &mut self,
61 state: &mut Self::ViewState,
62 _: Option<Self::ElementState>,
63 cx: &mut crate::ViewContext<Self::ViewState>,
64 ) -> (crate::LayoutId, Self::ElementState) {
65 let layout_ids = self
66 .children
67 .iter_mut()
68 .map(|child| child.layout(state, cx))
69 .collect::<Vec<_>>();
70
71 // todo!("pass just the style cascade")
72 let style = self.computed_style().clone();
73 let layout_id = cx.request_layout(style, layout_ids);
74 (layout_id, ())
75 }
76
77 fn paint(
78 &mut self,
79 _: crate::Bounds<crate::Pixels>,
80 state: &mut Self::ViewState,
81 _: &mut Self::ElementState,
82 cx: &mut crate::ViewContext<Self::ViewState>,
83 ) {
84 for child in &mut self.children {
85 child.paint(state, None, cx);
86 }
87 }
88}
89
90pub trait Styled {
91 fn style_cascade(&mut self) -> &mut StyleCascade;
92 fn computed_style(&mut self) -> &Style;
93}
94
95pub struct StyledElement<E> {
96 child: E,
97}
98
99impl<E> IntoAnyElement<E::ViewState> for StyledElement<E>
100where
101 E: Element + Styled,
102{
103 fn into_any(self) -> AnyElement<E::ViewState> {
104 AnyElement::new(self)
105 }
106}
107
108impl<E: Element + Styled> Element for StyledElement<E> {
109 type ViewState = E::ViewState;
110 type ElementState = E::ElementState;
111
112 fn element_id(&self) -> Option<crate::ElementId> {
113 self.child.element_id()
114 }
115
116 fn layout(
117 &mut self,
118 state: &mut Self::ViewState,
119 element_state: Option<Self::ElementState>,
120 cx: &mut crate::ViewContext<Self::ViewState>,
121 ) -> (crate::LayoutId, Self::ElementState) {
122 self.child.layout(state, element_state, cx)
123 }
124
125 fn paint(
126 &mut self,
127 bounds: crate::Bounds<crate::Pixels>,
128 state: &mut Self::ViewState,
129 element_state: &mut Self::ElementState,
130 cx: &mut crate::ViewContext<Self::ViewState>,
131 ) {
132 self.child.computed_style().paint(bounds, cx);
133 self.child.paint(bounds, state, element_state, cx);
134 }
135}
136
137pub trait Hoverable {
138 fn hover_style(&mut self) -> &mut StyleRefinement;
139
140 fn hover(mut self, f: impl FnOnce(&mut StyleRefinement) -> &mut StyleRefinement) -> Self
141 where
142 Self: Sized,
143 {
144 f(self.hover_style());
145 self
146 }
147}
148
149struct HoverableElement<Child> {
150 hover_style: StyleRefinement,
151 group: Option<SharedString>,
152 cascade_slot: CascadeSlot,
153 hovered: Arc<AtomicBool>,
154 child: Child,
155}
156
157impl<Child: Styled + Element> HoverableElement<Child> {
158 fn hover_style(&mut self) -> &mut StyleRefinement {
159 &mut self.hover_style
160 }
161}
162
163impl<E> IntoAnyElement<E::ViewState> for HoverableElement<E>
164where
165 E: Element + Styled,
166{
167 fn into_any(self) -> AnyElement<E::ViewState> {
168 AnyElement::new(self)
169 }
170}
171
172impl<E> Element for HoverableElement<E>
173where
174 E: Element + Styled,
175{
176 type ViewState = E::ViewState;
177 type ElementState = E::ElementState;
178
179 fn element_id(&self) -> Option<crate::ElementId> {
180 self.child.element_id()
181 }
182
183 fn layout(
184 &mut self,
185 state: &mut Self::ViewState,
186 element_state: Option<Self::ElementState>,
187 cx: &mut crate::ViewContext<Self::ViewState>,
188 ) -> (crate::LayoutId, Self::ElementState) {
189 self.child.layout(state, element_state, cx)
190 }
191
192 fn paint(
193 &mut self,
194 bounds: crate::Bounds<crate::Pixels>,
195 state: &mut Self::ViewState,
196 element_state: &mut Self::ElementState,
197 cx: &mut crate::ViewContext<Self::ViewState>,
198 ) {
199 let target_bounds = self
200 .group
201 .as_ref()
202 .and_then(|group| group_bounds(group, cx))
203 .unwrap_or(bounds);
204
205 let hovered = target_bounds.contains_point(cx.mouse_position());
206
207 let slot = self.cascade_slot;
208 let style = hovered.then_some(self.hover_style.clone());
209 self.child.style_cascade().set(slot, style);
210 self.hovered.store(hovered, SeqCst);
211
212 let hovered = self.hovered.clone();
213 cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
214 if phase == DispatchPhase::Capture {
215 if target_bounds.contains_point(event.position) != hovered.load(SeqCst) {
216 cx.notify();
217 }
218 }
219 });
220
221 self.child.paint(bounds, state, element_state, cx);
222 }
223}
224
225struct Div<V: 'static + Send + Sync>(HoverableElement<LayoutNodeState<V>>);
226
227impl<V: 'static + Send + Sync> LayoutNode<V> for Div<V> {
228 fn state(&mut self) -> &mut LayoutNodeState<V> {
229 &mut self.0.child
230 }
231}
232
233impl<V: 'static + Send + Sync> Styled for LayoutNodeState<V> {
234 fn style_cascade(&mut self) -> &mut StyleCascade {
235 &mut self.style_cascade
236 }
237
238 fn computed_style(&mut self) -> &Style {
239 self.computed_style
240 .get_or_insert_with(|| Style::default().refined(self.style_cascade.merged()))
241 }
242}
243
244impl<V: 'static + Send + Sync> Styled for Div<V> {
245 fn style_cascade(&mut self) -> &mut StyleCascade {
246 self.0.child.style_cascade()
247 }
248
249 fn computed_style(&mut self) -> &Style {
250 self.0.child.computed_style()
251 }
252}
253
254impl<V: 'static + Send + Sync> Hoverable for Div<V> {
255 fn hover_style(&mut self) -> &mut StyleRefinement {
256 self.0.hover_style()
257 }
258}