Checkpoint

Nathan Sobo created

Change summary

crates/storybook/src/gpui3/geometry.rs |  20 ++-
crates/storybook/src/gpui3/mod.rs      |   7 +
crates/storybook/src/gpui3/style.rs    | 106 +++++------------------
crates/storybook/src/gpui3/taffy.rs    | 120 ++++++++++++++++++++-------
crates/util/src/arc_cow.rs             |  14 +++
5 files changed, 144 insertions(+), 123 deletions(-)

Detailed changes

crates/storybook/src/gpui3/geometry.rs 🔗

@@ -4,12 +4,13 @@ use refineable::Refineable;
 use std::ops::Mul;
 
 #[derive(Refineable, Default, Add, AddAssign, Sub, Mul, Div, Copy, Debug, PartialEq, Eq, Hash)]
-pub struct Point<T: Clone> {
+#[refineable(debug)]
+pub struct Point<T: Clone + Debug> {
     pub x: T,
     pub y: T,
 }
 
-impl<T: Clone> Clone for Point<T> {
+impl<T: Clone + Debug> Clone for Point<T> {
     fn clone(&self) -> Self {
         Self {
             x: self.x.clone(),
@@ -18,8 +19,9 @@ impl<T: Clone> Clone for Point<T> {
     }
 }
 
-#[derive(Default, Clone, Refineable, Debug)]
-pub struct Size<T: Clone> {
+#[derive(Refineable, Default, Clone, Debug)]
+#[refineable(debug)]
+pub struct Size<T: Clone + Debug> {
     pub width: T,
     pub height: T,
 }
@@ -52,13 +54,15 @@ impl Size<Length> {
 }
 
 #[derive(Refineable, Clone, Default, Debug)]
-pub struct Bounds<F: Clone> {
-    pub origin: Point<F>,
-    pub size: Size<F>,
+#[refineable(debug)]
+pub struct Bounds<T: Clone + Debug> {
+    pub origin: Point<T>,
+    pub size: Size<T>,
 }
 
 #[derive(Refineable, Clone, Default, Debug)]
-pub struct Edges<T: Clone> {
+#[refineable(debug)]
+pub struct Edges<T: Clone + Debug> {
     pub top: T,
     pub right: T,
     pub bottom: T,

crates/storybook/src/gpui3/mod.rs 🔗

@@ -38,8 +38,15 @@ pub trait Context {
     ) -> R;
 }
 
+#[derive(Clone, Eq, PartialEq)]
 pub struct SharedString(ArcCow<'static, str>);
 
+impl std::fmt::Debug for SharedString {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
 impl<T: Into<ArcCow<'static, str>>> From<T> for SharedString {
     fn from(value: T) -> Self {
         Self(value.into())

crates/storybook/src/gpui3/style.rs 🔗

@@ -1,14 +1,12 @@
-use gpui2::fonts::TextStyleRefinement;
 use refineable::Refineable;
-use std::sync::Arc;
 
 pub use super::taffy::style::{
     AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,
     Overflow, Position,
 };
 use super::{
-    AbsoluteLength, DefiniteLength, Edges, EdgesRefinement, Hsla, Length, Point, PointRefinement,
-    SharedString, Size, SizeRefinement, WindowContext,
+    rems, AbsoluteLength, Bounds, DefiniteLength, Edges, EdgesRefinement, Hsla, Length, Pixels,
+    Point, PointRefinement, Rems, SharedString, Size, SizeRefinement, ViewContext, WindowContext,
 };
 pub use gpui2::style::{FontStyle, FontWeight};
 
@@ -98,30 +96,33 @@ pub struct Style {
     pub text_color: Option<Hsla>,
 
     /// The font size in rems.
-    pub font_size: Option<f32>,
+    pub font_size: Option<Rems>,
 
-    pub font_family: Option<Arc<str>>,
+    pub font_family: Option<SharedString>,
 
     pub font_weight: Option<FontWeight>,
 
     pub font_style: Option<FontStyle>,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Refineable, Clone, Debug)]
+#[refineable(debug)]
 pub struct TextStyle {
-    pub color: Color,
-    pub font_family_name: SharedString,
-    pub font_size: FontSize,
+    pub color: Hsla,
+    pub font_family: SharedString,
+    pub font_size: Rems,
+    pub font_weight: FontWeight,
+    pub font_style: FontStyle,
     pub underline: Underline,
-    pub soft_wrap: bool,
 }
 
-#[derive(Clone, Default, Debug)]
+#[derive(Refineable, Clone, Default, Debug)]
+#[refineable(debug)]
 pub struct Underline {
-    pub origin: Vector2F,
-    pub width: f32,
-    pub thickness: f32,
-    pub color: Color,
+    pub origin: Point<Pixels>,
+    pub width: Pixels,
+    pub thickness: Pixels,
+    pub color: Hsla,
     pub squiggly: bool,
 }
 
@@ -137,75 +138,31 @@ impl Style {
         }
 
         Some(TextStyleRefinement {
-            color: self.text_color.map(Into::into),
+            color: self.text_color,
             font_family: self.font_family.clone(),
-            font_size: self.font_size.map(|size| size * cx.rem_size()),
-            font_weight: self.font_weight.map(Into::into),
+            font_size: self.font_size,
+            font_weight: self.font_weight,
             font_style: self.font_style,
             underline: None,
         })
     }
 
-    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_widths.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
-        }
-    }
-
     /// Paints the background of an element styled with this style.
-    pub fn paint_background<V: 'static>(&self, bounds: RectF, cx: &mut ViewContext<V>) {
+    pub fn paint_background<V: 'static>(&self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
         let rem_size = cx.rem_size();
         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(bounds.size(), rem_size),
-                border: Default::default(),
-            });
+            todo!();
         }
     }
 
     /// Paints the foreground of an element styled with this style.
-    pub fn paint_foreground<V: 'static>(&self, bounds: RectF, cx: &mut ViewContext<V>) {
+    pub fn paint_foreground<V: 'static>(&self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
         let rem_size = cx.rem_size();
 
         if let Some(color) = self.border_color {
             let border = self.border_widths.to_pixels(rem_size);
             if !border.is_empty() {
-                cx.scene().push_quad(gpui::Quad {
-                    bounds,
-                    background: None,
-                    corner_radii: self.corner_radii.to_gpui(bounds.size(), rem_size),
-                    border: scene::Border {
-                        color: color.into(),
-                        top: border.top,
-                        right: border.right,
-                        bottom: border.bottom,
-                        left: border.left,
-                    },
-                });
+                todo!();
             }
         }
     }
@@ -245,7 +202,7 @@ impl Default for Style {
             border_color: None,
             corner_radii: CornerRadii::default(),
             text_color: None,
-            font_size: Some(1.),
+            font_size: Some(rems(1.)),
             font_family: None,
             font_weight: None,
             font_style: None,
@@ -286,16 +243,3 @@ pub struct CornerRadii {
     bottom_left: AbsoluteLength,
     bottom_right: AbsoluteLength,
 }
-
-impl CornerRadii {
-    pub fn to_gpui(&self, box_size: Vector2F, rem_size: f32) -> gpui::scene::CornerRadii {
-        let max_radius = box_size.x().min(box_size.y()) / 2.;
-
-        gpui::scene::CornerRadii {
-            top_left: self.top_left.to_pixels(rem_size).min(max_radius),
-            top_right: self.top_right.to_pixels(rem_size).min(max_radius),
-            bottom_left: self.bottom_left.to_pixels(rem_size).min(max_radius),
-            bottom_right: self.bottom_right.to_pixels(rem_size).min(max_radius),
-        }
-    }
-}

crates/storybook/src/gpui3/taffy.rs 🔗

@@ -33,17 +33,37 @@ impl TaffyLayoutEngine {
     }
 }
 
-trait ToTaffy {
-    type Output;
-
-    fn to_taffy(&self, rem_size: Pixels) -> Self::Output;
+trait ToTaffy<Output> {
+    fn to_taffy(&self, rem_size: Pixels) -> Output;
 }
 
-impl ToTaffy for Style {
-    type Output = taffy::style::Style;
-
-    fn to_taffy(&self, rem_size: Pixels) -> Self::Output {
-        todo!()
+impl ToTaffy<taffy::style::Style> for Style {
+    fn to_taffy(&self, rem_size: Pixels) -> 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_widths.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),
+            flex_grow: self.flex_grow,
+            flex_shrink: self.flex_shrink,
+            ..Default::default() // Ignore grid properties for now
+        }
     }
 }
 
@@ -61,20 +81,25 @@ impl ToTaffy for Style {
 //     }
 // }
 
-impl ToTaffy for Length {
-    type Output = taffy::style::LengthPercentageAuto;
-
+impl ToTaffy<taffy::style::LengthPercentageAuto> for Length {
     fn to_taffy(&self, rem_size: Pixels) -> taffy::prelude::LengthPercentageAuto {
         match self {
-            Length::Definite(length) => length.to_taffy(rem_size).into(),
+            Length::Definite(length) => length.to_taffy(rem_size),
             Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
         }
     }
 }
 
-impl ToTaffy for DefiniteLength {
-    type Output = taffy::style::LengthPercentage;
+impl ToTaffy<taffy::style::Dimension> for Length {
+    fn to_taffy(&self, rem_size: Pixels) -> taffy::prelude::Dimension {
+        match self {
+            Length::Definite(length) => length.to_taffy(rem_size),
+            Length::Auto => taffy::prelude::Dimension::Auto,
+        }
+    }
+}
 
+impl ToTaffy<taffy::style::LengthPercentage> for DefiniteLength {
     fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentage {
         match self {
             DefiniteLength::Absolute(length) => match length {
@@ -92,10 +117,40 @@ impl ToTaffy for DefiniteLength {
     }
 }
 
-impl ToTaffy for AbsoluteLength {
-    type Output = taffy::style::LengthPercentage;
+impl ToTaffy<taffy::style::LengthPercentageAuto> for DefiniteLength {
+    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentageAuto {
+        match self {
+            DefiniteLength::Absolute(length) => match length {
+                AbsoluteLength::Pixels(pixels) => {
+                    taffy::style::LengthPercentageAuto::Length(pixels.into())
+                }
+                AbsoluteLength::Rems(rems) => {
+                    taffy::style::LengthPercentageAuto::Length((*rems * rem_size).into())
+                }
+            },
+            DefiniteLength::Fraction(fraction) => {
+                taffy::style::LengthPercentageAuto::Percent(*fraction)
+            }
+        }
+    }
+}
+
+impl ToTaffy<taffy::style::Dimension> for DefiniteLength {
+    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::Dimension {
+        match self {
+            DefiniteLength::Absolute(length) => match length {
+                AbsoluteLength::Pixels(pixels) => taffy::style::Dimension::Length(pixels.into()),
+                AbsoluteLength::Rems(rems) => {
+                    taffy::style::Dimension::Length((*rems * rem_size).into())
+                }
+            },
+            DefiniteLength::Fraction(fraction) => taffy::style::Dimension::Percent(*fraction),
+        }
+    }
+}
 
-    fn to_taffy(&self, rem_size: Pixels) -> Self::Output {
+impl ToTaffy<taffy::style::LengthPercentage> for AbsoluteLength {
+    fn to_taffy(&self, rem_size: Pixels) -> taffy::style::LengthPercentage {
         match self {
             AbsoluteLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(pixels.into()),
             AbsoluteLength::Rems(rems) => {
@@ -105,7 +160,7 @@ impl ToTaffy for AbsoluteLength {
     }
 }
 
-impl<T, T2> From<taffy::geometry::Point<T>> for Point<T2>
+impl<T, T2: Clone + Debug> From<taffy::geometry::Point<T>> for Point<T2>
 where
     T: Into<T2>,
 {
@@ -117,7 +172,7 @@ where
     }
 }
 
-impl<T, T2> Into<taffy::geometry::Point<T2>> for Point<T>
+impl<T: Clone + Debug, T2> Into<taffy::geometry::Point<T2>> for Point<T>
 where
     T: Into<T2>,
 {
@@ -129,10 +184,8 @@ where
     }
 }
 
-impl<T: ToTaffy + Clone> ToTaffy for Size<T> {
-    type Output = taffy::geometry::Size<T::Output>;
-
-    fn to_taffy(&self, rem_size: Pixels) -> Self::Output {
+impl<T: ToTaffy<U> + Clone + Debug, U> ToTaffy<taffy::geometry::Size<U>> for Size<T> {
+    fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Size<U> {
         taffy::geometry::Size {
             width: self.width.to_taffy(rem_size).into(),
             height: self.height.to_taffy(rem_size).into(),
@@ -140,15 +193,16 @@ impl<T: ToTaffy + Clone> ToTaffy for Size<T> {
     }
 }
 
-impl<T: ToTaffy + Clone> ToTaffy for Edges<T> {
-    type Output = taffy::geometry::Rect<T::Output>;
-
-    fn to_taffy(&self, rem_size: Pixels) -> Self::Output {
+impl<T, U> ToTaffy<taffy::geometry::Rect<U>> for Edges<T>
+where
+    T: ToTaffy<U> + Clone + Debug,
+{
+    fn to_taffy(&self, rem_size: Pixels) -> taffy::geometry::Rect<U> {
         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),
+            top: self.top.to_taffy(rem_size).into(),
+            right: self.right.to_taffy(rem_size).into(),
+            bottom: self.bottom.to_taffy(rem_size).into(),
+            left: self.left.to_taffy(rem_size).into(),
         }
     }
 }
@@ -179,6 +233,6 @@ impl From<&taffy::tree::Layout> for Layout {
 
 impl From<f32> for Pixels {
     fn from(pixels: f32) -> Self {
-        Self(pixels)
+        Pixels(pixels)
     }
 }

crates/util/src/arc_cow.rs 🔗

@@ -1,4 +1,7 @@
-use std::sync::Arc;
+use std::{
+    fmt::{self, Debug},
+    sync::Arc,
+};
 
 #[derive(PartialEq, Eq)]
 pub enum ArcCow<'a, T: ?Sized> {
@@ -72,3 +75,12 @@ impl<T: ?Sized> AsRef<T> for ArcCow<'_, T> {
         }
     }
 }
+
+impl<'a, T: ?Sized + Debug> Debug for ArcCow<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            ArcCow::Borrowed(borrowed) => Debug::fmt(borrowed, f),
+            ArcCow::Owned(owned) => Debug::fmt(&**owned, f),
+        }
+    }
+}