mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-10 04:09:37 +00:00
WIP: iron out bugs in interaction between toggle and toggle focus key bindings
co-authored-by: max <max@zed.dev>
This commit is contained in:
parent
9c9af5ed94
commit
5065804388
1 changed files with 122 additions and 21 deletions
|
@ -478,6 +478,7 @@ pub struct Workspace {
|
|||
remote_entity_subscription: Option<client::Subscription>,
|
||||
modal: Option<AnyViewHandle>,
|
||||
zoomed: Option<AnyWeakViewHandle>,
|
||||
zoomed_position: Option<DockPosition>,
|
||||
center: PaneGroup,
|
||||
left_dock: ViewHandle<Dock>,
|
||||
bottom_dock: ViewHandle<Dock>,
|
||||
|
@ -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<Self>,
|
||||
) {
|
||||
pub fn toggle_dock(&mut self, dock_side: DockPosition, cx: &mut ViewContext<Self>) {
|
||||
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<T: Panel>(&mut self, cx: &mut ViewContext<Self>) {
|
||||
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::<T>() {
|
||||
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<Self>,
|
||||
) {
|
||||
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::<ZoomBackground>(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());
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue