Clean compile with redesigned element traits

Nathan Sobo created

Change summary

crates/collab_ui2/src/collab_panel.rs          |   2 
crates/collab_ui2/src/collab_titlebar_item.rs  |   4 
crates/command_palette2/src/command_palette.rs |   4 
crates/editor2/src/editor.rs                   |  35 ++--
crates/editor2/src/editor_tests.rs             |   2 
crates/editor2/src/element.rs                  |  39 +++--
crates/file_finder2/src/file_finder.rs         |   7 
crates/go_to_line2/src/go_to_line.rs           |   2 
crates/gpui2/src/element.rs                    | 130 +++++++++++++------
crates/gpui2/src/elements/div.rs               |  24 +-
crates/gpui2/src/elements/img.rs               |   8 
crates/gpui2/src/elements/overlay.rs           |   8 
crates/gpui2/src/elements/svg.rs               |   8 
crates/gpui2/src/elements/text.rs              |  32 ++--
crates/gpui2/src/elements/uniform_list.rs      |   8 
crates/gpui2/src/view.rs                       |  24 +-
crates/gpui2_macros/src/derive_render_once.rs  |   4 
crates/picker2/src/picker2.rs                  |   8 
crates/project_panel2/src/project_panel.rs     |   8 
crates/storybook2/src/stories/colors.rs        |   4 
crates/storybook2/src/stories/focus.rs         |   2 
crates/storybook2/src/stories/kitchen_sink.rs  |   2 
crates/storybook2/src/stories/picker.rs        |   9 
crates/storybook2/src/stories/scroll.rs        |   2 
crates/storybook2/src/stories/text.rs          |   6 
crates/storybook2/src/stories/z_index.rs       |  24 ++-
crates/storybook2/src/storybook2.rs            |   2 
crates/terminal_view2/src/terminal_panel.rs    |   2 
crates/terminal_view2/src/terminal_view.rs     |  10 
crates/ui2/src/components/context_menu.rs      |  31 +---
crates/ui2/src/components/divider.rs           |  21 ++
crates/workspace2/src/dock.rs                  |   9 
crates/workspace2/src/pane.rs                  |   6 
crates/workspace2/src/pane_group.rs            |   3 
crates/workspace2/src/status_bar.rs            |   4 
35 files changed, 278 insertions(+), 216 deletions(-)

Detailed changes

crates/collab_ui2/src/collab_panel.rs 🔗

@@ -3294,7 +3294,7 @@ impl CollabPanel {
 //     .with_width(size.x())
 // }
 
-impl Render for CollabPanel {
+impl Render<Self> for CollabPanel {
     type Element = Focusable<Self, Div<Self>>;
 
     fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {

crates/collab_ui2/src/collab_titlebar_item.rs 🔗

@@ -31,7 +31,7 @@ use std::sync::Arc;
 use call::ActiveCall;
 use client::{Client, UserStore};
 use gpui::{
-    div, px, rems, AppContext, Component, Div, InteractiveElement, Model, ParentElement, Render,
+    div, px, rems, AppContext, Div, InteractiveElement, Model, ParentElement, Render, RenderOnce,
     Stateful, StatefulInteractiveElement, Styled, Subscription, ViewContext, VisualContext,
     WeakView, WindowBounds,
 };
@@ -81,7 +81,7 @@ pub struct CollabTitlebarItem {
     _subscriptions: Vec<Subscription>,
 }
 
-impl Render for CollabTitlebarItem {
+impl Render<Self> for CollabTitlebarItem {
     type Element = Stateful<Self, Div<Self>>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/command_palette2/src/command_palette.rs 🔗

@@ -1,7 +1,7 @@
 use collections::{CommandPaletteFilter, HashMap};
 use fuzzy::{StringMatch, StringMatchCandidate};
 use gpui::{
-    actions, div, prelude::*, Action, AppContext, Component, Dismiss, Div, FocusHandle, Keystroke,
+    actions, div, prelude::*, Action, AppContext, Dismiss, Div, FocusHandle, Keystroke,
     ManagedView, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
 };
 use picker::{Picker, PickerDelegate};
@@ -74,7 +74,7 @@ impl ManagedView for CommandPalette {
     }
 }
 
-impl Render for CommandPalette {
+impl Render<Self> for CommandPalette {
     type Element = Div<Self>;
 
     fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {

crates/editor2/src/editor.rs 🔗

@@ -42,9 +42,9 @@ use gpui::{
     actions, div, point, prelude::*, px, relative, rems, size, uniform_list, Action, AnyElement,
     AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context,
     EventEmitter, FocusHandle, FocusableView, FontFeatures, FontStyle, FontWeight, HighlightStyle,
-    Hsla, InputHandler, KeyContext, Model, MouseButton, ParentElement, Pixels, Render, Styled,
-    Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext,
-    WeakView, WindowContext,
+    Hsla, InputHandler, KeyContext, Model, MouseButton, ParentElement, Pixels, Render,
+    SharedString, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, View,
+    ViewContext, VisualContext, WeakView, WindowContext,
 };
 use highlight_matching_bracket::refresh_matching_bracket_highlights;
 use hover_popover::{hide_hover, HoverState};
@@ -1580,7 +1580,8 @@ impl CodeActionsMenu {
                                     )
                                     .map(|task| task.detach_and_log_err(cx));
                             })
-                            .child(action.lsp_action.title.clone())
+                            // TASK: It would be good to make lsp_action.title a SharedString to avoid allocating here.
+                            .child(SharedString::from(action.lsp_action.title.clone()))
                     })
                     .collect()
             },
@@ -1595,7 +1596,7 @@ impl CodeActionsMenu {
                 .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
                 .map(|(ix, _)| ix),
         )
-        .render_once();
+        .render_into_any();
 
         if self.deployed_from_indicator {
             *cursor_position.column_mut() = 0;
@@ -4353,19 +4354,19 @@ impl Editor {
         style: &EditorStyle,
         is_active: bool,
         cx: &mut ViewContext<Self>,
-    ) -> Option<AnyElement<Self>> {
+    ) -> Option<IconButton<Self>> {
         if self.available_code_actions.is_some() {
             Some(
-                IconButton::new("code_actions_indicator", ui::Icon::Bolt)
-                    .on_click(|editor: &mut Editor, cx| {
+                IconButton::new("code_actions_indicator", ui::Icon::Bolt).on_click(
+                    |editor: &mut Editor, cx| {
                         editor.toggle_code_actions(
                             &ToggleCodeActions {
                                 deployed_from_indicator: true,
                             },
                             cx,
                         );
-                    })
-                    .into_any(),
+                    },
+                ),
             )
         } else {
             None
@@ -4380,7 +4381,7 @@ impl Editor {
         line_height: Pixels,
         gutter_margin: Pixels,
         cx: &mut ViewContext<Self>,
-    ) -> Vec<Option<AnyElement<Self>>> {
+    ) -> Vec<Option<IconButton<Self>>> {
         fold_data
             .iter()
             .enumerate()
@@ -4392,16 +4393,16 @@ impl Editor {
                                 FoldStatus::Folded => ui::Icon::ChevronRight,
                                 FoldStatus::Foldable => ui::Icon::ChevronDown,
                             };
-                            IconButton::new(ix as usize, icon)
-                                .on_click(move |editor: &mut Editor, cx| match fold_status {
+                            IconButton::new(ix as usize, icon).on_click(
+                                move |editor: &mut Editor, cx| match fold_status {
                                     FoldStatus::Folded => {
                                         editor.unfold_at(&UnfoldAt { buffer_row }, cx);
                                     }
                                     FoldStatus::Foldable => {
                                         editor.fold_at(&FoldAt { buffer_row }, cx);
                                     }
-                                })
-                                .into_any()
+                                },
+                            )
                         })
                     })
                     .flatten()
@@ -7792,7 +7793,7 @@ impl Editor {
                                                     cx.editor_style.diagnostic_style.clone(),
                                             },
                                         )))
