diff --git a/Robust.Client/UserInterface/Controls/Popup.cs b/Robust.Client/UserInterface/Controls/Popup.cs index 8950ec5589..2b4f363ea7 100644 --- a/Robust.Client/UserInterface/Controls/Popup.cs +++ b/Robust.Client/UserInterface/Controls/Popup.cs @@ -30,7 +30,7 @@ namespace Robust.Client.UserInterface.Controls public bool CloseOnEscape { get; set; } = true; - public virtual void Open(UIBox2? box = null, Vector2? altPos = null) + public virtual void Open(UIBox2? box = null, Vector2? altPos = null, Vector2? altPosUp = null) { if (Visible) { @@ -44,10 +44,12 @@ namespace Robust.Client.UserInterface.Controls if (box != null && (_desiredSize != box.Value.Size || PopupContainer.GetPopupOrigin(this) != box.Value.TopLeft || - PopupContainer.GetAltOrigin(this) != altPos)) + PopupContainer.GetAltOrigin(this) != altPos || + PopupContainer.GetAltOriginUp(this) != altPosUp)) { PopupContainer.SetPopupOrigin(this, box.Value.TopLeft); PopupContainer.SetAltOrigin(this, altPos); + PopupContainer.SetAltOriginUp(this, altPosUp); _desiredSize = box.Value.Size; InvalidateMeasure(); diff --git a/Robust.Client/UserInterface/Controls/PopupContainer.cs b/Robust.Client/UserInterface/Controls/PopupContainer.cs index 696d9c5aa4..59baa73c9a 100644 --- a/Robust.Client/UserInterface/Controls/PopupContainer.cs +++ b/Robust.Client/UserInterface/Controls/PopupContainer.cs @@ -27,6 +27,13 @@ namespace Robust.Client.UserInterface.Controls public static readonly AttachedProperty AltOriginProperty = AttachedProperty.Create("AltOrigin", typeof(PopupContainer), typeof(Vector2?), changed: PopupOriginChangedCallback); + /// + /// Alternative position to bottom-left-align the popup if + /// would put it off-screen vertically. + /// + public static readonly AttachedProperty AltOriginUpProperty = AttachedProperty.Create("AltOriginUp", + typeof(PopupContainer), typeof(Vector2?), changed: PopupOriginChangedCallback); + public PopupContainer() { RectClipContent = true; @@ -47,11 +54,21 @@ namespace Robust.Client.UserInterface.Controls return control.GetValue(AltOriginProperty); } + public static Vector2? GetAltOriginUp(Control control) + { + return control.GetValue(AltOriginUpProperty); + } + public static void SetAltOrigin(Control control, Vector2? origin) { control.SetValue(AltOriginProperty, origin); } + public static void SetAltOriginUp(Control control, Vector2? origin) + { + control.SetValue(AltOriginUpProperty, origin); + } + private static void PopupOriginChangedCallback(Control owner, AttachedPropertyChangedEventArgs eventArgs) { if (owner.Parent is PopupContainer container) @@ -67,47 +84,58 @@ namespace Robust.Client.UserInterface.Controls var size = child.DesiredSize; var offset = child.GetValue(PopupOriginProperty); var altPos = child.GetValue(AltOriginProperty); + var altPosUp = child.GetValue(AltOriginUpProperty); - var (r, b) = size + offset; // bottom right corner. + var box = UIBox2.FromDimensions(offset, size); var isAltPos = false; + var isAltPosUp = false; // Clamp the right edge. - if (r > Width) + if (box.Right > Width) { // Try to position at alt pos. if (altPos != null && altPos.Value.X - size.X > 0) { // There is horizontal room at the alt pos so there we go. isAltPos = true; - offset = new Vector2(altPos.Value.X - size.X, altPos.Value.Y); - (_, b) = size + offset; + box = UIBox2.FromDimensions(new Vector2(altPos.Value.X - size.X, altPos.Value.Y), size); } else { - offset -= new Vector2(r - Width, 0); + box = box.Translated(new Vector2(-(box.Right - Width), 0)); } } // Clamp the bottom edge. - if (b > Height) + if (box.Bottom > Height) { - offset -= new Vector2(0, b - Height); + // Try to position at alt pos. + if (altPosUp != null && altPosUp.Value.Y - size.Y > 0) + { + // There is vertical room at the alt pos so there we go. + isAltPosUp = true; + box = UIBox2.FromDimensions(new Vector2(altPosUp.Value.X, altPosUp.Value.Y - size.Y), size); + } + else + { + box = box.Translated(new Vector2(0, -(box.Bottom - Height))); + } } // Try to clamp the left edge. - if (offset.X < 0 && !isAltPos) + if (box.Left < 0 && !isAltPos) { - offset -= new Vector2(offset.X, 0); + box = box.Translated(new Vector2(-offset.X, 0)); } // Try to clamp the top edge. - if (offset.Y < 0) + if (box.Top < 0 && !isAltPosUp) { - offset -= new Vector2(0, offset.Y); + box = box.Translated(new Vector2(0, -offset.Y)); } - child.Arrange(UIBox2.FromDimensions(offset, size)); + child.Arrange(box); } return finalSize; diff --git a/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.Completions.cs b/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.Completions.cs index 77774c5f70..45f58301e7 100644 --- a/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.Completions.cs +++ b/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.Completions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Threading; using Robust.Client.UserInterface.Controls; using Robust.Shared; @@ -224,10 +225,13 @@ public sealed partial class DebugConsole if (_compPopup.Contents.ChildCount != 0) { - _compPopup.Open( - UIBox2.FromDimensions( - offset - _compPopup.Contents.Margin.Left, CommandBar.GlobalPosition.Y + CommandBar.Height + 2, - 5, 5)); + var box = UIBox2.FromDimensions( + offset - _compPopup.Contents.Margin.Left, + CommandBar.GlobalPosition.Y + CommandBar.Height + 2, + 5, + 5); + var altPosUp = new Vector2(offset - _compPopup.Contents.Margin.Left, CommandBar.GlobalPosition.Y); + _compPopup.Open(box, altPosUp: altPosUp); } } diff --git a/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.cs b/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.cs index b012319663..687333ef42 100644 --- a/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.cs +++ b/Robust.Client/UserInterface/CustomControls/DebugConsole.xaml.cs @@ -83,7 +83,7 @@ namespace Robust.Client.UserInterface.CustomControls _consoleHost.ClearText += OnClearText; _cfg.OnValueChanged(CVars.ConMaxEntries, MaxEntriesChanged, true); - UserInterfaceManager.ModalRoot.AddChild(_compPopup); + Root!.ModalRoot.AddChild(_compPopup); } protected override void ExitedTree() @@ -95,7 +95,7 @@ namespace Robust.Client.UserInterface.CustomControls _consoleHost.ClearText -= OnClearText; _cfg.UnsubValueChanged(CVars.ConMaxEntries, MaxEntriesChanged); - UserInterfaceManager.ModalRoot.RemoveChild(_compPopup); + _compPopup.Orphan(); } private void MaxEntriesChanged(int value)