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}