]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Revert "Remove some BUI boilerplate" (#30214)
authorNemanja <98561806+EmoGarbage404@users.noreply.github.com>
Sun, 21 Jul 2024 00:42:27 +0000 (20:42 -0400)
committerGitHub <noreply@github.com>
Sun, 21 Jul 2024 00:42:27 +0000 (20:42 -0400)
Revert "Remove some BUI boilerplate (#28399)"

This reverts commit cbf329a82d77eed2bb5e51666dab5d8a21fd3fff.

137 files changed:
Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs
Content.Client/Access/UI/AccessOverriderWindow.xaml.cs
Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs
Content.Client/Access/UI/AgentIDCardWindow.xaml.cs
Content.Client/Ame/UI/AmeControllerBoundUserInterface.cs
Content.Client/Ame/UI/AmeWindow.xaml.cs
Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs
Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs
Content.Client/Arcade/BlockGameMenu.cs
Content.Client/Arcade/SpaceVillainArcadeMenu.cs
Content.Client/Arcade/UI/BlockGameBoundUserInterface.cs
Content.Client/Arcade/UI/SpaceVillainArcadeBoundUserInterface.cs
Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs
Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs
Content.Client/Atmos/UI/GasCanisterBoundUserInterface.cs
Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs
Content.Client/Atmos/UI/GasFilterWindow.xaml.cs
Content.Client/Atmos/UI/GasMixerBoundUserInteface.cs
Content.Client/Atmos/UI/GasPressurePumpBoundUserInterface.cs
Content.Client/Atmos/UI/GasThermomachineBoundUserInterface.cs
Content.Client/Atmos/UI/GasVolumePumpBoundUserInterface.cs
Content.Client/Atmos/UI/SpaceHeaterBoundUserInterface.cs
Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs
Content.Client/Bed/Cryostorage/CryostorageBoundUserInterface.cs
Content.Client/Cargo/BUI/CargoBountyConsoleBoundUserInterface.cs
Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs
Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs
Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs
Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs
Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs
Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs
Content.Client/CloningConsole/UI/CloningConsoleBoundUserInterface.cs
Content.Client/Clothing/UI/ChameleonBoundUserInterface.cs
Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs
Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs
Content.Client/Computer/ComputerBoundUserInterface.cs
Content.Client/Configurable/UI/ConfigurationBoundUserInterface.cs
Content.Client/Configurable/UI/ConfigurationMenu.cs
Content.Client/Construction/UI/FlatpackCreatorBoundUserInterface.cs
Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs
Content.Client/Crayon/UI/CrayonBoundUserInterface.cs
Content.Client/Crayon/UI/CrayonWindow.xaml.cs
Content.Client/Disposal/UI/DisposalRouterBoundUserInterface.cs
Content.Client/Disposal/UI/DisposalTaggerBoundUserInterface.cs
Content.Client/Doors/Electronics/DoorElectronicsBoundUserInterface.cs
Content.Client/Doors/Electronics/DoorElectronicsConfigurationMenu.xaml.cs
Content.Client/Fax/UI/FaxBoundUi.cs
Content.Client/Forensics/ForensicScannerBoundUserInterface.cs
Content.Client/Gateway/UI/GatewayBoundUserInterface.cs
Content.Client/Gateway/UI/GatewayWindow.xaml.cs
Content.Client/Gravity/UI/GravityGeneratorBoundUserInterface.cs
Content.Client/Gravity/UI/GravityGeneratorWindow.xaml.cs
Content.Client/HealthAnalyzer/UI/HealthAnalyzerBoundUserInterface.cs
Content.Client/Humanoid/HumanoidMarkingModifierBoundUserInterface.cs
Content.Client/Instruments/UI/BandMenu.xaml.cs
Content.Client/Instruments/UI/ChannelsMenu.xaml.cs
Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs
Content.Client/Instruments/UI/InstrumentMenu.xaml.cs
Content.Client/Inventory/StrippableBoundUserInterface.cs
Content.Client/Kitchen/UI/GrinderMenu.xaml.cs
Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs
Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs
Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs
Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs
Content.Client/Lathe/UI/LatheBoundUserInterface.cs
Content.Client/Lathe/UI/LatheMenu.xaml.cs
Content.Client/MachineLinking/UI/SignalTimerBoundUserInterface.cs
Content.Client/MachineLinking/UI/SignalTimerWindow.xaml.cs
Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs
Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs
Content.Client/MassMedia/Ui/NewsWriterMenu.xaml.cs
Content.Client/Mech/Ui/MechBoundUserInterface.cs
Content.Client/Mech/Ui/MechMenu.xaml.cs
Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs
Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs
Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs
Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs
Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs
Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs
Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs
Content.Client/Nuke/NukeBoundUserInterface.cs
Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs
Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs
Content.Client/PDA/PdaBoundUserInterface.cs
Content.Client/PDA/Ringer/RingerBoundUserInterface.cs
Content.Client/Paper/UI/PaperBoundUserInterface.cs
Content.Client/Paper/UI/PaperWindow.xaml.cs
Content.Client/ParticleAccelerator/UI/ParticleAcceleratorBoundUserInterface.cs
Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs
Content.Client/Pinpointer/UI/NavMapBeaconBoundUserInterface.cs
Content.Client/Pinpointer/UI/NavMapBeaconWindow.xaml.cs
Content.Client/Pinpointer/UI/StationMapBoundUserInterface.cs
Content.Client/Pinpointer/UI/StationMapWindow.xaml.cs
Content.Client/Pinpointer/UI/UntrackedMapBoundUserInterface.cs
Content.Client/Power/APC/ApcBoundUserInterface.cs
Content.Client/Power/APC/UI/ApcMenu.xaml.cs
Content.Client/Power/Generator/GeneratorWindow.xaml.cs
Content.Client/Power/Generator/PortableGeneratorBoundUserInterface.cs
Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs
Content.Client/Power/PowerMonitoringWindow.xaml.Widgets.cs
Content.Client/Power/PowerMonitoringWindow.xaml.cs
Content.Client/RCD/RCDMenu.xaml.cs
Content.Client/RCD/RCDMenuBoundUserInterface.cs
Content.Client/Radio/Ui/IntercomBoundUserInterface.cs
Content.Client/Radio/Ui/IntercomMenu.xaml.cs
Content.Client/Research/UI/DiskConsoleBoundUserInterface.cs
Content.Client/Research/UI/ResearchClientBoundUserInterface.cs
Content.Client/Research/UI/ResearchClientServerSelectionMenu.xaml.cs
Content.Client/Research/UI/ResearchConsoleBoundUserInterface.cs
Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs
Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs
Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs
Content.Client/Salvage/UI/SalvageExpeditionConsoleBoundUserInterface.cs
Content.Client/Salvage/UI/SalvageMagnetBoundUserInterface.cs
Content.Client/Shuttles/BUI/IFFConsoleBoundUserInterface.cs
Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs
Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs
Content.Client/Silicons/Borgs/BorgBoundUserInterface.cs
Content.Client/Silicons/Borgs/BorgMenu.xaml
Content.Client/Silicons/Borgs/BorgMenu.xaml.cs
Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs
Content.Client/SprayPainter/UI/SprayPainterBoundUserInterface.cs
Content.Client/StationRecords/GeneralStationRecordConsoleBoundUserInterface.cs
Content.Client/Store/Ui/StoreBoundUserInterface.cs
Content.Client/Strip/StrippingMenu.cs
Content.Client/SurveillanceCamera/UI/SurveillanceCameraMonitorBoundUi.cs
Content.Client/Thief/ThiefBackpackBoundUserInterface.cs
Content.Client/Thief/ThiefBackpackMenu.xaml.cs
Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs
Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs
Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs
Content.Client/VoiceMask/VoiceMaskBoundUserInterface.cs
Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs
Content.Client/Weapons/Melee/UI/MeleeSpeechBoundUserInterface.cs
Content.Client/Wires/UI/WiresBoundUserInterface.cs
Content.Client/Wires/UI/WiresMenu.cs
Content.Client/Xenoarchaeology/Ui/AnalysisConsoleBoundUserInterface.cs

index d80c600c03e9c6673d0d41d31a0565299a57209d..c1b63dc4d05895d002c4c9ef5880005494f36cb3 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Access;
 using Content.Shared.Access.Components;
 using Content.Shared.Access.Systems;
 using Content.Shared.Containers.ItemSlots;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 using static Content.Shared.Access.Components.AccessOverriderComponent;
 
@@ -24,28 +23,6 @@ namespace Content.Client.Access.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<AccessOverriderWindow>();
-            RefreshAccess();
-            _window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
-            _window.OnSubmit += SubmitData;
-
-            _window.PrivilegedIdButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(PrivilegedIdCardSlotId));
-        }
-
-        public override void OnProtoReload(PrototypesReloadedEventArgs args)
-        {
-            base.OnProtoReload(args);
-            if (!args.WasModified<AccessLevelPrototype>())
-                return;
-
-            RefreshAccess();
-
-            if (State != null)
-                _window?.UpdateState(_prototypeManager, (AccessOverriderBoundUserInterfaceState) State);
-        }
-
-        private void RefreshAccess()
-        {
             List<ProtoId<AccessLevelPrototype>> accessLevels;
 
             if (EntMan.TryGetComponent<AccessOverriderComponent>(Owner, out var accessOverrider))
@@ -53,20 +30,38 @@ namespace Content.Client.Access.UI
                 accessLevels = accessOverrider.AccessLevels;
                 accessLevels.Sort();
             }
+
             else
             {
                 accessLevels = new List<ProtoId<AccessLevelPrototype>>();
                 _accessOverriderSystem.Log.Error($"No AccessOverrider component found for {EntMan.ToPrettyString(Owner)}!");
             }
 
-            _window?.SetAccessLevels(_prototypeManager, accessLevels);
+            _window = new AccessOverriderWindow(this, _prototypeManager, accessLevels)
+            {
+                Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName
+            };
+
+            _window.PrivilegedIdButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(PrivilegedIdCardSlotId));
+
+            _window.OnClose += Close;
+            _window.OpenCentered();
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            _window?.Dispose();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
         {
             base.UpdateState(state);
             var castState = (AccessOverriderBoundUserInterfaceState) state;
-            _window?.UpdateState(_prototypeManager, castState);
+            _window?.UpdateState(castState);
         }
 
         public void SubmitData(List<ProtoId<AccessLevelPrototype>> newAccessList)
index ba087718583e061973dab7e29799d89fb090f258..6025c3b551fd6623e4065c5152ebeed5ea45229f 100644 (file)
@@ -13,24 +13,26 @@ namespace Content.Client.Access.UI
     [GenerateTypedNameReferences]
     public sealed partial class AccessOverriderWindow : DefaultWindow
     {
-        private readonly Dictionary<string, Button> _accessButtons = new();
+        [Dependency] private readonly ILogManager _logManager = default!;
+        [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
 
-        public event Action<List<ProtoId<AccessLevelPrototype>>>? OnSubmit;
+        private readonly AccessOverriderBoundUserInterface _owner;
+        private readonly Dictionary<string, Button> _accessButtons = new();
 
-        public AccessOverriderWindow()
+        public AccessOverriderWindow(AccessOverriderBoundUserInterface owner, IPrototypeManager prototypeManager,
+            List<ProtoId<AccessLevelPrototype>> accessLevels)
         {
             RobustXamlLoader.Load(this);
-        }
+            IoCManager.InjectDependencies(this);
+            var logMill = _logManager.GetSawmill(SharedAccessOverriderSystem.Sawmill);
 
-        public void SetAccessLevels(IPrototypeManager protoManager, List<ProtoId<AccessLevelPrototype>> accessLevels)
-        {
-            _accessButtons.Clear();
-            AccessLevelGrid.DisposeAllChildren();
+            _owner = owner;
 
             foreach (var access in accessLevels)
             {
-                if (!protoManager.TryIndex(access, out var accessLevel))
+                if (!prototypeManager.TryIndex(access, out var accessLevel))
                 {
+                    logMill.Error($"Unable to find accesslevel for {access}");
                     continue;
                 }
 
@@ -42,16 +44,11 @@ namespace Content.Client.Access.UI
 
                 AccessLevelGrid.AddChild(newButton);
                 _accessButtons.Add(accessLevel.ID, newButton);
-                newButton.OnPressed += _ =>
-                {
-                    OnSubmit?.Invoke(
-                        // Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair
-                        _accessButtons.Where(x => x.Value.Pressed).Select(x => new ProtoId<AccessLevelPrototype>(x.Key)).ToList());
-                };
+                newButton.OnPressed += _ => SubmitData();
             }
         }
 
-        public void UpdateState(IPrototypeManager protoManager, AccessOverriderBoundUserInterfaceState state)
+        public void UpdateState(AccessOverriderBoundUserInterfaceState state)
         {
             PrivilegedIdLabel.Text = state.PrivilegedIdName;
             PrivilegedIdButton.Text = state.IsPrivilegedIdPresent
@@ -69,11 +66,11 @@ namespace Content.Client.Access.UI
 
             if (state.MissingPrivilegesList != null && state.MissingPrivilegesList.Any())
             {
-                var missingPrivileges = new List<string>();
+                List<string> missingPrivileges = new List<string>();
 
                 foreach (string tag in state.MissingPrivilegesList)
                 {
-                    var privilege = Loc.GetString(protoManager.Index<AccessLevelPrototype>(tag)?.Name ?? "generic-unknown");
+                    string privilege = Loc.GetString(_prototypeManager.Index<AccessLevelPrototype>(tag)?.Name ?? "generic-unknown");
                     missingPrivileges.Add(privilege);
                 }
 
@@ -93,5 +90,13 @@ namespace Content.Client.Access.UI
                 }
             }
         }
+
+        private void SubmitData()
+        {
+            _owner.SubmitData(
+
+                // Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair
+                _accessButtons.Where(x => x.Value.Pressed).Select(x => new ProtoId<AccessLevelPrototype>(x.Key)).ToList());
+        }
     }
 }
index 50add43dc91bf76729385327a826610343f67d15..761f52988a9da43c5788cc2a8e54bdbc212d9b11 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Access.Systems;
 using Content.Shared.StatusIcon;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.Access.UI
@@ -21,11 +20,16 @@ namespace Content.Client.Access.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<AgentIDCardWindow>();
+            _window?.Dispose();
+            _window = new AgentIDCardWindow(this);
+            if (State != null)
+                UpdateState(State);
 
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
             _window.OnNameChanged += OnNameChanged;
             _window.OnJobChanged += OnJobChanged;
-            _window.OnJobIconChanged += OnJobIconChanged;
         }
 
         private void OnNameChanged(string newName)
@@ -57,5 +61,14 @@ namespace Content.Client.Access.UI
             _window.SetCurrentJob(cast.CurrentJob);
             _window.SetAllowedIcons(cast.Icons, cast.CurrentJobIconId);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            _window?.Dispose();
+        }
     }
 }
index 071ce41a069841a0e3fbf73bfabba3a5fae3050a..6d0b2a184f49d29fbfae11116d82c0b2bab4a52d 100644 (file)
@@ -17,19 +17,19 @@ namespace Content.Client.Access.UI
         [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
         [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
         private readonly SpriteSystem _spriteSystem;
+        private readonly AgentIDCardBoundUserInterface _bui;
 
         private const int JobIconColumnCount = 10;
 
         public event Action<string>? OnNameChanged;
         public event Action<string>? OnJobChanged;
 
-        public event Action<ProtoId<StatusIconPrototype>>? OnJobIconChanged;
-
-        public AgentIDCardWindow()
+        public AgentIDCardWindow(AgentIDCardBoundUserInterface bui)
         {
             RobustXamlLoader.Load(this);
             IoCManager.InjectDependencies(this);
             _spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>();
+            _bui = bui;
 
             NameLineEdit.OnTextEntered += e => OnNameChanged?.Invoke(e.Text);
             NameLineEdit.OnFocusExit += e => OnNameChanged?.Invoke(e.Text);
@@ -67,7 +67,7 @@ namespace Content.Client.Access.UI
                 };
 
                 // Generate buttons textures
-                var jobIconTexture = new TextureRect
+                TextureRect jobIconTexture = new TextureRect
                 {
                     Texture = _spriteSystem.Frame0(jobIcon.Icon),
                     TextureScale = new Vector2(2.5f, 2.5f),
@@ -75,7 +75,7 @@ namespace Content.Client.Access.UI
                 };
 
                 jobIconButton.AddChild(jobIconTexture);
-                jobIconButton.OnPressed += _ => OnJobIconChanged?.Invoke(jobIcon.ID);
+                jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIconId);
                 IconGrid.AddChild(jobIconButton);
 
                 if (jobIconId.Equals(currentJobIconId))
index 3d65f7518990c8fe32b7c0ffa2bf520e5c0a1a39..e84cf5d34de8b6740fd04de39367f9f4e46b8a89 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Ame.Components;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Ame.UI
 {
@@ -17,8 +16,9 @@ namespace Content.Client.Ame.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<AmeWindow>();
-            _window.OnAmeButton += ButtonPressed;
+            _window = new AmeWindow(this);
+            _window.OnClose += Close;
+            _window.OpenCentered();
         }
 
         /// <summary>
@@ -40,5 +40,15 @@ namespace Content.Client.Ame.UI
         {
             SendMessage(new UiButtonPressedMessage(button));
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _window?.Dispose();
+            }
+        }
     }
 }
index d6d580bcdaf96ecdfcd2666de4c103f9d833e386..8b91ec596609bdc35ff6ae0611f5a16c51bec92f 100644 (file)
@@ -1,4 +1,3 @@
-using System.Linq;
 using Content.Client.UserInterface;
 using Content.Shared.Ame.Components;
 using Robust.Client.AutoGenerated;
@@ -10,17 +9,15 @@ namespace Content.Client.Ame.UI
     [GenerateTypedNameReferences]
     public sealed partial class AmeWindow : DefaultWindow
     {
-        public event Action<UiButton>? OnAmeButton;
-
-        public AmeWindow()
+        public AmeWindow(AmeControllerBoundUserInterface ui)
         {
             RobustXamlLoader.Load(this);
             IoCManager.InjectDependencies(this);
 
-            EjectButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.Eject);
-            ToggleInjection.OnPressed += _ => OnAmeButton?.Invoke(UiButton.ToggleInjection);
-            IncreaseFuelButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.IncreaseFuel);
-            DecreaseFuelButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.DecreaseFuel);
+            EjectButton.OnPressed += _ => ui.ButtonPressed(UiButton.Eject);
+            ToggleInjection.OnPressed += _ => ui.ButtonPressed(UiButton.ToggleInjection);
+            IncreaseFuelButton.OnPressed += _ => ui.ButtonPressed(UiButton.IncreaseFuel);
+            DecreaseFuelButton.OnPressed += _ => ui.ButtonPressed(UiButton.DecreaseFuel);
         }
 
         /// <summary>
@@ -32,7 +29,7 @@ namespace Content.Client.Ame.UI
             var castState = (AmeControllerBoundUserInterfaceState) state;
 
             // Disable all buttons if not powered
-            if (Contents.Children.Any())
+            if (Contents.Children != null)
             {
                 ButtonHelpers.SetButtonDisabledRecursive(Contents, !castState.HasPower);
                 EjectButton.Disabled = false;
@@ -68,8 +65,8 @@ namespace Content.Client.Ame.UI
             CoreCount.Text = $"{castState.CoreCount}";
             InjectionAmount.Text = $"{castState.InjectionAmount}";
             // format power statistics to pretty numbers
-            CurrentPowerSupply.Text = $"{castState.CurrentPowerSupply:N1}";
-            TargetedPowerSupply.Text = $"{castState.TargetedPowerSupply:N1}";
+            CurrentPowerSupply.Text = $"{castState.CurrentPowerSupply.ToString("N1")}";
+            TargetedPowerSupply.Text = $"{castState.TargetedPowerSupply.ToString("N1")}";
         }
     }
 }
index 5d1985485c4b930180c8aba9507512cebc3dc9da..5764d0a097d428d5bf8f88f08e24845f3b9cb115 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Anomaly;
 using Content.Shared.Gravity;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Anomaly.Ui;
 
@@ -19,8 +18,10 @@ public sealed class AnomalyGeneratorBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<AnomalyGeneratorWindow>();
-        _window.SetEntity(Owner);
+        _window = new(Owner);
+
+        _window.OpenCentered();
+        _window.OnClose += Close;
 
         _window.OnGenerateButtonPressed += () =>
         {
@@ -36,5 +37,18 @@ public sealed class AnomalyGeneratorBoundUserInterface : BoundUserInterface
             return;
         _window?.UpdateState(msg);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing) return;
+
+        _window?.Dispose();
+    }
+
+    public void SetPowerSwitch(bool on)
+    {
+        SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(on));
+    }
 }
 
index 82d41192dd0e29d74f4e13a0490b593c1e5cc0d6..08438e2a1b28b1517375f289b406ab6e19815201 100644 (file)
@@ -18,21 +18,17 @@ public sealed partial class AnomalyGeneratorWindow : FancyWindow
 
     public Action? OnGenerateButtonPressed;
 
-    public AnomalyGeneratorWindow()
+    public AnomalyGeneratorWindow(EntityUid gen)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
 
+        EntityView.SetEntity(gen);
         EntityView.SpriteOffset = false;
 
         GenerateButton.OnPressed += _ => OnGenerateButtonPressed?.Invoke();
     }
 
-    public void SetEntity(EntityUid uid)
-    {
-        EntityView.SetEntity(uid);
-    }
-
     public void UpdateState(AnomalyGeneratorUserInterfaceState state)
     {
         _cooldownEnd = state.CooldownEndTime;
index 4a579fc4bf4d352ba74ae73abedab669c863fb14..eeda2a31020988be629f0b101b42e2d0e7633426 100644 (file)
@@ -28,6 +28,8 @@ namespace Content.Client.Arcade
 
         private static readonly Vector2 BlockSize = new(15, 15);
 
+        private readonly BlockGameBoundUserInterface _owner;
+
         private readonly PanelContainer _mainPanel;
 
         private readonly BoxContainer _gameRootContainer;
@@ -56,11 +58,10 @@ namespace Content.Client.Arcade
         private bool _isPlayer = false;
         private bool _gameOver = false;
 
-        public event Action<BlockGamePlayerAction>? OnAction;
-
-        public BlockGameMenu()
+        public BlockGameMenu(BlockGameBoundUserInterface owner)
         {
             Title = Loc.GetString("blockgame-menu-title");
+            _owner = owner;
 
             MinSize = SetSize = new Vector2(410, 490);
 
@@ -175,7 +176,7 @@ namespace Content.Client.Arcade
             };
             _newGameButton.OnPressed += (e) =>
             {
-                OnAction?.Invoke(BlockGamePlayerAction.NewGame);
+                _owner.SendAction(BlockGamePlayerAction.NewGame);
             };
             pauseMenuContainer.AddChild(_newGameButton);
             pauseMenuContainer.AddChild(new Control { MinSize = new Vector2(1, 10) });
@@ -185,10 +186,7 @@ namespace Content.Client.Arcade
                 Text = Loc.GetString("blockgame-menu-button-scoreboard"),
                 TextAlign = Label.AlignMode.Center
             };
-            _scoreBoardButton.OnPressed += (e) =>
-            {
-                OnAction?.Invoke(BlockGamePlayerAction.ShowHighscores);
-            };
+            _scoreBoardButton.OnPressed += (e) => _owner.SendAction(BlockGamePlayerAction.ShowHighscores);
             pauseMenuContainer.AddChild(_scoreBoardButton);
             _unpauseButtonMargin = new Control { MinSize = new Vector2(1, 10), Visible = false };
             pauseMenuContainer.AddChild(_unpauseButtonMargin);
@@ -201,7 +199,7 @@ namespace Content.Client.Arcade
             };
             _unpauseButton.OnPressed += (e) =>
             {
-                OnAction?.Invoke(BlockGamePlayerAction.Unpause);
+                _owner.SendAction(BlockGamePlayerAction.Unpause);
             };
             pauseMenuContainer.AddChild(_unpauseButton);
 
@@ -259,7 +257,7 @@ namespace Content.Client.Arcade
             };
             _finalNewGameButton.OnPressed += (e) =>
             {
-                OnAction?.Invoke(BlockGamePlayerAction.NewGame);
+                _owner.SendAction(BlockGamePlayerAction.NewGame);
             };
             gameOverMenuContainer.AddChild(_finalNewGameButton);
 
@@ -329,10 +327,7 @@ namespace Content.Client.Arcade
                 Text = Loc.GetString("blockgame-menu-button-back"),
                 TextAlign = Label.AlignMode.Center
             };
-            _highscoreBackButton.OnPressed += (e) =>
-            {
-                OnAction?.Invoke(BlockGamePlayerAction.Pause);
-            };
+            _highscoreBackButton.OnPressed += (e) => _owner.SendAction(BlockGamePlayerAction.Pause);
             menuContainer.AddChild(_highscoreBackButton);
 
             menuInnerPanel.AddChild(menuContainer);
@@ -478,7 +473,7 @@ namespace Content.Client.Arcade
 
         private void TryPause()
         {
-            OnAction?.Invoke(BlockGamePlayerAction.Pause);
+            _owner.SendAction(BlockGamePlayerAction.Pause);
         }
 
         public void SetStarted()
@@ -581,19 +576,19 @@ namespace Content.Client.Arcade
                 return;
 
             else if (args.Function == ContentKeyFunctions.ArcadeLeft)
-                OnAction?.Invoke(BlockGamePlayerAction.StartLeft);
+                _owner.SendAction(BlockGamePlayerAction.StartLeft);
             else if (args.Function == ContentKeyFunctions.ArcadeRight)
-                OnAction?.Invoke(BlockGamePlayerAction.StartRight);
+                _owner.SendAction(BlockGamePlayerAction.StartRight);
             else if (args.Function == ContentKeyFunctions.ArcadeUp)
-                OnAction?.Invoke(BlockGamePlayerAction.Rotate);
+                _owner.SendAction(BlockGamePlayerAction.Rotate);
             else if (args.Function == ContentKeyFunctions.Arcade3)
-                OnAction?.Invoke(BlockGamePlayerAction.CounterRotate);
+                _owner.SendAction(BlockGamePlayerAction.CounterRotate);
             else if (args.Function == ContentKeyFunctions.ArcadeDown)
-                OnAction?.Invoke(BlockGamePlayerAction.SoftdropStart);
+                _owner.SendAction(BlockGamePlayerAction.SoftdropStart);
             else if (args.Function == ContentKeyFunctions.Arcade2)
-                OnAction?.Invoke(BlockGamePlayerAction.Hold);
+                _owner.SendAction(BlockGamePlayerAction.Hold);
             else if (args.Function == ContentKeyFunctions.Arcade1)
-                OnAction?.Invoke(BlockGamePlayerAction.Harddrop);
+                _owner.SendAction(BlockGamePlayerAction.Harddrop);
         }
 
         protected override void KeyBindUp(GUIBoundKeyEventArgs args)
@@ -604,11 +599,11 @@ namespace Content.Client.Arcade
                 return;
 
             else if (args.Function == ContentKeyFunctions.ArcadeLeft)
-                OnAction?.Invoke(BlockGamePlayerAction.EndLeft);
+                _owner.SendAction(BlockGamePlayerAction.EndLeft);
             else if (args.Function == ContentKeyFunctions.ArcadeRight)
-                OnAction?.Invoke(BlockGamePlayerAction.EndRight);
+                _owner.SendAction(BlockGamePlayerAction.EndRight);
             else if (args.Function == ContentKeyFunctions.ArcadeDown)
-                OnAction?.Invoke(BlockGamePlayerAction.SoftdropEnd);
+                _owner.SendAction(BlockGamePlayerAction.SoftdropEnd);
         }
 
         public void UpdateNextBlock(BlockGameBlock[] blocks)
index 1ee4c2681840654e3b49af25001ea51e822325d3..e5542a5848e94c227f60a9cc59d031f43a3fd969 100644 (file)
@@ -8,6 +8,8 @@ namespace Content.Client.Arcade
 {
     public sealed class SpaceVillainArcadeMenu : DefaultWindow
     {
+        public SpaceVillainArcadeBoundUserInterface Owner { get; set; }
+
         private readonly Label _enemyNameLabel;
         private readonly Label _playerInfoLabel;
         private readonly Label _enemyInfoLabel;
@@ -15,13 +17,11 @@ namespace Content.Client.Arcade
         private readonly Label _enemyActionLabel;
 
         private readonly Button[] _gameButtons = new Button[3]; //used to disable/enable all game buttons
-
-        public event Action<SharedSpaceVillainArcadeComponent.PlayerAction>? OnPlayerAction;
-
-        public SpaceVillainArcadeMenu()
+        public SpaceVillainArcadeMenu(SpaceVillainArcadeBoundUserInterface owner)
         {
             MinSize = SetSize = new Vector2(300, 225);
             Title = Loc.GetString("spacevillain-menu-title");
+            Owner = owner;
 
             var grid = new GridContainer { Columns = 1 };
 
@@ -47,43 +47,32 @@ namespace Content.Client.Arcade
             grid.AddChild(_enemyActionLabel);
 
             var buttonGrid = new GridContainer { Columns = 3 };
-            _gameButtons[0] = new Button()
+            _gameButtons[0] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Attack)
             {
                 Text = Loc.GetString("spacevillain-menu-button-attack")
             };
-
-            _gameButtons[0].OnPressed +=
-                _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Attack);
             buttonGrid.AddChild(_gameButtons[0]);
 
-            _gameButtons[1] = new Button()
+            _gameButtons[1] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Heal)
             {
                 Text = Loc.GetString("spacevillain-menu-button-heal")
             };
