diff --git a/crates/gpui/playground/src/adapter.rs b/crates/gpui/playground/src/adapter.rs index 7929c8704235c7713dd5ed99df107b66cdf50a0d..e9f279346f7b36af9e1d5c7c9015b12861c9bb6b 100644 --- a/crates/gpui/playground/src/adapter.rs +++ b/crates/gpui/playground/src/adapter.rs @@ -4,7 +4,6 @@ use util::ResultExt; use crate::element::AnyElement; -#[derive(Clone)] pub struct Adapter(pub(crate) AnyElement); impl gpui::Element for Adapter { diff --git a/crates/gpui/playground/src/components.rs b/crates/gpui/playground/src/components.rs index ebdd62f02b0567a5fd725575183beb00277b29a2..c966c4d29329e11a76a48f9dc364996b98845735 100644 --- a/crates/gpui/playground/src/components.rs +++ b/crates/gpui/playground/src/components.rs @@ -1,41 +1,57 @@ -use crate::{element::Element, frame, themes::rose_pine}; +use crate::{ + element::{AnyElement, Element, ElementMetadata}, + frame, + themes::rose_pine, +}; use gpui::ViewContext; -use std::{any::Any, borrow::Cow, marker::PhantomData, rc::Rc}; +use std::{borrow::Cow, marker::PhantomData, rc::Rc}; + +struct ButtonHandlers { + click: Option>, +} + +impl Default for ButtonHandlers { + fn default() -> Self { + Self { click: None } + } +} pub struct Button { + metadata: ElementMetadata, + button_handlers: ButtonHandlers, label: Cow<'static, str>, data: Rc, - click_handler: Option>, view_type: PhantomData, } impl Button { fn new(label: impl Into>) -> Self { Self { + metadata: Default::default(), + button_handlers: ButtonHandlers::default(), label: label.into(), data: Rc::new(()), - click_handler: None, view_type: PhantomData, } } pub fn data(self, data: D) -> Button { Button { + metadata: Default::default(), + button_handlers: ButtonHandlers::default(), label: self.label, data: Rc::new(data), - click_handler: None, view_type: PhantomData, } } } impl Button { - fn click(mut self, handler: impl Fn(&mut V, &D) + 'static) -> Self { - self.click_handler = Some(Rc::new(move |view, data| { - let data = data.downcast_ref::().unwrap(); - handler(view, data); - })); - self + fn click(self, handler: impl Fn(&mut V, &D) + 'static) -> Self { + let data = self.data.clone(); + Element::click(self, move |view, _| { + handler(view, data.as_ref()); + }) } } @@ -48,7 +64,7 @@ impl Button { // TODO: Drive from the context let button = frame().fill(rose_pine::dawn().error(0.5)).h_5().w_9(); - if let Some(handler) = self.click_handler.clone() { + if let Some(handler) = self.button_handlers.click.clone() { let data = self.data.clone(); button.click(move |view, event| handler(view, data.as_ref())) } else { @@ -56,3 +72,35 @@ impl Button { } } } + +impl Element for Button { + type Layout = AnyElement; + + fn style_mut(&mut self) -> &mut crate::style::ElementStyle { + &mut self.metadata.style + } + + fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers { + &mut self.metadata.handlers + } + + fn layout( + &mut self, + view: &mut V, + cx: &mut crate::element::LayoutContext, + ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> { + let mut element = self.render(view, cx).into_any(); + let node_id = element.layout(view, cx)?; + Ok((node_id, element)) + } + + fn paint<'a>( + &mut self, + layout: crate::element::Layout<'a, Self::Layout>, + view: &mut V, + cx: &mut crate::element::PaintContext, + ) -> anyhow::Result<()> { + layout.from_element.paint(view, cx)?; + Ok(()) + } +} diff --git a/crates/gpui/playground/src/element.rs b/crates/gpui/playground/src/element.rs index bf080b8770775653847fa445e1be0d11cafeee36..984056958271edd6727425e574f7c62f02cbc0d0 100644 --- a/crates/gpui/playground/src/element.rs +++ b/crates/gpui/playground/src/element.rs @@ -1,13 +1,14 @@ -use std::{any::Any, sync::Arc}; +use std::{any::Any, rc::Rc}; use crate::{ adapter::Adapter, - style::{DefinedLength, Display, Fill, Length, Overflow, Position, Style}, + style::{DefinedLength, Display, ElementStyle, Fill, Length, Overflow, Position}, }; use anyhow::Result; use derive_more::{Deref, DerefMut}; use gpui::{ - EngineLayout, LayoutContext as LegacyLayoutContext, PaintContext as LegacyPaintContext, + scene::MouseClick, EngineLayout, LayoutContext as LegacyLayoutContext, + PaintContext as LegacyPaintContext, }; use playground_macros::tailwind_lengths; pub use taffy::tree::NodeId; @@ -25,14 +26,48 @@ pub struct PaintContext<'a, 'b, 'c, 'd, V> { pub(crate) scene: &'d mut gpui::SceneBuilder, } -pub trait Element: 'static + Clone { +pub struct Layout<'a, E: ?Sized> { + pub from_engine: EngineLayout, + pub from_element: &'a mut E, +} + +pub struct ElementHandlers { + click: Option>, +} + +pub struct ElementMetadata { + pub style: ElementStyle, + pub handlers: ElementHandlers, +} + +impl Default for ElementMetadata { + fn default() -> Self { + Self { + style: ElementStyle::default(), + handlers: ElementHandlers::default(), + } + } +} + +impl Default for ElementHandlers { + fn default() -> Self { + ElementHandlers { click: None } + } +} + +pub trait Element: 'static { type Layout: 'static; - fn style_mut(&mut self) -> &mut Style; + fn style_mut(&mut self) -> &mut ElementStyle; + fn handlers_mut(&mut self) -> &mut ElementHandlers; fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result<(NodeId, Self::Layout)>; - fn paint(&mut self, layout: EngineLayout, view: &mut V, cx: &mut PaintContext) - -> Result<()>; + fn paint<'a>( + &mut self, + layout: Layout, + view: &mut V, + cx: &mut PaintContext, + ) -> Result<()>; /// Convert to a dynamically-typed element suitable for layout and paint. fn into_any(self) -> AnyElement @@ -53,6 +88,16 @@ pub trait Element: 'static + Clone { Adapter(self.into_any()) } + fn click(mut self, handler: impl Fn(&mut V, MouseClick) + 'static) -> Self + where + Self: Sized, + { + self.handlers_mut().click = Some(Rc::new(move |view, event| { + handler(view, event); + })); + self + } + // Display //////////////////// fn block(mut self) -> Self @@ -265,46 +310,59 @@ pub trait Element: 'static + Clone { } pub trait ElementObject { - fn style_mut(&mut self) -> &mut Style; + fn style_mut(&mut self) -> &mut ElementStyle; + fn handlers_mut(&mut self) -> &mut ElementHandlers; fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) - -> Result<(NodeId, Arc)>; - fn paint(&mut self, layout: EngineLayout, view: &mut V, cx: &mut PaintContext) - -> Result<()>; - fn clone_object(&self) -> Box>; + -> Result<(NodeId, Box)>; + fn paint( + &mut self, + layout: Layout, + view: &mut V, + cx: &mut PaintContext, + ) -> Result<()>; } impl> ElementObject for E { - fn style_mut(&mut self) -> &mut Style { - self.style_mut() + fn style_mut(&mut self) -> &mut ElementStyle { + Element::style_mut(self) + } + + fn handlers_mut(&mut self) -> &mut ElementHandlers { + Element::handlers_mut(self) } fn layout( &mut self, view: &mut V, cx: &mut LayoutContext, - ) -> Result<(NodeId, Arc)> { + ) -> Result<(NodeId, Box)> { let (node_id, layout) = self.layout(view, cx)?; - let layout = Arc::new(layout) as Arc; + let layout = Box::new(layout) as Box; Ok((node_id, layout)) } fn paint( &mut self, - layout: EngineLayout, + layout: Layout, view: &mut V, cx: &mut PaintContext, ) -> Result<()> { + let layout = Layout { + from_engine: layout.from_engine, + from_element: layout.from_element.downcast_mut::().unwrap(), + }; + self.paint(layout, view, cx) } - fn clone_object(&self) -> Box> { - Box::new(Clone::clone(self)) - } + // fn clone_object(&self) -> Box> { + // Box::new(Clone::clone(self)) + // } } pub struct AnyElement { element: Box>, - layout: Option<(NodeId, Arc)>, + layout: Option<(NodeId, Box)>, } impl AnyElement { @@ -315,32 +373,33 @@ impl AnyElement { } pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext) -> Result<()> { - let (layout_node_id, layout) = self.layout.clone().expect("paint called before layout"); - let layout = cx - .layout_engine() - .unwrap() - .computed_layout(layout_node_id) - .expect("you can currently only use playground elements within an adapter"); - self.element.paint(layout, view, cx) - } -} + let (layout_node_id, element_layout) = + self.layout.as_mut().expect("paint called before layout"); + + let layout = Layout { + from_engine: cx + .layout_engine() + .unwrap() + .computed_layout(*layout_node_id) + .expect("you can currently only use playground elements within an adapter"), + from_element: element_layout.as_mut(), + }; -impl Clone for AnyElement { - fn clone(&self) -> Self { - Self { - element: self.element.clone_object(), - layout: self.layout.clone(), - } + self.element.paint(layout, view, cx) } } impl Element for AnyElement { type Layout = (); - fn style_mut(&mut self) -> &mut Style { + fn style_mut(&mut self) -> &mut ElementStyle { self.element.style_mut() } + fn handlers_mut(&mut self) -> &mut ElementHandlers { + self.element.handlers_mut() + } + fn layout( &mut self, view: &mut V, @@ -349,12 +408,7 @@ impl Element for AnyElement { Ok((self.layout(view, cx)?, ())) } - fn paint( - &mut self, - layout: EngineLayout, - view: &mut V, - cx: &mut PaintContext, - ) -> Result<()> { + fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext) -> Result<()> { self.paint(view, cx) } } diff --git a/crates/gpui/playground/src/frame.rs b/crates/gpui/playground/src/frame.rs index b38c415d861ff63d79a84c090459d27860cd506c..4c2cc5d3850e736e5dfafbfbfd740f8c62eadb36 100644 --- a/crates/gpui/playground/src/frame.rs +++ b/crates/gpui/playground/src/frame.rs @@ -1,18 +1,20 @@ use crate::{ - element::{AnyElement, Element, LayoutContext, NodeId, PaintContext}, - style::Style, + element::{AnyElement, Element, ElementHandlers, Layout, LayoutContext, NodeId, PaintContext}, + style::ElementStyle, }; use anyhow::{anyhow, Result}; -use gpui::{EngineLayout, LayoutNodeId}; +use gpui::LayoutNodeId; pub struct Frame { - style: Style, + style: ElementStyle, + handlers: ElementHandlers, children: Vec>, } pub fn frame() -> Frame { Frame { - style: Style::default(), + style: ElementStyle::default(), + handlers: ElementHandlers::default(), children: Vec::new(), } } @@ -20,10 +22,14 @@ pub fn frame() -> Frame { impl Element for Frame { type Layout = (); - fn style_mut(&mut self) -> &mut Style { + fn style_mut(&mut self) -> &mut ElementStyle { &mut self.style } + fn handlers_mut(&mut self) -> &mut ElementHandlers { + &mut self.handlers + } + fn layout( &mut self, view: &mut V, @@ -44,14 +50,9 @@ impl Element for Frame { Ok((node_id, ())) } - fn paint( - &mut self, - layout: EngineLayout, - view: &mut V, - cx: &mut PaintContext, - ) -> Result<()> { + fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext) -> Result<()> { cx.scene.push_quad(gpui::scene::Quad { - bounds: layout.bounds, + bounds: layout.from_engine.bounds, background: self.style.fill.color().map(Into::into), border: Default::default(), corner_radii: Default::default(), @@ -63,12 +64,3 @@ impl Element for Frame { Ok(()) } } - -impl Clone for Frame { - fn clone(&self) -> Self { - Self { - style: self.style.clone(), - children: self.children.clone(), - } - } -} diff --git a/crates/gpui/playground/src/playground.rs b/crates/gpui/playground/src/playground.rs index 4631134649b46afaf6043b9dbc1cd72f346ddcd2..7f354cf3a8b3913aaee20815d05430c548b27204 100644 --- a/crates/gpui/playground/src/playground.rs +++ b/crates/gpui/playground/src/playground.rs @@ -14,6 +14,7 @@ use view::view; mod adapter; mod color; +mod components; mod element; mod frame; mod style; diff --git a/crates/gpui/playground/src/style.rs b/crates/gpui/playground/src/style.rs index 9741a2ff460329c98d8f05af5fc221b17e361976..91408d816b0b91f4ec0af563fed81019681b2fa7 100644 --- a/crates/gpui/playground/src/style.rs +++ b/crates/gpui/playground/src/style.rs @@ -5,7 +5,7 @@ pub use taffy::style::{ }; #[derive(Clone)] -pub struct Style { +pub struct ElementStyle { /// What layout strategy should be used? pub display: Display, @@ -67,8 +67,8 @@ pub struct Style { pub fill: Fill, } -impl Style { - pub const DEFAULT: Style = Style { +impl ElementStyle { + pub const DEFAULT: ElementStyle = ElementStyle { display: Display::DEFAULT, overflow: Point { x: Overflow::Visible, @@ -137,7 +137,7 @@ impl Style { } } -impl Default for Style { +impl Default for ElementStyle { fn default() -> Self { Self::DEFAULT.clone() } diff --git a/crates/gpui/playground_macros/src/derive_element.rs b/crates/gpui/playground_macros/src/derive_element.rs index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..8ea63cf620c4b0fec90f3d788677d4d0d41e6288 100644 --- a/crates/gpui/playground_macros/src/derive_element.rs +++ b/crates/gpui/playground_macros/src/derive_element.rs @@ -0,0 +1,48 @@ +// type Result = (); +// type LayoutContext<> = (); + +// trait Element: 'static + Clone { +// type Layout: 'static; + +// fn style_mut(&mut self) -> &mut Style; +// fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) +// -> Result<(NodeId, Self::Layout)>; +// fn paint<'a>( +// &mut self, +// layout: Layout<'a, Self::Layout>, +// view: &mut V, +// cx: &mut PaintContext, +// ) -> Result<()>; +// } + +// struct Button { +// style: Style, +// } + +// type Style = (); + +// impl Button { +// fn render() -> impl Element { +// todo!() +// } +// } + +// impl Element for Foo { +// type Layout = (); + +// fn style_mut(&mut self) -> &mut Style { +// unimplemented!() +// } + +// fn layout( +// &mut self, +// view: &mut V, +// cx: &mut LayoutContext, +// ) -> Result<(NodeId, Self::Layout)> { +// unimplemented!() +// } + +// fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext) -> Result<()> { +// unimplemented!() +// } +// }