div.rs

  1use crate::{
  2    AnyElement, BorrowWindow, Bounds, Cascade, Element, ElementId, IdentifiedElement, Interactive,
  3    IntoAnyElement, LayoutId, MouseEventListeners, Overflow, ParentElement, Pixels, Point,
  4    Refineable, Style, Styled, ViewContext,
  5};
  6use parking_lot::Mutex;
  7use smallvec::SmallVec;
  8use std::{marker::PhantomData, sync::Arc};
  9
 10pub enum HasId {}
 11
 12pub struct Div<S: 'static, I = ()> {
 13    styles: Cascade<Style>,
 14    id: Option<ElementId>,
 15    listeners: MouseEventListeners<S>,
 16    children: SmallVec<[AnyElement<S>; 2]>,
 17    scroll_state: Option<ScrollState>,
 18    identified: PhantomData<I>,
 19}
 20
 21pub fn div<S>() -> Div<S> {
 22    Div {
 23        styles: Default::default(),
 24        id: None,
 25        listeners: Default::default(),
 26        children: Default::default(),
 27        scroll_state: None,
 28        identified: PhantomData,
 29    }
 30}
 31
 32impl<S, Marker> IntoAnyElement<S> for Div<S, Marker>
 33where
 34    S: 'static + Send + Sync,
 35    Marker: 'static + Send + Sync,
 36{
 37    fn into_any(self) -> AnyElement<S> {
 38        AnyElement::new(self)
 39    }
 40}
 41
 42impl<S, Marker> Element for Div<S, Marker>
 43where
 44    S: 'static + Send + Sync,
 45    Marker: 'static + Send + Sync,
 46{
 47    type ViewState = S;
 48    type ElementState = ();
 49
 50    fn element_id(&self) -> Option<ElementId> {
 51        self.id.clone()
 52    }
 53
 54    fn layout(
 55        &mut self,
 56        view: &mut S,
 57        _: Option<Self::ElementState>,
 58        cx: &mut ViewContext<S>,
 59    ) -> (LayoutId, Self::ElementState) {
 60        let style = self.computed_style();
 61        let child_layout_ids = style.apply_text_style(cx, |cx| {
 62            self.with_element_id(cx, |this, cx| this.layout_children(view, cx))
 63        });
 64        let layout_id = cx.request_layout(style.into(), child_layout_ids.clone());
 65        (layout_id, ())
 66    }
 67
 68    fn paint(
 69        &mut self,
 70        bounds: Bounds<Pixels>,
 71        state: &mut S,
 72        _: &mut (),
 73        cx: &mut ViewContext<S>,
 74    ) {
 75        let style = self.computed_style();
 76        let z_index = style.z_index.unwrap_or(0);
 77        cx.stack(z_index, |cx| style.paint(bounds, cx));
 78
 79        let overflow = &style.overflow;
 80
 81        style.apply_text_style(cx, |cx| {
 82            cx.stack(z_index + 1, |cx| {
 83                style.apply_overflow(bounds, cx, |cx| {
 84                    self.with_element_id(cx, |this, cx| {
 85                        this.listeners.paint(bounds, cx);
 86                        this.paint_children(overflow, state, cx)
 87                    });
 88                })
 89            })
 90        });
 91    }
 92}
 93
 94impl<S> Div<S, ()>
 95where
 96    S: 'static + Send + Sync,
 97{
 98    pub fn id(self, id: impl Into<ElementId>) -> Div<S, HasId> {
 99        Div {
100            styles: self.styles,
101            id: Some(id.into()),
102            listeners: self.listeners,
103            children: self.children,
104            scroll_state: self.scroll_state,
105            identified: PhantomData,
106        }
107    }
108}
109
110impl<S, Marker> Div<S, Marker>
111where
112    S: 'static + Send + Sync,
113    Marker: 'static + Send + Sync,
114{
115    pub fn z_index(mut self, z_index: u32) -> Self {
116        self.declared_style().z_index = Some(z_index);
117        self
118    }
119
120    pub fn overflow_hidden(mut self) -> Self {
121        self.declared_style().overflow.x = Some(Overflow::Hidden);
122        self.declared_style().overflow.y = Some(Overflow::Hidden);
123        self
124    }
125
126    pub fn overflow_hidden_x(mut self) -> Self {
127        self.declared_style().overflow.x = Some(Overflow::Hidden);
128        self
129    }
130
131    pub fn overflow_hidden_y(mut self) -> Self {
132        self.declared_style().overflow.y = Some(Overflow::Hidden);
133        self
134    }
135
136    pub fn overflow_scroll(mut self, scroll_state: ScrollState) -> Self {
137        self.scroll_state = Some(scroll_state);
138        self.declared_style().overflow.x = Some(Overflow::Scroll);
139        self.declared_style().overflow.y = Some(Overflow::Scroll);
140        self
141    }
142
143    pub fn overflow_x_scroll(mut self, scroll_state: ScrollState) -> Self {
144        self.scroll_state = Some(scroll_state);
145        self.declared_style().overflow.x = Some(Overflow::Scroll);
146        self
147    }
148
149    pub fn overflow_y_scroll(mut self, scroll_state: ScrollState) -> Self {
150        self.scroll_state = Some(scroll_state);
151        self.declared_style().overflow.y = Some(Overflow::Scroll);
152        self
153    }
154
155    fn scroll_offset(&self, overflow: &Point<Overflow>) -> Point<Pixels> {
156        let mut offset = Point::default();
157        if overflow.y == Overflow::Scroll {
158            offset.y = self.scroll_state.as_ref().unwrap().y();
159        }
160        if overflow.x == Overflow::Scroll {
161            offset.x = self.scroll_state.as_ref().unwrap().x();
162        }
163
164        offset
165    }
166
167    fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> Vec<LayoutId> {
168        self.children
169            .iter_mut()
170            .map(|child| child.layout(view, cx))
171            .collect()
172    }
173
174    fn paint_children(
175        &mut self,
176        overflow: &Point<Overflow>,
177        state: &mut S,
178        cx: &mut ViewContext<S>,
179    ) {
180        let scroll_offset = self.scroll_offset(overflow);
181        for child in &mut self.children {
182            child.paint(state, Some(scroll_offset), cx);
183        }
184    }
185
186    fn with_element_id<R>(
187        &mut self,
188        cx: &mut ViewContext<S>,
189        f: impl FnOnce(&mut Self, &mut ViewContext<S>) -> R,
190    ) -> R {
191        if let Some(element_id) = self.element_id() {
192            cx.with_element_id(element_id, |cx| f(self, cx))
193        } else {
194            f(self, cx)
195        }
196    }
197}
198
199impl<V: 'static + Send + Sync, Marker: 'static + Send + Sync> Styled for Div<V, Marker> {
200    type Style = Style;
201
202    fn style_cascade(&mut self) -> &mut Cascade<Self::Style> {
203        &mut self.styles
204    }
205
206    fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
207        self.styles.base()
208    }
209}
210
211impl<V: Send + Sync + 'static> IdentifiedElement for Div<V, HasId> {}
212
213impl<V: Send + Sync + 'static, Marker: 'static + Send + Sync> Interactive<V> for Div<V, Marker> {
214    fn listeners(&mut self) -> &mut MouseEventListeners<V> {
215        &mut self.listeners
216    }
217}
218
219impl<V: 'static, Marker: 'static + Send + Sync> ParentElement for Div<V, Marker> {
220    type State = V;
221
222    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
223        &mut self.children
224    }
225}
226
227#[derive(Default, Clone)]
228pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
229
230impl ScrollState {
231    pub fn x(&self) -> Pixels {
232        self.0.lock().x
233    }
234
235    pub fn set_x(&self, value: Pixels) {
236        self.0.lock().x = value;
237    }
238
239    pub fn y(&self) -> Pixels {
240        self.0.lock().y
241    }
242
243    pub fn set_y(&self, value: Pixels) {
244        self.0.lock().y = value;
245    }
246}