Add the math for pane resizing

This commit is contained in:
Mikayla Maki 2023-07-12 22:34:33 -07:00
parent 5385ca411b
commit 26b9be628e
No known key found for this signature in database
5 changed files with 103 additions and 41 deletions

View file

@ -1268,6 +1268,19 @@ impl Vector2FExt for Vector2F {
} }
} }
pub trait RectFExt {
fn length_along(self, axis: Axis) -> f32;
}
impl RectFExt for RectF {
fn length_along(self, axis: Axis) -> f32 {
match axis {
Axis::Horizontal => self.width(),
Axis::Vertical => self.height(),
}
}
}
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct SizeConstraint { pub struct SizeConstraint {
pub min: Vector2F, pub min: Vector2F,

View file

@ -27,7 +27,7 @@ pub mod json;
pub mod keymap_matcher; pub mod keymap_matcher;
pub mod platform; pub mod platform;
pub use gpui_macros::{test, Element}; pub use gpui_macros::{test, Element};
pub use window::{Axis, SizeConstraint, Vector2FExt, WindowContext}; pub use window::{Axis, RectFExt, SizeConstraint, Vector2FExt, WindowContext};
pub use anyhow; pub use anyhow;
pub use serde_json; pub use serde_json;

View file

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

View file

@ -308,10 +308,19 @@ impl Member {
pub(crate) struct PaneAxis { pub(crate) struct PaneAxis {
pub axis: Axis, pub axis: Axis,
pub members: Vec<Member>, pub members: Vec<Member>,
pub ratios: Rc<RefCell<Vec<f32>>>, ratios: Rc<RefCell<Vec<f32>>>,
} }
impl PaneAxis { impl PaneAxis {
pub fn new(axis: Axis, members: Vec<Member>) -> Self {
let ratios = Rc::new(RefCell::new(vec![1.; members.len()]));
Self {
axis,
members,
ratios,
}
}
fn split( fn split(
&mut self, &mut self,
old_pane: &ViewHandle<Pane>, old_pane: &ViewHandle<Pane>,
@ -397,20 +406,24 @@ impl PaneAxis {
cx: &mut ViewContext<Workspace>, cx: &mut ViewContext<Workspace>,
) -> AnyElement<Workspace> { ) -> AnyElement<Workspace> {
let ratios = self.ratios.clone(); let ratios = self.ratios.clone();
let mut flex_container = AdjustableGroupElement::new(self.axis, 2., basis, move |new_flexes| { let mut flex_container =
let mut borrow = ratios.borrow_mut(); AdjustableGroupElement::new(self.axis, 2., basis, move |new_flexes, _, cx| {
borrow.extend(new_flexes); let mut borrow = ratios.borrow_mut();
borrow.truncate(10); for (ix, flex) in new_flexes {
dbg!(borrow); if let Some(el) = borrow.get_mut(ix) {
}); *el = flex;
}
}
cx.notify();
});
let ratios_borrow = self.ratios.borrow();
let next_basis = basis + self.members.len(); let next_basis = basis + self.members.len();
let mut members = self.members.iter().enumerate().peekable(); let mut members = self.members.iter().zip(ratios_borrow.iter()).peekable();
while let Some((_ix, member)) = members.next() { while let Some((member, flex)) = members.next() {
let last = members.peek().is_none(); let last = members.peek().is_none();
let mut flex = 1.0;
// TODO: Include minimum sizes
// TODO: Restore this // TODO: Restore this
// if member.contains(active_pane) { // if member.contains(active_pane) {
// flex = settings::get::<WorkspaceSettings>(cx).active_pane_magnification; // flex = settings::get::<WorkspaceSettings>(cx).active_pane_magnification;
@ -439,16 +452,11 @@ impl PaneAxis {
Axis::Horizontal => border.right = true, Axis::Horizontal => border.right = true,
} }
let side = match self.axis {
Axis::Horizontal => HandleSide::Right,
Axis::Vertical => HandleSide::Bottom,
};
member = member.contained().with_border(border).into_any(); member = member.contained().with_border(border).into_any();
} }
flex_container = flex_container =
flex_container.with_child(AdjustableGroupItem::new(member, flex).into_any()); flex_container.with_child(AdjustableGroupItem::new(member, *flex).into_any());
} }
flex_container.into_any() flex_container.into_any()
@ -520,10 +528,11 @@ mod adjustable_group {
}, },
json::{self, ToJson}, json::{self, ToJson},
platform::{CursorStyle, MouseButton}, platform::{CursorStyle, MouseButton},
AnyElement, Axis, CursorRegion, Element, LayoutContext, MouseRegion, Quad, SceneBuilder, AnyElement, Axis, CursorRegion, Element, EventContext, LayoutContext, MouseRegion, Quad,
SizeConstraint, Vector2FExt, View, ViewContext, RectFExt, SceneBuilder, SizeConstraint, Vector2FExt, View, ViewContext,
}; };
use serde_json::Value; use serde_json::Value;
use smallvec::SmallVec;
struct AdjustableFlexData { struct AdjustableFlexData {
flex: f32, flex: f32,
@ -533,7 +542,7 @@ mod adjustable_group {
axis: Axis, axis: Axis,
handle_size: f32, handle_size: f32,
basis: usize, basis: usize,
callback: Rc<dyn Fn(Vec<f32>)>, callback: Rc<dyn Fn(SmallVec<[(usize, f32); 2]>, &mut V, &mut EventContext<V>)>,
children: Vec<AnyElement<V>>, children: Vec<AnyElement<V>>,
} }
@ -542,7 +551,7 @@ mod adjustable_group {
axis: Axis, axis: Axis,
handle_size: f32, handle_size: f32,
basis: usize, basis: usize,
callback: impl Fn(Vec<f32>) + 'static, callback: impl Fn(SmallVec<[(usize, f32); 2]>, &mut V, &mut EventContext<V>) + 'static,
) -> Self { ) -> Self {
Self { Self {
axis, axis,
@ -676,8 +685,9 @@ mod adjustable_group {
let mut child_origin = bounds.origin(); let mut child_origin = bounds.origin();
let last_ix = self.children.len() - 1; let mut children_iter = self.children.iter_mut().enumerate().peekable();
for (ix, child) in self.children.iter_mut().enumerate() { while let Some((ix, child)) = children_iter.next() {
let child_start = child_origin.clone();
child.paint(scene, child_origin, visible_bounds, view, cx); child.paint(scene, child_origin, visible_bounds, view, cx);
match self.axis { match self.axis {
@ -685,7 +695,7 @@ mod adjustable_group {
Axis::Vertical => child_origin += vec2f(0.0, child.size().y()), Axis::Vertical => child_origin += vec2f(0.0, child.size().y()),
} }
if ix != last_ix { if let Some((next_ix, next_child)) = children_iter.peek() {
let bounds = match self.axis { let bounds = match self.axis {
Axis::Horizontal => RectF::new( Axis::Horizontal => RectF::new(
child_origin, child_origin,
@ -710,20 +720,66 @@ mod adjustable_group {
scene.push_cursor_region(CursorRegion { bounds, style }); scene.push_cursor_region(CursorRegion { bounds, style });
enum ResizeHandle {}
let callback = self.callback.clone(); let callback = self.callback.clone();
let axis = self.axis; let axis = self.axis;
let child_size = child.size();
let next_child_size = next_child.size();
let mut drag_bounds = visible_bounds.clone();
// Unsure why this should be needed....
drag_bounds.set_origin_y(0.);
let current_flex = child.metadata::<AdjustableFlexData>().unwrap().flex;
let next_flex = next_child.metadata::<AdjustableFlexData>().unwrap().flex;
let next_ix = *next_ix;
const HORIZONTAL_MIN_SIZE: f32 = 80.;
const VERTICAL_MIN_SIZE: f32 = 100.;
enum ResizeHandle {}
let mut mouse_region = let mut mouse_region =
MouseRegion::new::<ResizeHandle>(cx.view_id(), self.basis + ix, bounds); MouseRegion::new::<ResizeHandle>(cx.view_id(), self.basis + ix, bounds);
mouse_region = mouse_region =
mouse_region.on_drag(MouseButton::Left, move |drag, v: &mut V, cx| { mouse_region.on_drag(MouseButton::Left, move |drag, v: &mut V, cx| {
dbg!(drag); let min_size = match axis {
callback({ Axis::Horizontal => HORIZONTAL_MIN_SIZE,
match axis { Axis::Vertical => VERTICAL_MIN_SIZE,
Axis::Horizontal => vec![0., 1., 2.], };
Axis::Vertical => vec![3., 2., 1.], // Don't allow resizing to less than the minimum size, if elements are already too small
} if min_size - 1. > child_size.along(axis)
}) || min_size - 1. > next_child_size.along(axis)
{
return;
}
let flex_position = drag.position - drag_bounds.origin();
let mut current_target_size = (flex_position - child_start).along(axis);
let proposed_current_pixel_change =
current_target_size - child_size.along(axis);
if proposed_current_pixel_change < 0. {
current_target_size = current_target_size.max(min_size);
} else if proposed_current_pixel_change > 0. {
// TODO: cascade this size change down, collect into a vec
let next_target_size = (next_child_size.along(axis)
- proposed_current_pixel_change)
.max(min_size);
current_target_size = current_target_size.min(
child_size.along(axis) + next_child_size.along(axis)
- next_target_size,
);
}
let current_pixel_change = current_target_size - child_size.along(axis);
let flex_change = current_pixel_change / drag_bounds.length_along(axis);
let current_target_flex = current_flex + flex_change;
let next_target_flex = next_flex - flex_change;
callback(
smallvec::smallvec![
(ix, current_target_flex),
(next_ix, next_target_flex),
],
v,
cx,
)
}); });
scene.push_mouse_region(mouse_region); scene.push_mouse_region(mouse_region);

View file

@ -184,11 +184,7 @@ impl SerializedPaneGroup {
} }
Some(( Some((
Member::Axis(PaneAxis { Member::Axis(PaneAxis::new(*axis, members)),
axis: *axis,
members,
ratios: Default::default()
}),
current_active_pane, current_active_pane,
items, items,
)) ))