1use crate::{
2 Active, AnyElement, BorrowWindow, Bounds, Element, ElementFocusability, ElementId,
3 ElementInteractivity, Focus, FocusHandle, FocusListeners, Focusable, GlobalElementId,
4 GroupBounds, GroupStyle, Hover, InteractiveElementState, IntoAnyElement, LayoutId,
5 NonFocusable, Overflow, ParentElement, Pixels, Point, SharedString, StatefulInteractivity,
6 StatefullyInteractive, StatelessInteractivity, StatelesslyInteractive, Style, StyleRefinement,
7 Styled, ViewContext,
8};
9use parking_lot::Mutex;
10use refineable::Refineable;
11use smallvec::SmallVec;
12use std::sync::Arc;
13
14#[derive(Default, Clone)]
15pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
16
17impl ScrollState {
18 pub fn x(&self) -> Pixels {
19 self.0.lock().x
20 }
21
22 pub fn set_x(&self, value: Pixels) {
23 self.0.lock().x = value;
24 }
25
26 pub fn y(&self) -> Pixels {
27 self.0.lock().y
28 }
29
30 pub fn set_y(&self, value: Pixels) {
31 self.0.lock().y = value;
32 }
33}
34
35pub struct Div<
36 V: 'static + Send + Sync,
37 I: ElementInteractivity<V> = StatelessInteractivity<V>,
38 F: ElementFocusability<V> = NonFocusable,
39> {
40 interactivity: I,
41 focusability: F,
42 children: SmallVec<[AnyElement<V>; 2]>,
43 group: Option<SharedString>,
44 base_style: StyleRefinement,
45}
46
47pub fn div<V>() -> Div<V, StatelessInteractivity<V>, NonFocusable>
48where
49 V: 'static + Send + Sync,
50{
51 Div {
52 interactivity: StatelessInteractivity::default(),
53 focusability: NonFocusable,
54 children: SmallVec::new(),
55 group: None,
56 base_style: StyleRefinement::default(),
57 }
58}
59
60impl<V, F> Div<V, StatelessInteractivity<V>, F>
61where
62 F: ElementFocusability<V>,
63 V: 'static + Send + Sync,
64{
65 pub fn id(self, id: impl Into<ElementId>) -> Div<V, StatefulInteractivity<V>, F> {
66 Div {
67 interactivity: id.into().into(),
68 focusability: self.focusability,
69 children: self.children,
70 group: self.group,
71 base_style: self.base_style,
72 }
73 }
74}
75
76impl<V, I, F> Div<V, I, F>
77where
78 I: ElementInteractivity<V>,
79 F: ElementFocusability<V>,
80 V: 'static + Send + Sync,
81{
82 pub fn group(mut self, group: impl Into<SharedString>) -> Self {
83 self.group = Some(group.into());
84 self
85 }
86
87 pub fn z_index(mut self, z_index: u32) -> Self {
88 self.base_style.z_index = Some(z_index);
89 self
90 }
91
92 pub fn overflow_hidden(mut self) -> Self {
93 self.base_style.overflow.x = Some(Overflow::Hidden);
94 self.base_style.overflow.y = Some(Overflow::Hidden);
95 self
96 }
97
98 pub fn overflow_hidden_x(mut self) -> Self {
99 self.base_style.overflow.x = Some(Overflow::Hidden);
100 self
101 }
102
103 pub fn overflow_hidden_y(mut self) -> Self {
104 self.base_style.overflow.y = Some(Overflow::Hidden);
105 self
106 }
107
108 pub fn overflow_scroll(mut self, _scroll_state: ScrollState) -> Self {
109 // todo!("impl scrolling")
110 // self.scroll_state = Some(scroll_state);
111 self.base_style.overflow.x = Some(Overflow::Scroll);
112 self.base_style.overflow.y = Some(Overflow::Scroll);
113 self
114 }
115
116 pub fn overflow_x_scroll(mut self, _scroll_state: ScrollState) -> Self {
117 // todo!("impl scrolling")
118 // self.scroll_state = Some(scroll_state);
119 self.base_style.overflow.x = Some(Overflow::Scroll);
120 self
121 }
122
123 pub fn overflow_y_scroll(mut self, _scroll_state: ScrollState) -> Self {
124 // todo!("impl scrolling")
125 // self.scroll_state = Some(scroll_state);
126 self.base_style.overflow.y = Some(Overflow::Scroll);
127 self
128 }
129
130 fn with_element_id<R>(
131 &mut self,
132 cx: &mut ViewContext<V>,
133 f: impl FnOnce(&mut Self, Option<GlobalElementId>, &mut ViewContext<V>) -> R,
134 ) -> R {
135 if let Some(id) = self.id() {
136 cx.with_element_id(id, |global_id, cx| f(self, Some(global_id), cx))
137 } else {
138 f(self, None, cx)
139 }
140 }
141
142 pub fn compute_style(
143 &self,
144 bounds: Bounds<Pixels>,
145 state: &InteractiveElementState,
146 cx: &mut ViewContext<V>,
147 ) -> Style {
148 let mut computed_style = Style::default();
149 computed_style.refine(&self.base_style);
150 self.focusability.refine_style(&mut computed_style, cx);
151 self.interactivity
152 .refine_style(&mut computed_style, bounds, state, cx);
153 computed_style
154 }
155}
156
157impl<V, I> Div<V, I, NonFocusable>
158where
159 I: ElementInteractivity<V>,
160 V: 'static + Send + Sync,
161{
162 pub fn focusable(self, handle: &FocusHandle) -> Div<V, I, Focusable<V>> {
163 Div {
164 interactivity: self.interactivity,
165 focusability: handle.clone().into(),
166 children: self.children,
167 group: self.group,
168 base_style: self.base_style,
169 }
170 }
171}
172
173impl<V, I> Focus for Div<V, I, Focusable<V>>
174where
175 I: ElementInteractivity<V>,
176 V: 'static + Send + Sync,
177{
178 fn focus_listeners(&mut self) -> &mut FocusListeners<V> {
179 &mut self.focusability.focus_listeners
180 }
181
182 fn handle(&self) -> &FocusHandle {
183 &self.focusability.focus_handle
184 }
185
186 fn set_focus_style(&mut self, style: StyleRefinement) {
187 self.focusability.focus_style = style;
188 }
189
190 fn set_focus_in_style(&mut self, style: StyleRefinement) {
191 self.focusability.focus_in_style = style;
192 }
193
194 fn set_in_focus_style(&mut self, style: StyleRefinement) {
195 self.focusability.in_focus_style = style;
196 }
197}
198
199impl<V, I, F> Element for Div<V, I, F>
200where
201 I: ElementInteractivity<V>,
202 F: ElementFocusability<V>,
203 V: 'static + Send + Sync,
204{
205 type ViewState = V;
206 type ElementState = InteractiveElementState;
207
208 fn id(&self) -> Option<ElementId> {
209 self.interactivity
210 .as_stateful()
211 .map(|identified| identified.id.clone())
212 }
213
214 fn initialize(
215 &mut self,
216 view_state: &mut Self::ViewState,
217 element_state: Option<Self::ElementState>,
218 cx: &mut ViewContext<Self::ViewState>,
219 ) -> Self::ElementState {
220 self.interactivity.initialize(cx, |cx| {
221 self.focusability.initialize(cx, |cx| {
222 for child in &mut self.children {
223 child.initialize(view_state, cx);
224 }
225 });
226 });
227 element_state.unwrap_or_default()
228 }
229
230 fn layout(
231 &mut self,
232 view_state: &mut Self::ViewState,
233 element_state: &mut Self::ElementState,
234 cx: &mut ViewContext<Self::ViewState>,
235 ) -> LayoutId {
236 let style = self.compute_style(Bounds::default(), element_state, cx);
237 style.apply_text_style(cx, |cx| {
238 self.with_element_id(cx, |this, _global_id, cx| {
239 let layout_ids = this
240 .children
241 .iter_mut()
242 .map(|child| child.layout(view_state, cx))
243 .collect::<Vec<_>>();
244 cx.request_layout(&style, layout_ids)
245 })
246 })
247 }
248
249 fn paint(
250 &mut self,
251 bounds: Bounds<Pixels>,
252 view_state: &mut Self::ViewState,
253 element_state: &mut Self::ElementState,
254 cx: &mut ViewContext<Self::ViewState>,
255 ) {
256 self.with_element_id(cx, |this, _global_id, cx| {
257 if let Some(group) = this.group.clone() {
258 GroupBounds::push(group, bounds, cx);
259 }
260
261 let style = this.compute_style(bounds, element_state, cx);
262 let z_index = style.z_index.unwrap_or(0);
263
264 // Paint background and event handlers.
265 cx.stack(z_index, |cx| {
266 cx.stack(0, |cx| {
267 style.paint(bounds, cx);
268
269 this.focusability.paint(bounds, cx);
270 this.interactivity.paint(bounds, element_state, cx);
271 });
272
273 cx.stack(1, |cx| {
274 style.apply_text_style(cx, |cx| {
275 style.apply_overflow(bounds, cx, |cx| {
276 for child in &mut this.children {
277 child.paint(view_state, None, cx);
278 }
279 })
280 })
281 });
282 });
283
284 if let Some(group) = this.group.as_ref() {
285 GroupBounds::pop(group, cx);
286 }
287 })
288 }
289}
290
291impl<V, I, F> IntoAnyElement<V> for Div<V, I, F>
292where
293 I: ElementInteractivity<V>,
294 F: ElementFocusability<V>,
295 V: 'static + Send + Sync,
296{
297 fn into_any(self) -> AnyElement<V> {
298 AnyElement::new(self)
299 }
300}
301
302impl<V, I, F> ParentElement for Div<V, I, F>
303where
304 I: ElementInteractivity<V>,
305 F: ElementFocusability<V>,
306 V: 'static + Send + Sync,
307{
308 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
309 &mut self.children
310 }
311}
312
313impl<V, I, F> Styled for Div<V, I, F>
314where
315 I: ElementInteractivity<V>,
316 F: ElementFocusability<V>,
317 V: 'static + Send + Sync,
318{
319 fn style(&mut self) -> &mut StyleRefinement {
320 &mut self.base_style
321 }
322}
323
324impl<V, I, F> StatelesslyInteractive for Div<V, I, F>
325where
326 I: ElementInteractivity<V>,
327 F: ElementFocusability<V>,
328 V: 'static + Send + Sync,
329{
330 fn stateless_interactivity(&mut self) -> &mut StatelessInteractivity<V> {
331 self.interactivity.as_stateless_mut()
332 }
333}
334
335impl<V, I, F> Hover for Div<V, I, F>
336where
337 I: ElementInteractivity<V>,
338 F: ElementFocusability<V>,
339 V: 'static + Send + Sync,
340{
341 fn set_hover_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
342 let stateless = self.interactivity.as_stateless_mut();
343 if let Some(group) = group {
344 stateless.group_hover_style = Some(GroupStyle { group, style });
345 } else {
346 stateless.hover_style = style;
347 }
348 }
349}
350
351impl<V, F> StatefullyInteractive for Div<V, StatefulInteractivity<V>, F>
352where
353 F: ElementFocusability<V>,
354 V: 'static + Send + Sync,
355{
356 fn stateful_interactivity(&mut self) -> &mut StatefulInteractivity<Self::ViewState> {
357 &mut self.interactivity
358 }
359}
360
361impl<V, F> Active for Div<V, StatefulInteractivity<V>, F>
362where
363 F: ElementFocusability<V>,
364 V: 'static + Send + Sync,
365{
366 fn set_active_style(&mut self, group: Option<SharedString>, style: StyleRefinement) {
367 if let Some(group) = group {
368 self.interactivity.group_active_style = Some(GroupStyle { group, style });
369 } else {
370 self.interactivity.active_style = style;
371 }
372 }
373}