Checkpoint: Add methods for setting arbitrary lengths

Nathan Sobo created

Change summary

crates/gpui/src/geometry.rs                   | 21 ++++-
crates/gpui2/src/style.rs                     | 23 -----
crates/gpui2_macros/src/styleable_helpers.rs  | 83 +++++++++++++++++---
crates/storybook/src/ui/component/facepile.rs |  2 
4 files changed, 90 insertions(+), 39 deletions(-)

Detailed changes

crates/gpui/src/geometry.rs 🔗

@@ -1,12 +1,12 @@
-use std::fmt::Debug;
-
 use super::scene::{Path, PathVertex};
 use crate::{color::Color, json::ToJson};
+use derive_more::Neg;
 pub use pathfinder_geometry::*;
 use rect::RectF;
 use refineable::Refineable;
 use serde::{Deserialize, Deserializer};
 use serde_json::json;
+use std::fmt::Debug;
 use vector::{vec2f, Vector2F};
 
 pub struct PathBuilder {
@@ -235,6 +235,17 @@ pub struct Edges<T: Clone + Default + Debug> {
     pub left: T,
 }
 
+impl<T: Clone + Default + Debug> Edges<T> {
+    pub fn uniform(value: T) -> Self {
+        Self {
+            top: value.clone(),
+            right: value.clone(),
+            bottom: value.clone(),
+            left: value.clone(),
+        }
+    }
+}
+
 impl Edges<Length> {
     pub fn auto() -> Self {
         Self {
@@ -322,7 +333,7 @@ impl Edges<f32> {
     }
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Neg)]
 pub enum AbsoluteLength {
     Pixels(f32),
     Rems(f32),
@@ -360,7 +371,7 @@ impl Default for AbsoluteLength {
 }
 
 /// A non-auto length that can be defined in pixels, rems, or percent of parent.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Neg)]
 pub enum DefiniteLength {
     Absolute(AbsoluteLength),
     Relative(f32), // 0. to 1.
@@ -404,7 +415,7 @@ impl Default for DefiniteLength {
 }
 
 /// A length that can be defined in pixels, rems, percent of parent, or auto.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Neg)]
 pub enum Length {
     Definite(DefiniteLength),
     Auto,

crates/gpui2/src/style.rs 🔗

@@ -314,6 +314,8 @@ pub trait Styleable {
     }
 }
 
+use crate as gpui2;
+
 // Helpers methods that take and return mut self. This includes tailwind style methods for standard sizes etc.
 //
 // Example:
@@ -322,27 +324,6 @@ pub trait Styleable {
 pub trait StyleHelpers: Styleable<Style = Style> {
     styleable_helpers!();
 
-    fn h(mut self, height: Length) -> Self
-    where
-        Self: Sized,
-    {
-        self.declared_style().size.height = Some(height);
-        self
-    }
-
-    /// size_{n}: Sets width & height to {n}
-    ///
-    /// Example:
-    /// size_1: Sets width & height to 1
-    fn size(mut self, size: Length) -> Self
-    where
-        Self: Sized,
-    {
-        self.declared_style().size.height = Some(size);
-        self.declared_style().size.width = Some(size);
-        self
-    }
-
     fn full(mut self) -> Self
     where
         Self: Sized,

crates/gpui2_macros/src/styleable_helpers.rs 🔗

@@ -28,28 +28,58 @@ fn generate_methods() -> Vec<TokenStream2> {
     let mut methods = Vec::new();
 
     for (prefix, auto_allowed, fields) in box_prefixes() {
+        methods.push(generate_method_with_parameter(
+            prefix,
+            if auto_allowed {
+                quote! { Length }
+            } else {
+                quote! { DefiniteLength }
+            },
+            &fields,
+        ));
+
         for (suffix, length_tokens, doc_string) in box_suffixes() {
-            if auto_allowed || suffix != "auto" {
-                let method = generate_method(prefix, suffix, &fields, length_tokens, doc_string);
-                methods.push(method);
+            if suffix != "auto" || auto_allowed {
+                methods.push(generate_method(
+                    prefix,
+                    suffix,
+                    &fields,
+                    length_tokens,
+                    doc_string,
+                ));
             }
         }
     }
 
     for (prefix, fields) in corner_prefixes() {
+        methods.push(generate_method_with_parameter(
+            prefix,
+            quote! { AbsoluteLength },
+            &fields,
+        ));
+
         for (suffix, radius_tokens, doc_string) in corner_suffixes() {
-            let method = generate_method(prefix, suffix, &fields, radius_tokens, doc_string);
-            methods.push(method);
+            methods.push(generate_method(
+                prefix,
+                suffix,
+                &fields,
+                radius_tokens,
+                doc_string,
+            ));
         }
     }
 
     for (prefix, fields) in border_prefixes() {
         for (suffix, width_tokens, doc_string) in border_suffixes() {
-            let method = generate_method(prefix, suffix, &fields, width_tokens, doc_string);
-            methods.push(method);
+            methods.push(generate_method(
+                prefix,
+                suffix,
+                &fields,
+                width_tokens,
+                doc_string,
+            ));
         }
     }
-
     methods
 }
 
@@ -70,7 +100,7 @@ fn generate_method(
         .iter()
         .map(|field_tokens| {
             quote! {
-                style.#field_tokens = Some(gpui::geometry::#length_tokens);
+                style.#field_tokens = Some(gpui2::geometry::#length_tokens);
             }
         })
         .collect::<Vec<_>>();
@@ -87,6 +117,33 @@ fn generate_method(
     method
 }
 
+fn generate_method_with_parameter(
+    prefix: &'static str,
+    length_type: TokenStream2,
+    fields: &Vec<TokenStream2>,
+) -> TokenStream2 {
+    let method_name = format_ident!("{}", prefix);
+
+    let field_assignments = fields
+        .iter()
+        .map(|field_tokens| {
+            quote! {
+                style.#field_tokens = Some(length);
+            }
+        })
+        .collect::<Vec<_>>();
+
+    let method = quote! {
+        fn #method_name(mut self, length: gpui2::geometry::#length_type) -> Self where Self: std::marker::Sized {
+            let mut style = self.declared_style();
+            #(#field_assignments)*
+            self
+        }
+    };
+
+    method
+}
+
 fn box_prefixes() -> Vec<(&'static str, bool, Vec<TokenStream2>)> {
     vec![
         ("w", true, vec![quote! { size.width }]),
@@ -96,10 +153,10 @@ fn box_prefixes() -> Vec<(&'static str, bool, Vec<TokenStream2>)> {
             true,
             vec![quote! {size.width}, quote! {size.height}],
         ),
-        ("min_w", false, vec![quote! { min_size.width }]),
-        ("min_h", false, vec![quote! { min_size.height }]),
-        ("max_w", false, vec![quote! { max_size.width }]),
-        ("max_h", false, vec![quote! { max_size.height }]),
+        ("min_w", true, vec![quote! { min_size.width }]),
+        ("min_h", true, vec![quote! { min_size.height }]),
+        ("max_w", true, vec![quote! { max_size.width }]),
+        ("max_h", true, vec![quote! { max_size.height }]),
         (
             "m",
             true,

crates/storybook/src/ui/component/facepile.rs 🔗

@@ -1,5 +1,6 @@
 use crate::theme::theme;
 use crate::ui::Avatar;
+use gpui2::geometry::rems;
 use gpui2::style::StyleHelpers;
 use gpui2::{elements::div, IntoElement};
 use gpui2::{Element, ParentElement, ViewContext};
@@ -24,6 +25,7 @@ impl Facepile {
         div()
             .relative()
             .p_1()
+            .mx(rems(-0.125))
             .flex()
             .items_center()
             .children(player_list)