-                                        .render_once()
+                                        .render_into_any()
                                 }
                             }),
                             disposition: BlockDisposition::Below,
@@ -9994,7 +9995,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend
                 cx.write_to_clipboard(ClipboardItem::new(message.clone()));
             })
             .tooltip(|_, cx| Tooltip::text("Copy diagnostic message", cx))
-            .render_once()
+            .render_into_any()
     })
 }
 

crates/editor2/src/editor_tests.rs 🔗

@@ -3048,7 +3048,7 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) {
                 position: snapshot.anchor_after(Point::new(2, 0)),
                 disposition: BlockDisposition::Below,
                 height: 1,
-                render: Arc::new(|_| div().render_once()),
+                render: Arc::new(|_| div().into_any()),
             }],
             Some(Autoscroll::fit()),
             cx,

crates/editor2/src/element.rs 🔗

@@ -490,6 +490,7 @@ impl EditorElement {
 
         for (ix, fold_indicator) in layout.fold_indicators.drain(..).enumerate() {
             if let Some(mut fold_indicator) = fold_indicator {
+                let mut fold_indicator = fold_indicator.render_into_any();
                 let available_space = size(
                     AvailableSpace::MinContent,
                     AvailableSpace::Definite(line_height * 0.55),
@@ -509,20 +510,21 @@ impl EditorElement {
             }
         }
 
-        if let Some(mut indicator) = layout.code_actions_indicator.take() {
+        if let Some(indicator) = layout.code_actions_indicator.take() {
+            let mut button = indicator.button.render_into_any();
             let available_space = size(
                 AvailableSpace::MinContent,
                 AvailableSpace::Definite(line_height),
             );
-            let indicator_size = indicator.element.measure(available_space, editor, cx);
+            let indicator_size = button.measure(available_space, editor, cx);
+
             let mut x = Pixels::ZERO;
             let mut y = indicator.row as f32 * line_height - scroll_top;
             // Center indicator.
             x += ((layout.gutter_padding + layout.gutter_margin) - indicator_size.width) / 2.;
             y += (line_height - indicator_size.height) / 2.;
-            indicator
-                .element
-                .draw(bounds.origin + point(x, y), available_space, editor, cx);
+
+            button.draw(bounds.origin + point(x, y), available_space, editor, cx);
         }
     }
 
@@ -1810,7 +1812,7 @@ impl EditorElement {
                     .render_code_actions_indicator(&style, active, cx)
                     .map(|element| CodeActionsIndicator {
                         row: newest_selection_head.row(),
-                        element,
+                        button: element,
                     });
             }
         }
@@ -2041,14 +2043,19 @@ impl EditorElement {
                         // Can't use .and_then() because `.file_name()` and `.parent()` return references :(
                         if let Some(path) = path {
                             filename = path.file_name().map(|f| f.to_string_lossy().to_string());
-                            parent_path =
-                                path.parent().map(|p| p.to_string_lossy().to_string() + "/");
+                            parent_path = path
+                                .parent()
+                                .map(|p| SharedString::from(p.to_string_lossy().to_string() + "/"));
                         }
 
                         h_stack()
                             .size_full()
                             .bg(gpui::red())
-                            .child(filename.unwrap_or_else(|| "untitled".to_string()))
+                            .child(
+                                filename
+                                    .map(SharedString::from)
+                                    .unwrap_or_else(|| "untitled".into()),
+                            )
                             .children(parent_path)
                             .children(jump_icon) // .p_x(gutter_padding)
                     } else {
@@ -2059,7 +2066,7 @@ impl EditorElement {
                             .child("⋯")
                             .children(jump_icon) // .p_x(gutter_padding)
                     };
-                    element.render()
+                    element.into_any()
                 }
             };
 
@@ -2391,10 +2398,6 @@ enum Invisible {
 impl Element<Editor> for EditorElement {
     type State = ();
 
-    fn element_id(&self) -> Option<gpui::ElementId> {
-        Some(self.editor_id.into())
-    }
-
     fn layout(
         &mut self,
         editor: &mut Editor,
@@ -2469,6 +2472,10 @@ impl Element<Editor> for EditorElement {
 impl RenderOnce<Editor> for EditorElement {
     type Element = Self;
 
+    fn element_id(&self) -> Option<gpui::ElementId> {
+        Some(self.editor_id.into())
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -3098,14 +3105,14 @@ pub struct LayoutState {
     context_menu: Option<(DisplayPoint, AnyElement<Editor>)>,
     code_actions_indicator: Option<CodeActionsIndicator>,
     // hover_popovers: Option<(DisplayPoint, Vec<AnyElement<Editor>>)>,
-    fold_indicators: Vec<Option<AnyElement<Editor>>>,
+    fold_indicators: Vec<Option<IconButton<Editor>>>,
     tab_invisible: ShapedLine,
     space_invisible: ShapedLine,
 }
 
 struct CodeActionsIndicator {
     row: u32,
-    element: AnyElement<Editor>,
+    button: IconButton<Editor>,
 }
 
 struct PositionMap {

crates/file_finder2/src/file_finder.rs 🔗

@@ -2,9 +2,8 @@ use collections::HashMap;
 use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
 use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
 use gpui::{
-    actions, div, AppContext, Component, Dismiss, Div, FocusHandle, InteractiveElement,
-    ManagedView, Model, ParentElement, Render, Styled, Task, View, ViewContext, VisualContext,
-    WeakView,
+    actions, div, AppContext, Dismiss, Div, FocusHandle, InteractiveElement, ManagedView, Model,
+    ParentElement, Render, RenderOnce, Styled, Task, View, ViewContext, VisualContext, WeakView,
 };
 use picker::{Picker, PickerDelegate};
 use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
@@ -116,7 +115,7 @@ impl ManagedView for FileFinder {
         self.picker.focus_handle(cx)
     }
 }
-impl Render for FileFinder {
+impl Render<Self> for FileFinder {
     type Element = Div<Self>;
 
     fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {

crates/go_to_line2/src/go_to_line.rs 🔗

@@ -143,7 +143,7 @@ impl GoToLine {
     }
 }
 
-impl Render for GoToLine {
+impl Render<Self> for GoToLine {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/gpui2/src/element.rs 🔗

@@ -14,12 +14,50 @@ pub trait Render<V: 'static>: 'static + Sized {
 pub trait RenderOnce<V: 'static>: Sized {
     type Element: Element<V> + 'static;
 
+    fn element_id(&self) -> Option<ElementId>;
+
     fn render_once(self) -> Self::Element;
 
     fn render_into_any(self) -> AnyElement<V> {
         self.render_once().into_any()
     }
 
+    fn draw<T, R>(
+        self,
+        origin: Point<Pixels>,
+        available_space: Size<T>,
+        view_state: &mut V,
+        cx: &mut ViewContext<V>,
+        f: impl FnOnce(&mut <Self::Element as Element<V>>::State, &mut ViewContext<V>) -> R,
+    ) -> R
+    where
+        T: Clone + Default + Debug + Into<AvailableSpace>,
+    {
+        let element = self.render_once();
+        let element_id = element.element_id();
+        let element = DrawableElement {
+            element: Some(element),
+            phase: ElementDrawPhase::Start,
+        };
+        let frame_state = DrawableElement::draw(
+            element,
+            origin,
+            available_space.map(Into::into),
+            view_state,
+            cx,
+        );
+
+        if let Some(mut frame_state) = frame_state {
+            f(&mut frame_state, cx)
+        } else {
+            cx.with_element_state(element_id.unwrap(), |element_state, cx| {
+                let mut element_state = element_state.unwrap();
+                let result = f(&mut element_state, cx);
+                (result, element_state)
+            })
+        }
+    }
+
     fn map<U>(self, f: impl FnOnce(Self) -> U) -> U
     where
         Self: Sized,
@@ -52,8 +90,6 @@ pub trait RenderOnce<V: 'static>: Sized {
 pub trait Element<V: 'static>: 'static + RenderOnce<V> {
     type State: 'static;
 
-    fn element_id(&self) -> Option<ElementId>;
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -72,35 +108,6 @@ pub trait Element<V: 'static>: 'static + RenderOnce<V> {
     fn into_any(self) -> AnyElement<V> {
         AnyElement::new(self)
     }
-
-    fn draw<T, R>(
-        self,
-        origin: Point<Pixels>,
-        available_space: Size<T>,
-        view_state: &mut V,
-        cx: &mut ViewContext<V>,
-        f: impl FnOnce(&mut Self::State, &mut ViewContext<V>) -> R,
-    ) -> R
-    where
-        T: Clone + Default + Debug + Into<AvailableSpace>,
-    {
-        let element_id = self.element_id();
-        let element = DrawableElement {
-            element: Some(self),
-            phase: ElementDrawPhase::Start,
-        };
-        let frame_state = element.draw(origin, available_space.map(Into::into), view_state, cx);
-
-        if let Some(mut frame_state) = frame_state {
-            f(&mut frame_state, cx)
-        } else {
-            cx.with_element_state(element_id.unwrap(), |element_state, cx| {
-                let mut element_state = element_state.unwrap();
-                let result = f(&mut element_state, cx);
-                (result, element_state)
-            })
-        }
-    }
 }
 
 pub trait Component<V: 'static>: 'static {
@@ -131,10 +138,6 @@ impl<V, C> CompositeElement<V, C> {
 impl<V: 'static, C: Component<V>> Element<V> for CompositeElement<V, C> {
     type State = CompositeElementState<V, C>;
 
-    fn element_id(&self) -> Option<ElementId> {
-        None
-    }
-
     fn layout(
         &mut self,
         view: &mut V,
@@ -174,6 +177,10 @@ impl<V: 'static, C: Component<V>> Element<V> for CompositeElement<V, C> {
 impl<V: 'static, C: Component<V>> RenderOnce<V> for CompositeElement<V, C> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        None
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -231,23 +238,21 @@ pub struct DrawableElement<V: 'static, E: Element<V>> {
 }
 
 #[derive(Default)]
-enum ElementDrawPhase<V> {
+enum ElementDrawPhase<S> {
     #[default]
     Start,
     LayoutRequested {
         layout_id: LayoutId,
-        frame_state: Option<V>,
+        frame_state: Option<S>,
     },
     LayoutComputed {
         layout_id: LayoutId,
         available_space: Size<AvailableSpace>,
-        frame_state: Option<V>,
+        frame_state: Option<S>,
     },
 }
 
-/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
-/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
-/// improved usability.
+/// A wrapper around an implementer of [Element] that allows it to be drawn in a window.
 impl<V, E: Element<V>> DrawableElement<V, E> {
     fn new(element: E) -> Self {
         DrawableElement {
@@ -379,6 +384,41 @@ impl<V, E: Element<V>> DrawableElement<V, E> {
     }
 }
 
+// impl<V: 'static, E: Element<V>> Element<V> for DrawableElement<V, E> {
+//     type State = <E::Element as Element<V>>::State;
+
+//     fn layout(
+//         &mut self,
+//         view_state: &mut V,
+//         element_state: Option<Self::State>,
+//         cx: &mut ViewContext<V>,
+//     ) -> (LayoutId, Self::State) {
+
+//     }
+
+//     fn paint(
+//         self,
+//         bounds: Bounds<Pixels>,
+//         view_state: &mut V,
+//         element_state: &mut Self::State,
+//         cx: &mut ViewContext<V>,
+//     ) {
+//         todo!()
+//     }
+// }
+
+// impl<V: 'static, E: 'static + Element<V>> RenderOnce<V> for DrawableElement<V, E> {
+//     type Element = Self;
+
+//     fn element_id(&self) -> Option<ElementId> {
+//         self.element.as_ref()?.element_id()
+//     }
+
+//     fn render_once(self) -> Self::Element {
+//         self
+//     }
+// }
+
 impl<V, E> ElementObject<V> for Option<DrawableElement<V, E>>
 where
     E: Element<V>,
@@ -476,10 +516,6 @@ impl<V: 'static> AnyElement<V> {
 impl<V: 'static> Element<V> for AnyElement<V> {
     type State = ();
 
-    fn element_id(&self) -> Option<ElementId> {
-        AnyElement::element_id(self)
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -504,6 +540,10 @@ impl<V: 'static> Element<V> for AnyElement<V> {
 impl<V: 'static> RenderOnce<V> for AnyElement<V> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        AnyElement::element_id(self)
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2/src/elements/div.rs 🔗

@@ -602,10 +602,6 @@ impl<V: 'static> ParentElement<V> for Div<V> {
 impl<V: 'static> Element<V> for Div<V> {
     type State = DivState;
 
-    fn element_id(&self) -> Option<ElementId> {
-        self.interactivity.element_id.clone()
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -694,6 +690,10 @@ impl<V: 'static> Element<V> for Div<V> {
 impl<V: 'static> RenderOnce<V> for Div<V> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        self.interactivity.element_id.clone()
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -1293,10 +1293,6 @@ where
 {
     type State = E::State;
 
-    fn element_id(&self) -> Option<ElementId> {
-        self.element.element_id()
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -1324,6 +1320,10 @@ where
 {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        self.element.element_id()
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -1381,10 +1381,6 @@ where
 {
     type State = E::State;
 
-    fn element_id(&self) -> Option<ElementId> {
-        self.element.element_id()
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -1412,6 +1408,10 @@ where
 {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        self.element.element_id()
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2/src/elements/img.rs 🔗

@@ -37,10 +37,6 @@ where
 impl<V> Element<V> for Img<V> {
     type State = InteractiveElementState;
 
-    fn element_id(&self) -> Option<crate::ElementId> {
-        self.interactivity.element_id.clone()
-    }
-
     fn layout(
         &mut self,
         _view_state: &mut V,
@@ -98,6 +94,10 @@ impl<V> Element<V> for Img<V> {
 impl<V: 'static> RenderOnce<V> for Img<V> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<crate::ElementId> {
+        self.interactivity.element_id.clone()
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2/src/elements/overlay.rs 🔗

@@ -60,10 +60,6 @@ impl<V: 'static> ParentElement<V> for Overlay<V> {
 impl<V: 'static> Element<V> for Overlay<V> {
     type State = OverlayState;
 
-    fn element_id(&self) -> Option<crate::ElementId> {
-        None
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -160,6 +156,10 @@ impl<V: 'static> Element<V> for Overlay<V> {
 impl<V: 'static> RenderOnce<V> for Overlay<V> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<crate::ElementId> {
+        None
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2/src/elements/svg.rs 🔗

@@ -26,10 +26,6 @@ impl<V> Svg<V> {
 impl<V> Element<V> for Svg<V> {
     type State = InteractiveElementState;
 
-    fn element_id(&self) -> Option<ElementId> {
-        self.interactivity.element_id.clone()
-    }
-
     fn layout(
         &mut self,
         _view_state: &mut V,
@@ -62,6 +58,10 @@ impl<V> Element<V> for Svg<V> {
 impl<V: 'static> RenderOnce<V> for Svg<V> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        self.interactivity.element_id.clone()
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2/src/elements/text.rs 🔗

@@ -11,10 +11,6 @@ use util::ResultExt;
 impl<V: 'static> Element<V> for &'static str {
     type State = TextState;
 
-    fn element_id(&self) -> Option<ElementId> {
-        None
-    }
-
     fn layout(
         &mut self,
         _: &mut V,
@@ -40,6 +36,10 @@ impl<V: 'static> Element<V> for &'static str {
 impl<V: 'static> RenderOnce<V> for &'static str {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        None
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -48,10 +48,6 @@ impl<V: 'static> RenderOnce<V> for &'static str {
 impl<V: 'static> Element<V> for SharedString {
     type State = TextState;
 
-    fn element_id(&self) -> Option<ElementId> {
-        Some(self.clone().into())
-    }
-
     fn layout(
         &mut self,
         _: &mut V,
@@ -78,6 +74,10 @@ impl<V: 'static> Element<V> for SharedString {
 impl<V: 'static> RenderOnce<V> for SharedString {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        Some(self.clone().into())
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -105,10 +105,6 @@ impl StyledText {
 impl<V: 'static> Element<V> for StyledText {
     type State = TextState;
 
-    fn element_id(&self) -> Option<crate::ElementId> {
-        None
-    }
-
     fn layout(
         &mut self,
         _view: &mut V,
@@ -194,6 +190,10 @@ impl<V: 'static> Element<V> for StyledText {
 impl<V: 'static> RenderOnce<V> for StyledText {
     type Element = Self;
 
+    fn element_id(&self) -> Option<crate::ElementId> {
+        None
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -300,10 +300,6 @@ struct InteractiveTextState {
 impl<V: 'static> Element<V> for InteractiveText {
     type State = InteractiveTextState;
 
-    fn element_id(&self) -> Option<ElementId> {
-        Some(self.id.clone())
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -346,6 +342,10 @@ impl<V: 'static> Element<V> for InteractiveText {
 impl<V: 'static> RenderOnce<V> for InteractiveText {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        Some(self.id.clone())
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2/src/elements/uniform_list.rs 🔗

@@ -104,10 +104,6 @@ pub struct UniformListState {
 impl<V: 'static> Element<V> for UniformList<V> {
     type State = UniformListState;
 
-    fn element_id(&self) -> Option<crate::ElementId> {
-        Some(self.id.clone())
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -255,6 +251,10 @@ impl<V: 'static> Element<V> for UniformList<V> {
 impl<V> RenderOnce<V> for UniformList<V> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<crate::ElementId> {
+        Some(self.id.clone())
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2/src/view.rs 🔗

@@ -208,10 +208,6 @@ impl<V: 'static + Render<V>> From<View<V>> for AnyView {
 impl<V: 'static + Render<V>, ParentV: 'static> Element<ParentV> for View<V> {
     type State = Option<AnyElement<V>>;
 
-    fn element_id(&self) -> Option<ElementId> {
-        Some(self.model.entity_id.into())
-    }
-
     fn layout(
         &mut self,
         _parent_view: &mut ParentV,
@@ -241,6 +237,10 @@ impl<V: 'static + Render<V>, ParentV: 'static> Element<ParentV> for View<V> {
 impl<V: 'static + Render<V>, ParentV: 'static> RenderOnce<ParentV> for View<V> {
     type Element = View<V>;
 
+    fn element_id(&self) -> Option<ElementId> {
+        Some(self.model.entity_id.into())
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -249,10 +249,6 @@ impl<V: 'static + Render<V>, ParentV: 'static> RenderOnce<ParentV> for View<V> {
 impl<V: 'static> Element<V> for AnyView {
     type State = Option<Box<dyn Any>>;
 
-    fn element_id(&self) -> Option<ElementId> {
-        Some(self.model.entity_id.into())
-    }
-
     fn layout(
         &mut self,
         _view_state: &mut V,
@@ -277,6 +273,10 @@ impl<V: 'static> Element<V> for AnyView {
 impl<ParentV: 'static> RenderOnce<ParentV> for AnyView {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        Some(self.model.entity_id.into())
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -334,10 +334,6 @@ where
 {
     type State = Option<AnyElement<V>>;
 
-    fn element_id(&self) -> Option<ElementId> {
-        Some(self.view.entity_id().into())
-    }
-
     fn layout(
         &mut self,
         _: &mut ParentV,
@@ -371,6 +367,10 @@ where
 {
     type Element = Self;
 
+    fn element_id(&self) -> Option<ElementId> {
+        self.element.as_ref().unwrap().element_id()
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }

crates/gpui2_macros/src/derive_render_once.rs 🔗

@@ -33,6 +33,10 @@ pub fn derive_render_once(input: TokenStream) -> TokenStream {
         {
             type Element = gpui::CompositeElement<#view_type, Self>;
 
+            fn element_id(&self) -> Option<ElementId> {
+                None
+            }
+
             fn render_once(self) -> Self::Element {
                 gpui::CompositeElement::new(self)
             }

crates/picker2/src/picker2.rs 🔗

@@ -1,7 +1,7 @@
 use editor::Editor;
 use gpui::{
-    div, prelude::*, uniform_list, AppContext, Component, Div, FocusHandle, FocusableView,
-    MouseButton, Render, Task, UniformListScrollHandle, View, ViewContext, WindowContext,
+    div, prelude::*, uniform_list, AppContext, Div, FocusHandle, FocusableView, MouseButton,
+    Render, Task, UniformListScrollHandle, View, ViewContext, WindowContext,
 };
 use std::{cmp, sync::Arc};
 use ui::{prelude::*, v_stack, Divider, Label, TextColor};
@@ -15,7 +15,7 @@ pub struct Picker<D: PickerDelegate> {
 }
 
 pub trait PickerDelegate: Sized + 'static {
-    type ListItem: Component<Picker<Self>>;
+    type ListItem: RenderOnce<Picker<Self>>;
 
     fn match_count(&self) -> usize;
     fn selected_index(&self) -> usize;
@@ -180,7 +180,7 @@ impl<D: PickerDelegate> Picker<D> {
     }
 }
 
-impl<D: PickerDelegate> Render for Picker<D> {
+impl<D: PickerDelegate> Render<Self> for Picker<D> {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/project_panel2/src/project_panel.rs 🔗

@@ -9,9 +9,9 @@ use file_associations::FileAssociations;
 use anyhow::{anyhow, Result};
 use gpui::{
     actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext,
-    ClipboardItem, Component, Div, EventEmitter, FocusHandle, Focusable, FocusableView,
-    InteractiveElement, Model, MouseButton, ParentElement, Pixels, Point, PromptLevel, Render,
-    Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext,
+    ClipboardItem, Div, EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement,
+    Model, MouseButton, ParentElement, Pixels, Point, PromptLevel, Render, RenderOnce, Stateful,
+    StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View, ViewContext,
     VisualContext as _, WeakView, WindowContext,
 };
 use menu::{Confirm, SelectNext, SelectPrev};
@@ -1423,7 +1423,7 @@ impl ProjectPanel {
     }
 }
 
-impl Render for ProjectPanel {
+impl Render<Self> for ProjectPanel {
     type Element = Focusable<Self, Stateful<Self, Div<Self>>>;
 
     fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> Self::Element {

crates/storybook2/src/stories/colors.rs 🔗

@@ -5,7 +5,7 @@ use ui::prelude::*;
 
 pub struct ColorsStory;
 
-impl Render for ColorsStory {
+impl Render<Self> for ColorsStory {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
@@ -28,7 +28,7 @@ impl Render for ColorsStory {
                                 div()
                                     .w(px(75.))
                                     .line_height(px(24.))
-                                    .child(scale.name().to_string()),
+                                    .child(scale.name().clone()),
                             )
                             .child(
                                 div()

crates/storybook2/src/stories/focus.rs 🔗

@@ -26,7 +26,7 @@ impl FocusStory {
     }
 }
 
-impl Render for FocusStory {
+impl Render<Self> for FocusStory {
     type Element = Focusable<Self, Stateful<Self, Div<Self>>>;
 
     fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {

crates/storybook2/src/stories/kitchen_sink.rs 🔗

@@ -11,7 +11,7 @@ impl KitchenSinkStory {
     }
 }
 
-impl Render for KitchenSinkStory {
+impl Render<Self> for KitchenSinkStory {
     type Element = Stateful<Self, Div<Self>>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/storybook2/src/stories/picker.rs 🔗

@@ -1,5 +1,7 @@
 use fuzzy::StringMatchCandidate;
-use gpui::{div, prelude::*, Div, KeyBinding, Render, Styled, Task, View, WindowContext};
+use gpui::{
+    div, prelude::*, Div, KeyBinding, Render, SharedString, Styled, Task, View, WindowContext,
+};
 use picker::{Picker, PickerDelegate};
 use std::sync::Arc;
 use theme2::ActiveTheme;
@@ -54,7 +56,8 @@ impl PickerDelegate for Delegate {
         let Some(candidate_ix) = self.matches.get(ix) else {
             return div();
         };
-        let candidate = self.candidates[*candidate_ix].string.clone();
+        // TASK: Make StringMatchCandidate::string a SharedString
+        let candidate = SharedString::from(self.candidates[*candidate_ix].string.clone());
 
         div()
             .text_color(colors.text)
@@ -202,7 +205,7 @@ impl PickerStory {
     }
 }
 
-impl Render for PickerStory {
+impl Render<Self> for PickerStory {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {

crates/storybook2/src/stories/scroll.rs 🔗

@@ -10,7 +10,7 @@ impl ScrollStory {
     }
 }
 
-impl Render for ScrollStory {
+impl Render<Self> for ScrollStory {
     type Element = Stateful<Self, Div<Self>>;
 
     fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {

crates/storybook2/src/stories/text.rs 🔗

@@ -1,6 +1,4 @@
-use gpui::{
-    div, white, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext,
-};
+use gpui::{div, white, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext};
 
 pub struct TextStory;
 
@@ -10,7 +8,7 @@ impl TextStory {
     }
 }
 
-impl Render for TextStory {
+impl Render<Self> for TextStory {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {

crates/storybook2/src/stories/z_index.rs 🔗

@@ -1,4 +1,4 @@
-use gpui::{px, rgb, Div, Hsla, Render};
+use gpui::{px, rgb, Div, Hsla, Render, RenderOnce};
 use ui::prelude::*;
 
 use crate::story::Story;
@@ -7,7 +7,7 @@ use crate::story::Story;
 /// [https://developer.mozilla.org/en-US/docs/Web/CSS/z-index](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index).
 pub struct ZIndexStory;
 
-impl Render for ZIndexStory {
+impl Render<Self> for ZIndexStory {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
@@ -79,17 +79,15 @@ trait Styles: Styled + Sized {
 
 impl<V: 'static> Styles for Div<V> {}
 
-// #[derive(RenderOnce)]
+#[derive(RenderOnce)]
 struct ZIndexExample {
     z_index: u32,
 }
 
-impl ZIndexExample {
-    pub fn new(z_index: u32) -> Self {
-        Self { z_index }
-    }
+impl<V: 'static> Component<V> for ZIndexExample {
+    type Rendered = Div<V>;
 
-    fn render<V: 'static>(self, _view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
+    fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
         div()
             .relative()
             .size_full()
@@ -109,14 +107,14 @@ impl ZIndexExample {
                     // HACK: Simulate `text-align: center`.
                     .pl(px(24.))
                     .z_index(self.z_index)
-                    .child(format!(
+                    .child(SharedString::from(format!(
                         "z-index: {}",
                         if self.z_index == 0 {
                             "auto".to_string()
                         } else {
                             self.z_index.to_string()
                         }
-                    )),
+                    ))),
             )
             // Blue blocks.
             .child(
@@ -173,3 +171,9 @@ impl ZIndexExample {
             )
     }
 }
+
+impl ZIndexExample {
+    pub fn new(z_index: u32) -> Self {
+        Self { z_index }
+    }
+}

crates/storybook2/src/storybook2.rs 🔗

@@ -105,7 +105,7 @@ impl StoryWrapper {
     }
 }
 
-impl Render for StoryWrapper {
+impl Render<Self> for StoryWrapper {
     type Element = Div<Self>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {

crates/terminal_view2/src/terminal_panel.rs 🔗

@@ -335,7 +335,7 @@ impl TerminalPanel {
 
 impl EventEmitter<PanelEvent> for TerminalPanel {}
 
-impl Render for TerminalPanel {
+impl Render<Self> for TerminalPanel {
     type Element = Div<Self>;
 
     fn render(&mut self, _cx: &mut ViewContext<Self>) -> Self::Element {

crates/terminal_view2/src/terminal_view.rs 🔗

@@ -9,7 +9,7 @@ pub mod terminal_panel;
 // use crate::terminal_element::TerminalElement;
 use editor::{scroll::autoscroll::Autoscroll, Editor};
 use gpui::{
-    actions, div, img, red, Action, AnyElement, AppContext, Component, DispatchPhase, Div,
+    actions, div, img, red, Action, AnyElement, AppContext, DispatchPhase, Div, Element,
     EventEmitter, FocusEvent, FocusHandle, Focusable, FocusableElement, FocusableView,
     InputHandler, InteractiveElement, KeyDownEvent, Keystroke, Model, MouseButton, ParentElement,
     Pixels, Render, SharedString, Styled, Task, View, ViewContext, VisualContext, WeakView,
@@ -538,7 +538,7 @@ impl TerminalView {
     }
 }
 
-impl Render for TerminalView {
+impl Render<Self> for TerminalView {
     type Element = Focusable<Self, Div<Self>>;
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
@@ -578,7 +578,7 @@ impl Render for TerminalView {
             .children(
                 self.context_menu
                     .clone()
-                    .map(|context_menu| div().z_index(1).absolute().child(context_menu.render())),
+                    .map(|context_menu| div().z_index(1).absolute().child(context_menu)),
             )
             .track_focus(&self.focus_handle)
             .on_focus_in(Self::focus_in)
@@ -756,8 +756,8 @@ impl Item for TerminalView {
 
         div()
             .child(img().uri("icons/terminal.svg").bg(red()))
-            .child(title)
-            .render()
+            .child(SharedString::from(title))
+            .into_any()
     }
 
     fn clone_on_split(

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

@@ -78,7 +78,7 @@ impl Render<Self> for ContextMenu {
 }
 
 pub struct MenuHandle<V: 'static, M: ManagedView> {
-    id: Option<ElementId>,
+    id: ElementId,
     child_builder: Option<Box<dyn FnOnce(bool) -> AnyElement<V> + 'static>>,
     menu_builder: Option<Rc<dyn Fn(&mut V, &mut ViewContext<V>) -> View<M> + 'static>>,
 
@@ -87,11 +87,6 @@ pub struct MenuHandle<V: 'static, M: ManagedView> {
 }
 
 impl<V: 'static, M: ManagedView> MenuHandle<V, M> {
-    pub fn id(mut self, id: impl Into<ElementId>) -> Self {
-        self.id = Some(id.into());
-        self
-    }
-
     pub fn menu(mut self, f: impl Fn(&mut V, &mut ViewContext<V>) -> View<M> + 'static) -> Self {
         self.menu_builder = Some(Rc::new(f));
         self
@@ -116,9 +111,9 @@ impl<V: 'static, M: ManagedView> MenuHandle<V, M> {
     }
 }
 
-pub fn menu_handle<V: 'static, M: ManagedView>() -> MenuHandle<V, M> {
+pub fn menu_handle<V: 'static, M: ManagedView>(id: impl Into<ElementId>) -> MenuHandle<V, M> {
     MenuHandle {
-        id: None,
+        id: id.into(),
         child_builder: None,
         menu_builder: None,
         anchor: None,
@@ -136,10 +131,6 @@ pub struct MenuHandleState<V, M> {
 impl<V: 'static, M: ManagedView> Element<V> for MenuHandle<V, M> {
     type State = MenuHandleState<V, M>;
 
-    fn element_id(&self) -> Option<gpui::ElementId> {
-        Some(self.id.clone().expect("menu_handle must have an id()"))
-    }
-
     fn layout(
         &mut self,
         view_state: &mut V,
@@ -251,6 +242,10 @@ impl<V: 'static, M: ManagedView> Element<V> for MenuHandle<V, M> {
 impl<V: 'static, M: ManagedView> RenderOnce<V> for MenuHandle<V, M> {
     type Element = Self;
 
+    fn element_id(&self) -> Option<gpui::ElementId> {
+        Some(self.id.clone())
+    }
+
     fn render_once(self) -> Self::Element {
         self
     }
@@ -297,8 +292,7 @@ mod stories {
                         .flex_col()
                         .justify_between()
                         .child(
-                            menu_handle()
-                                .id("test2")
+                            menu_handle("test2")
                                 .child(|is_open| {
                                     Label::new(if is_open {
                                         "TOP LEFT"
@@ -309,8 +303,7 @@ mod stories {
                                 .menu(move |_, cx| build_menu(cx, "top left")),
                         )
                         .child(
-                            menu_handle()
-                                .id("test1")
+                            menu_handle("test1")
                                 .child(|is_open| {
                                     Label::new(if is_open {
                                         "BOTTOM LEFT"
@@ -329,8 +322,7 @@ mod stories {
                         .flex_col()
                         .justify_between()
                         .child(
-                            menu_handle()
-                                .id("test3")
+                            menu_handle("test3")
                                 .child(|is_open| {
                                     Label::new(if is_open {
                                         "TOP RIGHT"
@@ -342,8 +334,7 @@ mod stories {
                                 .menu(move |_, cx| build_menu(cx, "top right")),
                         )
                         .child(
-                            menu_handle()
-                                .id("test4")
+                            menu_handle("test4")
                                 .child(|is_open| {
                                     Label::new(if is_open {
                                         "BOTTOM RIGHT"

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

@@ -1,4 +1,4 @@
-use gpui::RenderOnce;
+use gpui::{Div, RenderOnce};
 
 use crate::prelude::*;
 
@@ -7,12 +7,29 @@ enum DividerDirection {
     Vertical,
 }
 
-// #[derive(RenderOnce)]
+#[derive(RenderOnce)]
 pub struct Divider {
     direction: DividerDirection,
     inset: bool,
 }
 
+impl<V: 'static> Component<V> for Divider {
+    type Rendered = Div<V>;
+
+    fn render(self, view: &mut V, cx: &mut ViewContext<V>) -> Self::Rendered {
+        div()
+            .map(|this| match self.direction {
+                DividerDirection::Horizontal => {
+                    this.h_px().w_full().when(self.inset, |this| this.mx_1p5())
+                }
+                DividerDirection::Vertical => {
+                    this.w_px().h_full().when(self.inset, |this| this.my_1p5())
+                }
+            })
+            .bg(cx.theme().colors().border_variant)
+    }
+}
+
 impl Divider {
     pub fn horizontal() -> Self {
         Self {

crates/workspace2/src/dock.rs 🔗

@@ -1,8 +1,8 @@
 use crate::{status_bar::StatusItemView, Axis, Workspace};
 use gpui::{
-    div, px, Action, AnchorCorner, AnyView, AppContext, Component, Div, Entity, EntityId,
-    EventEmitter, FocusHandle, FocusableView, ParentElement, Render, RenderOnce, SharedString,
-    Styled, Subscription, View, ViewContext, VisualContext, WeakView, WindowContext,
+    div, px, Action, AnchorCorner, AnyView, AppContext, Div, Entity, EntityId, EventEmitter,
+    FocusHandle, FocusableView, ParentElement, Render, RenderOnce, SharedString, Styled,
+    Subscription, View, ViewContext, VisualContext, WeakView, WindowContext,
 };
 use schemars::JsonSchema;
 use serde::{Deserialize, Serialize};
@@ -653,8 +653,7 @@ impl Render<Self> for PanelButtons {
                 };
 
                 Some(
-                    menu_handle()
-                        .id(name)
+                    menu_handle(name)
                         .menu(move |_, cx| {
                             cx.build_view(|cx| ContextMenu::new(cx).header("SECTION"))
                         })

crates/workspace2/src/pane.rs 🔗

@@ -7,9 +7,9 @@ use crate::{
 use anyhow::Result;
 use collections::{HashMap, HashSet, VecDeque};
 use gpui::{
-    actions, prelude::*, Action, AppContext, AsyncWindowContext, Component, Div, EntityId,
-    EventEmitter, FocusHandle, Focusable, FocusableView, Model, Pixels, Point, PromptLevel, Render,
-    Task, View, ViewContext, VisualContext, WeakView, WindowContext,
+    actions, prelude::*, Action, AppContext, AsyncWindowContext, Div, EntityId, EventEmitter,
+    FocusHandle, Focusable, FocusableView, Model, Pixels, Point, PromptLevel, Render, Task, View,
+    ViewContext, VisualContext, WeakView, WindowContext,
 };
 use parking_lot::Mutex;
 use project2::{Project, ProjectEntryId, ProjectPath};

crates/workspace2/src/pane_group.rs 🔗

@@ -7,8 +7,7 @@ use db2::sqlez::{
     statement::Statement,
 };
 use gpui::{
-    point, size, AnyElement, AnyWeakView, Bounds, Div, Model, Pixels, Point, RenderOnce, View,
-    ViewContext,
+    point, size, AnyWeakView, Bounds, Div, Model, Pixels, Point, RenderOnce, View, ViewContext,
 };
 use parking_lot::Mutex;
 use project2::Project;

crates/workspace2/src/status_bar.rs 🔗

@@ -2,8 +2,8 @@ use std::any::TypeId;
 
 use crate::{ItemHandle, Pane};
 use gpui::{
-    div, AnyView, Component, Div, ParentElement, Render, RenderOnce, Styled, Subscription, View,
-    ViewContext, WindowContext,
+    div, AnyView, Div, ParentElement, Render, RenderOnce, Styled, Subscription, View, ViewContext,
+    WindowContext,
 };
 use theme2::ActiveTheme;
 use ui::h_stack;