-
-            _gameButtons[1].OnPressed +=
-                _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Heal);
             buttonGrid.AddChild(_gameButtons[1]);
 
-            _gameButtons[2] = new Button()
+            _gameButtons[2] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Recharge)
             {
                 Text = Loc.GetString("spacevillain-menu-button-recharge")
             };
-
-            _gameButtons[2].OnPressed +=
-                _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Recharge);
             buttonGrid.AddChild(_gameButtons[2]);
 
             centerContainer = new CenterContainer();
             centerContainer.AddChild(buttonGrid);
             grid.AddChild(centerContainer);
 
-            var newGame = new Button()
+            var newGame = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.NewGame)
             {
                 Text = Loc.GetString("spacevillain-menu-button-new-game")
             };
-
-            newGame.OnPressed += _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.NewGame);
             grid.AddChild(newGame);
 
             Contents.AddChild(grid);
@@ -110,5 +99,23 @@ namespace Content.Client.Arcade
             _playerActionLabel.Text = message.PlayerActionMessage;
             _enemyActionLabel.Text = message.EnemyActionMessage;
         }
+
+        private sealed class ActionButton : Button
+        {
+            private readonly SpaceVillainArcadeBoundUserInterface _owner;
+            private readonly SharedSpaceVillainArcadeComponent.PlayerAction _playerAction;
+
+            public ActionButton(SpaceVillainArcadeBoundUserInterface owner, SharedSpaceVillainArcadeComponent.PlayerAction playerAction)
+            {
+                _owner = owner;
+                _playerAction = playerAction;
+                OnPressed += Clicked;
+            }
+
+            private void Clicked(ButtonEventArgs e)
+            {
+                _owner.SendAction(_playerAction);
+            }
+        }
     }
 }
index 8fa8035afd6620bad56f710dfadfdb9137283371..1a3422dec0fb5e0aeafeef2b8e11ad6016656e77 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Arcade;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Arcade.UI;
 
@@ -16,7 +15,9 @@ public sealed class BlockGameBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<BlockGameMenu>();
+        _menu = new BlockGameMenu(this);
+        _menu.OnClose += Close;
+        _menu.OpenCentered();
     }
 
     protected override void ReceiveMessage(BoundUserInterfaceMessage message)
index c0704530de24ed057526fec661cfd5ee7e213be8..40bbe8b2d8c721c6e58bd113deacf5bb13008454 100644 (file)
@@ -1,5 +1,4 @@
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.GameObjects;
 using Robust.Shared.ViewVariables;
 using static Content.Shared.Arcade.SharedSpaceVillainArcadeComponent;
@@ -10,6 +9,8 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface
 {
     [ViewVariables] private SpaceVillainArcadeMenu? _menu;
 
+    //public SharedSpaceVillainArcadeComponent SpaceVillainArcade;
+
     public SpaceVillainArcadeBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
     {
         SendAction(PlayerAction.RequestData);
@@ -24,7 +25,10 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<SpaceVillainArcadeMenu>();
+        _menu = new SpaceVillainArcadeMenu(this);
+
+        _menu.OnClose += Close;
+        _menu.OpenCentered();
     }
 
     protected override void ReceiveMessage(BoundUserInterfaceMessage message)
@@ -32,4 +36,12 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface
         if (message is SpaceVillainArcadeDataUpdateMessage msg)
             _menu?.UpdateInfo(msg);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        if (disposing)
+            _menu?.Dispose();
+    }
 }
index 2ae15188355de88bbf189cf0cc87a50e1b08b6a7..8f3b507c806e7142243cf92ea9167b1943956d68 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Atmos;
 using Content.Shared.Atmos.Monitor;
 using Content.Shared.Atmos.Monitor.Components;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.GameObjects;
 using Robust.Shared.IoC;
 using Robust.Shared.Log;
@@ -21,9 +20,16 @@ public sealed class AirAlarmBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<AirAlarmWindow>();
-        _window.SetEntity(Owner);
+        _window = new AirAlarmWindow(this);
 
+        if (State != null)
+        {
+            UpdateState(State);
+        }
+
+        _window.OpenCentered();
+
+        _window.OnClose += Close;
         _window.AtmosDeviceDataChanged += OnDeviceDataChanged;
                _window.AtmosDeviceDataCopied += OnDeviceDataCopied;
         _window.AtmosAlarmThresholdChanged += OnThresholdChanged;
index eeec11c7660cc598c240da0844397bc3ae3d81c5..43be67c9d6bb8758907afe5e66e4b6fa99fec2ae 100644 (file)
@@ -47,7 +47,7 @@ public sealed partial class AirAlarmWindow : FancyWindow
 
     private CheckBox _autoMode => AutoModeCheckBox;
 
-    public AirAlarmWindow()
+    public AirAlarmWindow(BoundUserInterface owner)
     {
         RobustXamlLoader.Load(this);
 
@@ -95,11 +95,8 @@ public sealed partial class AirAlarmWindow : FancyWindow
             _sensors.Clear();
             ResyncAllRequested!.Invoke();
         };
-    }
 
-    public void SetEntity(EntityUid uid)
-    {
-        EntityView.SetEntity(uid);
+        EntityView.SetEntity(owner.Owner);
     }
 
     public void UpdateState(AirAlarmUIState state)
index 7bf9b396d5e02d3bc9eed20767380a7d4341a84d..a5e316a8defc66e41589410e1586a475389bfab9 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Atmos.Piping.Binary.Components;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Atmos.UI
 {
@@ -22,8 +21,14 @@ namespace Content.Client.Atmos.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<GasCanisterWindow>();
+            _window = new GasCanisterWindow();
 
+            if (State != null)
+                UpdateState(State);
+
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
             _window.ReleaseValveCloseButtonPressed += OnReleaseValveClosePressed;
             _window.ReleaseValveOpenButtonPressed += OnReleaseValveOpenPressed;
             _window.ReleasePressureSet += OnReleasePressureSet;
index 2b8020924cf3bbee16708a579ae336519a10f90b..1904e2b3402a041f82a8a44ec9010dfa18131991 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.Atmos;
 using Content.Shared.Atmos.Piping.Trinary.Components;
 using Content.Shared.Localizations;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Atmos.UI
 {
@@ -29,8 +28,14 @@ namespace Content.Client.Atmos.UI
 
             var atmosSystem = EntMan.System<AtmosphereSystem>();
 
-            _window = this.CreateWindow<GasFilterWindow>();
-            _window.PopulateGasList(atmosSystem.Gases);
+            _window = new GasFilterWindow(atmosSystem.Gases);
+
+            if (State != null)
+                UpdateState(State);
+
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
 
             _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
             _window.FilterTransferRateChanged += OnFilterTransferRatePressed;
index 62748b52592ba36df823005fb9190d1c7f7d7b59..28766c688a0ede11d61484bb2fd6b1984466ab78 100644 (file)
@@ -26,9 +26,10 @@ namespace Content.Client.Atmos.UI
         public event Action<string>? FilterTransferRateChanged;
         public event Action? SelectGasPressed;
 
-        public GasFilterWindow()
+        public GasFilterWindow(IEnumerable<GasPrototype> gases)
         {
             RobustXamlLoader.Load(this);
+            PopulateGasList(gases);
 
             ToggleStatusButton.OnPressed += _ => SetFilterStatus(!FilterStatus);
             ToggleStatusButton.OnPressed += _ => ToggleStatusButtonPressed?.Invoke();
@@ -72,7 +73,7 @@ namespace Content.Client.Atmos.UI
             SelectGasButton.Disabled = true;
         }
 
-        public void PopulateGasList(IEnumerable<GasPrototype> gases)
+        private void PopulateGasList(IEnumerable<GasPrototype> gases)
         {
             GasList.Add(new ItemList.Item(GasList)
             {
@@ -80,7 +81,7 @@ namespace Content.Client.Atmos.UI
                 Text = Loc.GetString("comp-gas-filter-ui-filter-gas-none")
             });
 
-            foreach (var gas in gases)
+            foreach (GasPrototype gas in gases)
             {
                 var gasName = Loc.GetString(gas.Name);
                 GasList.Add(GetGasItem(gas.ID, gasName, GasList));
index 392fbf1cd9a9fe5ca24d5e9c24393448ed027cca..709c06517cb310c505a2d6369343e67768eb364a 100644 (file)
@@ -2,7 +2,7 @@ using Content.Shared.Atmos;
 using Content.Shared.Atmos.Piping.Trinary.Components;
 using Content.Shared.Localizations;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
+using Robust.Client.GameObjects;
 
 namespace Content.Client.Atmos.UI
 {
@@ -26,7 +26,14 @@ namespace Content.Client.Atmos.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<GasMixerWindow>();
+            _window = new GasMixerWindow();
+
+            if (State != null)
+                UpdateState(State);
+
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
 
             _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
             _window.MixerOutputPressureChanged += OnMixerOutputPressurePressed;
@@ -76,5 +83,12 @@ namespace Content.Client.Atmos.UI
             _window.SetOutputPressure(cast.OutputPressure);
             _window.SetNodePercentages(cast.NodeOne);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+            _window?.Dispose();
+        }
     }
 }
index 220fdbe875c929ad929080fbdc53fad5c963c06d..6eba2e0d2154114e360d46469d64f2a097a7a621 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.Atmos.Piping.Binary.Components;
 using Content.Shared.Localizations;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Atmos.UI
 {
@@ -27,7 +26,14 @@ namespace Content.Client.Atmos.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<GasPressurePumpWindow>();
+            _window = new GasPressurePumpWindow();
+
+            if (State != null)
+                UpdateState(State);
+
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
 
             _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
             _window.PumpOutputPressureChanged += OnPumpOutputPressurePressed;
@@ -61,5 +67,12 @@ namespace Content.Client.Atmos.UI
             _window.SetPumpStatus(cast.Enabled);
             _window.SetOutputPressure(cast.OutputPressure);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+            _window?.Dispose();
+        }
     }
 }
index d62be8f4bb4243ba130c48f9ddf7b03367e7e2ef..1664c8b9d750c320d828d996e95e953239f6de6f 100644 (file)
@@ -2,7 +2,6 @@
 using Content.Shared.Atmos.Piping.Unary.Components;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Atmos.UI
 {
@@ -32,7 +31,14 @@ namespace Content.Client.Atmos.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<GasThermomachineWindow>();
+            _window = new GasThermomachineWindow();
+
+            if (State != null)
+                UpdateState(State);
+
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
 
             _window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed();
             _window.TemperatureSpinbox.OnValueChanged += _ => OnTemperatureChanged(_window.TemperatureSpinbox.Value);
@@ -85,5 +91,12 @@ namespace Content.Client.Atmos.UI
                 true => Loc.GetString("comp-gas-thermomachine-ui-title-heater")
             };
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+            _window?.Dispose();
+        }
     }
 }
index 642f34c2f92f939da5f2f894b17f9e0d425e5eea..1b39306181a1c52911e63fb502bece3c8422d533 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.Atmos.Piping.Binary.Components;
 using Content.Shared.Localizations;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Atmos.UI
 {
@@ -27,7 +26,14 @@ namespace Content.Client.Atmos.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<GasVolumePumpWindow>();
+            _window = new GasVolumePumpWindow();
+
+            if (State != null)
+                UpdateState(State);
+
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
 
             _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed;
             _window.PumpTransferRateChanged += OnPumpTransferRatePressed;
@@ -58,9 +64,16 @@ namespace Content.Client.Atmos.UI
             if (_window == null || state is not GasVolumePumpBoundUserInterfaceState cast)
                 return;
 
-            _window.Title = cast.PumpLabel;
+            _window.Title = (cast.PumpLabel);
             _window.SetPumpStatus(cast.Enabled);
             _window.SetTransferRate(cast.TransferRate);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+            _window?.Dispose();
+        }
     }
 }
index e70426575d4b5da71228de1368304a968d2b591e..4d8d1191e912c1dc79b081a947093ed02f43351d 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Atmos.Piping.Portable.Components;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 
 namespace Content.Client.Atmos.UI;
@@ -22,7 +21,14 @@ public sealed class SpaceHeaterBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<SpaceHeaterWindow>();
+        _window = new SpaceHeaterWindow();
+
+        if (State != null)
+            UpdateState(State);
+
+        _window.OpenCentered();
+
+        _window.OnClose += Close;
 
         _window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed();
         _window.IncreaseTempRange.OnPressed += _ => OnTemperatureRangeChanged(_window.TemperatureChangeDelta);
index 865dfc478d0680fc1e174d79b08f19014a7a4c40..60fe339069af6dedf3b918053945dcc47730ad9b 100644 (file)
@@ -1,7 +1,8 @@
 using Content.Shared.Audio.Jukebox;
 using Robust.Client.Audio;
-using Robust.Client.UserInterface;
+using Robust.Client.Player;
 using Robust.Shared.Audio.Components;
+using Robust.Shared.Player;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.Audio.Jukebox;
@@ -22,7 +23,9 @@ public sealed class JukeboxBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<JukeboxMenu>();
+        _menu = new JukeboxMenu();
+        _menu.OnClose += Close;
+        _menu.OpenCentered();
 
         _menu.OnPlayPressed += args =>
         {
@@ -97,5 +100,19 @@ public sealed class JukeboxBoundUserInterface : BoundUserInterface
 
         SendMessage(new JukeboxSetTimeMessage(sentTime));
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+
+        if (_menu == null)
+            return;
+
+        _menu.OnClose -= Close;
+        _menu.Dispose();
+        _menu = null;
+    }
 }
 
index 09f3cec8fbf4e9a409c7dc6564acfc760e12bb0a..ffab1625483f6b015a2fdffa941f93da547671d2 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Bed.Cryostorage;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Bed.Cryostorage;
 
@@ -18,7 +17,9 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<CryostorageMenu>();
+        _menu = new();
+
+        _menu.OnClose += Close;
 
         _menu.SlotRemoveButtonPressed += (ent, slot) =>
         {
@@ -29,6 +30,8 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface
         {
             SendMessage(new CryostorageRemoveItemBuiMessage(ent, hand, CryostorageRemoveItemBuiMessage.RemovalType.Hand));
         };
+
+        _menu.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -42,4 +45,12 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface
                 break;
         }
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+        _menu?.Dispose();
+    }
 }
index 44c40143d830a2fb236c1773f435542783f41344..d3365702bcfc54bb346e48a72cfffef748291c78 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Client.Cargo.UI;
 using Content.Shared.Cargo.Components;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Cargo.BUI;
 
@@ -19,7 +18,9 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<CargoBountyMenu>();
+        _menu = new();
+
+        _menu.OnClose += Close;
 
         _menu.OnLabelButtonPressed += id =>
         {
@@ -30,6 +31,8 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
         {
             SendMessage(new BountySkipMessage(id));
         };
+
+        _menu.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState message)
@@ -41,4 +44,14 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface
 
         _menu?.UpdateEntries(state.Bounties, state.UntilNextSkip);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        if (!disposing)
+            return;
+
+        _menu?.Dispose();
+    }
 }
index 2461dafb5f39daee57ec5430123205fd52f0787b..20c23a48a0d50d4bda8976bb2a500374dd7691ad 100644 (file)
@@ -2,7 +2,6 @@ using Content.Client.Cargo.UI;
 using Content.Shared.Cargo.BUI;
 using Content.Shared.Cargo.Events;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Cargo.BUI;
 
@@ -19,9 +18,21 @@ public sealed class CargoPalletConsoleBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<CargoPalletMenu>();
+        _menu = new CargoPalletMenu();
         _menu.AppraiseRequested += OnAppraisal;
         _menu.SellRequested += OnSell;
+        _menu.OnClose += Close;
+
+        _menu.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (disposing)
+        {
+            _menu?.Dispose();
+        }
     }
 
     private void OnAppraisal()
index 02b721b902007e45aa468e920779ac6ce8060674..422d03707a01c949f3367d9e1017fde4fae16ce0 100644 (file)
@@ -2,7 +2,6 @@ using Content.Client.Cargo.UI;
 using Content.Shared.Cargo.BUI;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.Cargo.BUI;
@@ -10,8 +9,6 @@ namespace Content.Client.Cargo.BUI;
 [UsedImplicitly]
 public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface
 {
-    [Dependency] private readonly IPrototypeManager _protoManager = default!;
-
     [ViewVariables]
     private CargoShuttleMenu? _menu;
 
@@ -22,7 +19,24 @@ public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         base.Open();
-        _menu = this.CreateWindow<CargoShuttleMenu>();
+        var collection = IoCManager.Instance;
+
+        if (collection == null)
+            return;
+
+        _menu = new CargoShuttleMenu(collection.Resolve<IPrototypeManager>(), collection.Resolve<IEntitySystemManager>().GetEntitySystem<SpriteSystem>());
+        _menu.OnClose += Close;
+
+        _menu.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (disposing)
+        {
+            _menu?.Dispose();
+        }
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -31,6 +45,6 @@ public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface
         if (state is not CargoShuttleConsoleBoundUserInterfaceState cargoState) return;
         _menu?.SetAccountName(cargoState.AccountName);
         _menu?.SetShuttleName(cargoState.ShuttleName);
-        _menu?.SetOrders(EntMan.System<SpriteSystem>(), _protoManager, cargoState.Orders);
+        _menu?.SetOrders(cargoState.Orders);
     }
 }
index 43b00089e167e74a683550cc59a3faa60672984d..c591f917da3b5b8ca4099bd0aba1f8f0a5c6b5d2 100644 (file)
@@ -12,9 +12,14 @@ namespace Content.Client.Cargo.UI
     [GenerateTypedNameReferences]
     public sealed partial class CargoShuttleMenu : FancyWindow
     {
-        public CargoShuttleMenu()
+        private readonly IPrototypeManager _protoManager;
+        private readonly SpriteSystem _spriteSystem;
+
+        public CargoShuttleMenu(IPrototypeManager protoManager, SpriteSystem spriteSystem)
         {
             RobustXamlLoader.Load(this);
+            _protoManager = protoManager;
+            _spriteSystem = spriteSystem;
             Title = Loc.GetString("cargo-shuttle-console-menu-title");
         }
 
@@ -28,19 +33,19 @@ namespace Content.Client.Cargo.UI
             ShuttleNameLabel.Text = name;
         }
 
-        public void SetOrders(SpriteSystem sprites, IPrototypeManager protoManager, List<CargoOrderData> orders)
+        public void SetOrders(List<CargoOrderData> orders)
         {
             Orders.DisposeAllChildren();
 
             foreach (var order in orders)
             {
-                 var product = protoManager.Index<EntityPrototype>(order.ProductId);
+                 var product = _protoManager.Index<EntityPrototype>(order.ProductId);
                  var productName = product.Name;
 
                  var row = new CargoOrderRow
                  {
                      Order = order,
-                     Icon = { Texture = sprites.Frame0(product) },
+                     Icon = { Texture = _spriteSystem.Frame0(product) },
                      ProductName =
                      {
                          Text = Loc.GetString(
index 3ef7f0ae73ed19f95dbc689fedf84d35e243df1b..988fea7978b5966a027fe1e250b34c33437478ae 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Chemistry;
 using Content.Shared.Containers.ItemSlots;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Chemistry.UI
 {
@@ -28,8 +27,13 @@ namespace Content.Client.Chemistry.UI
             base.Open();
 
             // Setup window layout/elements
-            _window = this.CreateWindow<ChemMasterWindow>();
-            _window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
+            _window = new ChemMasterWindow
+            {
+                Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName,
+            };
+
+            _window.OpenCentered();
+            _window.OnClose += Close;
 
             // Setup static button actions.
             _window.InputEjectButton.OnPressed += _ => SendMessage(
@@ -71,5 +75,15 @@ namespace Content.Client.Chemistry.UI
 
             _window?.UpdateState(castState); // Update window state
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _window?.Dispose();
+            }
+        }
     }
 }
index 2ad1b71888791bc442415f36ae4445292946f826..99e5a3d39536248d153f1216ad1913ac745a6fa1 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.Chemistry;
 using Content.Shared.Containers.ItemSlots;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Chemistry.UI
 {
@@ -16,6 +15,9 @@ namespace Content.Client.Chemistry.UI
         [ViewVariables]
         private ReagentDispenserWindow? _window;
 
+        [ViewVariables]
+        private ReagentDispenserBoundUserInterfaceState? _lastState;
+
         public ReagentDispenserBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
         {
         }
@@ -30,9 +32,14 @@ namespace Content.Client.Chemistry.UI
             base.Open();
 
             // Setup window layout/elements
-            _window = this.CreateWindow<ReagentDispenserWindow>();
-            _window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
-            _window.HelpGuidebookIds = EntMan.GetComponent<GuideHelpComponent>(Owner).Guides;
+            _window = new()
+            {
+                Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName,
+                HelpGuidebookIds = EntMan.GetComponent<GuideHelpComponent>(Owner).Guides
+            };
+
+            _window.OpenCentered();
+            _window.OnClose += Close;
 
             // Setup static button actions.
             _window.EjectButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(SharedReagentDispenser.OutputSlotName));
@@ -56,7 +63,19 @@ namespace Content.Client.Chemistry.UI
             base.UpdateState(state);
 
             var castState = (ReagentDispenserBoundUserInterfaceState) state;
+            _lastState = castState;
+
             _window?.UpdateState(castState); //Update window state
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _window?.Dispose();
+            }
+        }
     }
 }
index f1cb27a62a4217957e4a4ff6ccf65b0139550c43..35df131312d127983161ad9ea303a53c60357816 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Chemistry;
 using Content.Shared.FixedPoint;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Chemistry.UI
 {
@@ -19,7 +18,7 @@ namespace Content.Client.Chemistry.UI
         protected override void Open()
         {
             base.Open();
-            _window = this.CreateWindow<TransferAmountWindow>();
+            _window = new TransferAmountWindow();
 
             _window.ApplyButton.OnPressed += _ =>
             {
@@ -29,6 +28,15 @@ namespace Content.Client.Chemistry.UI
                     _window.Close();
                 }
             };
+            _window.OnClose += Close;
+            _window.OpenCentered();
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+            _window?.Dispose();
         }
     }
 }
index 62a02f371864c4e35ef71e603b69436c2ff38081..26f0994701ee6a7c3d9ba1b052aac06a88ce93e9 100644 (file)
@@ -1,7 +1,6 @@
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
 using Content.Shared.Cloning.CloningConsole;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.CloningConsole.UI
 {
@@ -18,11 +17,13 @@ namespace Content.Client.CloningConsole.UI
         protected override void Open()
         {
             base.Open();
-
-            _window = this.CreateWindow<CloningConsoleWindow>();
-            _window.Title = Loc.GetString("cloning-console-window-title");
-
+            _window = new CloningConsoleWindow
+            {
+                Title = Loc.GetString("cloning-console-window-title")
+            };
+            _window.OnClose += Close;
             _window.CloneButton.OnPressed += _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone));
+            _window.OpenCentered();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -31,5 +32,19 @@ namespace Content.Client.CloningConsole.UI
 
             _window?.Populate((CloningConsoleBoundUserInterfaceState) state);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            if (_window != null)
+            {
+                _window.OnClose -= Close;
+                _window.CloneButton.OnPressed -= _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone));
+            }
+            _window?.Dispose();
+        }
     }
 }
index 83f6ba156629e10ec076675905769eeb68e40740..5b0d5fcf21f02aeace5e9d09e795fa8b677dbaf9 100644 (file)
@@ -2,7 +2,6 @@
 using Content.Shared.Clothing.Components;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Clothing.UI;
 
@@ -23,8 +22,10 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<ChameleonMenu>();
+        _menu = new ChameleonMenu();
+        _menu.OnClose += Close;
         _menu.OnIdSelected += OnIdSelected;
+        _menu.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -41,4 +42,15 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface
     {
         SendMessage(new ChameleonPrototypeSelectedMessage(selectedId));
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        if (disposing)
+        {
+            _menu?.Close();
+            _menu = null;
+        }
+    }
 }
index 0310e91eeb0a47c11ee5ab02a596f9804d8fb571..1c94d32bf8d17d142c56e93b426d524705474b5d 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.CCVar;
 using Content.Shared.Chat;
 using Content.Shared.Communications;
-using Robust.Client.UserInterface;
 using Robust.Shared.Configuration;
 using Robust.Shared.Timing;
 
@@ -9,11 +8,34 @@ namespace Content.Client.Communications.UI
 {
     public sealed class CommunicationsConsoleBoundUserInterface : BoundUserInterface
     {
+        [Dependency] private readonly IGameTiming _gameTiming = default!;
         [Dependency] private readonly IConfigurationManager _cfg = default!;
 
         [ViewVariables]
         private CommunicationsConsoleMenu? _menu;
 
+        [ViewVariables]
+        public bool CanAnnounce { get; private set; }
+        [ViewVariables]
+        public bool CanBroadcast { get; private set; }
+
+        [ViewVariables]
+        public bool CanCall { get; private set; }
+
+        [ViewVariables]
+        public bool CountdownStarted { get; private set; }
+
+        [ViewVariables]
+        public bool AlertLevelSelectable { get; private set; }
+
+        [ViewVariables]
+        public string CurrentLevel { get; private set; } = default!;
+
+        [ViewVariables]
+        private TimeSpan? _expectedCountdownTime;
+
+        public int Countdown => _expectedCountdownTime == null ? 0 : Math.Max((int) _expectedCountdownTime.Value.Subtract(_gameTiming.CurTime).TotalSeconds, 0);
+
         public CommunicationsConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
         {
         }
@@ -22,25 +44,23 @@ namespace Content.Client.Communications.UI
         {
             base.Open();
 
-            _menu = this.CreateWindow<CommunicationsConsoleMenu>();
-            _menu.OnAnnounce += AnnounceButtonPressed;
-            _menu.OnBroadcast += BroadcastButtonPressed;
-            _menu.OnAlertLevel += AlertLevelSelected;
-            _menu.OnEmergencyLevel += EmergencyShuttleButtonPressed;
+            _menu = new CommunicationsConsoleMenu(this);
+            _menu.OnClose += Close;
+            _menu.OpenCentered();
         }
 
         public void AlertLevelSelected(string level)
         {
-            if (_menu!.AlertLevelSelectable)
+            if (AlertLevelSelectable)
             {
-                _menu.CurrentLevel = level;
+                CurrentLevel = level;
                 SendMessage(new CommunicationsConsoleSelectAlertLevelMessage(level));
             }
         }
 
         public void EmergencyShuttleButtonPressed()
         {
-            if (_menu!.CountdownStarted)
+            if (CountdownStarted)
                 RecallShuttle();
             else
                 CallShuttle();
@@ -75,23 +95,31 @@ namespace Content.Client.Communications.UI
             if (state is not CommunicationsConsoleInterfaceState commsState)
                 return;
 
+            CanAnnounce = commsState.CanAnnounce;
+            CanBroadcast = commsState.CanBroadcast;
+            CanCall = commsState.CanCall;
+            _expectedCountdownTime = commsState.ExpectedCountdownEnd;
+            CountdownStarted = commsState.CountdownStarted;
+            AlertLevelSelectable = commsState.AlertLevels != null && !float.IsNaN(commsState.CurrentAlertDelay) && commsState.CurrentAlertDelay <= 0;
+            CurrentLevel = commsState.CurrentAlert;
+
             if (_menu != null)
             {
-                _menu.CanAnnounce = commsState.CanAnnounce;
-                _menu.CanBroadcast = commsState.CanBroadcast;
-                _menu.CanCall = commsState.CanCall;
-                _menu.CountdownStarted = commsState.CountdownStarted;
-                _menu.AlertLevelSelectable = commsState.AlertLevels != null && !float.IsNaN(commsState.CurrentAlertDelay) && commsState.CurrentAlertDelay <= 0;
-                _menu.CurrentLevel = commsState.CurrentAlert;
-                _menu.CountdownEnd = commsState.ExpectedCountdownEnd;
-
                 _menu.UpdateCountdown();
-                _menu.UpdateAlertLevels(commsState.AlertLevels, _menu.CurrentLevel);
-                _menu.AlertLevelButton.Disabled = !_menu.AlertLevelSelectable;
-                _menu.EmergencyShuttleButton.Disabled = !_menu.CanCall;
-                _menu.AnnounceButton.Disabled = !_menu.CanAnnounce;
-                _menu.BroadcastButton.Disabled = !_menu.CanBroadcast;
+                _menu.UpdateAlertLevels(commsState.AlertLevels, CurrentLevel);
+                _menu.AlertLevelButton.Disabled = !AlertLevelSelectable;
+                _menu.EmergencyShuttleButton.Disabled = !CanCall;
+                _menu.AnnounceButton.Disabled = !CanAnnounce;
+                _menu.BroadcastButton.Disabled = !CanBroadcast;
             }
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+
+            _menu?.Dispose();
+        }
     }
 }
