Snap overlay's bottom/right edge to same window's edge on overflow

Antonio Scandurra created

Change summary

crates/context_menu/src/context_menu.rs |  2 +-
crates/editor/src/element.rs            |  7 +++++++
crates/gpui/src/elements/overlay.rs     | 20 +++++++++++---------
crates/gpui/src/elements/tooltip.rs     |  2 +-
4 files changed, 20 insertions(+), 11 deletions(-)

Detailed changes

crates/context_menu/src/context_menu.rs 🔗

@@ -94,7 +94,7 @@ impl View for ContextMenu {
 
         Overlay::new(expanded_menu)
             .hoverable(true)
-            .align_to_fit(true)
+            .move_to_fit(true)
             .with_abs_position(self.position)
             .boxed()
     }

crates/editor/src/element.rs 🔗

@@ -491,8 +491,15 @@ impl EditorElement {
             let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left;
             let y = (position.row() + 1) as f32 * layout.line_height - scroll_top;
             let mut list_origin = content_origin + vec2f(x, y);
+            let list_width = context_menu.size().x();
             let list_height = context_menu.size().y();
 
+            // Snap the right edge of the list to the right edge of the window if
+            // its horizontal bounds overflow.
+            if list_origin.x() + list_width > cx.window_size.x() {
+                list_origin.set_x((cx.window_size.x() - list_width).max(0.));
+            }
+
             if list_origin.y() + list_height > bounds.max_y() {
                 list_origin.set_y(list_origin.y() - layout.line_height - list_height);
             }

crates/gpui/src/elements/overlay.rs 🔗

@@ -10,7 +10,7 @@ use crate::{
 pub struct Overlay {
     child: ElementBox,
     abs_position: Option<Vector2F>,
-    align_to_fit: bool,
+    move_to_fit: bool,
     hoverable: bool,
 }
 
@@ -19,7 +19,7 @@ impl Overlay {
         Self {
             child,
             abs_position: None,
-            align_to_fit: false,
+            move_to_fit: false,
             hoverable: false,
         }
     }
@@ -29,8 +29,8 @@ impl Overlay {
         self
     }
 
-    pub fn align_to_fit(mut self, align_to_fit: bool) -> Self {
-        self.align_to_fit = align_to_fit;
+    pub fn move_to_fit(mut self, align_to_fit: bool) -> Self {
+        self.move_to_fit = align_to_fit;
         self
     }
 
@@ -76,15 +76,17 @@ impl Element for Overlay {
             });
         }
 
-        if self.align_to_fit {
-            // Align overlay to the left if its bounds overflow the window width.
+        if self.move_to_fit {
+            // Snap the right edge of the overlay to the right edge of the window if
+            // its horizontal bounds overflow.
             if bounds.lower_right().x() > cx.window_size.x() {
-                bounds.set_origin_x(bounds.origin_x() - bounds.width());
+                bounds.set_origin_x((cx.window_size.x() - bounds.width()).max(0.));
             }
 
-            // Align overlay to the top if its bounds overflow the window height.
+            // Snap the bottom edge of the overlay to the bottom edge of the window if
+            // its vertical bounds overflow.
             if bounds.lower_right().y() > cx.window_size.y() {
-                bounds.set_origin_y(bounds.origin_y() - bounds.height());
+                bounds.set_origin_y((cx.window_size.y() - bounds.height()).max(0.));
             }
         }