1use crate::{
2 AnyElement, BorrowWindow, Bounds, Cascade, Element, ElementId, IdentifiedElement, Interactive,
3 IntoAnyElement, LayoutId, MouseEventListeners, Overflow, ParentElement, Pixels, Point,
4 Refineable, Style, Styled, ViewContext,
5};
6use parking_lot::Mutex;
7use smallvec::SmallVec;
8use std::{marker::PhantomData, sync::Arc};
9
10pub enum HasId {}
11
12pub struct Div<S: 'static, I = ()> {
13 styles: Cascade<Style>,
14 id: Option<ElementId>,
15 listeners: MouseEventListeners<S>,
16 children: SmallVec<[AnyElement<S>; 2]>,
17 scroll_state: Option<ScrollState>,
18 identified: PhantomData<I>,
19}
20
21pub fn div<S>() -> Div<S> {
22 Div {
23 styles: Default::default(),
24 id: None,
25 listeners: Default::default(),
26 children: Default::default(),
27 scroll_state: None,
28 identified: PhantomData,
29 }
30}
31
32impl<S, Marker> IntoAnyElement<S> for Div<S, Marker>
33where
34 S: 'static + Send + Sync,
35 Marker: 'static + Send + Sync,
36{
37 fn into_any(self) -> AnyElement<S> {
38 AnyElement::new(self)
39 }
40}
41
42impl<S, Marker> Element for Div<S, Marker>
43where
44 S: 'static + Send + Sync,
45 Marker: 'static + Send + Sync,
46{
47 type ViewState = S;
48 type ElementState = ();
49
50 fn element_id(&self) -> Option<ElementId> {
51 self.id.clone()
52 }
53
54 fn layout(
55 &mut self,
56 view: &mut S,
57 _: Option<Self::ElementState>,
58 cx: &mut ViewContext<S>,
59 ) -> (LayoutId, Self::ElementState) {
60 let style = self.computed_style();
61 let child_layout_ids = style.apply_text_style(cx, |cx| {
62 self.with_element_id(cx, |this, cx| this.layout_children(view, cx))
63 });
64 let layout_id = cx.request_layout(style.into(), child_layout_ids.clone());
65 (layout_id, ())
66 }
67
68 fn paint(
69 &mut self,
70 bounds: Bounds<Pixels>,
71 state: &mut S,
72 _: &mut (),
73 cx: &mut ViewContext<S>,
74 ) {
75 let style = self.computed_style();
76 let z_index = style.z_index.unwrap_or(0);
77 cx.stack(z_index, |cx| style.paint(bounds, cx));
78
79 let overflow = &style.overflow;
80
81 style.apply_text_style(cx, |cx| {
82 cx.stack(z_index + 1, |cx| {
83 style.apply_overflow(bounds, cx, |cx| {
84 self.with_element_id(cx, |this, cx| {
85 this.listeners.paint(bounds, cx);
86 this.paint_children(overflow, state, cx)
87 });
88 })
89 })
90 });
91 }
92}
93
94impl<S> Div<S, ()>
95where
96 S: 'static + Send + Sync,
97{
98 pub fn id(self, id: impl Into<ElementId>) -> Div<S, HasId> {
99 Div {
100 styles: self.styles,
101 id: Some(id.into()),
102 listeners: self.listeners,
103 children: self.children,
104 scroll_state: self.scroll_state,
105 identified: PhantomData,
106 }
107 }
108}
109
110impl<S, Marker> Div<S, Marker>
111where
112 S: 'static + Send + Sync,
113 Marker: 'static + Send + Sync,
114{
115 pub fn z_index(mut self, z_index: u32) -> Self {
116 self.declared_style().z_index = Some(z_index);
117 self
118 }
119
120 pub fn overflow_hidden(mut self) -> Self {
121 self.declared_style().overflow.x = Some(Overflow::Hidden);
122 self.declared_style().overflow.y = Some(Overflow::Hidden);
123 self
124 }
125
126 pub fn overflow_hidden_x(mut self) -> Self {
127 self.declared_style().overflow.x = Some(Overflow::Hidden);
128 self
129 }
130
131 pub fn overflow_hidden_y(mut self) -> Self {
132 self.declared_style().overflow.y = Some(Overflow::Hidden);
133 self
134 }
135
136 pub fn overflow_scroll(mut self, scroll_state: ScrollState) -> Self {
137 self.scroll_state = Some(scroll_state);
138 self.declared_style().overflow.x = Some(Overflow::Scroll);
139 self.declared_style().overflow.y = Some(Overflow::Scroll);
140 self
141 }
142
143 pub fn overflow_x_scroll(mut self, scroll_state: ScrollState) -> Self {
144 self.scroll_state = Some(scroll_state);
145 self.declared_style().overflow.x = Some(Overflow::Scroll);
146 self
147 }
148
149 pub fn overflow_y_scroll(mut self, scroll_state: ScrollState) -> Self {
150 self.scroll_state = Some(scroll_state);
151 self.declared_style().overflow.y = Some(Overflow::Scroll);
152 self
153 }
154
155 fn scroll_offset(&self, overflow: &Point<Overflow>) -> Point<Pixels> {
156 let mut offset = Point::default();
157 if overflow.y == Overflow::Scroll {
158 offset.y = self.scroll_state.as_ref().unwrap().y();
159 }
160 if overflow.x == Overflow::Scroll {
161 offset.x = self.scroll_state.as_ref().unwrap().x();
162 }
163
164 offset
165 }
166
167 fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> Vec<LayoutId> {
168 self.children
169 .iter_mut()
170 .map(|child| child.layout(view, cx))
171 .collect()
172 }
173
174 fn paint_children(
175 &mut self,
176 overflow: &Point<Overflow>,
177 state: &mut S,
178 cx: &mut ViewContext<S>,
179 ) {
180 let scroll_offset = self.scroll_offset(overflow);
181 for child in &mut self.children {
182 child.paint(state, Some(scroll_offset), cx);
183 }
184 }
185
186 fn with_element_id<R>(
187 &mut self,
188 cx: &mut ViewContext<S>,
189 f: impl FnOnce(&mut Self, &mut ViewContext<S>) -> R,
190 ) -> R {
191 if let Some(element_id) = self.element_id() {
192 cx.with_element_id(element_id, |cx| f(self, cx))
193 } else {
194 f(self, cx)
195 }
196 }
197}
198
199impl<V: 'static + Send + Sync, Marker: 'static + Send + Sync> Styled for Div<V, Marker> {
200 type Style = Style;
201
202 fn style_cascade(&mut self) -> &mut Cascade<Self::Style> {
203 &mut self.styles
204 }
205
206 fn declared_style(&mut self) -> &mut <Self::Style as Refineable>::Refinement {
207 self.styles.base()
208 }
209}
210
211impl<V: Send + Sync + 'static> IdentifiedElement for Div<V, HasId> {}
212
213impl<V: Send + Sync + 'static, Marker: 'static + Send + Sync> Interactive<V> for Div<V, Marker> {
214 fn listeners(&mut self) -> &mut MouseEventListeners<V> {
215 &mut self.listeners
216 }
217}
218
219impl<V: 'static, Marker: 'static + Send + Sync> ParentElement for Div<V, Marker> {
220 type State = V;
221
222 fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<V>; 2]> {
223 &mut self.children
224 }
225}
226
227#[derive(Default, Clone)]
228pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
229
230impl ScrollState {
231 pub fn x(&self) -> Pixels {
232 self.0.lock().x
233 }
234
235 pub fn set_x(&self, value: Pixels) {
236 self.0.lock().x = value;
237 }
238
239 pub fn y(&self) -> Pixels {
240 self.0.lock().y
241 }
242
243 pub fn set_y(&self, value: Pixels) {
244 self.0.lock().y = value;
245 }
246}