index cef68efd1f38f125401ed92c3ccdc19eca73d709..bbca06f5194ae333c55e4ec709217ec577d9af2d 100644 (file)
@@ -1,40 +1,31 @@
-using System.Globalization;
-using Content.Client.UserInterface.Controls;
+using Content.Client.UserInterface.Controls;
+using System.Threading;
 using Content.Shared.CCVar;
 using Robust.Client.AutoGenerated;
 using Robust.Client.UserInterface.XAML;
 using Robust.Shared.Configuration;
-using Robust.Shared.Timing;
 using Robust.Shared.Utility;
+using Timer = Robust.Shared.Timing.Timer;
 
 namespace Content.Client.Communications.UI
 {
     [GenerateTypedNameReferences]
     public sealed partial class CommunicationsConsoleMenu : FancyWindow
     {
+        private CommunicationsConsoleBoundUserInterface Owner { get; set; }
+        private readonly CancellationTokenSource _timerCancelTokenSource = new();
+
         [Dependency] private readonly IConfigurationManager _cfg = default!;
-        [Dependency] private readonly IGameTiming _timing = default!;
-        [Dependency] private readonly ILocalizationManager _loc = default!;
-
-        public bool CanAnnounce;
-        public bool CanBroadcast;
-        public bool CanCall;
-        public bool AlertLevelSelectable;
-        public bool CountdownStarted;
-        public string CurrentLevel = string.Empty;
-        public TimeSpan? CountdownEnd;
-
-        public event Action? OnEmergencyLevel;
-        public event Action<string>? OnAlertLevel;
-        public event Action<string>? OnAnnounce;
-        public event Action<string>? OnBroadcast;
-
-        public CommunicationsConsoleMenu()
+
+        public CommunicationsConsoleMenu(CommunicationsConsoleBoundUserInterface owner)
         {
             IoCManager.InjectDependencies(this);
             RobustXamlLoader.Load(this);
 
-            MessageInput.Placeholder = new Rope.Leaf(_loc.GetString("comms-console-menu-announcement-placeholder"));
+            Owner = owner;
+
+            var loc = IoCManager.Resolve<ILocalizationManager>();
+            MessageInput.Placeholder = new Rope.Leaf(loc.GetString("comms-console-menu-announcement-placeholder"));
 
             var maxAnnounceLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength);
             MessageInput.OnTextChanged += (args) =>
@@ -46,38 +37,33 @@ namespace Content.Client.Communications.UI
                 }
                 else
                 {
-                    AnnounceButton.Disabled = !CanAnnounce;
+                    AnnounceButton.Disabled = !owner.CanAnnounce;
                     AnnounceButton.ToolTip = null;
 
                 }
             };
 
-            AnnounceButton.OnPressed += _ => OnAnnounce?.Invoke(Rope.Collapse(MessageInput.TextRope));
-            AnnounceButton.Disabled = !CanAnnounce;
+            AnnounceButton.OnPressed += (_) => Owner.AnnounceButtonPressed(Rope.Collapse(MessageInput.TextRope));
+            AnnounceButton.Disabled = !owner.CanAnnounce;
 
-            BroadcastButton.OnPressed += _ => OnBroadcast?.Invoke(Rope.Collapse(MessageInput.TextRope));
-            BroadcastButton.Disabled = !CanBroadcast;
+            BroadcastButton.OnPressed += (_) => Owner.BroadcastButtonPressed(Rope.Collapse(MessageInput.TextRope));
+            BroadcastButton.Disabled = !owner.CanBroadcast;
 
             AlertLevelButton.OnItemSelected += args =>
             {
                 var metadata = AlertLevelButton.GetItemMetadata(args.Id);
                 if (metadata != null && metadata is string cast)
                 {
-                    OnAlertLevel?.Invoke(cast);
+                    Owner.AlertLevelSelected(cast);
                 }
             };
+            AlertLevelButton.Disabled = !owner.AlertLevelSelectable;
 
+            EmergencyShuttleButton.OnPressed += (_) => Owner.EmergencyShuttleButtonPressed();
+            EmergencyShuttleButton.Disabled = !owner.CanCall;
 
-            AlertLevelButton.Disabled = !AlertLevelSelectable;
-
-            EmergencyShuttleButton.OnPressed += _ => OnEmergencyLevel?.Invoke();
-            EmergencyShuttleButton.Disabled = !CanCall;
-        }
-
-        protected override void FrameUpdate(FrameEventArgs args)
-        {
-            base.FrameUpdate(args);
             UpdateCountdown();
+            Timer.SpawnRepeating(1000, UpdateCountdown, _timerCancelTokenSource.Token);
         }
 
         // The current alert could make levels unselectable, so we need to ensure that the UI reacts properly.
@@ -119,19 +105,32 @@ namespace Content.Client.Communications.UI
 
         public void UpdateCountdown()
         {
-            if (!CountdownStarted)
+            if (!Owner.CountdownStarted)
             {
-                CountdownLabel.SetMessage(string.Empty);
+                CountdownLabel.SetMessage("");
                 EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-call-shuttle");
                 return;
             }
 
-            var diff = (CountdownEnd - _timing.CurTime) ?? TimeSpan.Zero;
-
             EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-recall-shuttle");
             var infoText = Loc.GetString($"comms-console-menu-time-remaining",
-            ("time", diff.TotalSeconds.ToString(CultureInfo.CurrentCulture)));
+            ("time", Owner.Countdown.ToString()));
             CountdownLabel.SetMessage(infoText);
         }
+
+        public override void Close()
+        {
+            base.Close();
+
+            _timerCancelTokenSource.Cancel();
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+                _timerCancelTokenSource.Cancel();
+        }
     }
 }
index 11c26b252e9d31a5d7139fe38ff9495049239cf5..bdbfe03fa10929934b904b4e05d36c0e5e2b3b4e 100644 (file)
@@ -1,5 +1,4 @@
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.CustomControls;
 
 namespace Content.Client.Computer
@@ -20,8 +19,10 @@ namespace Content.Client.Computer
         {
             base.Open();
 
-            _window = this.CreateWindow<TWindow>();
+            _window = (TWindow) _dynamicTypeFactory.CreateInstance(typeof(TWindow));
             _window.SetupComputerWindow(this);
+            _window.OnClose += Close;
+            _window.OpenCentered();
         }
 
         // Alas, this constructor has to be copied to the subclass. :(
@@ -41,6 +42,16 @@ namespace Content.Client.Computer
             _window.UpdateState((TState) state);
         }
 
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _window?.Dispose();
+            }
+        }
+
         protected override void ReceiveMessage(BoundUserInterfaceMessage message)
         {
             _window?.ReceiveMessage(message);
index e4966f1ec43cf6fe7dccd92239b51638d16bb5cd..4fea44f2253fbaf04fd61324e061c6fd77c39e43 100644 (file)
@@ -1,6 +1,5 @@
 using System.Text.RegularExpressions;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using static Content.Shared.Configurable.ConfigurationComponent;
 
 namespace Content.Client.Configurable.UI
@@ -10,6 +9,9 @@ namespace Content.Client.Configurable.UI
         [ViewVariables]
         private ConfigurationMenu? _menu;
 
+        [ViewVariables]
+        public Regex? Validation { get; internal set; }
+
         public ConfigurationBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
         {
         }
@@ -17,8 +19,10 @@ namespace Content.Client.Configurable.UI
         protected override void Open()
         {
             base.Open();
-            _menu = this.CreateWindow<ConfigurationMenu>();
-            _menu.OnConfiguration += SendConfiguration;
+            _menu = new ConfigurationMenu(this);
+
+            _menu.OnClose += Close;
+            _menu.OpenCentered();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -26,7 +30,9 @@ namespace Content.Client.Configurable.UI
             base.UpdateState(state);
 
             if (state is not ConfigurationBoundUserInterfaceState configurationState)
+            {
                 return;
+            }
 
             _menu?.Populate(configurationState);
         }
@@ -35,12 +41,9 @@ namespace Content.Client.Configurable.UI
         {
             base.ReceiveMessage(message);
 
-            if (_menu == null)
-                return;
-
             if (message is ValidationUpdateMessage msg)
             {
-                _menu.Validation = new Regex(msg.ValidationString, RegexOptions.Compiled);
+                Validation = new Regex(msg.ValidationString, RegexOptions.Compiled);
             }
         }
 
@@ -48,5 +51,16 @@ namespace Content.Client.Configurable.UI
         {
             SendMessage(new ConfigurationUpdatedMessage(config));
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing && _menu != null)
+            {
+                _menu.OnClose -= Close;
+                _menu.Close();
+            }
+        }
     }
 }
index 29217eef7be159e371dfc690146d2eae48055ee5..cc24af28692bd140c1e134e2b3db3cbd29dc4ead 100644 (file)
@@ -1,6 +1,5 @@
 using System.Collections.Generic;
 using System.Numerics;
-using System.Text.RegularExpressions;
 using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 using Robust.Client.UserInterface.CustomControls;
@@ -14,25 +13,23 @@ namespace Content.Client.Configurable.UI
 {
     public sealed class ConfigurationMenu : DefaultWindow
     {
+        public ConfigurationBoundUserInterface Owner { get; }
+
         private readonly BoxContainer _column;
         private readonly BoxContainer _row;
 
         private readonly List<(string  name, LineEdit input)> _inputs;
 
-        [ViewVariables]
-        public Regex? Validation { get; internal set; }
-
-        public event Action<Dictionary<string, string>>? OnConfiguration;
-
-        public ConfigurationMenu()
+        public ConfigurationMenu(ConfigurationBoundUserInterface owner)
         {
             MinSize = SetSize = new Vector2(300, 250);
+            Owner = owner;
 
             _inputs = new List<(string name, LineEdit input)>();
 
             Title = Loc.GetString("configuration-menu-device-title");
 
-            var baseContainer = new BoxContainer
+            BoxContainer baseContainer = new BoxContainer
             {
                 Orientation = LayoutOrientation.Vertical,
                 VerticalExpand = true,
@@ -119,13 +116,14 @@ namespace Content.Client.Configurable.UI
         private void OnConfirm(ButtonEventArgs args)
         {
             var config = GenerateDictionary(_inputs, "Text");
-            OnConfiguration?.Invoke(config);
+
+            Owner.SendConfiguration(config);
             Close();
         }
 
         private bool Validate(string value)
         {
-            return Validation?.IsMatch(value) != false;
+            return Owner.Validation == null || Owner.Validation.IsMatch(value);
         }
 
         private Dictionary<string, string> GenerateDictionary(IEnumerable<(string name, LineEdit input)> inputs, string propertyName)
index 887492955e9b6b561f7102ee031c885708cb33d3..86f1b8b83c7acd21390681437494cda532c233b4 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Construction.Components;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Construction.UI
 {
@@ -18,8 +17,8 @@ namespace Content.Client.Construction.UI
         {
             base.Open();
 
-            _menu = this.CreateWindow<FlatpackCreatorMenu>();
-            _menu.SetEntity(Owner);
+            _menu = new FlatpackCreatorMenu(Owner);
+            _menu.OnClose += Close;
 
             _menu.PackButtonPressed += () =>
             {
@@ -28,5 +27,14 @@ namespace Content.Client.Construction.UI
 
             _menu.OpenCentered();
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            _menu?.Dispose();
+        }
     }
 }
index 269694ebf9ed87a066a6595a263041eec75f78b8..9f3d5695bb6089c9da4f9107211defd52c4a95ba 100644 (file)
@@ -24,7 +24,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
     private readonly FlatpackSystem _flatpack;
     private readonly MaterialStorageSystem _materialStorage;
 
-    private EntityUid _owner;
+    private readonly EntityUid _owner;
 
     [ValidatePrototypeId<EntityPrototype>]
     public const string NoBoardEffectId = "FlatpackerNoBoardEffect";
@@ -33,7 +33,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
 
     public event Action? PackButtonPressed;
 
-    public FlatpackCreatorMenu()
+    public FlatpackCreatorMenu(EntityUid uid)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
@@ -42,15 +42,12 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow
         _flatpack = _entityManager.System<FlatpackSystem>();
         _materialStorage = _entityManager.System<MaterialStorageSystem>();
 
-        PackButton.OnPressed += _ => PackButtonPressed?.Invoke();
+        _owner = uid;
 
-        InsertLabel.SetMarkup(Loc.GetString("flatpacker-ui-insert-board"));
-    }
+        PackButton.OnPressed += _ => PackButtonPressed?.Invoke();
 
-    public void SetEntity(EntityUid uid)
-    {
-        _owner = uid;
         MaterialStorageControl.SetOwner(uid);
+        InsertLabel.SetMarkup(Loc.GetString("flatpacker-ui-insert-board"));
     }
 
     protected override void FrameUpdate(FrameEventArgs args)
index e5be0b1811f11b8d39150ee3cb908192f2319ec1..e2c4d51ecd18f888d46b7efcdc7329d80f319da8 100644 (file)
@@ -2,15 +2,12 @@
 using Content.Shared.Crayon;
 using Content.Shared.Decals;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.Crayon.UI
 {
     public sealed class CrayonBoundUserInterface : BoundUserInterface
     {
-        [Dependency] private readonly IPrototypeManager _protoManager = default!;
-
         [ViewVariables]
         private CrayonWindow? _menu;
 
@@ -21,27 +18,13 @@ namespace Content.Client.Crayon.UI
         protected override void Open()
         {
             base.Open();
-            _menu = this.CreateWindow<CrayonWindow>();
-            _menu.OnColorSelected += SelectColor;
-            _menu.OnSelected += Select;
-            PopulateCrayons();
-            _menu.OpenCenteredLeft();
-        }
-
-        private void PopulateCrayons()
-        {
-            var crayonDecals = _protoManager.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("crayon"));
-            _menu?.Populate(crayonDecals);
-        }
-
-        public override void OnProtoReload(PrototypesReloadedEventArgs args)
-        {
-            base.OnProtoReload(args);
-
-            if (!args.WasModified<DecalPrototype>())
-                return;
+            _menu = new CrayonWindow(this);
 
-            PopulateCrayons();
+            _menu.OnClose += Close;
+            var prototypeManager = IoCManager.Resolve<IPrototypeManager>();
+            var crayonDecals = prototypeManager.EnumeratePrototypes<DecalPrototype>().Where(x => x.Tags.Contains("crayon"));
+            _menu.Populate(crayonDecals);
+            _menu.OpenCenteredLeft();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -60,5 +43,16 @@ namespace Content.Client.Crayon.UI
         {
             SendMessage(new CrayonColorMessage(color));
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _menu?.Close();
+                _menu = null;
+            }
+        }
     }
 }
index b97786cd41ae2e9dbad64b5fe13dbf87a0fcccff..2a5801ccf2d106abc34657bc5bffb4132f2608ae 100644 (file)
@@ -18,17 +18,18 @@ namespace Content.Client.Crayon.UI
     [GenerateTypedNameReferences]
     public sealed partial class CrayonWindow : DefaultWindow
     {
+        public CrayonBoundUserInterface Owner { get; }
+
         private Dictionary<string, Texture>? _decals;
         private string? _selected;
         private Color _color;
 
-        public event Action<Color>? OnColorSelected;
-        public event Action<string>? OnSelected;
-
-        public CrayonWindow()
+        public CrayonWindow(CrayonBoundUserInterface owner)
         {
             RobustXamlLoader.Load(this);
 
+            Owner = owner;
+
             Search.OnTextChanged += _ => RefreshList();
             ColorSelector.OnColorChanged += SelectColor;
         }
@@ -37,16 +38,16 @@ namespace Content.Client.Crayon.UI
         {
             _color = color;
 
-            OnColorSelected?.Invoke(color);
+            Owner.SelectColor(color);
+
             RefreshList();
         }
 
         private void RefreshList()
         {
             // Clear
-            Grid.DisposeAllChildren();
-            if (_decals == null)
-                return;
+            Grid.RemoveAllChildren();
+            if (_decals == null) return;
 
             var filter = Search.Text;
             foreach (var (decal, tex) in _decals)
@@ -88,6 +89,7 @@ namespace Content.Client.Crayon.UI
         {
             if (obj.Button.Name == null) return;
 
+            Owner.Select(obj.Button.Name);
             _selected = obj.Button.Name;
             RefreshList();
         }
index 296e71d3a9502c8ef66c27b9affa35392cebe7cb..e8e77217ea572c60836211d10b43052e5b2908a9 100644 (file)
@@ -1,6 +1,5 @@
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using static Content.Shared.Disposal.Components.SharedDisposalRouterComponent;
 
 namespace Content.Client.Disposal.UI
@@ -22,16 +21,20 @@ namespace Content.Client.Disposal.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<DisposalRouterWindow>();
+            _window = new DisposalRouterWindow();
+
+            _window.OpenCentered();
+            _window.OnClose += Close;
 
             _window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text);
             _window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text);
+
         }
 
         private void ButtonPressed(UiAction action, string tag)
         {
             SendMessage(new UiActionMessage(action, tag));
-            Close();
+            _window?.Close();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -45,5 +48,18 @@ namespace Content.Client.Disposal.UI
 
             _window?.UpdateState(cast);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _window?.Dispose();
+            }
+        }
+
+
     }
+
 }
index 7fc0eb854017542c75be4ea7a4838b709eb1402f..3aeed8dc802b0541e841407b6303996a8b6a9068 100644 (file)
@@ -1,6 +1,5 @@
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using static Content.Shared.Disposal.Components.SharedDisposalTaggerComponent;
 
 namespace Content.Client.Disposal.UI
@@ -22,17 +21,20 @@ namespace Content.Client.Disposal.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<DisposalTaggerWindow>();
+            _window = new DisposalTaggerWindow();
+
+            _window.OpenCentered();
+            _window.OnClose += Close;
 
             _window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text);
             _window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text);
+
         }
 
         private void ButtonPressed(UiAction action, string tag)
         {
-            // TODO: This looks copy-pasted with the other mailing stuff...
             SendMessage(new UiActionMessage(action, tag));
-            Close();
+            _window?.Close();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -46,5 +48,18 @@ namespace Content.Client.Disposal.UI
 
             _window?.UpdateState(cast);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _window?.Dispose();
+            }
+        }
+
+
     }
+
 }
index 9b7e23c03aafe1f607325e1ad5433652b6f666bb..cd7ea717ce3ce4848d33a785f0bcdca2283473dd 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Access;
 using Content.Shared.Doors.Electronics;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.Doors.Electronics;
@@ -19,23 +18,6 @@ public sealed class DoorElectronicsBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         base.Open();
-        _window = this.CreateWindow<DoorElectronicsConfigurationMenu>();
-        _window.OnAccessChanged += UpdateConfiguration;
-        Reset();
-    }
-
-    public override void OnProtoReload(PrototypesReloadedEventArgs args)
-    {
-        base.OnProtoReload(args);
-
-        if (!args.WasModified<AccessLevelPrototype>())
-            return;
-
-        Reset();
-    }
-
-    private void Reset()
-    {
         List<ProtoId<AccessLevelPrototype>> accessLevels = new();
 
         foreach (var accessLevel in _prototypeManager.EnumeratePrototypes<AccessLevelPrototype>())
@@ -47,7 +29,10 @@ public sealed class DoorElectronicsBoundUserInterface : BoundUserInterface
         }
 
         accessLevels.Sort();
-        _window?.Reset(_prototypeManager, accessLevels);
+
+        _window = new DoorElectronicsConfigurationMenu(this, accessLevels, _prototypeManager);
+        _window.OnClose += Close;
+        _window.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -59,6 +44,14 @@ public sealed class DoorElectronicsBoundUserInterface : BoundUserInterface
         _window?.UpdateState(castState);
     }
 
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing) return;
+
+        _window?.Dispose();
+    }
+
     public void UpdateConfiguration(List<ProtoId<AccessLevelPrototype>> newAccessList)
     {
         SendMessage(new DoorElectronicsUpdateConfigurationMessage(newAccessList));
index 2112a56297119f453f30d60d32433c8902b5c74e..c01f13a462e68010f232532cd9ad7fffecc633b1 100644 (file)
@@ -15,23 +15,22 @@ namespace Content.Client.Doors.Electronics;
 [GenerateTypedNameReferences]
 public sealed partial class DoorElectronicsConfigurationMenu : FancyWindow
 {
-    private readonly AccessLevelControl _buttonsList = new();
+    private readonly DoorElectronicsBoundUserInterface _owner;
+    private AccessLevelControl _buttonsList = new();
 
-    public event Action<List<ProtoId<AccessLevelPrototype>>>? OnAccessChanged;
-
-    public DoorElectronicsConfigurationMenu()
+    public DoorElectronicsConfigurationMenu(DoorElectronicsBoundUserInterface ui, List<ProtoId<AccessLevelPrototype>> accessLevels, IPrototypeManager prototypeManager)
     {
         RobustXamlLoader.Load(this);
-        AccessLevelControlContainer.AddChild(_buttonsList);
-    }
 
-    public void Reset(IPrototypeManager protoManager, List<ProtoId<AccessLevelPrototype>> accessLevels)
-    {
-        _buttonsList.Populate(accessLevels, protoManager);
+        _owner = ui;
+
+        _buttonsList.Populate(accessLevels, prototypeManager);
+        AccessLevelControlContainer.AddChild(_buttonsList);
 
-        foreach (var button in _buttonsList.ButtonsList.Values)
+        foreach (var (id, button) in _buttonsList.ButtonsList)
         {
-            button.OnPressed += _ => OnAccessChanged?.Invoke(_buttonsList.ButtonsList.Where(x => x.Value.Pressed).Select(x => x.Key).ToList());
+            button.OnPressed += _ => _owner.UpdateConfiguration(
+                _buttonsList.ButtonsList.Where(x => x.Value.Pressed).Select(x => x.Key).ToList());
         }
     }
 
index ca2e834b4fe243faaa4760b9157050c335653244..a95066a3b58fbbb6b2e6ab06acd17b465c00a49d 100644 (file)
@@ -25,7 +25,10 @@ public sealed class FaxBoundUi : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<FaxWindow>();
+        _window = new FaxWindow();
+        _window.OpenCentered();
+
+        _window.OnClose += Close;
         _window.FileButtonPressed += OnFileButtonPressed;
         _window.CopyButtonPressed += OnCopyButtonPressed;
         _window.SendButtonPressed += OnSendButtonPressed;
@@ -101,4 +104,11 @@ public sealed class FaxBoundUi : BoundUserInterface
 
         _window.UpdateState(cast);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (disposing)
+            _window?.Dispose();
+    }
 }
index 08596b04e6ecdd626f118a743f8cfafdc969bc39..ba49f11ea0f0e2f006268a23eda51351e115428f 100644 (file)
@@ -1,7 +1,6 @@
 using Robust.Client.GameObjects;
 using Robust.Shared.Timing;
 using Content.Shared.Forensics;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Forensics
 {
@@ -22,9 +21,11 @@ namespace Content.Client.Forensics
         protected override void Open()
         {
             base.Open();
-            _window = this.CreateWindow<ForensicScannerMenu>();
+            _window = new ForensicScannerMenu();
+            _window.OnClose += Close;
             _window.Print.OnPressed += _ => Print();
             _window.Clear.OnPressed += _ => Clear();
+            _window.OpenCentered();
         }
 
         private void Print()
@@ -61,7 +62,6 @@ namespace Content.Client.Forensics
 
             _printCooldown = cast.PrintCooldown;
 
-            // TODO: Fix this
             if (cast.PrintReadyAt > _gameTiming.CurTime)
                 Timer.Spawn(cast.PrintReadyAt - _gameTiming.CurTime, () =>
                 {
@@ -71,5 +71,14 @@ namespace Content.Client.Forensics
 
             _window.UpdateState(cast);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            _window?.Dispose();
+        }
     }
 }
index 457b70ca7cae8dab63d0067a5851c299d611f377..fdb3cdbc0109bcaa1a428e40c6de9e4b77e5aaca 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Gateway;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Gateway.UI;
 
@@ -18,13 +17,24 @@ public sealed class GatewayBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<GatewayWindow>();
-        _window.SetEntity(EntMan.GetNetEntity(Owner));
+        _window = new GatewayWindow(EntMan.GetNetEntity(Owner));
 
         _window.OpenPortal += destination =>
         {
             SendMessage(new GatewayOpenPortalMessage(destination));
         };
+        _window.OnClose += Close;
+        _window?.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (disposing)
+        {
+            _window?.Dispose();
+            _window = null;
+        }
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
index 1c779b2b3508adf26f4d818846dbf5be2b930765..889dd6e175905384356d9e1a763f35ae77826f6b 100644 (file)
@@ -22,7 +22,7 @@ public sealed partial class GatewayWindow : FancyWindow,
     public event Action<NetEntity>? OpenPortal;
     private List<GatewayDestinationData> _destinations = new();
 
-    public NetEntity Owner;
+    public readonly NetEntity Owner;
 
     private NetEntity? _current;
     private TimeSpan _nextReady;
@@ -46,20 +46,16 @@ public sealed partial class GatewayWindow : FancyWindow,
     /// </summary>
     private bool _isCooldownPending = true;
 
-    public GatewayWindow()
+    public GatewayWindow(NetEntity netEntity)
     {
         RobustXamlLoader.Load(this);
         var dependencies = IoCManager.Instance!;
         _timing = dependencies.Resolve<IGameTiming>();
+        Owner = netEntity;
 
         NextUnlockBar.ForegroundStyleBoxOverride = new StyleBoxFlat(Color.FromHex("#C74EBD"));
     }
 
-    public void SetEntity(NetEntity entity)
-    {
-
-    }
-
     public void UpdateState(GatewayBoundUserInterfaceState state)
     {
         _destinations = state.Destinations;
index 32b40747d55945625e03266b3b4397dd8bc358f4..d72da3e8120e2b34cc8ab7ed840140a04d76d621 100644 (file)
@@ -1,6 +1,6 @@
 using Content.Shared.Gravity;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
+using Robust.Client.GameObjects;
 
 namespace Content.Client.Gravity.UI
 {
@@ -18,8 +18,17 @@ namespace Content.Client.Gravity.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<GravityGeneratorWindow>();
-            _window.SetEntity(Owner);
+            _window = new GravityGeneratorWindow(this);
+
+            /*
+            _window.Switch.OnPressed += _ =>
+            {
+                SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(!IsOn));
+            };
+            */
+
+            _window.OpenCentered();
+            _window.OnClose += Close;
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -30,6 +39,14 @@ namespace Content.Client.Gravity.UI
             _window?.UpdateState(castState);
         }
 
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+
+            _window?.Dispose();
+        }
+
         public void SetPowerSwitch(bool on)
         {
             SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(on));
index 6f04133b594cffdb0b7034e1ad6566d3c09676f0..75f8eb479b5c50f1478d3317feed9c47bac8bc93 100644 (file)
@@ -12,23 +12,22 @@ namespace Content.Client.Gravity.UI
     {
         private readonly ButtonGroup _buttonGroup = new();
 
-        public event Action<bool>? OnPowerSwitch;
+        private readonly GravityGeneratorBoundUserInterface _owner;
 
-        public GravityGeneratorWindow()
+        public GravityGeneratorWindow(GravityGeneratorBoundUserInterface owner)
         {
             RobustXamlLoader.Load(this);
             IoCManager.InjectDependencies(this);
 
+            _owner = owner;
+
             OnButton.Group = _buttonGroup;
             OffButton.Group = _buttonGroup;
 
-            OnButton.OnPressed += _ => OnPowerSwitch?.Invoke(true);
-            OffButton.OnPressed += _ => OnPowerSwitch?.Invoke(false);
-        }
+            OnButton.OnPressed += _ => _owner.SetPowerSwitch(true);
+            OffButton.OnPressed += _ => _owner.SetPowerSwitch(false);
 
-        public void SetEntity(EntityUid uid)
-        {
-            EntityView.SetEntity(uid);
+            EntityView.SetEntity(owner.Owner);
         }
 
         public void UpdateState(SharedGravityGeneratorComponent.GeneratorState state)
index 38760f4aa3cd14eb18fddc3b4e3bd8c6eaa3c370..dc0a3e9fccdea9cbf2544bccc606dbb0a4116722 100644 (file)
@@ -1,6 +1,6 @@
 using Content.Shared.MedicalScanner;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
+using Robust.Client.GameObjects;
 
 namespace Content.Client.HealthAnalyzer.UI
 {
@@ -17,9 +17,12 @@ namespace Content.Client.HealthAnalyzer.UI
         protected override void Open()
         {
             base.Open();
-            _window = this.CreateWindow<HealthAnalyzerWindow>();
-
-            _window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
+            _window = new HealthAnalyzerWindow
+            {
+                Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName,
+            };
+            _window.OnClose += Close;
+            _window.OpenCentered();
         }
 
         protected override void ReceiveMessage(BoundUserInterfaceMessage message)
@@ -32,5 +35,17 @@ namespace Content.Client.HealthAnalyzer.UI
 
             _window.Populate(cast);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            if (_window != null)
+                _window.OnClose -= Close;
+
+            _window?.Dispose();
+        }
     }
 }
