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