element.rs

  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}