Fix DebugConsole completions in devwindow

PopupContainer now supports an AltOriginUpProperty so that the completion popup doesn't overlap the input bar.
This commit is contained in:
PJB3005
2025-08-30 17:21:15 +02:00
parent fb0ec52f8c
commit b61003e2a0
4 changed files with 54 additions and 20 deletions
@@ -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();
@@ -27,6 +27,13 @@ namespace Robust.Client.UserInterface.Controls
public static readonly AttachedProperty AltOriginProperty = AttachedProperty.Create("AltOrigin",
typeof(PopupContainer), typeof(Vector2?), changed: PopupOriginChangedCallback);
/// <summary>
/// Alternative position to bottom-left-align the popup if <see cref="PopupOriginProperty"/>
/// would put it off-screen vertically.
/// </summary>
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<Vector2?>(AltOriginProperty);
}
public static Vector2? GetAltOriginUp(Control control)
{
return control.GetValue<Vector2?>(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<Vector2>(PopupOriginProperty);
var altPos = child.GetValue<Vector2?>(AltOriginProperty);
var altPosUp = child.GetValue<Vector2?>(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;
@@ -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);
}
}
@@ -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)