Add the ability to resize sidebar items

Antonio Scandurra created

Change summary

zed/src/workspace.rs         | 16 ++-------
zed/src/workspace/sidebar.rs | 59 +++++++++++++++++++++++++++++++++----
2 files changed, 56 insertions(+), 19 deletions(-)

Detailed changes

zed/src/workspace.rs 🔗

@@ -960,20 +960,12 @@ impl View for Workspace {
                             .with_child({
                                 let mut content = Flex::row();
                                 content.add_child(self.left_sidebar.render(&settings, cx));
-                                if let Some(panel) = self.left_sidebar.active_item() {
-                                    content.add_child(
-                                        ConstrainedBox::new(ChildView::new(panel.id()).boxed())
-                                            .with_width(300.0)
-                                            .named("left panel"),
-                                    );
+                                if let Some(element) = self.left_sidebar.render_active_item(cx) {
+                                    content.add_child(element);
                                 }
                                 content.add_child(Expanded::new(1.0, self.center.render()).boxed());
-                                if let Some(panel) = self.right_sidebar.active_item() {
-                                    content.add_child(
-                                        ConstrainedBox::new(ChildView::new(panel.id()).boxed())
-                                            .with_width(300.0)
-                                            .named("right panel"),
-                                    );
+                                if let Some(element) = self.right_sidebar.render_active_item(cx) {
+                                    content.add_child(element);
                                 }
                                 content.add_child(self.right_sidebar.render(&settings, cx));
                                 content.boxed()

zed/src/workspace/sidebar.rs 🔗

@@ -1,16 +1,12 @@
 use crate::Settings;
-use gpui::{
-    action,
-    elements::{
-        Align, ConstrainedBox, Container, Flex, MouseEventHandler, ParentElement as _, Svg,
-    },
-    AnyViewHandle, AppContext, Element as _, ElementBox,
-};
+use gpui::{action, color::Color, elements::*, AnyViewHandle, AppContext, Border};
+use std::{cell::RefCell, rc::Rc};
 
 pub struct Sidebar {
     side: Side,
     items: Vec<Item>,
     active_item_ix: Option<usize>,
+    width: Rc<RefCell<f32>>,
 }
 
 #[derive(Clone, Copy)]
@@ -38,6 +34,7 @@ impl Sidebar {
             side,
             items: Default::default(),
             active_item_ix: None,
+            width: Rc::new(RefCell::new(100.)),
         }
     }
 
@@ -100,4 +97,52 @@ impl Sidebar {
         .with_style(&settings.theme.workspace.sidebar)
         .boxed()
     }
+
+    pub fn render_active_item(&self, cx: &AppContext) -> Option<ElementBox> {
+        if let Some(active_item) = self.active_item() {
+            let mut container = Flex::row();
+            if matches!(self.side, Side::Right) {
+                container.add_child(self.render_resize_handle(cx));
+            }
+            container.add_child(
+                ConstrainedBox::new(ChildView::new(active_item.id()).boxed())
+                    .with_width(*self.width.borrow())
+                    .boxed(),
+            );
+            if matches!(self.side, Side::Left) {
+                container.add_child(self.render_resize_handle(cx));
+            }
+            Some(container.boxed())
+        } else {
+            None
+        }
+    }
+
+    fn render_resize_handle(&self, cx: &AppContext) -> ElementBox {
+        let width = self.width.clone();
+        let side = self.side;
+        MouseEventHandler::new::<Self, _>(self.side.id(), cx, |_| {
+            Container::new(Empty::new().boxed())
+                .with_border(Border::left(3., Color::white()))
+                .boxed()
+        })
+        .on_drag(move |delta, cx| {
+            match side {
+                Side::Left => *width.borrow_mut() += delta.x(),
+                Side::Right => *width.borrow_mut() -= delta.x(),
+            }
+
+            cx.notify();
+        })
+        .boxed()
+    }
+}
+
+impl Side {
+    fn id(self) -> usize {
+        match self {
+            Side::Left => 0,
+            Side::Right => 1,
+        }
+    }
 }