index 53977eb636b30e40947502de1abf8d9dbfb6f3d7..a8872604a4c9e327b4d175b175c168714362b611 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Humanoid;
 using Content.Shared.Humanoid.Markings;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Humanoid;
 
@@ -21,7 +20,8 @@ public sealed class HumanoidMarkingModifierBoundUserInterface : BoundUserInterfa
     {
         base.Open();
 
-        _window = this.CreateWindow<HumanoidMarkingModifierWindow>();
+        _window = new();
+        _window.OnClose += Close;
         _window.OnMarkingAdded += SendMarkingSet;
         _window.OnMarkingRemoved += SendMarkingSet;
         _window.OnMarkingColorChange += SendMarkingSetNoResend;
index 26cd1369e55de69aa6fe07f2a9ed6eda9994c253..5fb293a194d766d5789cafc5a27fd1136c837fe8 100644 (file)
@@ -11,9 +11,7 @@ public sealed partial class BandMenu : DefaultWindow
 {
     private readonly InstrumentBoundUserInterface _owner;
 
-    public EntityUid? Master;
-
-    public BandMenu(InstrumentBoundUserInterface owner)
+    public BandMenu(InstrumentBoundUserInterface owner) : base()
     {
         RobustXamlLoader.Load(this);
 
@@ -42,7 +40,7 @@ public sealed partial class BandMenu : DefaultWindow
         {
             var uid = entManager.GetEntity(nent);
             var item = BandList.AddItem(name, null, true, uid);
-            item.Selected = Master == uid;
+            item.Selected = _owner.Instrument?.Master == uid;
         }
     }
 }
index c175e67842fbb7457c7feaa34e2abb5c2e245520..2814d415365ce1b17f61747c99feaa6abea8ecbb 100644 (file)
@@ -51,7 +51,7 @@ public sealed partial class ChannelsMenu : DefaultWindow
         }
     }
 
-    public void Populate(InstrumentComponent? instrument)
+    public void Populate()
     {
         ChannelList.Clear();
 
@@ -60,8 +60,7 @@ public sealed partial class ChannelsMenu : DefaultWindow
             var item = ChannelList.AddItem(_owner.Loc.GetString("instrument-component-channel-name",
                 ("number", i)), null, true, i);
 
-
-            item.Selected = !instrument?.FilteredChannels[i] ?? false;
+            item.Selected = !_owner.Instrument?.FilteredChannels[i] ?? false;
         }
     }
 }
index 4816ce8c365b93a006e3574d8f89c948cecfb8fb..0f5729f55b10ec1f59e30200fcf7777b1f631a71 100644 (file)
@@ -24,6 +24,8 @@ namespace Content.Client.Instruments.UI
         [ViewVariables] private BandMenu? _bandMenu;
         [ViewVariables] private ChannelsMenu? _channelsMenu;
 
+        [ViewVariables] public InstrumentComponent? Instrument { get; private set; }
+
         public InstrumentBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
         {
             IoCManager.InjectDependencies(this);
@@ -41,20 +43,14 @@ namespace Content.Client.Instruments.UI
 
         protected override void Open()
         {
-            _instrumentMenu = this.CreateWindow<InstrumentMenu>();
-            _instrumentMenu.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
-
-            _instrumentMenu.OnOpenBand += OpenBandMenu;
-            _instrumentMenu.OnOpenChannels += OpenChannelsMenu;
-            _instrumentMenu.OnCloseChannels += CloseChannelsMenu;
-            _instrumentMenu.OnCloseBands += CloseBandMenu;
+            if (!EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument))
+                return;
 
-            _instrumentMenu.SetMIDI(MidiManager.IsAvailable);
+            Instrument = instrument;
+            _instrumentMenu = new InstrumentMenu(this);
+            _instrumentMenu.OnClose += Close;
 
-            if (EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument))
-            {
-                _instrumentMenu.SetInstrument((Owner, instrument));
-            }
+            _instrumentMenu.OpenCentered();
         }
 
         protected override void Dispose(bool disposing)
@@ -62,12 +58,7 @@ namespace Content.Client.Instruments.UI
             base.Dispose(disposing);
             if (!disposing)
                 return;
-
-            if (EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument))
-            {
-                _instrumentMenu?.RemoveInstrument(instrument);
-            }
-
+            _instrumentMenu?.Dispose();
             _bandMenu?.Dispose();
             _channelsMenu?.Dispose();
         }
@@ -81,11 +72,6 @@ namespace Content.Client.Instruments.UI
         {
             _bandMenu ??= new BandMenu(this);
 
-            if (EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument))
-            {
-                _bandMenu.Master = instrument.Master;
-            }
-
             // Refresh cache...
             RefreshBands();
 
@@ -101,9 +87,7 @@ namespace Content.Client.Instruments.UI
         public void OpenChannelsMenu()
         {
             _channelsMenu ??= new ChannelsMenu(this);
-            EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument);
-
-            _channelsMenu.Populate(instrument);
+            _channelsMenu.Populate();
             _channelsMenu.OpenCenteredRight();
         }
 
index fc863648d798feed88265609578b6220a50ec2bc..da443e3fb5bbec0ca6ad2a0ebd5141e508be7fa6 100644 (file)
@@ -1,10 +1,7 @@
 using System.IO;
 using System.Numerics;
 using System.Threading.Tasks;
-using Content.Client.Interactable;
-using Content.Shared.ActionBlocker;
 using Robust.Client.AutoGenerated;
-using Robust.Client.Player;
 using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.CustomControls;
 using Robust.Client.UserInterface.XAML;
@@ -19,23 +16,33 @@ namespace Content.Client.Instruments.UI
     [GenerateTypedNameReferences]
     public sealed partial class InstrumentMenu : DefaultWindow
     {
-        [Dependency] private readonly IEntityManager _entManager = default!;
-        [Dependency] private readonly IFileDialogManager _dialogs = default!;
-        [Dependency] private readonly IPlayerManager _player = default!;
+        private readonly InstrumentBoundUserInterface _owner;
 
         private bool _isMidiFileDialogueWindowOpen;
 
-        public event Action? OnOpenBand;
-        public event Action? OnOpenChannels;
-        public event Action? OnCloseBands;
-        public event Action? OnCloseChannels;
-
-        public EntityUid Entity;
-
-        public InstrumentMenu()
+        public InstrumentMenu(InstrumentBoundUserInterface owner)
         {
             RobustXamlLoader.Load(this);
-            IoCManager.InjectDependencies(this);
+
+            _owner = owner;
+
+            if (_owner.Instrument != null)
+            {
+                _owner.Instrument.OnMidiPlaybackEnded += InstrumentOnMidiPlaybackEnded;
+                Title = _owner.Entities.GetComponent<MetaDataComponent>(_owner.Owner).EntityName;
+                LoopButton.Disabled = !_owner.Instrument.IsMidiOpen;
+                LoopButton.Pressed = _owner.Instrument.LoopMidi;
+                ChannelsButton.Disabled = !_owner.Instrument.IsRendererAlive;
+                StopButton.Disabled = !_owner.Instrument.IsMidiOpen;
+                PlaybackSlider.MouseFilter = _owner.Instrument.IsMidiOpen ? MouseFilterMode.Pass : MouseFilterMode.Ignore;
+            }
+
+            if (!_owner.MidiManager.IsAvailable)
+            {
+                UnavailableOverlay.Visible = true;
+                // We return early as to not give the buttons behavior.
+                return;
+            }
 
             InputButton.OnToggled += MidiInputButtonOnOnToggled;
             BandButton.OnPressed += BandButtonOnPressed;
@@ -50,34 +57,12 @@ namespace Content.Client.Instruments.UI
             MinSize = SetSize = new Vector2(400, 150);
         }
 
-        public void SetInstrument(Entity<InstrumentComponent> entity)
-        {
-            Entity = entity;
-            var component = entity.Comp;
-            component.OnMidiPlaybackEnded += InstrumentOnMidiPlaybackEnded;
-            LoopButton.Disabled = !component.IsMidiOpen;
-            LoopButton.Pressed = component.LoopMidi;
-            ChannelsButton.Disabled = !component.IsRendererAlive;
-            StopButton.Disabled = !component.IsMidiOpen;
-            PlaybackSlider.MouseFilter = component.IsMidiOpen ? MouseFilterMode.Pass : MouseFilterMode.Ignore;
-        }
-
-        public void RemoveInstrument(InstrumentComponent component)
-        {
-            component.OnMidiPlaybackEnded -= InstrumentOnMidiPlaybackEnded;
-        }
-
-        public void SetMIDI(bool available)
-        {
-            UnavailableOverlay.Visible = !available;
-        }
-
         private void BandButtonOnPressed(ButtonEventArgs obj)
         {
             if (!PlayCheck())
                 return;
 
-            OnOpenBand?.Invoke();
+            _owner.OpenBandMenu();
         }
 
         private void BandButtonOnToggled(ButtonToggledEventArgs obj)
@@ -85,15 +70,12 @@ namespace Content.Client.Instruments.UI
             if (obj.Pressed)
                 return;
 
-            if (_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument))
-            {
-                _entManager.System<InstrumentSystem>().SetMaster(Entity, instrument.Master);
-            }
+            _owner.Instruments.SetMaster(_owner.Owner, null);
         }
 
         private void ChannelsButtonOnPressed(ButtonEventArgs obj)
         {
-            OnOpenChannels?.Invoke();
+            _owner.OpenChannelsMenu();
         }
 
         private void InstrumentOnMidiPlaybackEnded()
@@ -103,10 +85,8 @@ namespace Content.Client.Instruments.UI
 
         public void MidiPlaybackSetButtonsDisabled(bool disabled)
         {
-            if (disabled)
-            {
-                OnCloseChannels?.Invoke();
-            }
+            if(disabled)
+                _owner.CloseChannelsMenu();
 
             LoopButton.Disabled = disabled;
             StopButton.Disabled = disabled;
@@ -120,7 +100,7 @@ namespace Content.Client.Instruments.UI
             if (_isMidiFileDialogueWindowOpen)
                 return;
 
-            OnCloseBands?.Invoke();
+            _owner.CloseBandMenu();
 
             var filters = new FileDialogFilters(new FileDialogFilters.Group("mid", "midi"));
 
@@ -128,7 +108,7 @@ namespace Content.Client.Instruments.UI
             // or focus the previously-opened window.
             _isMidiFileDialogueWindowOpen = true;
 
-            await using var file = await _dialogs.OpenFile(filters);
+            await using var file = await _owner.FileDialogManager.OpenFile(filters);
 
             _isMidiFileDialogueWindowOpen = false;
 
@@ -149,18 +129,9 @@ namespace Content.Client.Instruments.UI
 
             await file.CopyToAsync(memStream);
 
-            if (!_entManager.TryGetComponent<InstrumentComponent>(Entity, out var instrument))
-            {
+            if (_owner.Instrument is not {} instrument
+                || !_owner.Instruments.OpenMidi(_owner.Owner, memStream.GetBuffer().AsSpan(0, (int) memStream.Length), instrument))
                 return;
-            }
-
-            if (!_entManager.System<InstrumentSystem>()
-                    .OpenMidi(Entity,
-                    memStream.GetBuffer().AsSpan(0, (int) memStream.Length),
-                    instrument))
-            {
-                return;
-            }
 
             MidiPlaybackSetButtonsDisabled(false);
             if (InputButton.Pressed)
@@ -169,7 +140,7 @@ namespace Content.Client.Instruments.UI
 
         private void MidiInputButtonOnOnToggled(ButtonToggledEventArgs obj)
         {
-            OnCloseBands?.Invoke();
+            _owner.CloseBandMenu();
 
             if (obj.Pressed)
             {
@@ -177,99 +148,109 @@ namespace Content.Client.Instruments.UI
                     return;
 
                 MidiStopButtonOnPressed(null);
-
-                if (_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument))
-                    _entManager.System<InstrumentSystem>().OpenInput(Entity, instrument);
+                if(_owner.Instrument is {} instrument)
+                    _owner.Instruments.OpenInput(_owner.Owner, instrument);
             }
-            else
+            else if (_owner.Instrument is { } instrument)
             {
-                _entManager.System<InstrumentSystem>().CloseInput(Entity, false);
-                OnCloseChannels?.Invoke();
+                _owner.Instruments.CloseInput(_owner.Owner, false, instrument);
+                _owner.CloseChannelsMenu();
             }
         }
 
         private bool PlayCheck()
         {
             // TODO all of these checks should also be done server-side.
-            if (!_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument))
+
+            var instrumentEnt = _owner.Owner;
+            var instrument = _owner.Instrument;
+
+            if (instrument == null)
                 return false;
 
-            var localEntity = _player.LocalEntity;
+            var localEntity = _owner.PlayerManager.LocalEntity;
 
             // If we don't have a player or controlled entity, we return.
             if (localEntity == null)
                 return false;
 
             // By default, allow an instrument to play itself and skip all other checks
-            if (localEntity == Entity)
+            if (localEntity == instrumentEnt)
                 return true;
 
-            var container = _entManager.System<SharedContainerSystem>();
+            var container = _owner.Entities.System<SharedContainerSystem>();
             // If we're a handheld instrument, we might be in a container. Get it just in case.
-            container.TryGetContainingContainer(Entity, out var conMan);
+            container.TryGetContainingContainer(instrumentEnt, out var conMan);
 
             // If the instrument is handheld and we're not holding it, we return.
-            if (instrument.Handheld && (conMan == null || conMan.Owner != localEntity))
+            if ((instrument.Handheld && (conMan == null || conMan.Owner != localEntity)))
                 return false;
 
-            if (!_entManager.System<ActionBlockerSystem>().CanInteract(localEntity.Value, Entity))
+            if (!_owner.ActionBlocker.CanInteract(localEntity.Value, instrumentEnt))
                 return false;
 
             // We check that we're in range unobstructed just in case.
-            return _entManager.System<InteractionSystem>().InRangeUnobstructed(localEntity.Value, Entity);
+            return _owner.Interactions.InRangeUnobstructed(localEntity.Value, instrumentEnt);
         }
 
         private void MidiStopButtonOnPressed(ButtonEventArgs? obj)
         {
             MidiPlaybackSetButtonsDisabled(true);
 
-            _entManager.System<InstrumentSystem>().CloseMidi(Entity, false);
-            OnCloseChannels?.Invoke();
+            if (_owner.Instrument is not {} instrument)
+                return;
+
+            _owner.Instruments.CloseMidi(_owner.Owner, false, instrument);
+            _owner.CloseChannelsMenu();
         }
 
         private void MidiLoopButtonOnOnToggled(ButtonToggledEventArgs obj)
         {
-            var instrument = _entManager.System<InstrumentSystem>();
-
-            if (_entManager.TryGetComponent(Entity, out InstrumentComponent? instrumentComp))
-            {
-                instrumentComp.LoopMidi = obj.Pressed;
-            }
+            if (_owner.Instrument == null)
+                return;
 
-            instrument.UpdateRenderer(Entity);
+            _owner.Instrument.LoopMidi = obj.Pressed;
+            _owner.Instruments.UpdateRenderer(_owner.Owner, _owner.Instrument);
         }
 
         private void PlaybackSliderSeek(Range _)
         {
             // Do not seek while still grabbing.
-            if (PlaybackSlider.Grabbed)
+            if (PlaybackSlider.Grabbed || _owner.Instrument is not {} instrument)
                 return;
 
-            _entManager.System<InstrumentSystem>().SetPlayerTick(Entity, (int)Math.Ceiling(PlaybackSlider.Value));
+            _owner.Instruments.SetPlayerTick(_owner.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument);
         }
 
         private void PlaybackSliderKeyUp(GUIBoundKeyEventArgs args)
         {
-            if (args.Function != EngineKeyFunctions.UIClick)
+            if (args.Function != EngineKeyFunctions.UIClick || _owner.Instrument is not {} instrument)
                 return;
 
-            _entManager.System<InstrumentSystem>().SetPlayerTick(Entity, (int)Math.Ceiling(PlaybackSlider.Value));
+            _owner.Instruments.SetPlayerTick(_owner.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument);
+        }
+
+        public override void Close()
+        {
+            base.Close();
+            _owner.CloseBandMenu();
+            _owner.CloseChannelsMenu();
         }
 
         protected override void FrameUpdate(FrameEventArgs args)
         {
             base.FrameUpdate(args);
 
-            if (!_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument))
+            if (_owner.Instrument == null)
                 return;
 
-            var hasMaster = instrument.Master != null;
+            var hasMaster = _owner.Instrument.Master != null;
             BandButton.ToggleMode = hasMaster;
             BandButton.Pressed = hasMaster;
-            BandButton.Disabled = instrument.IsMidiOpen || instrument.IsInputOpen;
-            ChannelsButton.Disabled = !instrument.IsRendererAlive;
+            BandButton.Disabled = _owner.Instrument.IsMidiOpen || _owner.Instrument.IsInputOpen;
+            ChannelsButton.Disabled = !_owner.Instrument.IsRendererAlive;
 
-            if (!instrument.IsMidiOpen)
+            if (!_owner.Instrument.IsMidiOpen)
             {
                 PlaybackSlider.MaxValue = 1;
                 PlaybackSlider.SetValueWithoutEvent(0);
@@ -279,8 +260,8 @@ namespace Content.Client.Instruments.UI
             if (PlaybackSlider.Grabbed)
                 return;
 
-            PlaybackSlider.MaxValue = instrument.PlayerTotalTick;
-            PlaybackSlider.SetValueWithoutEvent(instrument.PlayerTick);
+            PlaybackSlider.MaxValue = _owner.Instrument.PlayerTotalTick;
+            PlaybackSlider.SetValueWithoutEvent(_owner.Instrument.PlayerTick);
         }
     }
 }
index 132c5ed654c30aac1e0e5dd46027ef3e81c320c3..7e50eb1c68a5290ae0a0dc76d13ffadfb4539ef5 100644 (file)
@@ -41,7 +41,7 @@ namespace Content.Client.Inventory
         public const string HiddenPocketEntityId = "StrippingHiddenEntity";
 
         [ViewVariables]
-        private StrippingMenu? _strippingMenu;
+        private readonly StrippingMenu? _strippingMenu;
 
         [ViewVariables]
         private readonly EntityUid _virtualHiddenEntity;
@@ -51,30 +51,33 @@ namespace Content.Client.Inventory
             _examine = EntMan.System<ExamineSystem>();
             _inv = EntMan.System<InventorySystem>();
             _cuffable = EntMan.System<SharedCuffableSystem>();
+
+            // TODO update name when identity changes
+            var title = Loc.GetString("strippable-bound-user-interface-stripping-menu-title", ("ownerName", Identity.Name(Owner, EntMan)));
+            _strippingMenu = new StrippingMenu(title, this);
+            _strippingMenu.OnClose += Close;
+
+            // TODO use global entity
+            // BUIs are opened and closed while applying comp sates, so spawning entities here is probably not the best idea.
             _virtualHiddenEntity = EntMan.SpawnEntity(HiddenPocketEntityId, MapCoordinates.Nullspace);
         }
 
         protected override void Open()
         {
             base.Open();
-
-            _strippingMenu = this.CreateWindow<StrippingMenu>();
-            _strippingMenu.OnDirty += UpdateMenu;
-            _strippingMenu.Title = Loc.GetString("strippable-bound-user-interface-stripping-menu-title", ("ownerName", Identity.Name(Owner, EntMan)));
-
             _strippingMenu?.OpenCenteredLeft();
         }
 
         protected override void Dispose(bool disposing)
         {
+            base.Dispose(disposing);
+
+            EntMan.DeleteEntity(_virtualHiddenEntity);
+
             if (!disposing)
                 return;
 
-            if (_strippingMenu != null)
-                _strippingMenu.OnDirty -= UpdateMenu;
-
-            EntMan.DeleteEntity(_virtualHiddenEntity);
-            base.Dispose(disposing);
+            _strippingMenu?.Dispose();
         }
 
         public void DirtyMenu()
index 7884268c4285bf896ff7bb6bf12b7da1e63b524a..f97d8a7330214633b50105a5d3ab142ff00906fc 100644 (file)
@@ -12,34 +12,42 @@ namespace Content.Client.Kitchen.UI
     [GenerateTypedNameReferences]
     public sealed partial class GrinderMenu : FancyWindow
     {
-        [Dependency] private readonly IEntityManager _entityManager = default!;
-        [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+        private readonly IEntityManager _entityManager;
+        private readonly IPrototypeManager _prototypeManager;
+        private readonly ReagentGrinderBoundUserInterface _owner;
 
         private readonly Dictionary<int, EntityUid> _chamberVisualContents = new();
 
-        public event Action? OnToggleAuto;
-        public event Action? OnGrind;
-        public event Action? OnJuice;
-        public event Action? OnEjectAll;
-        public event Action? OnEjectBeaker;
-        public event Action<EntityUid>? OnEjectChamber;
-
-        public GrinderMenu()
+        public GrinderMenu(ReagentGrinderBoundUserInterface owner, IEntityManager entityManager, IPrototypeManager prototypeManager)
         {
             RobustXamlLoader.Load(this);
-            IoCManager.InjectDependencies(this);
-            AutoModeButton.OnPressed += _ => OnToggleAuto?.Invoke();
-            GrindButton.OnPressed += _ => OnGrind?.Invoke();
-            JuiceButton.OnPressed += _ => OnJuice?.Invoke();
-            ChamberContentBox.EjectButton.OnPressed += _ => OnEjectAll?.Invoke();
-            BeakerContentBox.EjectButton.OnPressed += _ => OnEjectBeaker?.Invoke();
+            _entityManager = entityManager;
+            _prototypeManager = prototypeManager;
+            _owner = owner;
+            AutoModeButton.OnPressed += owner.ToggleAutoMode;
+            GrindButton.OnPressed += owner.StartGrinding;
+            JuiceButton.OnPressed += owner.StartJuicing;
+            ChamberContentBox.EjectButton.OnPressed += owner.EjectAll;
+            BeakerContentBox.EjectButton.OnPressed += owner.EjectBeaker;
             ChamberContentBox.BoxContents.OnItemSelected += OnChamberBoxContentsItemSelected;
             BeakerContentBox.BoxContents.SelectMode = ItemList.ItemListSelectMode.None;
         }
 
         private void OnChamberBoxContentsItemSelected(ItemList.ItemListSelectedEventArgs args)
         {
-            OnEjectChamber?.Invoke(_chamberVisualContents[args.ItemIndex]);
+            _owner.EjectChamberContent(_chamberVisualContents[args.ItemIndex]);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            _chamberVisualContents.Clear();
+            GrindButton.OnPressed -= _owner.StartGrinding;
+            JuiceButton.OnPressed -= _owner.StartJuicing;
+            ChamberContentBox.EjectButton.OnPressed -= _owner.EjectAll;
+            BeakerContentBox.EjectButton.OnPressed -= _owner.EjectBeaker;
+            ChamberContentBox.BoxContents.OnItemSelected -= OnChamberBoxContentsItemSelected;
         }
 
         public void UpdateState(ReagentGrinderInterfaceState state)
index 643ac47054bf6843f3ca8e5a11e087df2e6174a6..7e7dd2d6935e027ea3ee91eee6bb391e4a92ef32 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.Kitchen.Components;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
 using Robust.Client.Graphics;
-using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 using Robust.Shared.Timing;
 
@@ -20,15 +19,28 @@ namespace Content.Client.Kitchen.UI
 
         [ViewVariables]
         private readonly Dictionary<int, ReagentQuantity> _reagents = new();
+        [Dependency] private readonly IGameTiming _gameTiming = default!;
+
+        public MicrowaveUpdateUserInterfaceState currentState = default!;
+
+        private IEntityManager _entManager;
 
         public MicrowaveBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
         {
+            _entManager = IoCManager.Resolve<IEntityManager>();
+        }
+
+        public TimeSpan GetCurrentTime()
+        {
+            return _gameTiming.CurTime;
         }
 
         protected override void Open()
         {
             base.Open();
-            _menu = this.CreateWindow<MicrowaveMenu>();
+            _menu = new MicrowaveMenu(this);
+            _menu.OpenCentered();
+            _menu.OnClose += Close;
             _menu.StartButton.OnPressed += _ => SendPredictedMessage(new MicrowaveStartCookMessage());
             _menu.EjectButton.OnPressed += _ => SendPredictedMessage(new MicrowaveEjectMessage());
             _menu.IngredientsList.OnItemSelected += args =>
@@ -62,23 +74,38 @@ namespace Content.Client.Kitchen.UI
             };
         }
 
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (!disposing)
+            {
+                return;
+            }
+
+            _solids.Clear();
+            _menu?.Dispose();
+        }
+
         protected override void UpdateState(BoundUserInterfaceState state)
         {
             base.UpdateState(state);
-            if (state is not MicrowaveUpdateUserInterfaceState cState || _menu == null)
+            if (state is not MicrowaveUpdateUserInterfaceState cState)
             {
                 return;
             }
 
-            _menu.IsBusy = cState.IsMicrowaveBusy;
-            _menu.CurrentCooktimeEnd = cState.CurrentCookTimeEnd;
 
-            _menu.ToggleBusyDisableOverlayPanel(cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0);
+            _menu?.ToggleBusyDisableOverlayPanel(cState.IsMicrowaveBusy || cState.ContainedSolids.Length == 0);
+            currentState = cState;
+
             // TODO move this to a component state and ensure the net ids.
-            RefreshContentsDisplay(EntMan.GetEntityArray(cState.ContainedSolids));
+            RefreshContentsDisplay(_entManager.GetEntityArray(cState.ContainedSolids));
+
+            if (_menu == null) return;
 
             //Set the cook time info label
-            var cookTime = cState.ActiveButtonIndex == 0
+            var cookTime = cState.ActiveButtonIndex == 0 
                 ? Loc.GetString("microwave-menu-instant-button")
                 : cState.CurrentCookTime.ToString();
 
index 7565075f86f5dc7a017c6ce8d27ea7d2212c816b..b292e9f1465c3518bb85f23a274ab4fbcab236b9 100644 (file)
@@ -9,20 +9,22 @@ namespace Content.Client.Kitchen.UI
     [GenerateTypedNameReferences]
     public sealed partial class MicrowaveMenu : FancyWindow
     {
-        [Dependency] private readonly IGameTiming _timing = default!;
+        public sealed class MicrowaveCookTimeButton : Button
+        {
+            public uint CookTime;
+        }
 
         public event Action<BaseButton.ButtonEventArgs, int>? OnCookTimeSelected;
 
         public ButtonGroup CookTimeButtonGroup { get; }
+        private readonly MicrowaveBoundUserInterface _owner;
 
-        public bool IsBusy;
-        public TimeSpan CurrentCooktimeEnd;
-
-        public MicrowaveMenu()
+        public MicrowaveMenu(MicrowaveBoundUserInterface owner)
         {
             RobustXamlLoader.Load(this);
             CookTimeButtonGroup = new ButtonGroup();
             InstantCookButton.Group = CookTimeButtonGroup;
+            _owner = owner;
             InstantCookButton.OnPressed += args =>
             {
                 OnCookTimeSelected?.Invoke(args, 0);
@@ -63,20 +65,14 @@ namespace Content.Client.Kitchen.UI
         protected override void FrameUpdate(FrameEventArgs args)
         {
             base.FrameUpdate(args);
-
-            if (!IsBusy)
+            if(!_owner.currentState.IsMicrowaveBusy)
                 return;
 
-            if (CurrentCooktimeEnd > _timing.CurTime)
+            if(_owner.currentState.CurrentCookTimeEnd > _owner.GetCurrentTime())
             {
                 CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label",
-                ("time", CurrentCooktimeEnd.Subtract(_timing.CurTime).Seconds));
+                ("time",_owner.currentState.CurrentCookTimeEnd.Subtract(_owner.GetCurrentTime()).Seconds)); 
             }
         }
-
-        public sealed class MicrowaveCookTimeButton : Button
-        {
-            public uint CookTime;
-        }
     }
 }
index bc4cc75b4d1b45a41096c4b4a677c59e298061f8..e6f108b3050e03988c6309bfd069fa38ddb7bec8 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Containers.ItemSlots;
 using Content.Shared.Kitchen;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 using Robust.Shared.Prototypes;
 
