WIP

Mikayla Maki created

Change summary

crates/workspace/src/adjustable_flex.rs | 83 ++++++++++++++++++++++++++
crates/workspace/src/dock.rs            |  3 
crates/workspace/src/pane_group.rs      | 84 +++++++++++++++++---------
crates/workspace/src/workspace.rs       |  5 -
4 files changed, 140 insertions(+), 35 deletions(-)

Detailed changes

crates/workspace/src/adjustable_flex.rs 🔗

@@ -0,0 +1,83 @@
+use gpui::{Element, View, Axis, AnyElement};
+
+// Model for the center group: AdjustableGroup of AdjustableGroups
+// Implementation notes
+// - These have two representations: Exact pixel widths and ratios of elements compared to whole space
+// - We have a constraint of minimum sizes for things.
+//   - If The space is smaller than allowed, things run off the edge
+// - When doing Drag resize, we update the pixel width representation, causing a recalc of the ratios
+//   - If dragging past minimum, take space from next item, until out of space
+// - When doing a reflow (e.g. layout) we read off the ratios and calculate pixels from that
+// - When adding / removing items in an Adjustable flex, reset to default ratios (1:1)
+// - By default, every item takes up as much space as possible
+//
+
+
+struct AdjustableFlex<V: View> {
+    axis: Axis,
+    handle_size: f32,
+    items: Vec<(AnyElement<V>, f32)>
+}
+
+impl<V: View> AdjustableFlex<V> {
+    fn new(axis: Axis) -> Self {
+        AdjustableFlex {
+            axis,
+            handle_size: 2.,
+            items: Vec::new(),
+        }
+    }
+
+    fn add_item()
+}
+
+impl<V: View> Element<V> for AdjustableFlex<V> {
+    type LayoutState = ();
+
+    type PaintState = ();
+
+    fn layout(
+        &mut self,
+        constraint: gpui::SizeConstraint,
+        view: &mut V,
+        cx: &mut gpui::LayoutContext<V>,
+    ) -> (gpui::geometry::vector::Vector2F, Self::LayoutState) {
+        todo!()
+    }
+
+    fn paint(
+        &mut self,
+        scene: &mut gpui::SceneBuilder,
+        bounds: gpui::geometry::rect::RectF,
+        visible_bounds: gpui::geometry::rect::RectF,
+        layout: &mut Self::LayoutState,
+        view: &mut V,
+        cx: &mut gpui::ViewContext<V>,
+    ) -> Self::PaintState {
+        todo!()
+    }
+
+    fn rect_for_text_range(
+        &self,
+        range_utf16: std::ops::Range<usize>,
+        bounds: gpui::geometry::rect::RectF,
+        visible_bounds: gpui::geometry::rect::RectF,
+        layout: &Self::LayoutState,
+        paint: &Self::PaintState,
+        view: &V,
+        cx: &gpui::ViewContext<V>,
+    ) -> Option<gpui::geometry::rect::RectF> {
+        todo!()
+    }
+
+    fn debug(
+        &self,
+        bounds: gpui::geometry::rect::RectF,
+        layout: &Self::LayoutState,
+        paint: &Self::PaintState,
+        view: &V,
+        cx: &gpui::ViewContext<V>,
+    ) -> serde_json::Value {
+        todo!()
+    }
+}

crates/workspace/src/dock.rs 🔗

@@ -408,6 +408,9 @@ impl View for Dock {
     }
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
+
+
+
         if let Some(active_entry) = self.visible_entry() {
             let style = self.style(cx);
             ChildView::new(active_entry.panel.as_any(), cx)

crates/workspace/src/pane_group.rs 🔗

@@ -9,6 +9,7 @@ use gpui::{
     platform::{CursorStyle, MouseButton},
     AnyViewHandle, Axis, Border, ModelHandle, ViewContext, ViewHandle,
 };
+use itertools::Itertools;
 use project::Project;
 use serde::Deserialize;
 use theme::Theme;
@@ -385,40 +386,61 @@ impl PaneAxis {
         app_state: &Arc<AppState>,
         cx: &mut ViewContext<Workspace>,
     ) -> AnyElement<Workspace> {
-        let last_member_ix = self.members.len() - 1;
-        Flex::new(self.axis)
-            .with_children(self.members.iter().enumerate().map(|(ix, member)| {
-                let mut flex = 1.0;
-                if member.contains(active_pane) {
-                    flex = settings::get::<WorkspaceSettings>(cx).active_pane_magnification;
-                }
+        let mut flex_container = Flex::new(self.axis);
 
-                let mut member = member.render(
-                    project,
-                    theme,
-                    follower_state,
-                    active_call,
-                    active_pane,
-                    zoomed,
-                    app_state,
-                    cx,
-                );
-                if ix < last_member_ix {
-                    let mut border = theme.workspace.pane_divider;
-                    border.left = false;
-                    border.right = false;
-                    border.top = false;
-                    border.bottom = false;
-                    match self.axis {
-                        Axis::Vertical => border.bottom = true,
-                        Axis::Horizontal => border.right = true,
-                    }
-                    member = member.contained().with_border(border).into_any();
+        let mut members = self.members.iter().enumerate().peekable();
+        while let Some((ix, member)) = members.next() {
+            let last = members.peek().is_none();
+
+            let mut flex = 1.0;
+            if member.contains(active_pane) {
+                flex = settings::get::<WorkspaceSettings>(cx).active_pane_magnification;
+            }
+
+            let mut member = member.render(
+                project,
+                theme,
+                follower_state,
+                active_call,
+                active_pane,
+                zoomed,
+                app_state,
+                cx,
+            );
+            if !last {
+                let mut border = theme.workspace.pane_divider;
+                border.left = false;
+                border.right = false;
+                border.top = false;
+                border.bottom = false;
+
+                match self.axis {
+                    Axis::Vertical => border.bottom = true,
+                    Axis::Horizontal => border.right = true,
                 }
 
-                FlexItem::new(member).flex(flex, true)
-            }))
-            .into_any()
+                let side = match self.axis {
+                    Axis::Horizontal => HandleSide::Right,
+                    Axis::Vertical => HandleSide::Bottom,
+                };
+
+                member = member.contained().with_border(border)
+                    .resizable(side, 1., |workspace, size, cx| {
+                        dbg!("resize", size);
+                    })
+                    .into_any();
+
+
+            }
+
+            flex_container = flex_container.with_child(
+                FlexItem::new(member)
+                    .flex(flex, true)
+                    .into_any()
+            );
+        }
+
+        flex_container.into_any()
     }
 }
 

crates/workspace/src/workspace.rs 🔗

@@ -1,13 +1,10 @@
 pub mod dock;
-/// NOTE: Focus only 'takes' after an update has flushed_effects.
-///
-/// This may cause issues when you're trying to write tests that use workspace focus to add items at
-/// specific locations.
 pub mod item;
 pub mod notifications;
 pub mod pane;
 pub mod pane_group;
 mod persistence;
+mod adjustable_flex;
 pub mod searchable;
 pub mod shared_screen;
 mod status_bar;