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