Skip to content

Commit

Permalink
Improve popup menu to leave some margin with window edges (zed-indust…
Browse files Browse the repository at this point in the history
…ries#17159)

Release Notes:

- Improved popup menu to leave some margin with window edges.

## Updates in GPUI

- gpui: Add `snap_to_window_with_margin` method to `anchored` to support
leave margin to window edges.

## Before

<img width="609" alt="before-snap-to-window 2024-08-30 222506"
src="https://github.com/user-attachments/assets/62bb6791-7c89-4558-9484-5c7b31f5e91e">

## After

<img width="698" alt="snap-to-window1 2024-08-30 222506"
src="https://github.com/user-attachments/assets/51634e79-2a95-42fe-8362-a3c7003648eb">

<img width="622" alt="snap-to-window 2024-08-30 222506"
src="https://github.com/user-attachments/assets/43a865d6-d238-4fdc-ae9d-8160b9ba7953">
  • Loading branch information
huacnlee authored Sep 7, 2024
1 parent b401f69 commit 47aec5e
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 18 deletions.
2 changes: 1 addition & 1 deletion crates/editor/src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2732,7 +2732,7 @@ impl EditorElement {
.position(position)
.child(context_menu)
.anchor(AnchorCorner::TopLeft)
.snap_to_window(),
.snap_to_window_with_margin(px(8.)),
)
.with_priority(1)
.into_any(),
Expand Down
33 changes: 23 additions & 10 deletions crates/gpui/src/elements/anchored.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use smallvec::SmallVec;
use taffy::style::{Display, Position};

use crate::{
point, AnyElement, Bounds, Element, GlobalElementId, IntoElement, LayoutId, ParentElement,
Pixels, Point, Size, Style, WindowContext,
point, AnyElement, Bounds, Edges, Element, GlobalElementId, IntoElement, LayoutId,
ParentElement, Pixels, Point, Size, Style, WindowContext,
};

/// The state that the anchored element element uses to track its children.
Expand Down Expand Up @@ -60,6 +60,12 @@ impl Anchored {
self.fit_mode = AnchoredFitMode::SnapToWindow;
self
}

/// Snap to window edge and leave some margins.
pub fn snap_to_window_with_margin(mut self, edges: impl Into<Edges<Pixels>>) -> Self {
self.fit_mode = AnchoredFitMode::SnapToWindowWithMargin(edges.into());
self
}
}

impl ParentElement for Anchored {
Expand Down Expand Up @@ -153,22 +159,27 @@ impl Element for Anchored {
}
}

let edges = match self.fit_mode {
AnchoredFitMode::SnapToWindowWithMargin(edges) => edges,
_ => Edges::default(),
};

// Snap the horizontal edges of the anchored element to the horizontal edges of the window if
// its horizontal bounds overflow, aligning to the left if it is wider than the limits.
if desired.right() > limits.right() {
desired.origin.x -= desired.right() - limits.right();
desired.origin.x -= desired.right() - limits.right() + edges.right;
}
if desired.left() < limits.left() {
desired.origin.x = limits.origin.x;
desired.origin.x = limits.origin.x + edges.left;
}

// Snap the vertical edges of the anchored element to the vertical edges of the window if
// its vertical bounds overflow, aligning to the top if it is taller than the limits.
if desired.bottom() > limits.bottom() {
desired.origin.y -= desired.bottom() - limits.bottom();
desired.origin.y -= desired.bottom() - limits.bottom() + edges.bottom;
}
if desired.top() < limits.top() {
desired.origin.y = limits.origin.y;
desired.origin.y = limits.origin.y + edges.top;
}

let offset = desired.origin - bounds.origin;
Expand Down Expand Up @@ -211,18 +222,20 @@ enum Axis {
/// Which algorithm to use when fitting the anchored element to be inside the window.
#[derive(Copy, Clone, PartialEq)]
pub enum AnchoredFitMode {
/// Snap the anchored element to the window edge
/// Snap the anchored element to the window edge.
SnapToWindow,
/// Switch which corner anchor this anchored element is attached to
/// Snap to window edge and leave some margins.
SnapToWindowWithMargin(Edges<Pixels>),
/// Switch which corner anchor this anchored element is attached to.
SwitchAnchor,
}

/// Which algorithm to use when positioning the anchored element.
#[derive(Copy, Clone, PartialEq)]
pub enum AnchoredPositionMode {
/// Position the anchored element relative to the window
/// Position the anchored element relative to the window.
Window,
/// Position the anchored element relative to its parent
/// Position the anchored element relative to its parent.
Local,
}

Expand Down
15 changes: 11 additions & 4 deletions crates/gpui/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1836,11 +1836,18 @@ impl Edges<Pixels> {

impl From<f32> for Edges<Pixels> {
fn from(val: f32) -> Self {
let val: Pixels = val.into();
val.into()
}
}

impl From<Pixels> for Edges<Pixels> {
fn from(val: Pixels) -> Self {
Edges {
top: val.into(),
right: val.into(),
bottom: val.into(),
left: val.into(),
top: val,
right: val,
bottom: val,
left: val,
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion crates/ui/src/components/popover_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,9 @@ impl<M: ManagedView> Element for PopoverMenu<M> {
let mut menu_layout_id = None;

let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
let mut anchored = anchored().snap_to_window().anchor(self.anchor);
let mut anchored = anchored()
.snap_to_window_with_margin(px(8.))
.anchor(self.anchor);
if let Some(child_bounds) = element_state.child_bounds {
anchored = anchored.position(
self.resolved_attach().corner(child_bounds) + self.resolved_offset(cx),
Expand Down
4 changes: 2 additions & 2 deletions crates/ui/src/components/right_click_menu.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{cell::RefCell, rc::Rc};

use gpui::{
anchored, deferred, div, AnchorCorner, AnyElement, Bounds, DismissEvent, DispatchPhase,
anchored, deferred, div, px, AnchorCorner, AnyElement, Bounds, DismissEvent, DispatchPhase,
Element, ElementId, GlobalElementId, Hitbox, InteractiveElement, IntoElement, LayoutId,
ManagedView, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, View, VisualContext,
WindowContext,
Expand Down Expand Up @@ -118,7 +118,7 @@ impl<M: ManagedView> Element for RightClickMenu<M> {
let mut menu_layout_id = None;

let menu_element = element_state.menu.borrow_mut().as_mut().map(|menu| {
let mut anchored = anchored().snap_to_window();
let mut anchored = anchored().snap_to_window_with_margin(px(8.));
if let Some(anchor) = this.anchor {
anchored = anchored.anchor(anchor);
}
Expand Down

0 comments on commit 47aec5e

Please sign in to comment.