Get taffy style conversion working

This commit is contained in:
Nathan Sobo 2023-08-13 19:47:49 -06:00
parent 52ad48d50b
commit be7a43c81c
6 changed files with 343 additions and 109 deletions

View file

@ -47,7 +47,7 @@ serde_derive.workspace = true
serde_json.workspace = true
smallvec.workspace = true
smol.workspace = true
taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "dab541d6104d58e2e10ce90c4a1dad0b703160cd" }
taffy = { git = "https://github.com/DioxusLabs/taffy", rev = "dab541d6104d58e2e10ce90c4a1dad0b703160cd", features = ["flexbox"] }
time.workspace = true
tiny-skia = "0.5"
usvg = { version = "0.14", features = [] }

View file

@ -0,0 +1,190 @@
use crate::style::{Display, Length, Overflow, Position, Style};
use gpui::{LayoutContext, PaintContext};
use playground_macros::tailwind_lengths;
pub use taffy::tree::{Layout, NodeId};
pub trait Element<V> {
fn style_mut(&mut self) -> &mut Style;
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> NodeId;
fn paint(&mut self, layout: &Layout, view: &mut V, cx: &mut gpui::PaintContext<V>);
// Display ////////////////////
fn block(mut self) -> Self
where
Self: Sized,
{
self.style_mut().display = Display::Block;
self
}
fn flex(mut self) -> Self
where
Self: Sized,
{
self.style_mut().display = Display::Flex;
self
}
fn grid(mut self) -> Self
where
Self: Sized,
{
self.style_mut().display = Display::Grid;
self
}
// style::Overflow ///////////////////
fn overflow_visible(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.x = Overflow::Visible;
self.style_mut().overflow.y = Overflow::Visible;
self
}
fn overflow_hidden(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.x = Overflow::Hidden;
self.style_mut().overflow.y = Overflow::Hidden;
self
}
fn overflow_scroll(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.x = Overflow::Scroll;
self.style_mut().overflow.y = Overflow::Scroll;
self
}
fn overflow_x_visible(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.x = Overflow::Visible;
self
}
fn overflow_x_hidden(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.x = Overflow::Hidden;
self
}
fn overflow_x_scroll(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.x = Overflow::Scroll;
self
}
fn overflow_y_visible(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.y = Overflow::Visible;
self
}
fn overflow_y_hidden(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.y = Overflow::Hidden;
self
}
fn overflow_y_scroll(mut self) -> Self
where
Self: Sized,
{
self.style_mut().overflow.y = Overflow::Scroll;
self
}
// Position ///////////////////
fn relative(mut self) -> Self
where
Self: Sized,
{
self.style_mut().position = Position::Relative;
self
}
fn absolute(mut self) -> Self
where
Self: Sized,
{
self.style_mut().position = Position::Absolute;
self
}
#[tailwind_lengths]
fn inset(mut self, length: Length) -> Self
where
Self: Sized,
{
self.style_mut().inset.top = length;
self.style_mut().inset.right = length;
self.style_mut().inset.bottom = length;
self.style_mut().inset.left = length;
self
}
#[tailwind_lengths]
fn w(mut self, length: Length) -> Self
where
Self: Sized,
{
self.style_mut().size.width = length;
self
}
#[tailwind_lengths]
fn min_w(mut self, length: Length) -> Self
where
Self: Sized,
{
self.style_mut().size.width = length;
self
}
#[tailwind_lengths]
fn h(mut self, length: Length) -> Self
where
Self: Sized,
{
self.style_mut().size.height = length;
self
}
}
pub struct AnyElement<V> {
element: Box<dyn Element<V>>,
layout_node_id: Option<NodeId>,
}
impl<V> AnyElement<V> {
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> NodeId {
let layout_node_id = self.element.layout(view, cx);
self.layout_node_id = Some(layout_node_id);
layout_node_id
}
fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>) {
let layout_node_id = self.layout_node_id.expect("paint called before layout");
let layout = cx.layout_engine().layout(layout_node_id).unwrap().clone();
self.element.paint(&layout, view, cx);
}
}

View file

