diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index a1c7b24c7a112..d4f5c565c27ef 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -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(), diff --git a/crates/gpui/src/elements/anchored.rs b/crates/gpui/src/elements/anchored.rs index ed68e3e40dda5..7872ba6349bf1 100644 --- a/crates/gpui/src/elements/anchored.rs +++ b/crates/gpui/src/elements/anchored.rs @@ -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. @@ -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>) -> Self { + self.fit_mode = AnchoredFitMode::SnapToWindowWithMargin(edges.into()); + self + } } impl ParentElement for Anchored { @@ -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; @@ -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), + /// 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, } diff --git a/crates/gpui/src/geometry.rs b/crates/gpui/src/geometry.rs index eb04756cefb64..8de9e6f009d73 100644 --- a/crates/gpui/src/geometry.rs +++ b/crates/gpui/src/geometry.rs @@ -1836,11 +1836,18 @@ impl Edges { impl From for Edges { fn from(val: f32) -> Self { + let val: Pixels = val.into(); + val.into() + } +} + +impl From for Edges { + 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, } } } diff --git a/crates/ui/src/components/popover_menu.rs b/crates/ui/src/components/popover_menu.rs index 11768d19f71aa..02604b2cc6b19 100644 --- a/crates/ui/src/components/popover_menu.rs +++ b/crates/ui/src/components/popover_menu.rs @@ -252,7 +252,9 @@ impl Element for PopoverMenu { 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), diff --git a/crates/ui/src/components/right_click_menu.rs b/crates/ui/src/components/right_click_menu.rs index 25481252b3d00..c340a4ad896ef 100644 --- a/crates/ui/src/components/right_click_menu.rs +++ b/crates/ui/src/components/right_click_menu.rs @@ -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, @@ -118,7 +118,7 @@ impl Element for RightClickMenu { 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); }