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