Compiling checkpoint

This commit is contained in:
Nathan Sobo 2023-08-13 21:20:41 -06:00
parent be7a43c81c
commit 2d17e9685f
11 changed files with 375 additions and 345 deletions

View File

@ -0,0 +1,64 @@
use util::ResultExt;
use crate::element::AnyElement;
struct Adapter<V>(AnyElement<V>);
impl<V: 'static> gpui::Element<V> for Adapter<V> {
type LayoutState = ();
type PaintState = ();
fn layout(
&mut self,
constraint: gpui::SizeConstraint,
view: &mut V,
cx: &mut gpui::LayoutContext<V>,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
cx.push_layout_engine();
if let Some(node) = self.0.layout(view, cx).log_err() {
cx.layout_engine()
.unwrap()
.compute_layout(node, constraint.max)
.log_err();
}
cx.pop_layout_engine();
(constraint.max, ())
}
fn paint(
&mut self,
scene: &mut gpui::SceneBuilder,
bounds: gpui::geometry::rect::RectF,
visible_bounds: gpui::geometry::rect::RectF,
layout: &mut Self::LayoutState,
view: &mut V,
cx: &mut gpui::PaintContext<V>,
) -> Self::PaintState {
todo!()
}
fn rect_for_text_range(
&self,
range_utf16: std::ops::Range<usize>,
bounds: gpui::geometry::rect::RectF,
visible_bounds: gpui::geometry::rect::RectF,
layout: &Self::LayoutState,
paint: &Self::PaintState,
view: &V,
cx: &gpui::ViewContext<V>,
) -> Option<gpui::geometry::rect::RectF> {
todo!()
}
fn debug(
&self,
bounds: gpui::geometry::rect::RectF,
layout: &Self::LayoutState,
paint: &Self::PaintState,
view: &V,
cx: &gpui::ViewContext<V>,
) -> gpui::serde_json::Value {
todo!()
}
}

View File

@ -1,151 +0,0 @@
use gpui::{AnyElement, Element, LayoutContext, View, ViewContext};
#[derive(Element, Clone, Default)]
pub struct Playground<V>(PhantomData<V>);
// example layout design here: https://www.figma.com/file/5QLTmxjO0xQpDD3CD4hR6T/Untitled?type=design&node-id=0%3A1&mode=design&t=SoJieVVIvDDDKagv-1
impl<V> Playground<V> {
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> impl Element<V> {
col() // fullscreen container with header and main in it
.width(flex(1.))
.height(flex(1.))
.fill(colors(gray.900))
.children([
row() // header container
.fill(colors(gray.900))
.width(flex(1.))
.children([
row() // tab bar
.width(flex(1.))
.gap(spacing(2))
.padding(spacing(3))
.overflow_x(scroll())
.chidren([
row() // tab
.padding_x(spacing(3))
.padding_y(spacing(2))
.corner_radius(6.)
.gap(spacing(3))
.align(center())
.fill(colors(gray.800))
.children([text("Tab title 1"), svg("icon_name")]),
row() // tab
.padding_x(spacing(3))
.padding_y(spacing(2))
.corner_radius(6.)
.gap(spacing(3))
.align(center())
.fill(colors(gray.800))
.children([text("Tab title 2"), svg("icon_name")]),
row() // tab
.padding_x(spacing(3))
.padding_y(spacing(2))
.corner_radius(6.)
.gap(spacing(3))
.align(center())
.fill(colors(gray.800))
.children([text("Tab title 3"), svg("icon_name")]),
]),
row() // tab bar actions
.border_left(colors(gray.700))
.gap(spacing(2))
.padding(spacing(3))
.chidren([
row()
.width(spacing(8))
.height(spacing(8))
.corner_radius(6.)
.justify(center())
.align(center())
.fill(colors(gray.800))
.child(svg(icon_name)),
row()
.width(spacing(8))
.height(spacing(8))
.corner_radius(6.)
.justify(center())
.align(center())
.fill(colors(gray.800))
.child(svg(icon_name)),
row()
.width(spacing(8))
.height(spacing(8))
.corner_radius(6.)
.justify(center())
.align(center())
.fill(colors(gray.800))
.child(svg(icon_name)),
]),
]),
row() // main container
.width(flex(1.))
.height(flex(1.))
.children([
col() // left sidebar
.fill(colors(gray.800))
.border_right(colors(gray.700))
.height(flex(1.))
.width(260.)
.children([
col() // containter to hold list items and notification alert box
.justify(between())
.padding_x(spacing(6))
.padding_bottom(3)
.padding_top(spacing(6))
.children([
col().gap(spacing(3)).children([ // sidebar list
text("Item"),
text("Item"),
text("Item"),
text("Item"),
text("Item"),
text("Item"),
text("Item"),
text("Item"),
]),
col().align(center()).gap(spacing(1)).children([ // notification alert box
text("Title text").size("lg"),
text("Description text goes here")
.text_color(colors(rose.200)),
]),
]),
row()
.padding_x(spacing(3))
.padding_y(spacing(2))
.border_top(1., colors(gray.700))
.align(center())
.gap(spacing(2))
.fill(colors(gray.900))
.children([
row() // avatar container
.width(spacing(8))
.height(spacing(8))
.corner_radius(spacing(8))
.justify(center())
.align(center())
.child(image(image_url)),
text("FirstName Lastname"), // user name
]),
]),
col() // primary content container
.align(center())
.justify(center())
.child(
col().justify(center()).gap(spacing(8)).children([ // detail container wrapper for center positioning
col() // blue rectangle
.width(rem(30.))
.height(rem(20.))
.corner_radius(16.)
.fill(colors(blue.200)),
col().gap(spacing(1)).children([ // center content text items
text("This is a title").size("lg"),
text("This is a description").text_color(colors(gray.500)),
]),
]),
),
col(), // right sidebar
]),
])
}
}

