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