@@ -9,6 +8,8 @@ namespace Content.Client.Kitchen.UI
 {
     public sealed class ReagentGrinderBoundUserInterface : BoundUserInterface
     {
+        [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+
         [ViewVariables]
         private GrinderMenu? _menu;
 
@@ -20,13 +21,20 @@ namespace Content.Client.Kitchen.UI
         {
             base.Open();
 
-            _menu = this.CreateWindow<GrinderMenu>();
-            _menu.OnToggleAuto += ToggleAutoMode;
-            _menu.OnGrind += StartGrinding;
-            _menu.OnJuice += StartJuicing;
-            _menu.OnEjectAll += EjectAll;
-            _menu.OnEjectBeaker += EjectBeaker;
-            _menu.OnEjectChamber += EjectChamberContent;
+            _menu = new GrinderMenu(this, EntMan, _prototypeManager);
+            _menu.OpenCentered();
+            _menu.OnClose += Close;
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+            {
+                return;
+            }
+
+            _menu?.Dispose();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -44,27 +52,27 @@ namespace Content.Client.Kitchen.UI
             _menu?.HandleMessage(message);
         }
 
-        public void ToggleAutoMode()
+        public void ToggleAutoMode(BaseButton.ButtonEventArgs args)
         {
             SendMessage(new ReagentGrinderToggleAutoModeMessage());
         }
 
-        public void StartGrinding()
+        public void StartGrinding(BaseButton.ButtonEventArgs? _ = null)
         {
             SendMessage(new ReagentGrinderStartMessage(GrinderProgram.Grind));
         }
 
-        public void StartJuicing()
+        public void StartJuicing(BaseButton.ButtonEventArgs? _ = null)
         {
             SendMessage(new ReagentGrinderStartMessage(GrinderProgram.Juice));
         }
 
-        public void EjectAll()
+        public void EjectAll(BaseButton.ButtonEventArgs? _ = null)
         {
             SendMessage(new ReagentGrinderEjectChamberAllMessage());
         }
 
-        public void EjectBeaker()
+        public void EjectBeaker(BaseButton.ButtonEventArgs? _ = null)
         {
             SendMessage(new ItemSlotButtonPressedEvent(SharedReagentGrinder.BeakerSlotId));
         }
index 6b6561234122deee30e7946499753a6bbbb5cb3d..555f1ff09e697bbeed743761e10dde60f8f634c5 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Labels;
 using Content.Shared.Labels.Components;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Labels.UI
 {
@@ -24,8 +23,13 @@ namespace Content.Client.Labels.UI
         {
             base.Open();
 
-            _window = this.CreateWindow<HandLabelerWindow>();
+            _window = new HandLabelerWindow();
+            if (State != null)
+                UpdateState(State);
 
+            _window.OpenCentered();
+
+            _window.OnClose += Close;
             _window.OnLabelChanged += OnLabelChanged;
             Reload();
         }
@@ -47,5 +51,13 @@ namespace Content.Client.Labels.UI
 
             _window.SetCurrentLabel(component.AssignedLabel);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+            _window?.Dispose();
+        }
     }
+
 }
index a599f79152e37ff05a771864636f00597ade3a3f..6e6d1b9176154da25ee71fbb1218434956da96af 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Lathe;
 using Content.Shared.Research.Components;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Lathe.UI
 {
@@ -18,9 +17,9 @@ namespace Content.Client.Lathe.UI
         {
             base.Open();
 
-            _menu = this.CreateWindow<LatheMenu>();
-            _menu.SetEntity(Owner);
-            _menu.OpenCenteredRight();
+            _menu = new LatheMenu(this);
+            _menu.OnClose += Close;
+
 
             _menu.OnServerListButtonPressed += _ =>
             {
@@ -31,6 +30,8 @@ namespace Content.Client.Lathe.UI
             {
                 SendMessage(new LatheQueueRecipeMessage(recipe, amount));
             };
+
+            _menu.OpenCenteredRight();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -49,5 +50,13 @@ namespace Content.Client.Lathe.UI
                     break;
             }
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+            _menu?.Dispose();
+        }
     }
 }
index 6f530b76c75822ba85713aa707ea21e9774f38d1..f2f52b67b5b5b4dbf11ac0fbd733784f8ca8cbf0 100644 (file)
@@ -1,4 +1,3 @@
-using System.Buffers;
 using System.Linq;
 using System.Text;
 using Content.Client.Materials;
@@ -23,6 +22,7 @@ public sealed partial class LatheMenu : DefaultWindow
     [Dependency] private readonly IEntityManager _entityManager = default!;
     [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
 
+    private EntityUid _owner;
     private readonly SpriteSystem _spriteSystem;
     private readonly LatheSystem _lathe;
     private readonly MaterialStorageSystem _materialStorage;
@@ -36,10 +36,9 @@ public sealed partial class LatheMenu : DefaultWindow
 
     public ProtoId<LatheCategoryPrototype>? CurrentCategory;
 
-    public EntityUid Entity;
-
-    public LatheMenu()
+    public LatheMenu(LatheBoundUserInterface owner)
     {
+        _owner = owner.Owner;
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
 
@@ -47,6 +46,8 @@ public sealed partial class LatheMenu : DefaultWindow
         _lathe = _entityManager.System<LatheSystem>();
         _materialStorage = _entityManager.System<MaterialStorageSystem>();
 
+        Title = _entityManager.GetComponent<MetaDataComponent>(owner.Owner).EntityName;
+
         SearchBar.OnTextChanged += _ =>
         {
             PopulateRecipes();
@@ -59,13 +60,8 @@ public sealed partial class LatheMenu : DefaultWindow
         FilterOption.OnItemSelected += OnItemSelected;
 
         ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a);
-    }
 
-    public void SetEntity(EntityUid uid)
-    {
-        Entity = uid;
-
-        if (_entityManager.TryGetComponent<LatheComponent>(Entity, out var latheComponent))
+        if (_entityManager.TryGetComponent<LatheComponent>(owner.Owner, out var latheComponent))
         {
             if (!latheComponent.DynamicRecipes.Any())
             {
@@ -73,7 +69,7 @@ public sealed partial class LatheMenu : DefaultWindow
             }
         }
 
-        MaterialsList.SetOwner(Entity);
+        MaterialsList.SetOwner(owner.Owner);
     }
 
     /// <summary>
@@ -106,15 +102,13 @@ public sealed partial class LatheMenu : DefaultWindow
 
         var sortedRecipesToShow = recipesToShow.OrderBy(p => p.Name);
         RecipeList.Children.Clear();
-        _entityManager.TryGetComponent(Entity, out LatheComponent? lathe);
-
         foreach (var prototype in sortedRecipesToShow)
         {
             EntityPrototype? recipeProto = null;
-            if (_prototypeManager.TryIndex(prototype.Result, out EntityPrototype? entityProto))
+            if (_prototypeManager.TryIndex(prototype.Result, out EntityPrototype? entityProto) && entityProto != null)
                 recipeProto = entityProto;
 
-            var canProduce = _lathe.CanProduce(Entity, prototype, quantity, component: lathe);
+            var canProduce = _lathe.CanProduce(_owner, prototype, quantity);
 
             var control = new RecipeControl(prototype, () => GenerateTooltipText(prototype), canProduce, recipeProto);
             control.OnButtonPressed += s =>
@@ -130,20 +124,19 @@ public sealed partial class LatheMenu : DefaultWindow
     private string GenerateTooltipText(LatheRecipePrototype prototype)
     {
         StringBuilder sb = new();
-        var multiplier = _entityManager.GetComponent<LatheComponent>(Entity).MaterialUseMultiplier;
 
         foreach (var (id, amount) in prototype.RequiredMaterials)
         {
             if (!_prototypeManager.TryIndex<MaterialPrototype>(id, out var proto))
                 continue;
 
-            var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, multiplier);
+            var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, _entityManager.GetComponent<LatheComponent>(_owner).MaterialUseMultiplier);
             var sheetVolume = _materialStorage.GetSheetVolume(proto);
 
             var unit = Loc.GetString(proto.Unit);
             var sheets = adjustedAmount / (float) sheetVolume;
 
-            var availableAmount = _materialStorage.GetMaterialAmount(Entity, id);
+            var availableAmount = _materialStorage.GetMaterialAmount(_owner, id);
             var missingAmount = Math.Max(0, adjustedAmount - availableAmount);
             var missingSheets = missingAmount / (float) sheetVolume;
 
index 11abe8c2451f936d42852aada7571abfd33148ff..09bdedfd94c4afdb28248f24be65afe2c8d4e0b9 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.MachineLinking;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.Timing;
 
 namespace Content.Client.MachineLinking.UI;
@@ -20,14 +19,19 @@ public sealed class SignalTimerBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<SignalTimerWindow>();
-        _window.OnStartTimer += StartTimer;
+        _window = new SignalTimerWindow(this);
+
+        if (State != null)
+            UpdateState(State);
+
+        _window.OpenCentered();
+        _window.OnClose += Close;
         _window.OnCurrentTextChanged += OnTextChanged;
         _window.OnCurrentDelayMinutesChanged += OnDelayChanged;
         _window.OnCurrentDelaySecondsChanged += OnDelayChanged;
     }
 
-    public void StartTimer()
+    public void OnStartTimer()
     {
         SendMessage(new SignalTimerStartMessage());
     }
@@ -44,6 +48,11 @@ public sealed class SignalTimerBoundUserInterface : BoundUserInterface
         SendMessage(new SignalTimerDelayChangedMessage(_window.GetDelay()));
     }
 
+    public TimeSpan GetCurrentTime()
+    {
+        return _gameTiming.CurTime;
+    }
+
     /// <summary>
     /// Update the UI state based on server-sent info
     /// </summary>
@@ -63,4 +72,11 @@ public sealed class SignalTimerBoundUserInterface : BoundUserInterface
         _window.SetTimerStarted(cast.TimerStarted);
         _window.SetHasAccess(cast.HasAccess);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing) return;
+        _window?.Dispose();
+    }
 }
index 6133abfcb7043b931304cd19de2e66d06ec5d50e..b62595595e5654eb6ff4acb12244004e5c373df3 100644 (file)
@@ -9,44 +9,42 @@ namespace Content.Client.MachineLinking.UI;
 [GenerateTypedNameReferences]
 public sealed partial class SignalTimerWindow : DefaultWindow
 {
-    [Dependency] private readonly IGameTiming _timing = default!;
-
     private const int MaxTextLength = 5;
 
     public event Action<string>? OnCurrentTextChanged;
     public event Action<string>? OnCurrentDelayMinutesChanged;
     public event Action<string>? OnCurrentDelaySecondsChanged;
 
+    private readonly SignalTimerBoundUserInterface _owner;
+
     private TimeSpan? _triggerTime;
 
     private bool _timerStarted;
 
-    public event Action? OnStartTimer;
-
-    public SignalTimerWindow()
+    public SignalTimerWindow(SignalTimerBoundUserInterface owner)
     {
         RobustXamlLoader.Load(this);
-        IoCManager.InjectDependencies(this);
+
+        _owner = owner;
 
         CurrentTextEdit.OnTextChanged += e => OnCurrentTextChange(e.Text);
         CurrentDelayEditMinutes.OnTextChanged += e => OnCurrentDelayMinutesChange(e.Text);
         CurrentDelayEditSeconds.OnTextChanged += e => OnCurrentDelaySecondsChange(e.Text);
-        StartTimer.OnPressed += _ => StartTimerWeh();
+        StartTimer.OnPressed += _ => OnStartTimer();
     }
 
-    private void StartTimerWeh()
+    public void OnStartTimer()
     {
         if (!_timerStarted)
         {
             _timerStarted = true;
-            _triggerTime = _timing.CurTime + GetDelay();
+            _triggerTime = _owner.GetCurrentTime() + GetDelay();
         }
         else
         {
             SetTimerStarted(false);
         }
-
-        OnStartTimer?.Invoke();
+        _owner.OnStartTimer();
     }
 
     protected override void FrameUpdate(FrameEventArgs args)
@@ -56,9 +54,9 @@ public sealed partial class SignalTimerWindow : DefaultWindow
         if (!_timerStarted || _triggerTime == null)
             return;
 
-        if (_timing.CurTime < _triggerTime.Value)
+        if (_owner.GetCurrentTime() < _triggerTime.Value)
         {
-            StartTimer.Text = TextScreenSystem.TimeToString(_triggerTime.Value - _timing.CurTime);
+            StartTimer.Text = TextScreenSystem.TimeToString(_triggerTime.Value - _owner.GetCurrentTime());
         }
         else
         {
index 0a87948ff62fd411fe86bdd9acf1eea950ac3b87..f6979bf8d7bbee1d0de9e7810b8c380c2cd16b0e 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Humanoid.Markings;
 using Content.Shared.MagicMirror;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.MagicMirror;
 
@@ -18,7 +17,7 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<MagicMirrorWindow>();
+        _window = new();
 
         _window.OnHairSelected += tuple => SelectHair(MagicMirrorCategory.Hair, tuple.id, tuple.slot);
         _window.OnHairColorChanged += args => ChangeColor(MagicMirrorCategory.Hair, args.marking, args.slot);
@@ -30,6 +29,9 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface
             args => ChangeColor(MagicMirrorCategory.FacialHair, args.marking, args.slot);
         _window.OnFacialHairSlotAdded += delegate () { AddSlot(MagicMirrorCategory.FacialHair); };
         _window.OnFacialHairSlotRemoved += args => RemoveSlot(MagicMirrorCategory.FacialHair, args);
+
+        _window.OnClose += Close;
+        _window.OpenCentered();
     }
 
     private void SelectHair(MagicMirrorCategory category, string marking, int slot)
@@ -63,5 +65,14 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface
 
         _window.UpdateState(data);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+
+        _window?.Dispose();
+    }
 }
 
index 22e5bc452a0d458608718fa9123bed1355258aed..80eca82e324c5dec83b83a0898953b31d7c2b695 100644 (file)
@@ -1,7 +1,6 @@
 using JetBrains.Annotations;
 using Content.Shared.MassMedia.Systems;
 using Content.Shared.MassMedia.Components;
-using Robust.Client.UserInterface;
 using Robust.Shared.Timing;
 using Robust.Shared.Utility;
 
@@ -10,6 +9,8 @@ namespace Content.Client.MassMedia.Ui;
 [UsedImplicitly]
 public sealed class NewsWriterBoundUserInterface : BoundUserInterface
 {
+    [Dependency] private readonly IGameTiming _gameTiming = default!;
+
     [ViewVariables]
     private NewsWriterMenu? _menu;
 
@@ -20,7 +21,10 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface
 
     protected override void Open()
     {
-        _menu = this.CreateWindow<NewsWriterMenu>();
+        _menu = new NewsWriterMenu(_gameTiming);
+
+        _menu.OpenCentered();
+        _menu.OnClose += Close;
 
         _menu.ArticleEditorPanel.PublishButtonPressed += OnPublishButtonPressed;
         _menu.DeleteButtonPressed += OnDeleteButtonPressed;
@@ -28,6 +32,16 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface
         SendMessage(new NewsWriterArticlesRequestMessage());
     }
 
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+
+        _menu?.Close();
+        _menu?.Dispose();
+    }
+
     protected override void UpdateState(BoundUserInterfaceState state)
     {
         base.UpdateState(state);
index c059ce785af6c397d0f48ef1c0e37e2fcdf6565c..e2d57935e3a917d461583426870b646b27557139 100644 (file)
@@ -10,17 +10,17 @@ namespace Content.Client.MassMedia.Ui;
 [GenerateTypedNameReferences]
 public sealed partial class NewsWriterMenu : FancyWindow
 {
-    [Dependency] private readonly IGameTiming _gameTiming = default!;
+    private readonly IGameTiming _gameTiming;
 
     private TimeSpan? _nextPublish;
 
     public event Action<int>? DeleteButtonPressed;
 
-    public NewsWriterMenu()
+    public NewsWriterMenu(IGameTiming gameTiming)
     {
         RobustXamlLoader.Load(this);
-        IoCManager.InjectDependencies(this);
 
+        _gameTiming = gameTiming;
         ContentsContainer.RectClipContent = false;
 
         // Customize scrollbar width and margin. This is not possible in xaml
index 2130a8c609962a26f064c105c9dc7dc9c580d083..4172bdc90f1b9985b0363c425b82c78aabb8fe01 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.Mech;
 using Content.Shared.Mech.Components;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Mech.Ui;
 
@@ -21,8 +20,9 @@ public sealed class MechBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<MechMenu>();
-        _menu.SetEntity(Owner);
+        _menu = new(Owner);
+
+        _menu.OnClose += Close;
         _menu.OpenCenteredLeft();
 
         _menu.OnRemoveButtonPressed += uid =>
@@ -60,6 +60,16 @@ public sealed class MechBoundUserInterface : BoundUserInterface
         }
     }
 
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        if (!disposing)
+            return;
+
+        _menu?.Close();
+    }
+
     public UIFragment? GetEquipmentUi(EntityUid? uid)
     {
         var component = EntMan.GetComponentOrNull<UIFragmentComponent>(uid);
index 6f39bc386ee41b40c2095f7003d988e6f28d5910..fad7648808655b3dc28062857e0823dbe1fc42ba 100644 (file)
@@ -16,15 +16,14 @@ public sealed partial class MechMenu : FancyWindow
 
     public event Action<EntityUid>? OnRemoveButtonPressed;
 
-    public MechMenu()
+    public MechMenu(EntityUid mech)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
-    }
 
-    public void SetEntity(EntityUid uid)
-    {
-        MechView.SetEntity(uid);
+        _mech = mech;
+
+        MechView.SetEntity(mech);
     }
 
     public void UpdateMechStats()
index b1f239cd78e5ad9b3322ebd9a03b817a7ca23b36..397888098716b8bb4655a8f0fee6dd8111f3e936 100644 (file)
@@ -1,5 +1,4 @@
 using Content.Shared.Medical.CrewMonitoring;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Medical.CrewMonitoring;
 
@@ -15,7 +14,7 @@ public sealed class CrewMonitoringBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         EntityUid? gridUid = null;
-        var stationName = string.Empty;
+        string stationName = string.Empty;
 
         if (EntMan.TryGetComponent<TransformComponent>(Owner, out var xform))
         {
@@ -27,8 +26,10 @@ public sealed class CrewMonitoringBoundUserInterface : BoundUserInterface
             }
         }
 
-        _menu = this.CreateWindow<CrewMonitoringWindow>();
-        _menu.Set(stationName, gridUid);
+        _menu = new CrewMonitoringWindow(stationName, gridUid);
+
+        _menu.OpenCentered();
+        _menu.OnClose += Close;
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -43,4 +44,13 @@ public sealed class CrewMonitoringBoundUserInterface : BoundUserInterface
                 break;
         }
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+
+        _menu?.Dispose();
+    }
 }
index e861864c14479850ff176694effb24b436821694..863412e5532b996e95725d09343e6b81eb9e4750 100644 (file)
@@ -23,27 +23,22 @@ namespace Content.Client.Medical.CrewMonitoring;
 [GenerateTypedNameReferences]
 public sealed partial class CrewMonitoringWindow : FancyWindow
 {
-    [Dependency] private readonly IEntityManager _entManager = default!;
-    [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+    private readonly IEntityManager _entManager;
+    private readonly IPrototypeManager _prototypeManager;
     private readonly SpriteSystem _spriteSystem;
 
     private NetEntity? _trackedEntity;
     private bool _tryToScrollToListFocus;
     private Texture? _blipTexture;
 
-    public CrewMonitoringWindow()
+    public CrewMonitoringWindow(string stationName, EntityUid? mapUid)
     {
         RobustXamlLoader.Load(this);
-        IoCManager.InjectDependencies(this);
 
+        _entManager = IoCManager.Resolve<IEntityManager>();
+        _prototypeManager = IoCManager.Resolve<IPrototypeManager>();
         _spriteSystem = _entManager.System<SpriteSystem>();
 
-        NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap;
-
-    }
-
-    public void Set(string stationName, EntityUid? mapUid)
-    {
         _blipTexture = _spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")));
 
         if (_entManager.TryGetComponent<TransformComponent>(mapUid, out var xform))
@@ -54,6 +49,8 @@ public sealed partial class CrewMonitoringWindow : FancyWindow
 
         StationName.AddStyleClass("LabelBig");
         StationName.Text = stationName;
+
+        NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap;
         NavMap.ForceNavMapUpdate();
     }
 
index f85220a9266ac747fc66d11b492bd45f528e4647..80c98f143b989a57fb3700ac8459e20087570b28 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Client.NetworkConfigurator.Systems;
 using Content.Shared.DeviceNetwork;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 
 namespace Content.Client.NetworkConfigurator;
@@ -36,12 +35,14 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
         switch (UiKey)
         {
             case NetworkConfiguratorUiKey.List:
-                _listMenu = this.CreateWindow<NetworkConfiguratorListMenu>();
+                _listMenu = new NetworkConfiguratorListMenu(this);
+                _listMenu.OnClose += Close;
                 _listMenu.ClearButton.OnPressed += _ => OnClearButtonPressed();
-                _listMenu.OnRemoveAddress += OnRemoveButtonPressed;
+                _listMenu.OpenCenteredRight();
                 break;
             case NetworkConfiguratorUiKey.Configure:
-                _configurationMenu = this.CreateWindow<NetworkConfiguratorConfigurationMenu>();
+                _configurationMenu = new NetworkConfiguratorConfigurationMenu();
+                _configurationMenu.OnClose += Close;
                 _configurationMenu.Set.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Set);
                 _configurationMenu.Add.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Add);
                 //_configurationMenu.Edit.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Edit);
@@ -49,24 +50,12 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
                 _configurationMenu.Copy.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Copy);
                 _configurationMenu.Show.OnPressed += OnShowPressed;
                 _configurationMenu.Show.Pressed = _netConfig.ConfiguredListIsTracked(Owner);
-                _configurationMenu.OnRemoveAddress += OnRemoveButtonPressed;
+                _configurationMenu.OpenCentered();
                 break;
             case NetworkConfiguratorUiKey.Link:
-                _linkMenu = this.CreateWindow<NetworkConfiguratorLinkMenu>();
-                _linkMenu.OnLinkDefaults += args =>
-                {
-                    SendMessage(new NetworkConfiguratorLinksSaveMessage(args));
-                };
-
-                _linkMenu.OnToggleLink += (left, right) =>
-                {
-                    SendMessage(new NetworkConfiguratorToggleLinkMessage(left, right));
-                };
-
-                _linkMenu.OnClearLinks += () =>
-                {
-                    SendMessage(new NetworkConfiguratorClearLinksMessage());
-                };
+                _linkMenu = new NetworkConfiguratorLinkMenu(this);
+                _linkMenu.OnClose += Close;
+                _linkMenu.OpenCentered();
                 break;
         }
     }
@@ -94,6 +83,16 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
         }
     }
 
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing) return;
+
+        _linkMenu?.Dispose();
+        _listMenu?.Dispose();
+        _configurationMenu?.Dispose();
+    }
+
     private void OnClearButtonPressed()
     {
         SendMessage(new NetworkConfiguratorClearDevicesMessage());
index fcd2f7591873bad12b7d3447e854c7095e57c08a..19d04cd34641d7c74e3873b6a520f2d7df54d4c3 100644 (file)
@@ -9,23 +9,17 @@ namespace Content.Client.NetworkConfigurator;
 [GenerateTypedNameReferences]
 public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow
 {
-    public event Action<string>? OnRemoveAddress;
-
     public NetworkConfiguratorConfigurationMenu()
     {
         RobustXamlLoader.Load(this);
 
         Clear.StyleClasses.Add(StyleBase.ButtonOpenLeft);
         Clear.StyleClasses.Add(StyleNano.StyleClassButtonColorRed);
-        DeviceList.OnRemoveAddress += args =>
-        {
-            OnRemoveAddress?.Invoke(args);
-        };
     }
 
     public void UpdateState(DeviceListUserInterfaceState state)
     {
-        DeviceList.UpdateState(state.DeviceList, false);
+        DeviceList.UpdateState(null, state.DeviceList);
 
         Count.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count));
     }
index e75c60058cb5fde5f0765327117ecda5bd7acb25..8cfa97dc6c280b71329790020a7dc2f5a3dbb101 100644 (file)
@@ -7,19 +7,17 @@ namespace Content.Client.NetworkConfigurator;
 [GenerateTypedNameReferences]
 public sealed partial class NetworkConfiguratorDeviceList : ScrollContainer
 {
-    public event Action<string>? OnRemoveAddress;
-
-    public void UpdateState(HashSet<(string address, string name)> devices, bool ui)
+    public void UpdateState(NetworkConfiguratorBoundUserInterface? ui, HashSet<(string address, string name)> devices)
     {
         DeviceList.RemoveAllChildren();
 
         foreach (var device in devices)
         {
-            DeviceList.AddChild(BuildDeviceListRow(device, ui));
+            DeviceList.AddChild(BuildDeviceListRow(ui, device));
         }
     }
 
-    private BoxContainer BuildDeviceListRow((string address, string name) savedDevice, bool ui)
+    private static BoxContainer BuildDeviceListRow(NetworkConfiguratorBoundUserInterface? ui, (string address, string name) savedDevice)
     {
         var row = new BoxContainer()
         {
@@ -50,10 +48,10 @@ public sealed partial class NetworkConfiguratorDeviceList : ScrollContainer
         row.AddChild(name);
         row.AddChild(address);
 
-        if (ui)
+        if (ui != null)
         {
             row.AddChild(removeButton);
-            removeButton.OnPressed += _ => OnRemoveAddress?.Invoke(savedDevice.address);
+            removeButton.OnPressed += _ => ui.OnRemoveButtonPressed(savedDevice.address);
         }
 
         return row;
index 8cdffd16af608e2e7e24bc6fcfbe30589b92692f..c04b42f249bcc4e4a97a3d177dec9c63b6db17d4 100644 (file)
@@ -18,20 +18,20 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow
 
     private readonly LinksRender _links;
 
+
     private readonly List<SourcePortPrototype> _sources = new();
 
     private readonly List<SinkPortPrototype> _sinks = new();
 
+    private readonly NetworkConfiguratorBoundUserInterface _userInterface;
+
     private (ButtonPosition position, string id, int index)? _selectedButton;
 
     private List<(string left, string right)>? _defaults;
 
-    public event Action? OnClearLinks;
-    public event Action<string, string>? OnToggleLink;
-    public event Action<List<(string left, string right)>>? OnLinkDefaults;
-
-    public NetworkConfiguratorLinkMenu()
+    public NetworkConfiguratorLinkMenu(NetworkConfiguratorBoundUserInterface userInterface)
     {
+        _userInterface = userInterface;
         RobustXamlLoader.Load(this);
 
         var footerStyleBox = new StyleBoxFlat()
@@ -52,7 +52,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow
 
         ButtonOk.OnPressed += _ => Close();
         ButtonLinkDefault.OnPressed += _ => LinkDefaults();
-        ButtonClear.OnPressed += _ => OnClearLinks?.Invoke();
+        ButtonClear.OnPressed += _ => _userInterface.SendMessage(new NetworkConfiguratorClearLinksMessage());
     }
 
     public void UpdateState(DeviceLinkUserInterfaceState linkState)
@@ -98,7 +98,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow
         if (_defaults == default)
             return;
 
-        OnLinkDefaults?.Invoke(_defaults);
+        _userInterface.SendMessage(new NetworkConfiguratorLinksSaveMessage(_defaults));
     }
 
     private Button CreateButton(ButtonPosition position, string name, string description, string id, int index)
@@ -138,7 +138,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow
         var left = _selectedButton.Value.position == ButtonPosition.Left ? _selectedButton.Value.id : id;
         var right = _selectedButton.Value.position == ButtonPosition.Left ? id : _selectedButton.Value.id;
 
-        OnToggleLink?.Invoke(left, right);
+        _userInterface.SendMessage(new NetworkConfiguratorToggleLinkMessage(left, right));
 
         args.Button.Pressed = false;
 
index 6294facaeed73acc50720daa19273ea25d0f26bc..fb4aec1974bda5bfae69586bd195bca0618fe202 100644 (file)
@@ -9,20 +9,17 @@ namespace Content.Client.NetworkConfigurator;
 [GenerateTypedNameReferences]
 public sealed partial class NetworkConfiguratorListMenu : FancyWindow
 {
-    public event Action<string>? OnRemoveAddress;
-
-    public NetworkConfiguratorListMenu()
+    private readonly NetworkConfiguratorBoundUserInterface _ui;
+    public NetworkConfiguratorListMenu(NetworkConfiguratorBoundUserInterface ui)
     {
         RobustXamlLoader.Load(this);
-        DeviceList.OnRemoveAddress += args =>
-        {
-            OnRemoveAddress?.Invoke(args);
-        };
+
+        _ui = ui;
     }
 
     public void UpdateState(NetworkConfiguratorUserInterfaceState state)
     {
         DeviceCountLabel.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count));
-        DeviceList.UpdateState(state.DeviceList, true);
+        DeviceList.UpdateState(_ui, state.DeviceList);
     }
 }
index 2e150423734be55bd8b0bf4a823f8eb4699d7e11..59fbc5b319b93ecac145af38835ce6589cc820aa 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Containers.ItemSlots;
 using Content.Shared.Nuke;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Nuke
 {
@@ -12,13 +11,15 @@ namespace Content.Client.Nuke
         [ViewVariables]
         private NukeMenu? _menu;
 
-        public NukeBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
+        public NukeBoundUserInterface([NotNull] EntityUid owner, [NotNull] Enum uiKey) : base(owner, uiKey)
         {
         }
 
         protected override void Open()
         {
-            _menu = this.CreateWindow<NukeMenu>();
+            _menu = new NukeMenu();
+            _menu.OpenCentered();
+            _menu.OnClose += Close;
 
             _menu.OnKeypadButtonPressed += i =>
             {
@@ -61,5 +62,15 @@ namespace Content.Client.Nuke
                     break;
             }
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            _menu?.Close();
+            _menu?.Dispose();
+        }
     }
 }
