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