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