View File

@ -1,12 +1,25 @@
use crate::style::{Display, Length, Overflow, Position, Style}; use crate::style::{DefinedLength, Display, Overflow, Position, Style};
use gpui::{LayoutContext, PaintContext}; use anyhow::Result;
use gpui::{Layout, LayoutContext, PaintContext};
use playground_macros::tailwind_lengths; use playground_macros::tailwind_lengths;
pub use taffy::tree::{Layout, NodeId}; pub use taffy::tree::NodeId;
pub trait Element<V> { pub trait Element<V> {
fn style_mut(&mut self) -> &mut Style; fn style_mut(&mut self) -> &mut Style;
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> NodeId; fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<NodeId>;
fn paint(&mut self, layout: &Layout, view: &mut V, cx: &mut gpui::PaintContext<V>); fn paint(&mut self, layout: Layout, view: &mut V, cx: &mut gpui::PaintContext<V>)
-> Result<()>;
/// Convert to a dynamically-typed element suitable for layout and paint.
fn into_any(self) -> AnyElement<V>
where
Self: 'static + Sized,
{
AnyElement {
element: Box::new(self) as Box<dyn Element<V>>,
layout_node_id: None,
}
}
// Display //////////////////// // Display ////////////////////
@ -131,7 +144,7 @@ pub trait Element<V> {
} }
#[tailwind_lengths] #[tailwind_lengths]
fn inset(mut self, length: Length) -> Self fn inset(mut self, length: DefinedLength) -> Self
where where
Self: Sized, Self: Sized,
{ {
@ -143,7 +156,7 @@ pub trait Element<V> {
} }
#[tailwind_lengths] #[tailwind_lengths]
fn w(mut self, length: Length) -> Self fn w(mut self, length: DefinedLength) -> Self
where where
Self: Sized, Self: Sized,
{ {
@ -152,7 +165,7 @@ pub trait Element<V> {
} }
#[tailwind_lengths] #[tailwind_lengths]
fn min_w(mut self, length: Length) -> Self fn min_w(mut self, length: DefinedLength) -> Self
where where
Self: Sized, Self: Sized,
{ {
@ -161,7 +174,7 @@ pub trait Element<V> {
} }
#[tailwind_lengths] #[tailwind_lengths]
fn h(mut self, length: Length) -> Self fn h(mut self, length: DefinedLength) -> Self
where where
Self: Sized, Self: Sized,
{ {
@ -176,15 +189,19 @@ pub struct AnyElement<V> {
} }
impl<V> AnyElement<V> { impl<V> AnyElement<V> {
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> NodeId { pub fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>) -> Result<NodeId> {
let layout_node_id = self.element.layout(view, cx); let layout_node_id = self.element.layout(view, cx)?;
self.layout_node_id = Some(layout_node_id); self.layout_node_id = Some(layout_node_id);
layout_node_id Ok(layout_node_id)
} }
fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>) { pub fn paint(&mut self, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
let layout_node_id = self.layout_node_id.expect("paint called before layout"); let layout_node_id = self.layout_node_id.expect("paint called before layout");
let layout = cx.layout_engine().layout(layout_node_id).unwrap().clone(); let layout = cx
self.element.paint(&layout, view, 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)
} }
} }

View File

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

View File

@ -1,52 +1,94 @@
#![allow(dead_code, unused_variables)] #![allow(dead_code, unused_variables)]
use element::{AnyElement, Element};
use gpui::{elements::Empty, Element}; use frame::frame;
use log::LevelFilter; use log::LevelFilter;
use simplelog::SimpleLogger; use simplelog::SimpleLogger;
use taffy::tree::NodeId;
fn main() { 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.platform().activate(true); cx.platform().activate(true);
// cx.add_window( // cx.add_window(
// WindowOptions { // Default::default(),
// titlebar: Some(TitlebarOptions { // // |_| view(|_| Playground::new()),
// appears_transparent: true,
// ..Default::default()
// }),
// ..Default::default()
// },
// |_| view(|_| Playground::new()),
// ); // );
}); });
} }
use std::marker::PhantomData; use themes::{rose_pine, ThemeColors};
use themes::ThemeColors;
mod adapter;
mod color; mod color;
mod element; mod element;
mod frame; mod frame;
mod style; mod style;
mod themes; mod themes;
mod tokens;
#[derive(Element, Clone)] pub struct Playground<V: 'static>(AnyElement<V>);
pub struct Playground<V: 'static>(PhantomData<V>);
impl<V> Playground<V> { impl<V: 'static> gpui::Element<V> for Playground<V> {
pub fn new() -> Self { type LayoutState = NodeId;
Self(PhantomData)
type PaintState = ();
fn layout(
&mut self,
constraint: gpui::SizeConstraint,
view: &mut V,
cx: &mut gpui::LayoutContext<V>,
) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
todo!()
} }
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> impl Element<V> { fn paint(
Empty::new() &mut self,
// workspace(&rose_pine::dawn()) scene: &mut gpui::SceneBuilder,
bounds: gpui::geometry::rect::RectF,
visible_bounds: gpui::geometry::rect::RectF,
layout: &mut Self::LayoutState,
view: &mut V,
cx: &mut gpui::PaintContext<V>,
) -> Self::PaintState {
todo!()
}
fn rect_for_text_range(
&self,
range_utf16: std::ops::Range<usize>,
bounds: gpui::geometry::rect::RectF,
visible_bounds: gpui::geometry::rect::RectF,
layout: &Self::LayoutState,
paint: &Self::PaintState,
view: &V,
cx: &gpui::ViewContext<V>,
) -> Option<gpui::geometry::rect::RectF> {
todo!()
}
fn debug(
&self,
bounds: gpui::geometry::rect::RectF,
layout: &Self::LayoutState,
paint: &Self::PaintState,
view: &V,
cx: &gpui::ViewContext<V>,
) -> gpui::serde_json::Value {
todo!()
} }
} }
// fn workspace<V: 'static>(theme: &ThemeColors) -> impl Element<V> { impl<V> Playground<V> {
pub fn new() -> Self {
Self(workspace(&rose_pine::moon()).into_any())
}
}
fn workspace<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
frame()
}
// todo!() // todo!()
// // column() // // column()
// // .size(auto()) // // .size(auto())

