diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index ac52c8f179..a4b71fa5a7 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -175,6 +175,10 @@ impl Dock { } } + pub fn position(&self) -> DockPosition { + self.position + } + pub fn is_open(&self) -> bool { self.is_open } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index d051f6d80a..d721997053 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -908,18 +908,24 @@ impl Workspace { } }); } else if T::should_zoom_in_on_event(event) { - this.zoom_out(cx); 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); + dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, false, cx)); + if this.zoomed_position == Some(prev_position) { + this.zoomed = None; + this.zoomed_position = None; + } + cx.notify(); } else if T::is_focus_event(event) { + let position = panel.read(cx).position(cx); + this.dismiss_zoomed_items_to_reveal(Some(position), cx); if panel.is_zoomed(cx) { this.zoomed = Some(panel.downgrade().into_any()); - this.zoomed_position = Some(panel.read(cx).position(cx)); + this.zoomed_position = Some(position); } else { this.zoomed = None; this.zoomed_position = None; @@ -1592,7 +1598,7 @@ impl Workspace { DockPosition::Right => &self.right_dock, }; let mut focus_center = false; - let mut zoom_out = false; + let mut reveal_dock = 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; @@ -1607,14 +1613,15 @@ impl Workspace { if active_panel.is_zoomed(cx) { cx.focus(active_panel.as_any()); } - zoom_out = true; + reveal_dock = true; } } }); - if zoom_out { - self.zoom_out_everything_except(dock_side, cx); + if reveal_dock { + self.dismiss_zoomed_items_to_reveal(Some(dock_side), cx); } + if focus_center { cx.focus_self(); } @@ -1623,62 +1630,49 @@ impl Workspace { self.serialize_workspace(cx); } + /// Transfer focus to the panel of the given type. pub fn focus_panel(&mut self, cx: &mut ViewContext) -> Option> { - self.show_or_hide_panel::(cx, |_, _| true)? + self.focus_or_unfocus_panel::(cx, |_, _| true)? .as_any() .clone() .downcast() } + /// Focus the panel of the given type if it isn't already focused. If it is + /// already focused, then transfer focus back to the workspace center. pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { - self.show_or_hide_panel::(cx, |panel, cx| !panel.has_focus(cx)); + self.focus_or_unfocus_panel::(cx, |panel, cx| !panel.has_focus(cx)); } - fn show_or_hide_panel( + /// Focus or unfocus the given panel type, depending on the given callback. + fn focus_or_unfocus_panel( &mut self, cx: &mut ViewContext, - show: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool, + should_focus: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool, ) -> Option> { - 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(), - ) { + for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { let mut focus_center = false; - let mut zoom_out = false; + let mut reveal_dock = false; let panel = dock.update(cx, |dock, cx| { dock.activate_panel(panel_index, cx); let panel = dock.active_panel().cloned(); if let Some(panel) = panel.as_ref() { - let should_show = show(&**panel, cx); - if should_show { + if should_focus(&**panel, cx) { dock.set_open(true, cx); cx.focus(panel.as_any()); - zoom_out = true; + reveal_dock = true; } else { - if panel.is_zoomed(cx) { - dock.set_open(false, cx); - } + // if panel.is_zoomed(cx) { + // dock.set_open(false, cx); + // } focus_center = true; } } panel }); - if zoom_out { - self.zoom_out_everything_except(position, cx); - } if focus_center { cx.focus_self(); } @@ -1705,28 +1699,38 @@ impl Workspace { cx.notify(); } - fn zoom_out_everything_except( + fn dismiss_zoomed_items_to_reveal( &mut self, - except_position: DockPosition, + except_position: Option, cx: &mut ViewContext, ) { - for pane in &self.panes { - pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); + // If a center pane is zoomed, unzoom it. + if except_position.is_some() { + 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 another dock is zoomed, hide it. + let mut focus_center = false; + for dock in [&self.left_dock, &self.right_dock, &self.bottom_dock] { + dock.update(cx, |dock, cx| { + if Some(dock.position()) != except_position { + if let Some(panel) = dock.active_panel() { + if panel.is_zoomed(cx) { + focus_center |= panel.has_focus(cx); + dock.set_open(false, cx); + } + } + } + }); } - if except_position != DockPosition::Bottom { - self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx)); + if focus_center { + cx.focus_self(); } - if except_position != DockPosition::Right { - self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx)); - } - - if self.zoomed_position != Some(except_position) { + if self.zoomed_position != except_position { self.zoomed = None; self.zoomed_position = None; } @@ -1937,6 +1941,7 @@ impl Workspace { self.last_active_center_pane = Some(pane.downgrade()); } + self.dismiss_zoomed_items_to_reveal(None, cx); if pane.read(cx).is_zoomed() { self.zoomed = Some(pane.downgrade().into_any()); } else { @@ -1998,7 +2003,6 @@ impl Workspace { } pane::Event::ZoomIn => { if pane == self.active_pane { - self.zoom_out(cx); pane.update(cx, |pane, cx| pane.set_zoomed(true, cx)); if pane.read(cx).has_focus() { self.zoomed = Some(pane.downgrade().into_any()); @@ -2007,7 +2011,13 @@ impl Workspace { cx.notify(); } } - pane::Event::ZoomOut => self.zoom_out(cx), + pane::Event::ZoomOut => { + pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); + if self.zoomed_position.is_none() { + self.zoomed = None; + } + cx.notify(); + } } self.serialize_workspace(cx);