Checkpoint
This commit is contained in:
parent
afff46b335
commit
6663d3f8eb
7 changed files with 350 additions and 367 deletions
|
@ -1,131 +1,131 @@
|
||||||
use crate::{
|
// use crate::{
|
||||||
element::{Element, ElementMetadata, ParentElement},
|
// element::{Element, ElementMetadata, ParentElement},
|
||||||
frame,
|
// frame,
|
||||||
text::ArcCow,
|
// text::ArcCow,
|
||||||
themes::rose_pine,
|
// themes::rose_pine,
|
||||||
};
|
// };
|
||||||
use gpui::{platform::MouseButton, ViewContext};
|
// use gpui::{platform::MouseButton, ViewContext};
|
||||||
use playground_macros::Element;
|
// use playground_macros::Element;
|
||||||
use std::{marker::PhantomData, rc::Rc};
|
// use std::{marker::PhantomData, rc::Rc};
|
||||||
|
|
||||||
struct ButtonHandlers<V, D> {
|
// struct ButtonHandlers<V, D> {
|
||||||
click: Option<Rc<dyn Fn(&mut V, &D, &mut ViewContext<V>)>>,
|
// click: Option<Rc<dyn Fn(&mut V, &D, &mut ViewContext<V>)>>,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl<V, D> Default for ButtonHandlers<V, D> {
|
// impl<V, D> Default for ButtonHandlers<V, D> {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
Self { click: None }
|
// Self { click: None }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Element)]
|
|
||||||
#[element_crate = "crate"]
|
|
||||||
pub struct Button<V: 'static, D: 'static> {
|
|
||||||
metadata: ElementMetadata<V>,
|
|
||||||
handlers: ButtonHandlers<V, D>,
|
|
||||||
label: Option<ArcCow<'static, str>>,
|
|
||||||
icon: Option<ArcCow<'static, str>>,
|
|
||||||
data: Rc<D>,
|
|
||||||
view_type: PhantomData<V>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Impl block for buttons without data.
|
|
||||||
// See below for an impl block for any button.
|
|
||||||
impl<V: 'static> Button<V, ()> {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
metadata: Default::default(),
|
|
||||||
handlers: ButtonHandlers::default(),
|
|
||||||
label: None,
|
|
||||||
icon: None,
|
|
||||||
data: Rc::new(()),
|
|
||||||
view_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn data<D: 'static>(self, data: D) -> Button<V, D> {
|
|
||||||
Button {
|
|
||||||
metadata: Default::default(),
|
|
||||||
handlers: ButtonHandlers::default(),
|
|
||||||
label: self.label,
|
|
||||||
icon: self.icon,
|
|
||||||
data: Rc::new(data),
|
|
||||||
view_type: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Impl block for *any* button.
|
|
||||||
impl<V: 'static, D: 'static> Button<V, D> {
|
|
||||||
pub fn label(mut self, label: impl Into<ArcCow<'static, str>>) -> Self {
|
|
||||||
self.label = Some(label.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn icon(mut self, icon: impl Into<ArcCow<'static, str>>) -> Self {
|
|
||||||
self.icon = Some(icon.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn click(self, handler: impl Fn(&mut V, &D, &mut ViewContext<V>) + 'static) -> Self {
|
|
||||||
let data = self.data.clone();
|
|
||||||
Element::click(self, MouseButton::Left, move |view, _, cx| {
|
|
||||||
handler(view, data.as_ref(), cx);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn button<V>() -> Button<V, ()> {
|
|
||||||
Button::new()
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: 'static, D: 'static> Button<V, D> {
|
|
||||||
fn render(&mut self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
|
|
||||||
// TODO: Drive theme from the context
|
|
||||||
let button = frame()
|
|
||||||
.fill(rose_pine::dawn().error(0.5))
|
|
||||||
.h_4()
|
|
||||||
.children(self.label.clone());
|
|
||||||
|
|
||||||
if let Some(handler) = self.handlers.click.clone() {
|
|
||||||
let data = self.data.clone();
|
|
||||||
button.mouse_down(MouseButton::Left, move |view, event, cx| {
|
|
||||||
handler(view, data.as_ref(), cx)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
button
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl<V: 'static, D> Element<V> for Button<V, D> {
|
|
||||||
// type Layout = AnyElement<V>;
|
|
||||||
|
|
||||||
// fn style_mut(&mut self) -> &mut crate::style::ElementStyle {
|
|
||||||
// &mut self.metadata.style
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers<V> {
|
|
||||||
// &mut self.metadata.handlers
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fn layout(
|
|
||||||
// &mut self,
|
|
||||||
// view: &mut V,
|
|
||||||
// cx: &mut crate::element::LayoutContext<V>,
|
|
||||||
// ) -> 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<V>,
|
|
||||||
// ) -> anyhow::Result<()> {
|
|
||||||
// layout.from_element.paint(view, cx)?;
|
|
||||||
// Ok(())
|
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// #[derive(Element)]
|
||||||
|
// #[element_crate = "crate"]
|
||||||
|
// pub struct Button<V: 'static, D: 'static> {
|
||||||
|
// metadata: ElementMetadata<V>,
|
||||||
|
// handlers: ButtonHandlers<V, D>,
|
||||||
|
// label: Option<ArcCow<'static, str>>,
|
||||||
|
// icon: Option<ArcCow<'static, str>>,
|
||||||
|
// data: Rc<D>,
|
||||||
|
// view_type: PhantomData<V>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Impl block for buttons without data.
|
||||||
|
// // See below for an impl block for any button.
|
||||||
|
// impl<V: 'static> Button<V, ()> {
|
||||||
|
// fn new() -> Self {
|
||||||
|
// Self {
|
||||||
|
// metadata: Default::default(),
|
||||||
|
// handlers: ButtonHandlers::default(),
|
||||||
|
// label: None,
|
||||||
|
// icon: None,
|
||||||
|
// data: Rc::new(()),
|
||||||
|
// view_type: PhantomData,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn data<D: 'static>(self, data: D) -> Button<V, D> {
|
||||||
|
// Button {
|
||||||
|
// metadata: Default::default(),
|
||||||
|
// handlers: ButtonHandlers::default(),
|
||||||
|
// label: self.label,
|
||||||
|
// icon: self.icon,
|
||||||
|
// data: Rc::new(data),
|
||||||
|
// view_type: PhantomData,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Impl block for *any* button.
|
||||||
|
// impl<V: 'static, D: 'static> Button<V, D> {
|
||||||
|
// pub fn label(mut self, label: impl Into<ArcCow<'static, str>>) -> Self {
|
||||||
|
// self.label = Some(label.into());
|
||||||
|
// self
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn icon(mut self, icon: impl Into<ArcCow<'static, str>>) -> Self {
|
||||||
|
// self.icon = Some(icon.into());
|
||||||
|
// self
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn click(self, handler: impl Fn(&mut V, &D, &mut ViewContext<V>) + 'static) -> Self {
|
||||||
|
// let data = self.data.clone();
|
||||||
|
// Element::click(self, MouseButton::Left, move |view, _, cx| {
|
||||||
|
// handler(view, data.as_ref(), cx);
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn button<V>() -> Button<V, ()> {
|
||||||
|
// Button::new()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<V: 'static, D: 'static> Button<V, D> {
|
||||||
|
// fn render(&mut self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
|
||||||
|
// // TODO: Drive theme from the context
|
||||||
|
// let button = frame()
|
||||||
|
// .fill(rose_pine::dawn().error(0.5))
|
||||||
|
// .h_4()
|
||||||
|
// .children(self.label.clone());
|
||||||
|
|
||||||
|
// if let Some(handler) = self.handlers.click.clone() {
|
||||||
|
// let data = self.data.clone();
|
||||||
|
// button.mouse_down(MouseButton::Left, move |view, event, cx| {
|
||||||
|
// handler(view, data.as_ref(), cx)
|
||||||
|
// })
|
||||||
|
// } else {
|
||||||
|
// button
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // impl<V: 'static, D> Element<V> for Button<V, D> {
|
||||||
|
// // type Layout = AnyElement<V>;
|
||||||
|
|
||||||
|
// // fn style_mut(&mut self) -> &mut crate::style::ElementStyle {
|
||||||
|
// // &mut self.metadata.style
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers<V> {
|
||||||
|
// // &mut self.metadata.handlers
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // fn layout(
|
||||||
|
// // &mut self,
|
||||||
|
// // view: &mut V,
|
||||||
|
// // cx: &mut crate::element::LayoutContext<V>,
|
||||||
|
// // ) -> 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<V>,
|
||||||
|
// // ) -> anyhow::Result<()> {
|
||||||
|
// // layout.from_element.paint(view, cx)?;
|
||||||
|
// // Ok(())
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
|
@ -78,7 +78,6 @@ pub trait Element<V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate as playground; // Macro invocation below references this crate as playground.
|
|
||||||
pub trait Styleable {
|
pub trait Styleable {
|
||||||
type Style: refineable::Refineable;
|
type Style: refineable::Refineable;
|
||||||
|
|
||||||
|
@ -89,12 +88,15 @@ pub trait Styleable {
|
||||||
style.refine(self.declared_style());
|
style.refine(self.declared_style());
|
||||||
style
|
style
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tailwind-style helpers methods that take and return mut self
|
// Tailwind-style helpers methods that take and return mut self
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// // Sets the padding to 0.5rem, just like class="p-2" in Tailwind.
|
// // Sets the padding to 0.5rem, just like class="p-2" in Tailwind.
|
||||||
// fn p_2(mut self) -> Self where Self: Sized;
|
// fn p_2(mut self) -> Self where Self: Sized;
|
||||||
|
use crate as playground; // Macro invocation references this crate as playground.
|
||||||
|
pub trait StyleHelpers: Styleable<Style = Style> {
|
||||||
styleable_helpers!();
|
styleable_helpers!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +141,8 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
|
|
||||||
|
style.paint_background::<V, Self>(layout, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
adapter::Adapter,
|
adapter::Adapter,
|
||||||
color::Hsla,
|
color::Hsla,
|
||||||
hoverable::Hoverable,
|
|
||||||
style::{Display, Fill, Overflow, Position, StyleRefinement},
|
style::{Display, Fill, Overflow, Position, StyleRefinement},
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
pub use gpui::LayoutContext;
|
pub use gpui::LayoutContext;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
geometry::{DefinedLength, Length, PointRefinement},
|
geometry::PointRefinement,
|
||||||
platform::{MouseButton, MouseButtonEvent},
|
platform::{MouseButton, MouseButtonEvent},
|
||||||
EngineLayout, EventContext, RenderContext, ViewContext,
|
EngineLayout, EventContext, RenderContext, ViewContext,
|
||||||
};
|
};
|
||||||
use playground_macros::tailwind_lengths;
|
|
||||||
use refineable::Refineable;
|
use refineable::Refineable;
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
|
@ -338,94 +336,6 @@ pub trait Element<V: 'static>: 'static {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tailwind_lengths]
|
|
||||||
fn inset_(mut self, length: DefinedLength) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
let inset = &mut self.declared_style().inset;
|
|
||||||
inset.top = Some(length);
|
|
||||||
inset.right = Some(length);
|
|
||||||
inset.bottom = Some(length);
|
|
||||||
inset.left = Some(length);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn w(mut self, width: impl Into<Length>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().size.width = Some(width.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn w_auto(mut self) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().size.width = Some(Length::Auto);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tailwind_lengths]
|
|
||||||
fn w_(mut self, length: DefinedLength) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().size.width = Some(length);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tailwind_lengths]
|
|
||||||
fn min_w_(mut self, length: DefinedLength) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().min_size.width = Some(length);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn h(mut self, height: impl Into<Length>) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().size.height = Some(height.into());
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn h_auto(mut self) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().size.height = Some(Length::Auto);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tailwind_lengths]
|
|
||||||
fn h_(mut self, height: DefinedLength) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().size.height = Some(height);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tailwind_lengths]
|
|
||||||
fn min_h_(mut self, length: DefinedLength) -> Self
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
self.declared_style().min_size.height = Some(length);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hover(self) -> Hoverable<V, Self>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
Hoverable::new(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill(mut self, fill: impl Into<Fill>) -> Self
|
fn fill(mut self, fill: impl Into<Fill>) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
use color::black;
|
|
||||||
use components::button;
|
|
||||||
use element::{Element, ParentElement};
|
|
||||||
use frame::frame;
|
|
||||||
use gpui::{
|
|
||||||
geometry::{rect::RectF, vector::vec2f},
|
|
||||||
platform::WindowOptions,
|
|
||||||
};
|
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
|
|
||||||
use themes::{rose_pine, ThemeColors};
|
use themes::ThemeColors;
|
||||||
use view::view;
|
|
||||||
|
|
||||||
mod adapter;
|
mod adapter;
|
||||||
mod color;
|
mod color;
|
||||||
|
@ -31,31 +22,32 @@ fn main() {
|
||||||
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
|
||||||
|
|
||||||
gpui::App::new(()).unwrap().run(|cx| {
|
gpui::App::new(()).unwrap().run(|cx| {
|
||||||
cx.add_window(
|
// cx.add_window(
|
||||||
WindowOptions {
|
// WindowOptions {
|
||||||
bounds: gpui::platform::WindowBounds::Fixed(RectF::new(
|
// bounds: gpui::platform::WindowBounds::Fixed(RectF::new(
|
||||||
vec2f(0., 0.),
|
// vec2f(0., 0.),
|
||||||
vec2f(400., 300.),
|
// vec2f(400., 300.),
|
||||||
)),
|
// )),
|
||||||
center: true,
|
// center: true,
|
||||||
..Default::default()
|
// ..Default::default()
|
||||||
},
|
// },
|
||||||
|_| view(|_| playground(&rose_pine::moon())),
|
// |_| view(|_| playground(&rose_pine::moon())),
|
||||||
);
|
// );
|
||||||
cx.platform().activate(true);
|
cx.platform().activate(true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn playground<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
// fn playground<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
||||||
frame()
|
// todo!()
|
||||||
.text_color(black())
|
// // frame()
|
||||||
.h_full()
|
// // .text_color(black())
|
||||||
.w_half()
|
// // .h_full()
|
||||||
.fill(theme.success(0.5))
|
// // .w_half()
|
||||||
.hover()
|
// // .fill(theme.success(0.5))
|
||||||
.fill(theme.error(0.5))
|
// // .hover()
|
||||||
.child(button().label("Hello").click(|_, _, _| println!("click!")))
|
// // .fill(theme.error(0.5))
|
||||||
}
|
// // .child(button().label("Hello").click(|_, _, _| println!("click!")))
|
||||||
|
// }
|
||||||
|
|
||||||
// todo!()
|
// todo!()
|
||||||
// // column()
|
// // column()
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
use crate::color::Hsla;
|
use crate::{
|
||||||
|
color::Hsla,
|
||||||
|
div::{Element, Layout},
|
||||||
|
element::PaintContext,
|
||||||
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
fonts::TextStyleRefinement,
|
fonts::TextStyleRefinement,
|
||||||
geometry::{
|
geometry::{
|
||||||
DefinedLength, Edges, EdgesRefinement, Length, Point, PointRefinement, Size, SizeRefinement,
|
AbsoluteLength, DefiniteLength, Edges, EdgesRefinement, Length, Point, PointRefinement,
|
||||||
|
Size, SizeRefinement,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use refineable::Refineable;
|
use refineable::Refineable;
|
||||||
|
@ -49,10 +54,10 @@ pub struct Style {
|
||||||
pub margin: Edges<Length>,
|
pub margin: Edges<Length>,
|
||||||
/// How large should the padding be on each side?
|
/// How large should the padding be on each side?
|
||||||
#[refineable]
|
#[refineable]
|
||||||
pub padding: Edges<DefinedLength>,
|
pub padding: Edges<DefiniteLength>,
|
||||||
/// How large should the border be on each side?
|
/// How large should the border be on each side?
|
||||||
#[refineable]
|
#[refineable]
|
||||||
pub border: Edges<DefinedLength>,
|
pub border: Edges<DefiniteLength>,
|
||||||
|
|
||||||
// Alignment properties
|
// Alignment properties
|
||||||
/// How this node's children aligned in the cross/block axis?
|
/// How this node's children aligned in the cross/block axis?
|
||||||
|
@ -65,7 +70,7 @@ pub struct Style {
|
||||||
pub justify_content: Option<JustifyContent>,
|
pub justify_content: Option<JustifyContent>,
|
||||||
/// How large should the gaps between items in a flex container be?
|
/// How large should the gaps between items in a flex container be?
|
||||||
#[refineable]
|
#[refineable]
|
||||||
pub gap: Size<DefinedLength>,
|
pub gap: Size<DefiniteLength>,
|
||||||
|
|
||||||
// Flexbox properies
|
// Flexbox properies
|
||||||
/// Which direction does the main axis flow in?
|
/// Which direction does the main axis flow in?
|
||||||
|
@ -81,47 +86,14 @@ pub struct Style {
|
||||||
|
|
||||||
/// The fill color of this element
|
/// The fill color of this element
|
||||||
pub fill: Option<Fill>,
|
pub fill: Option<Fill>,
|
||||||
|
/// The radius of the corners of this element
|
||||||
|
#[refineable]
|
||||||
|
pub corner_radii: CornerRadii,
|
||||||
/// The color of text within this element. Cascades to children unless overridden.
|
/// The color of text within this element. Cascades to children unless overridden.
|
||||||
pub text_color: Option<Hsla>,
|
pub text_color: Option<Hsla>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Style {
|
impl Style {
|
||||||
pub const DEFAULT: Style = Style {
|
|
||||||
display: Display::DEFAULT,
|
|
||||||
overflow: Point {
|
|
||||||
x: Overflow::Visible,
|
|
||||||
y: Overflow::Visible,
|
|
||||||
},
|
|
||||||
scrollbar_width: 0.0,
|
|
||||||
position: Position::Relative,
|
|
||||||
inset: Edges::auto(),
|
|
||||||
margin: Edges::<Length>::zero(),
|
|
||||||
padding: Edges::<DefinedLength>::zero(),
|
|
||||||
border: Edges::<DefinedLength>::zero(),
|
|
||||||
size: Size::auto(),
|
|
||||||
min_size: Size::auto(),
|
|
||||||
max_size: Size::auto(),
|
|
||||||
aspect_ratio: None,
|
|
||||||
gap: Size::zero(),
|
|
||||||
// Aligment
|
|
||||||
align_items: None,
|
|
||||||
align_self: None,
|
|
||||||
align_content: None,
|
|
||||||
justify_content: None,
|
|
||||||
// Flexbox
|
|
||||||
flex_direction: FlexDirection::Row,
|
|
||||||
flex_wrap: FlexWrap::NoWrap,
|
|
||||||
flex_grow: 0.0,
|
|
||||||
flex_shrink: 1.0,
|
|
||||||
flex_basis: Length::Auto,
|
|
||||||
fill: None,
|
|
||||||
text_color: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::DEFAULT.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_taffy(&self, rem_size: f32) -> taffy::style::Style {
|
pub fn to_taffy(&self, rem_size: f32) -> taffy::style::Style {
|
||||||
taffy::style::Style {
|
taffy::style::Style {
|
||||||
display: self.display,
|
display: self.display,
|
||||||
|
@ -149,11 +121,61 @@ impl Style {
|
||||||
..Default::default() // Ignore grid properties for now
|
..Default::default() // Ignore grid properties for now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Paints the background of an element styled with this style.
|
||||||
|
/// Return the bounds in which to paint the content.
|
||||||
|
pub fn paint_background<V: 'static, E: Element<V>>(
|
||||||
|
&self,
|
||||||
|
layout: &mut Layout<V, E::Layout>,
|
||||||
|
cx: &mut PaintContext<V>,
|
||||||
|
) {
|
||||||
|
let bounds = layout.bounds(cx);
|
||||||
|
let rem_size = cx.rem_pixels();
|
||||||
|
if let Some(color) = self.fill.as_ref().and_then(Fill::color) {
|
||||||
|
cx.scene.push_quad(gpui::Quad {
|
||||||
|
bounds,
|
||||||
|
background: Some(color.into()),
|
||||||
|
corner_radii: self.corner_radii.to_gpui(rem_size),
|
||||||
|
border: Default::default(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Style {
|
impl Default for Style {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::DEFAULT.clone()
|
Style {
|
||||||
|
display: Display::DEFAULT,
|
||||||
|
overflow: Point {
|
||||||
|
x: Overflow::Visible,
|
||||||
|
y: Overflow::Visible,
|
||||||
|
},
|
||||||
|
scrollbar_width: 0.0,
|
||||||
|
position: Position::Relative,
|
||||||
|
inset: Edges::auto(),
|
||||||
|
margin: Edges::<Length>::zero(),
|
||||||
|
padding: Edges::<DefiniteLength>::zero(),
|
||||||
|
border: Edges::<DefiniteLength>::zero(),
|
||||||
|
size: Size::auto(),
|
||||||
|
min_size: Size::auto(),
|
||||||
|
max_size: Size::auto(),
|
||||||
|
aspect_ratio: None,
|
||||||
|
gap: Size::zero(),
|
||||||
|
// Aligment
|
||||||
|
align_items: None,
|
||||||
|
align_self: None,
|
||||||
|
align_content: None,
|
||||||
|
justify_content: None,
|
||||||
|
// Flexbox
|
||||||
|
flex_direction: FlexDirection::Row,
|
||||||
|
flex_wrap: FlexWrap::NoWrap,
|
||||||
|
flex_grow: 0.0,
|
||||||
|
flex_shrink: 1.0,
|
||||||
|
flex_basis: Length::Auto,
|
||||||
|
fill: None,
|
||||||
|
text_color: None,
|
||||||
|
corner_radii: CornerRadii::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,3 +224,22 @@ impl From<Hsla> for Fill {
|
||||||
Self::Color(color)
|
Self::Color(color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Refineable, Default)]
|
||||||
|
pub struct CornerRadii {
|
||||||
|
top_left: AbsoluteLength,
|
||||||
|
top_right: AbsoluteLength,
|
||||||
|
bottom_left: AbsoluteLength,
|
||||||
|
bottom_right: AbsoluteLength,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CornerRadii {
|
||||||
|
pub fn to_gpui(&self, rem_size: f32) -> gpui::scene::CornerRadii {
|
||||||
|
gpui::scene::CornerRadii {
|
||||||
|
top_left: self.top_left.to_pixels(rem_size),
|
||||||
|
top_right: self.top_right.to_pixels(rem_size),
|
||||||
|
bottom_left: self.bottom_left.to_pixels(rem_size),
|
||||||
|
bottom_right: self.bottom_right.to_pixels(rem_size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ fn generate_methods() -> Vec<TokenStream2> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field_tokens| {
|
.map(|field_tokens| {
|
||||||
quote! {
|
quote! {
|
||||||
style.#field_tokens = Some(gpui::geometry::#length_tokens.into());
|
style.#field_tokens = Some(gpui::geometry::#length_tokens);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -60,30 +60,30 @@ fn generate_methods() -> Vec<TokenStream2> {
|
||||||
|
|
||||||
fn tailwind_lengths() -> Vec<(&'static str, TokenStream2)> {
|
fn tailwind_lengths() -> Vec<(&'static str, TokenStream2)> {
|
||||||
vec![
|
vec![
|
||||||
("0", quote! { DefinedLength::Pixels(0.) }),
|
("0", quote! { pixels(0.) }),
|
||||||
("1", quote! { DefinedLength::Rems(0.25) }),
|
("1", quote! { rems(0.25) }),
|
||||||
("2", quote! { DefinedLength::Rems(0.5) }),
|
("2", quote! { rems(0.5) }),
|
||||||
("3", quote! { DefinedLength::Rems(0.75) }),
|
("3", quote! { rems(0.75) }),
|
||||||
("4", quote! { DefinedLength::Rems(1.0) }),
|
("4", quote! { rems(1.) }),
|
||||||
("5", quote! { DefinedLength::Rems(1.25) }),
|
("5", quote! { rems(1.25) }),
|
||||||
("6", quote! { DefinedLength::Rems(1.5) }),
|
("6", quote! { rems(1.5) }),
|
||||||
("8", quote! { DefinedLength::Rems(2.0) }),
|
("8", quote! { rems(2.0) }),
|
||||||
("10", quote! { DefinedLength::Rems(2.5) }),
|
("10", quote! { rems(2.5) }),
|
||||||
("12", quote! { DefinedLength::Rems(3.0) }),
|
("12", quote! { rems(3.) }),
|
||||||
("16", quote! { DefinedLength::Rems(4.0) }),
|
("16", quote! { rems(4.) }),
|
||||||
("20", quote! { DefinedLength::Rems(5.0) }),
|
("20", quote! { rems(5.) }),
|
||||||
("24", quote! { DefinedLength::Rems(6.0) }),
|
("24", quote! { rems(6.) }),
|
||||||
("32", quote! { DefinedLength::Rems(8.0) }),
|
("32", quote! { rems(8.) }),
|
||||||
("40", quote! { DefinedLength::Rems(10.0) }),
|
("40", quote! { rems(10.) }),
|
||||||
("48", quote! { DefinedLength::Rems(12.0) }),
|
("48", quote! { rems(12.) }),
|
||||||
("56", quote! { DefinedLength::Rems(14.0) }),
|
("56", quote! { rems(14.) }),
|
||||||
("64", quote! { DefinedLength::Rems(16.0) }),
|
("64", quote! { rems(16.) }),
|
||||||
("auto", quote! { Length::Auto }),
|
("auto", quote! { auto() }),
|
||||||
("px", quote! { DefinedLength::Pixels(1.0) }),
|
("px", quote! { pixels(1.) }),
|
||||||
("full", quote! { DefinedLength::Percent(100.0) }),
|
("full", quote! { relative(1.) }),
|
||||||
// ("screen_50", quote! { DefinedLength::Vh(50.0) }),
|
// ("screen_50", quote! { DefiniteLength::Vh(50.0) }),
|
||||||
// ("screen_75", quote! { DefinedLength::Vh(75.0) }),
|
// ("screen_75", quote! { DefiniteLength::Vh(75.0) }),
|
||||||
// ("screen", quote! { DefinedLength::Vh(100.0) }),
|
// ("screen", quote! { DefiniteLength::Vh(100.0) }),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -187,11 +187,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Size<DefinedLength> {
|
impl Size<DefiniteLength> {
|
||||||
pub const fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self {
|
Self {
|
||||||
width: DefinedLength::Pixels(0.),
|
width: pixels(0.),
|
||||||
height: DefinedLength::Pixels(0.),
|
height: pixels(0.),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ impl Size<DefinedLength> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Size<Length> {
|
impl Size<Length> {
|
||||||
pub const fn auto() -> Self {
|
pub fn auto() -> Self {
|
||||||
Self {
|
Self {
|
||||||
width: Length::Auto,
|
width: Length::Auto,
|
||||||
height: Length::Auto,
|
height: Length::Auto,
|
||||||
|
@ -230,13 +230,13 @@ pub struct Edges<T: Clone + Default> {
|
||||||
pub left: T,
|
pub left: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Edges<DefinedLength> {
|
impl Edges<DefiniteLength> {
|
||||||
pub const fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self {
|
Self {
|
||||||
top: DefinedLength::Pixels(0.0),
|
top: pixels(0.),
|
||||||
right: DefinedLength::Pixels(0.0),
|
right: pixels(0.),
|
||||||
bottom: DefinedLength::Pixels(0.0),
|
bottom: pixels(0.),
|
||||||
left: DefinedLength::Pixels(0.0),
|
left: pixels(0.),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +251,7 @@ impl Edges<DefinedLength> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Edges<Length> {
|
impl Edges<Length> {
|
||||||
pub const fn auto() -> Self {
|
pub fn auto() -> Self {
|
||||||
Self {
|
Self {
|
||||||
top: Length::Auto,
|
top: Length::Auto,
|
||||||
right: Length::Auto,
|
right: Length::Auto,
|
||||||
|
@ -260,12 +260,12 @@ impl Edges<Length> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self {
|
Self {
|
||||||
top: Length::Defined(DefinedLength::Pixels(0.0)),
|
top: pixels(0.),
|
||||||
right: Length::Defined(DefinedLength::Pixels(0.0)),
|
right: pixels(0.),
|
||||||
bottom: Length::Defined(DefinedLength::Pixels(0.0)),
|
bottom: pixels(0.),
|
||||||
left: Length::Defined(DefinedLength::Pixels(0.0)),
|
left: pixels(0.),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,72 +282,108 @@ impl Edges<Length> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A non-auto length that can be defined in pixels, rems, or percent of parent.
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum DefinedLength {
|
pub enum AbsoluteLength {
|
||||||
Pixels(f32),
|
Pixels(f32),
|
||||||
Rems(f32),
|
Rems(f32),
|
||||||
Percent(f32), // 0. - 100.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefinedLength {
|
impl AbsoluteLength {
|
||||||
|
pub fn to_pixels(&self, rem_size: f32) -> f32 {
|
||||||
|
match self {
|
||||||
|
AbsoluteLength::Pixels(pixels) => *pixels,
|
||||||
|
AbsoluteLength::Rems(rems) => rems * rem_size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AbsoluteLength {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Pixels(0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A non-auto length that can be defined in pixels, rems, or percent of parent.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum DefiniteLength {
|
||||||
|
Absolute(AbsoluteLength),
|
||||||
|
Relative(f32), // Percent, from 0 to 100.
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefiniteLength {
|
||||||
fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
|
fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
|
||||||
match self {
|
match self {
|
||||||
DefinedLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
|
DefiniteLength::Absolute(length) => match length {
|
||||||
DefinedLength::Rems(rems) => taffy::style::LengthPercentage::Length(rems * rem_size),
|
AbsoluteLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
|
||||||
DefinedLength::Percent(percent) => {
|
AbsoluteLength::Rems(rems) => {
|
||||||
taffy::style::LengthPercentage::Percent(*percent / 100.)
|
taffy::style::LengthPercentage::Length(rems * rem_size)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DefiniteLength::Relative(fraction) => {
|
||||||
|
taffy::style::LengthPercentage::Percent(*fraction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for DefinedLength {
|
impl From<AbsoluteLength> for DefiniteLength {
|
||||||
|
fn from(length: AbsoluteLength) -> Self {
|
||||||
|
Self::Absolute(length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DefiniteLength {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Pixels(0.)
|
Self::Absolute(AbsoluteLength::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A length that can be defined in pixels, rems, percent of parent, or auto.
|
/// A length that can be defined in pixels, rems, percent of parent, or auto.
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Length {
|
pub enum Length {
|
||||||
Defined(DefinedLength),
|
Definite(DefiniteLength),
|
||||||
Auto,
|
Auto,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn relative<T: From<DefiniteLength>>(fraction: f32) -> T {
|
||||||
|
DefiniteLength::Relative(fraction).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rems<T: From<AbsoluteLength>>(rems: f32) -> T {
|
||||||
|
AbsoluteLength::Rems(rems).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pixels<T: From<AbsoluteLength>>(pixels: f32) -> T {
|
||||||
|
AbsoluteLength::Pixels(pixels).into()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn auto() -> Length {
|
pub fn auto() -> Length {
|
||||||
Length::Auto
|
Length::Auto
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn percent(percent: f32) -> DefinedLength {
|
|
||||||
DefinedLength::Percent(percent)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rems(rems: f32) -> DefinedLength {
|
|
||||||
DefinedLength::Rems(rems)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pixels(pixels: f32) -> DefinedLength {
|
|
||||||
DefinedLength::Pixels(pixels)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Length {
|
impl Length {
|
||||||
pub fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto {
|
pub fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto {
|
||||||
match self {
|
match self {
|
||||||
Length::Defined(length) => length.to_taffy(rem_size).into(),
|
Length::Definite(length) => length.to_taffy(rem_size).into(),
|
||||||
Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
|
Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DefinedLength> for Length {
|
impl From<DefiniteLength> for Length {
|
||||||
fn from(value: DefinedLength) -> Self {
|
fn from(length: DefiniteLength) -> Self {
|
||||||
Length::Defined(value)
|
Self::Definite(length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AbsoluteLength> for Length {
|
||||||
|
fn from(length: AbsoluteLength) -> Self {
|
||||||
|
Self::Definite(length.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Length {
|
impl Default for Length {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::Defined(DefinedLength::default())
|
Self::Definite(DefiniteLength::default())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue