mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-10 12:19:28 +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>,
|
remote_entity_subscription: Option<client::Subscription>,
|
||||||
modal: Option<AnyViewHandle>,
|
modal: Option<AnyViewHandle>,
|
||||||
zoomed: Option<AnyWeakViewHandle>,
|
zoomed: Option<AnyWeakViewHandle>,
|
||||||
|
zoomed_position: Option<DockPosition>,
|
||||||
center: PaneGroup,
|
center: PaneGroup,
|
||||||
left_dock: ViewHandle<Dock>,
|
left_dock: ViewHandle<Dock>,
|
||||||
bottom_dock: ViewHandle<Dock>,
|
bottom_dock: ViewHandle<Dock>,
|
||||||
|
@ -683,6 +684,7 @@ impl Workspace {
|
||||||
weak_self: weak_handle.clone(),
|
weak_self: weak_handle.clone(),
|
||||||
modal: None,
|
modal: None,
|
||||||
zoomed: None,
|
zoomed: None,
|
||||||
|
zoomed_position: None,
|
||||||
center: PaneGroup::new(center_pane.clone()),
|
center: PaneGroup::new(center_pane.clone()),
|
||||||
panes: vec![center_pane.clone()],
|
panes: vec![center_pane.clone()],
|
||||||
panes_by_item: Default::default(),
|
panes_by_item: Default::default(),
|
||||||
|
@ -885,6 +887,11 @@ impl Workspace {
|
||||||
.map_or(false, |active_panel| active_panel.id() == panel.id());
|
.map_or(false, |active_panel| active_panel.id() == panel.id());
|
||||||
dock.remove_panel(&panel, cx);
|
dock.remove_panel(&panel, cx);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if panel.is_zoomed(cx) {
|
||||||
|
this.zoomed_position = Some(new_position);
|
||||||
|
}
|
||||||
|
|
||||||
dock = match panel.read(cx).position(cx) {
|
dock = match panel.read(cx).position(cx) {
|
||||||
DockPosition::Left => &this.left_dock,
|
DockPosition::Left => &this.left_dock,
|
||||||
DockPosition::Bottom => &this.bottom_dock,
|
DockPosition::Bottom => &this.bottom_dock,
|
||||||
|
@ -903,14 +910,17 @@ impl Workspace {
|
||||||
dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx));
|
dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx));
|
||||||
if panel.has_focus(cx) {
|
if panel.has_focus(cx) {
|
||||||
this.zoomed = Some(panel.downgrade().into_any());
|
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) {
|
} else if T::should_zoom_out_on_event(event) {
|
||||||
this.zoom_out(cx);
|
this.zoom_out(cx);
|
||||||
} else if T::is_focus_event(event) {
|
} else if T::is_focus_event(event) {
|
||||||
if panel.is_zoomed(cx) {
|
if panel.is_zoomed(cx) {
|
||||||
this.zoomed = Some(panel.downgrade().into_any());
|
this.zoomed = Some(panel.downgrade().into_any());
|
||||||
|
this.zoomed_position = Some(panel.read(cx).position(cx));
|
||||||
} else {
|
} else {
|
||||||
this.zoomed = None;
|
this.zoomed = None;
|
||||||
|
this.zoomed_position = None;
|
||||||
}
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -1573,33 +1583,36 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_dock(
|
pub fn toggle_dock(&mut self, dock_side: DockPosition, cx: &mut ViewContext<Self>) {
|
||||||
&mut self,
|
|
||||||
dock_side: DockPosition,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) {
|
|
||||||
let dock = match dock_side {
|
let dock = match dock_side {
|
||||||
DockPosition::Left => &self.left_dock,
|
DockPosition::Left => &self.left_dock,
|
||||||
DockPosition::Bottom => &self.bottom_dock,
|
DockPosition::Bottom => &self.bottom_dock,
|
||||||
DockPosition::Right => &self.right_dock,
|
DockPosition::Right => &self.right_dock,
|
||||||
};
|
};
|
||||||
let focus_center = dock.update(cx, |dock, cx| {
|
let mut focus_center = false;
|
||||||
let was_open = dock.is_open();
|
let mut zoom_out = false;
|
||||||
dock.set_open(!was_open, cx);
|
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 let Some(active_panel) = dock.active_panel() {
|
||||||
if was_open {
|
if was_visible {
|
||||||
if active_panel.has_focus(cx) {
|
if active_panel.has_focus(cx) {
|
||||||
return true;
|
focus_center = true;
|
||||||
}
|
}
|
||||||
} else if active_panel.is_zoomed(cx) {
|
} else {
|
||||||
cx.focus(active_panel.as_any());
|
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 {
|
if focus_center {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
}
|
}
|
||||||
|
@ -1646,9 +1659,24 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_panel_focus<T: Panel>(&mut self, cx: &mut ViewContext<Self>) {
|
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>() {
|
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);
|
dock.activate_panel(panel_index, cx);
|
||||||
|
|
||||||
if let Some(panel) = dock.active_panel().cloned() {
|
if let Some(panel) = dock.active_panel().cloned() {
|
||||||
|
@ -1656,15 +1684,18 @@ impl Workspace {
|
||||||
if panel.is_zoomed(cx) {
|
if panel.is_zoomed(cx) {
|
||||||
dock.set_open(false, cx);
|
dock.set_open(false, cx);
|
||||||
}
|
}
|
||||||
return true
|
focus_center = true;
|
||||||
} else {
|
} else {
|
||||||
dock.set_open(true, cx);
|
dock.set_open(true, cx);
|
||||||
cx.focus(panel.as_any());
|
cx.focus(panel.as_any());
|
||||||
|
zoom_out = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if zoom_out {
|
||||||
|
self.zoom_out_everything_except(position, cx);
|
||||||
|
}
|
||||||
if focus_center {
|
if focus_center {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
}
|
}
|
||||||
|
@ -1685,6 +1716,36 @@ impl Workspace {
|
||||||
self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
||||||
self.right_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 = 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();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -1901,6 +1962,7 @@ impl Workspace {
|
||||||
} else {
|
} else {
|
||||||
self.zoomed = None;
|
self.zoomed = None;
|
||||||
}
|
}
|
||||||
|
self.zoomed_position = None;
|
||||||
|
|
||||||
self.update_followers(
|
self.update_followers(
|
||||||
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
|
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
|
||||||
|
@ -1960,6 +2022,7 @@ impl Workspace {
|
||||||
pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
|
pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
|
||||||
if pane.read(cx).has_focus() {
|
if pane.read(cx).has_focus() {
|
||||||
self.zoomed = Some(pane.downgrade().into_any());
|
self.zoomed = Some(pane.downgrade().into_any());
|
||||||
|
self.zoomed_position = None;
|
||||||
}
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -3234,13 +3297,38 @@ impl View for Workspace {
|
||||||
.with_children(self.zoomed.as_ref().and_then(|zoomed| {
|
.with_children(self.zoomed.as_ref().and_then(|zoomed| {
|
||||||
enum ZoomBackground {}
|
enum ZoomBackground {}
|
||||||
let zoomed = zoomed.upgrade(cx)?;
|
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(
|
Some(
|
||||||
ChildView::new(&zoomed, cx)
|
ChildView::new(&zoomed, cx)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.workspace.zoomed_foreground)
|
.with_style(theme.workspace.zoomed_foreground)
|
||||||
.aligned()
|
.aligned()
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.workspace.zoomed_background)
|
.with_style(background_style)
|
||||||
.mouse::<ZoomBackground>(0)
|
.mouse::<ZoomBackground>(0)
|
||||||
.capture_all()
|
.capture_all()
|
||||||
.on_down(
|
.on_down(
|
||||||
|
@ -4436,6 +4524,14 @@ mod tests {
|
||||||
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomIn));
|
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomIn));
|
||||||
workspace.read_with(cx, |workspace, _| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any()));
|
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
|
// 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());
|
focus_receiver.update(cx, |_, cx| cx.focus_self());
|
||||||
workspace.read_with(cx, |workspace, _| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any()));
|
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.
|
// If focus is transferred elsewhere in the workspace, the panel is no longer zoomed.
|
||||||
workspace.update(cx, |_, cx| cx.focus_self());
|
workspace.update(cx, |_, cx| cx.focus_self());
|
||||||
workspace.read_with(cx, |workspace, _| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed, None);
|
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
|
// 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());
|
focus_receiver.update(cx, |_, cx| cx.focus_self());
|
||||||
workspace.read_with(cx, |workspace, _| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed, None);
|
assert_eq!(workspace.zoomed, None);
|
||||||
|
assert_eq!(workspace.zoomed_position, None);
|
||||||
});
|
});
|
||||||
|
|
||||||
// When focus is transferred back to the panel, it is zoomed again.
|
// When focus is transferred back to the panel, it is zoomed again.
|
||||||
panel_1.update(cx, |_, cx| cx.focus_self());
|
panel_1.update(cx, |_, cx| cx.focus_self());
|
||||||
workspace.read_with(cx, |workspace, _| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any()));
|
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.
|
// Emitting a ZoomOut event unzooms the panel.
|
||||||
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomOut));
|
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomOut));
|
||||||
workspace.read_with(cx, |workspace, _| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed, None);
|
assert_eq!(workspace.zoomed, None);
|
||||||
|
assert_eq!(workspace.zoomed_position, None);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Emit closed event on panel 1, which is active
|
// 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
|
// Now the left dock is closed, because panel_1 was the active panel
|
||||||
workspace.read_with(cx, |workspace, cx| {
|
workspace.read_with(cx, |workspace, cx| {
|
||||||
let left_dock = workspace.left_dock();
|
let right_dock = workspace.right_dock();
|
||||||
assert!(!left_dock.read(cx).is_open());
|
assert!(!right_dock.read(cx).is_open());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue