1use crate::{
2 adapter::Adapter,
3 color::Hsla,
4 style::{Display, ElementStyle, Fill, Overflow, Position},
5};
6use anyhow::Result;
7pub use gpui::LayoutContext;
8use gpui::{
9 geometry::{DefinedLength, Length},
10 platform::{MouseButton, MouseButtonEvent},
11 EngineLayout, EventContext, RenderContext, ViewContext,
12};
13use playground_macros::tailwind_lengths;
14use std::{
15 any::{Any, TypeId},
16 cell::Cell,
17 rc::Rc,
18};
19
20pub use crate::paint_context::PaintContext;
21pub use taffy::tree::NodeId;
22
23pub struct Layout<'a, E: ?Sized> {
24 pub from_engine: EngineLayout,
25 pub from_element: &'a mut E,
26}
27
28pub struct ElementMetadata<V> {
29 pub style: ElementStyle,
30 pub handlers: Vec<EventHandler<V>>,
31}
32
33pub struct EventHandler<V> {
34 handler: Rc<dyn Fn(&mut V, &dyn Any, &mut EventContext<V>)>,
35 event_type: TypeId,
36 outside_bounds: bool,
37}
38
39impl<V> Clone for EventHandler<V> {
40 fn clone(&self) -> Self {
41 Self {
42 handler: self.handler.clone(),
43 event_type: self.event_type,
44 outside_bounds: self.outside_bounds,
45 }
46 }
47}
48
49impl<V> Default for ElementMetadata<V> {
50 fn default() -> Self {
51 Self {
52 style: ElementStyle::default(),
53 handlers: Vec::new(),
54 }
55 }
56}
57
58pub trait Element<V: 'static>: 'static {
59 type Layout: 'static;
60
61 fn style_mut(&mut self) -> &mut ElementStyle;
62 fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>>;
63
64 fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
65 -> Result<(NodeId, Self::Layout)>;
66 fn paint<'a>(
67 &mut self,
68 layout: Layout<Self::Layout>,
69 view: &mut V,
70 cx: &mut PaintContext<V>,
71 ) -> Result<()>;
72
73 /// Convert to a dynamically-typed element suitable for layout and paint.
74 fn into_any(self) -> AnyElement<V>
75 where
76 Self: 'static + Sized,
77 {
78 AnyElement {
79 element: Box::new(self) as Box<dyn ElementObject<V>>,
80 layout: None,
81 }
82 }
83
84 fn adapt(self) -> Adapter<V>
85 where
86 Self: Sized,
87 Self: Element<V>,
88 {
89 Adapter(self.into_any())
90 }
91
92 fn click(
93 self,
94 button: MouseButton,
95 handler: impl Fn(&mut V, &MouseButtonEvent, &mut ViewContext<V>) + 'static,
96 ) -> Self
97 where
98 Self: Sized,
99 {
100 let pressed: Rc<Cell<bool>> = Default::default();
101 self.mouse_down(button, {
102 let pressed = pressed.clone();
103 move |_, _, _| {
104 pressed.set(true);
105 }
106 })
107 .mouse_up_outside(button, {
108 let pressed = pressed.clone();
109 move |_, _, _| {
110 pressed.set(false);
111 }
112 })
113 .mouse_up(button, move |view, event, event_cx| {
114 if pressed.get() {
115 pressed.set(false);
116 handler(view, event, event_cx);
117 }
118 })
119 }
120
121 fn mouse_down(
122 mut self,
123 button: MouseButton,
124 handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
125 ) -> Self
126 where
127 Self: Sized,
128 {
129 self.handlers_mut().push(EventHandler {
130 handler: Rc::new(move |view, event, event_cx| {
131 let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
132 if event.button == button && event.is_down {
133 handler(view, event, event_cx);
134 }
135 }),
136 event_type: TypeId::of::<MouseButtonEvent>(),
137 outside_bounds: false,
138 });
139 self
140 }
141
142 fn mouse_down_outside(
143 mut self,
144 button: MouseButton,
145 handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
146 ) -> Self
147 where
148 Self: Sized,
149 {
150 self.handlers_mut().push(EventHandler {
151 handler: Rc::new(move |view, event, event_cx| {
152 let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
153 if event.button == button && event.is_down {
154 handler(view, event, event_cx);
155 }
156 }),
157 event_type: TypeId::of::<MouseButtonEvent>(),
158 outside_bounds: true,
159 });
160 self
161 }
162
163 fn mouse_up(
164 mut self,
165 button: MouseButton,
166 handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
167 ) -> Self
168 where
169 Self: Sized,
170 {
171 self.handlers_mut().push(EventHandler {
172 handler: Rc::new(move |view, event, event_cx| {
173 let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
174 if event.button == button && !event.is_down {
175 handler(view, event, event_cx);
176 }
177 }),
178 event_type: TypeId::of::<MouseButtonEvent>(),
179 outside_bounds: false,
180 });
181 self
182 }
183
184 fn mouse_up_outside(
185 mut self,
186 button: MouseButton,
187 handler: impl Fn(&mut V, &MouseButtonEvent, &mut EventContext<V>) + 'static,
188 ) -> Self
189 where
190 Self: Sized,
191 {
192 self.handlers_mut().push(EventHandler {
193 handler: Rc::new(move |view, event, event_cx| {
194 let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
195 if event.button == button && !event.is_down {
196 handler(view, event, event_cx);
197 }
198 }),
199 event_type: TypeId::of::<MouseButtonEvent>(),
200 outside_bounds: true,
201 });
202 self
203 }
204
205 // Display ////////////////////
206
207 fn block(mut self) -> Self
208 where
209 Self: Sized,
210 {
211 self.style_mut().display = Display::Block;
212 self
213 }
214
215 fn flex(mut self) -> Self
216 where
217 Self: Sized,
218 {
219 self.style_mut().display = Display::Flex;
220 self
221 }
222
223 fn grid(mut self) -> Self
224 where
225 Self: Sized,
226 {
227 self.style_mut().display = Display::Grid;
228 self
229 }
230
231 // style::Overflow ///////////////////
232
233 fn overflow_visible(mut self) -> Self
234 where
235 Self: Sized,
236 {
237 self.style_mut().overflow.x = Overflow::Visible;
238 self.style_mut().overflow.y = Overflow::Visible;
239 self
240 }
241
242 fn overflow_hidden(mut self) -> Self
243 where
244 Self: Sized,
245 {
246 self.style_mut().overflow.x = Overflow::Hidden;
247 self.style_mut().overflow.y = Overflow::Hidden;
248 self
249 }
250
251 fn overflow_scroll(mut self) -> Self
252 where
253 Self: Sized,
254 {
255 self.style_mut().overflow.x = Overflow::Scroll;
256 self.style_mut().overflow.y = Overflow::Scroll;
257 self
258 }
259
260 fn overflow_x_visible(mut self) -> Self
261 where
262 Self: Sized,
263 {
264 self.style_mut().overflow.x = Overflow::Visible;
265 self
266 }
267
268 fn overflow_x_hidden(mut self) -> Self
269 where
270 Self: Sized,
271 {
272 self.style_mut().overflow.x = Overflow::Hidden;
273 self
274 }
275
276 fn overflow_x_scroll(mut self) -> Self
277 where
278 Self: Sized,
279 {
280 self.style_mut().overflow.x = Overflow::Scroll;
281 self
282 }
283
284 fn overflow_y_visible(mut self) -> Self
285 where
286 Self: Sized,
287 {
288 self.style_mut().overflow.y = Overflow::Visible;
289 self
290 }
291
292 fn overflow_y_hidden(mut self) -> Self
293 where
294 Self: Sized,
295 {
296 self.style_mut().overflow.y = Overflow::Hidden;
297 self
298 }
299
300 fn overflow_y_scroll(mut self) -> Self
301 where
302 Self: Sized,
303 {
304 self.style_mut().overflow.y = Overflow::Scroll;
305 self
306 }
307
308 // Position ///////////////////
309
310 fn relative(mut self) -> Self
311 where
312 Self: Sized,
313 {
314 self.style_mut().position = Position::Relative;
315 self
316 }
317
318 fn absolute(mut self) -> Self
319 where
320 Self: Sized,
321 {
322 self.style_mut().position = Position::Absolute;
323
324 self
325 }
326
327 #[tailwind_lengths]
328 fn inset_(mut self, length: DefinedLength) -> Self
329 where
330 Self: Sized,
331 {
332 self.style_mut().inset.top = length;
333 self.style_mut().inset.right = length;
334 self.style_mut().inset.bottom = length;
335 self.style_mut().inset.left = length;
336 self
337 }
338
339 fn w(mut self, width: impl Into<Length>) -> Self
340 where
341 Self: Sized,
342 {
343 self.style_mut().size.width = width.into();
344 self
345 }
346
347 fn w_auto(mut self) -> Self
348 where
349 Self: Sized,
350 {
351 self.style_mut().size.width = Length::Auto;
352 self
353 }
354
355 #[tailwind_lengths]
356 fn w_(mut self, length: DefinedLength) -> Self
357 where
358 Self: Sized,
359 {
360 self.style_mut().size.width = length;
361 self
362 }
363
364 #[tailwind_lengths]
365 fn min_w_(mut self, length: DefinedLength) -> Self
366 where
367 Self: Sized,
368 {
369 self.style_mut().min_size.width = length;
370 self
371 }
372
373 fn h(mut self, height: impl Into<Length>) -> Self
374 where
375 Self: Sized,
376 {
377 self.style_mut().size.height = height.into();
378 self
379 }
380
381 fn h_auto(mut self) -> Self
382 where
383 Self: Sized,
384 {
385 self.style_mut().size.height = Length::Auto;
386 self
387 }
388
389 #[tailwind_lengths]
390 fn h_(mut self, height: DefinedLength) -> Self
391 where
392 Self: Sized,
393 {
394 self.style_mut().size.height = height;
395 self
396 }
397
398 #[tailwind_lengths]
399 fn min_h_(mut self, length: DefinedLength) -> Self
400 where
401 Self: Sized,
402 {
403 self.style_mut().min_size.height = length;
404 self
405 }
406
407 fn fill(mut self, fill: impl Into<Fill>) -> Self
408 where
409 Self: Sized,
410 {
411 self.style_mut().fill = fill.into();
412 self
413 }
414
415 fn text_color(mut self, color: impl Into<Hsla>) -> Self
416 where
417 Self: Sized,
418 {
419 self.style_mut().text_color = Some(color.into());
420 self
421 }
422}
423
424// Object-safe counterpart of Element used by AnyElement to store elements as trait objects.
425trait ElementObject<V> {
426 fn style_mut(&mut self) -> &mut ElementStyle;
427 fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>>;
428 fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
429 -> Result<(NodeId, Box<dyn Any>)>;
430 fn paint(
431 &mut self,
432 layout: Layout<dyn Any>,
433 view: &mut V,
434 cx: &mut PaintContext<V>,
435 ) -> Result<()>;
436}
437
438impl<V: 'static, E: Element<V>> ElementObject<V> for E {
439 fn style_mut(&mut self) -> &mut ElementStyle {
440 Element::style_mut(self)
441 }
442
443 fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>> {
444 Element::handlers_mut(self)
445 }
446
447 fn layout(
448 &mut self,
449 view: &mut V,
450 cx: &mut LayoutContext<V>,
451 ) -> Result<(NodeId, Box<dyn Any>)> {
452 let (node_id, layout) = self.layout(view, cx)?;
453 let layout = Box::new(layout) as Box<dyn Any>;
454 Ok((node_id, layout))
455 }
456
457 fn paint(
458 &mut self,
459 layout: Layout<dyn Any>,
460 view: &mut V,
461 cx: &mut PaintContext<V>,
462 ) -> Result<()> {
463 let layout = Layout {
464 from_engine: layout.from_engine,
465 from_element: layout.from_element.downcast_mut::<E::Layout>().unwrap(),
466 };
467
468 self.paint(layout, view, cx)
469 }
470}
471
472/// A dynamically typed element.
473pub struct AnyElement<V> {
474 element: Box<dyn ElementObject<V>>,
475 layout: Option<(NodeId, Box<dyn Any>)>,
476}
477
478impl<V: 'static> AnyElement<V> {
479 pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<NodeId> {
480 let pushed_text_style = self.push_text_style(cx);
481
482 let (node_id, layout) = self.element.layout(view, cx)?;
483 self.layout = Some((node_id, layout));
484
485 if pushed_text_style {
486 cx.pop_text_style();
487 }
488
489 Ok(node_id)
490 }
491
492 pub fn push_text_style(&mut self, cx: &mut impl RenderContext) -> bool {
493 let text_style = self.element.style_mut().text_style();
494 if let Some(text_style) = text_style {
495 let mut current_text_style = cx.text_style();
496 text_style.apply(&mut current_text_style);
497 cx.push_text_style(current_text_style);
498 true
499 } else {
500 false
501 }
502 }
503
504 pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
505 let pushed_text_style = self.push_text_style(cx);
506
507 let (layout_node_id, element_layout) =
508 self.layout.as_mut().expect("paint called before layout");
509
510 let layout = Layout {
511 from_engine: cx
512 .layout_engine()
513 .unwrap()
514 .computed_layout(*layout_node_id)
515 .expect("you can currently only use playground elements within an adapter"),
516 from_element: element_layout.as_mut(),
517 };
518
519 for event_handler in self.element.handlers_mut().iter().cloned() {
520 let EngineLayout { order, bounds } = layout.from_engine;
521
522 let view_id = cx.view_id();
523 let view_event_handler = event_handler.handler.clone();
524
525 // TODO: Tuck this into a method on PaintContext.
526 cx.scene
527 .interactive_regions
528 .push(gpui::scene::InteractiveRegion {
529 order,
530 bounds,
531 outside_bounds: event_handler.outside_bounds,
532 event_handler: Rc::new(move |view, event, window_cx, view_id| {
533 let mut view_context = ViewContext::mutable(window_cx, view_id);
534 let mut event_context = EventContext::new(&mut view_context);
535 view_event_handler(view.downcast_mut().unwrap(), event, &mut event_context);
536 }),
537 event_type: event_handler.event_type,
538 view_id,
539 });
540 }
541
542 self.element.paint(layout, view, cx)?;
543 if pushed_text_style {
544 cx.pop_text_style();
545 }
546
547 Ok(())
548 }
549}
550
551impl<V: 'static> Element<V> for AnyElement<V> {
552 type Layout = ();
553
554 fn style_mut(&mut self) -> &mut ElementStyle {
555 self.element.style_mut()
556 }
557
558 fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>> {
559 self.element.handlers_mut()
560 }
561
562 fn layout(
563 &mut self,
564 view: &mut V,
565 cx: &mut LayoutContext<V>,
566 ) -> Result<(NodeId, Self::Layout)> {
567 Ok((self.layout(view, cx)?, ()))
568 }
569
570 fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
571 self.paint(view, cx)
572 }
573}
574
575pub trait IntoElement<V: 'static> {
576 type Element: Element<V>;
577
578 fn into_element(self) -> Self::Element;
579
580 fn into_any_element(self) -> AnyElement<V>
581 where
582 Self: Sized,
583 {
584 self.into_element().into_any()
585 }
586}