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))
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))
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 // let scroll_state = self.scroll_state.as_ref().unwrap().clone();
168 // cx.on_event(order, move |_, event: &ScrollWheelEvent, cx| {
169 // if bounds.contains_point(event.position) {
170 // let scroll_delta = match event.delta {
171 // ScrollDelta::Pixels(delta) => delta,
172 // ScrollDelta::Lines(delta) => cx.text_style().font_size * delta,
173 // };
174 // if overflow.x == Overflow::Scroll {
175 // scroll_state.set_x(
176 // (scroll_state.x() - scroll_delta.x())
177 // .max(px(0.))
178 // .min(scroll_max.x),
179 // );
180 // }
181 // if overflow.y == Overflow::Scroll {
182 // scroll_state.set_y(
183 // (scroll_state.y() - scroll_delta.y())
184 // .max(px(0.))
185 // .min(scroll_max.y),
186 // );
187 // }
188 // cx.repaint();
189 // } else {
190 // cx.bubble_event();
191 // }
192 // })
193 }
194 }
195
196 fn paint_inspector(
197 &self,
198 parent_origin: Point<Pixels>,
199 layout: &Layout,
200 cx: &mut ViewContext<V>,
201 ) {
202 let style = self.styles.merged();
203 let bounds = layout.bounds;
204
205 let hovered = bounds.contains_point(cx.mouse_position());
206 if hovered {
207 let rem_size = cx.rem_size();
208 // cx.scene().push_quad(scene::Quad {
209 // bounds,
210 // background: Some(hsla(0., 0., 1., 0.05).into()),
211 // border: gpui::Border {
212 // color: hsla(0., 0., 1., 0.2).into(),
213 // top: 1.,
214 // right: 1.,
215 // bottom: 1.,
216 // left: 1.,
217 // },
218 // corner_radii: CornerRadii::default()
219 // .refined(&style.corner_radii)
220 // .to_gpui(bounds.size(), rem_size),
221 // })
222 }
223
224 // let pressed = Cell::new(hovered && cx.is_mouse_down(MouseButton::Left));
225 // cx.on_event(layout.order, move |_, event: &MouseButtonEvent, _| {
226 // if bounds.contains_point(event.position) {
227 // if event.is_down {
228 // pressed.set(true);
229 // } else if pressed.get() {
230 // pressed.set(false);
231 // eprintln!("clicked div {:?} {:#?}", bounds, style);
232 // }
233 // }
234 // });
235
236 // let hovered = Cell::new(hovered);
237 // cx.on_event(layout.order, move |_, event: &MouseMovedEvent, cx| {
238 // cx.bubble_event();
239 // let hovered_now = bounds.contains_point(event.position);
240 // if hovered.get() != hovered_now {
241 // hovered.set(hovered_now);
242 // cx.repaint();
243 // }
244 // });
245 }
246}
247
248impl<V> Styled for Div<V> {
249 type Style = Style;
250
251 fn style_cascade(&mut self) -> &mut RefinementCascade<Self::Style> {
252 &mut self.styles
253 }
254
255 fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
256 self.styles.base()
257 }
258}
259
260impl<V> StyleHelpers for Div<V> {}
261
262// impl<V> Interactive<V> for Div<V> {
263// fn interaction_handlers(&mut self) -> &mut InteractionHandlers<V> {
264// &mut self.handlers
265// }
266// }
267
268impl<V: 'static> ParentElement<V> for Div<V> {
269 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
270 &mut self.children
271 }
272}
273
274#[derive(Default, Clone)]
275pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
276
277impl ScrollState {
278 pub fn x(&self) -> Pixels {
279 self.0.lock().x
280 }
281
282 pub fn set_x(&self, value: Pixels) {
283 self.0.lock().x = value;
284 }
285
286 pub fn y(&self) -> Pixels {
287 self.0.lock().y
288 }
289
290 pub fn set_y(&self, value: Pixels) {
291 self.0.lock().y = value;
292 }
293}