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