div.rs

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