]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
UI: Close window hotkeys (#15227)
authorSkye <22365940+Skyedra@users.noreply.github.com>
Sun, 9 Apr 2023 02:19:32 +0000 (19:19 -0700)
committerGitHub <noreply@github.com>
Sun, 9 Apr 2023 02:19:32 +0000 (19:19 -0700)
Content.Client/Options/UI/Tabs/KeyRebindTab.xaml.cs
Content.Client/UserInterface/Systems/CloseWindow/CloseAllWindowsUIController.cs [new file with mode: 0644]
Content.Client/UserInterface/Systems/CloseWindow/CloseRecentWindowUIController.cs [new file with mode: 0644]
Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
Resources/keybinds.yml

index 68003612eb7772c398499bc30be608f68e5cff57..28ec8d93923eb6fd6f05f97eec1c7f487eccbfb9 100644 (file)
@@ -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);
diff --git a/Content.Client/UserInterface/Systems/CloseWindow/CloseAllWindowsUIController.cs b/Content.Client/UserInterface/Systems/CloseWindow/CloseAllWindowsUIController.cs
new file mode 100644 (file)
index 0000000..0ec9b53
--- /dev/null
@@ -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();
+            }
+        }
+    }
+}
+
diff --git a/Content.Client/UserInterface/Systems/CloseWindow/CloseRecentWindowUIController.cs b/Content.Client/UserInterface/Systems/CloseWindow/CloseRecentWindowUIController.cs
new file mode 100644 (file)
index 0000000..18f2072
--- /dev/null
@@ -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);
+        }
+    }
+}
+
index 58cf96f942e38bb3907743b98f769b07938b15ad..86e4b613367b506c4c699b9d10ab642bb32d4361 100644 (file)
@@ -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]
\ No newline at end of file
+cmd-options-help = Usage: options [tab]
index 8fa3d13de68b9cdf797433ec7fba96457f36db66..b76d62116634f4f2670e4b5b3a1c7af204cf233d 100644 (file)
@@ -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