1use crate::{
2 AnyElement, Bounds, Element, Layout, LayoutId, Overflow, ParentElement, Pixels, Point,
3 Refineable, RefinementCascade, Result, Style, StyleHelpers, Styled, ViewContext,
4};
5use smallvec::SmallVec;
6use std::{cell::Cell, rc::Rc};
7use util::ResultExt;
8
9pub struct Div<S: 'static> {
10 styles: RefinementCascade<Style>,
11 // handlers: InteractionHandlers<V>,
12 children: SmallVec<[AnyElement<S>; 2]>,
13 scroll_state: Option<ScrollState>,
14}
15
16pub fn div<S>() -> Div<S> {
17 Div {
18 styles: Default::default(),
19 // handlers: Default::default(),
20 children: Default::default(),
21 scroll_state: None,
22 }
23}
24
25impl<S: 'static> Element for Div<S> {
26 type State = S;
27 type FrameState = Vec<LayoutId>;
28
29 fn layout(
30 &mut self,
31 view: &mut S,
32 cx: &mut ViewContext<S>,
33 ) -> Result<(LayoutId, Self::FrameState)> {
34 let style = self.computed_style();
35 let pop_text_style = style
36 .text_style(cx)
37 .map(|style| cx.push_text_style(style))
38 .is_some();
39
40 let children = self
41 .children
42 .iter_mut()
43 .map(|child| child.layout(view, cx))
44 .collect::<Result<Vec<LayoutId>>>()?;
45
46 if pop_text_style {
47 cx.pop_text_style();
48 }
49
50 Ok((cx.request_layout(style.into(), children.clone())?, children))
51 }
52
53 fn paint(
54 &mut self,
55 layout: Layout,
56 state: &mut S,
57 child_layouts: &mut Self::FrameState,
58 cx: &mut ViewContext<S>,
59 ) -> Result<()> {
60 let Layout { order, bounds } = layout;
61
62 let style = self.computed_style();
63 let pop_text_style = style
64 .text_style(cx)
65 .map(|style| cx.push_text_style(style))
66 .is_some();
67 style.paint_background(bounds, cx);
68 // self.interaction_handlers().paint(order, bounds, cx);
69
70 let scrolled_origin = bounds.origin - self.scroll_offset(&style.overflow);
71
72 // // TODO: Support only one dimension being hidden
73 // let mut pop_layer = false;
74 // if style.overflow.y != Overflow::Visible || style.overflow.x != Overflow::Visible {
75 // cx.scene().push_layer(Some(bounds));
76 // pop_layer = true;
77 // }
78
79 for child in &mut self.children {
80 child.paint(scrolled_origin, state, 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(Rc<Cell<Point<Pixels>>>);
276
277impl ScrollState {
278 pub fn x(&self) -> Pixels {
279 self.0.get().x
280 }
281
282 pub fn set_x(&self, value: Pixels) {
283 let mut current_value = self.0.get();
284 current_value.x = value;
285 self.0.set(current_value);
286 }
287
288 pub fn y(&self) -> Pixels {
289 self.0.get().y
290 }
291
292 pub fn set_y(&self, value: Pixels) {
293 let mut current_value = self.0.get();
294 current_value.y = value;
295 self.0.set(current_value);
296 }
297}