using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Maths; using Robust.Shared.Utility; using static Robust.Client.UserInterface.Controls.BoxContainer; namespace Content.Client.ContextMenu.UI { /// /// The base context-menu pop-up window used for both the entity and verb menus. /// [GenerateTypedNameReferences] public sealed partial class ContextMenuPopup : Popup { public const string StyleClassContextMenuPopup = "contextMenuPopup"; /// /// How many items to list before limiting the size and adding a scroll bar. /// public const int MaxItemsBeforeScroll = 10; /// /// If this pop-up is created by hovering over some element in another pop-up, this is that element. /// public ContextMenuElement? ParentElement; /// /// This is the main body of the menu. The menu entries should be added to this object. /// public BoxContainer MenuBody = new() { Orientation = LayoutOrientation.Vertical }; private ContextMenuPresenter _presenter; public ContextMenuPopup (ContextMenuPresenter presenter, ContextMenuElement? parentElement) : base() { RobustXamlLoader.Load(this); MenuPanel.SetOnlyStyleClass(StyleClassContextMenuPopup); _presenter = presenter; ParentElement = parentElement; //XAML controls are private. So defining and adding MenuBody here instead. Scroll.AddChild(MenuBody); // Set Max Height based on MaxItemsBeforeScroll and the panel's style box MenuPanel.ForceRunStyleUpdate(); MenuPanel.TryGetStyleProperty(PanelContainer.StylePropertyPanel, out var box); var styleSize = (box?.MinimumSize ?? Vector2.Zero) / UIScale; MenuPanel.MaxHeight = MaxItemsBeforeScroll * (ContextMenuElement.ElementHeight + 2 * ContextMenuElement.ElementMargin) + styleSize.Y; UserInterfaceManager.ModalRoot.AddChild(this); MenuBody.OnChildRemoved += ctrl => _presenter.OnRemoveElement(this, ctrl); if (ParentElement != null) { DebugTools.Assert(ParentElement.SubMenu == null); ParentElement.SubMenu = this; } // ensure the menu-stack is properly updated when a pop-up looses focus or otherwise closes without going // through the menu presenter. OnPopupHide += () => { if (ParentElement != null) _presenter.CloseSubMenus(ParentElement.ParentMenu); }; } protected override void Dispose(bool disposing) { MenuBody.OnChildRemoved -= ctrl => _presenter.OnRemoveElement(this, ctrl); ParentElement = null; base.Dispose(disposing); } } }