Unify Flexible and Expanded elements

Max Brunsfeld and Nathan Sobo created

We'll use the name Expanded for something else now.

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/chat_panel/src/chat_panel.rs         |  2 
crates/contacts_panel/src/contacts_panel.rs |  2 
crates/file_finder/src/file_finder.rs       |  3 
crates/gpui/src/elements.rs                 |  4 
crates/gpui/src/elements/flex.rs            | 77 ----------------------
crates/theme_selector/src/theme_selector.rs |  2 
crates/workspace/src/pane.rs                | 14 +--
crates/workspace/src/pane_group.rs          |  2 
crates/workspace/src/sidebar.rs             | 21 ++---
crates/workspace/src/status_bar.rs          |  2 
crates/workspace/src/workspace.rs           | 74 +++++++++------------
11 files changed, 58 insertions(+), 145 deletions(-)

Detailed changes

crates/chat_panel/src/chat_panel.rs 🔗

@@ -233,7 +233,7 @@ impl ChatPanel {
             Empty::new().boxed()
         };
 
-        Expanded::new(1., messages).boxed()
+        Flexible::new(1., true, messages).boxed()
     }
 
     fn render_message(&self, message: &ChannelMessage) -> ElementBox {

crates/file_finder/src/file_finder.rs 🔗

@@ -83,7 +83,7 @@ impl View for FileFinder {
                                 .with_style(settings.theme.selector.input_editor.container)
                                 .boxed(),
                         )
-                        .with_child(Flexible::new(1.0, self.render_matches()).boxed())
+                        .with_child(Flexible::new(1.0, false, self.render_matches()).boxed())
                         .boxed(),
                 )
                 .with_style(settings.theme.selector.container)
