div.rs

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