1use crate::{
2 AnyElement, Bounds, Element, LayoutId, Overflow, ParentElement, Pixels, Point, Refineable,
3 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 bounds: Bounds<Pixels>,
44 state: &mut S,
45 child_layouts: &mut Self::FrameState,
46 cx: &mut ViewContext<S>,
47 ) -> Result<()> {
48 let style = self.computed_style();
49 let z_index = style.z_index.unwrap_or(0);
50 cx.stack(z_index, |cx| style.paint(bounds, cx));
51
52 let overflow = &style.overflow;
53 style.apply_text_style(cx, |cx| {
54 cx.stack(z_index + 1, |cx| {
55 style.apply_overflow(bounds, cx, |cx| self.paint_children(overflow, state, cx))
56 })
57 })?;
58 self.handle_scroll(bounds, style.overflow.clone(), child_layouts, cx);
59
60 // todo!("enable inspector")
61 // if cx.is_inspector_enabled() {
62 // self.paint_inspector(parent_origin, layout, cx);
63 // }
64 //
65
66 Ok(())
67 }
68}
69
70impl<S: 'static> Div<S> {
71 pub fn z_index(mut self, z_index: u32) -> Self {
72 self.declared_style().z_index = Some(z_index);
73 self
74 }
75
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 bounds: Bounds<Pixels>,
146 overflow: Point<Overflow>,
147 child_layout_ids: &[LayoutId],
148 cx: &mut ViewContext<S>,
149 ) {
150 if overflow.y == Overflow::Scroll || overflow.x == Overflow::Scroll {
151 let mut scroll_max = Point::default();
152 for child_layout_id in child_layout_ids {
153 if let Some(child_bounds) = cx.layout_bounds(*child_layout_id).log_err() {
154 scroll_max = scroll_max.max(&child_bounds.lower_right());
155 }
156 }
157 scroll_max -= bounds.size;
158
159 // todo!("handle scroll")
160 // let scroll_state = self.scroll_state.as_ref().unwrap().clone();
161 // cx.on_event(order, move |_, event: &ScrollWheelEvent, cx| {
162 // if bounds.contains_point(event.position) {
163 // let scroll_delta = match event.delta {
164 // ScrollDelta::Pixels(delta) => delta,
165 // ScrollDelta::Lines(delta) => cx.text_style().font_size * delta,
166 // };
167 // if overflow.x == Overflow::Scroll {
168 // scroll_state.set_x(
169 // (scroll_state.x() - scroll_delta.x())
170 // .max(px(0.))
171 // .min(scroll_max.x),
172 // );
173 // }
174 // if overflow.y == Overflow::Scroll {
175 // scroll_state.set_y(
176 // (scroll_state.y() - scroll_delta.y())
177 // .max(px(0.))
178 // .min(scroll_max.y),
179 // );
180 // }
181 // cx.repaint();
182 // } else {
183 // cx.bubble_event();
184 // }
185 // })
186 }
187 }
188
189 // fn paint_inspector(
190 // &self,
191 // parent_origin: Point<Pixels>,
192 // layout: &Layout,
193 // cx: &mut ViewContext<V>,
194 // ) {
195 // let style = self.styles.merged();
196 // let bounds = layout.bounds;
197
198 // let hovered = bounds.contains_point(cx.mouse_position());
199 // if hovered {
200 // let rem_size = cx.rem_size();
201 // // cx.scene().push_quad(scene::Quad {
202 // // bounds,
203 // // background: Some(hsla(0., 0., 1., 0.05).into()),
204 // // border: gpui::Border {
205 // // color: hsla(0., 0., 1., 0.2).into(),
206 // // top: 1.,
207 // // right: 1.,
208 // // bottom: 1.,
209 // // left: 1.,
210 // // },
211 // // corner_radii: CornerRadii::default()
212 // // .refined(&style.corner_radii)
213 // // .to_gpui(bounds.size(), rem_size),
214 // // })
215 // }
216
217 // // let pressed = Cell::new(hovered && cx.is_mouse_down(MouseButton::Left));
218 // // cx.on_event(layout.order, move |_, event: &MouseButtonEvent, _| {
219 // // if bounds.contains_point(event.position) {
220 // // if event.is_down {
221 // // pressed.set(true);
222 // // } else if pressed.get() {
223 // // pressed.set(false);
224 // // eprintln!("clicked div {:?} {:#?}", bounds, style);
225 // // }
226 // // }
227 // // });
228
229 // // let hovered = Cell::new(hovered);
230 // // cx.on_event(layout.order, move |_, event: &MouseMovedEvent, cx| {
231 // // cx.bubble_event();
232 // // let hovered_now = bounds.contains_point(event.position);
233 // // if hovered.get() != hovered_now {
234 // // hovered.set(hovered_now);
235 // // cx.repaint();
236 // // }
237 // // });
238 // }
239 //
240}
241
242impl<V> Styled for Div<V> {
243 type Style = Style;
244
245 fn style_cascade(&mut self) -> &mut RefinementCascade<Self::Style> {
246 &mut self.styles
247 }
248
249 fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
250 self.styles.base()
251 }
252}
253
254impl<V> StyleHelpers for Div<V> {}
255
256// impl<V> Interactive<V> for Div<V> {
257// fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
258// &mut self.handlers
259// }
260// }
261
262impl<V: 'static> ParentElement<V> for Div<V> {
263 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
264 &mut self.children
265 }
266}
267
268#[derive(Default, Clone)]
269pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
270
271impl ScrollState {
272 pub fn x(&self) -> Pixels {
273 self.0.lock().x
274 }
275
276 pub fn set_x(&self, value: Pixels) {
277 self.0.lock().x = value;
278 }
279
280 pub fn y(&self) -> Pixels {
281 self.0.lock().y
282 }
283
284 pub fn set_y(&self, value: Pixels) {
285 self.0.lock().y = value;
286 }
287}