div.rs

  1use crate::{
  2    AnyElement, Bounds, Element, Layout, LayoutId, Overflow, ParentElement, Pixels, Point,
  3    Refineable, RefinementCascade, Result, StackContext, Style, StyleHelpers, Styled, ViewContext,
  4};
  5use parking_lot::Mutex;
  6use smallvec::SmallVec;
  7use std::sync::Arc;
  8use util::ResultExt;
  9
 10pub struct Div<S: 'static> {
 11    styles: RefinementCascade<Style>,
 12    // handlers: InteractionHandlers<V>,
 13    children: SmallVec<[AnyElement<S>; 2]>,
 14    scroll_state: Option<ScrollState>,
 15}
 16
 17pub fn div<S>() -> Div<S> {
 18    Div {
 19        styles: Default::default(),
 20        // handlers: Default::default(),
 21        children: Default::default(),
 22        scroll_state: None,
 23    }
 24}
 25
 26impl<S: 'static + Send + Sync> Element for Div<S> {
 27    type State = S;
 28    type FrameState = Vec<LayoutId>;
 29
 30    fn layout(
 31        &mut self,
 32        view: &mut S,
 33        cx: &mut ViewContext<S>,
 34    ) -> Result<(LayoutId, Self::FrameState)> {
 35        let style = self.computed_style();
 36        let child_layout_ids = if let Some(text_style) = style.text_style(cx) {
 37            cx.with_text_style(text_style.clone(), |cx| self.layout_children(view, cx))?
 38        } else {
 39            self.layout_children(view, cx)?
 40        };
 41
 42        Ok((
 43            cx.request_layout(style.into(), child_layout_ids.clone())?,
 44            child_layout_ids,
 45        ))
 46    }
 47
 48    fn paint(
 49        &mut self,
 50        layout: Layout,
 51        state: &mut S,
 52        child_layouts: &mut Self::FrameState,
 53        cx: &mut ViewContext<S>,
 54    ) -> Result<()> {
 55        let Layout { order, bounds } = layout;
 56
 57        let style = self.computed_style();
 58        style.paint_background(bounds, cx);
 59        let overflow = &style.overflow;
 60        // // todo!("support only one dimension being hidden")
 61        // if style.overflow.y != Overflow::Visible || style.overflow.x != Overflow::Visible {
 62        //     cx.scene().push_layer(Some(bounds));
 63        //     pop_layer = true;
 64        // }
 65        if let Some(text_style) = style.text_style(cx) {
 66            cx.with_text_style(text_style.clone(), |cx| {
 67                self.paint_children(overflow, state, cx)
 68            })?;
 69        } else {
 70            self.paint_children(overflow, state, cx)?;
 71        }
 72        style.paint_foreground(bounds, cx);
 73
 74        self.handle_scroll(order, bounds, style.overflow.clone(), child_layouts, cx);
 75
 76        // todo!("enable inspector")
 77        // if cx.is_inspector_enabled() {
 78        //     self.paint_inspector(parent_origin, layout, cx);
 79        // }
 80        //
 81        Ok(())
 82    }
 83}
 84
 85impl<S: 'static> Div<S> {
 86    pub fn overflow_hidden(mut self) -> Self {
 87        self.declared_style().overflow.x = Some(Overflow::Hidden);
 88        self.declared_style().overflow.y = Some(Overflow::Hidden);
 89        self
 90    }
 91
 92    pub fn overflow_hidden_x(mut self) -> Self {
 93        self.declared_style().overflow.x = Some(Overflow::Hidden);
 94        self
 95    }
 96
 97    pub fn overflow_hidden_y(mut self) -> Self {
 98        self.declared_style().overflow.y = Some(Overflow::Hidden);
 99        self
100    }
101
102    pub fn overflow_scroll(mut self, scroll_state: ScrollState) -> Self {
103        self.scroll_state = Some(scroll_state);
104        self.declared_style().overflow.x = Some(Overflow::Scroll);
105        self.declared_style().overflow.y = Some(Overflow::Scroll);
106        self
107    }
108
109    pub fn overflow_x_scroll(mut self, scroll_state: ScrollState) -> Self {
110        self.scroll_state = Some(scroll_state);
111        self.declared_style().overflow.x = Some(Overflow::Scroll);
112        self
113    }
114
115    pub fn overflow_y_scroll(mut self, scroll_state: ScrollState) -> Self {
116        self.scroll_state = Some(scroll_state);
117        self.declared_style().overflow.y = Some(Overflow::Scroll);
118        self
119    }
120
121    fn scroll_offset(&self, overflow: &Point<Overflow>) -> Point<Pixels> {
122        let mut offset = Point::default();
123        if overflow.y == Overflow::Scroll {
124            offset.y = self.scroll_state.as_ref().unwrap().y();
125        }
126        if overflow.x == Overflow::Scroll {
127            offset.x = self.scroll_state.as_ref().unwrap().x();
128        }
129
130        offset
131    }
132
133    fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> Result<Vec<LayoutId>> {
134        self.children
135            .iter_mut()
136            .map(|child| child.layout(view, cx))
137            .collect::<Result<Vec<LayoutId>>>()
138    }
139
140    fn paint_children(
141        &mut self,
142        overflow: &Point<Overflow>,
143        state: &mut S,
144        cx: &mut ViewContext<S>,
145    ) -> Result<()> {
146        let scroll_offset = self.scroll_offset(overflow);
147        for child in &mut self.children {
148            child.paint(state, Some(scroll_offset), cx)?;
149        }
150        Ok(())
151    }
152
153    fn handle_scroll(
154        &mut self,
155        _order: u32,
156        bounds: Bounds<Pixels>,
157        overflow: Point<Overflow>,
158        child_layout_ids: &[LayoutId],
159        cx: &mut ViewContext<S>,
160    ) {
161        if overflow.y == Overflow::Scroll || overflow.x == Overflow::Scroll {
162            let mut scroll_max = Point::default();
163            for child_layout_id in child_layout_ids {
164                if let Some(child_layout) = cx.layout(*child_layout_id).log_err() {
165                    scroll_max = scroll_max.max(&child_layout.bounds.lower_right());
166                }
167            }
168            scroll_max -= bounds.size;
169
170            // todo!("handle scroll")
171            // let scroll_state = self.scroll_state.as_ref().unwrap().clone();
172            // cx.on_event(order, move |_, event: &ScrollWheelEvent, cx| {
173            //     if bounds.contains_point(event.position) {
174            //         let scroll_delta = match event.delta {
175            //             ScrollDelta::Pixels(delta) => delta,
176            //             ScrollDelta::Lines(delta) => cx.text_style().font_size * delta,
177            //         };
178            //         if overflow.x == Overflow::Scroll {
179            //             scroll_state.set_x(
180            //                 (scroll_state.x() - scroll_delta.x())
181            //                     .max(px(0.))
182            //                     .min(scroll_max.x),
183            //             );
184            //         }
185            //         if overflow.y == Overflow::Scroll {
186            //             scroll_state.set_y(
187            //                 (scroll_state.y() - scroll_delta.y())
188            //                     .max(px(0.))
189            //                     .min(scroll_max.y),
190            //             );
191            //         }
192            //         cx.repaint();
193            //     } else {
194            //         cx.bubble_event();
195            //     }
196            // })
197        }
198    }
199
200    // fn paint_inspector(
201    //     &self,
202    //     parent_origin: Point<Pixels>,
203    //     layout: &Layout,
204    //     cx: &mut ViewContext<V>,
205    // ) {
206    //     let style = self.styles.merged();
207    //     let bounds = layout.bounds;
208
209    //     let hovered = bounds.contains_point(cx.mouse_position());
210    //     if hovered {
211    //         let rem_size = cx.rem_size();
212    //         // cx.scene().push_quad(scene::Quad {
213    //         //     bounds,
214    //         //     background: Some(hsla(0., 0., 1., 0.05).into()),
215    //         //     border: gpui::Border {
216    //         //         color: hsla(0., 0., 1., 0.2).into(),
217    //         //         top: 1.,
218    //         //         right: 1.,
219    //         //         bottom: 1.,
220    //         //         left: 1.,
221    //         //     },
222    //         //     corner_radii: CornerRadii::default()
223    //         //         .refined(&style.corner_radii)
224    //         //         .to_gpui(bounds.size(), rem_size),
225    //         // })
226    //     }
227
228    //     // let pressed = Cell::new(hovered && cx.is_mouse_down(MouseButton::Left));
229    //     // cx.on_event(layout.order, move |_, event: &MouseButtonEvent, _| {
230    //     //     if bounds.contains_point(event.position) {
231    //     //         if event.is_down {
232    //     //             pressed.set(true);
233    //     //         } else if pressed.get() {
234    //     //             pressed.set(false);
235    //     //             eprintln!("clicked div {:?} {:#?}", bounds, style);
236    //     //         }
237    //     //     }
238    //     // });
239
240    //     // let hovered = Cell::new(hovered);
241    //     // cx.on_event(layout.order, move |_, event: &MouseMovedEvent, cx| {
242    //     //     cx.bubble_event();
243    //     //     let hovered_now = bounds.contains_point(event.position);
244    //     //     if hovered.get() != hovered_now {
245    //     //         hovered.set(hovered_now);
246    //     //         cx.repaint();
247    //     //     }
248    //     // });
249    // }
250    //
251}
252
253impl<V> Styled for Div<V> {
254    type Style = Style;
255
256    fn style_cascade(&mut self) -> &mut RefinementCascade<Self::Style> {
257        &mut self.styles
258    }
259
260    fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
261        self.styles.base()
262    }
263}
264
265impl<V> StyleHelpers for Div<V> {}
266
267// impl<V> Interactive<V> for Div<V> {
268//     fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
269//         &mut self.handlers
270//     }
271// }
272
273impl<V: 'static> ParentElement<V> for Div<V> {
274    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
275        &mut self.children
276    }
277}
278
279#[derive(Default, Clone)]
280pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
281
282impl ScrollState {
283    pub fn x(&self) -> Pixels {
284        self.0.lock().x
285    }
286
287    pub fn set_x(&self, value: Pixels) {
288        self.0.lock().x = value;
289    }
290
291    pub fn y(&self) -> Pixels {
292        self.0.lock().y
293    }
294
295    pub fn set_y(&self, value: Pixels) {
296        self.0.lock().y = value;
297    }
298}