div.rs

  1use crate::{
  2    AnyElement, BorrowWindow, Bounds, Element, ElementFocus, ElementId, ElementInteraction,
  3    FocusDisabled, FocusEnabled, FocusHandle, FocusListeners, Focusable, GlobalElementId,
  4    GroupBounds, InteractiveElementState, IntoAnyElement, LayoutId, Overflow, ParentElement,
  5    Pixels, Point, SharedString, StatefulInteraction, StatefulInteractive, StatelessInteraction,
  6    StatelessInteractive, Style, StyleRefinement, Styled, ViewContext,
  7};
  8use parking_lot::Mutex;
  9use refineable::Refineable;
 10use smallvec::SmallVec;
 11use std::sync::Arc;
 12
 13#[derive(Default, Clone)]
 14pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
 15
 16impl ScrollState {
 17    pub fn x(&self) -> Pixels {
 18        self.0.lock().x
 19    }
 20
 21    pub fn set_x(&self, value: Pixels) {
 22        self.0.lock().x = value;
 23    }
 24
 25    pub fn y(&self) -> Pixels {
 26        self.0.lock().y
 27    }
 28
 29    pub fn set_y(&self, value: Pixels) {
 30        self.0.lock().y = value;
 31    }
 32}
 33
 34pub struct Div<
 35    V: 'static + Send + Sync,
 36    I: ElementInteraction<V> = StatelessInteraction<V>,
 37    F: ElementFocus<V> = FocusDisabled,
 38> {
 39    interaction: I,
 40    focus: F,
 41    children: SmallVec<[AnyElement<V>; 2]>,
 42    group: Option<SharedString>,
 43    base_style: StyleRefinement,
 44}
 45
 46pub fn div<V>() -> Div<V, StatelessInteraction<V>, FocusDisabled>
 47where
 48    V: 'static + Send + Sync,
 49{
 50    Div {
 51        interaction: StatelessInteraction::default(),
 52        focus: FocusDisabled,
 53        children: SmallVec::new(),
 54        group: None,
 55        base_style: StyleRefinement::default(),
 56    }
 57}
 58
 59impl<V, F> Div<V, StatelessInteraction<V>, F>
 60where
 61    F: ElementFocus<V>,
 62    V: 'static + Send + Sync,
 63{
 64    pub fn id(self, id: impl Into<ElementId>) -> Div<V, StatefulInteraction<V>, F> {
 65        Div {
 66            interaction: id.into().into(),
 67            focus: self.focus,
 68            children: self.children,
 69            group: self.group,
 70            base_style: self.base_style,
 71        }
 72    }
 73}
 74
 75impl<V, I, F> Div<V, I, F>
 76where
 77    I: ElementInteraction<V>,
 78    F: ElementFocus<V>,
 79    V: 'static + Send + Sync,
 80{
 81    pub fn group(mut self, group: impl Into<SharedString>) -> Self {
 82        self.group = Some(group.into());
 83        self
 84    }
 85
 86    pub fn z_index(mut self, z_index: u32) -> Self {
 87        self.base_style.z_index = Some(z_index);
 88        self
 89    }
 90
 91    pub fn overflow_hidden(mut self) -> Self {
 92        self.base_style.overflow.x = Some(Overflow::Hidden);
 93        self.base_style.overflow.y = Some(Overflow::Hidden);
 94        self
 95    }
 96
 97    pub fn overflow_hidden_x(mut self) -> Self {
 98        self.base_style.overflow.x = Some(Overflow::Hidden);
 99        self
100    }
101
102    pub fn overflow_hidden_y(mut self) -> Self {
103        self.base_style.overflow.y = Some(Overflow::Hidden);
104        self
105    }
106
107    pub fn overflow_scroll(mut self, _scroll_state: ScrollState) -> Self {
108        // todo!("impl scrolling")
109        // self.scroll_state = Some(scroll_state);
110        self.base_style.overflow.x = Some(Overflow::Scroll);
111        self.base_style.overflow.y = Some(Overflow::Scroll);
112        self
113    }
114
115    pub fn overflow_x_scroll(mut self, _scroll_state: ScrollState) -> Self {
116        // todo!("impl scrolling")
117        // self.scroll_state = Some(scroll_state);
118        self.base_style.overflow.x = Some(Overflow::Scroll);
119        self
120    }
121
122    pub fn overflow_y_scroll(mut self, _scroll_state: ScrollState) -> Self {
123        // todo!("impl scrolling")
124        // self.scroll_state = Some(scroll_state);
125        self.base_style.overflow.y = Some(Overflow::Scroll);
126        self
127    }
128
129    fn with_element_id<R>(
130        &mut self,
131        cx: &mut ViewContext<V>,
132        f: impl FnOnce(&mut Self, Option<GlobalElementId>, &mut ViewContext<V>) -> R,
133    ) -> R {
134        if let Some(id) = self.id() {
135            cx.with_element_id(id, |global_id, cx| f(self, Some(global_id), cx))
136        } else {
137            f(self, None, cx)
138        }
139    }
140
141    pub fn compute_style(
142        &self,
143        bounds: Bounds<Pixels>,
144        state: &InteractiveElementState,
145        cx: &mut ViewContext<V>,
146    ) -> Style {
147        let mut computed_style = Style::default();
148        computed_style.refine(&self.base_style);
149        self.focus.refine_style(&mut computed_style, cx);
150        self.interaction
151            .refine_style(&mut computed_style, bounds, state, cx);
152        computed_style
153    }
154}
155
156impl<V, I> Div<V, I, FocusDisabled>
157where
158    I: ElementInteraction<V>,
159    V: 'static + Send + Sync,
160{
161    pub fn focusable(self, handle: &FocusHandle) -> Div<V, I, FocusEnabled<V>> {
162        Div {
163            interaction: self.interaction,
164            focus: handle.clone().into(),
165            children: self.children,
166            group: self.group,
167            base_style: self.base_style,
168        }
169    }
170}
171
172impl<V, I> Focusable for Div<V, I, FocusEnabled<V>>
173where
174    I: ElementInteraction<V>,
175    V: 'static + Send + Sync,
176{
177    fn focus_listeners(&mut self) -> &mut FocusListeners<V> {
178        &mut self.focus.focus_listeners
179    }
180
181    fn handle(&self) -> &FocusHandle {
182        &self.focus.focus_handle
183    }
184
185    fn set_focus_style(&mut self, style: StyleRefinement) {
186        self.focus.focus_style = style;
187    }
188
189    fn set_focus_in_style(&mut self, style: StyleRefinement) {
190        self.focus.focus_in_style = style;
191    }
192
193    fn set_in_focus_style(&mut self, style: StyleRefinement) {
194        self.focus.in_focus_style = style;
195    }
196}
197
198impl<V, I, F> Element for Div<V, I, F>
199where
200    I: ElementInteraction<V>,
201    F: ElementFocus<V>,
202    V: 'static + Send + Sync,
203{
204    type ViewState = V;
205    type ElementState = InteractiveElementState;
206
207    fn id(&self) -> Option<ElementId> {
208        self.interaction
209            .as_stateful()
210            .map(|identified| identified.id.clone())
211    }
212
213    fn initialize(
214        &mut self,
215        view_state: &mut Self::ViewState,
216        element_state: Option<Self::ElementState>,
217        cx: &mut ViewContext<Self::ViewState>,
218    ) -> Self::ElementState {
219        self.interaction.initialize(cx, |cx| {
220            self.focus.initialize(cx, |cx| {
221                for child in &mut self.children {
222                    child.initialize(view_state, cx);
223                }
224            });
225        });
226        element_state.unwrap_or_default()
227    }
228
229    fn layout(
230        &mut self,
231        view_state: &mut Self::ViewState,
232        element_state: &mut Self::ElementState,
233        cx: &mut ViewContext<Self::ViewState>,
234    ) -> LayoutId {
235        let style = self.compute_style(Bounds::default(), element_state, cx);
236        style.apply_text_style(cx, |cx| {
237            self.with_element_id(cx, |this, _global_id, cx| {
238                let layout_ids = this
239                    .children
240                    .iter_mut()
241                    .map(|child| child.layout(view_state, cx))
242                    .collect::<Vec<_>>();
243                cx.request_layout(&style, layout_ids)
244            })
245        })
246    }
247
248    fn paint(
249        &mut self,
250        bounds: Bounds<Pixels>,
251        view_state: &mut Self::ViewState,
252        element_state: &mut Self::ElementState,
253        cx: &mut ViewContext<Self::ViewState>,
254    ) {
255        self.with_element_id(cx, |this, _global_id, cx| {
256            if let Some(group) = this.group.clone() {
257                GroupBounds::push(group, bounds, cx);
258            }
259
260            let style = this.compute_style(bounds, element_state, cx);
261            let z_index = style.z_index.unwrap_or(0);
262
263            // Paint background and event handlers.
264            cx.stack(z_index, |cx| {
265                cx.stack(0, |cx| {
266                    style.paint(bounds, cx);
267
268                    this.focus.paint(bounds, cx);
269                    this.interaction.paint(bounds, element_state, cx);
270                });
271
272                cx.stack(1, |cx| {
273                    style.apply_text_style(cx, |cx| {
274                        style.apply_overflow(bounds, cx, |cx| {
275                            for child in &mut this.children {
276                                child.paint(view_state, None, cx);
277                            }
278                        })
279                    })
280                });
281            });
282
283            if let Some(group) = this.group.as_ref() {
284                GroupBounds::pop(group, cx);
285            }
286        })
287    }
288}
289
290impl<V, I, F> IntoAnyElement<V> for Div<V, I, F>
291where
292    I: ElementInteraction<V>,
293    F: ElementFocus<V>,
294    V: 'static + Send + Sync,
295{
296    fn into_any(self) -> AnyElement<V> {
297        AnyElement::new(self)
298    }
299}
300
301impl<V, I, F> ParentElement for Div<V, I, F>
302where
303    I: ElementInteraction<V>,
304    F: ElementFocus<V>,
305    V: 'static + Send + Sync,
306{
307    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::ViewState>; 2]> {
308        &mut self.children
309    }
310}
311
312impl<V, I, F> Styled for Div<V, I, F>
313where
314    I: ElementInteraction<V>,
315    F: ElementFocus<V>,
316    V: 'static + Send + Sync,
317{
318    fn style(&mut self) -> &mut StyleRefinement {
319        &mut self.base_style
320    }
321}
322
323impl<V, I, F> StatelessInteractive for Div<V, I, F>
324where
325    I: ElementInteraction<V>,
326    F: ElementFocus<V>,
327    V: 'static + Send + Sync,
328{
329    fn stateless_interactivity(&mut self) -> &mut StatelessInteraction<V> {
330        self.interaction.as_stateless_mut()
331    }
332}
333
334impl<V, F> StatefulInteractive for Div<V, StatefulInteraction<V>, F>
335where
336    F: ElementFocus<V>,
337    V: 'static + Send + Sync,
338{
339    fn stateful_interactivity(&mut self) -> &mut StatefulInteraction<Self::ViewState> {
340        &mut self.interaction
341    }
342}