View File

@ -19,25 +19,25 @@ pub struct Style {
/// What should the `position` value of this struct use as a base offset? /// What should the `position` value of this struct use as a base offset?
pub position: Position, pub position: Position,
/// How should the position of this element be tweaked relative to the layout defined? /// How should the position of this element be tweaked relative to the layout defined?
pub inset: Edges<LengthOrAuto>, pub inset: Edges<Length>,
// Size properies // Size properies
/// Sets the initial size of the item /// Sets the initial size of the item
pub size: Size<LengthOrAuto>, pub size: Size<Length>,
/// Controls the minimum size of the item /// Controls the minimum size of the item
pub min_size: Size<LengthOrAuto>, pub min_size: Size<Length>,
/// Controls the maximum size of the item /// Controls the maximum size of the item
pub max_size: Size<LengthOrAuto>, pub max_size: Size<Length>,
/// Sets the preferred aspect ratio for the item. The ratio is calculated as width divided by height. /// Sets the preferred aspect ratio for the item. The ratio is calculated as width divided by height.
pub aspect_ratio: Option<f32>, pub aspect_ratio: Option<f32>,
// Spacing Properties // Spacing Properties
/// How large should the margin be on each side? /// How large should the margin be on each side?
pub margin: Edges<LengthOrAuto>, pub margin: Edges<Length>,
/// How large should the padding be on each side? /// How large should the padding be on each side?
pub padding: Edges<Length>, pub padding: Edges<DefinedLength>,
/// How large should the border be on each side? /// How large should the border be on each side?
pub border: Edges<Length>, pub border: Edges<DefinedLength>,
// 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?
@ -49,7 +49,7 @@ pub struct Style {
/// How should contained within this item be aligned in the main/inline axis /// How should contained within this item be aligned in the main/inline axis
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?
pub gap: Size<Length>, pub gap: Size<DefinedLength>,
// Flexbox properies // Flexbox properies
/// Which direction does the main axis flow in? /// Which direction does the main axis flow in?
@ -57,7 +57,7 @@ pub struct Style {
/// Should elements wrap, or stay in a single line? /// Should elements wrap, or stay in a single line?
pub flex_wrap: FlexWrap, pub flex_wrap: FlexWrap,
/// Sets the initial main axis size of the item /// Sets the initial main axis size of the item
pub flex_basis: LengthOrAuto, pub flex_basis: Length,
/// The relative rate at which this item grows when it is expanding to fill space, 0.0 is the default value, and this value must be positive. /// The relative rate at which this item grows when it is expanding to fill space, 0.0 is the default value, and this value must be positive.
pub flex_grow: f32, 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. /// 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.
@ -77,9 +77,9 @@ impl Style {
scrollbar_width: 0.0, scrollbar_width: 0.0,
position: Position::Relative, position: Position::Relative,
inset: Edges::auto(), inset: Edges::auto(),
margin: Edges::<LengthOrAuto>::zero(), margin: Edges::<Length>::zero(),
padding: Edges::<Length>::zero(), padding: Edges::<DefinedLength>::zero(),
border: Edges::<Length>::zero(), border: Edges::<DefinedLength>::zero(),
size: Size::auto(), size: Size::auto(),
min_size: Size::auto(), min_size: Size::auto(),
max_size: Size::auto(), max_size: Size::auto(),
@ -95,7 +95,7 @@ impl Style {
flex_wrap: FlexWrap::NoWrap, flex_wrap: FlexWrap::NoWrap,
flex_grow: 0.0, flex_grow: 0.0,
flex_shrink: 1.0, flex_shrink: 1.0,
flex_basis: LengthOrAuto::Auto, flex_basis: Length::Auto,
fill: Fill::Color(Hsla { fill: Fill::Color(Hsla {
h: 0., h: 0.,
s: 0., s: 0.,
@ -137,6 +137,12 @@ impl Style {
} }
} }
impl Default for Style {
fn default() -> Self {
Self::DEFAULT.clone()
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct Point<T> { pub struct Point<T> {
pub x: T, pub x: T,
@ -158,11 +164,11 @@ pub struct Size<T> {
pub height: T, pub height: T,
} }
impl Size<Length> { impl Size<DefinedLength> {
pub const fn zero() -> Self { pub const fn zero() -> Self {
Self { Self {
width: Length::Pixels(0.), width: DefinedLength::Pixels(0.),
height: Length::Pixels(0.), height: DefinedLength::Pixels(0.),
} }
} }
@ -174,11 +180,11 @@ impl Size<Length> {
} }
} }
impl Size<LengthOrAuto> { impl Size<Length> {
pub const fn auto() -> Self { pub const fn auto() -> Self {
Self { Self {
width: LengthOrAuto::Auto, width: Length::Auto,
height: LengthOrAuto::Auto, height: Length::Auto,
} }
} }
@ -201,13 +207,13 @@ pub struct Edges<T> {
pub left: T, pub left: T,
} }
impl Edges<Length> { impl Edges<DefinedLength> {
pub const fn zero() -> Self { pub const fn zero() -> Self {
Self { Self {
top: Length::Pixels(0.0), top: DefinedLength::Pixels(0.0),
right: Length::Pixels(0.0), right: DefinedLength::Pixels(0.0),
bottom: Length::Pixels(0.0), bottom: DefinedLength::Pixels(0.0),
left: Length::Pixels(0.0), left: DefinedLength::Pixels(0.0),
} }
} }
@ -221,22 +227,22 @@ impl Edges<Length> {
} }
} }
impl Edges<LengthOrAuto> { impl Edges<Length> {
pub const fn auto() -> Self { pub const fn auto() -> Self {
Self { Self {
top: LengthOrAuto::Auto, top: Length::Auto,
right: LengthOrAuto::Auto, right: Length::Auto,
bottom: LengthOrAuto::Auto, bottom: Length::Auto,
left: LengthOrAuto::Auto, left: Length::Auto,
} }
} }
pub const fn zero() -> Self { pub const fn zero() -> Self {
Self { Self {
top: LengthOrAuto::Length(Length::Pixels(0.0)), top: Length::Length(DefinedLength::Pixels(0.0)),
right: LengthOrAuto::Length(Length::Pixels(0.0)), right: Length::Length(DefinedLength::Pixels(0.0)),
bottom: LengthOrAuto::Length(Length::Pixels(0.0)), bottom: Length::Length(DefinedLength::Pixels(0.0)),
left: LengthOrAuto::Length(Length::Pixels(0.0)), left: Length::Length(DefinedLength::Pixels(0.0)),
} }
} }
@ -253,41 +259,43 @@ impl Edges<LengthOrAuto> {
} }
} }
/// A non-auto length that can be defined in pixels, rems, or percent of parent.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum Length { pub enum DefinedLength {
Pixels(f32), Pixels(f32),
Rems(f32), Rems(f32),
Percent(f32), // 0. - 100. Percent(f32), // 0. - 100.
} }
impl Length { impl DefinedLength {
fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage { fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
match self { match self {
Length::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels), DefinedLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
Length::Rems(rems) => taffy::style::LengthPercentage::Length(rems * rem_size), DefinedLength::Rems(rems) => taffy::style::LengthPercentage::Length(rems * rem_size),
Length::Percent(percent) => taffy::style::LengthPercentage::Percent(*percent), DefinedLength::Percent(percent) => taffy::style::LengthPercentage::Percent(*percent),
} }
} }
} }
/// A length that can be defined in pixels, rems, percent of parent, or auto.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum LengthOrAuto { pub enum Length {
Length(Length), Length(DefinedLength),
Auto, Auto,
} }
impl LengthOrAuto { impl Length {
fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto { fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto {
match self { match self {
LengthOrAuto::Length(length) => length.to_taffy(rem_size).into(), Length::Length(length) => length.to_taffy(rem_size).into(),
LengthOrAuto::Auto => taffy::prelude::LengthPercentageAuto::Auto, Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
} }
} }
} }
impl From<Length> for LengthOrAuto { impl From<DefinedLength> for Length {
fn from(value: Length) -> Self { fn from(value: DefinedLength) -> Self {
LengthOrAuto::Length(value) Length::Length(value)
} }
} }

View File

@ -1,6 +1,5 @@
use crate::color::{Hsla, Lerp}; use crate::color::{Hsla, Lerp};
use serde::{Deserialize, Serialize}; use std::ops::Range;
use std::{ops::Range, sync::Arc};
pub mod rose_pine; pub mod rose_pine;
@ -83,24 +82,3 @@ impl ThemeColors {
self.modified.lerp(level) self.modified.lerp(level)
} }
} }
#[derive(Serialize, Deserialize)]
struct Entity {
class: String,
#[serde(rename = "type")]
kind: String,
id: Arc<str>,
name: String,
value: String,
description: String,
category_id: String,
last_updated_by: String,
last_updated: String,
tags: Vec<String>,
}
#[derive(Serialize, Deserialize)]
struct Category {
id: String,
label: String,
}

