div.rs

  1use crate::{
  2    AnyElement, Bounds, Element, ElementId, Interactive, LayoutId, MouseEventListeners, Overflow,
  3    ParentElement, Pixels, Point, Refineable, RefinementCascade, StatefulElement, Style, Styled,
  4    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: RefinementCascade<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: 'static + Send + Sync, Marker: 'static + Send + Sync> Element for Div<S, Marker> {
 33    type ViewState = S;
 34    type ElementState = ();
 35
 36    fn element_id(&self) -> Option<ElementId> {
 37        self.id.clone()
 38    }
 39
 40    fn layout(
 41        &mut self,
 42        view: &mut S,
 43        _: Option<Self::ElementState>,
 44        cx: &mut ViewContext<S>,
 45    ) -> (LayoutId, Self::ElementState) {
 46        let style = self.computed_style();
 47        let child_layout_ids = style.apply_text_style(cx, |cx| self.layout_children(view, cx));
 48        let layout_id = cx.request_layout(style.into(), child_layout_ids.clone());
 49        (layout_id, ())
 50    }
 51
 52    fn paint(
 53        &mut self,
 54        bounds: Bounds<Pixels>,
 55        state: &mut S,
 56        _: &mut (),
 57        cx: &mut ViewContext<S>,
 58    ) {
 59        let style = self.computed_style();
 60        cx.stack(0, |cx| style.paint(bounds, cx));
 61
 62        let overflow = &style.overflow;
 63        style.apply_text_style(cx, |cx| {
 64            cx.stack(1, |cx| {
 65                style.apply_overflow(bounds, cx, |cx| {
 66                    self.listeners.paint(bounds, cx);
 67                    self.paint_children(overflow, state, cx)
 68                })
 69            })
 70        });
 71    }
 72}
 73
 74impl<S> Div<S, ()>
 75where
 76    S: 'static + Send + Sync,
 77{
 78    pub fn id(self, id: impl Into<ElementId>) -> Div<S, HasId> {
 79        Div {
 80            styles: self.styles,
 81            id: Some(id.into()),
 82            listeners: self.listeners,
 83            children: self.children,
 84            scroll_state: self.scroll_state,
 85            identified: PhantomData,
 86        }
 87    }
 88}
 89
 90impl<S, Marker> Div<S, Marker>
 91where
 92    S: 'static + Send + Sync,
 93    Marker: 'static + Send + Sync,
 94{
 95    pub fn overflow_hidden(mut self) -> Self {
 96        self.declared_style().overflow.x = Some(Overflow::Hidden);
 97        self.declared_style().overflow.y = Some(Overflow::Hidden);
 98        self
 99    }
100
101    pub fn overflow_hidden_x(mut self) -> Self {
102        self.declared_style().overflow.x = Some(Overflow::Hidden);
103        self
104    }
105
106    pub fn overflow_hidden_y(mut self) -> Self {
107        self.declared_style().overflow.y = Some(Overflow::Hidden);
108        self
109    }
110
111    pub fn overflow_scroll(mut self, scroll_state: ScrollState) -> Self {
112        self.scroll_state = Some(scroll_state);
113        self.declared_style().overflow.x = Some(Overflow::Scroll);
114        self.declared_style().overflow.y = Some(Overflow::Scroll);
115        self
116    }
117
118    pub fn overflow_x_scroll(mut self, scroll_state: ScrollState) -> Self {
119        self.scroll_state = Some(scroll_state);
120        self.declared_style().overflow.x = Some(Overflow::Scroll);
121        self
122    }
123
124    pub fn overflow_y_scroll(mut self, scroll_state: ScrollState) -> Self {
125        self.scroll_state = Some(scroll_state);
126        self.declared_style().overflow.y = Some(Overflow::Scroll);
127        self
128    }
129
130    fn scroll_offset(&self, overflow: &Point<Overflow>) -> Point<Pixels> {
131        let mut offset = Point::default();
132        if overflow.y == Overflow::Scroll {
133            offset.y = self.scroll_state.as_ref().unwrap().y();
134        }
135        if overflow.x == Overflow::Scroll {
136            offset.x = self.scroll_state.as_ref().unwrap().x();
137        }
138
139        offset
140    }
141
142    fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> Vec<LayoutId> {
143        self.children
144            .iter_mut()
145            .map(|child| child.layout(view, cx))
146            .collect()
147    }
148
149    fn paint_children(
150        &mut self,
151        overflow: &Point<Overflow>,
152        state: &mut S,
153        cx: &mut ViewContext<S>,
154    ) {
155        let scroll_offset = self.scroll_offset(overflow);
156        for child in &mut self.children {
157            child.paint(state, Some(scroll_offset), cx);
158        }
159    }
160}
161
162impl<V: 'static + Send + Sync, Marker: 'static + Send + Sync> Styled for Div<V, Marker> {
163    type Style = Style;
164
165    fn style_cascade(&mut self) -> &mut RefinementCascade<Self::Style> {
166        &mut self.styles
167    }
168
169    fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
170        self.styles.base()
171    }
172}
173
174impl<V: Send + Sync + 'static> StatefulElement for Div<V, HasId> {}
175
176impl<V: Send + Sync + 'static> Interactive<V> for Div<V, HasId> {
177    fn listeners(&mut self) -> &mut MouseEventListeners<V> {
178        &mut self.listeners
179    }
180}
181
182impl<S: 'static> ParentElement for Div<S> {
183    type State = S;
184
185    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<S>; 2]> {
186        &mut self.children
187    }
188}
189
190#[derive(Default, Clone)]
191pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
192
193impl ScrollState {
194    pub fn x(&self) -> Pixels {
195        self.0.lock().x
196    }
197
198    pub fn set_x(&self, value: Pixels) {
199        self.0.lock().x = value;
200    }
201
202    pub fn y(&self) -> Pixels {
203        self.0.lock().y
204    }
205
206    pub fn set_y(&self, value: Pixels) {
207        self.0.lock().y = value;
208    }
209}