1use crate::{
2 adapter::Adapter,
3 style::{Display, ElementStyle, Fill, Overflow, Position},
4};
5use anyhow::Result;
6use derive_more::{Deref, DerefMut};
7pub use gpui::LayoutContext;
8use gpui::{
9 geometry::{DefinedLength, Length},
10 scene::MouseClick,
11 EngineLayout, PaintContext as LegacyPaintContext,
12};
13use playground_macros::tailwind_lengths;
14use std::{any::Any, rc::Rc};
15pub use taffy::tree::NodeId;
16
17#[derive(Deref, DerefMut)]
18pub struct PaintContext<'a, 'b, 'c, 'd, V> {
19 #[deref]
20 #[deref_mut]
21 pub(crate) legacy_cx: &'d mut LegacyPaintContext<'a, 'b, 'c, V>,
22 pub(crate) scene: &'d mut gpui::SceneBuilder,
23}
24
25pub struct Layout<'a, E: ?Sized> {
26 pub from_engine: EngineLayout,
27 pub from_element: &'a mut E,
28}
29
30pub struct ElementHandlers<V> {
31 click: Option<Rc<dyn Fn(&mut V, MouseClick)>>,
32}
33
34pub struct ElementMetadata<V> {
35 pub style: ElementStyle,
36 pub handlers: ElementHandlers<V>,
37}
38
39impl<V> Default for ElementMetadata<V> {
40 fn default() -> Self {
41 Self {
42 style: ElementStyle::default(),
43 handlers: ElementHandlers::default(),
44 }
45 }
46}
47
48impl<V> Default for ElementHandlers<V> {
49 fn default() -> Self {
50 ElementHandlers { click: None }
51 }
52}
53
54pub trait Element<V: 'static>: 'static {
55 type Layout: 'static;
56
57 fn style_mut(&mut self) -> &mut ElementStyle;
58 fn handlers_mut(&mut self) -> &mut ElementHandlers<V>;
59 fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
60 -> Result<(NodeId, Self::Layout)>;
61 fn paint<'a>(
62 &mut self,
63 layout: Layout<Self::Layout>,
64 view: &mut V,
65 cx: &mut PaintContext<V>,
66 ) -> Result<()>;
67
68 /// Convert to a dynamically-typed element suitable for layout and paint.
69 fn into_any(self) -> AnyElement<V>
70 where
71 Self: 'static + Sized,
72 {
73 AnyElement {
74 element: Box::new(self) as Box<dyn ElementObject<V>>,
75 layout: None,
76 }
77 }
78
79 fn adapt(self) -> Adapter<V>
80 where
81 Self: Sized,
82 Self: Element<V>,
83 {
84 Adapter(self.into_any())
85 }
86
87 fn click(mut self, handler: impl Fn(&mut V, MouseClick) + 'static) -> Self
88 where
89 Self: Sized,
90 {
91 self.handlers_mut().click = Some(Rc::new(move |view, event| {
92 handler(view, event);
93 }));
94 self
95 }
96
97 // Display ////////////////////
98
99 fn block(mut self) -> Self
100 where
101 Self: Sized,
102 {
103 self.style_mut().display = Display::Block;
104 self
105 }
106
107 fn flex(mut self) -> Self
108 where
109 Self: Sized,
110 {
111 self.style_mut().display = Display::Flex;
112 self
113 }
114
115 fn grid(mut self) -> Self
116 where
117 Self: Sized,
118 {
119 self.style_mut().display = Display::Grid;
120 self
121 }
122
123 // style::Overflow ///////////////////
124
125 fn overflow_visible(mut self) -> Self
126 where
127 Self: Sized,
128 {
129 self.style_mut().overflow.x = Overflow::Visible;
130 self.style_mut().overflow.y = Overflow::Visible;
131 self
132 }
133
134 fn overflow_hidden(mut self) -> Self
135 where
136 Self: Sized,
137 {
138 self.style_mut().overflow.x = Overflow::Hidden;
139 self.style_mut().overflow.y = Overflow::Hidden;
140 self
141 }
142
143 fn overflow_scroll(mut self) -> Self
144 where
145 Self: Sized,
146 {
147 self.style_mut().overflow.x = Overflow::Scroll;
148 self.style_mut().overflow.y = Overflow::Scroll;
149 self
150 }
151
152 fn overflow_x_visible(mut self) -> Self
153 where
154 Self: Sized,
155 {
156 self.style_mut().overflow.x = Overflow::Visible;
157 self
158 }
159
160 fn overflow_x_hidden(mut self) -> Self
161 where
162 Self: Sized,
163 {
164 self.style_mut().overflow.x = Overflow::Hidden;
165 self
166 }
167
168 fn overflow_x_scroll(mut self) -> Self
169 where
170 Self: Sized,
171 {
172 self.style_mut().overflow.x = Overflow::Scroll;
173 self
174 }
175
176 fn overflow_y_visible(mut self) -> Self
177 where
178 Self: Sized,
179 {
180 self.style_mut().overflow.y = Overflow::Visible;
181 self
182 }
183
184 fn overflow_y_hidden(mut self) -> Self
185 where
186 Self: Sized,
187 {
188 self.style_mut().overflow.y = Overflow::Hidden;
189 self
190 }
191
192 fn overflow_y_scroll(mut self) -> Self
193 where
194 Self: Sized,
195 {
196 self.style_mut().overflow.y = Overflow::Scroll;
197 self
198 }
199
200 // Position ///////////////////
201
202 fn relative(mut self) -> Self
203 where
204 Self: Sized,
205 {
206 self.style_mut().position = Position::Relative;
207 self
208 }
209
210 fn absolute(mut self) -> Self
211 where
212 Self: Sized,
213 {
214 self.style_mut().position = Position::Absolute;
215
216 self
217 }
218
219 #[tailwind_lengths]
220 fn inset_(mut self, length: DefinedLength) -> Self
221 where
222 Self: Sized,
223 {
224 self.style_mut().inset.top = length;
225 self.style_mut().inset.right = length;
226 self.style_mut().inset.bottom = length;
227 self.style_mut().inset.left = length;
228 self
229 }
230
231 fn w(mut self, width: impl Into<Length>) -> Self
232 where
233 Self: Sized,
234 {
235 self.style_mut().size.width = width.into();
236 self
237 }
238
239 fn w_auto(mut self) -> Self
240 where
241 Self: Sized,
242 {
243 self.style_mut().size.width = Length::Auto;
244 self
245 }
246
247 #[tailwind_lengths]
248 fn w_(mut self, length: DefinedLength) -> Self
249 where
250 Self: Sized,
251 {
252 self.style_mut().size.width = length;
253 self
254 }
255
256 #[tailwind_lengths]
257 fn min_w_(mut self, length: DefinedLength) -> Self
258 where
259 Self: Sized,
260 {
261 self.style_mut().min_size.width = length;
262 self
263 }
264
265 fn h(mut self, height: impl Into<Length>) -> Self
266 where
267 Self: Sized,
268 {
269 self.style_mut().size.height = height.into();
270 self
271 }
272
273 fn h_auto(mut self) -> Self
274 where
275 Self: Sized,
276 {
277 self.style_mut().size.height = Length::Auto;
278 self
279 }
280
281 #[tailwind_lengths]
282 fn h_(mut self, height: DefinedLength) -> Self
283 where
284 Self: Sized,
285 {
286 self.style_mut().size.height = height;
287 self
288 }
289
290 #[tailwind_lengths]
291 fn min_h_(mut self, length: DefinedLength) -> Self
292 where
293 Self: Sized,
294 {
295 self.style_mut().min_size.height = length;
296 self
297 }
298
299 fn fill(mut self, fill: impl Into<Fill>) -> Self
300 where
301 Self: Sized,
302 {
303 self.style_mut().fill = fill.into();
304 self
305 }
306}
307
308pub trait ElementObject<V> {
309 fn style_mut(&mut self) -> &mut ElementStyle;
310 fn handlers_mut(&mut self) -> &mut ElementHandlers<V>;
311 fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
312 -> Result<(NodeId, Box<dyn Any>)>;
313 fn paint(
314 &mut self,
315 layout: Layout<dyn Any>,
316 view: &mut V,
317 cx: &mut PaintContext<V>,
318 ) -> Result<()>;
319}
320
321impl<V: 'static, E: Element<V>> ElementObject<V> for E {
322 fn style_mut(&mut self) -> &mut ElementStyle {
323 Element::style_mut(self)
324 }
325
326 fn handlers_mut(&mut self) -> &mut ElementHandlers<V> {
327 Element::handlers_mut(self)
328 }
329
330 fn layout(
331 &mut self,
332 view: &mut V,
333 cx: &mut LayoutContext<V>,
334 ) -> Result<(NodeId, Box<dyn Any>)> {
335 let (node_id, layout) = self.layout(view, cx)?;
336 let layout = Box::new(layout) as Box<dyn Any>;
337 Ok((node_id, layout))
338 }
339
340 fn paint(
341 &mut self,
342 layout: Layout<dyn Any>,
343 view: &mut V,
344 cx: &mut PaintContext<V>,
345 ) -> Result<()> {
346 let layout = Layout {
347 from_engine: layout.from_engine,
348 from_element: layout.from_element.downcast_mut::<E::Layout>().unwrap(),
349 };
350
351 self.paint(layout, view, cx)
352 }
353}
354
355/// A dynamically typed element.
356pub struct AnyElement<V> {
357 element: Box<dyn ElementObject<V>>,
358 layout: Option<(NodeId, Box<dyn Any>)>,
359}
360
361impl<V> AnyElement<V> {
362 pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<NodeId> {
363 let (node_id, layout) = self.element.layout(view, cx)?;
364 self.layout = Some((node_id, layout));
365 Ok(node_id)
366 }
367
368 pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
369 let (layout_node_id, element_layout) =
370 self.layout.as_mut().expect("paint called before layout");
371
372 let layout = Layout {
373 from_engine: cx
374 .layout_engine()
375 .unwrap()
376 .computed_layout(*layout_node_id)
377 .expect("you can currently only use playground elements within an adapter"),
378 from_element: element_layout.as_mut(),
379 };
380
381 self.element.paint(layout, view, cx)
382 }
383}
384
385impl<V: 'static> Element<V> for AnyElement<V> {
386 type Layout = ();
387
388 fn style_mut(&mut self) -> &mut ElementStyle {
389 self.element.style_mut()
390 }
391
392 fn handlers_mut(&mut self) -> &mut ElementHandlers<V> {
393 self.element.handlers_mut()
394 }
395
396 fn layout(
397 &mut self,
398 view: &mut V,
399 cx: &mut LayoutContext<V>,
400 ) -> Result<(NodeId, Self::Layout)> {
401 Ok((self.layout(view, cx)?, ()))
402 }
403
404 fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
405 self.paint(view, cx)
406 }
407}