Render a component

Nathan Sobo created

Change summary

crates/gpui/playground/src/components.rs | 34 +++++++++++++++++++------
crates/gpui/playground/src/frame.rs      |  7 +++++
crates/gpui/playground/src/playground.rs |  7 ++++
3 files changed, 38 insertions(+), 10 deletions(-)

Detailed changes

crates/gpui/playground/src/components.rs 🔗

@@ -18,18 +18,22 @@ impl<V, D> Default for ButtonHandlers<V, D> {
 
 pub struct Button<V: 'static, D: 'static> {
     metadata: ElementMetadata<V>,
-    button_handlers: ButtonHandlers<V, D>,
-    label: Cow<'static, str>,
+    handlers: ButtonHandlers<V, D>,
+    label: Option<Cow<'static, str>>,
+    icon: Option<Cow<'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(label: impl Into<Cow<'static, str>>) -> Self {
+    fn new() -> Self {
         Self {
             metadata: Default::default(),
-            button_handlers: ButtonHandlers::default(),
-            label: label.into(),
+            handlers: ButtonHandlers::default(),
+            label: None,
+            icon: None,
             data: Rc::new(()),
             view_type: PhantomData,
         }
@@ -38,15 +42,27 @@ impl<V: 'static> Button<V, ()> {
     pub fn data<D: 'static>(self, data: D) -> Button<V, D> {
         Button {
             metadata: Default::default(),
-            button_handlers: ButtonHandlers::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> {
+    fn label(mut self, label: impl Into<Cow<'static, str>>) -> Self {
+        self.label = Some(label.into());
+        self
+    }
+
+    fn icon(mut self, icon: impl Into<Cow<'static, str>>) -> Self {
+        self.icon = Some(icon.into());
+        self
+    }
+
     fn click(self, handler: impl Fn(&mut V, &D) + 'static) -> Self {
         let data = self.data.clone();
         Element::click(self, move |view, _| {
@@ -55,8 +71,8 @@ impl<V: 'static, D: 'static> Button<V, D> {
     }
 }
 
-pub fn button<V>(label: impl Into<Cow<'static, str>>) -> Button<V, ()> {
-    Button::new(label)
+pub fn button<V>() -> Button<V, ()> {
+    Button::new()
 }
 
 impl<V: 'static, D: 'static> Button<V, D> {
@@ -64,7 +80,7 @@ impl<V: 'static, D: 'static> Button<V, D> {
         // TODO: Drive from the context
         let button = frame().fill(rose_pine::dawn().error(0.5)).h_5().w_9();
 
-        if let Some(handler) = self.button_handlers.click.clone() {
+        if let Some(handler) = self.handlers.click.clone() {
             let data = self.data.clone();
             button.click(move |view, event| handler(view, data.as_ref()))
         } else {

crates/gpui/playground/src/frame.rs 🔗

@@ -64,3 +64,10 @@ impl<V: 'static> Element<V> for Frame<V> {
         Ok(())
     }
 }
+
+impl<V: 'static> Frame<V> {
+    pub fn child(mut self, child: impl Element<V>) -> Self {
+        self.children.push(child.into_any());
+        self
+    }
+}

crates/gpui/playground/src/playground.rs 🔗

@@ -1,4 +1,5 @@
 #![allow(dead_code, unused_variables)]
+use components::button;
 use element::Element;
 use frame::frame;
 use gpui::{
@@ -42,7 +43,11 @@ fn main() {
 
 fn workspace<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
     // frame().w_full().h_half().fill(theme.success(0.5))
-    frame().h_full().w(percent(50.)).fill(theme.success(0.5))
+    frame()
+        .h_full()
+        .w(percent(50.))
+        .fill(theme.success(0.5))
+        .child(button())
 }
 //     todo!()
 //     // column()