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