Use new children approach for `Pane`s and `Toast`s

Marshall Bowers created

Change summary

crates/ui2/src/components/panes.rs     | 26 ++++++++-------
crates/ui2/src/components/terminal.rs  | 29 +++++++++--------
crates/ui2/src/components/toast.rs     | 39 ++++++++++++++---------
crates/ui2/src/components/workspace.rs | 45 +++++++--------------------
4 files changed, 64 insertions(+), 75 deletions(-)

Detailed changes

crates/ui2/src/components/panes.rs 🔗

@@ -1,6 +1,7 @@
 use std::marker::PhantomData;
 
-use gpui3::{hsla, Hsla, Length, Size};
+use gpui3::{hsla, AnyElement, Hsla, Length, Size};
+use smallvec::SmallVec;
 
 use crate::prelude::*;
 use crate::theme;
@@ -18,17 +19,11 @@ pub struct Pane<S: 'static + Send + Sync> {
     scroll_state: ScrollState,
     size: Size<Length>,
     fill: Hsla,
-    children: HackyChildren<S>,
-    payload: HackyChildrenPayload,
+    children: SmallVec<[AnyElement<S>; 2]>,
 }
 
 impl<S: 'static + Send + Sync> Pane<S> {
-    pub fn new(
-        scroll_state: ScrollState,
-        size: Size<Length>,
-        children: HackyChildren<S>,
-        payload: HackyChildrenPayload,
-    ) -> Self {
+    pub fn new(scroll_state: ScrollState, size: Size<Length>) -> Self {
         // Fill is only here for debugging purposes, remove before release
         let system_color = SystemColor::new();
 
@@ -38,8 +33,7 @@ impl<S: 'static + Send + Sync> Pane<S> {
             size,
             fill: hsla(0.3, 0.3, 0.3, 1.),
             // fill: system_color.transparent,
-            children,
-            payload,
+            children: SmallVec::new(),
         }
     }
 
@@ -58,7 +52,15 @@ impl<S: 'static + Send + Sync> Pane<S> {
             .w(self.size.width)
             .h(self.size.height)
             .overflow_y_scroll(self.scroll_state.clone())
-            .children_any((self.children)(cx, self.payload.as_ref()))
+            .children(self.children.drain(..))
+    }
+}
+
+impl<S: 'static + Send + Sync> ParentElement for Pane<S> {
+    type State = S;
+
+    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
+        &mut self.children
     }
 }
 

crates/ui2/src/components/terminal.rs 🔗

@@ -72,19 +72,16 @@ impl<S: 'static + Send + Sync + Clone> Terminal<S> {
                     ),
             )
             // Terminal Pane.
-            .child(Pane::new(
-                ScrollState::default(),
-                Size {
-                    width: relative(1.).into(),
-                    height: rems(36.).into(),
-                },
-                |_, payload| {
-                    let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
-
-                    vec![crate::static_data::terminal_buffer(&theme).into_any()]
-                },
-                Box::new(theme),
-            ))
+            .child(
+                Pane::new(
+                    ScrollState::default(),
+                    Size {
+                        width: relative(1.).into(),
+                        height: rems(36.).into(),
+                    },
+                )
+                .child(crate::static_data::terminal_buffer(&theme)),
+            )
     }
 }
 
@@ -109,7 +106,11 @@ mod stories {
             }
         }
 
-        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(
+            &mut self,
+            _view: &mut S,
+            cx: &mut ViewContext<S>,
+        ) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Terminal<S>>(cx))
                 .child(Story::label(cx, "Default"))

crates/ui2/src/components/toast.rs 🔗

@@ -1,3 +1,8 @@
+use std::marker::PhantomData;
+
+use gpui3::AnyElement;
+use smallvec::SmallVec;
+
 use crate::prelude::*;
 
 #[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
@@ -24,20 +29,14 @@ pub enum ToastVariant {
 #[derive(Element)]
 pub struct Toast<S: 'static + Send + Sync> {
     origin: ToastOrigin,
-    children: HackyChildren<S>,
-    payload: HackyChildrenPayload,
+    children: SmallVec<[AnyElement<S>; 2]>,
 }
 
 impl<S: 'static + Send + Sync> Toast<S> {