index ad4f1a75d47f09c3f729a6193f1147d9d1f6b1bf..ec055b3240c5d059efecc1e42e81ce535ebcc0e8 100644 (file)
@@ -2,7 +2,6 @@
 using Content.Shared.Chat;
 using Content.Shared.NukeOps;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 using Robust.Shared.Configuration;
 using Robust.Shared.Timing;
 
@@ -12,6 +11,8 @@ namespace Content.Client.NukeOps;
 public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface
 {
     [Dependency] private readonly IConfigurationManager _cfg = default!;
+    [Dependency] private readonly IGameTiming _gameTiming = default!;
+    [Dependency] private readonly ILocalizationManager _localizationManager = default!;
 
     [ViewVariables]
     private WarDeclaratorWindow? _window;
@@ -22,7 +23,13 @@ public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<WarDeclaratorWindow>();
+        _window = new WarDeclaratorWindow(_gameTiming, _localizationManager);
+        if (State != null)
+            UpdateState(State);
+
+        _window.OpenCentered();
+
+        _window.OnClose += Close;
         _window.OnActivated += OnWarDeclaratorActivated;
     }
 
@@ -35,6 +42,13 @@ public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface
         _window?.UpdateState(cast);
     }
 
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (disposing)
+            _window?.Dispose();
+    }
+
     private void OnWarDeclaratorActivated(string message)
     {
         var maxLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength);
index aeceae13275fd05c2fb875985626e658e2ed6765..b4a3f1c7fa59459e3a27e3dd43fe6840a3577ce8 100644 (file)
@@ -11,8 +11,7 @@ namespace Content.Client.NukeOps;
 [GenerateTypedNameReferences]
 public sealed partial class WarDeclaratorWindow : FancyWindow
 {
-    [Dependency] private readonly IGameTiming _gameTiming = default!;
-    [Dependency] private readonly ILocalizationManager _localizationManager = default!;
+    private readonly IGameTiming _gameTiming;
 
     public event Action<string>? OnActivated;
 
@@ -20,13 +19,15 @@ public sealed partial class WarDeclaratorWindow : FancyWindow
     private TimeSpan _shuttleDisabledTime;
     private WarConditionStatus _status;
 
-    public WarDeclaratorWindow()
+    public WarDeclaratorWindow(IGameTiming gameTiming, ILocalizationManager localizationManager)
     {
         RobustXamlLoader.Load(this);
 
+        _gameTiming = gameTiming;
+
         WarButton.OnPressed += (_) => OnActivated?.Invoke(Rope.Collapse(MessageEdit.TextRope));
 
-        MessageEdit.Placeholder = new Rope.Leaf(_localizationManager.GetString("war-declarator-message-placeholder"));
+        MessageEdit.Placeholder = new Rope.Leaf(localizationManager.GetString("war-declarator-message-placeholder"));
     }
 
     protected override void FrameUpdate(FrameEventArgs args)
index 37ce9c4280f2a06017d0f1ed0b6fb8711d4db234..f8f4c67076cda57ecafc0c7ec29af9f0080330e7 100644 (file)
@@ -24,13 +24,14 @@ namespace Content.Client.PDA
 
             if (_menu == null)
                 CreateMenu();
+
+            _menu?.OpenCenteredLeft();
         }
 
         private void CreateMenu()
         {
-            _menu = this.CreateWindow<PdaMenu>();
-            _menu.OpenCenteredLeft();
-
+            _menu = new PdaMenu();
+            _menu.OnClose += Close;
             _menu.FlashLightToggleButton.OnToggled += _ =>
             {
                 SendMessage(new PdaToggleFlashlightMessage());
@@ -95,6 +96,7 @@ namespace Content.Client.PDA
             _menu?.UpdateState(updateState);
         }
 
+
         protected override void AttachCartridgeUI(Control cartridgeUIFragment, string? title)
         {
             _menu?.ProgramView.AddChild(cartridgeUIFragment);
@@ -116,6 +118,15 @@ namespace Content.Client.PDA
             _menu?.UpdateAvailablePrograms(programs);
         }
 
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+
+            _menu?.Dispose();
+        }
+
         private PdaBorderColorComponent? GetBorderColorComponent()
         {
             return EntMan.GetComponentOrNull<PdaBorderColorComponent>(Owner);
index 170a296ac2e2067f1d2f14cc7d16fb0e1334707a..a0688523f1ea472dd774454f47880058a6907b57 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.PDA;
 using Content.Shared.PDA.Ringer;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 using Robust.Shared.Timing;
 
 namespace Content.Client.PDA.Ringer
@@ -19,8 +18,9 @@ namespace Content.Client.PDA.Ringer
         protected override void Open()
         {
             base.Open();
-            _menu = this.CreateWindow<RingtoneMenu>();
+            _menu = new RingtoneMenu();
             _menu.OpenToLeft();
+            _menu.OnClose += Close;
 
             _menu.TestRingerButton.OnPressed += _ =>
             {
index f3ad1e347e76dc4a0b886073bbd20eeab721731c..4b0ac868f01704ff157bda37af7d0c0aa66510a2 100644 (file)
@@ -1,5 +1,4 @@
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 using Robust.Client.UserInterface.Controls;
 using Robust.Shared.Utility;
 using static Content.Shared.Paper.SharedPaperComponent;
@@ -20,13 +19,16 @@ public sealed class PaperBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<PaperWindow>();
-        _window.OnSaved += InputOnTextEntered;
+        _window = new PaperWindow();
+        _window.OnClose += Close;
+        _window.OnSaved += Input_OnTextEntered;
 
         if (EntMan.TryGetComponent<PaperVisualsComponent>(Owner, out var visuals))
         {
             _window.InitVisuals(Owner, visuals);
         }
+
+        _window.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -35,7 +37,7 @@ public sealed class PaperBoundUserInterface : BoundUserInterface
         _window?.Populate((PaperBoundUserInterfaceState) state);
     }
 
-    private void InputOnTextEntered(string text)
+    private void Input_OnTextEntered(string text)
     {
         SendMessage(new PaperInputTextMessage(text));
 
@@ -45,4 +47,11 @@ public sealed class PaperBoundUserInterface : BoundUserInterface
             _window.Input.CursorPosition = new TextEdit.CursorPos(0, TextEdit.LineBreakBias.Top);
         }
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing) return;
+        _window?.Dispose();
+    }
 }
index f7cace642ce5ae311603c9c05ff8adf856f54a91..7a5fd652643d7b669d6d0049d2ca37794f168cfb 100644 (file)
@@ -17,7 +17,6 @@ namespace Content.Client.Paper.UI
     public sealed partial class PaperWindow : BaseWindow
     {
         [Dependency] private readonly IInputManager _inputManager = default!;
-        [Dependency] private readonly IResourceCache _resCache = default!;
 
         private static Color DefaultTextColor = new(25, 25, 25);
 
@@ -86,10 +85,11 @@ namespace Content.Client.Paper.UI
             // Randomize the placement of any stamps based on the entity UID
             // so that there's some variety in different papers.
             StampDisplay.PlacementSeed = (int)entity;
+            var resCache = IoCManager.Resolve<IResourceCache>();
 
             // Initialize the background:
             PaperBackground.ModulateSelfOverride = visuals.BackgroundModulate;
-            var backgroundImage = visuals.BackgroundImagePath != null? _resCache.GetResource<TextureResource>(visuals.BackgroundImagePath) : null;
+            var backgroundImage = visuals.BackgroundImagePath != null? resCache.GetResource<TextureResource>(visuals.BackgroundImagePath) : null;
             if (backgroundImage != null)
             {
                 var backgroundImageMode = visuals.BackgroundImageTile ? StyleBoxTexture.StretchMode.Tile : StyleBoxTexture.StretchMode.Stretch;
@@ -127,7 +127,7 @@ namespace Content.Client.Paper.UI
             PaperContent.ModulateSelfOverride = visuals.ContentImageModulate;
             WrittenTextLabel.ModulateSelfOverride = visuals.FontAccentColor;
 
-            var contentImage = visuals.ContentImagePath != null ? _resCache.GetResource<TextureResource>(visuals.ContentImagePath) : null;
+            var contentImage = visuals.ContentImagePath != null ? resCache.GetResource<TextureResource>(visuals.ContentImagePath) : null;
             if (contentImage != null)
             {
                 // Setup the paper content texture, but keep a reference to it, as we can't set
index ff1eae36f55e1872503c53996a4342c10b65f9f0..cde5ba9ef79d424a9410dbd7a270c24bae5fcf24 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Singularity.Components;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.ParticleAccelerator.UI
 {
@@ -17,10 +16,9 @@ namespace Content.Client.ParticleAccelerator.UI
         {
             base.Open();
 
-            _menu = this.CreateWindow<ParticleAcceleratorControlMenu>();
-            _menu.OnOverallState += SendEnableMessage;
-            _menu.OnPowerState += SendPowerStateMessage;
-            _menu.OnScanPartsRequested += SendScanPartsMessage;
+            _menu = new ParticleAcceleratorControlMenu(this);
+            _menu.OnClose += Close;
+            _menu.OpenCentered();
         }
 
         public void SendEnableMessage(bool enable)
@@ -42,5 +40,13 @@ namespace Content.Client.ParticleAccelerator.UI
         {
             _menu?.DataUpdate((ParticleAcceleratorUIState) state);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            _menu?.Dispose();
+            _menu = null;
+        }
     }
 }
index 85a5f4762930d4036e2bc314831c39041184faf6..c69e0271372cfa67da0075f4666ce42e44def7bd 100644 (file)
@@ -18,11 +18,10 @@ namespace Content.Client.ParticleAccelerator.UI
 {
     public sealed class ParticleAcceleratorControlMenu : BaseWindow
     {
-        [Dependency] private readonly IPrototypeManager _protoManager = default!;
-        [Dependency] private readonly IResourceCache _cache = default!;
-
         private readonly ShaderInstance _greyScaleShader;
 
+        private readonly ParticleAcceleratorBoundUserInterface _owner;
+
         private readonly Label _drawLabel;
         private readonly FastNoiseLite _drawNoiseGenerator;
         private readonly Button _onButton;
@@ -51,21 +50,19 @@ namespace Content.Client.ParticleAccelerator.UI
         private bool _shouldContinueAnimating;
         private int _maxStrength = 3;
 
-        public event Action<bool>? OnOverallState;
-        public event Action<ParticleAcceleratorPowerState>? OnPowerState;
-        public event Action? OnScanPartsRequested;
-
-        public ParticleAcceleratorControlMenu()
+        public ParticleAcceleratorControlMenu(ParticleAcceleratorBoundUserInterface owner)
         {
             SetSize = new Vector2(400, 320);
-            _greyScaleShader = _protoManager.Index<ShaderPrototype>("Greyscale").Instance();
+            _greyScaleShader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("Greyscale").Instance();
 
+            _owner = owner;
             _drawNoiseGenerator = new();
             _drawNoiseGenerator.SetFractalType(FastNoiseLite.FractalType.FBm);
             _drawNoiseGenerator.SetFrequency(0.5f);
 
-            var font = _cache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13);
-            var panelTex = _cache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
+            var resourceCache = IoCManager.Resolve<IResourceCache>();
+            var font = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13);
+            var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
 
             MouseFilter = MouseFilterMode.Stop;
 
@@ -115,8 +112,7 @@ namespace Content.Client.ParticleAccelerator.UI
                 Text = Loc.GetString("particle-accelerator-control-menu-off-button"),
                 StyleClasses = { StyleBase.ButtonOpenRight },
             };
-
-            _offButton.OnPressed += args => OnOverallState?.Invoke(false);
+            _offButton.OnPressed += args => owner.SendEnableMessage(false);
 
             _onButton = new Button
             {
@@ -124,7 +120,7 @@ namespace Content.Client.ParticleAccelerator.UI
                 Text = Loc.GetString("particle-accelerator-control-menu-on-button"),
                 StyleClasses = { StyleBase.ButtonOpenLeft },
             };
-            _onButton.OnPressed += args => OnOverallState?.Invoke(true);
+            _onButton.OnPressed += args => owner.SendEnableMessage(true);
 
             var closeButton = new TextureButton
             {
@@ -320,7 +316,7 @@ namespace Content.Client.ParticleAccelerator.UI
                 }
             });
 
-            _scanButton.OnPressed += args => OnScanPartsRequested?.Invoke();
+            _scanButton.OnPressed += args => _owner.SendScanPartsMessage();
 
             _alarmControl.AnimationCompleted += s =>
             {
@@ -336,7 +332,7 @@ namespace Content.Client.ParticleAccelerator.UI
 
             PASegmentControl Segment(string name)
             {
-                return new(this, _cache, name);
+                return new(this, resourceCache, name);
             }
 
             UpdateUI(false, false, false, false);
@@ -372,7 +368,7 @@ namespace Content.Client.ParticleAccelerator.UI
             }
 
             _stateSpinBox.SetButtonDisabled(true);
-            OnPowerState?.Invoke(newState);
+            _owner.SendPowerStateMessage(newState);
         }
 
         protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
index 0df6787170a98ea4cb18a41d8abf5b37033a88ca..3ebcf7cbcedb37fa1a6a759443e038a912dadaf7 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Pinpointer;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Pinpointer.UI;
 
@@ -17,16 +16,19 @@ public sealed class NavMapBeaconBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         base.Open();
-        _window = this.CreateWindow<NavMapBeaconWindow>();
-
-        if (EntMan.TryGetComponent(Owner, out NavMapBeaconComponent? beacon))
-        {
-            _window.SetEntity(Owner, beacon);
-        }
+        _window = new NavMapBeaconWindow(Owner);
+        _window.OpenCentered();
+        _window.OnClose += Close;
 
         _window.OnApplyButtonPressed += (label, enabled, color) =>
         {
             SendMessage(new NavMapBeaconConfigureBuiMessage(label, enabled, color));
         };
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        _window?.Dispose();
+    }
 }
index b77f1af0472d3dc1e598aecd9ec827db07a6c453..968fe188f75f1977bc736ec3326fe6c9fc88b664 100644 (file)
@@ -10,35 +10,36 @@ namespace Content.Client.Pinpointer.UI;
 [GenerateTypedNameReferences]
 public sealed partial class NavMapBeaconWindow : FancyWindow
 {
+    [Dependency] private readonly IEntityManager _entityManager = default!;
+
     private string? _defaultLabel;
     private bool _defaultEnabled;
     private Color _defaultColor;
 
     public event Action<string?, bool, Color>? OnApplyButtonPressed;
 
-    public NavMapBeaconWindow()
+    public NavMapBeaconWindow(EntityUid beaconEntity)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
 
-
-        VisibleButton.OnPressed += args => UpdateVisibleButton(args.Button.Pressed);
-        LabelLineEdit.OnTextChanged += OnTextChanged;
-        ColorSelector.OnColorChanged += _ => TryEnableApplyButton();
-
-        TryEnableApplyButton();
-        ApplyButton.OnPressed += OnApplyPressed;
-    }
-
-    public void SetEntity(EntityUid uid, NavMapBeaconComponent navMap)
-    {
+        if (!_entityManager.TryGetComponent<NavMapBeaconComponent>(beaconEntity, out var navMap))
+            return;
         _defaultLabel = navMap.Text;
         _defaultEnabled = navMap.Enabled;
         _defaultColor = navMap.Color;
 
         UpdateVisibleButton(navMap.Enabled);
+        VisibleButton.OnPressed += args => UpdateVisibleButton(args.Button.Pressed);
+
         LabelLineEdit.Text = navMap.Text ?? string.Empty;
+        LabelLineEdit.OnTextChanged += OnTextChanged;
+
         ColorSelector.Color = navMap.Color;
+        ColorSelector.OnColorChanged += _ => TryEnableApplyButton();
+
+        TryEnableApplyButton();
+        ApplyButton.OnPressed += OnApplyPressed;
     }
 
     private void UpdateVisibleButton(bool value)
index 7417fafede526ee643b25a351f8a92366b267452..1483e75e73251066d89f4796f4138cdeb0e1029c 100644 (file)
@@ -1,4 +1,4 @@
-using Robust.Client.UserInterface;
+using Robust.Client.GameObjects;
 
 namespace Content.Client.Pinpointer.UI;
 
@@ -14,6 +14,7 @@ public sealed class StationMapBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         base.Open();
+        _window?.Close();
         EntityUid? gridUid = null;
 
         if (EntMan.TryGetComponent<TransformComponent>(Owner, out var xform))
@@ -21,8 +22,14 @@ public sealed class StationMapBoundUserInterface : BoundUserInterface
             gridUid = xform.GridUid;
         }
 
-        _window = this.CreateWindow<StationMapWindow>();
-        _window.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
-        _window.Set(gridUid, Owner);
+        _window = new StationMapWindow(gridUid, Owner);
+        _window.OpenCentered();
+        _window.OnClose += Close;
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        _window?.Dispose();
     }
 }
index 7cbb8b7d0dbc22e43ab19a21d4df300592cb9269..1b01fe4e30497b52e267ef175ea3521bc8ab27e2 100644 (file)
@@ -9,18 +9,19 @@ namespace Content.Client.Pinpointer.UI;
 [GenerateTypedNameReferences]
 public sealed partial class StationMapWindow : FancyWindow
 {
-    public StationMapWindow()
+    public StationMapWindow(EntityUid? mapUid, EntityUid? trackedEntity)
     {
         RobustXamlLoader.Load(this);
-    }
-
-    public void Set(EntityUid? mapUid, EntityUid? trackedEntity)
-    {
         NavMapScreen.MapUid = mapUid;
 
         if (trackedEntity != null)
             NavMapScreen.TrackedCoordinates.Add(new EntityCoordinates(trackedEntity.Value, Vector2.Zero), (true, Color.Cyan));
 
+        if (IoCManager.Resolve<IEntityManager>().TryGetComponent<MetaDataComponent>(mapUid, out var metadata))
+        {
+            Title = metadata.EntityName;
+        }
+
         NavMapScreen.ForceNavMapUpdate();
     }
 }
index a3ca6f65da2ca24ec1b03912604a59793c83af4d..57965b030a25693bccfb52755a4703b410cb066d 100644 (file)
@@ -1,4 +1,4 @@
-using Robust.Client.UserInterface;
+using Robust.Client.GameObjects;
 
 namespace Content.Client.Pinpointer.UI;
 
@@ -14,15 +14,22 @@ public sealed class UntrackedStationMapBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         base.Open();
+        _window?.Close();
         EntityUid? gridUid = null;
 
-        // TODO: What this just looks like it's been copy-pasted wholesale from StationMapBoundUserInterface?
         if (EntMan.TryGetComponent<TransformComponent>(Owner, out var xform))
         {
             gridUid = xform.GridUid;
         }
 
-        _window = this.CreateWindow<StationMapWindow>();
-        _window.Set(gridUid, Owner);
+        _window = new StationMapWindow(gridUid, null);
+        _window.OpenCentered();
+        _window.OnClose += Close;
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        _window?.Dispose();
     }
 }
index 759a5949ba625dc10202de2405cd63ecb443d4a6..fbcbf0115698661945566f8203871fc249e2ed50 100644 (file)
@@ -2,7 +2,6 @@
 using Content.Shared.APC;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Power.APC
 {
@@ -20,8 +19,9 @@ namespace Content.Client.Power.APC
         {
             base.Open();
 
-            _menu = this.CreateWindow<ApcMenu>();
-            _menu.OnBreaker += BreakerPressed;
+            _menu = new ApcMenu(this);
+            _menu.OnClose += Close;
+            _menu.OpenCentered();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
@@ -36,5 +36,15 @@ namespace Content.Client.Power.APC
         {
             SendMessage(new ApcToggleMainBreakerMessage());
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+
+            if (disposing)
+            {
+                _menu?.Dispose();
+            }
+        }
     }
 }
