From 0fe457020b366928d43f81606f42b20d73bf7ba5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 15 Aug 2023 09:26:16 -0600 Subject: [PATCH] WIP --- crates/gpui/playground/src/components.rs | 58 ++++++++++ crates/gpui/playground/src/element.rs | 30 +++++- crates/gpui/playground/src/frame.rs | 9 +- .../playground_macros/src/derive_element.rs | 0 .../src/playground_macros.rs | 101 +----------------- .../playground_macros/src/tailwind_lengths.rs | 99 +++++++++++++++++ crates/gpui/src/app/window.rs | 6 +- crates/gpui/src/gpui.rs | 3 +- 8 files changed, 199 insertions(+), 107 deletions(-) create mode 100644 crates/gpui/playground/src/components.rs create mode 100644 crates/gpui/playground_macros/src/derive_element.rs create mode 100644 crates/gpui/playground_macros/src/tailwind_lengths.rs diff --git a/crates/gpui/playground/src/components.rs b/crates/gpui/playground/src/components.rs new file mode 100644 index 0000000000..ebdd62f02b --- /dev/null +++ b/crates/gpui/playground/src/components.rs @@ -0,0 +1,58 @@ +use crate::{element::Element, frame, themes::rose_pine}; +use gpui::ViewContext; +use std::{any::Any, borrow::Cow, marker::PhantomData, rc::Rc}; + +pub struct Button { + label: Cow<'static, str>, + data: Rc, + click_handler: Option>, + view_type: PhantomData, +} + +impl Button { + fn new(label: impl Into>) -> Self { + Self { + label: label.into(), + data: Rc::new(()), + click_handler: None, + view_type: PhantomData, + } + } + + pub fn data(self, data: D) -> Button { + Button { + 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 + } +} + +pub fn button(label: impl Into>) -> Button { + Button::new(label) +} + +impl Button { + fn render(&mut self, view: &mut V, cx: &mut ViewContext) -> impl Element { + // 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() { + let data = self.data.clone(); + button.click(move |view, event| handler(view, data.as_ref())) + } else { + button + } + } +} diff --git a/crates/gpui/playground/src/element.rs b/crates/gpui/playground/src/element.rs index e962e71a25..d5f86885ce 100644 --- a/crates/gpui/playground/src/element.rs +++ b/crates/gpui/playground/src/element.rs @@ -4,7 +4,9 @@ use crate::{ }; use anyhow::Result; use derive_more::{Deref, DerefMut}; -use gpui::{Layout, LayoutContext as LegacyLayoutContext, PaintContext as LegacyPaintContext}; +use gpui::{ + EngineLayout, LayoutContext as LegacyLayoutContext, PaintContext as LegacyPaintContext, +}; use playground_macros::tailwind_lengths; pub use taffy::tree::NodeId; @@ -24,7 +26,8 @@ pub struct PaintContext<'a, 'b, 'c, 'd, V> { pub trait Element: 'static + Clone { fn style_mut(&mut self) -> &mut Style; fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result; - fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext) -> Result<()>; + fn paint(&mut self, layout: EngineLayout, view: &mut V, cx: &mut PaintContext) + -> Result<()>; /// Convert to a dynamically-typed element suitable for layout and paint. fn into_any(self) -> AnyElement @@ -259,7 +262,8 @@ pub trait Element: 'static + Clone { pub trait ElementObject { fn style_mut(&mut self) -> &mut Style; fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result; - fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext) -> Result<()>; + fn paint(&mut self, layout: EngineLayout, view: &mut V, cx: &mut PaintContext) + -> Result<()>; fn clone_object(&self) -> Box>; } @@ -272,7 +276,12 @@ impl> ElementObject for E { self.layout(view, cx) } - fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext) -> Result<()> { + fn paint( + &mut self, + layout: EngineLayout, + view: &mut V, + cx: &mut PaintContext, + ) -> Result<()> { self.paint(layout, view, cx) } @@ -286,6 +295,12 @@ pub struct AnyElement { layout_node_id: Option, } +// enum LayoutState { +// None, +// Registered(NodeId, Box), +// Computed(Layout, Box), +// } + impl AnyElement { pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -> Result { let layout_node_id = self.element.layout(view, cx)?; @@ -322,7 +337,12 @@ impl Element for AnyElement { self.layout(view, cx) } - fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext) -> Result<()> { + fn paint( + &mut self, + layout: EngineLayout, + 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 d025840caa..ef9be80c8e 100644 --- a/crates/gpui/playground/src/frame.rs +++ b/crates/gpui/playground/src/frame.rs @@ -1,5 +1,5 @@ use anyhow::{anyhow, Result}; -use gpui::{Layout, LayoutNodeId}; +use gpui::{EngineLayout, LayoutNodeId}; use crate::{ element::{AnyElement, Element, LayoutContext, PaintContext}, @@ -36,7 +36,12 @@ impl Element for Frame { .add_node(self.style.to_taffy(rem_size), child_layout_node_ids) } - fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext) -> Result<()> { + fn paint( + &mut self, + layout: EngineLayout, + view: &mut V, + cx: &mut PaintContext, + ) -> Result<()> { cx.scene.push_quad(gpui::scene::Quad { bounds: layout.bounds, background: self.style.fill.color().map(Into::into), diff --git a/crates/gpui/playground_macros/src/derive_element.rs b/crates/gpui/playground_macros/src/derive_element.rs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/crates/gpui/playground_macros/src/playground_macros.rs b/crates/gpui/playground_macros/src/playground_macros.rs index 01025f33af..1ea6ea9894 100644 --- a/crates/gpui/playground_macros/src/playground_macros.rs +++ b/crates/gpui/playground_macros/src/playground_macros.rs @@ -1,100 +1,9 @@ use proc_macro::TokenStream; -use proc_macro2::TokenStream as TokenStream2; -use quote::{format_ident, quote}; -use syn::{parse_macro_input, FnArg, ItemFn, PatType}; + +mod derive_element; +mod tailwind_lengths; #[proc_macro_attribute] -pub fn tailwind_lengths(_attr: TokenStream, item: TokenStream) -> TokenStream { - let input_function = parse_macro_input!(item as ItemFn); - - let visibility = &input_function.vis; - let function_signature = input_function.sig.clone(); - let function_body = input_function.block; - let where_clause = &function_signature.generics.where_clause; - - let argument_name = match function_signature.inputs.iter().nth(1) { - Some(FnArg::Typed(PatType { pat, .. })) => pat, - _ => panic!("Couldn't find the second argument in the function signature"), - }; - - let mut output_functions = TokenStream2::new(); - - for (length, value) in fixed_lengths() { - let function_name = format_ident!("{}{}", function_signature.ident, length); - output_functions.extend(quote! { - #visibility fn #function_name(mut self) -> Self #where_clause { - let #argument_name = #value.into(); - #function_body - } - }); - } - - output_functions.into() -} - -fn fixed_lengths() -> Vec<(&'static str, TokenStream2)> { - vec![ - ("0", quote! { DefinedLength::Pixels(0.) }), - ("px", quote! { DefinedLength::Pixels(1.) }), - ("0_5", quote! { DefinedLength::Rems(0.125) }), - ("1", quote! { DefinedLength::Rems(0.25) }), - ("1_5", quote! { DefinedLength::Rems(0.375) }), - ("2", quote! { DefinedLength::Rems(0.5) }), - ("2_5", quote! { DefinedLength::Rems(0.625) }), - ("3", quote! { DefinedLength::Rems(0.75) }), - ("3_5", quote! { DefinedLength::Rems(0.875) }), - ("4", quote! { DefinedLength::Rems(1.) }), - ("5", quote! { DefinedLength::Rems(1.25) }), - ("6", quote! { DefinedLength::Rems(1.5) }), - ("7", quote! { DefinedLength::Rems(1.75) }), - ("8", quote! { DefinedLength::Rems(2.) }), - ("9", quote! { DefinedLength::Rems(2.25) }), - ("10", quote! { DefinedLength::Rems(2.5) }), - ("11", quote! { DefinedLength::Rems(2.75) }), - ("12", quote! { DefinedLength::Rems(3.) }), - ("14", quote! { DefinedLength::Rems(3.5) }), - ("16", quote! { DefinedLength::Rems(4.) }), - ("20", quote! { DefinedLength::Rems(5.) }), - ("24", quote! { DefinedLength::Rems(6.) }), - ("28", quote! { DefinedLength::Rems(7.) }), - ("32", quote! { DefinedLength::Rems(8.) }), - ("36", quote! { DefinedLength::Rems(9.) }), - ("40", quote! { DefinedLength::Rems(10.) }), - ("44", quote! { DefinedLength::Rems(11.) }), - ("48", quote! { DefinedLength::Rems(12.) }), - ("52", quote! { DefinedLength::Rems(13.) }), - ("56", quote! { DefinedLength::Rems(14.) }), - ("60", quote! { DefinedLength::Rems(15.) }), - ("64", quote! { DefinedLength::Rems(16.) }), - ("72", quote! { DefinedLength::Rems(18.) }), - ("80", quote! { DefinedLength::Rems(20.) }), - ("96", quote! { DefinedLength::Rems(24.) }), - ("half", quote! { DefinedLength::Percent(50.) }), - ("1_3rd", quote! { DefinedLength::Percent(33.333333) }), - ("2_3rd", quote! { DefinedLength::Percent(66.666667) }), - ("1_4th", quote! { DefinedLength::Percent(25.) }), - ("2_4th", quote! { DefinedLength::Percent(50.) }), - ("3_4th", quote! { DefinedLength::Percent(75.) }), - ("1_5th", quote! { DefinedLength::Percent(20.) }), - ("2_5th", quote! { DefinedLength::Percent(40.) }), - ("3_5th", quote! { DefinedLength::Percent(60.) }), - ("4_5th", quote! { DefinedLength::Percent(80.) }), - ("1_6th", quote! { DefinedLength::Percent(16.666667) }), - ("2_6th", quote! { DefinedLength::Percent(33.333333) }), - ("3_6th", quote! { DefinedLength::Percent(50.) }), - ("4_6th", quote! { DefinedLength::Percent(66.666667) }), - ("5_6th", quote! { DefinedLength::Percent(83.333333) }), - ("1_12th", quote! { DefinedLength::Percent(8.333333) }), - ("2_12th", quote! { DefinedLength::Percent(16.666667) }), - ("3_12th", quote! { DefinedLength::Percent(25.) }), - ("4_12th", quote! { DefinedLength::Percent(33.333333) }), - ("5_12th", quote! { DefinedLength::Percent(41.666667) }), - ("6_12th", quote! { DefinedLength::Percent(50.) }), - ("7_12th", quote! { DefinedLength::Percent(58.333333) }), - ("8_12th", quote! { DefinedLength::Percent(66.666667) }), - ("9_12th", quote! { DefinedLength::Percent(75.) }), - ("10_12th", quote! { DefinedLength::Percent(83.333333) }), - ("11_12th", quote! { DefinedLength::Percent(91.666667) }), - ("full", quote! { DefinedLength::Percent(100.) }), - ] +pub fn tailwind_lengths(attr: TokenStream, item: TokenStream) -> TokenStream { + tailwind_lengths::tailwind_lengths(attr, item) } diff --git a/crates/gpui/playground_macros/src/tailwind_lengths.rs b/crates/gpui/playground_macros/src/tailwind_lengths.rs new file mode 100644 index 0000000000..96c7d29947 --- /dev/null +++ b/crates/gpui/playground_macros/src/tailwind_lengths.rs @@ -0,0 +1,99 @@ +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +use quote::{format_ident, quote}; +use syn::{parse_macro_input, FnArg, ItemFn, PatType}; + +pub fn tailwind_lengths(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input_function = parse_macro_input!(item as ItemFn); + + let visibility = &input_function.vis; + let function_signature = input_function.sig.clone(); + let function_body = input_function.block; + let where_clause = &function_signature.generics.where_clause; + + let argument_name = match function_signature.inputs.iter().nth(1) { + Some(FnArg::Typed(PatType { pat, .. })) => pat, + _ => panic!("Couldn't find the second argument in the function signature"), + }; + + let mut output_functions = TokenStream2::new(); + + for (length, value) in fixed_lengths() { + let function_name = format_ident!("{}{}", function_signature.ident, length); + output_functions.extend(quote! { + #visibility fn #function_name(mut self) -> Self #where_clause { + let #argument_name = #value.into(); + #function_body + } + }); + } + + output_functions.into() +} + +fn fixed_lengths() -> Vec<(&'static str, TokenStream2)> { + vec![ + ("0", quote! { DefinedLength::Pixels(0.) }), + ("px", quote! { DefinedLength::Pixels(1.) }), + ("0_5", quote! { DefinedLength::Rems(0.125) }), + ("1", quote! { DefinedLength::Rems(0.25) }), + ("1_5", quote! { DefinedLength::Rems(0.375) }), + ("2", quote! { DefinedLength::Rems(0.5) }), + ("2_5", quote! { DefinedLength::Rems(0.625) }), + ("3", quote! { DefinedLength::Rems(0.75) }), + ("3_5", quote! { DefinedLength::Rems(0.875) }), + ("4", quote! { DefinedLength::Rems(1.) }), + ("5", quote! { DefinedLength::Rems(1.25) }), + ("6", quote! { DefinedLength::Rems(1.5) }), + ("7", quote! { DefinedLength::Rems(1.75) }), + ("8", quote! { DefinedLength::Rems(2.) }), + ("9", quote! { DefinedLength::Rems(2.25) }), + ("10", quote! { DefinedLength::Rems(2.5) }), + ("11", quote! { DefinedLength::Rems(2.75) }), + ("12", quote! { DefinedLength::Rems(3.) }), + ("14", quote! { DefinedLength::Rems(3.5) }), + ("16", quote! { DefinedLength::Rems(4.) }), + ("20", quote! { DefinedLength::Rems(5.) }), + ("24", quote! { DefinedLength::Rems(6.) }), + ("28", quote! { DefinedLength::Rems(7.) }), + ("32", quote! { DefinedLength::Rems(8.) }), + ("36", quote! { DefinedLength::Rems(9.) }), + ("40", quote! { DefinedLength::Rems(10.) }), + ("44", quote! { DefinedLength::Rems(11.) }), + ("48", quote! { DefinedLength::Rems(12.) }), + ("52", quote! { DefinedLength::Rems(13.) }), + ("56", quote! { DefinedLength::Rems(14.) }), + ("60", quote! { DefinedLength::Rems(15.) }), + ("64", quote! { DefinedLength::Rems(16.) }), + ("72", quote! { DefinedLength::Rems(18.) }), + ("80", quote! { DefinedLength::Rems(20.) }), + ("96", quote! { DefinedLength::Rems(24.) }), + ("half", quote! { DefinedLength::Percent(50.) }), + ("1_3rd", quote! { DefinedLength::Percent(33.333333) }), + ("2_3rd", quote! { DefinedLength::Percent(66.666667) }), + ("1_4th", quote! { DefinedLength::Percent(25.) }), + ("2_4th", quote! { DefinedLength::Percent(50.) }), + ("3_4th", quote! { DefinedLength::Percent(75.) }), + ("1_5th", quote! { DefinedLength::Percent(20.) }), + ("2_5th", quote! { DefinedLength::Percent(40.) }), + ("3_5th", quote! { DefinedLength::Percent(60.) }), + ("4_5th", quote! { DefinedLength::Percent(80.) }), + ("1_6th", quote! { DefinedLength::Percent(16.666667) }), + ("2_6th", quote! { DefinedLength::Percent(33.333333) }), + ("3_6th", quote! { DefinedLength::Percent(50.) }), + ("4_6th", quote! { DefinedLength::Percent(66.666667) }), + ("5_6th", quote! { DefinedLength::Percent(83.333333) }), + ("1_12th", quote! { DefinedLength::Percent(8.333333) }), + ("2_12th", quote! { DefinedLength::Percent(16.666667) }), + ("3_12th", quote! { DefinedLength::Percent(25.) }), + ("4_12th", quote! { DefinedLength::Percent(33.333333) }), + ("5_12th", quote! { DefinedLength::Percent(41.666667) }), + ("6_12th", quote! { DefinedLength::Percent(50.) }), + ("7_12th", quote! { DefinedLength::Percent(58.333333) }), + ("8_12th", quote! { DefinedLength::Percent(66.666667) }), + ("9_12th", quote! { DefinedLength::Percent(75.) }), + ("10_12th", quote! { DefinedLength::Percent(83.333333) }), + ("11_12th", quote! { DefinedLength::Percent(91.666667) }), + ("full", quote! { DefinedLength::Percent(100.) }), + ] +} diff --git a/crates/gpui/src/app/window.rs b/crates/gpui/src/app/window.rs index cfd602df5c..65071d89ed 100644 --- a/crates/gpui/src/app/window.rs +++ b/crates/gpui/src/app/window.rs @@ -1264,17 +1264,17 @@ impl LayoutEngine { Ok(()) } - pub fn computed_layout(&mut self, node: LayoutNodeId) -> Result { + pub fn computed_layout(&mut self, node: LayoutNodeId) -> Result { Ok(self.0.layout(node)?.into()) } } -pub struct Layout { +pub struct EngineLayout { pub bounds: RectF, pub order: u32, } -impl From<&taffy::tree::Layout> for Layout { +impl From<&taffy::tree::Layout> for EngineLayout { fn from(value: &taffy::tree::Layout) -> Self { Self { bounds: RectF::new( diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 3b3374e7eb..33aeb50bbd 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -28,7 +28,8 @@ pub mod keymap_matcher; pub mod platform; pub use gpui_macros::{test, Element}; pub use window::{ - Axis, Layout, LayoutEngine, LayoutNodeId, RectFExt, SizeConstraint, Vector2FExt, WindowContext, + Axis, EngineLayout, LayoutEngine, LayoutNodeId, RectFExt, SizeConstraint, Vector2FExt, + WindowContext, }; pub use anyhow;