-    pub fn new(
-        origin: ToastOrigin,
-        children: HackyChildren<S>,
-        payload: HackyChildrenPayload,
-    ) -> Self {
+    pub fn new(origin: ToastOrigin) -> Self {
         Self {
             origin,
-            children,
-            payload,
+            children: SmallVec::new(),
         }
     }
 
@@ -62,7 +61,15 @@ impl<S: 'static + Send + Sync> Toast<S> {
             .rounded_md()
             .fill(color.elevated_surface)
             .max_w_64()
-            .children_any((self.children)(cx, self.payload.as_ref()))
+            .children(self.children.drain(..))
+    }
+}
+
+impl<S: 'static + Send + Sync> ParentElement for Toast<S> {
+    type State = S;
+
+    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement<Self::State>; 2]> {
+        &mut self.children
     }
 }
 
@@ -89,15 +96,15 @@ mod stories {
             }
         }
 
-        fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
+        fn render(
+            &mut self,
+            _view: &mut S,
+            cx: &mut ViewContext<S>,
+        ) -> impl Element<ViewState = S> {
             Story::container(cx)
                 .child(Story::title_for::<_, Toast<S>>(cx))
                 .child(Story::label(cx, "Default"))
-                .child(Toast::new(
-                    ToastOrigin::Bottom,
-                    |_, _| vec![Label::new("label").into_any()],
-                    Box::new(()),
-                ))
+                .child(Toast::new(ToastOrigin::Bottom).child(Label::new("label")))
         }
     }
 }

crates/ui2/src/components/workspace.rs 🔗

@@ -172,25 +172,18 @@ impl Workspace {
                                 width: relative(1.).into(),
                                 height: temp_size,
                             },
-                            |_, payload| {
-                                let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
-
-                                vec![EditorPane::new(hello_world_rust_editor_with_status_example(
-                                    &theme,
-                                ))
-                                .into_any()]
-                            },
-                            Box::new(theme.clone()),
-                        ),
+                        )
+                        .child(EditorPane::new(
+                            hello_world_rust_editor_with_status_example(&theme),
+                        )),
                         Pane::new(
                             ScrollState::default(),
                             Size {
                                 width: relative(1.).into(),
                                 height: temp_size,
                             },
-                            |_, _| vec![Terminal::new().into_any()],
-                            Box::new(()),
-                        ),
+                        )
+                        .child(Terminal::new()),
                     ],
                     SplitDirection::Vertical,
                 ),
@@ -201,16 +194,10 @@ impl Workspace {
                             width: relative(1.).into(),
                             height: relative(1.).into(),
                         },
-                        |_, payload| {
-                            let theme = payload.downcast_ref::<Arc<Theme>>().unwrap();
-
-                            vec![EditorPane::new(hello_world_rust_editor_with_status_example(
-                                &theme,
-                            ))
-                            .into_any()]
-                        },
-                        Box::new(theme.clone()),
-                    )],
+                    )
+                    .child(EditorPane::new(
+                        hello_world_rust_editor_with_status_example(&theme),
+                    ))],
                     SplitDirection::Vertical,
                 ),
             ],
@@ -326,16 +313,8 @@ impl Workspace {
                 )
                 .filter(|_| workspace_state.is_language_selector_open()),
             )
-            .child(Toast::new(
-                ToastOrigin::Bottom,
-                |_, _| vec![Label::new("A toast").into_any()],
-                Box::new(()),
-            ))
-            .child(Toast::new(
-                ToastOrigin::BottomRight,
-                |_, _| vec![Label::new("Another toast").into_any()],
-                Box::new(()),
-            ))
+            .child(Toast::new(ToastOrigin::Bottom).child(Label::new("A toast")))
+            .child(Toast::new(ToastOrigin::BottomRight).child(Label::new("Another toast")))
     }
 }