@ -1 +1,34 @@
use crate::{element::Element, style::Style};
pub struct Frame {
style: Style,
children: Vec<Frame>,
}
impl<V: 'static> Element<V> for Frame {
fn style_mut(&mut self) -> &mut Style {
&mut self.style
}
fn layout(&mut self, view: &mut V, cx: &mut gpui::LayoutContext<V>) -> taffy::tree::NodeId {
let child_layout_node_ids = self
.children
.iter_mut()
.map(|child| child.layout(view, cx))
.collect::<Vec<_>>();
let rem_size = cx.rem_pixels();
cx.layout_engine()
.new_with_children(self.style.to_taffy(rem_size), &child_layout_node_ids)
.unwrap()
}
fn paint(
&mut self,
layout: &taffy::tree::Layout,
view: &mut V,
cx: &mut gpui::PaintContext<V>,
) {
todo!()
}
}

View file

@ -26,6 +26,7 @@ use std::marker::PhantomData;
use themes::ThemeColors;
mod color;
mod element;
mod frame;
mod style;
mod themes;

View file

@ -1,5 +1,5 @@
use playground_macros::tailwind_lengths;
use taffy::style::{
use crate::color::Hsla;
pub use taffy::style::{
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,
Overflow, Position,
};
@ -62,6 +62,9 @@ pub struct Style {
pub flex_grow: f32,
/// The relative rate at which this item shrinks when it is contracting to fit into space, 1.0 is the default value, and this value must be positive.
pub flex_shrink: f32,
/// The fill color of this element
pub fill: Fill,
}
impl Style {
@ -93,117 +96,44 @@ impl Style {
flex_grow: 0.0,
flex_shrink: 1.0,
flex_basis: LengthOrAuto::Auto,
fill: Fill::Color(Hsla {
h: 0.,
s: 0.,
l: 0.,
a: 0.,
}),
};
pub fn new() -> Self {
Self::DEFAULT.clone()
}
// Display ////////////////////
fn block(mut self) -> Self {
self.display = Display::Block;
self
}
fn flex(mut self) -> Self {
self.display = Display::Flex;
self
}
fn grid(mut self) -> Self {
self.display = Display::Grid;
self
}
// Overflow ///////////////////
pub fn overflow_visible(mut self) -> Self {
self.overflow.x = Overflow::Visible;
self.overflow.y = Overflow::Visible;
self
}
pub fn overflow_hidden(mut self) -> Self {
self.overflow.x = Overflow::Hidden;
self.overflow.y = Overflow::Hidden;
self
}
pub fn overflow_scroll(mut self) -> Self {
self.overflow.x = Overflow::Scroll;
self.overflow.y = Overflow::Scroll;
self
}
pub fn overflow_x_visible(mut self) -> Self {
self.overflow.x = Overflow::Visible;
self
}
pub fn overflow_x_hidden(mut self) -> Self {
self.overflow.x = Overflow::Hidden;
self
}
pub fn overflow_x_scroll(mut self) -> Self {
self.overflow.x = Overflow::Scroll;
self
}
pub fn overflow_y_visible(mut self) -> Self {
self.overflow.y = Overflow::Visible;
self
}
pub fn overflow_y_hidden(mut self) -> Self {
self.overflow.y = Overflow::Hidden;
self
}
pub fn overflow_y_scroll(mut self) -> Self {
self.overflow.y = Overflow::Scroll;
self
}
// Position ///////////////////
pub fn relative(mut self) -> Self {
self.position = Position::Relative;
self
}
pub fn absolute(mut self) -> Self {
self.position = Position::Absolute;
self
}
#[tailwind_lengths]
pub fn inset(mut self, length: Length) -> Self {
self.inset.top = length;
self.inset.right = length;
self.inset.bottom = length;
self.inset.left = length;
self
}
#[tailwind_lengths]
pub fn w(mut self, length: Length) -> Self {
self.size.width = length;
self
}
#[tailwind_lengths]
pub fn min_w(mut self, length: Length) -> Self {
self.size.width = length;
self
}
#[tailwind_lengths]
pub fn h(mut self, length: Length) -> Self {
self.size.height = length;
self
pub fn to_taffy(&self, rem_size: f32) -> taffy::style::Style {
taffy::style::Style {
display: self.display,
overflow: self.overflow.clone().into(),
scrollbar_width: self.scrollbar_width,
position: self.position,
inset: self.inset.to_taffy(rem_size),
size: self.size.to_taffy(rem_size),
min_size: self.min_size.to_taffy(rem_size),
max_size: self.max_size.to_taffy(rem_size),
aspect_ratio: self.aspect_ratio,
margin: self.margin.to_taffy(rem_size),
padding: self.padding.to_taffy(rem_size),
border: self.border.to_taffy(rem_size),
align_items: self.align_items,
align_self: self.align_self,
align_content: self.align_content,
justify_content: self.justify_content,
gap: self.gap.to_taffy(rem_size),
flex_direction: self.flex_direction,
flex_wrap: self.flex_wrap,
flex_basis: self.flex_basis.to_taffy(rem_size).into(),
flex_grow: self.flex_grow,
flex_shrink: self.flex_shrink,
..Default::default() // Ignore grid properties for now
}
}
}
@ -213,6 +143,15 @@ pub struct Point<T> {
pub y: T,
}
impl<T> Into<taffy::geometry::Point<T>> for Point<T> {
fn into(self) -> taffy::geometry::Point<T> {
taffy::geometry::Point {
x: self.x,
y: self.y,
}
}
}
#[derive(Clone)]
pub struct Size<T> {
pub width: T,
@ -226,6 +165,13 @@ impl Size<Length> {
height: Length::Pixels(0.),
}
}
pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Size<taffy::style::LengthPercentage> {
taffy::geometry::Size {
width: self.width.to_taffy(rem_size),
height: self.height.to_taffy(rem_size),
}
}
}
impl Size<LengthOrAuto> {
@ -235,6 +181,16 @@ impl Size<LengthOrAuto> {
height: LengthOrAuto::Auto,
}
}
pub fn to_taffy<T: From<taffy::prelude::LengthPercentageAuto>>(
&self,
rem_size: f32,
) -> taffy::geometry::Size<T> {
taffy::geometry::Size {
width: self.width.to_taffy(rem_size).into(),
height: self.height.to_taffy(rem_size).into(),
}
}
}
#[derive(Clone)]
@ -254,6 +210,15 @@ impl Edges<Length> {
left: Length::Pixels(0.0),
}
}
pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Rect<taffy::style::LengthPercentage> {
taffy::geometry::Rect {
top: self.top.to_taffy(rem_size),
right: self.right.to_taffy(rem_size),
bottom: self.bottom.to_taffy(rem_size),
left: self.left.to_taffy(rem_size),
}
}
}
impl Edges<LengthOrAuto> {
@ -274,6 +239,18 @@ impl Edges<LengthOrAuto> {
left: LengthOrAuto::Length(Length::Pixels(0.0)),
}
}
pub fn to_taffy(
&self,
rem_size: f32,
) -> taffy::geometry::Rect<taffy::style::LengthPercentageAuto> {
taffy::geometry::Rect {
top: self.top.to_taffy(rem_size),
right: self.right.to_taffy(rem_size),
bottom: self.bottom.to_taffy(rem_size),
left: self.left.to_taffy(rem_size),
}
}
}
#[derive(Clone, Copy)]
@ -283,14 +260,44 @@ pub enum Length {
Percent(f32), // 0. - 100.
}
impl Length {
fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
match self {
Length::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
Length::Rems(rems) => taffy::style::LengthPercentage::Length(rems * rem_size),
Length::Percent(percent) => taffy::style::LengthPercentage::Percent(*percent),
}
}
}
#[derive(Clone, Copy)]
pub enum LengthOrAuto {
Length(Length),
Auto,
}
impl LengthOrAuto {
fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto {
match self {
LengthOrAuto::Length(length) => length.to_taffy(rem_size).into(),
LengthOrAuto::Auto => taffy::prelude::LengthPercentageAuto::Auto,
}
}
}
impl From<Length> for LengthOrAuto {
fn from(value: Length) -> Self {
LengthOrAuto::Length(value)
}
}
#[derive(Clone)]
pub enum Fill {
Color(Hsla),
}
impl Default for Fill {
fn default() -> Self {
Self::Color(Hsla::default())
}
}

View file

@ -6,8 +6,11 @@ use syn::{parse_macro_input, FnArg, ItemFn, PatType};
#[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,
@ -19,7 +22,7 @@ pub fn tailwind_lengths(_attr: TokenStream, item: TokenStream) -> TokenStream {
for (length, value) in fixed_lengths() {
let function_name = format_ident!("{}_{}", function_signature.ident, length);
output_functions.extend(quote! {
pub fn #function_name(mut self) -> Self {
#visibility fn #function_name(mut self) -> Self #where_clause {
let #argument_name = #value.into();
#function_body
}