index 2f61ea63a864032fd93c474f7dcae96ff2b15433..dbf68ea07b0df75dc20f9a869b2230652751791d 100644 (file)
@@ -17,19 +17,13 @@ namespace Content.Client.Power.APC.UI
     [GenerateTypedNameReferences]
     public sealed partial class ApcMenu : FancyWindow
     {
-        public event Action? OnBreaker;
-
-        public ApcMenu()
+        public ApcMenu(ApcBoundUserInterface owner)
         {
             IoCManager.InjectDependencies(this);
             RobustXamlLoader.Load(this);
 
-            BreakerButton.OnPressed += _ => OnBreaker?.Invoke();
-        }
-
-        public void SetEntity(EntityUid entity)
-        {
-            EntityView.SetEntity(entity);
+            EntityView.SetEntity(owner.Owner);
+            BreakerButton.OnPressed += _ => owner.BreakerPressed();
         }
 
         public void UpdateState(BoundUserInterfaceState state)
index e975e5d466e181619f58eb517a10308c2c509110..bd5b75de1dadddf89f3f0da52c83d0987c5aca38 100644 (file)
@@ -9,39 +9,35 @@ namespace Content.Client.Power.Generator;
 [GenerateTypedNameReferences]
 public sealed partial class GeneratorWindow : FancyWindow
 {
+    private readonly EntityUid _entity;
+
     [Dependency] private readonly IEntityManager _entityManager = default!;
     [Dependency] private readonly ILocalizationManager _loc = default!;
 
-    private EntityUid _entity;
-
-    public float? MaximumPower;
-
-    public event Action<int>? OnPower;
-    public event Action<bool>? OnState;
-    public event Action? OnSwitchOutput;
-    public event Action? OnEjectFuel;
+    private readonly SharedPowerSwitchableSystem _switchable;
+    private readonly FuelGeneratorComponent? _component;
+    private PortableGeneratorComponentBuiState? _lastState;
 
-    public GeneratorWindow()
+    public GeneratorWindow(PortableGeneratorBoundUserInterface bui, EntityUid entity)
     {
+        _entity = entity;
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
 
+        _entityManager.TryGetComponent(entity, out _component);
+        _switchable = _entityManager.System<SharedPowerSwitchableSystem>();
+
+        EntityView.SetEntity(entity);
         TargetPower.IsValid += IsValid;
         TargetPower.ValueChanged += (args) =>
         {
-            OnPower?.Invoke(args.Value);
+            bui.SetTargetPower(args.Value);
         };
 
-        StartButton.OnPressed += _ => OnState?.Invoke(true);
-        StopButton.OnPressed += _ => OnState?.Invoke(false);
-        OutputSwitchButton.OnPressed += _ => OnSwitchOutput?.Invoke();
-        FuelEject.OnPressed += _ => OnEjectFuel?.Invoke();
-    }
-
-    public void SetEntity(EntityUid entity)
-    {
-        _entity = entity;
-        EntityView.SetEntity(entity);
+        StartButton.OnPressed += _ => bui.Start();
+        StopButton.OnPressed += _ => bui.Stop();
+        OutputSwitchButton.OnPressed += _ => bui.SwitchOutput();
+        FuelEject.OnPressed += _ => bui.EjectFuel();
     }
 
     private bool IsValid(int arg)
@@ -49,7 +45,7 @@ public sealed partial class GeneratorWindow : FancyWindow
         if (arg < 0)
             return false;
 
-        if (arg > (MaximumPower / 1000.0f ?? 0))
+        if (arg > (_lastState?.MaximumPower / 1000.0f ?? 0))
             return false;
 
         return true;
@@ -57,17 +53,16 @@ public sealed partial class GeneratorWindow : FancyWindow
 
     public void Update(PortableGeneratorComponentBuiState state)
     {
-        MaximumPower = state.MaximumPower;
-
-        if (!_entityManager.TryGetComponent(_entity, out FuelGeneratorComponent? component))
+        if (_component == null)
             return;
 
+        _lastState = state;
         if (!TargetPower.LineEditControl.HasKeyboardFocus())
             TargetPower.OverrideValue((int)(state.TargetPower / 1000.0f));
-        var efficiency = SharedGeneratorSystem.CalcFuelEfficiency(state.TargetPower, state.OptimalPower, component);
+        var efficiency = SharedGeneratorSystem.CalcFuelEfficiency(state.TargetPower, state.OptimalPower, _component);
         Efficiency.Text = efficiency.ToString("P1");
 
-        var burnRate = component.OptimalBurnRate / efficiency;
+        var burnRate = _component.OptimalBurnRate / efficiency;
         var left = state.RemainingFuel / burnRate;
 
         Eta.Text = Loc.GetString(
@@ -107,15 +102,14 @@ public sealed partial class GeneratorWindow : FancyWindow
         }
 
         var canSwitch = _entityManager.TryGetComponent(_entity, out PowerSwitchableComponent? switchable);
-        var switcher = _entityManager.System<SharedPowerSwitchableSystem>();
         OutputSwitchLabel.Visible = canSwitch;
         OutputSwitchButton.Visible = canSwitch;
 
         if (switchable != null)
         {
-            var voltage = switcher.VoltageString(switcher.GetVoltage(_entity, switchable));
+            var voltage = _switchable.VoltageString(_switchable.GetVoltage(_entity, switchable));
             OutputSwitchLabel.Text = Loc.GetString("portable-generator-ui-current-output", ("voltage", voltage));
-            var nextVoltage = switcher.VoltageString(switcher.GetNextVoltage(_entity, switchable));
+            var nextVoltage = _switchable.VoltageString(_switchable.GetNextVoltage(_entity, switchable));
             OutputSwitchButton.Text = Loc.GetString("power-switchable-switch-voltage", ("voltage", nextVoltage));
             OutputSwitchButton.Disabled = state.On;
         }
index 550e1041b626d937c0bb6d26f42f45645145396a..30679d71fd65cd8f176d26f08b73e006cd056736 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Power.Generator;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Power.Generator;
 
@@ -17,25 +16,10 @@ public sealed class PortableGeneratorBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         base.Open();
-        _window = this.CreateWindow<GeneratorWindow>();
-        _window.SetEntity(Owner);
-        _window.OnState += args =>
-        {
-            if (args)
-            {
-                Start();
-            }
-            else
-            {
-                Stop();
-            }
-        };
-
-        _window.OnPower += SetTargetPower;
-        _window.OnEjectFuel += EjectFuel;
-        _window.OnSwitchOutput += SwitchOutput;
+        _window = new GeneratorWindow(this, Owner);
 
         _window.OpenCenteredLeft();
+        _window.OnClose += Close;
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -46,6 +30,11 @@ public sealed class PortableGeneratorBoundUserInterface : BoundUserInterface
         _window?.Update(msg);
     }
 
+    protected override void Dispose(bool disposing)
+    {
+       _window?.Dispose();
+    }
+
     public void SetTargetPower(int target)
     {
         SendMessage(new PortableGeneratorSetTargetPowerMessage(target));
index cbc343c06c6f12ac300cddf771c9a9f5d3cb0429..dc1dcd03ef12f687cb31133dfc9fb56d703ff3a9 100644 (file)
@@ -1,5 +1,4 @@
 using Content.Shared.Power;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Power;
 
@@ -12,9 +11,9 @@ public sealed class PowerMonitoringConsoleBoundUserInterface : BoundUserInterfac
 
     protected override void Open()
     {
-        _menu = this.CreateWindow<PowerMonitoringWindow>();
-        _menu.SetEntity(Owner);
-        _menu.SendPowerMonitoringConsoleMessageAction += SendPowerMonitoringConsoleMessage;
+        _menu = new PowerMonitoringWindow(this, Owner);
+        _menu.OpenCentered();
+        _menu.OnClose += Close;
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -23,6 +22,9 @@ public sealed class PowerMonitoringConsoleBoundUserInterface : BoundUserInterfac
 
         var castState = (PowerMonitoringConsoleBoundInterfaceState) state;
 
+        if (castState == null)
+            return;
+
         EntMan.TryGetComponent<TransformComponent>(Owner, out var xform);
         _menu?.ShowEntites
             (castState.TotalSources,
@@ -38,4 +40,13 @@ public sealed class PowerMonitoringConsoleBoundUserInterface : BoundUserInterfac
     {
         SendMessage(new PowerMonitoringConsoleMessage(netEntity, group));
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+
+        _menu?.Dispose();
+    }
 }
index d995299207051b8392b6e75afd70891c3499954f..74752ddc5343a29fad47daf931dc5ec81d645ae2 100644 (file)
@@ -32,7 +32,7 @@ public sealed partial class PowerMonitoringWindow
         if (windowEntry == null)
             return;
 
-        // Update sources and loads
+        // Update sources and loads 
         UpdateEntrySourcesOrLoads(masterContainer, windowEntry.SourcesContainer, focusSources, _sourceIcon);
         UpdateEntrySourcesOrLoads(masterContainer, windowEntry.LoadsContainer, focusLoads, _loadIconPath);
 
@@ -134,7 +134,7 @@ public sealed partial class PowerMonitoringWindow
             subEntry.Button.OnButtonUp += args => { ButtonAction(subEntry, masterContainer); };
         }
 
-        if (!_entManager.TryGetComponent<PowerMonitoringConsoleComponent>(Entity, out var console))
+        if (!_entManager.TryGetComponent<PowerMonitoringConsoleComponent>(_owner, out var console))
             return;
 
         // Update all children
@@ -379,7 +379,7 @@ public sealed class PowerMonitoringWindowEntry : PowerMonitoringWindowBaseEntry
 
         AddChild(MainContainer);
 
-        // Grid container to hold the list of sources when selected
+        // Grid container to hold the list of sources when selected 
         SourcesContainer = new BoxContainer()
         {
             Orientation = LayoutOrientation.Vertical,
index e304325248662a9a0a12541b25169b4ac699565c..81fe1f4d047831cba14179e2e88338b061e5d9f2 100644 (file)
@@ -15,12 +15,13 @@ namespace Content.Client.Power;
 [GenerateTypedNameReferences]
 public sealed partial class PowerMonitoringWindow : FancyWindow
 {
-    [Dependency] private IEntityManager _entManager = default!;
+    private readonly IEntityManager _entManager;
     private readonly SpriteSystem _spriteSystem;
-    [Dependency] private IGameTiming _gameTiming = default!;
+    private readonly IGameTiming _gameTiming;
 
     private const float BlinkFrequency = 1f;
 
+    private EntityUid? _owner;
     private NetEntity? _focusEntity;
 
     public event Action<NetEntity?, PowerMonitoringConsoleGroup>? SendPowerMonitoringConsoleMessageAction;
@@ -33,56 +34,31 @@ public sealed partial class PowerMonitoringWindow : FancyWindow
         { PowerMonitoringConsoleGroup.APC, (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_triangle.png")), Color.LimeGreen) },
     };
 
-    public EntityUid Entity;
-
-    public PowerMonitoringWindow()
+    public PowerMonitoringWindow(PowerMonitoringConsoleBoundUserInterface userInterface, EntityUid? owner)
     {
         RobustXamlLoader.Load(this);
-        IoCManager.InjectDependencies(this);
+        _entManager = IoCManager.Resolve<IEntityManager>();
+        _gameTiming = IoCManager.Resolve<IGameTiming>();
 
         _spriteSystem = _entManager.System<SpriteSystem>();
-
-        // Set trackable entity selected action
-        NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap;
-
-        // Update nav map
-        NavMap.ForceNavMapUpdate();
-
-        // Set UI tab titles
-        MasterTabContainer.SetTabTitle(0, Loc.GetString("power-monitoring-window-label-sources"));
-        MasterTabContainer.SetTabTitle(1, Loc.GetString("power-monitoring-window-label-smes"));
-        MasterTabContainer.SetTabTitle(2, Loc.GetString("power-monitoring-window-label-substation"));
-        MasterTabContainer.SetTabTitle(3, Loc.GetString("power-monitoring-window-label-apc"));
-
-        // Track when the MasterTabContainer changes its tab
-        MasterTabContainer.OnTabChanged += OnTabChanged;
-
-        // Set UI toggles
-        ShowHVCable.OnToggled += _ => OnShowCableToggled(PowerMonitoringConsoleLineGroup.HighVoltage);
-        ShowMVCable.OnToggled += _ => OnShowCableToggled(PowerMonitoringConsoleLineGroup.MediumVoltage);
-        ShowLVCable.OnToggled += _ => OnShowCableToggled(PowerMonitoringConsoleLineGroup.Apc);
-    }
-
-    public void SetEntity(EntityUid uid)
-    {
-        Entity = uid;
+        _owner = owner;
 
         // Pass owner to nav map
-        NavMap.Owner = uid;
+        NavMap.Owner = _owner;
 
         // Set nav map grid uid
         var stationName = Loc.GetString("power-monitoring-window-unknown-location");
 
-        if (_entManager.TryGetComponent<TransformComponent>(uid, out var xform))
+        if (_entManager.TryGetComponent<TransformComponent>(owner, out var xform))
         {
             NavMap.MapUid = xform.GridUid;
 
-            // Assign station name
+            // Assign station name      
             if (_entManager.TryGetComponent<MetaDataComponent>(xform.GridUid, out var stationMetaData))
                 stationName = stationMetaData.EntityName;
 
             var msg = new FormattedMessage();
-            msg.AddMarkupOrThrow(Loc.GetString("power-monitoring-window-station-name", ("stationName", stationName)));
+            msg.AddMarkup(Loc.GetString("power-monitoring-window-station-name", ("stationName", stationName)));
 
             StationName.SetMessage(msg);
         }
@@ -92,6 +68,29 @@ public sealed partial class PowerMonitoringWindow : FancyWindow
             StationName.SetMessage(stationName);
             NavMap.Visible = false;
         }
+
+        // Set trackable entity selected action
+        NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap;
+
+        // Update nav map
+        NavMap.ForceNavMapUpdate();
+
+        // Set UI tab titles
+        MasterTabContainer.SetTabTitle(0, Loc.GetString("power-monitoring-window-label-sources"));
+        MasterTabContainer.SetTabTitle(1, Loc.GetString("power-monitoring-window-label-smes"));
+        MasterTabContainer.SetTabTitle(2, Loc.GetString("power-monitoring-window-label-substation"));
+        MasterTabContainer.SetTabTitle(3, Loc.GetString("power-monitoring-window-label-apc"));
+
+        // Track when the MasterTabContainer changes its tab
+        MasterTabContainer.OnTabChanged += OnTabChanged;
+
+        // Set UI toggles
+        ShowHVCable.OnToggled += _ => OnShowCableToggled(PowerMonitoringConsoleLineGroup.HighVoltage);
+        ShowMVCable.OnToggled += _ => OnShowCableToggled(PowerMonitoringConsoleLineGroup.MediumVoltage);
+        ShowLVCable.OnToggled += _ => OnShowCableToggled(PowerMonitoringConsoleLineGroup.Apc);
+
+        // Set power monitoring message action
+        SendPowerMonitoringConsoleMessageAction += userInterface.SendPowerMonitoringConsoleMessage;
     }
 
     private void OnTabChanged(int tab)
@@ -114,7 +113,10 @@ public sealed partial class PowerMonitoringWindow : FancyWindow
         PowerMonitoringConsoleEntry[] focusLoads,
         EntityCoordinates? monitorCoords)
     {
-        if (!_entManager.TryGetComponent<PowerMonitoringConsoleComponent>(Entity, out var console))
+        if (_owner == null)
+            return;
+
+        if (!_entManager.TryGetComponent<PowerMonitoringConsoleComponent>(_owner.Value, out var console))
             return;
 
         // Update power status text
@@ -159,13 +161,13 @@ public sealed partial class PowerMonitoringWindow : FancyWindow
         }
 
         // Show monitor location
-        var mon = _entManager.GetNetEntity(Entity);
+        var mon = _entManager.GetNetEntity(_owner);
 
-        if (monitorCoords != null && mon.IsValid())
+        if (monitorCoords != null && mon != null)
         {
             var texture = _spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png")));
             var blip = new NavMapBlip(monitorCoords.Value, texture, Color.Cyan, true, false);
-            NavMap.TrackedEntities[mon] = blip;
+            NavMap.TrackedEntities[mon.Value] = blip;
         }
 
         // If the entry group doesn't match the current tab, the data is out dated, do not use it
@@ -237,7 +239,7 @@ public sealed partial class PowerMonitoringWindow : FancyWindow
         if (netEntity == null)
             return;
 
-        if (!_entManager.TryGetComponent<PowerMonitoringConsoleComponent>(Entity, out var console))
+        if (!_entManager.TryGetComponent<PowerMonitoringConsoleComponent>(_owner, out var console))
             return;
 
         if (!console.PowerMonitoringDeviceMetaData.TryGetValue(netEntity.Value, out var metaData))
@@ -264,7 +266,7 @@ public sealed partial class PowerMonitoringWindow : FancyWindow
     {
         AutoScrollToFocus();
 
-        // Warning sign pulse
+        // Warning sign pulse        
         var lit = _gameTiming.RealTime.TotalSeconds % BlinkFrequency > BlinkFrequency / 2f;
         SystemWarningPanel.Modulate = lit ? Color.White : new Color(178, 178, 178);
     }
index aefb319181284f3814a0aebc181f844db43d52ba..3eb0397a6908b640b0e1849030017299b12bde28 100644 (file)
@@ -20,36 +20,31 @@ public sealed partial class RCDMenu : RadialMenu
     [Dependency] private readonly IPrototypeManager _protoManager = default!;
     [Dependency] private readonly IPlayerManager _playerManager = default!;
 
-    private SharedPopupSystem _popup;
-    private SpriteSystem _sprites;
+    private readonly SpriteSystem _spriteSystem;
+    private readonly SharedPopupSystem _popup;
 
     public event Action<ProtoId<RCDPrototype>>? SendRCDSystemMessageAction;
 
     private EntityUid _owner;
 
-    public RCDMenu()
+    public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui)
     {
         IoCManager.InjectDependencies(this);
         RobustXamlLoader.Load(this);
 
+        _spriteSystem = _entManager.System<SpriteSystem>();
         _popup = _entManager.System<SharedPopupSystem>();
-        _sprites = _entManager.System<SpriteSystem>();
 
-        OnChildAdded += AddRCDMenuButtonOnClickActions;
-    }
-
-    public void SetEntity(EntityUid uid)
-    {
-        _owner = uid;
-    }
+        _owner = owner;
 
-    public void Refresh()
-    {
         // Find the main radial container
         var main = FindControl<RadialContainer>("Main");
 
+        if (main == null)
+            return;
+
         // Populate secondary radial containers
-        if (!_entManager.TryGetComponent<RCDComponent>(_owner, out var rcd))
+        if (!_entManager.TryGetComponent<RCDComponent>(owner, out var rcd))
             return;
 
         foreach (var protoId in rcd.AvailablePrototypes)
@@ -61,6 +56,10 @@ public sealed partial class RCDMenu : RadialMenu
                 continue;
 
             var parent = FindControl<RadialContainer>(proto.Category);
+
+            if (parent == null)
+                continue;
+
             var tooltip = Loc.GetString(proto.SetName);
 
             if ((proto.Mode == RcdMode.ConstructTile || proto.Mode == RcdMode.ConstructObject) &&
@@ -85,7 +84,7 @@ public sealed partial class RCDMenu : RadialMenu
                 {
                     VerticalAlignment = VAlignment.Center,
                     HorizontalAlignment = HAlignment.Center,
-                    Texture = _sprites.Frame0(proto.Sprite),
+                    Texture = _spriteSystem.Frame0(proto.Sprite),
                     TextureScale = new Vector2(2f, 2f),
                 };
 
@@ -113,9 +112,11 @@ public sealed partial class RCDMenu : RadialMenu
 
         // Set up menu actions
         foreach (var child in Children)
-        {
             AddRCDMenuButtonOnClickActions(child);
-        }
+
+        OnChildAdded += AddRCDMenuButtonOnClickActions;
+
+        SendRCDSystemMessageAction += bui.SendRCDSystemMessage;
     }
 
     private static string OopsConcat(string a, string b)
index 1dd03626ae62d674d28f1f382fd7a8dd1aaf5860..a37dbcecf8c829d4bf843c71145de978333ccc06 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.RCD.Components;
 using JetBrains.Annotations;
 using Robust.Client.Graphics;
 using Robust.Client.Input;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.RCD;
@@ -25,9 +24,8 @@ public sealed class RCDMenuBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<RCDMenu>();
-        _menu.SetEntity(Owner);
-        _menu.SendRCDSystemMessageAction += SendRCDSystemMessage;
+        _menu = new(Owner, this);
+        _menu.OnClose += Close;
 
         // Open the menu, centered on the mouse
         var vpSize = _displayManager.ScreenSize;
@@ -36,8 +34,16 @@ public sealed class RCDMenuBoundUserInterface : BoundUserInterface
 
     public void SendRCDSystemMessage(ProtoId<RCDPrototype> protoId)
     {
-        // A predicted message cannot be used here as the RCD UI is closed immediately
+        // A predicted message cannot be used here as the RCD UI is closed immediately 
         // after this message is sent, which will stop the server from receiving it
         SendMessage(new RCDSystemMessage(protoId));
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing) return;
+
+        _menu?.Dispose();
+    }
 }
index 401e7edd44a65d2e1ab2ca82cd0874b64960222b..7b3e39aa084b11a486e874594d54d920a6c453f9 100644 (file)
@@ -1,8 +1,6 @@
 using Content.Shared.Radio;
 using Content.Shared.Radio.Components;
 using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Radio.Ui;
 
@@ -21,12 +19,9 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<IntercomMenu>();
+        var comp = EntMan.GetComponent<IntercomComponent>(Owner);
 
-        if (EntMan.TryGetComponent(Owner, out IntercomComponent? intercom))
-        {
-            _menu.Update((Owner, intercom));
-        }
+        _menu = new((Owner, comp));
 
         _menu.OnMicPressed += enabled =>
         {
@@ -40,6 +35,17 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface
         {
             SendMessage(new SelectIntercomChannelMessage(channel));
         };
+
+        _menu.OnClose += Close;
+        _menu.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+        _menu?.Close();
     }
 
     public void Update(Entity<IntercomComponent> ent)
index 20d2e4a3e54e98119909e5622a896ebd95110b54..2e08913051c8bcaa74f9015cebc7e68ab1b511e1 100644 (file)
@@ -18,13 +18,15 @@ public sealed partial class IntercomMenu : FancyWindow
 
     private readonly List<string> _channels = new();
 
-    public IntercomMenu()
+    public IntercomMenu(Entity<IntercomComponent> entity)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
 
         MicButton.OnPressed += args => OnMicPressed?.Invoke(args.Button.Pressed);
         SpeakerButton.OnPressed += args => OnSpeakerPressed?.Invoke(args.Button.Pressed);
+
+        Update(entity);
     }
 
     public void Update(Entity<IntercomComponent> entity)
index 9641adb5b2d368c31de74f123f74fa320f5fdd3b..c14a8c5bd05c881bdc103fa5c1feb22123c2e8ce 100644 (file)
@@ -1,7 +1,5 @@
 using Content.Shared.Research;
 using Content.Shared.Research.Components;
-using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Research.UI
 {
@@ -18,7 +16,10 @@ namespace Content.Client.Research.UI
         {
             base.Open();
 
-            _menu = this.CreateWindow<DiskConsoleMenu>();
+            _menu = new();
+
+            _menu.OnClose += Close;
+            _menu.OpenCentered();
 
             _menu.OnServerButtonPressed += () =>
             {
@@ -30,6 +31,14 @@ namespace Content.Client.Research.UI
             };
         }
 
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing)
+                return;
+            _menu?.Close();
+        }
+
         protected override void UpdateState(BoundUserInterfaceState state)
         {
             base.UpdateState(state);
index 288445e4deaa89234d9f989414364b4976e5df91..a0a2b58e88925de8f9e33fbb08ca9de254f5aa79 100644 (file)
@@ -1,6 +1,4 @@
 using Content.Shared.Research.Components;
-using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Research.UI
 {
@@ -17,9 +15,10 @@ namespace Content.Client.Research.UI
         protected override void Open()
         {
             base.Open();
-            _menu = this.CreateWindow<ResearchClientServerSelectionMenu>();
-            _menu.OnServerSelected += SelectServer;
-            _menu.OnServerDeselected += DeselectServer;
+
+            _menu = new ResearchClientServerSelectionMenu(this);
+            _menu.OnClose += Close;
+            _menu.OpenCentered();
         }
 
         public void SelectServer(int serverId)
@@ -38,5 +37,12 @@ namespace Content.Client.Research.UI
             if (state is not ResearchClientBoundInterfaceState rState) return;
             _menu?.Populate(rState.ServerCount, rState.ServerNames, rState.ServerIds, rState.SelectedServerId);
         }
+
+        protected override void Dispose(bool disposing)
+        {
+            base.Dispose(disposing);
+            if (!disposing) return;
+            _menu?.Dispose();
+        }
     }
 }
index d10f8b39f48ab32af4be6eb94ea9d496c4170891..ceaa965e59f763a0b5b33129cee3d6bbddfb4770 100644 (file)
@@ -13,26 +13,27 @@ namespace Content.Client.Research.UI
         private int[] _serverIds = Array.Empty<int>();
         private int _selectedServerId = -1;
 
-        public event Action<int>? OnServerSelected;
-        public event Action? OnServerDeselected;
+        private ResearchClientBoundUserInterface Owner { get; }
 
-        public ResearchClientServerSelectionMenu()
+        public ResearchClientServerSelectionMenu(ResearchClientBoundUserInterface owner)
         {
             RobustXamlLoader.Load(this);
             IoCManager.InjectDependencies(this);
 
+            Owner = owner;
+
             Servers.OnItemSelected += OnItemSelected;
             Servers.OnItemDeselected += OnItemDeselected;
         }
 
         public void OnItemSelected(ItemList.ItemListSelectedEventArgs itemListSelectedEventArgs)
         {
-            OnServerSelected?.Invoke(_serverIds[itemListSelectedEventArgs.ItemIndex]);
+            Owner.SelectServer(_serverIds[itemListSelectedEventArgs.ItemIndex]);
         }
 
         public void OnItemDeselected(ItemList.ItemListDeselectedEventArgs itemListDeselectedEventArgs)
         {
-            OnServerDeselected?.Invoke();
+            Owner.DeselectServer();
         }
 
         public void Populate(int serverCount, string[] serverNames, int[] serverIds, int selectedServerId)
index 2895ada61fbb9ab3072067379c2229246b72c87f..2a9782045b86e89f5035578944d658e52fc98ee4 100644 (file)
@@ -1,8 +1,5 @@
 using Content.Shared.Research.Components;
-using Content.Shared.Research.Prototypes;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
-using Robust.Shared.Prototypes;
 
 namespace Content.Client.Research.UI;
 
@@ -22,8 +19,7 @@ public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface
 
         var owner = Owner;
 
-        _consoleMenu = this.CreateWindow<ResearchConsoleMenu>();
-        _consoleMenu.SetEntity(owner);
+        _consoleMenu = new ResearchConsoleMenu(owner);
 
         _consoleMenu.OnTechnologyCardPressed += id =>
         {
@@ -34,20 +30,10 @@ public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface
         {
             SendMessage(new ConsoleServerSelectionMessage());
         };
-    }
-
-    public override void OnProtoReload(PrototypesReloadedEventArgs args)
-    {
-        base.OnProtoReload(args);
-
-        if (!args.WasModified<TechnologyPrototype>())
-            return;
 
-        if (State is not ResearchConsoleBoundInterfaceState rState)
-            return;
+        _consoleMenu.OnClose += Close;
 
-        _consoleMenu?.UpdatePanels(rState);
-        _consoleMenu?.UpdateInformationPanel(rState);
+        _consoleMenu.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -59,4 +45,12 @@ public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface
         _consoleMenu?.UpdatePanels(castState);
         _consoleMenu?.UpdateInformationPanel(castState);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+        _consoleMenu?.Dispose();
+    }
 }
index eafbe75fbb9e25d071bfc1bb8cbe66f68f823463..77ebe6740c542513aa3ce46d1dae1d36b00bf32d 100644 (file)
@@ -25,13 +25,14 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
     [Dependency] private readonly IEntityManager _entity = default!;
     [Dependency] private readonly IPrototypeManager _prototype = default!;
     [Dependency] private readonly IPlayerManager _player = default!;
+    private readonly TechnologyDatabaseComponent? _technologyDatabase;
     private readonly ResearchSystem _research;
     private readonly SpriteSystem _sprite;
     private readonly AccessReaderSystem _accessReader;
 
-    public EntityUid Entity;
+    public readonly EntityUid Entity;
 
-    public ResearchConsoleMenu()
+    public ResearchConsoleMenu(EntityUid entity)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
@@ -39,23 +40,21 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
         _research = _entity.System<ResearchSystem>();
         _sprite = _entity.System<SpriteSystem>();
         _accessReader = _entity.System<AccessReaderSystem>();
+        Entity = entity;
 
         ServerButton.OnPressed += _ => OnServerButtonPressed?.Invoke();
-    }
 
-    public void SetEntity(EntityUid entity)
-    {
-        Entity = entity;
+        _entity.TryGetComponent(entity, out _technologyDatabase);
     }
 
-    public void UpdatePanels(ResearchConsoleBoundInterfaceState state)
+    public void  UpdatePanels(ResearchConsoleBoundInterfaceState state)
     {
         TechnologyCardsContainer.Children.Clear();
 
         var availableTech = _research.GetAvailableTechnologies(Entity);
         SyncTechnologyList(AvailableCardsContainer, availableTech);
 
-        if (!_entity.TryGetComponent(Entity, out TechnologyDatabaseComponent? database))
+        if (_technologyDatabase == null)
             return;
 
         // i can't figure out the spacing so here you go
@@ -67,7 +66,7 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
         var hasAccess = _player.LocalEntity is not { } local ||
                         !_entity.TryGetComponent<AccessReaderComponent>(Entity, out var access) ||
                         _accessReader.IsAllowed(local, Entity, access);
-        foreach (var techId in database.CurrentTechnologyCards)
+        foreach (var techId in _technologyDatabase.CurrentTechnologyCards)
         {
             var tech = _prototype.Index<TechnologyPrototype>(techId);
             var cardControl = new TechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech, includeTier: false), state.Points, hasAccess);
@@ -75,7 +74,7 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
             TechnologyCardsContainer.AddChild(cardControl);
         }
 
-        var unlockedTech = database.UnlockedTechnologies.Select(x => _prototype.Index<TechnologyPrototype>(x));
+        var unlockedTech = _technologyDatabase.UnlockedTechnologies.Select(x => _prototype.Index<TechnologyPrototype>(x));
         SyncTechnologyList(UnlockedCardsContainer, unlockedTech);
     }
 
@@ -86,14 +85,14 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
             ("points", state.Points)));
         ResearchAmountLabel.SetMessage(amountMsg);
 
-        if (!_entity.TryGetComponent(Entity, out TechnologyDatabaseComponent? database))
+        if (_technologyDatabase == null)
             return;
 
         var disciplineText = Loc.GetString("research-discipline-none");
         var disciplineColor = Color.Gray;
-        if (database.MainDiscipline != null)
+        if (_technologyDatabase.MainDiscipline != null)
         {
-            var discipline = _prototype.Index<TechDisciplinePrototype>(database.MainDiscipline);
+            var discipline = _prototype.Index<TechDisciplinePrototype>(_technologyDatabase.MainDiscipline);
             disciplineText = Loc.GetString(discipline.Name);
             disciplineColor = discipline.Color;
         }
@@ -104,10 +103,10 @@ public sealed partial class ResearchConsoleMenu : FancyWindow
         MainDisciplineLabel.SetMessage(msg);
 
         TierDisplayContainer.Children.Clear();
-        foreach (var disciplineId in database.SupportedDisciplines)
+        foreach (var disciplineId in _technologyDatabase.SupportedDisciplines)
         {
             var discipline = _prototype.Index<TechDisciplinePrototype>(disciplineId);
-            var tier = _research.GetHighestDisciplineTier(database, discipline);
+            var tier = _research.GetHighestDisciplineTier(_technologyDatabase, discipline);
 
             // don't show tiers with no available tech
             if (tier == 0)
index 9a5159880f903b7068a165f710c9511068e938b7..6185979eee6d226e62c27b1e8d8f8031f4ef2cc4 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Robotics;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Robotics.UI;
 
@@ -17,9 +16,7 @@ public sealed class RoboticsConsoleBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<RoboticsConsoleWindow>();
-        _window.SetEntity(Owner);
-
+        _window = new RoboticsConsoleWindow(Owner);
         _window.OnDisablePressed += address =>
         {
             SendMessage(new RoboticsConsoleDisableMessage(address));
@@ -28,6 +25,9 @@ public sealed class RoboticsConsoleBoundUserInterface : BoundUserInterface
         {
             SendMessage(new RoboticsConsoleDestroyMessage(address));
         };
+        _window.OnClose += Close;
+
+        _window.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -37,6 +37,14 @@ public sealed class RoboticsConsoleBoundUserInterface : BoundUserInterface
         if (state is not RoboticsConsoleState cast)
             return;
 
-        _window.UpdateState(cast);
+        _window?.UpdateState(cast);
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        if (disposing)
+            _window?.Dispose();
     }
 }
index 87d7e62c392ba980d99247861ba69bfda71715b5..fc7b234bccc1435c018f0ef5888a7b7d43e25f28 100644 (file)
@@ -23,12 +23,11 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow
     public Action<string>? OnDisablePressed;
     public Action<string>? OnDestroyPressed;
 
+    private Entity<RoboticsConsoleComponent, LockComponent?> _console;
     private string? _selected;
     private Dictionary<string, CyborgControlData> _cyborgs = new();
 
-    public EntityUid Entity;
-
-    public RoboticsConsoleWindow()
+    public RoboticsConsoleWindow(EntityUid console)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
@@ -36,6 +35,9 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow
         _lock = _entMan.System<LockSystem>();
         _sprite = _entMan.System<SpriteSystem>();
 
+        _console = (console, _entMan.GetComponent<RoboticsConsoleComponent>(console), null);
+        _entMan.TryGetComponent(_console, out _console.Comp2);
+
         Cyborgs.OnItemSelected += args =>
         {
             if (Cyborgs[args.ItemIndex].Metadata is not string address)
@@ -64,11 +66,6 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow
         DestroyButton.StyleClasses.Add(StyleBase.ButtonCaution);
     }
 
-    public void SetEntity(EntityUid uid)
-    {
-        Entity = uid;
-    }
-
     public void UpdateState(RoboticsConsoleState state)
     {
         _cyborgs = state.Cyborgs;
@@ -84,7 +81,7 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow
 
         PopulateData();
 
-        var locked = _lock.IsLocked(Entity);
+        var locked = _lock.IsLocked((_console, _console.Comp2));
         DangerZone.Visible = !locked;
         LockedMessage.Visible = locked;
     }
@@ -138,19 +135,13 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow
 
         // how the turntables
         DisableButton.Disabled = !(data.HasBrain && data.CanDisable);
+        DestroyButton.Disabled = _timing.CurTime < _console.Comp1.NextDestroy;
     }
 
     protected override void FrameUpdate(FrameEventArgs args)
     {
         base.FrameUpdate(args);
 
-        if (_entMan.TryGetComponent(Entity, out RoboticsConsoleComponent? console))
-        {
-            DestroyButton.Disabled = _timing.CurTime < console.NextDestroy;
-        }
-        else
-        {
-            DestroyButton.Disabled = true;
-        }
+        DestroyButton.Disabled = _timing.CurTime < _console.Comp1.NextDestroy;
     }
 }
index 663bde15b0db5b0366d9b4d60c0ac518ca227ab5..8f1723d1f221165d27762bc0d9d7ade862a3c591 100644 (file)
@@ -30,9 +30,17 @@ public sealed class SalvageExpeditionConsoleBoundUserInterface : BoundUserInterf
     protected override void Open()
     {
         base.Open();
-        _window = this.CreateWindow<OfferingWindow>();
+        _window = new OfferingWindow();
         _window.Title = Loc.GetString("salvage-expedition-window-title");
-        _window.OpenCenteredLeft();
+        _window.OnClose += Close;
+        _window?.OpenCenteredLeft();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        _window?.Dispose();
+        _window = null;
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
index a248126a855eb8da2fc4ab2b9fa37d36cd8bd2ca..eafb692733f3613ac839399bd9a27e7c7bbf7bb4 100644 (file)
@@ -21,9 +21,13 @@ public sealed class SalvageMagnetBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<OfferingWindow>();
-        _window.Title = Loc.GetString("salvage-magnet-window-title");
-        _window.OpenCenteredLeft();
+        if (_window is null)
+        {
+            _window = new OfferingWindow();
+            _window.Title = Loc.GetString("salvage-magnet-window-title");
+            _window.OnClose += Close;
+            _window.OpenCenteredLeft();
+        }
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -108,4 +112,15 @@ public sealed class SalvageMagnetBoundUserInterface : BoundUserInterface
             _window.AddOption(option);
         }
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        if (disposing)
+        {
+            _window?.Close();
+            _window?.Dispose();
+        }
+    }
 }
index b8b4fb8a74693c0d61dafa790ef280df397ef334..086369aa264e122d92a038fc3ceb61d9f2606b0f 100644 (file)
@@ -3,7 +3,6 @@ using Content.Shared.Shuttles.BUIStates;
 using Content.Shared.Shuttles.Events;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Shuttles.BUI;
 
@@ -21,7 +20,8 @@ public sealed class IFFConsoleBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<IFFConsoleWindow>();
+        _window = new IFFConsoleWindow();
+        _window.OnClose += Close;
         _window.ShowIFF += SendIFFMessage;
         _window.ShowVessel += SendVesselMessage;
         _window.OpenCenteredLeft();
index f75759b042fd72bb323cba7637a4df1e24ba0809..4bd44a47a8e61c6b3ce036a69ca9beec4eb84ac4 100644 (file)
@@ -2,7 +2,6 @@ using Content.Client.Shuttles.UI;
 using Content.Shared.Shuttles.BUIStates;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using RadarConsoleWindow = Content.Client.Shuttles.UI.RadarConsoleWindow;
 
 namespace Content.Client.Shuttles.BUI;