View File

@ -1,10 +0,0 @@
pub mod color {
use crate::color::{scale, ColorScale, Hsla};
pub fn ramp(color: impl Into<Hsla>) -> ColorScale {
let color = color.into();
let end_color = color.desaturate(0.1).brighten(0.5);
let start_color = color.desaturate(0.1).darken(0.4);
scale([start_color, color, end_color])
}
}

View File

@ -34,67 +34,67 @@ pub fn tailwind_lengths(_attr: TokenStream, item: TokenStream) -> TokenStream {
fn fixed_lengths() -> Vec<(&'static str, TokenStream2)> { fn fixed_lengths() -> Vec<(&'static str, TokenStream2)> {
vec![ vec![
("0", quote! { Length::Pixels(0.) }), ("0", quote! { DefinedLength::Pixels(0.) }),
("px", quote! { Length::Pixels(1.) }), ("px", quote! { DefinedLength::Pixels(1.) }),
("0_5", quote! { Length::Rems(0.125) }), ("0_5", quote! { DefinedLength::Rems(0.125) }),
("1", quote! { Length::Rems(0.25) }), ("1", quote! { DefinedLength::Rems(0.25) }),
("1_5", quote! { Length::Rems(0.375) }), ("1_5", quote! { DefinedLength::Rems(0.375) }),
("2", quote! { Length::Rems(0.5) }), ("2", quote! { DefinedLength::Rems(0.5) }),
("2_5", quote! { Length::Rems(0.625) }), ("2_5", quote! { DefinedLength::Rems(0.625) }),
("3", quote! { Length::Rems(0.75) }), ("3", quote! { DefinedLength::Rems(0.75) }),
("3_5", quote! { Length::Rems(0.875) }), ("3_5", quote! { DefinedLength::Rems(0.875) }),
("4", quote! { Length::Rems(1.) }), ("4", quote! { DefinedLength::Rems(1.) }),
("5", quote! { Length::Rems(1.25) }), ("5", quote! { DefinedLength::Rems(1.25) }),
("6", quote! { Length::Rems(1.5) }), ("6", quote! { DefinedLength::Rems(1.5) }),
("7", quote! { Length::Rems(1.75) }), ("7", quote! { DefinedLength::Rems(1.75) }),
("8", quote! { Length::Rems(2.) }), ("8", quote! { DefinedLength::Rems(2.) }),
("9", quote! { Length::Rems(2.25) }), ("9", quote! { DefinedLength::Rems(2.25) }),
("10", quote! { Length::Rems(2.5) }), ("10", quote! { DefinedLength::Rems(2.5) }),
("11", quote! { Length::Rems(2.75) }), ("11", quote! { DefinedLength::Rems(2.75) }),
("12", quote! { Length::Rems(3.) }), ("12", quote! { DefinedLength::Rems(3.) }),
("14", quote! { Length::Rems(3.5) }), ("14", quote! { DefinedLength::Rems(3.5) }),
("16", quote! { Length::Rems(4.) }), ("16", quote! { DefinedLength::Rems(4.) }),
("20", quote! { Length::Rems(5.) }), ("20", quote! { DefinedLength::Rems(5.) }),
("24", quote! { Length::Rems(6.) }), ("24", quote! { DefinedLength::Rems(6.) }),
("28", quote! { Length::Rems(7.) }), ("28", quote! { DefinedLength::Rems(7.) }),
("32", quote! { Length::Rems(8.) }), ("32", quote! { DefinedLength::Rems(8.) }),
("36", quote! { Length::Rems(9.) }), ("36", quote! { DefinedLength::Rems(9.) }),
("40", quote! { Length::Rems(10.) }), ("40", quote! { DefinedLength::Rems(10.) }),
("44", quote! { Length::Rems(11.) }), ("44", quote! { DefinedLength::Rems(11.) }),
("48", quote! { Length::Rems(12.) }), ("48", quote! { DefinedLength::Rems(12.) }),
("52", quote! { Length::Rems(13.) }), ("52", quote! { DefinedLength::Rems(13.) }),
("56", quote! { Length::Rems(14.) }), ("56", quote! { DefinedLength::Rems(14.) }),
("60", quote! { Length::Rems(15.) }), ("60", quote! { DefinedLength::Rems(15.) }),
("64", quote! { Length::Rems(16.) }), ("64", quote! { DefinedLength::Rems(16.) }),
("72", quote! { Length::Rems(18.) }), ("72", quote! { DefinedLength::Rems(18.) }),
("80", quote! { Length::Rems(20.) }), ("80", quote! { DefinedLength::Rems(20.) }),
("96", quote! { Length::Rems(24.) }), ("96", quote! { DefinedLength::Rems(24.) }),
("half", quote! { Length::Percent(50.) }), ("half", quote! { DefinedLength::Percent(50.) }),
("1_3rd", quote! { Length::Percent(33.333333) }), ("1_3rd", quote! { DefinedLength::Percent(33.333333) }),
("2_3rd", quote! { Length::Percent(66.666667) }), ("2_3rd", quote! { DefinedLength::Percent(66.666667) }),
("1_4th", quote! { Length::Percent(25.) }), ("1_4th", quote! { DefinedLength::Percent(25.) }),
("2_4th", quote! { Length::Percent(50.) }), ("2_4th", quote! { DefinedLength::Percent(50.) }),
("3_4th", quote! { Length::Percent(75.) }), ("3_4th", quote! { DefinedLength::Percent(75.) }),
("1_5th", quote! { Length::Percent(20.) }), ("1_5th", quote! { DefinedLength::Percent(20.) }),
("2_5th", quote! { Length::Percent(40.) }), ("2_5th", quote! { DefinedLength::Percent(40.) }),
("3_5th", quote! { Length::Percent(60.) }), ("3_5th", quote! { DefinedLength::Percent(60.) }),
("4_5th", quote! { Length::Percent(80.) }), ("4_5th", quote! { DefinedLength::Percent(80.) }),
("1_6th", quote! { Length::Percent(16.666667) }), ("1_6th", quote! { DefinedLength::Percent(16.666667) }),
("2_6th", quote! { Length::Percent(33.333333) }), ("2_6th", quote! { DefinedLength::Percent(33.333333) }),
("3_6th", quote! { Length::Percent(50.) }), ("3_6th", quote! { DefinedLength::Percent(50.) }),
("4_6th", quote! { Length::Percent(66.666667) }), ("4_6th", quote! { DefinedLength::Percent(66.666667) }),
("5_6th", quote! { Length::Percent(83.333333) }), ("5_6th", quote! { DefinedLength::Percent(83.333333) }),
("1_12th", quote! { Length::Percent(8.333333) }), ("1_12th", quote! { DefinedLength::Percent(8.333333) }),
("2_12th", quote! { Length::Percent(16.666667) }), ("2_12th", quote! { DefinedLength::Percent(16.666667) }),
("3_12th", quote! { Length::Percent(25.) }), ("3_12th", quote! { DefinedLength::Percent(25.) }),
("4_12th", quote! { Length::Percent(33.333333) }), ("4_12th", quote! { DefinedLength::Percent(33.333333) }),
("5_12th", quote! { Length::Percent(41.666667) }), ("5_12th", quote! { DefinedLength::Percent(41.666667) }),
("6_12th", quote! { Length::Percent(50.) }), ("6_12th", quote! { DefinedLength::Percent(50.) }),
("7_12th", quote! { Length::Percent(58.333333) }), ("7_12th", quote! { DefinedLength::Percent(58.333333) }),
("8_12th", quote! { Length::Percent(66.666667) }), ("8_12th", quote! { DefinedLength::Percent(66.666667) }),
("9_12th", quote! { Length::Percent(75.) }), ("9_12th", quote! { DefinedLength::Percent(75.) }),
("10_12th", quote! { Length::Percent(83.333333) }), ("10_12th", quote! { DefinedLength::Percent(83.333333) }),
("11_12th", quote! { Length::Percent(91.666667) }), ("11_12th", quote! { DefinedLength::Percent(91.666667) }),
("full", quote! { Length::Percent(100.) }), ("full", quote! { DefinedLength::Percent(100.) }),
] ]
} }

