From 506580438803a2ef050c40351a0841596f6b4952 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Tue, 30 May 2023 14:55:49 -0700 Subject: [PATCH] WIP: iron out bugs in interaction between toggle and toggle focus key bindings co-authored-by: max --- crates/workspace/src/workspace.rs | 143 +++++++++++++++++++++++++----- 1 file changed, 122 insertions(+), 21 deletions(-) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 657285388a..53240a9a73 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -478,6 +478,7 @@ pub struct Workspace { remote_entity_subscription: Option, modal: Option, zoomed: Option, + zoomed_position: Option, center: PaneGroup, left_dock: ViewHandle, bottom_dock: ViewHandle, @@ -683,6 +684,7 @@ impl Workspace { weak_self: weak_handle.clone(), modal: None, zoomed: None, + zoomed_position: None, center: PaneGroup::new(center_pane.clone()), panes: vec![center_pane.clone()], panes_by_item: Default::default(), @@ -885,6 +887,11 @@ impl Workspace { .map_or(false, |active_panel| active_panel.id() == panel.id()); dock.remove_panel(&panel, cx); }); + + if panel.is_zoomed(cx) { + this.zoomed_position = Some(new_position); + } + dock = match panel.read(cx).position(cx) { DockPosition::Left => &this.left_dock, DockPosition::Bottom => &this.bottom_dock, @@ -903,14 +910,17 @@ impl Workspace { dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx)); if panel.has_focus(cx) { this.zoomed = Some(panel.downgrade().into_any()); + this.zoomed_position = Some(panel.read(cx).position(cx)); } } else if T::should_zoom_out_on_event(event) { this.zoom_out(cx); } else if T::is_focus_event(event) { if panel.is_zoomed(cx) { this.zoomed = Some(panel.downgrade().into_any()); + this.zoomed_position = Some(panel.read(cx).position(cx)); } else { this.zoomed = None; + this.zoomed_position = None; } cx.notify(); } @@ -1573,33 +1583,36 @@ impl Workspace { } } - pub fn toggle_dock( - &mut self, - dock_side: DockPosition, - cx: &mut ViewContext, - ) { + pub fn toggle_dock(&mut self, dock_side: DockPosition, cx: &mut ViewContext) { let dock = match dock_side { DockPosition::Left => &self.left_dock, DockPosition::Bottom => &self.bottom_dock, DockPosition::Right => &self.right_dock, }; - let focus_center = dock.update(cx, |dock, cx| { - let was_open = dock.is_open(); - dock.set_open(!was_open, cx); + let mut focus_center = false; + let mut zoom_out = false; + dock.update(cx, |dock, cx| { + let other_is_zoomed = self.zoomed.is_some() && self.zoomed_position != Some(dock_side); + let was_visible = dock.is_open() && !other_is_zoomed; + dock.set_open(!was_visible, cx); if let Some(active_panel) = dock.active_panel() { - if was_open { + if was_visible { if active_panel.has_focus(cx) { - return true; + focus_center = true; } - } else if active_panel.is_zoomed(cx) { - cx.focus(active_panel.as_any()); + } else { + if active_panel.is_zoomed(cx) { + cx.focus(active_panel.as_any()); + } + zoom_out = true; } } - - false }); + if zoom_out { + self.zoom_out_everything_except(dock_side, cx); + } if focus_center { cx.focus_self(); } @@ -1646,9 +1659,24 @@ impl Workspace { } pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { - for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { + for (dock, position) in [ + self.left_dock.clone(), + self.bottom_dock.clone(), + self.right_dock.clone(), + ] + .into_iter() + .zip( + [ + DockPosition::Left, + DockPosition::Bottom, + DockPosition::Right, + ] + .into_iter(), + ) { if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { - let focus_center = dock.update(cx, |dock, cx| { + let mut focus_center = false; + let mut zoom_out = false; + dock.update(cx, |dock, cx| { dock.activate_panel(panel_index, cx); if let Some(panel) = dock.active_panel().cloned() { @@ -1656,15 +1684,18 @@ impl Workspace { if panel.is_zoomed(cx) { dock.set_open(false, cx); } - return true + focus_center = true; } else { dock.set_open(true, cx); cx.focus(panel.as_any()); + zoom_out = true; } } - false }); + if zoom_out { + self.zoom_out_everything_except(position, cx); + } if focus_center { cx.focus_self(); } @@ -1685,6 +1716,36 @@ impl Workspace { self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx)); self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx)); self.zoomed = None; + self.zoomed_position = None; + + cx.notify(); + } + + fn zoom_out_everything_except( + &mut self, + except_position: DockPosition, + cx: &mut ViewContext, + ) { + for pane in &self.panes { + pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); + } + + if except_position != DockPosition::Left { + self.left_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + } + + if except_position != DockPosition::Bottom { + self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + } + + if except_position != DockPosition::Right { + self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + } + + if self.zoomed_position != Some(except_position) { + self.zoomed = None; + self.zoomed_position = None; + } cx.notify(); } @@ -1901,6 +1962,7 @@ impl Workspace { } else { self.zoomed = None; } + self.zoomed_position = None; self.update_followers( proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView { @@ -1960,6 +2022,7 @@ impl Workspace { pane.update(cx, |pane, cx| pane.set_zoomed(true, cx)); if pane.read(cx).has_focus() { self.zoomed = Some(pane.downgrade().into_any()); + self.zoomed_position = None; } cx.notify(); } @@ -3234,13 +3297,38 @@ impl View for Workspace { .with_children(self.zoomed.as_ref().and_then(|zoomed| { enum ZoomBackground {} let zoomed = zoomed.upgrade(cx)?; + + let mut background_style = + theme.workspace.zoomed_background; + match self.zoomed_position { + Some(DockPosition::Left) => { + background_style.padding.left = 0.; + background_style.padding.top = 0.; + background_style.padding.bottom = 0.; + background_style.padding.right *= 1.; + } + Some(DockPosition::Right) => { + background_style.padding.right = 0.; + background_style.padding.top = 0.; + background_style.padding.bottom = 0.; + background_style.padding.left *= 1.; + } + Some(DockPosition::Bottom) => { + background_style.padding.left = 0.; + background_style.padding.right = 0.; + background_style.padding.bottom = 0.; + background_style.padding.top *= 1.; + } + None => {} + } + Some( ChildView::new(&zoomed, cx) .contained() .with_style(theme.workspace.zoomed_foreground) .aligned() .contained() - .with_style(theme.workspace.zoomed_background) + .with_style(background_style) .mouse::(0) .capture_all() .on_down( @@ -4436,6 +4524,14 @@ mod tests { panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomIn)); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Left)); + }); + + // Move panel to another dock while it is zoomed + panel_1.update(cx, |panel, cx| panel.set_position(DockPosition::Right, cx)); + workspace.read_with(cx, |workspace, _| { + assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); }); // If focus is transferred to another view that's not a panel or another pane, we still show @@ -4444,12 +4540,14 @@ mod tests { focus_receiver.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); }); // If focus is transferred elsewhere in the workspace, the panel is no longer zoomed. workspace.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, None); + assert_eq!(workspace.zoomed_position, None); }); // If focus is transferred again to another view that's not a panel or a pane, we won't @@ -4457,18 +4555,21 @@ mod tests { focus_receiver.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, None); + assert_eq!(workspace.zoomed_position, None); }); // When focus is transferred back to the panel, it is zoomed again. panel_1.update(cx, |_, cx| cx.focus_self()); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); + assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); }); // Emitting a ZoomOut event unzooms the panel. panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomOut)); workspace.read_with(cx, |workspace, _| { assert_eq!(workspace.zoomed, None); + assert_eq!(workspace.zoomed_position, None); }); // Emit closed event on panel 1, which is active @@ -4476,8 +4577,8 @@ mod tests { // Now the left dock is closed, because panel_1 was the active panel workspace.read_with(cx, |workspace, cx| { - let left_dock = workspace.left_dock(); - assert!(!left_dock.read(cx).is_open()); + let right_dock = workspace.right_dock(); + assert!(!right_dock.read(cx).is_open()); }); }