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,
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 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 for Div<V, I, F>
193where
194 I: ElementInteraction<V>,
195 F: ElementFocus<V>,
196{
197 type ViewState = V;
198 type ElementState = DivState;
199
200 fn id(&self) -> Option<ElementId> {
201 self.interaction
202 .as_stateful()
203 .map(|identified| identified.id.clone())
204 }
205
206 fn initialize(
207 &mut self,
208 view_state: &mut Self::ViewState,
209 element_state: Option<Self::ElementState>,
210 cx: &mut ViewContext<Self::ViewState>,
211 ) -> Self::ElementState {
212 let mut element_state = element_state.unwrap_or_default();
213 self.focus
214 .initialize(element_state.focus_handle.take(), cx, |focus_handle, cx| {
215 element_state.focus_handle = focus_handle;
216 self.interaction.initialize(cx, |cx| {
217 for child in &mut self.children {
218 child.initialize(view_state, cx);
219 }
220 })
221 });
222 element_state
223 }
224
225 fn layout(
226 &mut self,
227 view_state: &mut Self::ViewState,
228 element_state: &mut Self::ElementState,
229 cx: &mut ViewContext<Self::ViewState>,
230 ) -> LayoutId {
231 let style = self.compute_style(Bounds::default(), element_state, cx);
232 style.apply_text_style(cx, |cx| {
233 self.with_element_id(cx, |this, _global_id, cx| {
234 let layout_ids = this
235 .children
236 .iter_mut()
237 .map(|child| child.layout(view_state, cx))
238 .collect::<SmallVec<_>>();
239 element_state.child_layout_ids = layout_ids.clone();
240 cx.request_layout(&style, layout_ids)
241 })
242 })
243 }
244
245 fn paint(
246 &mut self,
247 bounds: Bounds<Pixels>,
248 view_state: &mut Self::ViewState,
249 element_state: &mut Self::ElementState,
250 cx: &mut ViewContext<Self::ViewState>,
251 ) {
252 self.with_element_id(cx, |this, _global_id, cx| {
253 if let Some(group) = this.group.clone() {
254 GroupBounds::push(group, bounds, cx);
255 }
256
257 let style = this.compute_style(bounds, element_state, cx);
258 let z_index = style.z_index.unwrap_or(0);
259
260 let mut child_min = point(Pixels::MAX, Pixels::MAX);
261 let mut child_max = Point::default();
262
263 let content_size = if element_state.child_layout_ids.is_empty() {
264 bounds.size
265 } else {
266 for child_layout_id in &element_state.child_layout_ids {
267 let child_bounds = cx.layout_bounds(*child_layout_id);
268 child_min = child_min.min(&child_bounds.origin);
269 child_max = child_max.max(&child_bounds.lower_right());
270 }
271 (child_max - child_min).into()
272 };
273
274 cx.stack(z_index, |cx| {
275 cx.stack(0, |cx| {
276 style.paint(bounds, cx);
277 this.focus.paint(bounds, cx);
278 this.interaction.paint(
279 bounds,
280 content_size,
281 style.overflow,
282 &mut element_state.interactive,
283 cx,
284 );
285 });
286 cx.stack(1, |cx| {
287 style.apply_text_style(cx, |cx| {
288 style.apply_overflow(bounds, cx, |cx| {
289 let scroll_offset = element_state.interactive.scroll_offset();
290 cx.with_element_offset(scroll_offset, |cx| {
291 for child in &mut this.children {
292 child.paint(view_state, cx);
293 }
294 });
295 })
296 })
297 });
298 });
299
300 if let Some(group) = this.group.as_ref() {
301 GroupBounds::pop(group, cx);
302 }
303 })
304 }
305}
306
307impl<V, I, F> IntoAnyElement<V> for Div<V, I, F>
308where
309 // V: Any + Send + Sync,
310 I: ElementInteraction<V>,
311 F: ElementFocus<V>,
312{
313 fn into_any(self) -> AnyElement<V> {
314 AnyElement::new(self)
315 }
316}
317
318impl<V, I, F> ParentElement for Div<V, I, F>
319where
320 I: ElementInteraction<V>,
321 F: ElementFocus<V>,
322{
323 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
324 &mut self.children
325 }
326}
327
328impl<V, I, F> Styled for Div<V, I, F>
329where
330 I: ElementInteraction<V>,
331 F: ElementFocus<V>,
332{
333 fn style(&mut self) -> &mut StyleRefinement {
334 &mut self.base_style
335 }
336}
337
338impl<V, I, F> StatelessInteractive for Div<V, I, F>
339where
340 I: ElementInteraction<V>,
341 F: ElementFocus<V>,
342{
343 fn stateless_interaction(&mut self) -> &mut StatelessInteraction<V> {
344 self.interaction.as_stateless_mut()
345 }
346}
347
348impl<V, F> StatefulInteractive for Div<V, StatefulInteraction<V>, F>
349where
350 F: ElementFocus<V>,
351{
352 fn stateful_interaction(&mut self) -> &mut StatefulInteraction<Self::ViewState> {
353 &mut self.interaction
354 }
355}