Take an `Into<AnyViewHandle>` in `ChildView::new`

Antonio Scandurra , Nathan Sobo , and Max Brunsfeld created

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

Change summary

crates/chat_panel/src/chat_panel.rs         |  4 
crates/diagnostics/src/diagnostics.rs       |  2 
crates/file_finder/src/file_finder.rs       |  2 
crates/go_to_line/src/go_to_line.rs         |  2 
crates/gpui/src/presenter.rs                | 10 ++-
crates/outline/src/outline.rs               |  2 
crates/theme_selector/src/theme_selector.rs |  2 
crates/workspace/src/pane.rs                |  2 
crates/workspace/src/pane_group.rs          | 65 ++++++++++++----------
crates/workspace/src/sidebar.rs             |  2 
crates/workspace/src/status_bar.rs          | 20 ++++--
crates/workspace/src/workspace.rs           | 12 +--
12 files changed, 69 insertions(+), 56 deletions(-)

Detailed changes

crates/chat_panel/src/chat_panel.rs 🔗

@@ -217,7 +217,7 @@ impl ChatPanel {
         let theme = &self.settings.borrow().theme;
         Flex::column()
             .with_child(
-                Container::new(ChildView::new(self.channel_select.id()).boxed())
+                Container::new(ChildView::new(&self.channel_select).boxed())
                     .with_style(theme.chat_panel.channel_select.container)
                     .boxed(),
             )
@@ -282,7 +282,7 @@ impl ChatPanel {
 
     fn render_input_box(&self) -> ElementBox {
         let theme = &self.settings.borrow().theme;
-        Container::new(ChildView::new(self.input_editor.id()).boxed())
+        Container::new(ChildView::new(&self.input_editor).boxed())
             .with_style(theme.chat_panel.input_editor.container)
             .boxed()
     }

crates/diagnostics/src/diagnostics.rs 🔗

@@ -111,7 +111,7 @@ impl View for ProjectDiagnosticsEditor {
             .with_style(theme.container)
             .boxed()
         } else {
-            ChildView::new(self.editor.id()).boxed()
+            ChildView::new(&self.editor).boxed()
         }
     }
 

crates/file_finder/src/file_finder.rs 🔗

@@ -76,7 +76,7 @@ impl View for FileFinder {
                 Container::new(
                     Flex::new(Axis::Vertical)
                         .with_child(
-                            Container::new(ChildView::new(self.query_editor.id()).boxed())
+                            Container::new(ChildView::new(&self.query_editor).boxed())
                                 .with_style(settings.theme.selector.input_editor.container)
                                 .boxed(),
                         )

crates/go_to_line/src/go_to_line.rs 🔗

@@ -181,7 +181,7 @@ impl View for GoToLine {
                 Container::new(
                     Flex::new(Axis::Vertical)
                         .with_child(
-                            Container::new(ChildView::new(self.line_editor.id()).boxed())
+                            Container::new(ChildView::new(&self.line_editor).boxed())
                                 .with_style(theme.input_editor.container)
                                 .boxed(),
                         )

crates/gpui/src/presenter.rs 🔗

@@ -6,8 +6,8 @@ use crate::{
     json::{self, ToJson},
     platform::Event,
     text_layout::TextLayoutCache,
-    Action, AnyAction, AssetCache, ElementBox, Entity, FontSystem, ModelHandle, ReadModel,
-    ReadView, Scene, View, ViewHandle,
+    Action, AnyAction, AnyViewHandle, AssetCache, ElementBox, Entity, FontSystem, ModelHandle,
+    ReadModel, ReadView, Scene, View, ViewHandle,
 };
 use pathfinder_geometry::vector::{vec2f, Vector2F};
 use serde_json::json;
@@ -462,8 +462,10 @@ pub struct ChildView {
 }
 
 impl ChildView {
-    pub fn new(view_id: usize) -> Self {
-        Self { view_id }
+    pub fn new(view: impl Into<AnyViewHandle>) -> Self {
+        Self {
+            view_id: view.into().id(),
+        }
     }
 }
 

crates/outline/src/outline.rs 🔗

@@ -80,7 +80,7 @@ impl View for OutlineView {
 
         Flex::new(Axis::Vertical)
             .with_child(
-                Container::new(ChildView::new(self.query_editor.id()).boxed())
+                Container::new(ChildView::new(&self.query_editor).boxed())
                     .with_style(settings.theme.selector.input_editor.container)
                     .boxed(),
             )

crates/theme_selector/src/theme_selector.rs 🔗

@@ -299,7 +299,7 @@ impl View for ThemeSelector {
             ConstrainedBox::new(
                 Container::new(
                     Flex::new(Axis::Vertical)
-                        .with_child(ChildView::new(self.query_editor.id()).boxed())
+                        .with_child(ChildView::new(&self.query_editor).boxed())
                         .with_child(Flexible::new(1.0, false, self.render_matches(cx)).boxed())
                         .boxed(),
                 )

crates/workspace/src/pane.rs 🔗

@@ -516,7 +516,7 @@ impl View for Pane {
         if let Some(active_item) = self.active_item() {
             Flex::column()
                 .with_child(self.render_tabs(cx))
-                .with_child(ChildView::new(active_item.id()).flexible(1., true).boxed())
+                .with_child(ChildView::new(active_item).flexible(1., true).boxed())
                 .named("pane")
         } else {
             Empty::new().named("pane")

crates/workspace/src/pane_group.rs 🔗

@@ -1,43 +1,45 @@
 use anyhow::{anyhow, Result};
-use gpui::{elements::*, Axis};
+use gpui::{elements::*, Axis, ViewHandle};
 use theme::Theme;
 
+use crate::Pane;
+
 #[derive(Clone, Debug, Eq, PartialEq)]
 pub struct PaneGroup {
     root: Member,
 }
 
 impl PaneGroup {
-    pub fn new(pane_id: usize) -> Self {
+    pub fn new(pane: ViewHandle<Pane>) -> Self {
         Self {
-            root: Member::Pane(pane_id),
+            root: Member::Pane(pane),
         }
     }
 
     pub fn split(
         &mut self,
-        old_pane_id: usize,
-        new_pane_id: usize,
+        old_pane: &ViewHandle<Pane>,
+        new_pane: &ViewHandle<Pane>,
         direction: SplitDirection,
     ) -> Result<()> {
         match &mut self.root {
-            Member::Pane(pane_id) => {
-                if *pane_id == old_pane_id {
-                    self.root = Member::new_axis(old_pane_id, new_pane_id, direction);
+            Member::Pane(pane) => {
+                if pane == old_pane {
+                    self.root = Member::new_axis(old_pane.clone(), new_pane.clone(), direction);
                     Ok(())
                 } else {
                     Err(anyhow!("Pane not found"))
                 }
             }
-            Member::Axis(axis) => axis.split(old_pane_id, new_pane_id, direction),
+            Member::Axis(axis) => axis.split(old_pane, new_pane, direction),
         }
     }
 
-    pub fn remove(&mut self, pane_id: usize) -> Result<bool> {
+    pub fn remove(&mut self, pane: &ViewHandle<Pane>) -> Result<bool> {
         match &mut self.root {
             Member::Pane(_) => Ok(false),
             Member::Axis(axis) => {
-                if let Some(last_pane) = axis.remove(pane_id)? {
+                if let Some(last_pane) = axis.remove(pane)? {
                     self.root = last_pane;
                 }
                 Ok(true)
@@ -53,11 +55,15 @@ impl PaneGroup {
 #[derive(Clone, Debug, Eq, PartialEq)]
 enum Member {
     Axis(PaneAxis),
-    Pane(usize),
+    Pane(ViewHandle<Pane>),
 }
 
 impl Member {
-    fn new_axis(old_pane_id: usize, new_pane_id: usize, direction: SplitDirection) -> Self {
+    fn new_axis(
+        old_pane: ViewHandle<Pane>,
+        new_pane: ViewHandle<Pane>,
+        direction: SplitDirection,
+    ) -> Self {
         use Axis::*;
         use SplitDirection::*;
 
@@ -67,16 +73,16 @@ impl Member {
         };
 
         let members = match direction {
-            Up | Left => vec![Member::Pane(new_pane_id), Member::Pane(old_pane_id)],
-            Down | Right => vec![Member::Pane(old_pane_id), Member::Pane(new_pane_id)],
+            Up | Left => vec![Member::Pane(new_pane), Member::Pane(old_pane)],
+            Down | Right => vec![Member::Pane(old_pane), Member::Pane(new_pane)],
         };
 
         Member::Axis(PaneAxis { axis, members })
     }
 
-    pub fn render<'a>(&self, theme: &Theme) -> ElementBox {
+    pub fn render(&self, theme: &Theme) -> ElementBox {
         match self {
-            Member::Pane(view_id) => ChildView::new(*view_id).boxed(),
+            Member::Pane(pane) => ChildView::new(pane).boxed(),
             Member::Axis(axis) => axis.render(theme),
         }
     }
@@ -91,8 +97,8 @@ struct PaneAxis {
 impl PaneAxis {
     fn split(
         &mut self,
-        old_pane_id: usize,
-        new_pane_id: usize,
+        old_pane: &ViewHandle<Pane>,
+        new_pane: &ViewHandle<Pane>,
         direction: SplitDirection,
     ) -> Result<()> {
         use SplitDirection::*;
@@ -100,23 +106,24 @@ impl PaneAxis {
         for (idx, member) in self.members.iter_mut().enumerate() {
             match member {
                 Member::Axis(axis) => {
-                    if axis.split(old_pane_id, new_pane_id, direction).is_ok() {
+                    if axis.split(old_pane, new_pane, direction).is_ok() {
                         return Ok(());
                     }
                 }
-                Member::Pane(pane_id) => {
-                    if *pane_id == old_pane_id {
+                Member::Pane(pane) => {
+                    if pane == old_pane {
                         if direction.matches_axis(self.axis) {
                             match direction {
                                 Up | Left => {
-                                    self.members.insert(idx, Member::Pane(new_pane_id));
+                                    self.members.insert(idx, Member::Pane(new_pane.clone()));
                                 }
                                 Down | Right => {
-                                    self.members.insert(idx + 1, Member::Pane(new_pane_id));
+                                    self.members.insert(idx + 1, Member::Pane(new_pane.clone()));
                                 }
                             }
                         } else {
-                            *member = Member::new_axis(old_pane_id, new_pane_id, direction);
+                            *member =
+                                Member::new_axis(old_pane.clone(), new_pane.clone(), direction);
                         }
                         return Ok(());
                     }
@@ -126,13 +133,13 @@ impl PaneAxis {
         Err(anyhow!("Pane not found"))
     }
 
-    fn remove(&mut self, pane_id_to_remove: usize) -> Result<Option<Member>> {
+    fn remove(&mut self, pane_to_remove: &ViewHandle<Pane>) -> Result<Option<Member>> {
         let mut found_pane = false;
         let mut remove_member = None;
         for (idx, member) in self.members.iter_mut().enumerate() {
             match member {
                 Member::Axis(axis) => {
-                    if let Ok(last_pane) = axis.remove(pane_id_to_remove) {
+                    if let Ok(last_pane) = axis.remove(pane_to_remove) {
                         if let Some(last_pane) = last_pane {
                             *member = last_pane;
                         }
@@ -140,8 +147,8 @@ impl PaneAxis {
                         break;
                     }
                 }
-                Member::Pane(pane_id) => {
-                    if *pane_id == pane_id_to_remove {
+                Member::Pane(pane) => {
+                    if pane == pane_to_remove {
                         found_pane = true;
                         remove_member = Some(idx);
                         break;

crates/workspace/src/sidebar.rs 🔗

@@ -136,7 +136,7 @@ impl Sidebar {
 
             container.add_child(
                 Hook::new(
-                    ConstrainedBox::new(ChildView::new(active_item.id()).boxed())
+                    ConstrainedBox::new(ChildView::new(active_item).boxed())
                         .with_max_width(*self.width.borrow())
                         .boxed(),
                 )

crates/workspace/src/status_bar.rs 🔗

@@ -1,7 +1,7 @@
 use crate::{ItemViewHandle, Pane, Settings};
 use gpui::{
-    elements::*, ElementBox, Entity, MutableAppContext, RenderContext, Subscription, View,
-    ViewContext, ViewHandle,
+    elements::*, AnyViewHandle, ElementBox, Entity, MutableAppContext, RenderContext, Subscription,
+    View, ViewContext, ViewHandle,
 };
 use postage::watch;
 
@@ -14,7 +14,7 @@ pub trait StatusItemView: View {
 }
 
 trait StatusItemViewHandle {
-    fn id(&self) -> usize;
+    fn to_any(&self) -> AnyViewHandle;
     fn set_active_pane_item(
         &self,
         active_pane_item: Option<&dyn ItemViewHandle>,
@@ -45,13 +45,13 @@ impl View for StatusBar {
             .with_children(
                 self.left_items
                     .iter()
-                    .map(|i| ChildView::new(i.id()).aligned().boxed()),
+                    .map(|i| ChildView::new(i.as_ref()).aligned().boxed()),
             )
             .with_child(Empty::new().flexible(1., true).boxed())
             .with_children(
                 self.right_items
                     .iter()
-                    .map(|i| ChildView::new(i.id()).aligned().boxed()),
+                    .map(|i| ChildView::new(i.as_ref()).aligned().boxed()),
             )
             .contained()
             .with_style(theme.container)
@@ -111,8 +111,8 @@ impl StatusBar {
 }
 
 impl<T: StatusItemView> StatusItemViewHandle for ViewHandle<T> {
-    fn id(&self) -> usize {
-        self.id()
+    fn to_any(&self) -> AnyViewHandle {
+        self.into()
     }
 
     fn set_active_pane_item(
@@ -125,3 +125,9 @@ impl<T: StatusItemView> StatusItemViewHandle for ViewHandle<T> {
         });
     }
 }
+
+impl Into<AnyViewHandle> for &dyn StatusItemViewHandle {
+    fn into(self) -> AnyViewHandle {
+        self.to_any()
+    }
+}

crates/workspace/src/workspace.rs 🔗

@@ -599,7 +599,7 @@ impl Workspace {
         Workspace {
             modal: None,
             weak_self: cx.weak_handle(),
-            center: PaneGroup::new(pane.id()),
+            center: PaneGroup::new(pane.clone()),
             panes: vec![pane.clone()],
             active_pane: pane.clone(),
             status_bar,
@@ -1048,15 +1048,13 @@ impl Workspace {
                 new_pane.update(cx, |new_pane, cx| new_pane.add_item_view(clone, cx));
             }
         }
-        self.center
-            .split(pane.id(), new_pane.id(), direction)
-            .unwrap();
+        self.center.split(&pane, &new_pane, direction).unwrap();
         cx.notify();
         new_pane
     }
 
     fn remove_pane(&mut self, pane: ViewHandle<Pane>, cx: &mut ViewContext<Self>) {
-        if self.center.remove(pane.id()).unwrap() {
+        if self.center.remove(&pane).unwrap() {
             self.panes.retain(|p| p != &pane);
             self.activate_pane(self.panes.last().unwrap().clone(), cx);
         }
@@ -1287,7 +1285,7 @@ impl View for Workspace {
                                     Flexible::new(1., true, self.center.render(&settings.theme))
                                         .boxed(),
                                 )
-                                .with_child(ChildView::new(self.status_bar.id()).boxed())
+                                .with_child(ChildView::new(&self.status_bar).boxed())
                                 .flexible(1., true)
                                 .boxed(),
                         );
@@ -1298,7 +1296,7 @@ impl View for Workspace {
                         content.add_child(self.right_sidebar.render(&settings, cx));
                         content.boxed()
                     })
-                    .with_children(self.modal.as_ref().map(|m| ChildView::new(m.id()).boxed()))
+                    .with_children(self.modal.as_ref().map(|m| ChildView::new(m).boxed()))
                     .flexible(1.0, true)
                     .boxed(),
             )