Center dock resize handle hitboxes (#9225)

Also, add a `deferred` function which takes an element to paint after
the current element tree.

Release Notes:

- Improved the size and position of the hitbox for resizing left, right,
and bottom panels.
([#8855](https://github.com/zed-industries/zed/issues/8855))

Co-authored-by: Julia <julia@zed.dev>
Co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2024-03-12 15:42:18 +01:00 committed by GitHub
parent 409aa513d4
commit 39a0841ea8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 88 additions and 25 deletions

View file

@ -0,0 +1,63 @@
use crate::{AnyElement, Bounds, Element, ElementContext, IntoElement, LayoutId, Pixels};
/// Builds a `Deferred` element, which delays the layout and paint of its child.
pub fn deferred(child: impl IntoElement) -> Deferred {
Deferred {
child: Some(child.into_any_element()),
priority: 0,
}
}
/// An element which delays the painting of its child until after all of
/// its ancestors, while keeping its layout as part of the current element tree.
pub struct Deferred {
child: Option<AnyElement>,
priority: usize,
}
impl Element for Deferred {
type BeforeLayout = ();
type AfterLayout = ();
fn before_layout(&mut self, cx: &mut ElementContext) -> (LayoutId, ()) {
let layout_id = self.child.as_mut().unwrap().before_layout(cx);
(layout_id, ())
}
fn after_layout(
&mut self,
_bounds: Bounds<Pixels>,
_before_layout: &mut Self::BeforeLayout,
cx: &mut ElementContext,
) {
let child = self.child.take().unwrap();
let element_offset = cx.element_offset();
cx.defer_draw(child, element_offset, self.priority)
}
fn paint(
&mut self,
_bounds: Bounds<Pixels>,
_before_layout: &mut Self::BeforeLayout,
_after_layout: &mut Self::AfterLayout,
_cx: &mut ElementContext,
) {
}
}
impl IntoElement for Deferred {
type Element = Self;
fn into_element(self) -> Self::Element {
self
}
}
impl Deferred {
/// Sets a priority for the element. A higher priority conceptually means painting the element
/// on top of deferred draws with a lower priority (i.e. closer to the viewer).
pub fn priority(mut self, priority: usize) -> Self {
self.priority = priority;
self
}
}

View file

@ -1,4 +1,5 @@
mod canvas; mod canvas;
mod deferred;
mod div; mod div;
mod img; mod img;
mod list; mod list;
@ -8,6 +9,7 @@ mod text;
mod uniform_list; mod uniform_list;
pub use canvas::*; pub use canvas::*;
pub use deferred::*;
pub use div::*; pub use div::*;
pub use img::*; pub use img::*;
pub use list::*; pub use list::*;

View file

@ -381,8 +381,7 @@ impl<'a> ElementContext<'a> {
let mut sorted_deferred_draws = let mut sorted_deferred_draws =
(0..self.window.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>(); (0..self.window.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();
sorted_deferred_draws sorted_deferred_draws.sort_by_key(|ix| self.window.next_frame.deferred_draws[*ix].priority);
.sort_unstable_by_key(|ix| self.window.next_frame.deferred_draws[*ix].priority);
self.layout_deferred_draws(&sorted_deferred_draws); self.layout_deferred_draws(&sorted_deferred_draws);
self.window.mouse_hit_test = self.window.next_frame.hit_test(self.window.mouse_position); self.window.mouse_hit_test = self.window.next_frame.hit_test(self.window.mouse_position);

View file

@ -2,10 +2,10 @@ use crate::persistence::model::DockData;
use crate::DraggedDock; use crate::DraggedDock;
use crate::{status_bar::StatusItemView, Workspace}; use crate::{status_bar::StatusItemView, Workspace};
use gpui::{ use gpui::{
div, px, Action, AnchorCorner, AnyView, AppContext, Axis, ClickEvent, Entity, EntityId, deferred, div, px, Action, AnchorCorner, AnyView, AppContext, Axis, ClickEvent, Entity,
EventEmitter, FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton, ParentElement, EntityId, EventEmitter, FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton,
Render, SharedString, StyleRefinement, Styled, Subscription, View, ViewContext, VisualContext, ParentElement, Render, SharedString, StyleRefinement, Styled, Subscription, View, ViewContext,
WeakView, WindowContext, VisualContext, WeakView, WindowContext,
}; };
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -551,7 +551,7 @@ impl Render for Dock {
let size = entry.panel.size(cx); let size = entry.panel.size(cx);
let position = self.position; let position = self.position;
let mut handle = div() let handle = div()
.id("resize-handle") .id("resize-handle")
.on_drag(DraggedDock(position), |dock, cx| { .on_drag(DraggedDock(position), |dock, cx| {
cx.stop_propagation(); cx.stop_propagation();
@ -564,36 +564,35 @@ impl Render for Dock {
} }
})) }))
.occlude(); .occlude();
let handle = match self.position() {
match self.position() { DockPosition::Left => deferred(
DockPosition::Left => { handle
handle = handle
.absolute() .absolute()
.right(px(0.)) .right(-RESIZE_HANDLE_SIZE / 2.)
.top(px(0.)) .top(px(0.))
.h_full() .h_full()
.w(RESIZE_HANDLE_SIZE) .w(RESIZE_HANDLE_SIZE)
.cursor_col_resize(); .cursor_col_resize(),
} ),
DockPosition::Bottom => { DockPosition::Bottom => deferred(
handle = handle handle
.absolute() .absolute()
.top(px(0.)) .top(-RESIZE_HANDLE_SIZE / 2.)
.left(px(0.)) .left(px(0.))
.w_full() .w_full()
.h(RESIZE_HANDLE_SIZE) .h(RESIZE_HANDLE_SIZE)
.cursor_row_resize(); .cursor_row_resize(),
} ),
DockPosition::Right => { DockPosition::Right => deferred(
handle = handle handle
.absolute() .absolute()
.top(px(0.)) .top(px(0.))
.left(px(0.)) .left(-RESIZE_HANDLE_SIZE / 2.)
.h_full() .h_full()
.w(RESIZE_HANDLE_SIZE) .w(RESIZE_HANDLE_SIZE)
.cursor_col_resize(); .cursor_col_resize(),
} ),
} };
div() div()
.key_context(dispatch_context) .key_context(dispatch_context)