View File

@ -40,7 +40,7 @@ use uuid::Uuid;
use super::{Reference, ViewMetadata}; use super::{Reference, ViewMetadata};
pub struct Window { pub struct Window {
layout_engine: Taffy, layout_engines: Vec<LayoutEngine>,
pub(crate) root_view: Option<AnyViewHandle>, pub(crate) root_view: Option<AnyViewHandle>,
pub(crate) focused_view_id: Option<usize>, pub(crate) focused_view_id: Option<usize>,
pub(crate) parents: HashMap<usize, usize>, pub(crate) parents: HashMap<usize, usize>,
@ -75,7 +75,7 @@ impl Window {
let titlebar_height = platform_window.titlebar_height(); let titlebar_height = platform_window.titlebar_height();
let appearance = platform_window.appearance(); let appearance = platform_window.appearance();
let mut window = Self { let mut window = Self {
layout_engine: Taffy::new(), layout_engines: Vec::new(),
root_view: None, root_view: None,
focused_view_id: None, focused_view_id: None,
parents: Default::default(), parents: Default::default(),
@ -210,8 +210,16 @@ impl<'a> WindowContext<'a> {
} }
} }
pub fn layout_engine(&mut self) -> &mut Taffy { pub fn layout_engine(&mut self) -> Option<&mut LayoutEngine> {
&mut self.window.layout_engine self.window.layout_engines.last_mut()
}
pub fn push_layout_engine(&mut self) {
self.window.layout_engines.push(LayoutEngine::new());
}
pub fn pop_layout_engine(&mut self) {
self.window.layout_engines.pop();
} }
pub fn remove_window(&mut self) { pub fn remove_window(&mut self) {
@ -1222,6 +1230,58 @@ impl<'a> WindowContext<'a> {
} }
} }
pub struct LayoutEngine(Taffy);
pub use taffy::style::Style as LayoutStyle;
impl LayoutEngine {
fn new() -> Self {
Self(Taffy::new())
}
pub fn add_node<C>(&mut self, style: LayoutStyle, children: C) -> Result<LayoutNodeId>
where
C: IntoIterator<Item = LayoutNodeId>,
{
Ok(self
.0
.new_with_children(style, &children.into_iter().collect::<Vec<_>>())?)
}
pub fn compute_layout(&mut self, root: LayoutNodeId, available_space: Vector2F) -> Result<()> {
self.0.compute_layout(
root,
taffy::geometry::Size {
width: available_space.x().into(),
height: available_space.y().into(),
},
)?;
Ok(())
}
pub fn computed_layout(&mut self, node: LayoutNodeId) -> Result<Layout> {
Ok(self.0.layout(node)?.into())
}
}
pub struct Layout {
pub bounds: RectF,
pub order: u32,
}
impl From<&taffy::tree::Layout> for Layout {
fn from(value: &taffy::tree::Layout) -> Self {
Self {
bounds: RectF::new(
vec2f(value.location.x, value.location.y),
vec2f(value.size.width, value.size.height),
),
order: value.order,
}
}
}
pub type LayoutNodeId = taffy::prelude::NodeId;
pub struct RenderParams { pub struct RenderParams {
pub view_id: usize, pub view_id: usize,
pub titlebar_height: f32, pub titlebar_height: f32,

View File

@ -27,7 +27,9 @@ pub mod json;
pub mod keymap_matcher; pub mod keymap_matcher;
pub mod platform; pub mod platform;
pub use gpui_macros::{test, Element}; pub use gpui_macros::{test, Element};
pub use window::{Axis, RectFExt, SizeConstraint, Vector2FExt, WindowContext}; pub use window::{
Axis, Layout, LayoutNodeId, RectFExt, SizeConstraint, Vector2FExt, WindowContext,
};
pub use anyhow; pub use anyhow;
pub use serde_json; pub use serde_json;