WIP
This commit is contained in:
parent
f9858445b8
commit
0fe457020b
8 changed files with 199 additions and 107 deletions
58
crates/gpui/playground/src/components.rs
Normal file
58
crates/gpui/playground/src/components.rs
Normal file
|
@ -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<V: 'static, D: 'static> {
|
||||
label: Cow<'static, str>,
|
||||
data: Rc<D>,
|
||||
click_handler: Option<Rc<dyn Fn(&mut V, &dyn Any)>>,
|
||||
view_type: PhantomData<V>,
|
||||
}
|
||||
|
||||
impl<V: 'static> Button<V, ()> {
|
||||
fn new(label: impl Into<Cow<'static, str>>) -> Self {
|
||||
Self {
|
||||
label: label.into(),
|
||||
data: Rc::new(()),
|
||||
click_handler: None,
|
||||
view_type: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn data<D: 'static>(self, data: D) -> Button<V, D> {
|
||||
Button {
|
||||
label: self.label,
|
||||
data: Rc::new(data),
|
||||
click_handler: None,
|
||||
view_type: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: 'static, D: 'static> Button<V, D> {
|
||||
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::<D>().unwrap();
|
||||
handler(view, data);
|
||||
}));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn button<V>(label: impl Into<Cow<'static, str>>) -> Button<V, ()> {
|
||||
Button::new(label)
|
||||
}
|
||||
|
||||
impl<V: 'static, D: 'static> Button<V, D> {
|
||||
fn render(&mut self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<V: 'static>: 'static + Clone {
|
||||
fn style_mut(&mut self) -> &mut Style;
|
||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<NodeId>;
|
||||
fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext<V>) -> Result<()>;
|
||||
fn paint(&mut self, layout: EngineLayout, view: &mut V, cx: &mut PaintContext<V>)
|
||||
-> Result<()>;
|
||||
|
||||
/// Convert to a dynamically-typed element suitable for layout and paint.
|
||||
fn into_any(self) -> AnyElement<V>
|
||||
|
@ -259,7 +262,8 @@ pub trait Element<V: 'static>: 'static + Clone {
|
|||
pub trait ElementObject<V> {
|
||||
fn style_mut(&mut self) -> &mut Style;
|
||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<NodeId>;
|
||||
fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext<V>) -> Result<()>;
|
||||
fn paint(&mut self, layout: EngineLayout, view: &mut V, cx: &mut PaintContext<V>)
|
||||
-> Result<()>;
|
||||
fn clone_object(&self) -> Box<dyn ElementObject<V>>;
|
||||
}
|
||||
|
||||
|
@ -272,7 +276,12 @@ impl<V: 'static, E: Element<V>> ElementObject<V> for E {
|
|||
self.layout(view, cx)
|
||||
}
|
||||
|
||||
fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
|
||||
fn paint(
|
||||
&mut self,
|
||||
layout: EngineLayout,
|
||||
view: &mut V,
|
||||
cx: &mut PaintContext<V>,
|
||||
) -> Result<()> {
|
||||
self.paint(layout, view, cx)
|
||||
}
|
||||
|
||||
|
@ -286,6 +295,12 @@ pub struct AnyElement<V> {
|
|||
layout_node_id: Option<NodeId>,
|
||||
}
|
||||
|
||||
// enum LayoutState {
|
||||
// None,
|
||||
// Registered(NodeId, Box<dyn Any>),
|
||||
// Computed(Layout, Box<dyn Any>),
|
||||
// }
|
||||
|
||||
impl<V> AnyElement<V> {
|
||||
pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<NodeId> {
|
||||
let layout_node_id = self.element.layout(view, cx)?;
|
||||
|
@ -322,7 +337,12 @@ impl<V: 'static> Element<V> for AnyElement<V> {
|
|||
self.layout(view, cx)
|
||||
}
|
||||
|
||||
fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
|
||||
fn paint(
|
||||
&mut self,
|
||||
layout: EngineLayout,
|
||||
view: &mut V,
|
||||
cx: &mut PaintContext<V>,
|
||||
) -> Result<()> {
|
||||
self.paint(view, cx)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<V: 'static> Element<V> for Frame<V> {
|
|||
.add_node(self.style.to_taffy(rem_size), child_layout_node_ids)
|
||||
}
|
||||
|
||||
fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
|
||||
fn paint(
|
||||
&mut self,
|
||||
layout: EngineLayout,
|
||||
view: &mut V,
|
||||
cx: &mut PaintContext<V>,
|
||||
) -> Result<()> {
|
||||
cx.scene.push_quad(gpui::scene::Quad {
|
||||
bounds: layout.bounds,
|
||||
background: self.style.fill.color().map(Into::into),
|
||||
|
|
0
crates/gpui/playground_macros/src/derive_element.rs
Normal file
0
crates/gpui/playground_macros/src/derive_element.rs
Normal file
|
@ -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)
|
||||
}
|
||||
|
|
99
crates/gpui/playground_macros/src/tailwind_lengths.rs
Normal file
99
crates/gpui/playground_macros/src/tailwind_lengths.rs
Normal file
|
@ -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.) }),
|
||||
]
|
||||
}
|
|
@ -1264,17 +1264,17 @@ impl LayoutEngine {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn computed_layout(&mut self, node: LayoutNodeId) -> Result<Layout> {
|
||||
pub fn computed_layout(&mut self, node: LayoutNodeId) -> Result<EngineLayout> {
|
||||
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(
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue