div.rs

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