div.rs

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