UI: Close window hotkeys (#15227)
This commit is contained in:
@@ -145,6 +145,8 @@ namespace Content.Client.Options.UI.Tabs
|
||||
AddButton(ContentKeyFunctions.OpenTileSpawnWindow);
|
||||
AddButton(ContentKeyFunctions.OpenDecalSpawnWindow);
|
||||
AddButton(ContentKeyFunctions.OpenAdminMenu);
|
||||
AddButton(EngineKeyFunctions.WindowCloseAll);
|
||||
AddButton(EngineKeyFunctions.WindowCloseRecent);
|
||||
|
||||
AddHeader("ui-options-header-misc");
|
||||
AddButton(ContentKeyFunctions.TakeScreenshot);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.Info;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Input.Binding;
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.Info;
|
||||
|
||||
public sealed class CloseAllWindowsUIController : UIController
|
||||
{
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
_inputManager.SetInputCommand(EngineKeyFunctions.WindowCloseAll,
|
||||
InputCmdHandler.FromDelegate(session => CloseAllWindows()));
|
||||
}
|
||||
|
||||
private void CloseAllWindows()
|
||||
{
|
||||
foreach (var childControl in new List<Control>(_uiManager.WindowRoot.Children)) // Copy children list as it will be modified on Close()
|
||||
{
|
||||
if (childControl is BaseWindow)
|
||||
{
|
||||
((BaseWindow) childControl).Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
using Content.Client.Gameplay;
|
||||
using Content.Client.Info;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controllers;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Input.Binding;
|
||||
|
||||
namespace Content.Client.UserInterface.Systems.Info;
|
||||
|
||||
public sealed class CloseRecentWindowUIController : UIController
|
||||
{
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IUserInterfaceManager _uiManager = default!;
|
||||
|
||||
/// <summary>
|
||||
/// A list of windows that have been interacted with recently. Windows should only
|
||||
/// be in this list once, with the most recent window at the end, and the oldest
|
||||
/// window at the start.
|
||||
/// </summary>
|
||||
List<BaseWindow> recentlyInteractedWindows = new List<BaseWindow>();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
// Add listeners to be able to know when windows are opened.
|
||||
// (Does not need to be unlistened since UIControllers live forever)
|
||||
_uiManager.OnKeyBindDown += OnKeyBindDown;
|
||||
_uiManager.WindowRoot.OnChildAdded += OnRootChildAdded;
|
||||
|
||||
_inputManager.SetInputCommand(EngineKeyFunctions.WindowCloseRecent,
|
||||
InputCmdHandler.FromDelegate(session => CloseMostRecentWindow()));
|
||||
}
|
||||
|
||||
private void CloseMostRecentWindow()
|
||||
{
|
||||
// Search backwards through the recency list to find a still open window and close it
|
||||
for (int i=recentlyInteractedWindows.Count-1; i>=0; i--)
|
||||
{
|
||||
var window = recentlyInteractedWindows[i];
|
||||
recentlyInteractedWindows.RemoveAt(i); // Should always be removed as either the reference is stale or we're closing it
|
||||
if (window.IsOpen)
|
||||
{
|
||||
window.Close();
|
||||
return;
|
||||
}
|
||||
// continue going down the list, hoping to find a still-open window
|
||||
}
|
||||
}
|
||||
|
||||
private void OnKeyBindDown(Control control)
|
||||
{
|
||||
// On click, we should set the window that owns this control (if any) to the most recently
|
||||
// clicked window. By doing this, we can create an ordering of what windows have been
|
||||
// interacted with.
|
||||
|
||||
// Something was clicked, so find the window corresponding to what was clicked
|
||||
var window = GetWindowForControl(control);
|
||||
|
||||
// Find the window owning the control
|
||||
if (window != null)
|
||||
{
|
||||
// And move to top of recent stack
|
||||
//Logger.Debug("Most recent window is " + window.Name);
|
||||
SetMostRecentlyInteractedWindow(window);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the window as the one most recently interacted with. This function will update the
|
||||
/// internal recentlyInteractedWindows tracking.
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
private void SetMostRecentlyInteractedWindow(BaseWindow window)
|
||||
{
|
||||
// Search through the list and see if already added.
|
||||
// (This search is backwards since it's fairly common that the user is clicking the same
|
||||
// window multiple times in a row, and so that saves a tiny bit of perf doing it this way)
|
||||
for (int i=recentlyInteractedWindows.Count-1; i>=0; i--)
|
||||
{
|
||||
if (recentlyInteractedWindows[i] == window)
|
||||
{
|
||||
// Window already in the list
|
||||
|
||||
// Is window the top most recent entry?
|
||||
if (i == recentlyInteractedWindows.Count-1)
|
||||
return; // Then there's nothing to do, it's already in the right spot
|
||||
else
|
||||
{
|
||||
// Need to remove the old entry so it can be readded (no duplicates in list allowed)
|
||||
recentlyInteractedWindows.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that the list has been checked for duplicates, okay to add new window at end of tracking
|
||||
recentlyInteractedWindows.Add(window);
|
||||
}
|
||||
|
||||
private BaseWindow? GetWindowForControl(Control? control)
|
||||
{
|
||||
if (control == null)
|
||||
return null;
|
||||
|
||||
if (control is BaseWindow)
|
||||
return (BaseWindow) control;
|
||||
|
||||
// Go up the hierarchy until we find a window (or don't)
|
||||
return GetWindowForControl(control.Parent);
|
||||
}
|
||||
|
||||
private void OnRootChildAdded(Control control)
|
||||
{
|
||||
if (control is BaseWindow)
|
||||
{
|
||||
// On new window open, add to tracking
|
||||
SetMostRecentlyInteractedWindow((BaseWindow) control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +135,8 @@ ui-options-function-open-tile-spawn-window = Open tile spawn menu
|
||||
ui-options-function-open-decal-spawn-window = Open decal spawn menu
|
||||
ui-options-function-open-admin-menu = Open admin menu
|
||||
ui-options-function-open-guidebook = Open guidebook
|
||||
ui-options-function-window-close-all = Close all windows
|
||||
ui-options-function-window-close-recent = Close recent window
|
||||
|
||||
ui-options-function-take-screenshot = Take screenshot
|
||||
ui-options-function-take-screenshot-no-ui = Take screenshot (without UI)
|
||||
@@ -214,4 +216,4 @@ ui-options-net-pvs-leave-tooltip = This limits the rate at which the client will
|
||||
|
||||
## Toggle window console command
|
||||
cmd-options-desc = Opens options menu, optionally with a specific tab selected.
|
||||
cmd-options-help = Usage: options [tab]
|
||||
cmd-options-help = Usage: options [tab]
|
||||
|
||||
@@ -79,7 +79,7 @@ binds:
|
||||
# Misc
|
||||
- function: ShowEscapeMenu
|
||||
type: State
|
||||
key: Escape
|
||||
key: F12
|
||||
- function: CycleChatChannelForward
|
||||
type: State
|
||||
key: Tab
|
||||
@@ -404,6 +404,13 @@ binds:
|
||||
type: State
|
||||
key: Tab
|
||||
mod1: Shift
|
||||
- function: WindowCloseRecent
|
||||
type: State
|
||||
key: Escape
|
||||
- function: WindowCloseAll
|
||||
type: State
|
||||
key: Escape
|
||||
mod1: Shift
|
||||
- function: Point
|
||||
type: State
|
||||
key: MouseMiddle
|
||||
|
||||
Reference in New Issue
Block a user