layout_node.rs

  1use crate::{
  2    AnyElement, AppContext, BorrowWindow, Bounds, Element, ElementId, IdentifiedElement,
  3    IntoAnyElement, LayoutId, Pixels, SharedString, Style, StyleCascade, Styled, ViewContext,
  4};
  5use collections::HashMap;
  6use refineable::Refineable;
  7use smallvec::SmallVec;
  8
  9#[derive(Default)]
 10struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
 11
 12pub fn group_bounds(name: &SharedString, cx: &mut AppContext) -> Option<Bounds<Pixels>> {
 13    cx.default_global::<GroupBounds>()
 14        .0
 15        .get(name)
 16        .and_then(|bounds_stack| bounds_stack.last().cloned())
 17}
 18
 19pub trait LayoutNode<V: 'static + Send + Sync, K: ElementKind> {
 20    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]>;
 21    fn group_mut(&mut self) -> &mut Option<SharedString>;
 22
 23    fn child(mut self, child: impl IntoAnyElement<V>) -> Self
 24    where
 25        Self: Sized,
 26    {
 27        self.children_mut().push(child.into_any());
 28        self
 29    }
 30
 31    fn children<C, E>(mut self, children: C) -> Self
 32    where
 33        C: IntoIterator<Item = E>,
 34        E: IntoAnyElement<V>,
 35        Self: Sized,
 36    {
 37        for child in children {
 38            self.children_mut().push(child.into_any());
 39        }
 40        self
 41    }
 42}
 43
 44pub trait ElementKind: 'static + Send + Sync {
 45    fn id(&self) -> Option<ElementId>;
 46}
 47
 48pub struct IdentifiedElementKind(ElementId);
 49pub struct AnonymousElementKind;
 50
 51impl ElementKind for IdentifiedElementKind {
 52    fn id(&self) -> Option<ElementId> {
 53        Some(self.0.clone())
 54    }
 55}
 56
 57impl ElementKind for AnonymousElementKind {
 58    fn id(&self) -> Option<ElementId> {
 59        None
 60    }
 61}
 62
 63pub struct LayoutNodeElement<V: 'static + Send + Sync, K: ElementKind> {
 64    style_cascade: StyleCascade,
 65    computed_style: Option<Style>,
 66    children: SmallVec<[AnyElement<V>; 2]>,
 67    kind: K,
 68    group: Option<SharedString>,
 69}
 70
 71impl<V: 'static + Send + Sync> LayoutNodeElement<V, AnonymousElementKind> {
 72    pub fn identify(self, id: impl Into<ElementId>) -> LayoutNodeElement<V, IdentifiedElementKind> {
 73        LayoutNodeElement {
 74            style_cascade: self.style_cascade,
 75            computed_style: self.computed_style,
 76            children: self.children,
 77            kind: IdentifiedElementKind(id.into()),
 78            group: self.group,
 79        }
 80    }
 81}
 82
 83impl<V: 'static + Send + Sync, E: ElementKind> LayoutNodeElement<V, E> {
 84    pub fn set_group(&mut self, group: impl Into<SharedString>) {
 85        self.group = Some(group.into());
 86    }
 87
 88    fn with_element_id<R>(
 89        &mut self,
 90        cx: &mut ViewContext<V>,
 91        f: impl FnOnce(&mut Self, &mut ViewContext<V>) -> R,
 92    ) -> R {
 93        if let Some(id) = self.id() {
 94            cx.with_element_id(id, |cx| f(self, cx))
 95        } else {
 96            f(self, cx)
 97        }
 98    }
 99}
100
101impl<V: 'static + Send + Sync, K: ElementKind> Styled for LayoutNodeElement<V, K> {
102    fn style_cascade(&mut self) -> &mut StyleCascade {
103        &mut self.style_cascade
104    }
105
106    fn computed_style(&mut self) -> &Style {
107        self.computed_style
108            .get_or_insert_with(|| Style::default().refined(self.style_cascade.merged()))
109    }
110}
111
112impl<V: 'static + Send + Sync> IdentifiedElement for LayoutNodeElement<V, IdentifiedElementKind> {
113    fn id(&self) -> ElementId {
114        self.kind.0.clone()
115    }
116}
117
118impl<V, K> IntoAnyElement<V> for LayoutNodeElement<V, K>
119where
120    V: 'static + Send + Sync,
121    K: ElementKind,
122{
123    fn into_any(self) -> AnyElement<V> {
124        AnyElement::new(self)
125    }
126}
127
128impl<V: 'static + Send + Sync, K: ElementKind> Element for LayoutNodeElement<V, K> {
129    type ViewState = V;
130    type ElementState = ();
131
132    fn id(&self) -> Option<ElementId> {
133        self.kind.id()
134    }
135
136    fn layout(
137        &mut self,
138        state: &mut Self::ViewState,
139        _: Option<Self::ElementState>,
140        cx: &mut ViewContext<Self::ViewState>,
141    ) -> (LayoutId, Self::ElementState) {
142        self.with_element_id(cx, |this, cx| {
143            let layout_ids = this
144                .children
145                .iter_mut()
146                .map(|child| child.layout(state, cx))
147                .collect::<Vec<_>>();
148
149            let style = this.computed_style();
150            let layout_id = cx.request_layout(style, layout_ids);
151            (layout_id, ())
152        })
153    }
154
155    fn paint(
156        &mut self,
157        bounds: Bounds<Pixels>,
158        state: &mut Self::ViewState,
159        _: &mut Self::ElementState,
160        cx: &mut ViewContext<Self::ViewState>,
161    ) {
162        self.with_element_id(cx, |this, cx| {
163            if let Some(group) = this.group.clone() {
164                cx.default_global::<GroupBounds>()
165                    .0
166                    .entry(group)
167                    .or_default()
168                    .push(bounds);
169            }
170
171            let style = this.computed_style().clone();
172            let z_index = style.z_index.unwrap_or(0);
173            cx.stack(z_index, |cx| style.paint(bounds, cx));
174
175            // todo!("implement overflow")
176            // let overflow = &style.overflow;
177
178            style.apply_text_style(cx, |cx| {
179                cx.stack(z_index + 1, |cx| {
180                    style.apply_overflow(bounds, cx, |cx| {
181                        for child in &mut this.children {
182                            child.paint(state, None, cx);
183                        }
184                    })
185                })
186            });
187
188            if let Some(group) = this.group.as_ref() {
189                cx.default_global::<GroupBounds>()
190                    .0
191                    .get_mut(group)
192                    .unwrap()
193                    .pop();
194            }
195        })
196    }
197}
198
199impl<V: 'static + Send + Sync, K: ElementKind> LayoutNode<V, K> for LayoutNodeElement<V, K> {
200    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
201        &mut self.children
202    }
203
204    fn group_mut(&mut self) -> &mut Option<SharedString> {
205        &mut self.group
206    }
207}