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