diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index 8d95465388..bed99d6cc4 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -587,14 +587,16 @@ mod element { use std::{cell::RefCell, ops::Range, rc::Rc}; use gpui::{ + elements::MouseEventHandler, geometry::{ rect::RectF, vector::{vec2f, Vector2F}, }, json::{self, ToJson}, platform::{CursorStyle, MouseButton}, - AnyElement, Axis, CursorRegion, Element, LayoutContext, MouseRegion, RectFExt, - SceneBuilder, SizeConstraint, Vector2FExt, ViewContext, + scene::MouseDrag, + AnyElement, Axis, CursorRegion, Element, EventContext, LayoutContext, MouseRegion, + RectFExt, SceneBuilder, SizeConstraint, Vector2FExt, ViewContext, }; use crate::{ @@ -682,6 +684,90 @@ mod element { *cross_axis_max = cross_axis_max.max(child_size.along(cross_axis)); } } + + fn handle_resize( + flexes: Rc>>, + axis: Axis, + ix: usize, + child_start: Vector2F, + drag_bounds: RectF, + ) -> impl Fn(MouseDrag, &mut Workspace, &mut EventContext) { + let size = move |ix, flexes: &[f32]| { + drag_bounds.length_along(axis) * (flexes[ix] / flexes.len() as f32) + }; + + move |drag, workspace: &mut Workspace, cx| { + let min_size = match axis { + Axis::Horizontal => HORIZONTAL_MIN_SIZE, + Axis::Vertical => VERTICAL_MIN_SIZE, + }; + let mut flexes = flexes.borrow_mut(); + + // Don't allow resizing to less than the minimum size, if elements are already too small + if min_size - 1. > size(ix, flexes.as_slice()) { + return; + } + + let mut current_target_size = (drag.position - child_start).along(axis); + + let mut proposed_current_pixel_change = + current_target_size - size(ix, flexes.as_slice()); + + let flex_changes = |pixel_dx, target_ix, flexes: &[f32]| { + let flex_change = pixel_dx / drag_bounds.length_along(axis); + let current_target_flex = flexes[target_ix] + flex_change; + let next_target_flex = flexes[target_ix + 1] - flex_change; + (current_target_flex, next_target_flex) + }; + + if proposed_current_pixel_change < 0. { + current_target_size = f32::max(current_target_size, min_size); + let current_pixel_change = current_target_size - size(ix, flexes.as_slice()); + + let (current_target_flex, next_target_flex) = + flex_changes(current_pixel_change, ix, flexes.as_slice()); + + flexes[ix] = current_target_flex; + flexes[ix + 1] = next_target_flex; + } else if proposed_current_pixel_change > 0. { + let mut ix_offset = 0; + while proposed_current_pixel_change > 0.01 && ix + 1 + ix_offset < flexes.len() + { + let next_target_size = f32::max( + size(ix + 1, flexes.as_slice()) - proposed_current_pixel_change, + min_size, + ); + + current_target_size = f32::min( + current_target_size, + size(ix, flexes.as_slice()) + size(ix + 1, flexes.as_slice()) + - next_target_size, + ); + + let current_pixel_change = + current_target_size - size(ix, flexes.as_slice()); + + let (current_target_flex, next_target_flex) = + flex_changes(current_pixel_change, ix, flexes.as_slice()); + + flexes[ix_offset + ix] = current_target_flex; + flexes[ix_offset + ix + 1] = next_target_flex; + + dbg!( + current_pixel_change, + proposed_current_pixel_change, + proposed_current_pixel_change - current_pixel_change + ); + proposed_current_pixel_change -= current_pixel_change; + ix_offset += 1; + } + dbg!("done"); + } + + workspace.schedule_serialize(cx); + cx.notify(); + } + } } impl Extend> for PaneAxisElement { @@ -780,11 +866,6 @@ mod element { let mut bounding_boxes = self.bounding_boxes.borrow_mut(); bounding_boxes.clear(); - let sizes = self - .children - .iter() - .map(|child| child.size()) - .collect::>(); let mut children_iter = self.children.iter_mut().enumerate().peekable(); while let Some((ix, child)) = children_iter.next() { let child_start = child_origin.clone(); @@ -826,8 +907,6 @@ mod element { style, }); - let axis = self.axis; - let drag_bounds = visible_bounds.clone(); enum ResizeHandle {} let mut mouse_region = MouseRegion::new::( cx.view_id(), @@ -835,75 +914,16 @@ mod element { handle_bounds, ); mouse_region = mouse_region - .on_drag(MouseButton::Left, { - let flexes = self.flexes.clone(); - let sizes = sizes.clone(); - move |drag, workspace: &mut Workspace, cx| { - let min_size = match axis { - Axis::Horizontal => HORIZONTAL_MIN_SIZE, - Axis::Vertical => VERTICAL_MIN_SIZE, - }; - // Don't allow resizing to less than the minimum size, if elements are already too small - if min_size - 1. > sizes[ix].along(axis) { - return; - } - - let mut flexes = flexes.borrow_mut(); - - let mut current_target_size = - (drag.position - child_start).along(axis); - - let mut proposed_current_pixel_change = - current_target_size - sizes[ix].along(axis); - - let flex_changes = |target_size, target_ix| { - let current_pixel_change = target_size - sizes[ix].along(axis); - let flex_change = - current_pixel_change / drag_bounds.length_along(axis); - let current_target_flex = flexes[target_ix] + flex_change; - let next_target_flex = flexes[target_ix + 1] - flex_change; - (current_target_flex, next_target_flex) - }; - - if proposed_current_pixel_change < 0. { - current_target_size = f32::max(current_target_size, min_size); - let (current_target_flex, next_target_flex) = - flex_changes(current_target_size, ix); - - *flexes.get_mut(ix).unwrap() = current_target_flex; - *flexes.get_mut(ix + 1).unwrap() = next_target_flex; - } else if proposed_current_pixel_change > 0. { - let mut next_target_size = f32::max( - sizes[ix + 1].along(axis) - proposed_current_pixel_change, - min_size, - ); - - current_target_size = f32::min( - current_target_size, - sizes[ix].along(axis) + sizes[ix + 1].along(axis) - - next_target_size, - ); - - let (current_target_flex, next_target_flex) = - flex_changes(current_target_size, ix); - - // TODO: make this into a loop - *flexes.get_mut(ix).unwrap() = current_target_flex; - *flexes.get_mut(ix + 1).unwrap() = next_target_flex; - - // let mut ix_offset = 0; - - // while proposed_current_pixel_change > 0. - // && ix + 1 + ix_offset < flexes.len() - // { - - // } - } - - workspace.schedule_serialize(cx); - cx.notify(); - } - }) + .on_drag( + MouseButton::Left, + Self::handle_resize( + self.flexes.clone(), + self.axis, + ix, + child_start, + visible_bounds.clone(), + ), + ) .on_click(MouseButton::Left, { let flexes = self.flexes.clone(); move |e, v: &mut Workspace, cx| {