workspace: Fix panel resize handles leaking through zoomed panels (#9909)

Fixes #9501 

Release Notes:

- Fixed panel resize handle "leaking through" into a zoomed panel or
pane.
This commit is contained in:
Piotr Osiewicz 2024-03-28 12:18:51 +01:00 committed by GitHub
parent f5823f9942
commit cb7c53bc52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 74 additions and 54 deletions

View File

@ -1,6 +1,6 @@
use crate::persistence::model::DockData;
use crate::DraggedDock;
use crate::{status_bar::StatusItemView, Workspace};
use crate::{DraggedDock, Event};
use gpui::{
deferred, div, px, Action, AnchorCorner, AnyView, AppContext, Axis, ClickEvent, Entity,
EntityId, EventEmitter, FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton,
@ -149,7 +149,8 @@ pub struct Dock {
active_panel_index: usize,
focus_handle: FocusHandle,
pub(crate) serialized_dock: Option<DockData>,
_focus_subscription: Subscription,
resizeable: bool,
_subscriptions: [Subscription; 2],
}
impl FocusableView for Dock {
@ -195,21 +196,28 @@ pub struct PanelButtons {
impl Dock {
pub fn new(position: DockPosition, cx: &mut ViewContext<Workspace>) -> View<Self> {
let focus_handle = cx.focus_handle();
let workspace = cx.view().clone();
let dock = cx.new_view(|cx: &mut ViewContext<Self>| {
let focus_subscription = cx.on_focus(&focus_handle, |dock, cx| {
if let Some(active_entry) = dock.panel_entries.get(dock.active_panel_index) {
active_entry.panel.focus_handle(cx).focus(cx)
}
});
let zoom_subscription = cx.subscribe(&workspace, |dock, workspace, e: &Event, cx| {
if matches!(e, Event::ZoomChanged) {
let is_zoomed = workspace.read(cx).zoomed.is_some();
dock.resizeable = !is_zoomed;
}
});
Self {
position,
panel_entries: Default::default(),
active_panel_index: 0,
is_open: false,
focus_handle: focus_handle.clone(),
_focus_subscription: focus_subscription,
_subscriptions: [focus_subscription, zoom_subscription],
serialized_dock: None,
resizeable: true,
}
});
@ -229,6 +237,7 @@ impl Dock {
workspace.zoomed = None;
workspace.zoomed_position = None;
}
cx.emit(Event::ZoomChanged);
workspace.dismiss_zoomed_items_to_reveal(Some(position), cx);
workspace.update_active_view_for_followers(cx)
}
@ -241,6 +250,7 @@ impl Dock {
if panel.is_zoomed(cx) {
workspace.zoomed = Some(panel.to_any().downgrade());
workspace.zoomed_position = Some(position);
cx.emit(Event::ZoomChanged);
return;
}
}
@ -248,6 +258,7 @@ impl Dock {
if workspace.zoomed_position == Some(position) {
workspace.zoomed = None;
workspace.zoomed_position = None;
cx.emit(Event::ZoomChanged);
}
})
.detach();
@ -380,6 +391,7 @@ impl Dock {
.update(cx, |workspace, cx| {
workspace.zoomed = Some(panel.downgrade().into());
workspace.zoomed_position = Some(panel.read(cx).position(cx));
cx.emit(Event::ZoomChanged);
})
.ok();
}
@ -390,6 +402,7 @@ impl Dock {
if workspace.zoomed_position == Some(this.position) {
workspace.zoomed = None;
workspace.zoomed_position = None;
cx.emit(Event::ZoomChanged);
}
cx.notify();
})
@ -553,47 +566,49 @@ impl Render for Dock {
let size = entry.panel.size(cx);
let position = self.position;
let handle = div()
.id("resize-handle")
.on_drag(DraggedDock(position), |dock, cx| {
cx.stop_propagation();
cx.new_view(|_| dock.clone())
})
.on_click(cx.listener(|v, e: &ClickEvent, cx| {
if e.down.button == MouseButton::Left && e.down.click_count == 2 {
v.resize_active_panel(None, cx);
let create_resize_handle = || {
let handle = div()
.id("resize-handle")
.on_drag(DraggedDock(position), |dock, cx| {
cx.stop_propagation();
}
}))
.occlude();
let handle = match self.position() {
DockPosition::Left => deferred(
handle
.absolute()
.right(-RESIZE_HANDLE_SIZE / 2.)
.top(px(0.))
.h_full()
.w(RESIZE_HANDLE_SIZE)
.cursor_col_resize(),
),
DockPosition::Bottom => deferred(
handle
.absolute()
.top(-RESIZE_HANDLE_SIZE / 2.)
.left(px(0.))
.w_full()
.h(RESIZE_HANDLE_SIZE)
.cursor_row_resize(),
),
DockPosition::Right => deferred(
handle
.absolute()
.top(px(0.))
.left(-RESIZE_HANDLE_SIZE / 2.)
.h_full()
.w(RESIZE_HANDLE_SIZE)
.cursor_col_resize(),
),
cx.new_view(|_| dock.clone())
})
.on_click(cx.listener(|v, e: &ClickEvent, cx| {
if e.down.button == MouseButton::Left && e.down.click_count == 2 {
v.resize_active_panel(None, cx);
cx.stop_propagation();
}
}))
.occlude();
match self.position() {
DockPosition::Left => deferred(
handle
.absolute()
.right(-RESIZE_HANDLE_SIZE / 2.)
.top(px(0.))
.h_full()
.w(RESIZE_HANDLE_SIZE)
.cursor_col_resize(),
),
DockPosition::Bottom => deferred(
handle
.absolute()
.top(-RESIZE_HANDLE_SIZE / 2.)
.left(px(0.))
.w_full()
.h(RESIZE_HANDLE_SIZE)
.cursor_row_resize(),
),
DockPosition::Right => deferred(
handle
.absolute()
.top(px(0.))
.left(-RESIZE_HANDLE_SIZE / 2.)
.h_full()
.w(RESIZE_HANDLE_SIZE)
.cursor_col_resize(),
),
}
};
div()
@ -625,7 +640,7 @@ impl Render for Dock {
.cached(StyleRefinement::default().v_flex().size_full()),
),
)
.child(handle)
.when(self.resizeable, |this| this.child(create_resize_handle()))
} else {
div()
.key_context(dispatch_context)

View File

@ -75,9 +75,9 @@ use theme::{ActiveTheme, SystemAppearance, ThemeSettings};
pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
pub use ui;
use ui::{
div, Context as _, Div, Element, ElementContext, InteractiveElement as _, IntoElement, Label,
ParentElement as _, Pixels, SharedString, Styled as _, ViewContext, VisualContext as _,
WindowContext,
div, Context as _, Div, Element, ElementContext, FluentBuilder as _, InteractiveElement as _,
IntoElement, Label, ParentElement as _, Pixels, SharedString, Styled as _, ViewContext,
VisualContext as _, WindowContext,
};
use util::ResultExt;
use uuid::Uuid;
@ -520,6 +520,7 @@ pub enum Event {
ContactRequestedJoin(u64),
WorkspaceCreated(WeakView<Workspace>),
SpawnTask(SpawnInTerminal),
ZoomChanged,
}
pub enum OpenVisible {
@ -1913,6 +1914,7 @@ impl Workspace {
if self.zoomed_position != dock_to_reveal {
self.zoomed = None;
self.zoomed_position = None;
cx.emit(Event::ZoomChanged);
}
cx.notify();
@ -2341,6 +2343,7 @@ impl Workspace {
self.zoomed = None;
}
self.zoomed_position = None;
cx.emit(Event::ZoomChanged);
self.update_active_view_for_followers(cx);
cx.notify();
@ -2390,6 +2393,7 @@ impl Workspace {
if pane.read(cx).has_focus(cx) {
self.zoomed = Some(pane.downgrade().into());
self.zoomed_position = None;
cx.emit(Event::ZoomChanged);
}
cx.notify();
}
@ -2398,6 +2402,7 @@ impl Workspace {
pane.update(cx, |pane, cx| pane.set_zoomed(false, cx));
if self.zoomed_position.is_none() {
self.zoomed = None;
cx.emit(Event::ZoomChanged);
}
cx.notify();
}
@ -3918,9 +3923,9 @@ impl Render for Workspace {
.absolute()
.size_full()
})
.on_drag_move(
cx.listener(|workspace, e: &DragMoveEvent<DraggedDock>, cx| {
match e.drag(cx).0 {
.when(self.zoomed.is_none(), |this| {
this.on_drag_move(cx.listener(
|workspace, e: &DragMoveEvent<DraggedDock>, cx| match e.drag(cx).0 {
DockPosition::Left => {
let size = workspace.bounds.left() + e.event.position.x;
workspace.left_dock.update(cx, |left_dock, cx| {
@ -3939,9 +3944,9 @@ impl Render for Workspace {
bottom_dock.resize_active_panel(Some(size), cx);
});
}
}
}),
)
},
))
})
.child(
div()
.flex()