| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- 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()));
- }
- /// <summary>
- /// Closes the most recently focused window.
- /// </summary>
- public 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>
- public 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);
- }
- }
- /// <summary>
- /// Checks whether there are any windows that can be closed.
- /// </summary>
- /// <returns></returns>
- public bool HasClosableWindow()
- {
- for (var i = recentlyInteractedWindows.Count - 1; i >= 0; i--)
- {
- var window = recentlyInteractedWindows[i];
- if (window.IsOpen)
- return true;
- // continue going down the list, hoping to find a still-open window
- }
- return false;
- }
- }
|