workspace: Reset all configured dock panels (#62552)
Closes #57388. When a dock is listed in `resize_all_panels_in_dock`, reset its compatible panels to the active panel's default size. This applies to the reset actions and resize-handle double-clicks. Docks not listed in the setting continue to reset only the active panel. Adds regression coverage for fixed panels with different defaults, flexible panels, and active-panel-only resets. Release Notes: - Fixed dock size reset commands only resetting the active panel when `resize_all_panels_in_dock` is enabled. --------- Co-authored-by: dino <dinojoaocosta@gmail.com>
This commit is contained in:
1 parent
29202c1ab5
commit
33b0b39e40
2 files changed
+314
-53
No files matched your search
@@ -546,6 +546,11 @@ impl Dock {
|
||||
.and_then(|index| self.panel_entries.get(index))
|
||||
}
|
||||
|
||||
fn active_panel_entry_mut(&mut self) -> Option<&mut PanelEntry> {
|
||||
self.active_panel_index
|
||||
.and_then(|index| self.panel_entries.get_mut(index))
|
||||
}
|
||||
|
||||
pub fn active_panel_index(&self) -> Option<usize> {
|
||||
self.active_panel_index
|
||||
}
|
||||
@@ -999,18 +1004,17 @@ impl Dock {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn resize_active_panel(
|
||||
fn resize_active_panel(
|
||||
&mut self,
|
||||
size: Option<Pixels>,
|
||||
flex: Option<f32>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if let Some(index) = self.active_panel_index
|
||||
&& let Some(entry) = self.panel_entries.get_mut(index)
|
||||
{
|
||||
let position = self.position;
|
||||
if let Some(entry) = self.active_panel_entry_mut() {
|
||||
let (panel_key, size_state) =
|
||||
resize_panel_entry(self.position, entry, size, flex, window, cx);
|
||||
resize_panel_entry(position, entry, size, flex, window, cx);
|
||||
|
||||
let workspace = self.workspace.clone();
|
||||
cx.defer(move |cx| {
|
||||
@@ -1024,7 +1028,54 @@ impl Dock {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resize_all_panels(
|
||||
/// Resizes the active panel and, when this dock is included in
|
||||
/// `resize_all_panels_in_dock`, all panels using the same sizing mode.
|
||||
pub fn resize_panel_sizes(
|
||||
&mut self,
|
||||
size: Option<Pixels>,
|
||||
flex: Option<f32>,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
if self.should_resize_all_panels(cx) {
|
||||
self.resize_all_panels(size, flex, window, cx);
|
||||
} else {
|
||||
self.resize_active_panel(size, flex, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
/// Resets the active panel and, when this dock is included in
|
||||
/// `resize_all_panels_in_dock`, all panels using the same sizing mode.
|
||||
pub fn reset_panel_sizes(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.should_resize_all_panels(cx) {
|
||||
self.reset_all_panel_sizes(window, cx);
|
||||
} else {
|
||||
self.reset_active_panel_size(window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_active_panel_size(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let state = PanelSizeState::default();
|
||||
self.resize_active_panel(state.size, state.flex, window, cx);
|
||||
}
|
||||
|
||||
fn reset_all_panel_sizes(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let Some(active_entry) = self.active_panel_entry() else {
|
||||
return;
|
||||
};
|
||||
let size =
|
||||
(!panel_uses_flexible_width(self.position, active_entry.panel.as_ref(), window, cx))
|
||||
.then(|| active_entry.panel.default_size(window, cx));
|
||||
self.resize_all_panels(size, None, window, cx);
|
||||
}
|
||||
|
||||
fn should_resize_all_panels(&self, cx: &App) -> bool {
|
||||
WorkspaceSettings::get_global(cx)
|
||||
.resize_all_panels_in_dock
|
||||
.contains(&self.position)
|
||||
}
|
||||
|
||||
fn resize_all_panels(
|
||||
&mut self,
|
||||
size: Option<Pixels>,
|
||||
flex: Option<f32>,
|
||||
@@ -1151,7 +1202,7 @@ impl Render for Dock {
|
||||
MouseButton::Left,
|
||||
cx.listener(|dock, e: &MouseUpEvent, window, cx| {
|
||||
if e.click_count == 2 {
|
||||
dock.resize_active_panel(None, None, window, cx);
|
||||
dock.reset_panel_sizes(window, cx);
|
||||
dock.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
workspace.serialize_workspace(window, cx);
|
||||
|
||||
@@ -7716,34 +7716,19 @@ impl Workspace {
|
||||
))
|
||||
.on_action(cx.listener(
|
||||
|workspace: &mut Workspace, _: &ResetActiveDockSize, window, cx| {
|
||||
for dock in workspace.all_docks() {
|
||||
if dock.focus_handle(cx).contains_focused(window, cx) {
|
||||
let panel = dock.read(cx).active_panel().cloned();
|
||||
if let Some(panel) = panel {
|
||||
dock.update(cx, |dock, cx| {
|
||||
dock.set_panel_size_state(
|
||||
panel.as_ref(),
|
||||
dock::PanelSizeState::default(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
if let Some(dock) = workspace.active_dock(window, cx).cloned() {
|
||||
dock.update(cx, |dock, cx| {
|
||||
dock.reset_panel_sizes(window, cx);
|
||||
});
|
||||
}
|
||||
},
|
||||
))
|
||||
.on_action(cx.listener(
|
||||
|workspace: &mut Workspace, _: &ResetOpenDocksSize, _window, cx| {
|
||||
|workspace: &mut Workspace, _: &ResetOpenDocksSize, window, cx| {
|
||||
for dock in workspace.all_docks() {
|
||||
let panel = dock.read(cx).visible_panel().cloned();
|
||||
if let Some(panel) = panel {
|
||||
if dock.read(cx).visible_panel().is_some() {
|
||||
dock.update(cx, |dock, cx| {
|
||||
dock.set_panel_size_state(
|
||||
panel.as_ref(),
|
||||
dock::PanelSizeState::default(),
|
||||
cx,
|
||||
);
|
||||
dock.reset_panel_sizes(window, cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -8456,14 +8441,7 @@ impl Workspace {
|
||||
|
||||
let flex_grow = self.dock_flex_for_size(DockPosition::Left, size, window, cx);
|
||||
self.left_dock.update(cx, |left_dock, cx| {
|
||||
if WorkspaceSettings::get_global(cx)
|
||||
.resize_all_panels_in_dock
|
||||
.contains(&DockPosition::Left)
|
||||
{
|
||||
left_dock.resize_all_panels(Some(size), flex_grow, window, cx);
|
||||
} else {
|
||||
left_dock.resize_active_panel(Some(size), flex_grow, window, cx);
|
||||
}
|
||||
left_dock.resize_panel_sizes(Some(size), flex_grow, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8480,28 +8458,14 @@ impl Workspace {
|
||||
});
|
||||
let flex_grow = self.dock_flex_for_size(DockPosition::Right, size, window, cx);
|
||||
self.right_dock.update(cx, |right_dock, cx| {
|
||||
if WorkspaceSettings::get_global(cx)
|
||||
.resize_all_panels_in_dock
|
||||
.contains(&DockPosition::Right)
|
||||
{
|
||||
right_dock.resize_all_panels(Some(size), flex_grow, window, cx);
|
||||
} else {
|
||||
right_dock.resize_active_panel(Some(size), flex_grow, window, cx);
|
||||
}
|
||||
right_dock.resize_panel_sizes(Some(size), flex_grow, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
fn resize_bottom_dock(&mut self, new_size: Pixels, window: &mut Window, cx: &mut App) {
|
||||
let size = new_size.min(self.bounds.bottom() - RESIZE_HANDLE_SIZE - self.bounds.top());
|
||||
self.bottom_dock.update(cx, |bottom_dock, cx| {
|
||||
if WorkspaceSettings::get_global(cx)
|
||||
.resize_all_panels_in_dock
|
||||
.contains(&DockPosition::Bottom)
|
||||
{
|
||||
bottom_dock.resize_all_panels(Some(size), None, window, cx);
|
||||
} else {
|
||||
bottom_dock.resize_active_panel(Some(size), None, window, cx);
|
||||
}
|
||||
bottom_dock.resize_panel_sizes(Some(size), None, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -14663,6 +14627,252 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_reset_all_panel_sizes_in_dock(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx);
|
||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.update_user_settings(cx, |settings| {
|
||||
settings.workspace.resize_all_panels_in_dock =
|
||||
Some(vec![settings::DockPosition::Left]);
|
||||
});
|
||||
});
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let (multi_workspace, cx) =
|
||||
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project, window, cx));
|
||||
let workspace =
|
||||
multi_workspace.read_with(cx, |multi_workspace, _| multi_workspace.workspace().clone());
|
||||
|
||||
let (first_panel, second_panel) = workspace.update_in(cx, |workspace, window, cx| {
|
||||
let first_panel = cx.new(|cx| {
|
||||
let mut panel = TestPanel::new(DockPosition::Left, 100, cx);
|
||||
panel.default_size = px(350.);
|
||||
panel
|
||||
});
|
||||
let second_panel = cx.new(|cx| {
|
||||
let mut panel = TestPanel::new(DockPosition::Left, 200, cx);
|
||||
panel.default_size = px(500.);
|
||||
panel
|
||||
});
|
||||
workspace.add_panel(first_panel.clone(), window, cx);
|
||||
workspace.add_panel(second_panel.clone(), window, cx);
|
||||
workspace.left_dock().update(cx, |dock, cx| {
|
||||
dock.activate_panel(0, window, cx);
|
||||
dock.set_open(true, window, cx);
|
||||
});
|
||||
workspace.resize_left_dock(px(400.), window, cx);
|
||||
(first_panel, second_panel)
|
||||
});
|
||||
|
||||
cx.dispatch_action(ResetOpenDocksSize);
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let dock = workspace.left_dock().read(cx);
|
||||
let first_panel_size = dock.stored_panel_size(&first_panel, window, cx);
|
||||
let second_panel_size = dock.stored_panel_size(&second_panel, window, cx);
|
||||
|
||||
assert_eq!(first_panel_size, Some(px(350.)));
|
||||
assert_eq!(second_panel_size, Some(px(350.)));
|
||||
});
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.left_dock().update(cx, |dock, cx| {
|
||||
dock.activate_panel(1, window, cx);
|
||||
});
|
||||
workspace.resize_left_dock(px(450.), window, cx);
|
||||
});
|
||||
cx.dispatch_action(ResetOpenDocksSize);
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let dock = workspace.left_dock().read(cx);
|
||||
let first_panel_size = dock.stored_panel_size(&first_panel, window, cx);
|
||||
let second_panel_size = dock.stored_panel_size(&second_panel, window, cx);
|
||||
|
||||
assert_eq!(first_panel_size, Some(px(500.)));
|
||||
assert_eq!(second_panel_size, Some(px(500.)));
|
||||
});
|
||||
|
||||
first_panel.update(cx, |panel, _| panel.flexible = true);
|
||||
second_panel.update(cx, |panel, _| panel.flexible = true);
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.resize_left_dock(px(350.), window, cx);
|
||||
workspace.left_dock().update(cx, |dock, cx| {
|
||||
dock.reset_panel_sizes(window, cx);
|
||||
});
|
||||
let dock = workspace.left_dock().read(cx);
|
||||
let first_panel_flex = dock
|
||||
.stored_panel_size_state(&first_panel)
|
||||
.and_then(|state| state.flex);
|
||||
let second_panel_flex = dock
|
||||
.stored_panel_size_state(&second_panel)
|
||||
.and_then(|state| state.flex);
|
||||
|
||||
assert_eq!(
|
||||
workspace.dock_size(&dock, window, cx),
|
||||
Some(workspace.bounds.size.width / 2.)
|
||||
);
|
||||
assert!(first_panel_flex.is_none());
|
||||
assert!(second_panel_flex.is_none());
|
||||
});
|
||||
|
||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.update_user_settings(cx, |settings| {
|
||||
settings.workspace.resize_all_panels_in_dock = Some(Vec::new());
|
||||
});
|
||||
});
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
first_panel.update(cx, |panel, _| panel.flexible = false);
|
||||
second_panel.update(cx, |panel, _| panel.flexible = false);
|
||||
workspace.left_dock().update(cx, |dock, cx| {
|
||||
dock.activate_panel(0, window, cx);
|
||||
});
|
||||
workspace.resize_left_dock(px(400.), window, cx);
|
||||
workspace.left_dock().update(cx, |dock, cx| {
|
||||
dock.reset_panel_sizes(window, cx);
|
||||
});
|
||||
|
||||
let dock = workspace.left_dock().read(cx);
|
||||
let first_panel_size = dock.stored_panel_size(&first_panel, window, cx);
|
||||
let second_panel_size = dock.stored_panel_size(&second_panel, window, cx);
|
||||
|
||||
assert_eq!(first_panel_size, Some(px(350.)));
|
||||
assert_eq!(second_panel_size, Some(px(500.)));
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_reset_panel_mixed_modes(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx);
|
||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.update_user_settings(cx, |settings| {
|
||||
settings.workspace.resize_all_panels_in_dock =
|
||||
Some(vec![settings::DockPosition::Left]);
|
||||
});
|
||||
});
|
||||
|
||||
let fs = FakeFs::new(cx.executor());
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let (multi_workspace, cx) =
|
||||
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project, window, cx));
|
||||
let workspace =
|
||||
multi_workspace.read_with(cx, |multi_workspace, _| multi_workspace.workspace().clone());
|
||||
|
||||
// Create 4 panels, 2 with fixed width and another 2 with flexible width
|
||||
// so that we can later confirm that updating a flexible width panel
|
||||
// only affects other flexible panels, and the same with fixed width
|
||||
// panels.
|
||||
let (fixed_panel_a, fixed_panel_b, flexible_panel_a, flexible_panel_b) = workspace
|
||||
.update_in(cx, |workspace, window, cx| {
|
||||
let fixed_panel_a = cx.new(|cx| {
|
||||
let mut panel = TestPanel::new(DockPosition::Left, 100, cx);
|
||||
panel.default_size = px(350.);
|
||||
panel
|
||||
});
|
||||
|
||||
let fixed_panel_b = cx.new(|cx| {
|
||||
let mut panel = TestPanel::new(DockPosition::Left, 200, cx);
|
||||
panel.default_size = px(375.);
|
||||
panel
|
||||
});
|
||||
|
||||
let flexible_panel_a =
|
||||
cx.new(|cx| TestPanel::new_flexible(DockPosition::Left, 300, cx));
|
||||
|
||||
let flexible_panel_b =
|
||||
cx.new(|cx| TestPanel::new_flexible(DockPosition::Left, 400, cx));
|
||||
|
||||
workspace.add_panel(fixed_panel_a.clone(), window, cx);
|
||||
workspace.add_panel(fixed_panel_b.clone(), window, cx);
|
||||
workspace.add_panel(flexible_panel_a.clone(), window, cx);
|
||||
workspace.add_panel(flexible_panel_b.clone(), window, cx);
|
||||
|
||||
(
|
||||
fixed_panel_a,
|
||||
fixed_panel_b,
|
||||
flexible_panel_a,
|
||||
flexible_panel_b,
|
||||
)
|
||||
});
|
||||
|
||||
// We'll start by activating one of the flexible panels and ensuring
|
||||
// that resizing the dock will sync the state between the flexible
|
||||
// panels.
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.left_dock().update(cx, |dock, cx| {
|
||||
dock.activate_panel(2, window, cx);
|
||||
dock.set_open(true, window, cx);
|
||||
});
|
||||
|
||||
workspace.resize_left_dock(px(450.0), window, cx);
|
||||
|
||||
let dock = workspace.left_dock().read(cx);
|
||||
let fixed_panel_a_size = dock.stored_panel_size(&fixed_panel_a, window, cx);
|
||||
let fixed_panel_b_size = dock.stored_panel_size(&fixed_panel_b, window, cx);
|
||||
let flexible_panel_a_flex = dock
|
||||
.stored_panel_size_state(&flexible_panel_a)
|
||||
.and_then(|state| state.flex);
|
||||
let flexible_panel_b_flex = dock
|
||||
.stored_panel_size_state(&flexible_panel_b)
|
||||
.and_then(|state| state.flex);
|
||||
|
||||
assert_eq!(fixed_panel_a_size, Some(px(350.)));
|
||||
assert_eq!(fixed_panel_b_size, Some(px(375.)));
|
||||
assert!(flexible_panel_a_flex.is_some());
|
||||
assert_eq!(flexible_panel_a_flex, flexible_panel_b_flex);
|
||||
});
|
||||
|
||||
// Resetting the active panel's size should continue syncing the state
|
||||
// between flexible width panels but not affect fixed width panels.
|
||||
cx.dispatch_action(ResetOpenDocksSize);
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let dock = workspace.left_dock().read(cx);
|
||||
let fixed_panel_a_size = dock.stored_panel_size(&fixed_panel_a, window, cx);
|
||||
let fixed_panel_b_size = dock.stored_panel_size(&fixed_panel_b, window, cx);
|
||||
let flexible_panel_a_flex = dock
|
||||
.stored_panel_size_state(&flexible_panel_a)
|
||||
.and_then(|state| state.flex);
|
||||
let flexible_panel_b_flex = dock
|
||||
.stored_panel_size_state(&flexible_panel_b)
|
||||
.and_then(|state| state.flex);
|
||||
|
||||
assert_eq!(fixed_panel_a_size, Some(px(350.)));
|
||||
assert_eq!(fixed_panel_b_size, Some(px(375.)));
|
||||
assert_eq!(flexible_panel_a_flex, None);
|
||||
assert_eq!(flexible_panel_b_flex, None);
|
||||
});
|
||||
|
||||
// Lastly, activate a fixed width panel and ensure that resetting its
|
||||
// size will affect all other fixed width panels.
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
workspace.left_dock().update(cx, |dock, cx| {
|
||||
dock.activate_panel(0, window, cx);
|
||||
});
|
||||
|
||||
workspace.resize_left_dock(px(450.), window, cx);
|
||||
});
|
||||
|
||||
cx.dispatch_action(ResetOpenDocksSize);
|
||||
|
||||
workspace.update_in(cx, |workspace, window, cx| {
|
||||
let dock = workspace.left_dock().read(cx);
|
||||
let fixed_panel_a_size = dock.stored_panel_size(&fixed_panel_a, window, cx);
|
||||
let fixed_panel_b_size = dock.stored_panel_size(&fixed_panel_b, window, cx);
|
||||
let flexible_panel_a_flex = dock
|
||||
.stored_panel_size_state(&flexible_panel_a)
|
||||
.and_then(|state| state.flex);
|
||||
let flexible_panel_b_flex = dock
|
||||
.stored_panel_size_state(&flexible_panel_b)
|
||||
.and_then(|state| state.flex);
|
||||
|
||||
assert_eq!(fixed_panel_a_size, Some(px(350.)));
|
||||
assert_eq!(fixed_panel_b_size, Some(px(350.)));
|
||||
assert_eq!(flexible_panel_a_flex, None);
|
||||
assert_eq!(flexible_panel_b_flex, None);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_flexible_panel_left_dock_sizing(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx);
|
||||
|
||||
Reference in new issue
Block a user