div.rs

  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}