@@ -175,6 +175,7 @@ impl FileFinder {
                 .with_child(
                     Flexible::new(
                         1.0,
+                        false,
                         Flex::column()
                             .with_child(
                                 Label::new(file_name.to_string(), style.label.clone())

crates/gpui/src/elements.rs 🔗

@@ -130,11 +130,11 @@ pub trait Element {
         Container::new(self.boxed())
     }
 
-    fn expanded(self, flex: f32) -> Expanded
+    fn flexible(self, flex: f32, expanded: bool) -> Flexible
     where
         Self: 'static + Sized,
     {
-        Expanded::new(flex, self.boxed())
+        Flexible::new(flex, expanded, self.boxed())
     }
 }
 

crates/gpui/src/elements/flex.rs 🔗

@@ -228,88 +228,15 @@ struct FlexParentData {
     expanded: bool,
 }
 
-pub struct Expanded {
-    metadata: FlexParentData,
-    child: ElementBox,
-}
-
-impl Expanded {
-    pub fn new(flex: f32, child: ElementBox) -> Self {
-        Expanded {
-            metadata: FlexParentData {
-                flex,
-                expanded: true,
-            },
-            child,
-        }
-    }
-}
-
-impl Element for Expanded {
-    type LayoutState = ();
-    type PaintState = ();
-
-    fn layout(
-        &mut self,
-        constraint: SizeConstraint,
-        cx: &mut LayoutContext,
-    ) -> (Vector2F, Self::LayoutState) {
-        let size = self.child.layout(constraint, cx);
-        (size, ())
-    }
-
-    fn paint(
-        &mut self,
-        bounds: RectF,
-        visible_bounds: RectF,
-        _: &mut Self::LayoutState,
-        cx: &mut PaintContext,
-    ) -> Self::PaintState {
-        self.child.paint(bounds.origin(), visible_bounds, cx)
-    }
-
-    fn dispatch_event(
-        &mut self,
-        event: &Event,
-        _: RectF,
-        _: &mut Self::LayoutState,
-        _: &mut Self::PaintState,
-        cx: &mut EventContext,
-    ) -> bool {
-        self.child.dispatch_event(event, cx)
-    }
-
-    fn metadata(&self) -> Option<&dyn Any> {
-        Some(&self.metadata)
-    }
-
-    fn debug(
-        &self,
-        _: RectF,
-        _: &Self::LayoutState,
-        _: &Self::PaintState,
-        cx: &DebugContext,
-    ) -> Value {
-        json!({
-            "type": "Expanded",
-            "flex": self.metadata.flex,
-            "child": self.child.debug(cx)
-        })
-    }
-}
-
 pub struct Flexible {
     metadata: FlexParentData,
     child: ElementBox,
 }
 
 impl Flexible {
-    pub fn new(flex: f32, child: ElementBox) -> Self {
+    pub fn new(flex: f32, expanded: bool, child: ElementBox) -> Self {
         Flexible {
-            metadata: FlexParentData {
-                flex,
-                expanded: false,
-            },
+            metadata: FlexParentData { flex, expanded },
             child,
         }
     }

crates/theme_selector/src/theme_selector.rs 🔗

@@ -293,7 +293,7 @@ impl View for ThemeSelector {
                 Container::new(
                     Flex::new(Axis::Vertical)
                         .with_child(ChildView::new(self.query_editor.id()).boxed())
-                        .with_child(Flexible::new(1.0, self.render_matches(cx)).boxed())
+                        .with_child(Flexible::new(1.0, false, self.render_matches(cx)).boxed())
                         .boxed(),
                 )
                 .with_style(settings.theme.selector.container)

crates/workspace/src/pane.rs 🔗

@@ -314,13 +314,11 @@ impl Pane {
             }
 
             row.add_child(
-                Expanded::new(
-                    0.0,
-                    Container::new(Empty::new().boxed())
-                        .with_border(theme.workspace.tab.container.border)
-                        .boxed(),
-                )
-                .named("filler"),
+                Empty::new()
+                    .contained()
+                    .with_border(theme.workspace.tab.container.border)
+                    .flexible(0., true)
+                    .named("filler"),
             );
 
             row.boxed()
@@ -345,7 +343,7 @@ impl View for Pane {
         if let Some(active_item) = self.active_item() {
             Flex::column()
                 .with_child(self.render_tabs(cx))
-                .with_child(Expanded::new(1.0, ChildView::new(active_item.id()).boxed()).boxed())
+                .with_child(ChildView::new(active_item.id()).flexible(1., true).boxed())
                 .named("pane")
         } else {
             Empty::new().named("pane")

crates/workspace/src/pane_group.rs 🔗

@@ -183,7 +183,7 @@ impl PaneAxis {
                     member = Container::new(member).with_border(border).boxed();
                 }
 
-                Expanded::new(1.0, member).boxed()
+                Flexible::new(1.0, true, member).boxed()
             }))
             .boxed()
     }

crates/workspace/src/sidebar.rs 🔗

@@ -135,19 +135,16 @@ impl Sidebar {
             }
 
             container.add_child(
-                Flexible::new(
-                    1.,
-                    Hook::new(
-                        ConstrainedBox::new(ChildView::new(active_item.id()).boxed())
-                            .with_max_width(*self.width.borrow())
-                            .boxed(),
-                    )
-                    .on_after_layout({
-                        let width = self.width.clone();
-                        move |size, _| *width.borrow_mut() = size.x()
-                    })
-                    .boxed(),
+                Hook::new(
+                    ConstrainedBox::new(ChildView::new(active_item.id()).boxed())
+                        .with_max_width(*self.width.borrow())
+                        .boxed(),
                 )
+                .on_after_layout({
+                    let width = self.width.clone();
+                    move |size, _| *width.borrow_mut() = size.x()
+                })
+                .flexible(1., false)
                 .boxed(),
             );
             if matches!(self.side, Side::Left) {

crates/workspace/src/status_bar.rs 🔗

@@ -47,7 +47,7 @@ impl View for StatusBar {
                     .iter()
                     .map(|i| ChildView::new(i.id()).aligned().boxed()),
             )
-            .with_child(Empty::new().expanded(1.).boxed())
+            .with_child(Empty::new().flexible(1., true).boxed())
             .with_children(
                 self.right_items
                     .iter()

crates/workspace/src/workspace.rs 🔗

@@ -1191,50 +1191,40 @@ impl View for Workspace {
     fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
         let settings = self.settings.borrow();
         let theme = &settings.theme;
-        Container::new(
-            Flex::column()
-                .with_child(self.render_titlebar(&theme, cx))
-                .with_child(
-                    Expanded::new(
-                        1.0,
-                        Stack::new()
-                            .with_child({
-                                let mut content = Flex::row();
-                                content.add_child(self.left_sidebar.render(&settings, cx));
-                                if let Some(element) =
-                                    self.left_sidebar.render_active_item(&settings, cx)
-                                {
-                                    content.add_child(Flexible::new(0.8, element).boxed());
-                                }
-                                content.add_child(
-                                    Flex::column()
-                                        .with_child(
-                                            Expanded::new(1.0, self.center.render(&settings.theme))
-                                                .boxed(),
-                                        )
-                                        .with_child(ChildView::new(self.status_bar.id()).boxed())
-                                        .expanded(1.)
+        Flex::column()
+            .with_child(self.render_titlebar(&theme, cx))
+            .with_child(
+                Stack::new()
+                    .with_child({
+                        let mut content = Flex::row();
+                        content.add_child(self.left_sidebar.render(&settings, cx));
+                        if let Some(element) = self.left_sidebar.render_active_item(&settings, cx) {
+                            content.add_child(Flexible::new(0.8, false, element).boxed());
+                        }
+                        content.add_child(
+                            Flex::column()
+                                .with_child(
+                                    Flexible::new(1., true, self.center.render(&settings.theme))
                                         .boxed(),
-                                );
-                                if let Some(element) =
-                                    self.right_sidebar.render_active_item(&settings, cx)
-                                {
-                                    content.add_child(Flexible::new(0.8, element).boxed());
-                                }
-                                content.add_child(self.right_sidebar.render(&settings, cx));
-                                content.boxed()
-                            })
-                            .with_children(
-                                self.modal.as_ref().map(|m| ChildView::new(m.id()).boxed()),
-                            )
-                            .boxed(),
-                    )
+                                )
+                                .with_child(ChildView::new(self.status_bar.id()).boxed())
+                                .flexible(1., true)
+                                .boxed(),
+                        );
+                        if let Some(element) = self.right_sidebar.render_active_item(&settings, cx)
+                        {
+                            content.add_child(Flexible::new(0.8, false, element).boxed());
+                        }
+                        content.add_child(self.right_sidebar.render(&settings, cx));
+                        content.boxed()
+                    })
+                    .with_children(self.modal.as_ref().map(|m| ChildView::new(m.id()).boxed()))
+                    .flexible(1.0, true)
                     .boxed(),
-                )
-                .boxed(),
-        )
-        .with_background_color(settings.theme.workspace.background)
-        .named("workspace")
+            )
+            .contained()
+            .with_background_color(settings.theme.workspace.background)
+            .named("workspace")
     }
 
     fn on_focus(&mut self, cx: &mut ViewContext<Self>) {