@@ -21,7 +20,18 @@ public sealed class RadarConsoleBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<RadarConsoleWindow>();
+        _window = new RadarConsoleWindow();
+        _window.OnClose += Close;
+        _window.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (disposing)
+        {
+            _window?.Dispose();
+        }
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
index e677181419e9402fcbf36844c1c1052c96dded58..af7b6055c809c1e63f3dca56e18dac7742cedf0f 100644 (file)
@@ -2,7 +2,6 @@ using Content.Client.Shuttles.UI;
 using Content.Shared.Shuttles.BUIStates;
 using Content.Shared.Shuttles.Events;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 using Robust.Shared.Map;
 
 namespace Content.Client.Shuttles.BUI;
@@ -20,7 +19,9 @@ public sealed class ShuttleConsoleBoundUserInterface : BoundUserInterface
     protected override void Open()
     {
         base.Open();
-        _window = this.CreateWindow<ShuttleConsoleWindow>();
+        _window = new ShuttleConsoleWindow();
+        _window.OpenCentered();
+        _window.OnClose += Close;
 
         _window.RequestFTL += OnFTLRequest;
         _window.RequestBeaconFTL += OnFTLBeaconRequest;
index ed9bf40a481af40fb23cecf03840a3905861ed13..3cc2a35d79514544384e94865ee86cd7e4f6658e 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Silicons.Borgs;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Silicons.Borgs;
 
@@ -19,8 +18,9 @@ public sealed class BorgBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<BorgMenu>();
-        _menu.SetEntity(Owner);
+        var owner = Owner;
+
+        _menu = new BorgMenu(owner);
 
         _menu.BrainButtonPressed += () =>
         {
@@ -41,6 +41,10 @@ public sealed class BorgBoundUserInterface : BoundUserInterface
         {
             SendMessage(new BorgRemoveModuleBuiMessage(EntMan.GetNetEntity(module)));
         };
+
+        _menu.OnClose += Close;
+
+        _menu.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -51,4 +55,12 @@ public sealed class BorgBoundUserInterface : BoundUserInterface
             return;
         _menu?.UpdateState(msg);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+        _menu?.Dispose();
+    }
 }
index 4cc2e41a8fbee384560b5dd6544976b6d8fa0dfa..7d8fd9fe57d757ac8bde251213e2bf49684732b8 100644 (file)
@@ -10,7 +10,7 @@
                   VerticalExpand="True">
         <BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True" Margin="15 10 15 15">
             <BoxContainer Orientation="Horizontal">
-                <ProgressBar Name="ChargeBar" Access="Public" HorizontalExpand="True" MinValue="0" Value="1" MaxValue="1">
+                <ProgressBar Name="ChargeBar" Access="Public" HorizontalExpand="True" MinValue="0" MaxValue="1">
                     <Label Name="ChargeLabel" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="5 0 0 0"/>
                 </ProgressBar>
                 <Control MinWidth="5"/>
index f6a861aa057b96c4842218448de46f75180de852..474a83b453093afe4fb09a930b305799a9555547 100644 (file)
@@ -21,33 +21,25 @@ public sealed partial class BorgMenu : FancyWindow
     public Action<string>? NameChanged;
     public Action<EntityUid>? RemoveModuleButtonPressed;
 
+    private readonly BorgChassisComponent? _chassis;
+    public readonly EntityUid Entity;
     public float AccumulatedTime;
     private string _lastValidName;
     private List<EntityUid> _modules = new();
 
-    public EntityUid Entity;
-
-    public BorgMenu()
+    public BorgMenu(EntityUid entity)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
 
-        _lastValidName = NameLineEdit.Text;
-
-        EjectBatteryButton.OnPressed += _ => EjectBatteryButtonPressed?.Invoke();
-        BrainButton.OnPressed += _ => BrainButtonPressed?.Invoke();
-
-        NameLineEdit.OnTextChanged += OnNameChanged;
-        NameLineEdit.OnTextEntered += OnNameEntered;
-        NameLineEdit.OnFocusExit += OnNameFocusExit;
+        Entity = entity;
 
-        UpdateBrainButton();
-    }
+        if (_entity.TryGetComponent<BorgChassisComponent>(Entity, out var chassis))
+            _chassis = chassis;
 
-    public void SetEntity(EntityUid entity)
-    {
-        Entity = entity;
         BorgSprite.SetEntity(entity);
+        ChargeBar.MaxValue = 1f;
+        ChargeBar.Value = 1f;
 
         if (_entity.TryGetComponent<NameIdentifierComponent>(Entity, out var nameIdentifierComponent))
         {
@@ -63,6 +55,17 @@ public sealed partial class BorgMenu : FancyWindow
             NameIdentifierLabel.Visible = false;
             NameLineEdit.Text = _entity.GetComponent<MetaDataComponent>(Entity).EntityName;
         }
+
+        _lastValidName = NameLineEdit.Text;
+
+        EjectBatteryButton.OnPressed += _ => EjectBatteryButtonPressed?.Invoke();
+        BrainButton.OnPressed += _ => BrainButtonPressed?.Invoke();
+
+        NameLineEdit.OnTextChanged += OnNameChanged;
+        NameLineEdit.OnTextEntered += OnNameEntered;
+        NameLineEdit.OnFocusExit += OnNameFocusExit;
+
+        UpdateBrainButton();
     }
 
     protected override void FrameUpdate(FrameEventArgs args)
@@ -86,7 +89,7 @@ public sealed partial class BorgMenu : FancyWindow
 
     private void UpdateBrainButton()
     {
-        if (_entity.TryGetComponent(Entity, out BorgChassisComponent? chassis) && chassis.BrainEntity is { } brain)
+        if (_chassis?.BrainEntity is { } brain)
         {
             BrainButton.Text = _entity.GetComponent<MetaDataComponent>(brain).EntityName;
             BrainView.Visible = true;
@@ -105,17 +108,17 @@ public sealed partial class BorgMenu : FancyWindow
 
     private void UpdateModulePanel()
     {
-        if (!_entity.TryGetComponent(Entity, out BorgChassisComponent? chassis))
+        if (_chassis == null)
             return;
 
         ModuleCounter.Text = Loc.GetString("borg-ui-module-counter",
-            ("actual", chassis.ModuleCount),
-            ("max", chassis.MaxModules));
+            ("actual", _chassis.ModuleCount),
+            ("max", _chassis.MaxModules));
 
-        if (chassis.ModuleContainer.Count == _modules.Count)
+        if (_chassis.ModuleContainer.Count == _modules.Count)
         {
             var isSame = true;
-            foreach (var module in chassis.ModuleContainer.ContainedEntities)
+            foreach (var module in _chassis.ModuleContainer.ContainedEntities)
             {
                 if (_modules.Contains(module))
                     continue;
@@ -129,7 +132,7 @@ public sealed partial class BorgMenu : FancyWindow
 
         ModuleContainer.Children.Clear();
         _modules.Clear();
-        foreach (var module in chassis.ModuleContainer.ContainedEntities)
+        foreach (var module in _chassis.ModuleContainer.ContainedEntities)
         {
             var control = new BorgModuleControl(module, _entity);
             control.RemoveButtonPressed += () =>
index 56216b91847e218f1f94592b4c523c91fd1fa396..d150735fa110ab975bcc726ccc931e583fa28a54 100644 (file)
@@ -2,7 +2,6 @@ using System.Linq;
 using Content.Shared.Silicons.Laws;
 using Content.Shared.Silicons.Laws.Components;
 using JetBrains.Annotations;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Silicons.Laws.Ui;
 
@@ -23,7 +22,18 @@ public sealed class SiliconLawBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _menu = this.CreateWindow<SiliconLawMenu>();
+        _menu = new();
+
+        _menu.OnClose += Close;
+        _menu.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+        _menu?.Close();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
index 7d6a6cf2a5a09042fd5667c1f56bad2b211f2e35..e8442d239086faaa9855d0ddf7904c6f488bdd36 100644 (file)
@@ -1,6 +1,6 @@
 using Content.Shared.SprayPainter;
 using Content.Shared.SprayPainter.Components;
-using Robust.Client.UserInterface;
+using Robust.Client.GameObjects;
 using Robust.Client.UserInterface.Controls;
 
 namespace Content.Client.SprayPainter.UI;
@@ -10,6 +10,9 @@ public sealed class SprayPainterBoundUserInterface : BoundUserInterface
     [ViewVariables]
     private SprayPainterWindow? _window;
 
+    [ViewVariables]
+    private SprayPainterSystem? _painter;
+
     public SprayPainterBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
     {
     }
@@ -18,15 +21,27 @@ public sealed class SprayPainterBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<SprayPainterWindow>();
+        if (!EntMan.TryGetComponent<SprayPainterComponent>(Owner, out var comp))
+            return;
+
+        _window = new SprayPainterWindow();
 
+        _painter = EntMan.System<SprayPainterSystem>();
+
+        _window.OnClose += Close;
         _window.OnSpritePicked = OnSpritePicked;
         _window.OnColorPicked = OnColorPicked;
 
-        if (EntMan.TryGetComponent(Owner, out SprayPainterComponent? comp))
-        {
-            _window.Populate(EntMan.System<SprayPainterSystem>().Entries, comp.Index, comp.PickedColor, comp.ColorPalette);
-        }
+        _window.Populate(_painter.Entries, comp.Index, comp.PickedColor, comp.ColorPalette);
+
+        _window.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        _window?.Dispose();
     }
 
     private void OnSpritePicked(ItemList.ItemListSelectedEventArgs args)
index e7bab71e38e8b2f9434fb6bdb5868fb10566a6bc..720a2efb9ddea3dc9835f2ac01a6074aeb5a2811 100644 (file)
@@ -1,5 +1,4 @@
 using Content.Shared.StationRecords;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.StationRecords;
 
@@ -16,12 +15,15 @@ public sealed class GeneralStationRecordConsoleBoundUserInterface : BoundUserInt
     {
         base.Open();
 
-        _window = this.CreateWindow<GeneralStationRecordConsoleWindow>();
+        _window = new();
         _window.OnKeySelected += key =>
             SendMessage(new SelectStationRecord(key));
         _window.OnFiltersChanged += (type, filterValue) =>
             SendMessage(new SetStationRecordFilter(type, filterValue));
         _window.OnDeleted += id => SendMessage(new DeleteStationRecord(id));
+        _window.OnClose += Close;
+
+        _window.OpenCentered();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
@@ -33,4 +35,11 @@ public sealed class GeneralStationRecordConsoleBoundUserInterface : BoundUserInt
 
         _window?.UpdateState(cast);
     }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+
+        _window?.Close();
+    }
 }
index 7ed67f7b5dd9fdfbad7475efc91d6a0c8abafc27..0010aedd96472f7e30b9c66050104834864181b9 100644 (file)
@@ -2,7 +2,6 @@ using Content.Shared.Store;
 using JetBrains.Annotations;
 using System.Linq;
 using Content.Shared.Store.Components;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.Store.Ui;
@@ -27,10 +26,13 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
 
     protected override void Open()
     {
-        _menu = this.CreateWindow<StoreMenu>();
+        _menu = new StoreMenu();
         if (EntMan.TryGetComponent<StoreComponent>(Owner, out var store))
             _menu.Title = Loc.GetString(store.Name);
 
+        _menu.OpenCentered();
+        _menu.OnClose += Close;
+
         _menu.OnListingButtonPressed += (_, listing) =>
         {
             SendMessage(new StoreBuyListingMessage(listing));
@@ -75,6 +77,15 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
         }
     }
 
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+        _menu?.Close();
+        _menu?.Dispose();
+    }
+
     private void UpdateListingsWithSearchFilter()
     {
         if (_menu == null)
index 1c46b4be35c889cb08034246b7b19ad8216678ed..eea867b79484d2a63f28899e777a17713fedc03b 100644 (file)
@@ -1,3 +1,4 @@
+using Content.Client.Inventory;
 using Robust.Client.UserInterface.Controls;
 using Robust.Client.UserInterface.CustomControls;
 using Robust.Shared.Timing;
@@ -10,12 +11,14 @@ namespace Content.Client.Strip
         public LayoutContainer InventoryContainer = new();
         public BoxContainer HandsContainer = new() { Orientation = LayoutOrientation.Horizontal };
         public BoxContainer SnareContainer = new();
+        private StrippableBoundUserInterface _bui;
         public bool Dirty = true;
 
-        public event Action? OnDirty;
-
-        public StrippingMenu()
+        public StrippingMenu(string title, StrippableBoundUserInterface bui)
         {
+            Title = title;
+            _bui = bui;
+
             var box = new BoxContainer() { Orientation = LayoutOrientation.Vertical, Margin = new Thickness(0, 8) };
             Contents.AddChild(box);
             box.AddChild(SnareContainer);
@@ -36,7 +39,7 @@ namespace Content.Client.Strip
                 return;
 
             Dirty = false;
-            OnDirty?.Invoke();
+            _bui.UpdateMenu();
         }
     }
 }
index e3646c00cc3098d07ed793299140c90178167482..9132dd6ed5f82b4255044453d49ae787b69843f3 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Client.Eye;
 using Content.Shared.SurveillanceCamera;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.SurveillanceCamera.UI;
 
@@ -26,12 +25,20 @@ public sealed class SurveillanceCameraMonitorBoundUserInterface : BoundUserInter
     {
         base.Open();
 
-        _window = this.CreateWindow<SurveillanceCameraMonitorWindow>();
+        _window = new SurveillanceCameraMonitorWindow();
+
+        if (State != null)
+        {
+            UpdateState(State);
+        }
+
+        _window.OpenCentered();
 
         _window.CameraSelected += OnCameraSelected;
         _window.SubnetOpened += OnSubnetRequest;
         _window.CameraRefresh += OnCameraRefresh;
         _window.SubnetRefresh += OnSubnetRefresh;
+        _window.OnClose += Close;
         _window.CameraSwitchTimer += OnCameraSwitchTimer;
         _window.CameraDisconnect += OnCameraDisconnect;
     }
index 0631d98993ac82df24509b5e51ba4534a16cbf6c..37384daafefd109b8d19ace9798293ee6c379983 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Thief;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Thief;
 
@@ -16,9 +15,21 @@ public sealed class ThiefBackpackBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<ThiefBackpackMenu>();
-        _window.OnApprove += SendApprove;
-        _window.OnSetChange += SendChangeSelected;
+        _window = new ThiefBackpackMenu(this);
+        _window.OnClose += Close;
+        _window.OpenCentered();
+    }
+
+    protected override void Dispose(bool disposing)
+    {
+        base.Dispose(disposing);
+        if (!disposing)
+            return;
+
+        if (_window != null)
+            _window.OnClose -= Close;
+
+        _window?.Dispose();
     }
 
     protected override void UpdateState(BoundUserInterfaceState state)
index aaee35761749f8da7c9ac80a749bb8efa7ad5143..543772c704ce4d201b7a118425e86f90e25aabb9 100644 (file)
@@ -12,42 +12,46 @@ public sealed partial class ThiefBackpackMenu : FancyWindow
     [Dependency] private readonly IEntitySystemManager _sysMan = default!;
     private readonly SpriteSystem _spriteSystem;
 
-    public event Action? OnApprove;
-    public event Action<int>? OnSetChange;
+    private readonly ThiefBackpackBoundUserInterface _owner;
 
-    public ThiefBackpackMenu()
+    public ThiefBackpackMenu(ThiefBackpackBoundUserInterface owner)
     {
         RobustXamlLoader.Load(this);
         IoCManager.InjectDependencies(this);
         _spriteSystem = _sysMan.GetEntitySystem<SpriteSystem>();
 
-        ApproveButton.OnPressed += args =>
+        _owner = owner;
+
+        ApproveButton.OnButtonDown += (args) =>
         {
-            OnApprove?.Invoke();
+            _owner.SendApprove();
         };
     }
 
     public void UpdateState(ThiefBackpackBoundUserInterfaceState state)
     {
-        SetsGrid.DisposeAllChildren();
-        var selectedNumber = 0;
-        foreach (var (set, info) in state.Sets)
+        SetsGrid.RemoveAllChildren();
+        int count = 0;
+        int selectedNumber = 0;
+        foreach (var set in state.Sets)
         {
-            var child = new ThiefBackpackSet(info, _spriteSystem);
+            var child = new ThiefBackpackSet(set.Value, _spriteSystem);
 
             child.SetButton.OnButtonDown += (args) =>
             {
-                OnSetChange?.Invoke(set);
+                _owner.SendChangeSelected(set.Key);
             };
 
             SetsGrid.AddChild(child);
 
-            if (info.Selected)
+            count++;
+
+            if (set.Value.Selected)
                 selectedNumber++;
         }
 
         Description.Text = Loc.GetString("thief-backpack-window-description", ("maxCount", state.MaxSelectedSets));
         SelectedSets.Text = Loc.GetString("thief-backpack-window-selected", ("selectedCount", selectedNumber), ("maxCount", state.MaxSelectedSets));
-        ApproveButton.Disabled = selectedNumber != state.MaxSelectedSets;
+        ApproveButton.Disabled = selectedNumber == state.MaxSelectedSets ? false : true;
     }
 }
index 4ae74a5d65e5aba60df097e90d9add26b06fa162..4702f8f3659494e6950dd99949786b764d79a647 100644 (file)
@@ -1,7 +1,5 @@
 using Content.Shared.Atmos.Components;
 using JetBrains.Annotations;
-using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.UserInterface.Systems.Atmos.GasTank
 {
@@ -15,7 +13,7 @@ namespace Content.Client.UserInterface.Systems.Atmos.GasTank
         {
         }
 
-        public void SetOutputPressure(float value)
+        public void SetOutputPressure(in float value)
         {
             SendMessage(new GasTankSetPressureMessage
             {
@@ -31,10 +29,9 @@ namespace Content.Client.UserInterface.Systems.Atmos.GasTank
         protected override void Open()
         {
             base.Open();
-            _window = this.CreateWindow<GasTankWindow>();
-            _window.SetTitle(EntMan.GetComponent<MetaDataComponent>(Owner).EntityName);
-            _window.OnOutputPressure += SetOutputPressure;
-            _window.OnToggleInternals += ToggleInternals;
+            _window = new GasTankWindow(this, EntMan.GetComponent<MetaDataComponent>(Owner).EntityName);
+            _window.OnClose += Close;
+            _window.OpenCentered();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
index 12eeaa55de914ce02ec2373e0036af1056f97fd3..c23850a6503472bc8191e8ed09e8166942655212 100644 (file)
@@ -15,28 +15,23 @@ namespace Content.Client.UserInterface.Systems.Atmos.GasTank;
 public sealed class GasTankWindow
     : BaseWindow
 {
-    [Dependency] private readonly IResourceCache _cache = default!;
-
     private readonly RichTextLabel _lblPressure;
     private readonly FloatSpinBox _spbPressure;
     private readonly RichTextLabel _lblInternals;
     private readonly Button _btnInternals;
-    private readonly Label _topLabel;
-
-    public event Action<float>? OnOutputPressure;
-    public event Action? OnToggleInternals;
 
-    public GasTankWindow()
+    public GasTankWindow(GasTankBoundUserInterface owner, string uidName)
     {
         Control contentContainer;
         BoxContainer topContainer;
         TextureButton btnClose;
+        var resourceCache = IoCManager.Resolve<IResourceCache>();
         var rootContainer = new LayoutContainer { Name = "GasTankRoot" };
         AddChild(rootContainer);
 
         MouseFilter = MouseFilterMode.Stop;
 
-        var panelTex = _cache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
+        var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
         var back = new StyleBoxTexture
         {
             Texture = panelTex,
@@ -83,17 +78,7 @@ public sealed class GasTankWindow
 
         LayoutContainer.SetAnchorPreset(topContainerWrap, LayoutContainer.LayoutPreset.Wide);
 
-        var font = _cache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13);
-
-        _topLabel = new Label
-        {
-            FontOverride = font,
-            FontColorOverride = StyleNano.NanoGold,
-            VerticalAlignment = VAlignment.Center,
-            HorizontalExpand = true,
-            HorizontalAlignment = HAlignment.Left,
-            Margin = new Thickness(0, 0, 20, 0),
-        };
+        var font = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13);
 
         var topRow = new BoxContainer
         {
@@ -101,7 +86,16 @@ public sealed class GasTankWindow
             Margin = new Thickness(4, 2, 12, 2),
             Children =
             {
-                _topLabel,
+                (new Label
+                {
+                    Text = uidName,
+                    FontOverride = font,
+                    FontColorOverride = StyleNano.NanoGold,
+                    VerticalAlignment = VAlignment.Center,
+                    HorizontalExpand = true,
+                    HorizontalAlignment = HAlignment.Left,
+                    Margin = new Thickness(0, 0, 20, 0),
+                }),
                 (btnClose = new TextureButton
                 {
                     StyleClasses = {DefaultWindow.StyleClassWindowCloseButton},
@@ -174,22 +168,17 @@ public sealed class GasTankWindow
         // Handlers
         _spbPressure.OnValueChanged += args =>
         {
-            OnOutputPressure?.Invoke(args.Value);
+            owner.SetOutputPressure(args.Value);
         };
 
         _btnInternals.OnPressed += args =>
         {
-            OnToggleInternals?.Invoke();
+            owner.ToggleInternals();
         };
 
         btnClose.OnPressed += _ => Close();
     }
 
-    public void SetTitle(string name)
-    {
-        _topLabel.Text = name;
-    }
-
     public void UpdateState(GasTankBoundUserInterfaceState state)
     {
         _lblPressure.SetMarkup(Loc.GetString("gas-tank-window-tank-pressure-text", ("tankPressure", $"{state.TankPressure:0.##}")));
index eafab84ed6381b0f7605326b048f70eba200ff2a..17ddba77ffc1c413de40ba18db80d06fa148800a 100644 (file)
@@ -2,7 +2,6 @@ using Content.Client.VendingMachines.UI;
 using Content.Shared.VendingMachines;
 using Robust.Client.UserInterface.Controls;
 using System.Linq;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.VendingMachines
 {
@@ -29,14 +28,15 @@ namespace Content.Client.VendingMachines
 
             _cachedInventory = vendingMachineSys.GetAllInventory(Owner);
 
-            _menu = this.CreateWindow<VendingMachineMenu>();
-            _menu.OpenCenteredLeft();
-            _menu.Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName;
+            _menu = new VendingMachineMenu { Title = EntMan.GetComponent<MetaDataComponent>(Owner).EntityName };
 
+            _menu.OnClose += Close;
             _menu.OnItemSelected += OnItemSelected;
             _menu.OnSearchChanged += OnSearchChanged;
 
             _menu.Populate(_cachedInventory, out _cachedFilteredIndex);
+
+            _menu.OpenCenteredLeft();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
index 891804674d3c9587d7b4bab00ef611c8a72d8561..f700c6663b9aec556d391bc4f1907edc86066608 100644 (file)
@@ -1,13 +1,12 @@
 using Content.Shared.VoiceMask;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 using Robust.Shared.Prototypes;
 
 namespace Content.Client.VoiceMask;
 
 public sealed class VoiceMaskBoundUserInterface : BoundUserInterface
 {
-    [Dependency] private readonly IPrototypeManager _protomanager = default!;
+    [Dependency] private readonly IPrototypeManager _proto = default!;
 
     [ViewVariables]
     private VoiceMaskNameChangeWindow? _window;
@@ -20,11 +19,12 @@ public sealed class VoiceMaskBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<VoiceMaskNameChangeWindow>();
-        _window.ReloadVerbs(_protomanager);
+        _window = new(_proto);
 
+        _window.OpenCentered();
         _window.OnNameChange += OnNameSelected;
         _window.OnVerbChange += verb => SendMessage(new VoiceMaskChangeVerbMessage(verb));
+        _window.OnClose += Close;
     }
 
     private void OnNameSelected(string name)
index 0dc41f807ab127d0e2491f6d3d96fe92191f8584..16a28f9d9b3ee2b25cbbe9ca680e4fc04904ec91 100644 (file)
@@ -17,7 +17,7 @@ public sealed partial class VoiceMaskNameChangeWindow : FancyWindow
 
     private string? _verb;
 
-    public VoiceMaskNameChangeWindow()
+    public VoiceMaskNameChangeWindow(IPrototypeManager proto)
     {
         RobustXamlLoader.Load(this);
 
@@ -32,10 +32,12 @@ public sealed partial class VoiceMaskNameChangeWindow : FancyWindow
             SpeechVerbSelector.SelectId(args.Id);
         };
 
+        ReloadVerbs(proto);
+
         AddVerbs();
     }
 
-    public void ReloadVerbs(IPrototypeManager proto)
+    private void ReloadVerbs(IPrototypeManager proto)
     {
         foreach (var verb in proto.EnumeratePrototypes<SpeechVerbPrototype>())
         {
index 3f01808c422f61224d82463489908a94c9b7be50..f3e0c0a539ad5bfc244724a4d794a1dea1035f2d 100644 (file)
@@ -1,6 +1,5 @@
 using Robust.Client.GameObjects;
 using Content.Shared.Speech.Components;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Weapons.Melee.UI;
 
@@ -20,10 +19,17 @@ public sealed class MeleeSpeechBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _window = this.CreateWindow<MeleeSpeechWindow>();
+        _window = new MeleeSpeechWindow();
+        if (State != null)
+            UpdateState(State);
+
+        _window.OpenCentered();
+
+        _window.OnClose += Close;
         _window.OnBattlecryEntered += OnBattlecryChanged;
     }
 
+
     private void OnBattlecryChanged(string newBattlecry)
     {
         SendMessage(new MeleeSpeechBattlecryChangedMessage(newBattlecry));
index edf1a2d37704c9056ac6ec37b026c26186987256..5a8869a204ed24bc047deb1f13b78ec455b4d463 100644 (file)
@@ -1,6 +1,5 @@
 using Content.Shared.Wires;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Wires.UI
 {
@@ -16,8 +15,10 @@ namespace Content.Client.Wires.UI
         protected override void Open()
         {
             base.Open();
-            _menu = this.CreateWindow<WiresMenu>();
-            _menu.OnAction += PerformAction;
+
+            _menu = new WiresMenu(this);
+            _menu.OnClose += Close;
+            _menu.OpenCenteredLeft();
         }
 
         protected override void UpdateState(BoundUserInterfaceState state)
index eccc548297cd8c6e2252464d3b85353185e83c31..7bccc208616c2ac2b94cfffb170c003f33d12328 100644 (file)
@@ -1,3 +1,4 @@
+using System;
 using System.Numerics;
 using Content.Client.Examine;
 using Content.Client.Resources;
@@ -11,6 +12,10 @@ using Robust.Client.UserInterface.Controls;
 using Robust.Client.UserInterface.CustomControls;
 using Robust.Shared.Animations;
 using Robust.Shared.Input;
+using Robust.Shared.IoC;
+using Robust.Shared.Localization;
+using Robust.Shared.Maths;
+using Robust.Shared.Random;
 using static Robust.Client.UserInterface.Controls.BoxContainer;
 
 namespace Content.Client.Wires.UI
@@ -19,6 +24,8 @@ namespace Content.Client.Wires.UI
     {
         [Dependency] private readonly IResourceCache _resourceCache = default!;
 
+        public WiresBoundUserInterface Owner { get; }
+
         private readonly Control _wiresHBox;
         private readonly Control _topContainer;
         private readonly Control _statusContainer;
@@ -28,12 +35,11 @@ namespace Content.Client.Wires.UI
 
         public TextureButton CloseButton { get; set; }
 
-        public event Action<int, WiresAction>? OnAction;
-
-        public WiresMenu()
+        public WiresMenu(WiresBoundUserInterface owner)
         {
             IoCManager.InjectDependencies(this);
 
+            Owner = owner;
             var rootContainer = new LayoutContainer {Name = "WireRoot"};
             AddChild(rootContainer);
 
@@ -251,12 +257,12 @@ namespace Content.Client.Wires.UI
 
                 control.WireClicked += () =>
                 {
-                    OnAction?.Invoke(wire.Id, wire.IsCut ? WiresAction.Mend : WiresAction.Cut);
+                    Owner.PerformAction(wire.Id, wire.IsCut ? WiresAction.Mend : WiresAction.Cut);
                 };
 
                 control.ContactsClicked += () =>
                 {
-                    OnAction?.Invoke(wire.Id, WiresAction.Pulse);
+                    Owner.PerformAction(wire.Id, WiresAction.Pulse);
                 };
             }
 
index c7a74815b6b84ee0b2db29502c7304eeccdf334a..2538caf6eb8d22ace64bb9075b14738cc128b71d 100644 (file)
@@ -1,7 +1,6 @@
 using Content.Shared.Xenoarchaeology.Equipment;
 using JetBrains.Annotations;
 using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
 
 namespace Content.Client.Xenoarchaeology.Ui;
 
@@ -19,7 +18,10 @@ public sealed class AnalysisConsoleBoundUserInterface : BoundUserInterface
     {
         base.Open();
 
-        _consoleMenu = this.CreateWindow<AnalysisConsoleMenu>();
+        _consoleMenu = new AnalysisConsoleMenu();
+
+        _consoleMenu.OnClose += Close;
+        _consoleMenu.OpenCentered();
 
         _consoleMenu.OnServerSelectionButtonPressed += () =>
         {