]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Remove some BUI boilerplate (#28399)
authormetalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Sat, 20 Jul 2024 05:40:16 +0000 (15:40 +1000)
committerGitHub <noreply@github.com>
Sat, 20 Jul 2024 05:40:16 +0000 (15:40 +1000)
* Remove some BUI boilerplate

- The disposals overrides got removed due to the helper method handling it.
- Replace window creation with CreateWindow helper.
- Fixed some stinky code which would cause exceptions.

* More

* moar

* weh

* done

* More BUIs

* More updates

* weh

* moar

* look who it is

* weh

* merge

* weh

* fixes

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