From cb0ba66be38677d248ce11f809221230ebe89642 Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sat, 20 Jul 2024 20:42:27 -0400 Subject: [PATCH] Revert "Remove some BUI boilerplate" (#30214) Revert "Remove some BUI boilerplate (#28399)" This reverts commit cbf329a82d77eed2bb5e51666dab5d8a21fd3fff. --- .../UI/AccessOverriderBoundUserInterface.cs | 45 ++--- .../Access/UI/AccessOverriderWindow.xaml.cs | 41 +++-- .../UI/AgentIDCardBoundUserInterface.cs | 19 +- .../Access/UI/AgentIDCardWindow.xaml.cs | 10 +- .../Ame/UI/AmeControllerBoundUserInterface.cs | 16 +- Content.Client/Ame/UI/AmeWindow.xaml.cs | 19 +- .../Ui/AnomalyGeneratorBoundUserInterface.cs | 20 +- .../Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs | 8 +- Content.Client/Arcade/BlockGameMenu.cs | 45 ++--- .../Arcade/SpaceVillainArcadeMenu.cs | 45 +++-- .../Arcade/UI/BlockGameBoundUserInterface.cs | 5 +- .../SpaceVillainArcadeBoundUserInterface.cs | 16 +- .../Monitor/UI/AirAlarmBoundUserInterface.cs | 12 +- .../Atmos/Monitor/UI/AirAlarmWindow.xaml.cs | 7 +- .../Atmos/UI/GasCanisterBoundUserInterface.cs | 9 +- .../Atmos/UI/GasFilterBoundUserInterface.cs | 11 +- .../Atmos/UI/GasFilterWindow.xaml.cs | 7 +- .../Atmos/UI/GasMixerBoundUserInteface.cs | 18 +- .../UI/GasPressurePumpBoundUserInterface.cs | 17 +- .../UI/GasThermomachineBoundUserInterface.cs | 17 +- .../UI/GasVolumePumpBoundUserInterface.cs | 19 +- .../Atmos/UI/SpaceHeaterBoundUserInterface.cs | 10 +- .../Jukebox/JukeboxBoundUserInterface.cs | 21 ++- .../CryostorageBoundUserInterface.cs | 15 +- .../CargoBountyConsoleBoundUserInterface.cs | 17 +- .../CargoPalletConsoleBoundUserInterface.cs | 15 +- .../CargoShuttleConsoleBoundUserInterface.cs | 24 ++- .../Cargo/UI/CargoShuttleMenu.xaml.cs | 13 +- .../UI/ChemMasterBoundUserInterface.cs | 20 +- .../UI/ReagentDispenserBoundUserInterface.cs | 27 ++- .../UI/TransferAmountBoundUserInterface.cs | 12 +- .../UI/CloningConsoleBoundUserInterface.cs | 25 ++- .../UI/ChameleonBoundUserInterface.cs | 16 +- ...CommunicationsConsoleBoundUserInterface.cs | 72 +++++--- .../UI/CommunicationsConsoleMenu.xaml.cs | 79 ++++---- .../Computer/ComputerBoundUserInterface.cs | 15 +- .../UI/ConfigurationBoundUserInterface.cs | 28 ++- .../Configurable/UI/ConfigurationMenu.cs | 18 +- .../UI/FlatpackCreatorBoundUserInterface.cs | 14 +- .../UI/FlatpackCreatorMenu.xaml.cs | 13 +- .../Crayon/UI/CrayonBoundUserInterface.cs | 40 ++-- Content.Client/Crayon/UI/CrayonWindow.xaml.cs | 18 +- .../UI/DisposalRouterBoundUserInterface.cs | 22 ++- .../UI/DisposalTaggerBoundUserInterface.cs | 23 ++- .../DoorElectronicsBoundUserInterface.cs | 31 ++-- .../DoorElectronicsConfigurationMenu.xaml.cs | 21 +-- Content.Client/Fax/UI/FaxBoundUi.cs | 12 +- .../ForensicScannerBoundUserInterface.cs | 15 +- .../Gateway/UI/GatewayBoundUserInterface.cs | 16 +- .../Gateway/UI/GatewayWindow.xaml.cs | 10 +- .../UI/GravityGeneratorBoundUserInterface.cs | 23 ++- .../Gravity/UI/GravityGeneratorWindow.xaml.cs | 15 +- .../UI/HealthAnalyzerBoundUserInterface.cs | 23 ++- ...manoidMarkingModifierBoundUserInterface.cs | 4 +- .../Instruments/UI/BandMenu.xaml.cs | 6 +- .../Instruments/UI/ChannelsMenu.xaml.cs | 5 +- .../UI/InstrumentBoundUserInterface.cs | 36 +--- .../Instruments/UI/InstrumentMenu.xaml.cs | 171 ++++++++---------- .../Inventory/StrippableBoundUserInterface.cs | 25 +-- Content.Client/Kitchen/UI/GrinderMenu.xaml.cs | 42 +++-- .../Kitchen/UI/MicrowaveBoundUserInterface.cs | 47 ++++- .../Kitchen/UI/MicrowaveMenu.xaml.cs | 24 +-- .../UI/ReagentGrinderBoundUserInterface.cs | 34 ++-- .../UI/HandLabelerBoundUserInterface.cs | 16 +- .../Lathe/UI/LatheBoundUserInterface.cs | 17 +- Content.Client/Lathe/UI/LatheMenu.xaml.cs | 29 ++- .../UI/SignalTimerBoundUserInterface.cs | 24 ++- .../UI/SignalTimerWindow.xaml.cs | 24 ++- .../MagicMirrorBoundUserInterface.cs | 15 +- .../Ui/NewsWriterBoundUserInterface.cs | 18 +- .../MassMedia/Ui/NewsWriterMenu.xaml.cs | 6 +- .../Mech/Ui/MechBoundUserInterface.cs | 16 +- Content.Client/Mech/Ui/MechMenu.xaml.cs | 9 +- .../CrewMonitoringBoundUserInterface.cs | 18 +- .../CrewMonitoringWindow.xaml.cs | 17 +- .../NetworkConfiguratorBoundUserInterface.cs | 39 ++-- ...tworkConfiguratorConfigurationMenu.xaml.cs | 8 +- .../NetworkConfiguratorDeviceList.xaml.cs | 12 +- .../NetworkConfiguratorLinkMenu.xaml.cs | 16 +- .../NetworkConfiguratorListMenu.xaml.cs | 13 +- Content.Client/Nuke/NukeBoundUserInterface.cs | 17 +- .../WarDeclaratorBoundUserInterface.cs | 18 +- .../NukeOps/WarDeclaratorWindow.xaml.cs | 9 +- Content.Client/PDA/PdaBoundUserInterface.cs | 17 +- .../PDA/Ringer/RingerBoundUserInterface.cs | 4 +- .../Paper/UI/PaperBoundUserInterface.cs | 17 +- Content.Client/Paper/UI/PaperWindow.xaml.cs | 6 +- .../ParticleAcceleratorBoundUserInterface.cs | 16 +- .../UI/ParticleAcceleratorControlMenu.cs | 30 ++- .../UI/NavMapBeaconBoundUserInterface.cs | 16 +- .../Pinpointer/UI/NavMapBeaconWindow.xaml.cs | 25 +-- .../UI/StationMapBoundUserInterface.cs | 15 +- .../Pinpointer/UI/StationMapWindow.xaml.cs | 11 +- .../UI/UntrackedMapBoundUserInterface.cs | 15 +- .../Power/APC/ApcBoundUserInterface.cs | 16 +- Content.Client/Power/APC/UI/ApcMenu.xaml.cs | 12 +- .../Power/Generator/GeneratorWindow.xaml.cs | 52 +++--- .../PortableGeneratorBoundUserInterface.cs | 25 +-- ...owerMonitoringConsoleBoundUserInterface.cs | 19 +- .../PowerMonitoringWindow.xaml.Widgets.cs | 6 +- .../Power/PowerMonitoringWindow.xaml.cs | 86 ++++----- Content.Client/RCD/RCDMenu.xaml.cs | 35 ++-- .../RCD/RCDMenuBoundUserInterface.cs | 16 +- .../Radio/Ui/IntercomBoundUserInterface.cs | 20 +- Content.Client/Radio/Ui/IntercomMenu.xaml.cs | 4 +- .../UI/DiskConsoleBoundUserInterface.cs | 15 +- .../UI/ResearchClientBoundUserInterface.cs | 16 +- .../ResearchClientServerSelectionMenu.xaml.cs | 11 +- .../UI/ResearchConsoleBoundUserInterface.cs | 28 ++- .../Research/UI/ResearchConsoleMenu.xaml.cs | 31 ++-- .../UI/RoboticsConsoleBoundUserInterface.cs | 18 +- .../Robotics/UI/RoboticsConsoleWindow.xaml.cs | 25 +-- ...vageExpeditionConsoleBoundUserInterface.cs | 12 +- .../UI/SalvageMagnetBoundUserInterface.cs | 21 ++- .../BUI/IFFConsoleBoundUserInterface.cs | 4 +- .../BUI/RadarConsoleBoundUserInterface.cs | 14 +- .../BUI/ShuttleConsoleBoundUserInterface.cs | 5 +- .../Silicons/Borgs/BorgBoundUserInterface.cs | 18 +- Content.Client/Silicons/Borgs/BorgMenu.xaml | 2 +- .../Silicons/Borgs/BorgMenu.xaml.cs | 51 +++--- .../Laws/Ui/SiliconLawBoundUserInterface.cs | 14 +- .../UI/SprayPainterBoundUserInterface.cs | 27 ++- ...lStationRecordConsoleBoundUserInterface.cs | 13 +- .../Store/Ui/StoreBoundUserInterface.cs | 15 +- Content.Client/Strip/StrippingMenu.cs | 11 +- .../UI/SurveillanceCameraMonitorBoundUi.cs | 11 +- .../Thief/ThiefBackpackBoundUserInterface.cs | 19 +- .../Thief/ThiefBackpackMenu.xaml.cs | 28 +-- .../GasTank/GasTankBoundUserInterface.cs | 11 +- .../Systems/Atmos/GasTank/GasTankWindow.cs | 43 ++--- .../VendingMachineBoundUserInterface.cs | 8 +- .../VoiceMask/VoiceMaskBoundUserInterface.cs | 8 +- .../VoiceMaskNameChangeWindow.xaml.cs | 6 +- .../Melee/UI/MeleeSpeechBoundUserInterface.cs | 10 +- .../Wires/UI/WiresBoundUserInterface.cs | 7 +- Content.Client/Wires/UI/WiresMenu.cs | 16 +- .../Ui/AnalysisConsoleBoundUserInterface.cs | 6 +- 137 files changed, 1755 insertions(+), 1096 deletions(-) diff --git a/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs b/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs index d80c600c03..c1b63dc4d0 100644 --- a/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs +++ b/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Access; using Content.Shared.Access.Components; using Content.Shared.Access.Systems; using Content.Shared.Containers.ItemSlots; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; using static Content.Shared.Access.Components.AccessOverriderComponent; @@ -24,28 +23,6 @@ namespace Content.Client.Access.UI { base.Open(); - _window = this.CreateWindow(); - RefreshAccess(); - _window.Title = EntMan.GetComponent(Owner).EntityName; - _window.OnSubmit += SubmitData; - - _window.PrivilegedIdButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(PrivilegedIdCardSlotId)); - } - - public override void OnProtoReload(PrototypesReloadedEventArgs args) - { - base.OnProtoReload(args); - if (!args.WasModified()) - return; - - RefreshAccess(); - - if (State != null) - _window?.UpdateState(_prototypeManager, (AccessOverriderBoundUserInterfaceState) State); - } - - private void RefreshAccess() - { List> accessLevels; if (EntMan.TryGetComponent(Owner, out var accessOverrider)) @@ -53,20 +30,38 @@ namespace Content.Client.Access.UI accessLevels = accessOverrider.AccessLevels; accessLevels.Sort(); } + else { accessLevels = new List>(); _accessOverriderSystem.Log.Error($"No AccessOverrider component found for {EntMan.ToPrettyString(Owner)}!"); } - _window?.SetAccessLevels(_prototypeManager, accessLevels); + _window = new AccessOverriderWindow(this, _prototypeManager, accessLevels) + { + Title = EntMan.GetComponent(Owner).EntityName + }; + + _window.PrivilegedIdButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(PrivilegedIdCardSlotId)); + + _window.OnClose += Close; + _window.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _window?.Dispose(); } protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); var castState = (AccessOverriderBoundUserInterfaceState) state; - _window?.UpdateState(_prototypeManager, castState); + _window?.UpdateState(castState); } public void SubmitData(List> newAccessList) diff --git a/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs b/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs index ba08771858..6025c3b551 100644 --- a/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs +++ b/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs @@ -13,24 +13,26 @@ 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 _accessButtons = new(); - public event Action>>? OnSubmit; - - public AccessOverriderWindow() + public AccessOverriderWindow(AccessOverriderBoundUserInterface owner, IPrototypeManager prototypeManager, + List> accessLevels) { RobustXamlLoader.Load(this); - } + IoCManager.InjectDependencies(this); + var logMill = _logManager.GetSawmill(SharedAccessOverriderSystem.Sawmill); - public void SetAccessLevels(IPrototypeManager protoManager, List> accessLevels) - { - _accessButtons.Clear(); - AccessLevelGrid.DisposeAllChildren(); + _owner = owner; foreach (var access in accessLevels) { - if (!protoManager.TryIndex(access, out var accessLevel)) + if (!prototypeManager.TryIndex(access, out var accessLevel)) { + logMill.Error($"Unable to find accesslevel for {access}"); continue; } @@ -42,16 +44,11 @@ namespace Content.Client.Access.UI AccessLevelGrid.AddChild(newButton); _accessButtons.Add(accessLevel.ID, newButton); - newButton.OnPressed += _ => - { - OnSubmit?.Invoke( - // Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair - _accessButtons.Where(x => x.Value.Pressed).Select(x => new ProtoId(x.Key)).ToList()); - }; + newButton.OnPressed += _ => SubmitData(); } } - public void UpdateState(IPrototypeManager protoManager, AccessOverriderBoundUserInterfaceState state) + public void UpdateState(AccessOverriderBoundUserInterfaceState state) { PrivilegedIdLabel.Text = state.PrivilegedIdName; PrivilegedIdButton.Text = state.IsPrivilegedIdPresent @@ -69,11 +66,11 @@ namespace Content.Client.Access.UI if (state.MissingPrivilegesList != null && state.MissingPrivilegesList.Any()) { - var missingPrivileges = new List(); + List missingPrivileges = new List(); foreach (string tag in state.MissingPrivilegesList) { - var privilege = Loc.GetString(protoManager.Index(tag)?.Name ?? "generic-unknown"); + string privilege = Loc.GetString(_prototypeManager.Index(tag)?.Name ?? "generic-unknown"); missingPrivileges.Add(privilege); } @@ -93,5 +90,13 @@ namespace Content.Client.Access.UI } } } + + private void SubmitData() + { + _owner.SubmitData( + + // Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair + _accessButtons.Where(x => x.Value.Pressed).Select(x => new ProtoId(x.Key)).ToList()); + } } } diff --git a/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs b/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs index 50add43dc9..761f52988a 100644 --- a/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs +++ b/Content.Client/Access/UI/AgentIDCardBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Access.Systems; using Content.Shared.StatusIcon; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client.Access.UI @@ -21,11 +20,16 @@ namespace Content.Client.Access.UI { base.Open(); - _window = this.CreateWindow(); + _window?.Dispose(); + _window = new AgentIDCardWindow(this); + if (State != null) + UpdateState(State); + _window.OpenCentered(); + + _window.OnClose += Close; _window.OnNameChanged += OnNameChanged; _window.OnJobChanged += OnJobChanged; - _window.OnJobIconChanged += OnJobIconChanged; } private void OnNameChanged(string newName) @@ -57,5 +61,14 @@ namespace Content.Client.Access.UI _window.SetCurrentJob(cast.CurrentJob); _window.SetAllowedIcons(cast.Icons, cast.CurrentJobIconId); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _window?.Dispose(); + } } } diff --git a/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs b/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs index 071ce41a06..6d0b2a184f 100644 --- a/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs +++ b/Content.Client/Access/UI/AgentIDCardWindow.xaml.cs @@ -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? OnNameChanged; public event Action? OnJobChanged; - public event Action>? OnJobIconChanged; - - public AgentIDCardWindow() + public AgentIDCardWindow(AgentIDCardBoundUserInterface bui) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _spriteSystem = _entitySystem.GetEntitySystem(); + _bui = bui; NameLineEdit.OnTextEntered += e => OnNameChanged?.Invoke(e.Text); NameLineEdit.OnFocusExit += e => OnNameChanged?.Invoke(e.Text); @@ -67,7 +67,7 @@ namespace Content.Client.Access.UI }; // Generate buttons textures - var jobIconTexture = new TextureRect + TextureRect jobIconTexture = new TextureRect { Texture = _spriteSystem.Frame0(jobIcon.Icon), TextureScale = new Vector2(2.5f, 2.5f), @@ -75,7 +75,7 @@ namespace Content.Client.Access.UI }; jobIconButton.AddChild(jobIconTexture); - jobIconButton.OnPressed += _ => OnJobIconChanged?.Invoke(jobIcon.ID); + jobIconButton.OnPressed += _ => _bui.OnJobIconChanged(jobIconId); IconGrid.AddChild(jobIconButton); if (jobIconId.Equals(currentJobIconId)) diff --git a/Content.Client/Ame/UI/AmeControllerBoundUserInterface.cs b/Content.Client/Ame/UI/AmeControllerBoundUserInterface.cs index 3d65f75189..e84cf5d34d 100644 --- a/Content.Client/Ame/UI/AmeControllerBoundUserInterface.cs +++ b/Content.Client/Ame/UI/AmeControllerBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Ame.Components; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Ame.UI { @@ -17,8 +16,9 @@ namespace Content.Client.Ame.UI { base.Open(); - _window = this.CreateWindow(); - _window.OnAmeButton += ButtonPressed; + _window = new AmeWindow(this); + _window.OnClose += Close; + _window.OpenCentered(); } /// @@ -40,5 +40,15 @@ namespace Content.Client.Ame.UI { SendMessage(new UiButtonPressedMessage(button)); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } } } diff --git a/Content.Client/Ame/UI/AmeWindow.xaml.cs b/Content.Client/Ame/UI/AmeWindow.xaml.cs index d6d580bcda..8b91ec5966 100644 --- a/Content.Client/Ame/UI/AmeWindow.xaml.cs +++ b/Content.Client/Ame/UI/AmeWindow.xaml.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Client.UserInterface; using Content.Shared.Ame.Components; using Robust.Client.AutoGenerated; @@ -10,17 +9,15 @@ namespace Content.Client.Ame.UI [GenerateTypedNameReferences] public sealed partial class AmeWindow : DefaultWindow { - public event Action? OnAmeButton; - - public AmeWindow() + public AmeWindow(AmeControllerBoundUserInterface ui) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); - EjectButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.Eject); - ToggleInjection.OnPressed += _ => OnAmeButton?.Invoke(UiButton.ToggleInjection); - IncreaseFuelButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.IncreaseFuel); - DecreaseFuelButton.OnPressed += _ => OnAmeButton?.Invoke(UiButton.DecreaseFuel); + EjectButton.OnPressed += _ => ui.ButtonPressed(UiButton.Eject); + ToggleInjection.OnPressed += _ => ui.ButtonPressed(UiButton.ToggleInjection); + IncreaseFuelButton.OnPressed += _ => ui.ButtonPressed(UiButton.IncreaseFuel); + DecreaseFuelButton.OnPressed += _ => ui.ButtonPressed(UiButton.DecreaseFuel); } /// @@ -32,7 +29,7 @@ namespace Content.Client.Ame.UI var castState = (AmeControllerBoundUserInterfaceState) state; // Disable all buttons if not powered - if (Contents.Children.Any()) + if (Contents.Children != null) { ButtonHelpers.SetButtonDisabledRecursive(Contents, !castState.HasPower); EjectButton.Disabled = false; @@ -68,8 +65,8 @@ namespace Content.Client.Ame.UI CoreCount.Text = $"{castState.CoreCount}"; InjectionAmount.Text = $"{castState.InjectionAmount}"; // format power statistics to pretty numbers - CurrentPowerSupply.Text = $"{castState.CurrentPowerSupply:N1}"; - TargetedPowerSupply.Text = $"{castState.TargetedPowerSupply:N1}"; + CurrentPowerSupply.Text = $"{castState.CurrentPowerSupply.ToString("N1")}"; + TargetedPowerSupply.Text = $"{castState.TargetedPowerSupply.ToString("N1")}"; } } } diff --git a/Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs b/Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs index 5d1985485c..5764d0a097 100644 --- a/Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs +++ b/Content.Client/Anomaly/Ui/AnomalyGeneratorBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Anomaly; using Content.Shared.Gravity; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Anomaly.Ui; @@ -19,8 +18,10 @@ public sealed class AnomalyGeneratorBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.SetEntity(Owner); + _window = new(Owner); + + _window.OpenCentered(); + _window.OnClose += Close; _window.OnGenerateButtonPressed += () => { @@ -36,5 +37,18 @@ public sealed class AnomalyGeneratorBoundUserInterface : BoundUserInterface return; _window?.UpdateState(msg); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _window?.Dispose(); + } + + public void SetPowerSwitch(bool on) + { + SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(on)); + } } diff --git a/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs index 82d41192dd..08438e2a1b 100644 --- a/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs +++ b/Content.Client/Anomaly/Ui/AnomalyGeneratorWindow.xaml.cs @@ -18,21 +18,17 @@ public sealed partial class AnomalyGeneratorWindow : FancyWindow public Action? OnGenerateButtonPressed; - public AnomalyGeneratorWindow() + public AnomalyGeneratorWindow(EntityUid gen) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + EntityView.SetEntity(gen); EntityView.SpriteOffset = false; GenerateButton.OnPressed += _ => OnGenerateButtonPressed?.Invoke(); } - public void SetEntity(EntityUid uid) - { - EntityView.SetEntity(uid); - } - public void UpdateState(AnomalyGeneratorUserInterfaceState state) { _cooldownEnd = state.CooldownEndTime; diff --git a/Content.Client/Arcade/BlockGameMenu.cs b/Content.Client/Arcade/BlockGameMenu.cs index 4a579fc4bf..eeda2a3102 100644 --- a/Content.Client/Arcade/BlockGameMenu.cs +++ b/Content.Client/Arcade/BlockGameMenu.cs @@ -28,6 +28,8 @@ namespace Content.Client.Arcade private static readonly Vector2 BlockSize = new(15, 15); + private readonly BlockGameBoundUserInterface _owner; + private readonly PanelContainer _mainPanel; private readonly BoxContainer _gameRootContainer; @@ -56,11 +58,10 @@ namespace Content.Client.Arcade private bool _isPlayer = false; private bool _gameOver = false; - public event Action? OnAction; - - public BlockGameMenu() + public BlockGameMenu(BlockGameBoundUserInterface owner) { Title = Loc.GetString("blockgame-menu-title"); + _owner = owner; MinSize = SetSize = new Vector2(410, 490); @@ -175,7 +176,7 @@ namespace Content.Client.Arcade }; _newGameButton.OnPressed += (e) => { - OnAction?.Invoke(BlockGamePlayerAction.NewGame); + _owner.SendAction(BlockGamePlayerAction.NewGame); }; pauseMenuContainer.AddChild(_newGameButton); pauseMenuContainer.AddChild(new Control { MinSize = new Vector2(1, 10) }); @@ -185,10 +186,7 @@ namespace Content.Client.Arcade Text = Loc.GetString("blockgame-menu-button-scoreboard"), TextAlign = Label.AlignMode.Center }; - _scoreBoardButton.OnPressed += (e) => - { - OnAction?.Invoke(BlockGamePlayerAction.ShowHighscores); - }; + _scoreBoardButton.OnPressed += (e) => _owner.SendAction(BlockGamePlayerAction.ShowHighscores); pauseMenuContainer.AddChild(_scoreBoardButton); _unpauseButtonMargin = new Control { MinSize = new Vector2(1, 10), Visible = false }; pauseMenuContainer.AddChild(_unpauseButtonMargin); @@ -201,7 +199,7 @@ namespace Content.Client.Arcade }; _unpauseButton.OnPressed += (e) => { - OnAction?.Invoke(BlockGamePlayerAction.Unpause); + _owner.SendAction(BlockGamePlayerAction.Unpause); }; pauseMenuContainer.AddChild(_unpauseButton); @@ -259,7 +257,7 @@ namespace Content.Client.Arcade }; _finalNewGameButton.OnPressed += (e) => { - OnAction?.Invoke(BlockGamePlayerAction.NewGame); + _owner.SendAction(BlockGamePlayerAction.NewGame); }; gameOverMenuContainer.AddChild(_finalNewGameButton); @@ -329,10 +327,7 @@ namespace Content.Client.Arcade Text = Loc.GetString("blockgame-menu-button-back"), TextAlign = Label.AlignMode.Center }; - _highscoreBackButton.OnPressed += (e) => - { - OnAction?.Invoke(BlockGamePlayerAction.Pause); - }; + _highscoreBackButton.OnPressed += (e) => _owner.SendAction(BlockGamePlayerAction.Pause); menuContainer.AddChild(_highscoreBackButton); menuInnerPanel.AddChild(menuContainer); @@ -478,7 +473,7 @@ namespace Content.Client.Arcade private void TryPause() { - OnAction?.Invoke(BlockGamePlayerAction.Pause); + _owner.SendAction(BlockGamePlayerAction.Pause); } public void SetStarted() @@ -581,19 +576,19 @@ namespace Content.Client.Arcade return; else if (args.Function == ContentKeyFunctions.ArcadeLeft) - OnAction?.Invoke(BlockGamePlayerAction.StartLeft); + _owner.SendAction(BlockGamePlayerAction.StartLeft); else if (args.Function == ContentKeyFunctions.ArcadeRight) - OnAction?.Invoke(BlockGamePlayerAction.StartRight); + _owner.SendAction(BlockGamePlayerAction.StartRight); else if (args.Function == ContentKeyFunctions.ArcadeUp) - OnAction?.Invoke(BlockGamePlayerAction.Rotate); + _owner.SendAction(BlockGamePlayerAction.Rotate); else if (args.Function == ContentKeyFunctions.Arcade3) - OnAction?.Invoke(BlockGamePlayerAction.CounterRotate); + _owner.SendAction(BlockGamePlayerAction.CounterRotate); else if (args.Function == ContentKeyFunctions.ArcadeDown) - OnAction?.Invoke(BlockGamePlayerAction.SoftdropStart); + _owner.SendAction(BlockGamePlayerAction.SoftdropStart); else if (args.Function == ContentKeyFunctions.Arcade2) - OnAction?.Invoke(BlockGamePlayerAction.Hold); + _owner.SendAction(BlockGamePlayerAction.Hold); else if (args.Function == ContentKeyFunctions.Arcade1) - OnAction?.Invoke(BlockGamePlayerAction.Harddrop); + _owner.SendAction(BlockGamePlayerAction.Harddrop); } protected override void KeyBindUp(GUIBoundKeyEventArgs args) @@ -604,11 +599,11 @@ namespace Content.Client.Arcade return; else if (args.Function == ContentKeyFunctions.ArcadeLeft) - OnAction?.Invoke(BlockGamePlayerAction.EndLeft); + _owner.SendAction(BlockGamePlayerAction.EndLeft); else if (args.Function == ContentKeyFunctions.ArcadeRight) - OnAction?.Invoke(BlockGamePlayerAction.EndRight); + _owner.SendAction(BlockGamePlayerAction.EndRight); else if (args.Function == ContentKeyFunctions.ArcadeDown) - OnAction?.Invoke(BlockGamePlayerAction.SoftdropEnd); + _owner.SendAction(BlockGamePlayerAction.SoftdropEnd); } public void UpdateNextBlock(BlockGameBlock[] blocks) diff --git a/Content.Client/Arcade/SpaceVillainArcadeMenu.cs b/Content.Client/Arcade/SpaceVillainArcadeMenu.cs index 1ee4c26818..e5542a5848 100644 --- a/Content.Client/Arcade/SpaceVillainArcadeMenu.cs +++ b/Content.Client/Arcade/SpaceVillainArcadeMenu.cs @@ -8,6 +8,8 @@ namespace Content.Client.Arcade { public sealed class SpaceVillainArcadeMenu : DefaultWindow { + public SpaceVillainArcadeBoundUserInterface Owner { get; set; } + private readonly Label _enemyNameLabel; private readonly Label _playerInfoLabel; private readonly Label _enemyInfoLabel; @@ -15,13 +17,11 @@ namespace Content.Client.Arcade private readonly Label _enemyActionLabel; private readonly Button[] _gameButtons = new Button[3]; //used to disable/enable all game buttons - - public event Action? OnPlayerAction; - - public SpaceVillainArcadeMenu() + public SpaceVillainArcadeMenu(SpaceVillainArcadeBoundUserInterface owner) { MinSize = SetSize = new Vector2(300, 225); Title = Loc.GetString("spacevillain-menu-title"); + Owner = owner; var grid = new GridContainer { Columns = 1 }; @@ -47,43 +47,32 @@ namespace Content.Client.Arcade grid.AddChild(_enemyActionLabel); var buttonGrid = new GridContainer { Columns = 3 }; - _gameButtons[0] = new Button() + _gameButtons[0] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Attack) { Text = Loc.GetString("spacevillain-menu-button-attack") }; - - _gameButtons[0].OnPressed += - _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Attack); buttonGrid.AddChild(_gameButtons[0]); - _gameButtons[1] = new Button() + _gameButtons[1] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Heal) { Text = Loc.GetString("spacevillain-menu-button-heal") }; - - _gameButtons[1].OnPressed += - _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Heal); buttonGrid.AddChild(_gameButtons[1]); - _gameButtons[2] = new Button() + _gameButtons[2] = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.Recharge) { Text = Loc.GetString("spacevillain-menu-button-recharge") }; - - _gameButtons[2].OnPressed += - _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.Recharge); buttonGrid.AddChild(_gameButtons[2]); centerContainer = new CenterContainer(); centerContainer.AddChild(buttonGrid); grid.AddChild(centerContainer); - var newGame = new Button() + var newGame = new ActionButton(Owner, SharedSpaceVillainArcadeComponent.PlayerAction.NewGame) { Text = Loc.GetString("spacevillain-menu-button-new-game") }; - - newGame.OnPressed += _ => OnPlayerAction?.Invoke(SharedSpaceVillainArcadeComponent.PlayerAction.NewGame); grid.AddChild(newGame); Contents.AddChild(grid); @@ -110,5 +99,23 @@ namespace Content.Client.Arcade _playerActionLabel.Text = message.PlayerActionMessage; _enemyActionLabel.Text = message.EnemyActionMessage; } + + private sealed class ActionButton : Button + { + private readonly SpaceVillainArcadeBoundUserInterface _owner; + private readonly SharedSpaceVillainArcadeComponent.PlayerAction _playerAction; + + public ActionButton(SpaceVillainArcadeBoundUserInterface owner, SharedSpaceVillainArcadeComponent.PlayerAction playerAction) + { + _owner = owner; + _playerAction = playerAction; + OnPressed += Clicked; + } + + private void Clicked(ButtonEventArgs e) + { + _owner.SendAction(_playerAction); + } + } } } diff --git a/Content.Client/Arcade/UI/BlockGameBoundUserInterface.cs b/Content.Client/Arcade/UI/BlockGameBoundUserInterface.cs index 8fa8035afd..1a3422dec0 100644 --- a/Content.Client/Arcade/UI/BlockGameBoundUserInterface.cs +++ b/Content.Client/Arcade/UI/BlockGameBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Arcade; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Arcade.UI; @@ -16,7 +15,9 @@ public sealed class BlockGameBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new BlockGameMenu(this); + _menu.OnClose += Close; + _menu.OpenCentered(); } protected override void ReceiveMessage(BoundUserInterfaceMessage message) diff --git a/Content.Client/Arcade/UI/SpaceVillainArcadeBoundUserInterface.cs b/Content.Client/Arcade/UI/SpaceVillainArcadeBoundUserInterface.cs index c0704530de..40bbe8b2d8 100644 --- a/Content.Client/Arcade/UI/SpaceVillainArcadeBoundUserInterface.cs +++ b/Content.Client/Arcade/UI/SpaceVillainArcadeBoundUserInterface.cs @@ -1,5 +1,4 @@ using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.GameObjects; using Robust.Shared.ViewVariables; using static Content.Shared.Arcade.SharedSpaceVillainArcadeComponent; @@ -10,6 +9,8 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface { [ViewVariables] private SpaceVillainArcadeMenu? _menu; + //public SharedSpaceVillainArcadeComponent SpaceVillainArcade; + public SpaceVillainArcadeBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { SendAction(PlayerAction.RequestData); @@ -24,7 +25,10 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new SpaceVillainArcadeMenu(this); + + _menu.OnClose += Close; + _menu.OpenCentered(); } protected override void ReceiveMessage(BoundUserInterfaceMessage message) @@ -32,4 +36,12 @@ public sealed class SpaceVillainArcadeBoundUserInterface : BoundUserInterface if (message is SpaceVillainArcadeDataUpdateMessage msg) _menu?.UpdateInfo(msg); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + _menu?.Dispose(); + } } diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs index 2ae1518835..8f3b507c80 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Atmos; using Content.Shared.Atmos.Monitor; using Content.Shared.Atmos.Monitor.Components; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Log; @@ -21,9 +20,16 @@ public sealed class AirAlarmBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.SetEntity(Owner); + _window = new AirAlarmWindow(this); + if (State != null) + { + UpdateState(State); + } + + _window.OpenCentered(); + + _window.OnClose += Close; _window.AtmosDeviceDataChanged += OnDeviceDataChanged; _window.AtmosDeviceDataCopied += OnDeviceDataCopied; _window.AtmosAlarmThresholdChanged += OnThresholdChanged; diff --git a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs index eeec11c766..43be67c9d6 100644 --- a/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs +++ b/Content.Client/Atmos/Monitor/UI/AirAlarmWindow.xaml.cs @@ -47,7 +47,7 @@ public sealed partial class AirAlarmWindow : FancyWindow private CheckBox _autoMode => AutoModeCheckBox; - public AirAlarmWindow() + public AirAlarmWindow(BoundUserInterface owner) { RobustXamlLoader.Load(this); @@ -95,11 +95,8 @@ public sealed partial class AirAlarmWindow : FancyWindow _sensors.Clear(); ResyncAllRequested!.Invoke(); }; - } - public void SetEntity(EntityUid uid) - { - EntityView.SetEntity(uid); + EntityView.SetEntity(owner.Owner); } public void UpdateState(AirAlarmUIState state) diff --git a/Content.Client/Atmos/UI/GasCanisterBoundUserInterface.cs b/Content.Client/Atmos/UI/GasCanisterBoundUserInterface.cs index 7bf9b396d5..a5e316a8de 100644 --- a/Content.Client/Atmos/UI/GasCanisterBoundUserInterface.cs +++ b/Content.Client/Atmos/UI/GasCanisterBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Atmos.Piping.Binary.Components; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Atmos.UI { @@ -22,8 +21,14 @@ namespace Content.Client.Atmos.UI { base.Open(); - _window = this.CreateWindow(); + _window = new GasCanisterWindow(); + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.ReleaseValveCloseButtonPressed += OnReleaseValveClosePressed; _window.ReleaseValveOpenButtonPressed += OnReleaseValveOpenPressed; _window.ReleasePressureSet += OnReleasePressureSet; diff --git a/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs b/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs index 2b8020924c..1904e2b340 100644 --- a/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs +++ b/Content.Client/Atmos/UI/GasFilterBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.Atmos; using Content.Shared.Atmos.Piping.Trinary.Components; using Content.Shared.Localizations; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Atmos.UI { @@ -29,8 +28,14 @@ namespace Content.Client.Atmos.UI var atmosSystem = EntMan.System(); - _window = this.CreateWindow(); - _window.PopulateGasList(atmosSystem.Gases); + _window = new GasFilterWindow(atmosSystem.Gases); + + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed; _window.FilterTransferRateChanged += OnFilterTransferRatePressed; diff --git a/Content.Client/Atmos/UI/GasFilterWindow.xaml.cs b/Content.Client/Atmos/UI/GasFilterWindow.xaml.cs index 62748b5259..28766c688a 100644 --- a/Content.Client/Atmos/UI/GasFilterWindow.xaml.cs +++ b/Content.Client/Atmos/UI/GasFilterWindow.xaml.cs @@ -26,9 +26,10 @@ namespace Content.Client.Atmos.UI public event Action? FilterTransferRateChanged; public event Action? SelectGasPressed; - public GasFilterWindow() + public GasFilterWindow(IEnumerable gases) { RobustXamlLoader.Load(this); + PopulateGasList(gases); ToggleStatusButton.OnPressed += _ => SetFilterStatus(!FilterStatus); ToggleStatusButton.OnPressed += _ => ToggleStatusButtonPressed?.Invoke(); @@ -72,7 +73,7 @@ namespace Content.Client.Atmos.UI SelectGasButton.Disabled = true; } - public void PopulateGasList(IEnumerable gases) + private void PopulateGasList(IEnumerable gases) { GasList.Add(new ItemList.Item(GasList) { @@ -80,7 +81,7 @@ namespace Content.Client.Atmos.UI Text = Loc.GetString("comp-gas-filter-ui-filter-gas-none") }); - foreach (var gas in gases) + foreach (GasPrototype gas in gases) { var gasName = Loc.GetString(gas.Name); GasList.Add(GetGasItem(gas.ID, gasName, GasList)); diff --git a/Content.Client/Atmos/UI/GasMixerBoundUserInteface.cs b/Content.Client/Atmos/UI/GasMixerBoundUserInteface.cs index 392fbf1cd9..709c06517c 100644 --- a/Content.Client/Atmos/UI/GasMixerBoundUserInteface.cs +++ b/Content.Client/Atmos/UI/GasMixerBoundUserInteface.cs @@ -2,7 +2,7 @@ using Content.Shared.Atmos; using Content.Shared.Atmos.Piping.Trinary.Components; using Content.Shared.Localizations; using JetBrains.Annotations; -using Robust.Client.UserInterface; +using Robust.Client.GameObjects; namespace Content.Client.Atmos.UI { @@ -26,7 +26,14 @@ namespace Content.Client.Atmos.UI { base.Open(); - _window = this.CreateWindow(); + _window = new GasMixerWindow(); + + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed; _window.MixerOutputPressureChanged += OnMixerOutputPressurePressed; @@ -76,5 +83,12 @@ namespace Content.Client.Atmos.UI _window.SetOutputPressure(cast.OutputPressure); _window.SetNodePercentages(cast.NodeOne); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); + } } } diff --git a/Content.Client/Atmos/UI/GasPressurePumpBoundUserInterface.cs b/Content.Client/Atmos/UI/GasPressurePumpBoundUserInterface.cs index 220fdbe875..6eba2e0d21 100644 --- a/Content.Client/Atmos/UI/GasPressurePumpBoundUserInterface.cs +++ b/Content.Client/Atmos/UI/GasPressurePumpBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.Atmos.Piping.Binary.Components; using Content.Shared.Localizations; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Atmos.UI { @@ -27,7 +26,14 @@ namespace Content.Client.Atmos.UI { base.Open(); - _window = this.CreateWindow(); + _window = new GasPressurePumpWindow(); + + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed; _window.PumpOutputPressureChanged += OnPumpOutputPressurePressed; @@ -61,5 +67,12 @@ namespace Content.Client.Atmos.UI _window.SetPumpStatus(cast.Enabled); _window.SetOutputPressure(cast.OutputPressure); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); + } } } diff --git a/Content.Client/Atmos/UI/GasThermomachineBoundUserInterface.cs b/Content.Client/Atmos/UI/GasThermomachineBoundUserInterface.cs index d62be8f4bb..1664c8b9d7 100644 --- a/Content.Client/Atmos/UI/GasThermomachineBoundUserInterface.cs +++ b/Content.Client/Atmos/UI/GasThermomachineBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Atmos.Piping.Unary.Components; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Atmos.UI { @@ -32,7 +31,14 @@ namespace Content.Client.Atmos.UI { base.Open(); - _window = this.CreateWindow(); + _window = new GasThermomachineWindow(); + + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed(); _window.TemperatureSpinbox.OnValueChanged += _ => OnTemperatureChanged(_window.TemperatureSpinbox.Value); @@ -85,5 +91,12 @@ namespace Content.Client.Atmos.UI true => Loc.GetString("comp-gas-thermomachine-ui-title-heater") }; } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); + } } } diff --git a/Content.Client/Atmos/UI/GasVolumePumpBoundUserInterface.cs b/Content.Client/Atmos/UI/GasVolumePumpBoundUserInterface.cs index 642f34c2f9..1b39306181 100644 --- a/Content.Client/Atmos/UI/GasVolumePumpBoundUserInterface.cs +++ b/Content.Client/Atmos/UI/GasVolumePumpBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.Atmos.Piping.Binary.Components; using Content.Shared.Localizations; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Atmos.UI { @@ -27,7 +26,14 @@ namespace Content.Client.Atmos.UI { base.Open(); - _window = this.CreateWindow(); + _window = new GasVolumePumpWindow(); + + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.ToggleStatusButtonPressed += OnToggleStatusButtonPressed; _window.PumpTransferRateChanged += OnPumpTransferRatePressed; @@ -58,9 +64,16 @@ namespace Content.Client.Atmos.UI if (_window == null || state is not GasVolumePumpBoundUserInterfaceState cast) return; - _window.Title = cast.PumpLabel; + _window.Title = (cast.PumpLabel); _window.SetPumpStatus(cast.Enabled); _window.SetTransferRate(cast.TransferRate); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); + } } } diff --git a/Content.Client/Atmos/UI/SpaceHeaterBoundUserInterface.cs b/Content.Client/Atmos/UI/SpaceHeaterBoundUserInterface.cs index e70426575d..4d8d1191e9 100644 --- a/Content.Client/Atmos/UI/SpaceHeaterBoundUserInterface.cs +++ b/Content.Client/Atmos/UI/SpaceHeaterBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Atmos.Piping.Portable.Components; using JetBrains.Annotations; -using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; namespace Content.Client.Atmos.UI; @@ -22,7 +21,14 @@ public sealed class SpaceHeaterBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + _window = new SpaceHeaterWindow(); + + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.ToggleStatusButton.OnPressed += _ => OnToggleStatusButtonPressed(); _window.IncreaseTempRange.OnPressed += _ => OnTemperatureRangeChanged(_window.TemperatureChangeDelta); diff --git a/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs b/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs index 865dfc478d..60fe339069 100644 --- a/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs +++ b/Content.Client/Audio/Jukebox/JukeboxBoundUserInterface.cs @@ -1,7 +1,8 @@ using Content.Shared.Audio.Jukebox; using Robust.Client.Audio; -using Robust.Client.UserInterface; +using Robust.Client.Player; using Robust.Shared.Audio.Components; +using Robust.Shared.Player; using Robust.Shared.Prototypes; namespace Content.Client.Audio.Jukebox; @@ -22,7 +23,9 @@ public sealed class JukeboxBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new JukeboxMenu(); + _menu.OnClose += Close; + _menu.OpenCentered(); _menu.OnPlayPressed += args => { @@ -97,5 +100,19 @@ public sealed class JukeboxBoundUserInterface : BoundUserInterface SendMessage(new JukeboxSetTimeMessage(sentTime)); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_menu == null) + return; + + _menu.OnClose -= Close; + _menu.Dispose(); + _menu = null; + } } diff --git a/Content.Client/Bed/Cryostorage/CryostorageBoundUserInterface.cs b/Content.Client/Bed/Cryostorage/CryostorageBoundUserInterface.cs index 09f3cec8fb..ffab162548 100644 --- a/Content.Client/Bed/Cryostorage/CryostorageBoundUserInterface.cs +++ b/Content.Client/Bed/Cryostorage/CryostorageBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Bed.Cryostorage; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Bed.Cryostorage; @@ -18,7 +17,9 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new(); + + _menu.OnClose += Close; _menu.SlotRemoveButtonPressed += (ent, slot) => { @@ -29,6 +30,8 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface { SendMessage(new CryostorageRemoveItemBuiMessage(ent, hand, CryostorageRemoveItemBuiMessage.RemovalType.Hand)); }; + + _menu.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -42,4 +45,12 @@ public sealed class CryostorageBoundUserInterface : BoundUserInterface break; } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Dispose(); + } } diff --git a/Content.Client/Cargo/BUI/CargoBountyConsoleBoundUserInterface.cs b/Content.Client/Cargo/BUI/CargoBountyConsoleBoundUserInterface.cs index 44c40143d8..d3365702bc 100644 --- a/Content.Client/Cargo/BUI/CargoBountyConsoleBoundUserInterface.cs +++ b/Content.Client/Cargo/BUI/CargoBountyConsoleBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Client.Cargo.UI; using Content.Shared.Cargo.Components; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Cargo.BUI; @@ -19,7 +18,9 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new(); + + _menu.OnClose += Close; _menu.OnLabelButtonPressed += id => { @@ -30,6 +31,8 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface { SendMessage(new BountySkipMessage(id)); }; + + _menu.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState message) @@ -41,4 +44,14 @@ public sealed class CargoBountyConsoleBoundUserInterface : BoundUserInterface _menu?.UpdateEntries(state.Bounties, state.UntilNextSkip); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (!disposing) + return; + + _menu?.Dispose(); + } } diff --git a/Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs b/Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs index 2461dafb5f..20c23a48a0 100644 --- a/Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs +++ b/Content.Client/Cargo/BUI/CargoPalletConsoleBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Client.Cargo.UI; using Content.Shared.Cargo.BUI; using Content.Shared.Cargo.Events; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Cargo.BUI; @@ -19,9 +18,21 @@ public sealed class CargoPalletConsoleBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new CargoPalletMenu(); _menu.AppraiseRequested += OnAppraisal; _menu.SellRequested += OnSell; + _menu.OnClose += Close; + + _menu.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + _menu?.Dispose(); + } } private void OnAppraisal() diff --git a/Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs b/Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs index 02b721b902..422d03707a 100644 --- a/Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Cargo/BUI/CargoShuttleConsoleBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Client.Cargo.UI; using Content.Shared.Cargo.BUI; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client.Cargo.BUI; @@ -10,8 +9,6 @@ namespace Content.Client.Cargo.BUI; [UsedImplicitly] public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface { - [Dependency] private readonly IPrototypeManager _protoManager = default!; - [ViewVariables] private CargoShuttleMenu? _menu; @@ -22,7 +19,24 @@ public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface protected override void Open() { base.Open(); - _menu = this.CreateWindow(); + var collection = IoCManager.Instance; + + if (collection == null) + return; + + _menu = new CargoShuttleMenu(collection.Resolve(), collection.Resolve().GetEntitySystem()); + _menu.OnClose += Close; + + _menu.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + _menu?.Dispose(); + } } protected override void UpdateState(BoundUserInterfaceState state) @@ -31,6 +45,6 @@ public sealed class CargoShuttleConsoleBoundUserInterface : BoundUserInterface if (state is not CargoShuttleConsoleBoundUserInterfaceState cargoState) return; _menu?.SetAccountName(cargoState.AccountName); _menu?.SetShuttleName(cargoState.ShuttleName); - _menu?.SetOrders(EntMan.System(), _protoManager, cargoState.Orders); + _menu?.SetOrders(cargoState.Orders); } } diff --git a/Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs b/Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs index 43b00089e1..c591f917da 100644 --- a/Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs +++ b/Content.Client/Cargo/UI/CargoShuttleMenu.xaml.cs @@ -12,9 +12,14 @@ namespace Content.Client.Cargo.UI [GenerateTypedNameReferences] public sealed partial class CargoShuttleMenu : FancyWindow { - public CargoShuttleMenu() + private readonly IPrototypeManager _protoManager; + private readonly SpriteSystem _spriteSystem; + + public CargoShuttleMenu(IPrototypeManager protoManager, SpriteSystem spriteSystem) { RobustXamlLoader.Load(this); + _protoManager = protoManager; + _spriteSystem = spriteSystem; Title = Loc.GetString("cargo-shuttle-console-menu-title"); } @@ -28,19 +33,19 @@ namespace Content.Client.Cargo.UI ShuttleNameLabel.Text = name; } - public void SetOrders(SpriteSystem sprites, IPrototypeManager protoManager, List orders) + public void SetOrders(List orders) { Orders.DisposeAllChildren(); foreach (var order in orders) { - var product = protoManager.Index(order.ProductId); + var product = _protoManager.Index(order.ProductId); var productName = product.Name; var row = new CargoOrderRow { Order = order, - Icon = { Texture = sprites.Frame0(product) }, + Icon = { Texture = _spriteSystem.Frame0(product) }, ProductName = { Text = Loc.GetString( diff --git a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs index 3ef7f0ae73..988fea7978 100644 --- a/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs +++ b/Content.Client/Chemistry/UI/ChemMasterBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Chemistry; using Content.Shared.Containers.ItemSlots; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Chemistry.UI { @@ -28,8 +27,13 @@ namespace Content.Client.Chemistry.UI base.Open(); // Setup window layout/elements - _window = this.CreateWindow(); - _window.Title = EntMan.GetComponent(Owner).EntityName; + _window = new ChemMasterWindow + { + Title = EntMan.GetComponent(Owner).EntityName, + }; + + _window.OpenCentered(); + _window.OnClose += Close; // Setup static button actions. _window.InputEjectButton.OnPressed += _ => SendMessage( @@ -71,5 +75,15 @@ namespace Content.Client.Chemistry.UI _window?.UpdateState(castState); // Update window state } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } } } diff --git a/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs b/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs index 2ad1b71888..99e5a3d395 100644 --- a/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs +++ b/Content.Client/Chemistry/UI/ReagentDispenserBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.Chemistry; using Content.Shared.Containers.ItemSlots; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Chemistry.UI { @@ -16,6 +15,9 @@ namespace Content.Client.Chemistry.UI [ViewVariables] private ReagentDispenserWindow? _window; + [ViewVariables] + private ReagentDispenserBoundUserInterfaceState? _lastState; + public ReagentDispenserBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } @@ -30,9 +32,14 @@ namespace Content.Client.Chemistry.UI base.Open(); // Setup window layout/elements - _window = this.CreateWindow(); - _window.Title = EntMan.GetComponent(Owner).EntityName; - _window.HelpGuidebookIds = EntMan.GetComponent(Owner).Guides; + _window = new() + { + Title = EntMan.GetComponent(Owner).EntityName, + HelpGuidebookIds = EntMan.GetComponent(Owner).Guides + }; + + _window.OpenCentered(); + _window.OnClose += Close; // Setup static button actions. _window.EjectButton.OnPressed += _ => SendMessage(new ItemSlotButtonPressedEvent(SharedReagentDispenser.OutputSlotName)); @@ -56,7 +63,19 @@ namespace Content.Client.Chemistry.UI base.UpdateState(state); var castState = (ReagentDispenserBoundUserInterfaceState) state; + _lastState = castState; + _window?.UpdateState(castState); //Update window state } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } } } diff --git a/Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs b/Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs index f1cb27a62a..35df131312 100644 --- a/Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs +++ b/Content.Client/Chemistry/UI/TransferAmountBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Chemistry; using Content.Shared.FixedPoint; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Chemistry.UI { @@ -19,7 +18,7 @@ namespace Content.Client.Chemistry.UI protected override void Open() { base.Open(); - _window = this.CreateWindow(); + _window = new TransferAmountWindow(); _window.ApplyButton.OnPressed += _ => { @@ -29,6 +28,15 @@ namespace Content.Client.Chemistry.UI _window.Close(); } }; + _window.OnClose += Close; + _window.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); } } } diff --git a/Content.Client/CloningConsole/UI/CloningConsoleBoundUserInterface.cs b/Content.Client/CloningConsole/UI/CloningConsoleBoundUserInterface.cs index 62a02f3718..26f0994701 100644 --- a/Content.Client/CloningConsole/UI/CloningConsoleBoundUserInterface.cs +++ b/Content.Client/CloningConsole/UI/CloningConsoleBoundUserInterface.cs @@ -1,7 +1,6 @@ using JetBrains.Annotations; using Robust.Client.GameObjects; using Content.Shared.Cloning.CloningConsole; -using Robust.Client.UserInterface; namespace Content.Client.CloningConsole.UI { @@ -18,11 +17,13 @@ namespace Content.Client.CloningConsole.UI protected override void Open() { base.Open(); - - _window = this.CreateWindow(); - _window.Title = Loc.GetString("cloning-console-window-title"); - + _window = new CloningConsoleWindow + { + Title = Loc.GetString("cloning-console-window-title") + }; + _window.OnClose += Close; _window.CloneButton.OnPressed += _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone)); + _window.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -31,5 +32,19 @@ namespace Content.Client.CloningConsole.UI _window?.Populate((CloningConsoleBoundUserInterfaceState) state); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_window != null) + { + _window.OnClose -= Close; + _window.CloneButton.OnPressed -= _ => SendMessage(new UiButtonPressedMessage(UiButton.Clone)); + } + _window?.Dispose(); + } } } diff --git a/Content.Client/Clothing/UI/ChameleonBoundUserInterface.cs b/Content.Client/Clothing/UI/ChameleonBoundUserInterface.cs index 83f6ba1566..5b0d5fcf21 100644 --- a/Content.Client/Clothing/UI/ChameleonBoundUserInterface.cs +++ b/Content.Client/Clothing/UI/ChameleonBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Clothing.Components; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Clothing.UI; @@ -23,8 +22,10 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new ChameleonMenu(); + _menu.OnClose += Close; _menu.OnIdSelected += OnIdSelected; + _menu.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -41,4 +42,15 @@ public sealed class ChameleonBoundUserInterface : BoundUserInterface { SendMessage(new ChameleonPrototypeSelectedMessage(selectedId)); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _menu?.Close(); + _menu = null; + } + } } diff --git a/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs b/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs index 0310e91eeb..1c94d32bf8 100644 --- a/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs +++ b/Content.Client/Communications/UI/CommunicationsConsoleBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.CCVar; using Content.Shared.Chat; using Content.Shared.Communications; -using Robust.Client.UserInterface; using Robust.Shared.Configuration; using Robust.Shared.Timing; @@ -9,11 +8,34 @@ namespace Content.Client.Communications.UI { public sealed class CommunicationsConsoleBoundUserInterface : BoundUserInterface { + [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly IConfigurationManager _cfg = default!; [ViewVariables] private CommunicationsConsoleMenu? _menu; + [ViewVariables] + public bool CanAnnounce { get; private set; } + [ViewVariables] + public bool CanBroadcast { get; private set; } + + [ViewVariables] + public bool CanCall { get; private set; } + + [ViewVariables] + public bool CountdownStarted { get; private set; } + + [ViewVariables] + public bool AlertLevelSelectable { get; private set; } + + [ViewVariables] + public string CurrentLevel { get; private set; } = default!; + + [ViewVariables] + private TimeSpan? _expectedCountdownTime; + + public int Countdown => _expectedCountdownTime == null ? 0 : Math.Max((int) _expectedCountdownTime.Value.Subtract(_gameTiming.CurTime).TotalSeconds, 0); + public CommunicationsConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } @@ -22,25 +44,23 @@ namespace Content.Client.Communications.UI { base.Open(); - _menu = this.CreateWindow(); - _menu.OnAnnounce += AnnounceButtonPressed; - _menu.OnBroadcast += BroadcastButtonPressed; - _menu.OnAlertLevel += AlertLevelSelected; - _menu.OnEmergencyLevel += EmergencyShuttleButtonPressed; + _menu = new CommunicationsConsoleMenu(this); + _menu.OnClose += Close; + _menu.OpenCentered(); } public void AlertLevelSelected(string level) { - if (_menu!.AlertLevelSelectable) + if (AlertLevelSelectable) { - _menu.CurrentLevel = level; + CurrentLevel = level; SendMessage(new CommunicationsConsoleSelectAlertLevelMessage(level)); } } public void EmergencyShuttleButtonPressed() { - if (_menu!.CountdownStarted) + if (CountdownStarted) RecallShuttle(); else CallShuttle(); @@ -75,23 +95,31 @@ namespace Content.Client.Communications.UI if (state is not CommunicationsConsoleInterfaceState commsState) return; + CanAnnounce = commsState.CanAnnounce; + CanBroadcast = commsState.CanBroadcast; + CanCall = commsState.CanCall; + _expectedCountdownTime = commsState.ExpectedCountdownEnd; + CountdownStarted = commsState.CountdownStarted; + AlertLevelSelectable = commsState.AlertLevels != null && !float.IsNaN(commsState.CurrentAlertDelay) && commsState.CurrentAlertDelay <= 0; + CurrentLevel = commsState.CurrentAlert; + if (_menu != null) { - _menu.CanAnnounce = commsState.CanAnnounce; - _menu.CanBroadcast = commsState.CanBroadcast; - _menu.CanCall = commsState.CanCall; - _menu.CountdownStarted = commsState.CountdownStarted; - _menu.AlertLevelSelectable = commsState.AlertLevels != null && !float.IsNaN(commsState.CurrentAlertDelay) && commsState.CurrentAlertDelay <= 0; - _menu.CurrentLevel = commsState.CurrentAlert; - _menu.CountdownEnd = commsState.ExpectedCountdownEnd; - _menu.UpdateCountdown(); - _menu.UpdateAlertLevels(commsState.AlertLevels, _menu.CurrentLevel); - _menu.AlertLevelButton.Disabled = !_menu.AlertLevelSelectable; - _menu.EmergencyShuttleButton.Disabled = !_menu.CanCall; - _menu.AnnounceButton.Disabled = !_menu.CanAnnounce; - _menu.BroadcastButton.Disabled = !_menu.CanBroadcast; + _menu.UpdateAlertLevels(commsState.AlertLevels, CurrentLevel); + _menu.AlertLevelButton.Disabled = !AlertLevelSelectable; + _menu.EmergencyShuttleButton.Disabled = !CanCall; + _menu.AnnounceButton.Disabled = !CanAnnounce; + _menu.BroadcastButton.Disabled = !CanBroadcast; } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _menu?.Dispose(); + } } } diff --git a/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs b/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs index cef68efd1f..bbca06f519 100644 --- a/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs +++ b/Content.Client/Communications/UI/CommunicationsConsoleMenu.xaml.cs @@ -1,40 +1,31 @@ -using System.Globalization; -using Content.Client.UserInterface.Controls; +using Content.Client.UserInterface.Controls; +using System.Threading; using Content.Shared.CCVar; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface.XAML; using Robust.Shared.Configuration; -using Robust.Shared.Timing; using Robust.Shared.Utility; +using Timer = Robust.Shared.Timing.Timer; namespace Content.Client.Communications.UI { [GenerateTypedNameReferences] public sealed partial class CommunicationsConsoleMenu : FancyWindow { + private CommunicationsConsoleBoundUserInterface Owner { get; set; } + private readonly CancellationTokenSource _timerCancelTokenSource = new(); + [Dependency] private readonly IConfigurationManager _cfg = default!; - [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly ILocalizationManager _loc = default!; - public bool CanAnnounce; - public bool CanBroadcast; - public bool CanCall; - public bool AlertLevelSelectable; - public bool CountdownStarted; - public string CurrentLevel = string.Empty; - public TimeSpan? CountdownEnd; - - public event Action? OnEmergencyLevel; - public event Action? OnAlertLevel; - public event Action? OnAnnounce; - public event Action? OnBroadcast; - - public CommunicationsConsoleMenu() + public CommunicationsConsoleMenu(CommunicationsConsoleBoundUserInterface owner) { IoCManager.InjectDependencies(this); RobustXamlLoader.Load(this); - MessageInput.Placeholder = new Rope.Leaf(_loc.GetString("comms-console-menu-announcement-placeholder")); + Owner = owner; + + var loc = IoCManager.Resolve(); + MessageInput.Placeholder = new Rope.Leaf(loc.GetString("comms-console-menu-announcement-placeholder")); var maxAnnounceLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength); MessageInput.OnTextChanged += (args) => @@ -46,38 +37,33 @@ namespace Content.Client.Communications.UI } else { - AnnounceButton.Disabled = !CanAnnounce; + AnnounceButton.Disabled = !owner.CanAnnounce; AnnounceButton.ToolTip = null; } }; - AnnounceButton.OnPressed += _ => OnAnnounce?.Invoke(Rope.Collapse(MessageInput.TextRope)); - AnnounceButton.Disabled = !CanAnnounce; + AnnounceButton.OnPressed += (_) => Owner.AnnounceButtonPressed(Rope.Collapse(MessageInput.TextRope)); + AnnounceButton.Disabled = !owner.CanAnnounce; - BroadcastButton.OnPressed += _ => OnBroadcast?.Invoke(Rope.Collapse(MessageInput.TextRope)); - BroadcastButton.Disabled = !CanBroadcast; + BroadcastButton.OnPressed += (_) => Owner.BroadcastButtonPressed(Rope.Collapse(MessageInput.TextRope)); + BroadcastButton.Disabled = !owner.CanBroadcast; AlertLevelButton.OnItemSelected += args => { var metadata = AlertLevelButton.GetItemMetadata(args.Id); if (metadata != null && metadata is string cast) { - OnAlertLevel?.Invoke(cast); + Owner.AlertLevelSelected(cast); } }; + AlertLevelButton.Disabled = !owner.AlertLevelSelectable; + EmergencyShuttleButton.OnPressed += (_) => Owner.EmergencyShuttleButtonPressed(); + EmergencyShuttleButton.Disabled = !owner.CanCall; - AlertLevelButton.Disabled = !AlertLevelSelectable; - - EmergencyShuttleButton.OnPressed += _ => OnEmergencyLevel?.Invoke(); - EmergencyShuttleButton.Disabled = !CanCall; - } - - protected override void FrameUpdate(FrameEventArgs args) - { - base.FrameUpdate(args); UpdateCountdown(); + Timer.SpawnRepeating(1000, UpdateCountdown, _timerCancelTokenSource.Token); } // The current alert could make levels unselectable, so we need to ensure that the UI reacts properly. @@ -119,19 +105,32 @@ namespace Content.Client.Communications.UI public void UpdateCountdown() { - if (!CountdownStarted) + if (!Owner.CountdownStarted) { - CountdownLabel.SetMessage(string.Empty); + CountdownLabel.SetMessage(""); EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-call-shuttle"); return; } - var diff = (CountdownEnd - _timing.CurTime) ?? TimeSpan.Zero; - EmergencyShuttleButton.Text = Loc.GetString("comms-console-menu-recall-shuttle"); var infoText = Loc.GetString($"comms-console-menu-time-remaining", - ("time", diff.TotalSeconds.ToString(CultureInfo.CurrentCulture))); + ("time", Owner.Countdown.ToString())); CountdownLabel.SetMessage(infoText); } + + public override void Close() + { + base.Close(); + + _timerCancelTokenSource.Cancel(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + _timerCancelTokenSource.Cancel(); + } } } diff --git a/Content.Client/Computer/ComputerBoundUserInterface.cs b/Content.Client/Computer/ComputerBoundUserInterface.cs index 11c26b252e..bdbfe03fa1 100644 --- a/Content.Client/Computer/ComputerBoundUserInterface.cs +++ b/Content.Client/Computer/ComputerBoundUserInterface.cs @@ -1,5 +1,4 @@ using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Client.UserInterface.CustomControls; namespace Content.Client.Computer @@ -20,8 +19,10 @@ namespace Content.Client.Computer { base.Open(); - _window = this.CreateWindow(); + _window = (TWindow) _dynamicTypeFactory.CreateInstance(typeof(TWindow)); _window.SetupComputerWindow(this); + _window.OnClose += Close; + _window.OpenCentered(); } // Alas, this constructor has to be copied to the subclass. :( @@ -41,6 +42,16 @@ namespace Content.Client.Computer _window.UpdateState((TState) state); } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } + protected override void ReceiveMessage(BoundUserInterfaceMessage message) { _window?.ReceiveMessage(message); diff --git a/Content.Client/Configurable/UI/ConfigurationBoundUserInterface.cs b/Content.Client/Configurable/UI/ConfigurationBoundUserInterface.cs index e4966f1ec4..4fea44f225 100644 --- a/Content.Client/Configurable/UI/ConfigurationBoundUserInterface.cs +++ b/Content.Client/Configurable/UI/ConfigurationBoundUserInterface.cs @@ -1,6 +1,5 @@ using System.Text.RegularExpressions; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using static Content.Shared.Configurable.ConfigurationComponent; namespace Content.Client.Configurable.UI @@ -10,6 +9,9 @@ namespace Content.Client.Configurable.UI [ViewVariables] private ConfigurationMenu? _menu; + [ViewVariables] + public Regex? Validation { get; internal set; } + public ConfigurationBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } @@ -17,8 +19,10 @@ namespace Content.Client.Configurable.UI protected override void Open() { base.Open(); - _menu = this.CreateWindow(); - _menu.OnConfiguration += SendConfiguration; + _menu = new ConfigurationMenu(this); + + _menu.OnClose += Close; + _menu.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -26,7 +30,9 @@ namespace Content.Client.Configurable.UI base.UpdateState(state); if (state is not ConfigurationBoundUserInterfaceState configurationState) + { return; + } _menu?.Populate(configurationState); } @@ -35,12 +41,9 @@ namespace Content.Client.Configurable.UI { base.ReceiveMessage(message); - if (_menu == null) - return; - if (message is ValidationUpdateMessage msg) { - _menu.Validation = new Regex(msg.ValidationString, RegexOptions.Compiled); + Validation = new Regex(msg.ValidationString, RegexOptions.Compiled); } } @@ -48,5 +51,16 @@ namespace Content.Client.Configurable.UI { SendMessage(new ConfigurationUpdatedMessage(config)); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing && _menu != null) + { + _menu.OnClose -= Close; + _menu.Close(); + } + } } } diff --git a/Content.Client/Configurable/UI/ConfigurationMenu.cs b/Content.Client/Configurable/UI/ConfigurationMenu.cs index 29217eef7b..cc24af2869 100644 --- a/Content.Client/Configurable/UI/ConfigurationMenu.cs +++ b/Content.Client/Configurable/UI/ConfigurationMenu.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Numerics; -using System.Text.RegularExpressions; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; @@ -14,25 +13,23 @@ namespace Content.Client.Configurable.UI { public sealed class ConfigurationMenu : DefaultWindow { + public ConfigurationBoundUserInterface Owner { get; } + private readonly BoxContainer _column; private readonly BoxContainer _row; private readonly List<(string name, LineEdit input)> _inputs; - [ViewVariables] - public Regex? Validation { get; internal set; } - - public event Action>? OnConfiguration; - - public ConfigurationMenu() + public ConfigurationMenu(ConfigurationBoundUserInterface owner) { MinSize = SetSize = new Vector2(300, 250); + Owner = owner; _inputs = new List<(string name, LineEdit input)>(); Title = Loc.GetString("configuration-menu-device-title"); - var baseContainer = new BoxContainer + BoxContainer baseContainer = new BoxContainer { Orientation = LayoutOrientation.Vertical, VerticalExpand = true, @@ -119,13 +116,14 @@ namespace Content.Client.Configurable.UI private void OnConfirm(ButtonEventArgs args) { var config = GenerateDictionary(_inputs, "Text"); - OnConfiguration?.Invoke(config); + + Owner.SendConfiguration(config); Close(); } private bool Validate(string value) { - return Validation?.IsMatch(value) != false; + return Owner.Validation == null || Owner.Validation.IsMatch(value); } private Dictionary GenerateDictionary(IEnumerable<(string name, LineEdit input)> inputs, string propertyName) diff --git a/Content.Client/Construction/UI/FlatpackCreatorBoundUserInterface.cs b/Content.Client/Construction/UI/FlatpackCreatorBoundUserInterface.cs index 887492955e..86f1b8b83c 100644 --- a/Content.Client/Construction/UI/FlatpackCreatorBoundUserInterface.cs +++ b/Content.Client/Construction/UI/FlatpackCreatorBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Construction.Components; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Construction.UI { @@ -18,8 +17,8 @@ namespace Content.Client.Construction.UI { base.Open(); - _menu = this.CreateWindow(); - _menu.SetEntity(Owner); + _menu = new FlatpackCreatorMenu(Owner); + _menu.OnClose += Close; _menu.PackButtonPressed += () => { @@ -28,5 +27,14 @@ namespace Content.Client.Construction.UI _menu.OpenCentered(); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Dispose(); + } } } diff --git a/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs b/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs index 269694ebf9..9f3d5695bb 100644 --- a/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs +++ b/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs @@ -24,7 +24,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow private readonly FlatpackSystem _flatpack; private readonly MaterialStorageSystem _materialStorage; - private EntityUid _owner; + private readonly EntityUid _owner; [ValidatePrototypeId] public const string NoBoardEffectId = "FlatpackerNoBoardEffect"; @@ -33,7 +33,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow public event Action? PackButtonPressed; - public FlatpackCreatorMenu() + public FlatpackCreatorMenu(EntityUid uid) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); @@ -42,15 +42,12 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow _flatpack = _entityManager.System(); _materialStorage = _entityManager.System(); + _owner = uid; + PackButton.OnPressed += _ => PackButtonPressed?.Invoke(); - InsertLabel.SetMarkup(Loc.GetString("flatpacker-ui-insert-board")); - } - - public void SetEntity(EntityUid uid) - { - _owner = uid; MaterialStorageControl.SetOwner(uid); + InsertLabel.SetMarkup(Loc.GetString("flatpacker-ui-insert-board")); } protected override void FrameUpdate(FrameEventArgs args) diff --git a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs index e5be0b1811..e2c4d51ecd 100644 --- a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs +++ b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs @@ -2,15 +2,12 @@ using Content.Shared.Crayon; using Content.Shared.Decals; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client.Crayon.UI { public sealed class CrayonBoundUserInterface : BoundUserInterface { - [Dependency] private readonly IPrototypeManager _protoManager = default!; - [ViewVariables] private CrayonWindow? _menu; @@ -21,29 +18,15 @@ namespace Content.Client.Crayon.UI protected override void Open() { base.Open(); - _menu = this.CreateWindow(); - _menu.OnColorSelected += SelectColor; - _menu.OnSelected += Select; - PopulateCrayons(); + _menu = new CrayonWindow(this); + + _menu.OnClose += Close; + var prototypeManager = IoCManager.Resolve(); + var crayonDecals = prototypeManager.EnumeratePrototypes().Where(x => x.Tags.Contains("crayon")); + _menu.Populate(crayonDecals); _menu.OpenCenteredLeft(); } - private void PopulateCrayons() - { - var crayonDecals = _protoManager.EnumeratePrototypes().Where(x => x.Tags.Contains("crayon")); - _menu?.Populate(crayonDecals); - } - - public override void OnProtoReload(PrototypesReloadedEventArgs args) - { - base.OnProtoReload(args); - - if (!args.WasModified()) - return; - - PopulateCrayons(); - } - protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); @@ -60,5 +43,16 @@ namespace Content.Client.Crayon.UI { SendMessage(new CrayonColorMessage(color)); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _menu?.Close(); + _menu = null; + } + } } } diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs index b97786cd41..2a5801ccf2 100644 --- a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs +++ b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs @@ -18,17 +18,18 @@ namespace Content.Client.Crayon.UI [GenerateTypedNameReferences] public sealed partial class CrayonWindow : DefaultWindow { + public CrayonBoundUserInterface Owner { get; } + private Dictionary? _decals; private string? _selected; private Color _color; - public event Action? OnColorSelected; - public event Action? OnSelected; - - public CrayonWindow() + public CrayonWindow(CrayonBoundUserInterface owner) { RobustXamlLoader.Load(this); + Owner = owner; + Search.OnTextChanged += _ => RefreshList(); ColorSelector.OnColorChanged += SelectColor; } @@ -37,16 +38,16 @@ namespace Content.Client.Crayon.UI { _color = color; - OnColorSelected?.Invoke(color); + Owner.SelectColor(color); + RefreshList(); } private void RefreshList() { // Clear - Grid.DisposeAllChildren(); - if (_decals == null) - return; + Grid.RemoveAllChildren(); + if (_decals == null) return; var filter = Search.Text; foreach (var (decal, tex) in _decals) @@ -88,6 +89,7 @@ namespace Content.Client.Crayon.UI { if (obj.Button.Name == null) return; + Owner.Select(obj.Button.Name); _selected = obj.Button.Name; RefreshList(); } diff --git a/Content.Client/Disposal/UI/DisposalRouterBoundUserInterface.cs b/Content.Client/Disposal/UI/DisposalRouterBoundUserInterface.cs index 296e71d3a9..e8e77217ea 100644 --- a/Content.Client/Disposal/UI/DisposalRouterBoundUserInterface.cs +++ b/Content.Client/Disposal/UI/DisposalRouterBoundUserInterface.cs @@ -1,6 +1,5 @@ using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using static Content.Shared.Disposal.Components.SharedDisposalRouterComponent; namespace Content.Client.Disposal.UI @@ -22,16 +21,20 @@ namespace Content.Client.Disposal.UI { base.Open(); - _window = this.CreateWindow(); + _window = new DisposalRouterWindow(); + + _window.OpenCentered(); + _window.OnClose += Close; _window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text); _window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text); + } private void ButtonPressed(UiAction action, string tag) { SendMessage(new UiActionMessage(action, tag)); - Close(); + _window?.Close(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -45,5 +48,18 @@ namespace Content.Client.Disposal.UI _window?.UpdateState(cast); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } + + } + } diff --git a/Content.Client/Disposal/UI/DisposalTaggerBoundUserInterface.cs b/Content.Client/Disposal/UI/DisposalTaggerBoundUserInterface.cs index 7fc0eb8540..3aeed8dc80 100644 --- a/Content.Client/Disposal/UI/DisposalTaggerBoundUserInterface.cs +++ b/Content.Client/Disposal/UI/DisposalTaggerBoundUserInterface.cs @@ -1,6 +1,5 @@ using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using static Content.Shared.Disposal.Components.SharedDisposalTaggerComponent; namespace Content.Client.Disposal.UI @@ -22,17 +21,20 @@ namespace Content.Client.Disposal.UI { base.Open(); - _window = this.CreateWindow(); + _window = new DisposalTaggerWindow(); + + _window.OpenCentered(); + _window.OnClose += Close; _window.Confirm.OnPressed += _ => ButtonPressed(UiAction.Ok, _window.TagInput.Text); _window.TagInput.OnTextEntered += args => ButtonPressed(UiAction.Ok, args.Text); + } private void ButtonPressed(UiAction action, string tag) { - // TODO: This looks copy-pasted with the other mailing stuff... SendMessage(new UiActionMessage(action, tag)); - Close(); + _window?.Close(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -46,5 +48,18 @@ namespace Content.Client.Disposal.UI _window?.UpdateState(cast); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Dispose(); + } + } + + } + } diff --git a/Content.Client/Doors/Electronics/DoorElectronicsBoundUserInterface.cs b/Content.Client/Doors/Electronics/DoorElectronicsBoundUserInterface.cs index 9b7e23c03a..cd7ea717ce 100644 --- a/Content.Client/Doors/Electronics/DoorElectronicsBoundUserInterface.cs +++ b/Content.Client/Doors/Electronics/DoorElectronicsBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Access; using Content.Shared.Doors.Electronics; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client.Doors.Electronics; @@ -19,23 +18,6 @@ public sealed class DoorElectronicsBoundUserInterface : BoundUserInterface protected override void Open() { base.Open(); - _window = this.CreateWindow(); - _window.OnAccessChanged += UpdateConfiguration; - Reset(); - } - - public override void OnProtoReload(PrototypesReloadedEventArgs args) - { - base.OnProtoReload(args); - - if (!args.WasModified()) - return; - - Reset(); - } - - private void Reset() - { List> accessLevels = new(); foreach (var accessLevel in _prototypeManager.EnumeratePrototypes()) @@ -47,7 +29,10 @@ public sealed class DoorElectronicsBoundUserInterface : BoundUserInterface } accessLevels.Sort(); - _window?.Reset(_prototypeManager, accessLevels); + + _window = new DoorElectronicsConfigurationMenu(this, accessLevels, _prototypeManager); + _window.OnClose += Close; + _window.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -59,6 +44,14 @@ public sealed class DoorElectronicsBoundUserInterface : BoundUserInterface _window?.UpdateState(castState); } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _window?.Dispose(); + } + public void UpdateConfiguration(List> newAccessList) { SendMessage(new DoorElectronicsUpdateConfigurationMessage(newAccessList)); diff --git a/Content.Client/Doors/Electronics/DoorElectronicsConfigurationMenu.xaml.cs b/Content.Client/Doors/Electronics/DoorElectronicsConfigurationMenu.xaml.cs index 2112a56297..c01f13a462 100644 --- a/Content.Client/Doors/Electronics/DoorElectronicsConfigurationMenu.xaml.cs +++ b/Content.Client/Doors/Electronics/DoorElectronicsConfigurationMenu.xaml.cs @@ -15,23 +15,22 @@ namespace Content.Client.Doors.Electronics; [GenerateTypedNameReferences] public sealed partial class DoorElectronicsConfigurationMenu : FancyWindow { - private readonly AccessLevelControl _buttonsList = new(); + private readonly DoorElectronicsBoundUserInterface _owner; + private AccessLevelControl _buttonsList = new(); - public event Action>>? OnAccessChanged; - - public DoorElectronicsConfigurationMenu() + public DoorElectronicsConfigurationMenu(DoorElectronicsBoundUserInterface ui, List> accessLevels, IPrototypeManager prototypeManager) { RobustXamlLoader.Load(this); + + _owner = ui; + + _buttonsList.Populate(accessLevels, prototypeManager); AccessLevelControlContainer.AddChild(_buttonsList); - } - public void Reset(IPrototypeManager protoManager, List> accessLevels) - { - _buttonsList.Populate(accessLevels, protoManager); - - foreach (var button in _buttonsList.ButtonsList.Values) + foreach (var (id, button) in _buttonsList.ButtonsList) { - button.OnPressed += _ => OnAccessChanged?.Invoke(_buttonsList.ButtonsList.Where(x => x.Value.Pressed).Select(x => x.Key).ToList()); + button.OnPressed += _ => _owner.UpdateConfiguration( + _buttonsList.ButtonsList.Where(x => x.Value.Pressed).Select(x => x.Key).ToList()); } } diff --git a/Content.Client/Fax/UI/FaxBoundUi.cs b/Content.Client/Fax/UI/FaxBoundUi.cs index ca2e834b4f..a95066a3b5 100644 --- a/Content.Client/Fax/UI/FaxBoundUi.cs +++ b/Content.Client/Fax/UI/FaxBoundUi.cs @@ -25,7 +25,10 @@ public sealed class FaxBoundUi : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + _window = new FaxWindow(); + _window.OpenCentered(); + + _window.OnClose += Close; _window.FileButtonPressed += OnFileButtonPressed; _window.CopyButtonPressed += OnCopyButtonPressed; _window.SendButtonPressed += OnSendButtonPressed; @@ -101,4 +104,11 @@ public sealed class FaxBoundUi : BoundUserInterface _window.UpdateState(cast); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + _window?.Dispose(); + } } diff --git a/Content.Client/Forensics/ForensicScannerBoundUserInterface.cs b/Content.Client/Forensics/ForensicScannerBoundUserInterface.cs index 08596b04e6..ba49f11ea0 100644 --- a/Content.Client/Forensics/ForensicScannerBoundUserInterface.cs +++ b/Content.Client/Forensics/ForensicScannerBoundUserInterface.cs @@ -1,7 +1,6 @@ using Robust.Client.GameObjects; using Robust.Shared.Timing; using Content.Shared.Forensics; -using Robust.Client.UserInterface; namespace Content.Client.Forensics { @@ -22,9 +21,11 @@ namespace Content.Client.Forensics protected override void Open() { base.Open(); - _window = this.CreateWindow(); + _window = new ForensicScannerMenu(); + _window.OnClose += Close; _window.Print.OnPressed += _ => Print(); _window.Clear.OnPressed += _ => Clear(); + _window.OpenCentered(); } private void Print() @@ -61,7 +62,6 @@ namespace Content.Client.Forensics _printCooldown = cast.PrintCooldown; - // TODO: Fix this if (cast.PrintReadyAt > _gameTiming.CurTime) Timer.Spawn(cast.PrintReadyAt - _gameTiming.CurTime, () => { @@ -71,5 +71,14 @@ namespace Content.Client.Forensics _window.UpdateState(cast); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _window?.Dispose(); + } } } diff --git a/Content.Client/Gateway/UI/GatewayBoundUserInterface.cs b/Content.Client/Gateway/UI/GatewayBoundUserInterface.cs index 457b70ca7c..fdb3cdbc01 100644 --- a/Content.Client/Gateway/UI/GatewayBoundUserInterface.cs +++ b/Content.Client/Gateway/UI/GatewayBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Gateway; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Gateway.UI; @@ -18,13 +17,24 @@ public sealed class GatewayBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.SetEntity(EntMan.GetNetEntity(Owner)); + _window = new GatewayWindow(EntMan.GetNetEntity(Owner)); _window.OpenPortal += destination => { SendMessage(new GatewayOpenPortalMessage(destination)); }; + _window.OnClose += Close; + _window?.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + _window?.Dispose(); + _window = null; + } } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/Gateway/UI/GatewayWindow.xaml.cs b/Content.Client/Gateway/UI/GatewayWindow.xaml.cs index 1c779b2b35..889dd6e175 100644 --- a/Content.Client/Gateway/UI/GatewayWindow.xaml.cs +++ b/Content.Client/Gateway/UI/GatewayWindow.xaml.cs @@ -22,7 +22,7 @@ public sealed partial class GatewayWindow : FancyWindow, public event Action? OpenPortal; private List _destinations = new(); - public NetEntity Owner; + public readonly NetEntity Owner; private NetEntity? _current; private TimeSpan _nextReady; @@ -46,20 +46,16 @@ public sealed partial class GatewayWindow : FancyWindow, /// private bool _isCooldownPending = true; - public GatewayWindow() + public GatewayWindow(NetEntity netEntity) { RobustXamlLoader.Load(this); var dependencies = IoCManager.Instance!; _timing = dependencies.Resolve(); + Owner = netEntity; NextUnlockBar.ForegroundStyleBoxOverride = new StyleBoxFlat(Color.FromHex("#C74EBD")); } - public void SetEntity(NetEntity entity) - { - - } - public void UpdateState(GatewayBoundUserInterfaceState state) { _destinations = state.Destinations; diff --git a/Content.Client/Gravity/UI/GravityGeneratorBoundUserInterface.cs b/Content.Client/Gravity/UI/GravityGeneratorBoundUserInterface.cs index 32b40747d5..d72da3e812 100644 --- a/Content.Client/Gravity/UI/GravityGeneratorBoundUserInterface.cs +++ b/Content.Client/Gravity/UI/GravityGeneratorBoundUserInterface.cs @@ -1,6 +1,6 @@ using Content.Shared.Gravity; using JetBrains.Annotations; -using Robust.Client.UserInterface; +using Robust.Client.GameObjects; namespace Content.Client.Gravity.UI { @@ -18,8 +18,17 @@ namespace Content.Client.Gravity.UI { base.Open(); - _window = this.CreateWindow(); - _window.SetEntity(Owner); + _window = new GravityGeneratorWindow(this); + + /* + _window.Switch.OnPressed += _ => + { + SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(!IsOn)); + }; + */ + + _window.OpenCentered(); + _window.OnClose += Close; } protected override void UpdateState(BoundUserInterfaceState state) @@ -30,6 +39,14 @@ namespace Content.Client.Gravity.UI _window?.UpdateState(castState); } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _window?.Dispose(); + } + public void SetPowerSwitch(bool on) { SendMessage(new SharedGravityGeneratorComponent.SwitchGeneratorMessage(on)); diff --git a/Content.Client/Gravity/UI/GravityGeneratorWindow.xaml.cs b/Content.Client/Gravity/UI/GravityGeneratorWindow.xaml.cs index 6f04133b59..75f8eb479b 100644 --- a/Content.Client/Gravity/UI/GravityGeneratorWindow.xaml.cs +++ b/Content.Client/Gravity/UI/GravityGeneratorWindow.xaml.cs @@ -12,23 +12,22 @@ namespace Content.Client.Gravity.UI { private readonly ButtonGroup _buttonGroup = new(); - public event Action? OnPowerSwitch; + private readonly GravityGeneratorBoundUserInterface _owner; - public GravityGeneratorWindow() + public GravityGeneratorWindow(GravityGeneratorBoundUserInterface owner) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + _owner = owner; + OnButton.Group = _buttonGroup; OffButton.Group = _buttonGroup; - OnButton.OnPressed += _ => OnPowerSwitch?.Invoke(true); - OffButton.OnPressed += _ => OnPowerSwitch?.Invoke(false); - } + OnButton.OnPressed += _ => _owner.SetPowerSwitch(true); + OffButton.OnPressed += _ => _owner.SetPowerSwitch(false); - public void SetEntity(EntityUid uid) - { - EntityView.SetEntity(uid); + EntityView.SetEntity(owner.Owner); } public void UpdateState(SharedGravityGeneratorComponent.GeneratorState state) diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerBoundUserInterface.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerBoundUserInterface.cs index 38760f4aa3..dc0a3e9fcc 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerBoundUserInterface.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerBoundUserInterface.cs @@ -1,6 +1,6 @@ using Content.Shared.MedicalScanner; using JetBrains.Annotations; -using Robust.Client.UserInterface; +using Robust.Client.GameObjects; namespace Content.Client.HealthAnalyzer.UI { @@ -17,9 +17,12 @@ namespace Content.Client.HealthAnalyzer.UI protected override void Open() { base.Open(); - _window = this.CreateWindow(); - - _window.Title = EntMan.GetComponent(Owner).EntityName; + _window = new HealthAnalyzerWindow + { + Title = EntMan.GetComponent(Owner).EntityName, + }; + _window.OnClose += Close; + _window.OpenCentered(); } protected override void ReceiveMessage(BoundUserInterfaceMessage message) @@ -32,5 +35,17 @@ namespace Content.Client.HealthAnalyzer.UI _window.Populate(cast); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_window != null) + _window.OnClose -= Close; + + _window?.Dispose(); + } } } diff --git a/Content.Client/Humanoid/HumanoidMarkingModifierBoundUserInterface.cs b/Content.Client/Humanoid/HumanoidMarkingModifierBoundUserInterface.cs index 53977eb636..a8872604a4 100644 --- a/Content.Client/Humanoid/HumanoidMarkingModifierBoundUserInterface.cs +++ b/Content.Client/Humanoid/HumanoidMarkingModifierBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; -using Robust.Client.UserInterface; namespace Content.Client.Humanoid; @@ -21,7 +20,8 @@ public sealed class HumanoidMarkingModifierBoundUserInterface : BoundUserInterfa { base.Open(); - _window = this.CreateWindow(); + _window = new(); + _window.OnClose += Close; _window.OnMarkingAdded += SendMarkingSet; _window.OnMarkingRemoved += SendMarkingSet; _window.OnMarkingColorChange += SendMarkingSetNoResend; diff --git a/Content.Client/Instruments/UI/BandMenu.xaml.cs b/Content.Client/Instruments/UI/BandMenu.xaml.cs index 26cd1369e5..5fb293a194 100644 --- a/Content.Client/Instruments/UI/BandMenu.xaml.cs +++ b/Content.Client/Instruments/UI/BandMenu.xaml.cs @@ -11,9 +11,7 @@ public sealed partial class BandMenu : DefaultWindow { private readonly InstrumentBoundUserInterface _owner; - public EntityUid? Master; - - public BandMenu(InstrumentBoundUserInterface owner) + public BandMenu(InstrumentBoundUserInterface owner) : base() { RobustXamlLoader.Load(this); @@ -42,7 +40,7 @@ public sealed partial class BandMenu : DefaultWindow { var uid = entManager.GetEntity(nent); var item = BandList.AddItem(name, null, true, uid); - item.Selected = Master == uid; + item.Selected = _owner.Instrument?.Master == uid; } } } diff --git a/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs b/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs index c175e67842..2814d41536 100644 --- a/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs +++ b/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs @@ -51,7 +51,7 @@ public sealed partial class ChannelsMenu : DefaultWindow } } - public void Populate(InstrumentComponent? instrument) + public void Populate() { ChannelList.Clear(); @@ -60,8 +60,7 @@ public sealed partial class ChannelsMenu : DefaultWindow var item = ChannelList.AddItem(_owner.Loc.GetString("instrument-component-channel-name", ("number", i)), null, true, i); - - item.Selected = !instrument?.FilteredChannels[i] ?? false; + item.Selected = !_owner.Instrument?.FilteredChannels[i] ?? false; } } } diff --git a/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs b/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs index 4816ce8c36..0f5729f55b 100644 --- a/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs +++ b/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs @@ -24,6 +24,8 @@ namespace Content.Client.Instruments.UI [ViewVariables] private BandMenu? _bandMenu; [ViewVariables] private ChannelsMenu? _channelsMenu; + [ViewVariables] public InstrumentComponent? Instrument { get; private set; } + public InstrumentBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { IoCManager.InjectDependencies(this); @@ -41,20 +43,14 @@ namespace Content.Client.Instruments.UI protected override void Open() { - _instrumentMenu = this.CreateWindow(); - _instrumentMenu.Title = EntMan.GetComponent(Owner).EntityName; + if (!EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument)) + return; - _instrumentMenu.OnOpenBand += OpenBandMenu; - _instrumentMenu.OnOpenChannels += OpenChannelsMenu; - _instrumentMenu.OnCloseChannels += CloseChannelsMenu; - _instrumentMenu.OnCloseBands += CloseBandMenu; + Instrument = instrument; + _instrumentMenu = new InstrumentMenu(this); + _instrumentMenu.OnClose += Close; - _instrumentMenu.SetMIDI(MidiManager.IsAvailable); - - if (EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument)) - { - _instrumentMenu.SetInstrument((Owner, instrument)); - } + _instrumentMenu.OpenCentered(); } protected override void Dispose(bool disposing) @@ -62,12 +58,7 @@ namespace Content.Client.Instruments.UI base.Dispose(disposing); if (!disposing) return; - - if (EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument)) - { - _instrumentMenu?.RemoveInstrument(instrument); - } - + _instrumentMenu?.Dispose(); _bandMenu?.Dispose(); _channelsMenu?.Dispose(); } @@ -81,11 +72,6 @@ namespace Content.Client.Instruments.UI { _bandMenu ??= new BandMenu(this); - if (EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument)) - { - _bandMenu.Master = instrument.Master; - } - // Refresh cache... RefreshBands(); @@ -101,9 +87,7 @@ namespace Content.Client.Instruments.UI public void OpenChannelsMenu() { _channelsMenu ??= new ChannelsMenu(this); - EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument); - - _channelsMenu.Populate(instrument); + _channelsMenu.Populate(); _channelsMenu.OpenCenteredRight(); } diff --git a/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs b/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs index fc863648d7..da443e3fb5 100644 --- a/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs +++ b/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs @@ -1,10 +1,7 @@ using System.IO; using System.Numerics; using System.Threading.Tasks; -using Content.Client.Interactable; -using Content.Shared.ActionBlocker; using Robust.Client.AutoGenerated; -using Robust.Client.Player; using Robust.Client.UserInterface; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; @@ -19,23 +16,33 @@ namespace Content.Client.Instruments.UI [GenerateTypedNameReferences] public sealed partial class InstrumentMenu : DefaultWindow { - [Dependency] private readonly IEntityManager _entManager = default!; - [Dependency] private readonly IFileDialogManager _dialogs = default!; - [Dependency] private readonly IPlayerManager _player = default!; + private readonly InstrumentBoundUserInterface _owner; private bool _isMidiFileDialogueWindowOpen; - public event Action? OnOpenBand; - public event Action? OnOpenChannels; - public event Action? OnCloseBands; - public event Action? OnCloseChannels; - - public EntityUid Entity; - - public InstrumentMenu() + public InstrumentMenu(InstrumentBoundUserInterface owner) { RobustXamlLoader.Load(this); - IoCManager.InjectDependencies(this); + + _owner = owner; + + if (_owner.Instrument != null) + { + _owner.Instrument.OnMidiPlaybackEnded += InstrumentOnMidiPlaybackEnded; + Title = _owner.Entities.GetComponent(_owner.Owner).EntityName; + LoopButton.Disabled = !_owner.Instrument.IsMidiOpen; + LoopButton.Pressed = _owner.Instrument.LoopMidi; + ChannelsButton.Disabled = !_owner.Instrument.IsRendererAlive; + StopButton.Disabled = !_owner.Instrument.IsMidiOpen; + PlaybackSlider.MouseFilter = _owner.Instrument.IsMidiOpen ? MouseFilterMode.Pass : MouseFilterMode.Ignore; + } + + if (!_owner.MidiManager.IsAvailable) + { + UnavailableOverlay.Visible = true; + // We return early as to not give the buttons behavior. + return; + } InputButton.OnToggled += MidiInputButtonOnOnToggled; BandButton.OnPressed += BandButtonOnPressed; @@ -50,34 +57,12 @@ namespace Content.Client.Instruments.UI MinSize = SetSize = new Vector2(400, 150); } - public void SetInstrument(Entity entity) - { - Entity = entity; - var component = entity.Comp; - component.OnMidiPlaybackEnded += InstrumentOnMidiPlaybackEnded; - LoopButton.Disabled = !component.IsMidiOpen; - LoopButton.Pressed = component.LoopMidi; - ChannelsButton.Disabled = !component.IsRendererAlive; - StopButton.Disabled = !component.IsMidiOpen; - PlaybackSlider.MouseFilter = component.IsMidiOpen ? MouseFilterMode.Pass : MouseFilterMode.Ignore; - } - - public void RemoveInstrument(InstrumentComponent component) - { - component.OnMidiPlaybackEnded -= InstrumentOnMidiPlaybackEnded; - } - - public void SetMIDI(bool available) - { - UnavailableOverlay.Visible = !available; - } - private void BandButtonOnPressed(ButtonEventArgs obj) { if (!PlayCheck()) return; - OnOpenBand?.Invoke(); + _owner.OpenBandMenu(); } private void BandButtonOnToggled(ButtonToggledEventArgs obj) @@ -85,15 +70,12 @@ namespace Content.Client.Instruments.UI if (obj.Pressed) return; - if (_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument)) - { - _entManager.System().SetMaster(Entity, instrument.Master); - } + _owner.Instruments.SetMaster(_owner.Owner, null); } private void ChannelsButtonOnPressed(ButtonEventArgs obj) { - OnOpenChannels?.Invoke(); + _owner.OpenChannelsMenu(); } private void InstrumentOnMidiPlaybackEnded() @@ -103,10 +85,8 @@ namespace Content.Client.Instruments.UI public void MidiPlaybackSetButtonsDisabled(bool disabled) { - if (disabled) - { - OnCloseChannels?.Invoke(); - } + if(disabled) + _owner.CloseChannelsMenu(); LoopButton.Disabled = disabled; StopButton.Disabled = disabled; @@ -120,7 +100,7 @@ namespace Content.Client.Instruments.UI if (_isMidiFileDialogueWindowOpen) return; - OnCloseBands?.Invoke(); + _owner.CloseBandMenu(); var filters = new FileDialogFilters(new FileDialogFilters.Group("mid", "midi")); @@ -128,7 +108,7 @@ namespace Content.Client.Instruments.UI // or focus the previously-opened window. _isMidiFileDialogueWindowOpen = true; - await using var file = await _dialogs.OpenFile(filters); + await using var file = await _owner.FileDialogManager.OpenFile(filters); _isMidiFileDialogueWindowOpen = false; @@ -149,18 +129,9 @@ namespace Content.Client.Instruments.UI await file.CopyToAsync(memStream); - if (!_entManager.TryGetComponent(Entity, out var instrument)) - { + if (_owner.Instrument is not {} instrument + || !_owner.Instruments.OpenMidi(_owner.Owner, memStream.GetBuffer().AsSpan(0, (int) memStream.Length), instrument)) return; - } - - if (!_entManager.System() - .OpenMidi(Entity, - memStream.GetBuffer().AsSpan(0, (int) memStream.Length), - instrument)) - { - return; - } MidiPlaybackSetButtonsDisabled(false); if (InputButton.Pressed) @@ -169,7 +140,7 @@ namespace Content.Client.Instruments.UI private void MidiInputButtonOnOnToggled(ButtonToggledEventArgs obj) { - OnCloseBands?.Invoke(); + _owner.CloseBandMenu(); if (obj.Pressed) { @@ -177,99 +148,109 @@ namespace Content.Client.Instruments.UI return; MidiStopButtonOnPressed(null); - - if (_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument)) - _entManager.System().OpenInput(Entity, instrument); + if(_owner.Instrument is {} instrument) + _owner.Instruments.OpenInput(_owner.Owner, instrument); } - else + else if (_owner.Instrument is { } instrument) { - _entManager.System().CloseInput(Entity, false); - OnCloseChannels?.Invoke(); + _owner.Instruments.CloseInput(_owner.Owner, false, instrument); + _owner.CloseChannelsMenu(); } } private bool PlayCheck() { // TODO all of these checks should also be done server-side. - if (!_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument)) + + var instrumentEnt = _owner.Owner; + var instrument = _owner.Instrument; + + if (instrument == null) return false; - var localEntity = _player.LocalEntity; + var localEntity = _owner.PlayerManager.LocalEntity; // If we don't have a player or controlled entity, we return. if (localEntity == null) return false; // By default, allow an instrument to play itself and skip all other checks - if (localEntity == Entity) + if (localEntity == instrumentEnt) return true; - var container = _entManager.System(); + var container = _owner.Entities.System(); // If we're a handheld instrument, we might be in a container. Get it just in case. - container.TryGetContainingContainer(Entity, out var conMan); + container.TryGetContainingContainer(instrumentEnt, out var conMan); // If the instrument is handheld and we're not holding it, we return. - if (instrument.Handheld && (conMan == null || conMan.Owner != localEntity)) + if ((instrument.Handheld && (conMan == null || conMan.Owner != localEntity))) return false; - if (!_entManager.System().CanInteract(localEntity.Value, Entity)) + if (!_owner.ActionBlocker.CanInteract(localEntity.Value, instrumentEnt)) return false; // We check that we're in range unobstructed just in case. - return _entManager.System().InRangeUnobstructed(localEntity.Value, Entity); + return _owner.Interactions.InRangeUnobstructed(localEntity.Value, instrumentEnt); } private void MidiStopButtonOnPressed(ButtonEventArgs? obj) { MidiPlaybackSetButtonsDisabled(true); - _entManager.System().CloseMidi(Entity, false); - OnCloseChannels?.Invoke(); + if (_owner.Instrument is not {} instrument) + return; + + _owner.Instruments.CloseMidi(_owner.Owner, false, instrument); + _owner.CloseChannelsMenu(); } private void MidiLoopButtonOnOnToggled(ButtonToggledEventArgs obj) { - var instrument = _entManager.System(); + if (_owner.Instrument == null) + return; - if (_entManager.TryGetComponent(Entity, out InstrumentComponent? instrumentComp)) - { - instrumentComp.LoopMidi = obj.Pressed; - } - - instrument.UpdateRenderer(Entity); + _owner.Instrument.LoopMidi = obj.Pressed; + _owner.Instruments.UpdateRenderer(_owner.Owner, _owner.Instrument); } private void PlaybackSliderSeek(Range _) { // Do not seek while still grabbing. - if (PlaybackSlider.Grabbed) + if (PlaybackSlider.Grabbed || _owner.Instrument is not {} instrument) return; - _entManager.System().SetPlayerTick(Entity, (int)Math.Ceiling(PlaybackSlider.Value)); + _owner.Instruments.SetPlayerTick(_owner.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument); } private void PlaybackSliderKeyUp(GUIBoundKeyEventArgs args) { - if (args.Function != EngineKeyFunctions.UIClick) + if (args.Function != EngineKeyFunctions.UIClick || _owner.Instrument is not {} instrument) return; - _entManager.System().SetPlayerTick(Entity, (int)Math.Ceiling(PlaybackSlider.Value)); + _owner.Instruments.SetPlayerTick(_owner.Owner, (int)Math.Ceiling(PlaybackSlider.Value), instrument); + } + + public override void Close() + { + base.Close(); + _owner.CloseBandMenu(); + _owner.CloseChannelsMenu(); } protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); - if (!_entManager.TryGetComponent(Entity, out InstrumentComponent? instrument)) + if (_owner.Instrument == null) return; - var hasMaster = instrument.Master != null; + var hasMaster = _owner.Instrument.Master != null; BandButton.ToggleMode = hasMaster; BandButton.Pressed = hasMaster; - BandButton.Disabled = instrument.IsMidiOpen || instrument.IsInputOpen; - ChannelsButton.Disabled = !instrument.IsRendererAlive; + BandButton.Disabled = _owner.Instrument.IsMidiOpen || _owner.Instrument.IsInputOpen; + ChannelsButton.Disabled = !_owner.Instrument.IsRendererAlive; - if (!instrument.IsMidiOpen) + if (!_owner.Instrument.IsMidiOpen) { PlaybackSlider.MaxValue = 1; PlaybackSlider.SetValueWithoutEvent(0); @@ -279,8 +260,8 @@ namespace Content.Client.Instruments.UI if (PlaybackSlider.Grabbed) return; - PlaybackSlider.MaxValue = instrument.PlayerTotalTick; - PlaybackSlider.SetValueWithoutEvent(instrument.PlayerTick); + PlaybackSlider.MaxValue = _owner.Instrument.PlayerTotalTick; + PlaybackSlider.SetValueWithoutEvent(_owner.Instrument.PlayerTick); } } } diff --git a/Content.Client/Inventory/StrippableBoundUserInterface.cs b/Content.Client/Inventory/StrippableBoundUserInterface.cs index 132c5ed654..7e50eb1c68 100644 --- a/Content.Client/Inventory/StrippableBoundUserInterface.cs +++ b/Content.Client/Inventory/StrippableBoundUserInterface.cs @@ -41,7 +41,7 @@ namespace Content.Client.Inventory public const string HiddenPocketEntityId = "StrippingHiddenEntity"; [ViewVariables] - private StrippingMenu? _strippingMenu; + private readonly StrippingMenu? _strippingMenu; [ViewVariables] private readonly EntityUid _virtualHiddenEntity; @@ -51,30 +51,33 @@ namespace Content.Client.Inventory _examine = EntMan.System(); _inv = EntMan.System(); _cuffable = EntMan.System(); + + // 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.OnDirty += UpdateMenu; - _strippingMenu.Title = Loc.GetString("strippable-bound-user-interface-stripping-menu-title", ("ownerName", Identity.Name(Owner, EntMan))); - _strippingMenu?.OpenCenteredLeft(); } protected override void Dispose(bool disposing) { + base.Dispose(disposing); + + EntMan.DeleteEntity(_virtualHiddenEntity); + if (!disposing) return; - if (_strippingMenu != null) - _strippingMenu.OnDirty -= UpdateMenu; - - EntMan.DeleteEntity(_virtualHiddenEntity); - base.Dispose(disposing); + _strippingMenu?.Dispose(); } public void DirtyMenu() diff --git a/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs b/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs index 7884268c42..f97d8a7330 100644 --- a/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs +++ b/Content.Client/Kitchen/UI/GrinderMenu.xaml.cs @@ -12,34 +12,42 @@ namespace Content.Client.Kitchen.UI [GenerateTypedNameReferences] public sealed partial class GrinderMenu : FancyWindow { - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + private readonly IEntityManager _entityManager; + private readonly IPrototypeManager _prototypeManager; + private readonly ReagentGrinderBoundUserInterface _owner; private readonly Dictionary _chamberVisualContents = new(); - public event Action? OnToggleAuto; - public event Action? OnGrind; - public event Action? OnJuice; - public event Action? OnEjectAll; - public event Action? OnEjectBeaker; - public event Action? OnEjectChamber; - - public GrinderMenu() + public GrinderMenu(ReagentGrinderBoundUserInterface owner, IEntityManager entityManager, IPrototypeManager prototypeManager) { RobustXamlLoader.Load(this); - IoCManager.InjectDependencies(this); - AutoModeButton.OnPressed += _ => OnToggleAuto?.Invoke(); - GrindButton.OnPressed += _ => OnGrind?.Invoke(); - JuiceButton.OnPressed += _ => OnJuice?.Invoke(); - ChamberContentBox.EjectButton.OnPressed += _ => OnEjectAll?.Invoke(); - BeakerContentBox.EjectButton.OnPressed += _ => OnEjectBeaker?.Invoke(); + _entityManager = entityManager; + _prototypeManager = prototypeManager; + _owner = owner; + AutoModeButton.OnPressed += owner.ToggleAutoMode; + GrindButton.OnPressed += owner.StartGrinding; + JuiceButton.OnPressed += owner.StartJuicing; + ChamberContentBox.EjectButton.OnPressed += owner.EjectAll; + BeakerContentBox.EjectButton.OnPressed += owner.EjectBeaker; ChamberContentBox.BoxContents.OnItemSelected += OnChamberBoxContentsItemSelected; BeakerContentBox.BoxContents.SelectMode = ItemList.ItemListSelectMode.None; } private void OnChamberBoxContentsItemSelected(ItemList.ItemListSelectedEventArgs args) { - OnEjectChamber?.Invoke(_chamberVisualContents[args.ItemIndex]); + _owner.EjectChamberContent(_chamberVisualContents[args.ItemIndex]); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + _chamberVisualContents.Clear(); + GrindButton.OnPressed -= _owner.StartGrinding; + JuiceButton.OnPressed -= _owner.StartJuicing; + ChamberContentBox.EjectButton.OnPressed -= _owner.EjectAll; + BeakerContentBox.EjectButton.OnPressed -= _owner.EjectBeaker; + ChamberContentBox.BoxContents.OnItemSelected -= OnChamberBoxContentsItemSelected; } public void UpdateState(ReagentGrinderInterfaceState state) diff --git a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs index 643ac47054..7e7dd2d693 100644 --- a/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs +++ b/Content.Client/Kitchen/UI/MicrowaveBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.Kitchen.Components; using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Client.Graphics; -using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Timing; @@ -20,15 +19,28 @@ namespace Content.Client.Kitchen.UI [ViewVariables] private readonly Dictionary _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(); + } + + public TimeSpan GetCurrentTime() + { + return _gameTiming.CurTime; } protected override void Open() { base.Open(); - _menu = this.CreateWindow(); + _menu = new MicrowaveMenu(this); + _menu.OpenCentered(); + _menu.OnClose += Close; _menu.StartButton.OnPressed += _ => SendPredictedMessage(new MicrowaveStartCookMessage()); _menu.EjectButton.OnPressed += _ => SendPredictedMessage(new MicrowaveEjectMessage()); _menu.IngredientsList.OnItemSelected += args => @@ -62,23 +74,38 @@ namespace Content.Client.Kitchen.UI }; } - protected override void UpdateState(BoundUserInterfaceState state) + protected override void Dispose(bool disposing) { - base.UpdateState(state); - if (state is not MicrowaveUpdateUserInterfaceState cState || _menu == null) + base.Dispose(disposing); + + if (!disposing) { return; } - _menu.IsBusy = cState.IsMicrowaveBusy; - _menu.CurrentCooktimeEnd = cState.CurrentCookTimeEnd; + _solids.Clear(); + _menu?.Dispose(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + if (state is not MicrowaveUpdateUserInterfaceState cState) + { + return; + } + + + _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(EntMan.GetEntityArray(cState.ContainedSolids)); + RefreshContentsDisplay(_entManager.GetEntityArray(cState.ContainedSolids)); + + if (_menu == null) return; //Set the cook time info label - var cookTime = cState.ActiveButtonIndex == 0 + var cookTime = cState.ActiveButtonIndex == 0 ? Loc.GetString("microwave-menu-instant-button") : cState.CurrentCookTime.ToString(); diff --git a/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs b/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs index 7565075f86..b292e9f146 100644 --- a/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs +++ b/Content.Client/Kitchen/UI/MicrowaveMenu.xaml.cs @@ -9,20 +9,22 @@ namespace Content.Client.Kitchen.UI [GenerateTypedNameReferences] public sealed partial class MicrowaveMenu : FancyWindow { - [Dependency] private readonly IGameTiming _timing = default!; + public sealed class MicrowaveCookTimeButton : Button + { + public uint CookTime; + } public event Action? OnCookTimeSelected; public ButtonGroup CookTimeButtonGroup { get; } + private readonly MicrowaveBoundUserInterface _owner; - public bool IsBusy; - public TimeSpan CurrentCooktimeEnd; - - public MicrowaveMenu() + public MicrowaveMenu(MicrowaveBoundUserInterface owner) { RobustXamlLoader.Load(this); CookTimeButtonGroup = new ButtonGroup(); InstantCookButton.Group = CookTimeButtonGroup; + _owner = owner; InstantCookButton.OnPressed += args => { OnCookTimeSelected?.Invoke(args, 0); @@ -63,20 +65,14 @@ namespace Content.Client.Kitchen.UI protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); - - if (!IsBusy) + if(!_owner.currentState.IsMicrowaveBusy) return; - if (CurrentCooktimeEnd > _timing.CurTime) + if(_owner.currentState.CurrentCookTimeEnd > _owner.GetCurrentTime()) { CookTimeInfoLabel.Text = Loc.GetString("microwave-bound-user-interface-cook-time-label", - ("time", CurrentCooktimeEnd.Subtract(_timing.CurTime).Seconds)); + ("time",_owner.currentState.CurrentCookTimeEnd.Subtract(_owner.GetCurrentTime()).Seconds)); } } - - public sealed class MicrowaveCookTimeButton : Button - { - public uint CookTime; - } } } diff --git a/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs b/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs index bc4cc75b4d..e6f108b305 100644 --- a/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs +++ b/Content.Client/Kitchen/UI/ReagentGrinderBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Containers.ItemSlots; using Content.Shared.Kitchen; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Prototypes; @@ -9,6 +8,8 @@ namespace Content.Client.Kitchen.UI { public sealed class ReagentGrinderBoundUserInterface : BoundUserInterface { + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [ViewVariables] private GrinderMenu? _menu; @@ -20,13 +21,20 @@ namespace Content.Client.Kitchen.UI { base.Open(); - _menu = this.CreateWindow(); - _menu.OnToggleAuto += ToggleAutoMode; - _menu.OnGrind += StartGrinding; - _menu.OnJuice += StartJuicing; - _menu.OnEjectAll += EjectAll; - _menu.OnEjectBeaker += EjectBeaker; - _menu.OnEjectChamber += EjectChamberContent; + _menu = new GrinderMenu(this, EntMan, _prototypeManager); + _menu.OpenCentered(); + _menu.OnClose += Close; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + { + return; + } + + _menu?.Dispose(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -44,27 +52,27 @@ namespace Content.Client.Kitchen.UI _menu?.HandleMessage(message); } - public void ToggleAutoMode() + public void ToggleAutoMode(BaseButton.ButtonEventArgs args) { SendMessage(new ReagentGrinderToggleAutoModeMessage()); } - public void StartGrinding() + public void StartGrinding(BaseButton.ButtonEventArgs? _ = null) { SendMessage(new ReagentGrinderStartMessage(GrinderProgram.Grind)); } - public void StartJuicing() + public void StartJuicing(BaseButton.ButtonEventArgs? _ = null) { SendMessage(new ReagentGrinderStartMessage(GrinderProgram.Juice)); } - public void EjectAll() + public void EjectAll(BaseButton.ButtonEventArgs? _ = null) { SendMessage(new ReagentGrinderEjectChamberAllMessage()); } - public void EjectBeaker() + public void EjectBeaker(BaseButton.ButtonEventArgs? _ = null) { SendMessage(new ItemSlotButtonPressedEvent(SharedReagentGrinder.BeakerSlotId)); } diff --git a/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs index 6b65612341..555f1ff09e 100644 --- a/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs +++ b/Content.Client/Labels/UI/HandLabelerBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Labels; using Content.Shared.Labels.Components; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Labels.UI { @@ -24,8 +23,13 @@ namespace Content.Client.Labels.UI { base.Open(); - _window = this.CreateWindow(); + _window = new HandLabelerWindow(); + if (State != null) + UpdateState(State); + _window.OpenCentered(); + + _window.OnClose += Close; _window.OnLabelChanged += OnLabelChanged; Reload(); } @@ -47,5 +51,13 @@ namespace Content.Client.Labels.UI _window.SetCurrentLabel(component.AssignedLabel); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); + } } + } diff --git a/Content.Client/Lathe/UI/LatheBoundUserInterface.cs b/Content.Client/Lathe/UI/LatheBoundUserInterface.cs index a599f79152..6e6d1b9176 100644 --- a/Content.Client/Lathe/UI/LatheBoundUserInterface.cs +++ b/Content.Client/Lathe/UI/LatheBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Lathe; using Content.Shared.Research.Components; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Lathe.UI { @@ -18,9 +17,9 @@ namespace Content.Client.Lathe.UI { base.Open(); - _menu = this.CreateWindow(); - _menu.SetEntity(Owner); - _menu.OpenCenteredRight(); + _menu = new LatheMenu(this); + _menu.OnClose += Close; + _menu.OnServerListButtonPressed += _ => { @@ -31,6 +30,8 @@ namespace Content.Client.Lathe.UI { SendMessage(new LatheQueueRecipeMessage(recipe, amount)); }; + + _menu.OpenCenteredRight(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -49,5 +50,13 @@ namespace Content.Client.Lathe.UI break; } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Dispose(); + } } } diff --git a/Content.Client/Lathe/UI/LatheMenu.xaml.cs b/Content.Client/Lathe/UI/LatheMenu.xaml.cs index 6f530b76c7..f2f52b67b5 100644 --- a/Content.Client/Lathe/UI/LatheMenu.xaml.cs +++ b/Content.Client/Lathe/UI/LatheMenu.xaml.cs @@ -1,4 +1,3 @@ -using System.Buffers; using System.Linq; using System.Text; using Content.Client.Materials; @@ -23,6 +22,7 @@ public sealed partial class LatheMenu : DefaultWindow [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + private EntityUid _owner; private readonly SpriteSystem _spriteSystem; private readonly LatheSystem _lathe; private readonly MaterialStorageSystem _materialStorage; @@ -36,10 +36,9 @@ public sealed partial class LatheMenu : DefaultWindow public ProtoId? CurrentCategory; - public EntityUid Entity; - - public LatheMenu() + public LatheMenu(LatheBoundUserInterface owner) { + _owner = owner.Owner; RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); @@ -47,6 +46,8 @@ public sealed partial class LatheMenu : DefaultWindow _lathe = _entityManager.System(); _materialStorage = _entityManager.System(); + Title = _entityManager.GetComponent(owner.Owner).EntityName; + SearchBar.OnTextChanged += _ => { PopulateRecipes(); @@ -59,13 +60,8 @@ public sealed partial class LatheMenu : DefaultWindow FilterOption.OnItemSelected += OnItemSelected; ServerListButton.OnPressed += a => OnServerListButtonPressed?.Invoke(a); - } - public void SetEntity(EntityUid uid) - { - Entity = uid; - - if (_entityManager.TryGetComponent(Entity, out var latheComponent)) + if (_entityManager.TryGetComponent(owner.Owner, out var latheComponent)) { if (!latheComponent.DynamicRecipes.Any()) { @@ -73,7 +69,7 @@ public sealed partial class LatheMenu : DefaultWindow } } - MaterialsList.SetOwner(Entity); + MaterialsList.SetOwner(owner.Owner); } /// @@ -106,15 +102,13 @@ public sealed partial class LatheMenu : DefaultWindow var sortedRecipesToShow = recipesToShow.OrderBy(p => p.Name); RecipeList.Children.Clear(); - _entityManager.TryGetComponent(Entity, out LatheComponent? lathe); - foreach (var prototype in sortedRecipesToShow) { EntityPrototype? recipeProto = null; - if (_prototypeManager.TryIndex(prototype.Result, out EntityPrototype? entityProto)) + if (_prototypeManager.TryIndex(prototype.Result, out EntityPrototype? entityProto) && entityProto != null) recipeProto = entityProto; - var canProduce = _lathe.CanProduce(Entity, prototype, quantity, component: lathe); + var canProduce = _lathe.CanProduce(_owner, prototype, quantity); var control = new RecipeControl(prototype, () => GenerateTooltipText(prototype), canProduce, recipeProto); control.OnButtonPressed += s => @@ -130,20 +124,19 @@ public sealed partial class LatheMenu : DefaultWindow private string GenerateTooltipText(LatheRecipePrototype prototype) { StringBuilder sb = new(); - var multiplier = _entityManager.GetComponent(Entity).MaterialUseMultiplier; foreach (var (id, amount) in prototype.RequiredMaterials) { if (!_prototypeManager.TryIndex(id, out var proto)) continue; - var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, multiplier); + var adjustedAmount = SharedLatheSystem.AdjustMaterial(amount, prototype.ApplyMaterialDiscount, _entityManager.GetComponent(_owner).MaterialUseMultiplier); var sheetVolume = _materialStorage.GetSheetVolume(proto); var unit = Loc.GetString(proto.Unit); var sheets = adjustedAmount / (float) sheetVolume; - var availableAmount = _materialStorage.GetMaterialAmount(Entity, id); + var availableAmount = _materialStorage.GetMaterialAmount(_owner, id); var missingAmount = Math.Max(0, adjustedAmount - availableAmount); var missingSheets = missingAmount / (float) sheetVolume; diff --git a/Content.Client/MachineLinking/UI/SignalTimerBoundUserInterface.cs b/Content.Client/MachineLinking/UI/SignalTimerBoundUserInterface.cs index 11abe8c245..09bdedfd94 100644 --- a/Content.Client/MachineLinking/UI/SignalTimerBoundUserInterface.cs +++ b/Content.Client/MachineLinking/UI/SignalTimerBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.MachineLinking; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.Timing; namespace Content.Client.MachineLinking.UI; @@ -20,14 +19,19 @@ public sealed class SignalTimerBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.OnStartTimer += StartTimer; + _window = new SignalTimerWindow(this); + + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + _window.OnClose += Close; _window.OnCurrentTextChanged += OnTextChanged; _window.OnCurrentDelayMinutesChanged += OnDelayChanged; _window.OnCurrentDelaySecondsChanged += OnDelayChanged; } - public void StartTimer() + public void OnStartTimer() { SendMessage(new SignalTimerStartMessage()); } @@ -44,6 +48,11 @@ public sealed class SignalTimerBoundUserInterface : BoundUserInterface SendMessage(new SignalTimerDelayChangedMessage(_window.GetDelay())); } + public TimeSpan GetCurrentTime() + { + return _gameTiming.CurTime; + } + /// /// Update the UI state based on server-sent info /// @@ -63,4 +72,11 @@ public sealed class SignalTimerBoundUserInterface : BoundUserInterface _window.SetTimerStarted(cast.TimerStarted); _window.SetHasAccess(cast.HasAccess); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); + } } diff --git a/Content.Client/MachineLinking/UI/SignalTimerWindow.xaml.cs b/Content.Client/MachineLinking/UI/SignalTimerWindow.xaml.cs index 6133abfcb7..b62595595e 100644 --- a/Content.Client/MachineLinking/UI/SignalTimerWindow.xaml.cs +++ b/Content.Client/MachineLinking/UI/SignalTimerWindow.xaml.cs @@ -9,44 +9,42 @@ namespace Content.Client.MachineLinking.UI; [GenerateTypedNameReferences] public sealed partial class SignalTimerWindow : DefaultWindow { - [Dependency] private readonly IGameTiming _timing = default!; - private const int MaxTextLength = 5; public event Action? OnCurrentTextChanged; public event Action? OnCurrentDelayMinutesChanged; public event Action? OnCurrentDelaySecondsChanged; + private readonly SignalTimerBoundUserInterface _owner; + private TimeSpan? _triggerTime; private bool _timerStarted; - public event Action? OnStartTimer; - - public SignalTimerWindow() + public SignalTimerWindow(SignalTimerBoundUserInterface owner) { RobustXamlLoader.Load(this); - IoCManager.InjectDependencies(this); + + _owner = owner; CurrentTextEdit.OnTextChanged += e => OnCurrentTextChange(e.Text); CurrentDelayEditMinutes.OnTextChanged += e => OnCurrentDelayMinutesChange(e.Text); CurrentDelayEditSeconds.OnTextChanged += e => OnCurrentDelaySecondsChange(e.Text); - StartTimer.OnPressed += _ => StartTimerWeh(); + StartTimer.OnPressed += _ => OnStartTimer(); } - private void StartTimerWeh() + public void OnStartTimer() { if (!_timerStarted) { _timerStarted = true; - _triggerTime = _timing.CurTime + GetDelay(); + _triggerTime = _owner.GetCurrentTime() + GetDelay(); } else { SetTimerStarted(false); } - - OnStartTimer?.Invoke(); + _owner.OnStartTimer(); } protected override void FrameUpdate(FrameEventArgs args) @@ -56,9 +54,9 @@ public sealed partial class SignalTimerWindow : DefaultWindow if (!_timerStarted || _triggerTime == null) return; - if (_timing.CurTime < _triggerTime.Value) + if (_owner.GetCurrentTime() < _triggerTime.Value) { - StartTimer.Text = TextScreenSystem.TimeToString(_triggerTime.Value - _timing.CurTime); + StartTimer.Text = TextScreenSystem.TimeToString(_triggerTime.Value - _owner.GetCurrentTime()); } else { diff --git a/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs b/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs index 0a87948ff6..f6979bf8d7 100644 --- a/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs +++ b/Content.Client/MagicMirror/MagicMirrorBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Humanoid.Markings; using Content.Shared.MagicMirror; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.MagicMirror; @@ -18,7 +17,7 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + _window = new(); _window.OnHairSelected += tuple => SelectHair(MagicMirrorCategory.Hair, tuple.id, tuple.slot); _window.OnHairColorChanged += args => ChangeColor(MagicMirrorCategory.Hair, args.marking, args.slot); @@ -30,6 +29,9 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface args => ChangeColor(MagicMirrorCategory.FacialHair, args.marking, args.slot); _window.OnFacialHairSlotAdded += delegate () { AddSlot(MagicMirrorCategory.FacialHair); }; _window.OnFacialHairSlotRemoved += args => RemoveSlot(MagicMirrorCategory.FacialHair, args); + + _window.OnClose += Close; + _window.OpenCentered(); } private void SelectHair(MagicMirrorCategory category, string marking, int slot) @@ -63,5 +65,14 @@ public sealed class MagicMirrorBoundUserInterface : BoundUserInterface _window.UpdateState(data); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _window?.Dispose(); + } } diff --git a/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs b/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs index 22e5bc452a..80eca82e32 100644 --- a/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs +++ b/Content.Client/MassMedia/Ui/NewsWriterBoundUserInterface.cs @@ -1,7 +1,6 @@ using JetBrains.Annotations; using Content.Shared.MassMedia.Systems; using Content.Shared.MassMedia.Components; -using Robust.Client.UserInterface; using Robust.Shared.Timing; using Robust.Shared.Utility; @@ -10,6 +9,8 @@ namespace Content.Client.MassMedia.Ui; [UsedImplicitly] public sealed class NewsWriterBoundUserInterface : BoundUserInterface { + [Dependency] private readonly IGameTiming _gameTiming = default!; + [ViewVariables] private NewsWriterMenu? _menu; @@ -20,7 +21,10 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface protected override void Open() { - _menu = this.CreateWindow(); + _menu = new NewsWriterMenu(_gameTiming); + + _menu.OpenCentered(); + _menu.OnClose += Close; _menu.ArticleEditorPanel.PublishButtonPressed += OnPublishButtonPressed; _menu.DeleteButtonPressed += OnDeleteButtonPressed; @@ -28,6 +32,16 @@ public sealed class NewsWriterBoundUserInterface : BoundUserInterface SendMessage(new NewsWriterArticlesRequestMessage()); } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Close(); + _menu?.Dispose(); + } + protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); diff --git a/Content.Client/MassMedia/Ui/NewsWriterMenu.xaml.cs b/Content.Client/MassMedia/Ui/NewsWriterMenu.xaml.cs index c059ce785a..e2d57935e3 100644 --- a/Content.Client/MassMedia/Ui/NewsWriterMenu.xaml.cs +++ b/Content.Client/MassMedia/Ui/NewsWriterMenu.xaml.cs @@ -10,17 +10,17 @@ namespace Content.Client.MassMedia.Ui; [GenerateTypedNameReferences] public sealed partial class NewsWriterMenu : FancyWindow { - [Dependency] private readonly IGameTiming _gameTiming = default!; + private readonly IGameTiming _gameTiming; private TimeSpan? _nextPublish; public event Action? DeleteButtonPressed; - public NewsWriterMenu() + public NewsWriterMenu(IGameTiming gameTiming) { RobustXamlLoader.Load(this); - IoCManager.InjectDependencies(this); + _gameTiming = gameTiming; ContentsContainer.RectClipContent = false; // Customize scrollbar width and margin. This is not possible in xaml diff --git a/Content.Client/Mech/Ui/MechBoundUserInterface.cs b/Content.Client/Mech/Ui/MechBoundUserInterface.cs index 2130a8c609..4172bdc90f 100644 --- a/Content.Client/Mech/Ui/MechBoundUserInterface.cs +++ b/Content.Client/Mech/Ui/MechBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.Mech; using Content.Shared.Mech.Components; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Mech.Ui; @@ -21,8 +20,9 @@ public sealed class MechBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); - _menu.SetEntity(Owner); + _menu = new(Owner); + + _menu.OnClose += Close; _menu.OpenCenteredLeft(); _menu.OnRemoveButtonPressed += uid => @@ -60,6 +60,16 @@ public sealed class MechBoundUserInterface : BoundUserInterface } } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (!disposing) + return; + + _menu?.Close(); + } + public UIFragment? GetEquipmentUi(EntityUid? uid) { var component = EntMan.GetComponentOrNull(uid); diff --git a/Content.Client/Mech/Ui/MechMenu.xaml.cs b/Content.Client/Mech/Ui/MechMenu.xaml.cs index 6f39bc386e..fad7648808 100644 --- a/Content.Client/Mech/Ui/MechMenu.xaml.cs +++ b/Content.Client/Mech/Ui/MechMenu.xaml.cs @@ -16,15 +16,14 @@ public sealed partial class MechMenu : FancyWindow public event Action? OnRemoveButtonPressed; - public MechMenu() + public MechMenu(EntityUid mech) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); - } - public void SetEntity(EntityUid uid) - { - MechView.SetEntity(uid); + _mech = mech; + + MechView.SetEntity(mech); } public void UpdateMechStats() diff --git a/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs b/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs index b1f239cd78..3978880987 100644 --- a/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs +++ b/Content.Client/Medical/CrewMonitoring/CrewMonitoringBoundUserInterface.cs @@ -1,5 +1,4 @@ using Content.Shared.Medical.CrewMonitoring; -using Robust.Client.UserInterface; namespace Content.Client.Medical.CrewMonitoring; @@ -15,7 +14,7 @@ public sealed class CrewMonitoringBoundUserInterface : BoundUserInterface protected override void Open() { EntityUid? gridUid = null; - var stationName = string.Empty; + string stationName = string.Empty; if (EntMan.TryGetComponent(Owner, out var xform)) { @@ -27,8 +26,10 @@ public sealed class CrewMonitoringBoundUserInterface : BoundUserInterface } } - _menu = this.CreateWindow(); - _menu.Set(stationName, gridUid); + _menu = new CrewMonitoringWindow(stationName, gridUid); + + _menu.OpenCentered(); + _menu.OnClose += Close; } protected override void UpdateState(BoundUserInterfaceState state) @@ -43,4 +44,13 @@ public sealed class CrewMonitoringBoundUserInterface : BoundUserInterface break; } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Dispose(); + } } diff --git a/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs b/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs index e861864c14..863412e553 100644 --- a/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs +++ b/Content.Client/Medical/CrewMonitoring/CrewMonitoringWindow.xaml.cs @@ -23,27 +23,22 @@ namespace Content.Client.Medical.CrewMonitoring; [GenerateTypedNameReferences] public sealed partial class CrewMonitoringWindow : FancyWindow { - [Dependency] private readonly IEntityManager _entManager = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + private readonly IEntityManager _entManager; + private readonly IPrototypeManager _prototypeManager; private readonly SpriteSystem _spriteSystem; private NetEntity? _trackedEntity; private bool _tryToScrollToListFocus; private Texture? _blipTexture; - public CrewMonitoringWindow() + public CrewMonitoringWindow(string stationName, EntityUid? mapUid) { RobustXamlLoader.Load(this); - IoCManager.InjectDependencies(this); + _entManager = IoCManager.Resolve(); + _prototypeManager = IoCManager.Resolve(); _spriteSystem = _entManager.System(); - 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(mapUid, out var xform)) @@ -54,6 +49,8 @@ public sealed partial class CrewMonitoringWindow : FancyWindow StationName.AddStyleClass("LabelBig"); StationName.Text = stationName; + + NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap; NavMap.ForceNavMapUpdate(); } diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs index f85220a926..80c98f143b 100644 --- a/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs +++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Client.NetworkConfigurator.Systems; using Content.Shared.DeviceNetwork; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; namespace Content.Client.NetworkConfigurator; @@ -36,12 +35,14 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface switch (UiKey) { case NetworkConfiguratorUiKey.List: - _listMenu = this.CreateWindow(); + _listMenu = new NetworkConfiguratorListMenu(this); + _listMenu.OnClose += Close; _listMenu.ClearButton.OnPressed += _ => OnClearButtonPressed(); - _listMenu.OnRemoveAddress += OnRemoveButtonPressed; + _listMenu.OpenCenteredRight(); break; case NetworkConfiguratorUiKey.Configure: - _configurationMenu = this.CreateWindow(); + _configurationMenu = new NetworkConfiguratorConfigurationMenu(); + _configurationMenu.OnClose += Close; _configurationMenu.Set.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Set); _configurationMenu.Add.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Add); //_configurationMenu.Edit.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Edit); @@ -49,24 +50,12 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface _configurationMenu.Copy.OnPressed += _ => OnConfigButtonPressed(NetworkConfiguratorButtonKey.Copy); _configurationMenu.Show.OnPressed += OnShowPressed; _configurationMenu.Show.Pressed = _netConfig.ConfiguredListIsTracked(Owner); - _configurationMenu.OnRemoveAddress += OnRemoveButtonPressed; + _configurationMenu.OpenCentered(); break; case NetworkConfiguratorUiKey.Link: - _linkMenu = this.CreateWindow(); - _linkMenu.OnLinkDefaults += args => - { - SendMessage(new NetworkConfiguratorLinksSaveMessage(args)); - }; - - _linkMenu.OnToggleLink += (left, right) => - { - SendMessage(new NetworkConfiguratorToggleLinkMessage(left, right)); - }; - - _linkMenu.OnClearLinks += () => - { - SendMessage(new NetworkConfiguratorClearLinksMessage()); - }; + _linkMenu = new NetworkConfiguratorLinkMenu(this); + _linkMenu.OnClose += Close; + _linkMenu.OpenCentered(); break; } } @@ -94,6 +83,16 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface } } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + + _linkMenu?.Dispose(); + _listMenu?.Dispose(); + _configurationMenu?.Dispose(); + } + private void OnClearButtonPressed() { SendMessage(new NetworkConfiguratorClearDevicesMessage()); diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs index fcd2f75918..19d04cd346 100644 --- a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs +++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs @@ -9,23 +9,17 @@ namespace Content.Client.NetworkConfigurator; [GenerateTypedNameReferences] public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow { - public event Action? OnRemoveAddress; - public NetworkConfiguratorConfigurationMenu() { RobustXamlLoader.Load(this); Clear.StyleClasses.Add(StyleBase.ButtonOpenLeft); Clear.StyleClasses.Add(StyleNano.StyleClassButtonColorRed); - DeviceList.OnRemoveAddress += args => - { - OnRemoveAddress?.Invoke(args); - }; } public void UpdateState(DeviceListUserInterfaceState state) { - DeviceList.UpdateState(state.DeviceList, false); + DeviceList.UpdateState(null, state.DeviceList); Count.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count)); } diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs index e75c60058c..8cfa97dc6c 100644 --- a/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs +++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs @@ -7,19 +7,17 @@ namespace Content.Client.NetworkConfigurator; [GenerateTypedNameReferences] public sealed partial class NetworkConfiguratorDeviceList : ScrollContainer { - public event Action? OnRemoveAddress; - - public void UpdateState(HashSet<(string address, string name)> devices, bool ui) + public void UpdateState(NetworkConfiguratorBoundUserInterface? ui, HashSet<(string address, string name)> devices) { DeviceList.RemoveAllChildren(); foreach (var device in devices) { - DeviceList.AddChild(BuildDeviceListRow(device, ui)); + DeviceList.AddChild(BuildDeviceListRow(ui, device)); } } - private BoxContainer BuildDeviceListRow((string address, string name) savedDevice, bool ui) + private static BoxContainer BuildDeviceListRow(NetworkConfiguratorBoundUserInterface? ui, (string address, string name) savedDevice) { var row = new BoxContainer() { @@ -50,10 +48,10 @@ public sealed partial class NetworkConfiguratorDeviceList : ScrollContainer row.AddChild(name); row.AddChild(address); - if (ui) + if (ui != null) { row.AddChild(removeButton); - removeButton.OnPressed += _ => OnRemoveAddress?.Invoke(savedDevice.address); + removeButton.OnPressed += _ => ui.OnRemoveButtonPressed(savedDevice.address); } return row; diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs index 8cdffd16af..c04b42f249 100644 --- a/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs +++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorLinkMenu.xaml.cs @@ -18,20 +18,20 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow private readonly LinksRender _links; + private readonly List _sources = new(); private readonly List _sinks = new(); + private readonly NetworkConfiguratorBoundUserInterface _userInterface; + private (ButtonPosition position, string id, int index)? _selectedButton; private List<(string left, string right)>? _defaults; - public event Action? OnClearLinks; - public event Action? OnToggleLink; - public event Action>? OnLinkDefaults; - - public NetworkConfiguratorLinkMenu() + public NetworkConfiguratorLinkMenu(NetworkConfiguratorBoundUserInterface userInterface) { + _userInterface = userInterface; RobustXamlLoader.Load(this); var footerStyleBox = new StyleBoxFlat() @@ -52,7 +52,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow ButtonOk.OnPressed += _ => Close(); ButtonLinkDefault.OnPressed += _ => LinkDefaults(); - ButtonClear.OnPressed += _ => OnClearLinks?.Invoke(); + ButtonClear.OnPressed += _ => _userInterface.SendMessage(new NetworkConfiguratorClearLinksMessage()); } public void UpdateState(DeviceLinkUserInterfaceState linkState) @@ -98,7 +98,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow if (_defaults == default) return; - OnLinkDefaults?.Invoke(_defaults); + _userInterface.SendMessage(new NetworkConfiguratorLinksSaveMessage(_defaults)); } private Button CreateButton(ButtonPosition position, string name, string description, string id, int index) @@ -138,7 +138,7 @@ public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow var left = _selectedButton.Value.position == ButtonPosition.Left ? _selectedButton.Value.id : id; var right = _selectedButton.Value.position == ButtonPosition.Left ? id : _selectedButton.Value.id; - OnToggleLink?.Invoke(left, right); + _userInterface.SendMessage(new NetworkConfiguratorToggleLinkMessage(left, right)); args.Button.Pressed = false; diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs index 6294facaee..fb4aec1974 100644 --- a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs +++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs @@ -9,20 +9,17 @@ namespace Content.Client.NetworkConfigurator; [GenerateTypedNameReferences] public sealed partial class NetworkConfiguratorListMenu : FancyWindow { - public event Action? OnRemoveAddress; - - public NetworkConfiguratorListMenu() + private readonly NetworkConfiguratorBoundUserInterface _ui; + public NetworkConfiguratorListMenu(NetworkConfiguratorBoundUserInterface ui) { RobustXamlLoader.Load(this); - DeviceList.OnRemoveAddress += args => - { - OnRemoveAddress?.Invoke(args); - }; + + _ui = ui; } public void UpdateState(NetworkConfiguratorUserInterfaceState state) { DeviceCountLabel.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count)); - DeviceList.UpdateState(state.DeviceList, true); + DeviceList.UpdateState(_ui, state.DeviceList); } } diff --git a/Content.Client/Nuke/NukeBoundUserInterface.cs b/Content.Client/Nuke/NukeBoundUserInterface.cs index 2e15042373..59fbc5b319 100644 --- a/Content.Client/Nuke/NukeBoundUserInterface.cs +++ b/Content.Client/Nuke/NukeBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Containers.ItemSlots; using Content.Shared.Nuke; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Nuke { @@ -12,13 +11,15 @@ namespace Content.Client.Nuke [ViewVariables] private NukeMenu? _menu; - public NukeBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + public NukeBoundUserInterface([NotNull] EntityUid owner, [NotNull] Enum uiKey) : base(owner, uiKey) { } protected override void Open() { - _menu = this.CreateWindow(); + _menu = new NukeMenu(); + _menu.OpenCentered(); + _menu.OnClose += Close; _menu.OnKeypadButtonPressed += i => { @@ -61,5 +62,15 @@ namespace Content.Client.Nuke break; } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Close(); + _menu?.Dispose(); + } } } diff --git a/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs b/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs index ad4f1a75d4..ec055b3240 100644 --- a/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs +++ b/Content.Client/NukeOps/WarDeclaratorBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Chat; using Content.Shared.NukeOps; using JetBrains.Annotations; -using Robust.Client.UserInterface; using Robust.Shared.Configuration; using Robust.Shared.Timing; @@ -12,6 +11,8 @@ namespace Content.Client.NukeOps; public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface { [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly ILocalizationManager _localizationManager = default!; [ViewVariables] private WarDeclaratorWindow? _window; @@ -22,7 +23,13 @@ public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + _window = new WarDeclaratorWindow(_gameTiming, _localizationManager); + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.OnActivated += OnWarDeclaratorActivated; } @@ -35,6 +42,13 @@ public sealed class WarDeclaratorBoundUserInterface : BoundUserInterface _window?.UpdateState(cast); } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + _window?.Dispose(); + } + private void OnWarDeclaratorActivated(string message) { var maxLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength); diff --git a/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs b/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs index aeceae1327..b4a3f1c7fa 100644 --- a/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs +++ b/Content.Client/NukeOps/WarDeclaratorWindow.xaml.cs @@ -11,8 +11,7 @@ namespace Content.Client.NukeOps; [GenerateTypedNameReferences] public sealed partial class WarDeclaratorWindow : FancyWindow { - [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly ILocalizationManager _localizationManager = default!; + private readonly IGameTiming _gameTiming; public event Action? OnActivated; @@ -20,13 +19,15 @@ public sealed partial class WarDeclaratorWindow : FancyWindow private TimeSpan _shuttleDisabledTime; private WarConditionStatus _status; - public WarDeclaratorWindow() + public WarDeclaratorWindow(IGameTiming gameTiming, ILocalizationManager localizationManager) { RobustXamlLoader.Load(this); + _gameTiming = gameTiming; + WarButton.OnPressed += (_) => OnActivated?.Invoke(Rope.Collapse(MessageEdit.TextRope)); - MessageEdit.Placeholder = new Rope.Leaf(_localizationManager.GetString("war-declarator-message-placeholder")); + MessageEdit.Placeholder = new Rope.Leaf(localizationManager.GetString("war-declarator-message-placeholder")); } protected override void FrameUpdate(FrameEventArgs args) diff --git a/Content.Client/PDA/PdaBoundUserInterface.cs b/Content.Client/PDA/PdaBoundUserInterface.cs index 37ce9c4280..f8f4c67076 100644 --- a/Content.Client/PDA/PdaBoundUserInterface.cs +++ b/Content.Client/PDA/PdaBoundUserInterface.cs @@ -24,13 +24,14 @@ namespace Content.Client.PDA if (_menu == null) CreateMenu(); + + _menu?.OpenCenteredLeft(); } private void CreateMenu() { - _menu = this.CreateWindow(); - _menu.OpenCenteredLeft(); - + _menu = new PdaMenu(); + _menu.OnClose += Close; _menu.FlashLightToggleButton.OnToggled += _ => { SendMessage(new PdaToggleFlashlightMessage()); @@ -95,6 +96,7 @@ namespace Content.Client.PDA _menu?.UpdateState(updateState); } + protected override void AttachCartridgeUI(Control cartridgeUIFragment, string? title) { _menu?.ProgramView.AddChild(cartridgeUIFragment); @@ -116,6 +118,15 @@ namespace Content.Client.PDA _menu?.UpdateAvailablePrograms(programs); } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Dispose(); + } + private PdaBorderColorComponent? GetBorderColorComponent() { return EntMan.GetComponentOrNull(Owner); diff --git a/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs b/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs index 170a296ac2..a0688523f1 100644 --- a/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs +++ b/Content.Client/PDA/Ringer/RingerBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.PDA; using Content.Shared.PDA.Ringer; using JetBrains.Annotations; -using Robust.Client.UserInterface; using Robust.Shared.Timing; namespace Content.Client.PDA.Ringer @@ -19,8 +18,9 @@ namespace Content.Client.PDA.Ringer protected override void Open() { base.Open(); - _menu = this.CreateWindow(); + _menu = new RingtoneMenu(); _menu.OpenToLeft(); + _menu.OnClose += Close; _menu.TestRingerButton.OnPressed += _ => { diff --git a/Content.Client/Paper/UI/PaperBoundUserInterface.cs b/Content.Client/Paper/UI/PaperBoundUserInterface.cs index f3ad1e347e..4b0ac868f0 100644 --- a/Content.Client/Paper/UI/PaperBoundUserInterface.cs +++ b/Content.Client/Paper/UI/PaperBoundUserInterface.cs @@ -1,5 +1,4 @@ using JetBrains.Annotations; -using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Utility; using static Content.Shared.Paper.SharedPaperComponent; @@ -20,13 +19,16 @@ public sealed class PaperBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.OnSaved += InputOnTextEntered; + _window = new PaperWindow(); + _window.OnClose += Close; + _window.OnSaved += Input_OnTextEntered; if (EntMan.TryGetComponent(Owner, out var visuals)) { _window.InitVisuals(Owner, visuals); } + + _window.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -35,7 +37,7 @@ public sealed class PaperBoundUserInterface : BoundUserInterface _window?.Populate((PaperBoundUserInterfaceState) state); } - private void InputOnTextEntered(string text) + private void Input_OnTextEntered(string text) { SendMessage(new PaperInputTextMessage(text)); @@ -45,4 +47,11 @@ public sealed class PaperBoundUserInterface : BoundUserInterface _window.Input.CursorPosition = new TextEdit.CursorPos(0, TextEdit.LineBreakBias.Top); } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _window?.Dispose(); + } } diff --git a/Content.Client/Paper/UI/PaperWindow.xaml.cs b/Content.Client/Paper/UI/PaperWindow.xaml.cs index f7cace642c..7a5fd65264 100644 --- a/Content.Client/Paper/UI/PaperWindow.xaml.cs +++ b/Content.Client/Paper/UI/PaperWindow.xaml.cs @@ -17,7 +17,6 @@ namespace Content.Client.Paper.UI public sealed partial class PaperWindow : BaseWindow { [Dependency] private readonly IInputManager _inputManager = default!; - [Dependency] private readonly IResourceCache _resCache = default!; private static Color DefaultTextColor = new(25, 25, 25); @@ -86,10 +85,11 @@ namespace Content.Client.Paper.UI // Randomize the placement of any stamps based on the entity UID // so that there's some variety in different papers. StampDisplay.PlacementSeed = (int)entity; + var resCache = IoCManager.Resolve(); // Initialize the background: PaperBackground.ModulateSelfOverride = visuals.BackgroundModulate; - var backgroundImage = visuals.BackgroundImagePath != null? _resCache.GetResource(visuals.BackgroundImagePath) : null; + var backgroundImage = visuals.BackgroundImagePath != null? resCache.GetResource(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(visuals.ContentImagePath) : null; + var contentImage = visuals.ContentImagePath != null ? resCache.GetResource(visuals.ContentImagePath) : null; if (contentImage != null) { // Setup the paper content texture, but keep a reference to it, as we can't set diff --git a/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorBoundUserInterface.cs b/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorBoundUserInterface.cs index ff1eae36f5..cde5ba9ef7 100644 --- a/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorBoundUserInterface.cs +++ b/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Singularity.Components; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.ParticleAccelerator.UI { @@ -17,10 +16,9 @@ namespace Content.Client.ParticleAccelerator.UI { base.Open(); - _menu = this.CreateWindow(); - _menu.OnOverallState += SendEnableMessage; - _menu.OnPowerState += SendPowerStateMessage; - _menu.OnScanPartsRequested += SendScanPartsMessage; + _menu = new ParticleAcceleratorControlMenu(this); + _menu.OnClose += Close; + _menu.OpenCentered(); } public void SendEnableMessage(bool enable) @@ -42,5 +40,13 @@ namespace Content.Client.ParticleAccelerator.UI { _menu?.DataUpdate((ParticleAcceleratorUIState) state); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + _menu?.Dispose(); + _menu = null; + } } } diff --git a/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs b/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs index 85a5f47629..c69e027137 100644 --- a/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs +++ b/Content.Client/ParticleAccelerator/UI/ParticleAcceleratorControlMenu.cs @@ -18,11 +18,10 @@ namespace Content.Client.ParticleAccelerator.UI { public sealed class ParticleAcceleratorControlMenu : BaseWindow { - [Dependency] private readonly IPrototypeManager _protoManager = default!; - [Dependency] private readonly IResourceCache _cache = default!; - private readonly ShaderInstance _greyScaleShader; + private readonly ParticleAcceleratorBoundUserInterface _owner; + private readonly Label _drawLabel; private readonly FastNoiseLite _drawNoiseGenerator; private readonly Button _onButton; @@ -51,21 +50,19 @@ namespace Content.Client.ParticleAccelerator.UI private bool _shouldContinueAnimating; private int _maxStrength = 3; - public event Action? OnOverallState; - public event Action? OnPowerState; - public event Action? OnScanPartsRequested; - - public ParticleAcceleratorControlMenu() + public ParticleAcceleratorControlMenu(ParticleAcceleratorBoundUserInterface owner) { SetSize = new Vector2(400, 320); - _greyScaleShader = _protoManager.Index("Greyscale").Instance(); + _greyScaleShader = IoCManager.Resolve().Index("Greyscale").Instance(); + _owner = owner; _drawNoiseGenerator = new(); _drawNoiseGenerator.SetFractalType(FastNoiseLite.FractalType.FBm); _drawNoiseGenerator.SetFrequency(0.5f); - var font = _cache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13); - var panelTex = _cache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"); + var resourceCache = IoCManager.Resolve(); + var font = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13); + var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"); MouseFilter = MouseFilterMode.Stop; @@ -115,8 +112,7 @@ namespace Content.Client.ParticleAccelerator.UI Text = Loc.GetString("particle-accelerator-control-menu-off-button"), StyleClasses = { StyleBase.ButtonOpenRight }, }; - - _offButton.OnPressed += args => OnOverallState?.Invoke(false); + _offButton.OnPressed += args => owner.SendEnableMessage(false); _onButton = new Button { @@ -124,7 +120,7 @@ namespace Content.Client.ParticleAccelerator.UI Text = Loc.GetString("particle-accelerator-control-menu-on-button"), StyleClasses = { StyleBase.ButtonOpenLeft }, }; - _onButton.OnPressed += args => OnOverallState?.Invoke(true); + _onButton.OnPressed += args => owner.SendEnableMessage(true); var closeButton = new TextureButton { @@ -320,7 +316,7 @@ namespace Content.Client.ParticleAccelerator.UI } }); - _scanButton.OnPressed += args => OnScanPartsRequested?.Invoke(); + _scanButton.OnPressed += args => _owner.SendScanPartsMessage(); _alarmControl.AnimationCompleted += s => { @@ -336,7 +332,7 @@ namespace Content.Client.ParticleAccelerator.UI PASegmentControl Segment(string name) { - return new(this, _cache, name); + return new(this, resourceCache, name); } UpdateUI(false, false, false, false); @@ -372,7 +368,7 @@ namespace Content.Client.ParticleAccelerator.UI } _stateSpinBox.SetButtonDisabled(true); - OnPowerState?.Invoke(newState); + _owner.SendPowerStateMessage(newState); } protected override DragMode GetDragModeFor(Vector2 relativeMousePos) diff --git a/Content.Client/Pinpointer/UI/NavMapBeaconBoundUserInterface.cs b/Content.Client/Pinpointer/UI/NavMapBeaconBoundUserInterface.cs index 0df6787170..3ebcf7cbce 100644 --- a/Content.Client/Pinpointer/UI/NavMapBeaconBoundUserInterface.cs +++ b/Content.Client/Pinpointer/UI/NavMapBeaconBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Pinpointer; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Pinpointer.UI; @@ -17,16 +16,19 @@ public sealed class NavMapBeaconBoundUserInterface : BoundUserInterface protected override void Open() { base.Open(); - _window = this.CreateWindow(); - - if (EntMan.TryGetComponent(Owner, out NavMapBeaconComponent? beacon)) - { - _window.SetEntity(Owner, beacon); - } + _window = new NavMapBeaconWindow(Owner); + _window.OpenCentered(); + _window.OnClose += Close; _window.OnApplyButtonPressed += (label, enabled, color) => { SendMessage(new NavMapBeaconConfigureBuiMessage(label, enabled, color)); }; } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _window?.Dispose(); + } } diff --git a/Content.Client/Pinpointer/UI/NavMapBeaconWindow.xaml.cs b/Content.Client/Pinpointer/UI/NavMapBeaconWindow.xaml.cs index b77f1af047..968fe188f7 100644 --- a/Content.Client/Pinpointer/UI/NavMapBeaconWindow.xaml.cs +++ b/Content.Client/Pinpointer/UI/NavMapBeaconWindow.xaml.cs @@ -10,35 +10,36 @@ namespace Content.Client.Pinpointer.UI; [GenerateTypedNameReferences] public sealed partial class NavMapBeaconWindow : FancyWindow { + [Dependency] private readonly IEntityManager _entityManager = default!; + private string? _defaultLabel; private bool _defaultEnabled; private Color _defaultColor; public event Action? OnApplyButtonPressed; - public NavMapBeaconWindow() + public NavMapBeaconWindow(EntityUid beaconEntity) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); - - VisibleButton.OnPressed += args => UpdateVisibleButton(args.Button.Pressed); - LabelLineEdit.OnTextChanged += OnTextChanged; - ColorSelector.OnColorChanged += _ => TryEnableApplyButton(); - - TryEnableApplyButton(); - ApplyButton.OnPressed += OnApplyPressed; - } - - public void SetEntity(EntityUid uid, NavMapBeaconComponent navMap) - { + if (!_entityManager.TryGetComponent(beaconEntity, out var navMap)) + return; _defaultLabel = navMap.Text; _defaultEnabled = navMap.Enabled; _defaultColor = navMap.Color; UpdateVisibleButton(navMap.Enabled); + VisibleButton.OnPressed += args => UpdateVisibleButton(args.Button.Pressed); + LabelLineEdit.Text = navMap.Text ?? string.Empty; + LabelLineEdit.OnTextChanged += OnTextChanged; + ColorSelector.Color = navMap.Color; + ColorSelector.OnColorChanged += _ => TryEnableApplyButton(); + + TryEnableApplyButton(); + ApplyButton.OnPressed += OnApplyPressed; } private void UpdateVisibleButton(bool value) diff --git a/Content.Client/Pinpointer/UI/StationMapBoundUserInterface.cs b/Content.Client/Pinpointer/UI/StationMapBoundUserInterface.cs index 7417fafede..1483e75e73 100644 --- a/Content.Client/Pinpointer/UI/StationMapBoundUserInterface.cs +++ b/Content.Client/Pinpointer/UI/StationMapBoundUserInterface.cs @@ -1,4 +1,4 @@ -using Robust.Client.UserInterface; +using Robust.Client.GameObjects; namespace Content.Client.Pinpointer.UI; @@ -14,6 +14,7 @@ public sealed class StationMapBoundUserInterface : BoundUserInterface protected override void Open() { base.Open(); + _window?.Close(); EntityUid? gridUid = null; if (EntMan.TryGetComponent(Owner, out var xform)) @@ -21,8 +22,14 @@ public sealed class StationMapBoundUserInterface : BoundUserInterface gridUid = xform.GridUid; } - _window = this.CreateWindow(); - _window.Title = EntMan.GetComponent(Owner).EntityName; - _window.Set(gridUid, Owner); + _window = new StationMapWindow(gridUid, Owner); + _window.OpenCentered(); + _window.OnClose += Close; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _window?.Dispose(); } } diff --git a/Content.Client/Pinpointer/UI/StationMapWindow.xaml.cs b/Content.Client/Pinpointer/UI/StationMapWindow.xaml.cs index 7cbb8b7d0d..1b01fe4e30 100644 --- a/Content.Client/Pinpointer/UI/StationMapWindow.xaml.cs +++ b/Content.Client/Pinpointer/UI/StationMapWindow.xaml.cs @@ -9,18 +9,19 @@ namespace Content.Client.Pinpointer.UI; [GenerateTypedNameReferences] public sealed partial class StationMapWindow : FancyWindow { - public StationMapWindow() + public StationMapWindow(EntityUid? mapUid, EntityUid? trackedEntity) { RobustXamlLoader.Load(this); - } - - public void Set(EntityUid? mapUid, EntityUid? trackedEntity) - { NavMapScreen.MapUid = mapUid; if (trackedEntity != null) NavMapScreen.TrackedCoordinates.Add(new EntityCoordinates(trackedEntity.Value, Vector2.Zero), (true, Color.Cyan)); + if (IoCManager.Resolve().TryGetComponent(mapUid, out var metadata)) + { + Title = metadata.EntityName; + } + NavMapScreen.ForceNavMapUpdate(); } } diff --git a/Content.Client/Pinpointer/UI/UntrackedMapBoundUserInterface.cs b/Content.Client/Pinpointer/UI/UntrackedMapBoundUserInterface.cs index a3ca6f65da..57965b030a 100644 --- a/Content.Client/Pinpointer/UI/UntrackedMapBoundUserInterface.cs +++ b/Content.Client/Pinpointer/UI/UntrackedMapBoundUserInterface.cs @@ -1,4 +1,4 @@ -using Robust.Client.UserInterface; +using Robust.Client.GameObjects; namespace Content.Client.Pinpointer.UI; @@ -14,15 +14,22 @@ public sealed class UntrackedStationMapBoundUserInterface : BoundUserInterface protected override void Open() { base.Open(); + _window?.Close(); EntityUid? gridUid = null; - // TODO: What this just looks like it's been copy-pasted wholesale from StationMapBoundUserInterface? if (EntMan.TryGetComponent(Owner, out var xform)) { gridUid = xform.GridUid; } - _window = this.CreateWindow(); - _window.Set(gridUid, Owner); + _window = new StationMapWindow(gridUid, null); + _window.OpenCentered(); + _window.OnClose += Close; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _window?.Dispose(); } } diff --git a/Content.Client/Power/APC/ApcBoundUserInterface.cs b/Content.Client/Power/APC/ApcBoundUserInterface.cs index 759a5949ba..fbcbf01156 100644 --- a/Content.Client/Power/APC/ApcBoundUserInterface.cs +++ b/Content.Client/Power/APC/ApcBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.APC; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Power.APC { @@ -20,8 +19,9 @@ namespace Content.Client.Power.APC { base.Open(); - _menu = this.CreateWindow(); - _menu.OnBreaker += BreakerPressed; + _menu = new ApcMenu(this); + _menu.OnClose += Close; + _menu.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -36,5 +36,15 @@ namespace Content.Client.Power.APC { SendMessage(new ApcToggleMainBreakerMessage()); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _menu?.Dispose(); + } + } } } diff --git a/Content.Client/Power/APC/UI/ApcMenu.xaml.cs b/Content.Client/Power/APC/UI/ApcMenu.xaml.cs index 2f61ea63a8..dbf68ea07b 100644 --- a/Content.Client/Power/APC/UI/ApcMenu.xaml.cs +++ b/Content.Client/Power/APC/UI/ApcMenu.xaml.cs @@ -17,19 +17,13 @@ namespace Content.Client.Power.APC.UI [GenerateTypedNameReferences] public sealed partial class ApcMenu : FancyWindow { - public event Action? OnBreaker; - - public ApcMenu() + public ApcMenu(ApcBoundUserInterface owner) { IoCManager.InjectDependencies(this); RobustXamlLoader.Load(this); - BreakerButton.OnPressed += _ => OnBreaker?.Invoke(); - } - - public void SetEntity(EntityUid entity) - { - EntityView.SetEntity(entity); + EntityView.SetEntity(owner.Owner); + BreakerButton.OnPressed += _ => owner.BreakerPressed(); } public void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/Power/Generator/GeneratorWindow.xaml.cs b/Content.Client/Power/Generator/GeneratorWindow.xaml.cs index e975e5d466..bd5b75de1d 100644 --- a/Content.Client/Power/Generator/GeneratorWindow.xaml.cs +++ b/Content.Client/Power/Generator/GeneratorWindow.xaml.cs @@ -9,39 +9,35 @@ namespace Content.Client.Power.Generator; [GenerateTypedNameReferences] public sealed partial class GeneratorWindow : FancyWindow { + private readonly EntityUid _entity; + [Dependency] private readonly IEntityManager _entityManager = default!; [Dependency] private readonly ILocalizationManager _loc = default!; - private EntityUid _entity; + private readonly SharedPowerSwitchableSystem _switchable; + private readonly FuelGeneratorComponent? _component; + private PortableGeneratorComponentBuiState? _lastState; - public float? MaximumPower; - - public event Action? OnPower; - public event Action? OnState; - public event Action? OnSwitchOutput; - public event Action? OnEjectFuel; - - public GeneratorWindow() + public GeneratorWindow(PortableGeneratorBoundUserInterface bui, EntityUid entity) { + _entity = entity; RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + _entityManager.TryGetComponent(entity, out _component); + _switchable = _entityManager.System(); + + EntityView.SetEntity(entity); TargetPower.IsValid += IsValid; TargetPower.ValueChanged += (args) => { - OnPower?.Invoke(args.Value); + bui.SetTargetPower(args.Value); }; - StartButton.OnPressed += _ => OnState?.Invoke(true); - StopButton.OnPressed += _ => OnState?.Invoke(false); - OutputSwitchButton.OnPressed += _ => OnSwitchOutput?.Invoke(); - FuelEject.OnPressed += _ => OnEjectFuel?.Invoke(); - } - - public void SetEntity(EntityUid entity) - { - _entity = entity; - EntityView.SetEntity(entity); + StartButton.OnPressed += _ => bui.Start(); + StopButton.OnPressed += _ => bui.Stop(); + OutputSwitchButton.OnPressed += _ => bui.SwitchOutput(); + FuelEject.OnPressed += _ => bui.EjectFuel(); } private bool IsValid(int arg) @@ -49,7 +45,7 @@ public sealed partial class GeneratorWindow : FancyWindow if (arg < 0) return false; - if (arg > (MaximumPower / 1000.0f ?? 0)) + if (arg > (_lastState?.MaximumPower / 1000.0f ?? 0)) return false; return true; @@ -57,17 +53,16 @@ public sealed partial class GeneratorWindow : FancyWindow public void Update(PortableGeneratorComponentBuiState state) { - MaximumPower = state.MaximumPower; - - if (!_entityManager.TryGetComponent(_entity, out FuelGeneratorComponent? component)) + if (_component == null) return; + _lastState = state; if (!TargetPower.LineEditControl.HasKeyboardFocus()) TargetPower.OverrideValue((int)(state.TargetPower / 1000.0f)); - var efficiency = SharedGeneratorSystem.CalcFuelEfficiency(state.TargetPower, state.OptimalPower, component); + var efficiency = SharedGeneratorSystem.CalcFuelEfficiency(state.TargetPower, state.OptimalPower, _component); Efficiency.Text = efficiency.ToString("P1"); - var burnRate = component.OptimalBurnRate / efficiency; + var burnRate = _component.OptimalBurnRate / efficiency; var left = state.RemainingFuel / burnRate; Eta.Text = Loc.GetString( @@ -107,15 +102,14 @@ public sealed partial class GeneratorWindow : FancyWindow } var canSwitch = _entityManager.TryGetComponent(_entity, out PowerSwitchableComponent? switchable); - var switcher = _entityManager.System(); OutputSwitchLabel.Visible = canSwitch; OutputSwitchButton.Visible = canSwitch; if (switchable != null) { - var voltage = switcher.VoltageString(switcher.GetVoltage(_entity, switchable)); + var voltage = _switchable.VoltageString(_switchable.GetVoltage(_entity, switchable)); OutputSwitchLabel.Text = Loc.GetString("portable-generator-ui-current-output", ("voltage", voltage)); - var nextVoltage = switcher.VoltageString(switcher.GetNextVoltage(_entity, switchable)); + var nextVoltage = _switchable.VoltageString(_switchable.GetNextVoltage(_entity, switchable)); OutputSwitchButton.Text = Loc.GetString("power-switchable-switch-voltage", ("voltage", nextVoltage)); OutputSwitchButton.Disabled = state.On; } diff --git a/Content.Client/Power/Generator/PortableGeneratorBoundUserInterface.cs b/Content.Client/Power/Generator/PortableGeneratorBoundUserInterface.cs index 550e1041b6..30679d71fd 100644 --- a/Content.Client/Power/Generator/PortableGeneratorBoundUserInterface.cs +++ b/Content.Client/Power/Generator/PortableGeneratorBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Power.Generator; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Power.Generator; @@ -17,25 +16,10 @@ public sealed class PortableGeneratorBoundUserInterface : BoundUserInterface protected override void Open() { base.Open(); - _window = this.CreateWindow(); - _window.SetEntity(Owner); - _window.OnState += args => - { - if (args) - { - Start(); - } - else - { - Stop(); - } - }; - - _window.OnPower += SetTargetPower; - _window.OnEjectFuel += EjectFuel; - _window.OnSwitchOutput += SwitchOutput; + _window = new GeneratorWindow(this, Owner); _window.OpenCenteredLeft(); + _window.OnClose += Close; } protected override void UpdateState(BoundUserInterfaceState state) @@ -46,6 +30,11 @@ public sealed class PortableGeneratorBoundUserInterface : BoundUserInterface _window?.Update(msg); } + protected override void Dispose(bool disposing) + { + _window?.Dispose(); + } + public void SetTargetPower(int target) { SendMessage(new PortableGeneratorSetTargetPowerMessage(target)); diff --git a/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs b/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs index cbc343c06c..dc1dcd03ef 100644 --- a/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs +++ b/Content.Client/Power/PowerMonitoringConsoleBoundUserInterface.cs @@ -1,5 +1,4 @@ using Content.Shared.Power; -using Robust.Client.UserInterface; namespace Content.Client.Power; @@ -12,9 +11,9 @@ public sealed class PowerMonitoringConsoleBoundUserInterface : BoundUserInterfac protected override void Open() { - _menu = this.CreateWindow(); - _menu.SetEntity(Owner); - _menu.SendPowerMonitoringConsoleMessageAction += SendPowerMonitoringConsoleMessage; + _menu = new PowerMonitoringWindow(this, Owner); + _menu.OpenCentered(); + _menu.OnClose += Close; } protected override void UpdateState(BoundUserInterfaceState state) @@ -23,6 +22,9 @@ public sealed class PowerMonitoringConsoleBoundUserInterface : BoundUserInterfac var castState = (PowerMonitoringConsoleBoundInterfaceState) state; + if (castState == null) + return; + EntMan.TryGetComponent(Owner, out var xform); _menu?.ShowEntites (castState.TotalSources, @@ -38,4 +40,13 @@ public sealed class PowerMonitoringConsoleBoundUserInterface : BoundUserInterfac { SendMessage(new PowerMonitoringConsoleMessage(netEntity, group)); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + _menu?.Dispose(); + } } diff --git a/Content.Client/Power/PowerMonitoringWindow.xaml.Widgets.cs b/Content.Client/Power/PowerMonitoringWindow.xaml.Widgets.cs index d995299207..74752ddc53 100644 --- a/Content.Client/Power/PowerMonitoringWindow.xaml.Widgets.cs +++ b/Content.Client/Power/PowerMonitoringWindow.xaml.Widgets.cs @@ -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(Entity, out var console)) + if (!_entManager.TryGetComponent(_owner, out var console)) return; // Update all children @@ -379,7 +379,7 @@ public sealed class PowerMonitoringWindowEntry : PowerMonitoringWindowBaseEntry AddChild(MainContainer); - // Grid container to hold the list of sources when selected + // Grid container to hold the list of sources when selected SourcesContainer = new BoxContainer() { Orientation = LayoutOrientation.Vertical, diff --git a/Content.Client/Power/PowerMonitoringWindow.xaml.cs b/Content.Client/Power/PowerMonitoringWindow.xaml.cs index e304325248..81fe1f4d04 100644 --- a/Content.Client/Power/PowerMonitoringWindow.xaml.cs +++ b/Content.Client/Power/PowerMonitoringWindow.xaml.cs @@ -15,12 +15,13 @@ namespace Content.Client.Power; [GenerateTypedNameReferences] public sealed partial class PowerMonitoringWindow : FancyWindow { - [Dependency] private IEntityManager _entManager = default!; + private readonly IEntityManager _entManager; private readonly SpriteSystem _spriteSystem; - [Dependency] private IGameTiming _gameTiming = default!; + private readonly IGameTiming _gameTiming; private const float BlinkFrequency = 1f; + private EntityUid? _owner; private NetEntity? _focusEntity; public event Action? SendPowerMonitoringConsoleMessageAction; @@ -33,14 +34,40 @@ public sealed partial class PowerMonitoringWindow : FancyWindow { PowerMonitoringConsoleGroup.APC, (new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_triangle.png")), Color.LimeGreen) }, }; - public EntityUid Entity; - - public PowerMonitoringWindow() + public PowerMonitoringWindow(PowerMonitoringConsoleBoundUserInterface userInterface, EntityUid? owner) { RobustXamlLoader.Load(this); - IoCManager.InjectDependencies(this); + _entManager = IoCManager.Resolve(); + _gameTiming = IoCManager.Resolve(); _spriteSystem = _entManager.System(); + _owner = owner; + + // Pass owner to nav map + NavMap.Owner = _owner; + + // Set nav map grid uid + var stationName = Loc.GetString("power-monitoring-window-unknown-location"); + + if (_entManager.TryGetComponent(owner, out var xform)) + { + NavMap.MapUid = xform.GridUid; + + // Assign station name + if (_entManager.TryGetComponent(xform.GridUid, out var stationMetaData)) + stationName = stationMetaData.EntityName; + + var msg = new FormattedMessage(); + msg.AddMarkup(Loc.GetString("power-monitoring-window-station-name", ("stationName", stationName))); + + StationName.SetMessage(msg); + } + + else + { + StationName.SetMessage(stationName); + NavMap.Visible = false; + } // Set trackable entity selected action NavMap.TrackedEntitySelectedAction += SetTrackedEntityFromNavMap; @@ -61,37 +88,9 @@ public sealed partial class PowerMonitoringWindow : FancyWindow 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 = uid; - - // Set nav map grid uid - var stationName = Loc.GetString("power-monitoring-window-unknown-location"); - - if (_entManager.TryGetComponent(uid, out var xform)) - { - NavMap.MapUid = xform.GridUid; - - // Assign station name - if (_entManager.TryGetComponent(xform.GridUid, out var stationMetaData)) - stationName = stationMetaData.EntityName; - - var msg = new FormattedMessage(); - msg.AddMarkupOrThrow(Loc.GetString("power-monitoring-window-station-name", ("stationName", stationName))); - - StationName.SetMessage(msg); - } - - else - { - StationName.SetMessage(stationName); - NavMap.Visible = false; - } + // Set power monitoring message action + SendPowerMonitoringConsoleMessageAction += userInterface.SendPowerMonitoringConsoleMessage; } private void OnTabChanged(int tab) @@ -114,7 +113,10 @@ public sealed partial class PowerMonitoringWindow : FancyWindow PowerMonitoringConsoleEntry[] focusLoads, EntityCoordinates? monitorCoords) { - if (!_entManager.TryGetComponent(Entity, out var console)) + if (_owner == null) + return; + + if (!_entManager.TryGetComponent(_owner.Value, out var console)) return; // Update power status text @@ -159,13 +161,13 @@ public sealed partial class PowerMonitoringWindow : FancyWindow } // Show monitor location - var mon = _entManager.GetNetEntity(Entity); + var mon = _entManager.GetNetEntity(_owner); - if (monitorCoords != null && mon.IsValid()) + if (monitorCoords != null && mon != null) { var texture = _spriteSystem.Frame0(new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/NavMap/beveled_circle.png"))); var blip = new NavMapBlip(monitorCoords.Value, texture, Color.Cyan, true, false); - NavMap.TrackedEntities[mon] = blip; + NavMap.TrackedEntities[mon.Value] = blip; } // If the entry group doesn't match the current tab, the data is out dated, do not use it @@ -237,7 +239,7 @@ public sealed partial class PowerMonitoringWindow : FancyWindow if (netEntity == null) return; - if (!_entManager.TryGetComponent(Entity, out var console)) + if (!_entManager.TryGetComponent(_owner, out var console)) return; if (!console.PowerMonitoringDeviceMetaData.TryGetValue(netEntity.Value, out var metaData)) @@ -264,7 +266,7 @@ public sealed partial class PowerMonitoringWindow : FancyWindow { AutoScrollToFocus(); - // Warning sign pulse + // Warning sign pulse var lit = _gameTiming.RealTime.TotalSeconds % BlinkFrequency > BlinkFrequency / 2f; SystemWarningPanel.Modulate = lit ? Color.White : new Color(178, 178, 178); } diff --git a/Content.Client/RCD/RCDMenu.xaml.cs b/Content.Client/RCD/RCDMenu.xaml.cs index aefb319181..3eb0397a69 100644 --- a/Content.Client/RCD/RCDMenu.xaml.cs +++ b/Content.Client/RCD/RCDMenu.xaml.cs @@ -20,36 +20,31 @@ public sealed partial class RCDMenu : RadialMenu [Dependency] private readonly IPrototypeManager _protoManager = default!; [Dependency] private readonly IPlayerManager _playerManager = default!; - private SharedPopupSystem _popup; - private SpriteSystem _sprites; + private readonly SpriteSystem _spriteSystem; + private readonly SharedPopupSystem _popup; public event Action>? SendRCDSystemMessageAction; private EntityUid _owner; - public RCDMenu() + public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui) { IoCManager.InjectDependencies(this); RobustXamlLoader.Load(this); + _spriteSystem = _entManager.System(); _popup = _entManager.System(); - _sprites = _entManager.System(); - OnChildAdded += AddRCDMenuButtonOnClickActions; - } + _owner = owner; - public void SetEntity(EntityUid uid) - { - _owner = uid; - } - - public void Refresh() - { // Find the main radial container var main = FindControl("Main"); + if (main == null) + return; + // Populate secondary radial containers - if (!_entManager.TryGetComponent(_owner, out var rcd)) + if (!_entManager.TryGetComponent(owner, out var rcd)) return; foreach (var protoId in rcd.AvailablePrototypes) @@ -61,6 +56,10 @@ public sealed partial class RCDMenu : RadialMenu continue; var parent = FindControl(proto.Category); + + if (parent == null) + continue; + var tooltip = Loc.GetString(proto.SetName); if ((proto.Mode == RcdMode.ConstructTile || proto.Mode == RcdMode.ConstructObject) && @@ -85,7 +84,7 @@ public sealed partial class RCDMenu : RadialMenu { VerticalAlignment = VAlignment.Center, HorizontalAlignment = HAlignment.Center, - Texture = _sprites.Frame0(proto.Sprite), + Texture = _spriteSystem.Frame0(proto.Sprite), TextureScale = new Vector2(2f, 2f), }; @@ -113,9 +112,11 @@ public sealed partial class RCDMenu : RadialMenu // Set up menu actions foreach (var child in Children) - { AddRCDMenuButtonOnClickActions(child); - } + + OnChildAdded += AddRCDMenuButtonOnClickActions; + + SendRCDSystemMessageAction += bui.SendRCDSystemMessage; } private static string OopsConcat(string a, string b) diff --git a/Content.Client/RCD/RCDMenuBoundUserInterface.cs b/Content.Client/RCD/RCDMenuBoundUserInterface.cs index 1dd03626ae..a37dbcecf8 100644 --- a/Content.Client/RCD/RCDMenuBoundUserInterface.cs +++ b/Content.Client/RCD/RCDMenuBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.RCD.Components; using JetBrains.Annotations; using Robust.Client.Graphics; using Robust.Client.Input; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client.RCD; @@ -25,9 +24,8 @@ public sealed class RCDMenuBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); - _menu.SetEntity(Owner); - _menu.SendRCDSystemMessageAction += SendRCDSystemMessage; + _menu = new(Owner, this); + _menu.OnClose += Close; // Open the menu, centered on the mouse var vpSize = _displayManager.ScreenSize; @@ -36,8 +34,16 @@ public sealed class RCDMenuBoundUserInterface : BoundUserInterface public void SendRCDSystemMessage(ProtoId 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(); + } } diff --git a/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs b/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs index 401e7edd44..7b3e39aa08 100644 --- a/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs +++ b/Content.Client/Radio/Ui/IntercomBoundUserInterface.cs @@ -1,8 +1,6 @@ using Content.Shared.Radio; using Content.Shared.Radio.Components; using JetBrains.Annotations; -using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Radio.Ui; @@ -21,12 +19,9 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + var comp = EntMan.GetComponent(Owner); - if (EntMan.TryGetComponent(Owner, out IntercomComponent? intercom)) - { - _menu.Update((Owner, intercom)); - } + _menu = new((Owner, comp)); _menu.OnMicPressed += enabled => { @@ -40,6 +35,17 @@ public sealed class IntercomBoundUserInterface : BoundUserInterface { SendMessage(new SelectIntercomChannelMessage(channel)); }; + + _menu.OnClose += Close; + _menu.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Close(); } public void Update(Entity ent) diff --git a/Content.Client/Radio/Ui/IntercomMenu.xaml.cs b/Content.Client/Radio/Ui/IntercomMenu.xaml.cs index 20d2e4a3e5..2e08913051 100644 --- a/Content.Client/Radio/Ui/IntercomMenu.xaml.cs +++ b/Content.Client/Radio/Ui/IntercomMenu.xaml.cs @@ -18,13 +18,15 @@ public sealed partial class IntercomMenu : FancyWindow private readonly List _channels = new(); - public IntercomMenu() + public IntercomMenu(Entity entity) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); MicButton.OnPressed += args => OnMicPressed?.Invoke(args.Button.Pressed); SpeakerButton.OnPressed += args => OnSpeakerPressed?.Invoke(args.Button.Pressed); + + Update(entity); } public void Update(Entity entity) diff --git a/Content.Client/Research/UI/DiskConsoleBoundUserInterface.cs b/Content.Client/Research/UI/DiskConsoleBoundUserInterface.cs index 9641adb5b2..c14a8c5bd0 100644 --- a/Content.Client/Research/UI/DiskConsoleBoundUserInterface.cs +++ b/Content.Client/Research/UI/DiskConsoleBoundUserInterface.cs @@ -1,7 +1,5 @@ using Content.Shared.Research; using Content.Shared.Research.Components; -using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Research.UI { @@ -18,7 +16,10 @@ namespace Content.Client.Research.UI { base.Open(); - _menu = this.CreateWindow(); + _menu = new(); + + _menu.OnClose += Close; + _menu.OpenCentered(); _menu.OnServerButtonPressed += () => { @@ -30,6 +31,14 @@ namespace Content.Client.Research.UI }; } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Close(); + } + protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); diff --git a/Content.Client/Research/UI/ResearchClientBoundUserInterface.cs b/Content.Client/Research/UI/ResearchClientBoundUserInterface.cs index 288445e4de..a0a2b58e88 100644 --- a/Content.Client/Research/UI/ResearchClientBoundUserInterface.cs +++ b/Content.Client/Research/UI/ResearchClientBoundUserInterface.cs @@ -1,6 +1,4 @@ using Content.Shared.Research.Components; -using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Research.UI { @@ -17,9 +15,10 @@ namespace Content.Client.Research.UI protected override void Open() { base.Open(); - _menu = this.CreateWindow(); - _menu.OnServerSelected += SelectServer; - _menu.OnServerDeselected += DeselectServer; + + _menu = new ResearchClientServerSelectionMenu(this); + _menu.OnClose += Close; + _menu.OpenCentered(); } public void SelectServer(int serverId) @@ -38,5 +37,12 @@ namespace Content.Client.Research.UI if (state is not ResearchClientBoundInterfaceState rState) return; _menu?.Populate(rState.ServerCount, rState.ServerNames, rState.ServerIds, rState.SelectedServerId); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) return; + _menu?.Dispose(); + } } } diff --git a/Content.Client/Research/UI/ResearchClientServerSelectionMenu.xaml.cs b/Content.Client/Research/UI/ResearchClientServerSelectionMenu.xaml.cs index d10f8b39f4..ceaa965e59 100644 --- a/Content.Client/Research/UI/ResearchClientServerSelectionMenu.xaml.cs +++ b/Content.Client/Research/UI/ResearchClientServerSelectionMenu.xaml.cs @@ -13,26 +13,27 @@ namespace Content.Client.Research.UI private int[] _serverIds = Array.Empty(); private int _selectedServerId = -1; - public event Action? OnServerSelected; - public event Action? OnServerDeselected; + private ResearchClientBoundUserInterface Owner { get; } - public ResearchClientServerSelectionMenu() + public ResearchClientServerSelectionMenu(ResearchClientBoundUserInterface owner) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); + Owner = owner; + Servers.OnItemSelected += OnItemSelected; Servers.OnItemDeselected += OnItemDeselected; } public void OnItemSelected(ItemList.ItemListSelectedEventArgs itemListSelectedEventArgs) { - OnServerSelected?.Invoke(_serverIds[itemListSelectedEventArgs.ItemIndex]); + Owner.SelectServer(_serverIds[itemListSelectedEventArgs.ItemIndex]); } public void OnItemDeselected(ItemList.ItemListDeselectedEventArgs itemListDeselectedEventArgs) { - OnServerDeselected?.Invoke(); + Owner.DeselectServer(); } public void Populate(int serverCount, string[] serverNames, int[] serverIds, int selectedServerId) diff --git a/Content.Client/Research/UI/ResearchConsoleBoundUserInterface.cs b/Content.Client/Research/UI/ResearchConsoleBoundUserInterface.cs index 2895ada61f..2a9782045b 100644 --- a/Content.Client/Research/UI/ResearchConsoleBoundUserInterface.cs +++ b/Content.Client/Research/UI/ResearchConsoleBoundUserInterface.cs @@ -1,8 +1,5 @@ using Content.Shared.Research.Components; -using Content.Shared.Research.Prototypes; using JetBrains.Annotations; -using Robust.Client.UserInterface; -using Robust.Shared.Prototypes; namespace Content.Client.Research.UI; @@ -22,8 +19,7 @@ public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface var owner = Owner; - _consoleMenu = this.CreateWindow(); - _consoleMenu.SetEntity(owner); + _consoleMenu = new ResearchConsoleMenu(owner); _consoleMenu.OnTechnologyCardPressed += id => { @@ -34,20 +30,10 @@ public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface { SendMessage(new ConsoleServerSelectionMessage()); }; - } - public override void OnProtoReload(PrototypesReloadedEventArgs args) - { - base.OnProtoReload(args); + _consoleMenu.OnClose += Close; - if (!args.WasModified()) - return; - - if (State is not ResearchConsoleBoundInterfaceState rState) - return; - - _consoleMenu?.UpdatePanels(rState); - _consoleMenu?.UpdateInformationPanel(rState); + _consoleMenu.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -59,4 +45,12 @@ public sealed class ResearchConsoleBoundUserInterface : BoundUserInterface _consoleMenu?.UpdatePanels(castState); _consoleMenu?.UpdateInformationPanel(castState); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _consoleMenu?.Dispose(); + } } diff --git a/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs b/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs index eafbe75fbb..77ebe6740c 100644 --- a/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs +++ b/Content.Client/Research/UI/ResearchConsoleMenu.xaml.cs @@ -25,13 +25,14 @@ public sealed partial class ResearchConsoleMenu : FancyWindow [Dependency] private readonly IEntityManager _entity = default!; [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly IPlayerManager _player = default!; + private readonly TechnologyDatabaseComponent? _technologyDatabase; private readonly ResearchSystem _research; private readonly SpriteSystem _sprite; private readonly AccessReaderSystem _accessReader; - public EntityUid Entity; + public readonly EntityUid Entity; - public ResearchConsoleMenu() + public ResearchConsoleMenu(EntityUid entity) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); @@ -39,23 +40,21 @@ public sealed partial class ResearchConsoleMenu : FancyWindow _research = _entity.System(); _sprite = _entity.System(); _accessReader = _entity.System(); + 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 (!_entity.TryGetComponent(Entity, out TechnologyDatabaseComponent? database)) + if (_technologyDatabase == null) return; // i can't figure out the spacing so here you go @@ -67,7 +66,7 @@ public sealed partial class ResearchConsoleMenu : FancyWindow var hasAccess = _player.LocalEntity is not { } local || !_entity.TryGetComponent(Entity, out var access) || _accessReader.IsAllowed(local, Entity, access); - foreach (var techId in database.CurrentTechnologyCards) + foreach (var techId in _technologyDatabase.CurrentTechnologyCards) { var tech = _prototype.Index(techId); var cardControl = new TechnologyCardControl(tech, _prototype, _sprite, _research.GetTechnologyDescription(tech, includeTier: false), state.Points, hasAccess); @@ -75,7 +74,7 @@ public sealed partial class ResearchConsoleMenu : FancyWindow TechnologyCardsContainer.AddChild(cardControl); } - var unlockedTech = database.UnlockedTechnologies.Select(x => _prototype.Index(x)); + var unlockedTech = _technologyDatabase.UnlockedTechnologies.Select(x => _prototype.Index(x)); SyncTechnologyList(UnlockedCardsContainer, unlockedTech); } @@ -86,14 +85,14 @@ public sealed partial class ResearchConsoleMenu : FancyWindow ("points", state.Points))); ResearchAmountLabel.SetMessage(amountMsg); - if (!_entity.TryGetComponent(Entity, out TechnologyDatabaseComponent? database)) + if (_technologyDatabase == null) return; var disciplineText = Loc.GetString("research-discipline-none"); var disciplineColor = Color.Gray; - if (database.MainDiscipline != null) + if (_technologyDatabase.MainDiscipline != null) { - var discipline = _prototype.Index(database.MainDiscipline); + var discipline = _prototype.Index(_technologyDatabase.MainDiscipline); disciplineText = Loc.GetString(discipline.Name); disciplineColor = discipline.Color; } @@ -104,10 +103,10 @@ public sealed partial class ResearchConsoleMenu : FancyWindow MainDisciplineLabel.SetMessage(msg); TierDisplayContainer.Children.Clear(); - foreach (var disciplineId in database.SupportedDisciplines) + foreach (var disciplineId in _technologyDatabase.SupportedDisciplines) { var discipline = _prototype.Index(disciplineId); - var tier = _research.GetHighestDisciplineTier(database, discipline); + var tier = _research.GetHighestDisciplineTier(_technologyDatabase, discipline); // don't show tiers with no available tech if (tier == 0) diff --git a/Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs b/Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs index 9a5159880f..6185979eee 100644 --- a/Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs +++ b/Content.Client/Robotics/UI/RoboticsConsoleBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Robotics; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Robotics.UI; @@ -17,9 +16,7 @@ public sealed class RoboticsConsoleBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.SetEntity(Owner); - + _window = new RoboticsConsoleWindow(Owner); _window.OnDisablePressed += address => { SendMessage(new RoboticsConsoleDisableMessage(address)); @@ -28,6 +25,9 @@ public sealed class RoboticsConsoleBoundUserInterface : BoundUserInterface { SendMessage(new RoboticsConsoleDestroyMessage(address)); }; + _window.OnClose += Close; + + _window.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -37,6 +37,14 @@ public sealed class RoboticsConsoleBoundUserInterface : BoundUserInterface if (state is not RoboticsConsoleState cast) return; - _window.UpdateState(cast); + _window?.UpdateState(cast); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + _window?.Dispose(); } } diff --git a/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs b/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs index 87d7e62c39..fc7b234bcc 100644 --- a/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs +++ b/Content.Client/Robotics/UI/RoboticsConsoleWindow.xaml.cs @@ -23,12 +23,11 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow public Action? OnDisablePressed; public Action? OnDestroyPressed; + private Entity _console; private string? _selected; private Dictionary _cyborgs = new(); - public EntityUid Entity; - - public RoboticsConsoleWindow() + public RoboticsConsoleWindow(EntityUid console) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); @@ -36,6 +35,9 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow _lock = _entMan.System(); _sprite = _entMan.System(); + _console = (console, _entMan.GetComponent(console), null); + _entMan.TryGetComponent(_console, out _console.Comp2); + Cyborgs.OnItemSelected += args => { if (Cyborgs[args.ItemIndex].Metadata is not string address) @@ -64,11 +66,6 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow DestroyButton.StyleClasses.Add(StyleBase.ButtonCaution); } - public void SetEntity(EntityUid uid) - { - Entity = uid; - } - public void UpdateState(RoboticsConsoleState state) { _cyborgs = state.Cyborgs; @@ -84,7 +81,7 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow PopulateData(); - var locked = _lock.IsLocked(Entity); + var locked = _lock.IsLocked((_console, _console.Comp2)); DangerZone.Visible = !locked; LockedMessage.Visible = locked; } @@ -138,19 +135,13 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow // how the turntables DisableButton.Disabled = !(data.HasBrain && data.CanDisable); + DestroyButton.Disabled = _timing.CurTime < _console.Comp1.NextDestroy; } protected override void FrameUpdate(FrameEventArgs args) { base.FrameUpdate(args); - if (_entMan.TryGetComponent(Entity, out RoboticsConsoleComponent? console)) - { - DestroyButton.Disabled = _timing.CurTime < console.NextDestroy; - } - else - { - DestroyButton.Disabled = true; - } + DestroyButton.Disabled = _timing.CurTime < _console.Comp1.NextDestroy; } } diff --git a/Content.Client/Salvage/UI/SalvageExpeditionConsoleBoundUserInterface.cs b/Content.Client/Salvage/UI/SalvageExpeditionConsoleBoundUserInterface.cs index 663bde15b0..8f1723d1f2 100644 --- a/Content.Client/Salvage/UI/SalvageExpeditionConsoleBoundUserInterface.cs +++ b/Content.Client/Salvage/UI/SalvageExpeditionConsoleBoundUserInterface.cs @@ -30,9 +30,17 @@ public sealed class SalvageExpeditionConsoleBoundUserInterface : BoundUserInterf protected override void Open() { base.Open(); - _window = this.CreateWindow(); + _window = new OfferingWindow(); _window.Title = Loc.GetString("salvage-expedition-window-title"); - _window.OpenCenteredLeft(); + _window.OnClose += Close; + _window?.OpenCenteredLeft(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _window?.Dispose(); + _window = null; } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/Salvage/UI/SalvageMagnetBoundUserInterface.cs b/Content.Client/Salvage/UI/SalvageMagnetBoundUserInterface.cs index a248126a85..eafb692733 100644 --- a/Content.Client/Salvage/UI/SalvageMagnetBoundUserInterface.cs +++ b/Content.Client/Salvage/UI/SalvageMagnetBoundUserInterface.cs @@ -21,9 +21,13 @@ public sealed class SalvageMagnetBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.Title = Loc.GetString("salvage-magnet-window-title"); - _window.OpenCenteredLeft(); + if (_window is null) + { + _window = new OfferingWindow(); + _window.Title = Loc.GetString("salvage-magnet-window-title"); + _window.OnClose += Close; + _window.OpenCenteredLeft(); + } } protected override void UpdateState(BoundUserInterfaceState state) @@ -108,4 +112,15 @@ public sealed class SalvageMagnetBoundUserInterface : BoundUserInterface _window.AddOption(option); } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (disposing) + { + _window?.Close(); + _window?.Dispose(); + } + } } diff --git a/Content.Client/Shuttles/BUI/IFFConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/IFFConsoleBoundUserInterface.cs index b8b4fb8a74..086369aa26 100644 --- a/Content.Client/Shuttles/BUI/IFFConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/IFFConsoleBoundUserInterface.cs @@ -3,7 +3,6 @@ using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Events; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Shuttles.BUI; @@ -21,7 +20,8 @@ public sealed class IFFConsoleBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + _window = new IFFConsoleWindow(); + _window.OnClose += Close; _window.ShowIFF += SendIFFMessage; _window.ShowVessel += SendVesselMessage; _window.OpenCenteredLeft(); diff --git a/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs index f75759b042..4bd44a47a8 100644 --- a/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/RadarConsoleBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Client.Shuttles.UI; using Content.Shared.Shuttles.BUIStates; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using RadarConsoleWindow = Content.Client.Shuttles.UI.RadarConsoleWindow; namespace Content.Client.Shuttles.BUI; @@ -21,7 +20,18 @@ public sealed class RadarConsoleBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + _window = new RadarConsoleWindow(); + _window.OnClose += Close; + _window.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + { + _window?.Dispose(); + } } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs index e677181419..af7b6055c8 100644 --- a/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs +++ b/Content.Client/Shuttles/BUI/ShuttleConsoleBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Client.Shuttles.UI; using Content.Shared.Shuttles.BUIStates; using Content.Shared.Shuttles.Events; using JetBrains.Annotations; -using Robust.Client.UserInterface; using Robust.Shared.Map; namespace Content.Client.Shuttles.BUI; @@ -20,7 +19,9 @@ public sealed class ShuttleConsoleBoundUserInterface : BoundUserInterface protected override void Open() { base.Open(); - _window = this.CreateWindow(); + _window = new ShuttleConsoleWindow(); + _window.OpenCentered(); + _window.OnClose += Close; _window.RequestFTL += OnFTLRequest; _window.RequestBeaconFTL += OnFTLBeaconRequest; diff --git a/Content.Client/Silicons/Borgs/BorgBoundUserInterface.cs b/Content.Client/Silicons/Borgs/BorgBoundUserInterface.cs index ed9bf40a48..3cc2a35d79 100644 --- a/Content.Client/Silicons/Borgs/BorgBoundUserInterface.cs +++ b/Content.Client/Silicons/Borgs/BorgBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Silicons.Borgs; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Silicons.Borgs; @@ -19,8 +18,9 @@ public sealed class BorgBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); - _menu.SetEntity(Owner); + var owner = Owner; + + _menu = new BorgMenu(owner); _menu.BrainButtonPressed += () => { @@ -41,6 +41,10 @@ public sealed class BorgBoundUserInterface : BoundUserInterface { SendMessage(new BorgRemoveModuleBuiMessage(EntMan.GetNetEntity(module))); }; + + _menu.OnClose += Close; + + _menu.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -51,4 +55,12 @@ public sealed class BorgBoundUserInterface : BoundUserInterface return; _menu?.UpdateState(msg); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Dispose(); + } } diff --git a/Content.Client/Silicons/Borgs/BorgMenu.xaml b/Content.Client/Silicons/Borgs/BorgMenu.xaml index 4cc2e41a8f..7d8fd9fe57 100644 --- a/Content.Client/Silicons/Borgs/BorgMenu.xaml +++ b/Content.Client/Silicons/Borgs/BorgMenu.xaml @@ -10,7 +10,7 @@ VerticalExpand="True"> - + diff --git a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs index f6a861aa05..474a83b453 100644 --- a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs +++ b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs @@ -21,33 +21,25 @@ public sealed partial class BorgMenu : FancyWindow public Action? NameChanged; public Action? RemoveModuleButtonPressed; + private readonly BorgChassisComponent? _chassis; + public readonly EntityUid Entity; public float AccumulatedTime; private string _lastValidName; private List _modules = new(); - public EntityUid Entity; - - public BorgMenu() + public BorgMenu(EntityUid entity) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); - _lastValidName = NameLineEdit.Text; - - EjectBatteryButton.OnPressed += _ => EjectBatteryButtonPressed?.Invoke(); - BrainButton.OnPressed += _ => BrainButtonPressed?.Invoke(); - - NameLineEdit.OnTextChanged += OnNameChanged; - NameLineEdit.OnTextEntered += OnNameEntered; - NameLineEdit.OnFocusExit += OnNameFocusExit; - - UpdateBrainButton(); - } - - public void SetEntity(EntityUid entity) - { Entity = entity; + + if (_entity.TryGetComponent(Entity, out var chassis)) + _chassis = chassis; + BorgSprite.SetEntity(entity); + ChargeBar.MaxValue = 1f; + ChargeBar.Value = 1f; if (_entity.TryGetComponent(Entity, out var nameIdentifierComponent)) { @@ -63,6 +55,17 @@ public sealed partial class BorgMenu : FancyWindow NameIdentifierLabel.Visible = false; NameLineEdit.Text = _entity.GetComponent(Entity).EntityName; } + + _lastValidName = NameLineEdit.Text; + + EjectBatteryButton.OnPressed += _ => EjectBatteryButtonPressed?.Invoke(); + BrainButton.OnPressed += _ => BrainButtonPressed?.Invoke(); + + NameLineEdit.OnTextChanged += OnNameChanged; + NameLineEdit.OnTextEntered += OnNameEntered; + NameLineEdit.OnFocusExit += OnNameFocusExit; + + UpdateBrainButton(); } protected override void FrameUpdate(FrameEventArgs args) @@ -86,7 +89,7 @@ public sealed partial class BorgMenu : FancyWindow private void UpdateBrainButton() { - if (_entity.TryGetComponent(Entity, out BorgChassisComponent? chassis) && chassis.BrainEntity is { } brain) + if (_chassis?.BrainEntity is { } brain) { BrainButton.Text = _entity.GetComponent(brain).EntityName; BrainView.Visible = true; @@ -105,17 +108,17 @@ public sealed partial class BorgMenu : FancyWindow private void UpdateModulePanel() { - if (!_entity.TryGetComponent(Entity, out BorgChassisComponent? chassis)) + if (_chassis == null) return; ModuleCounter.Text = Loc.GetString("borg-ui-module-counter", - ("actual", chassis.ModuleCount), - ("max", chassis.MaxModules)); + ("actual", _chassis.ModuleCount), + ("max", _chassis.MaxModules)); - if (chassis.ModuleContainer.Count == _modules.Count) + if (_chassis.ModuleContainer.Count == _modules.Count) { var isSame = true; - foreach (var module in chassis.ModuleContainer.ContainedEntities) + foreach (var module in _chassis.ModuleContainer.ContainedEntities) { if (_modules.Contains(module)) continue; @@ -129,7 +132,7 @@ public sealed partial class BorgMenu : FancyWindow ModuleContainer.Children.Clear(); _modules.Clear(); - foreach (var module in chassis.ModuleContainer.ContainedEntities) + foreach (var module in _chassis.ModuleContainer.ContainedEntities) { var control = new BorgModuleControl(module, _entity); control.RemoveButtonPressed += () => diff --git a/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs b/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs index 56216b9184..d150735fa1 100644 --- a/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs +++ b/Content.Client/Silicons/Laws/Ui/SiliconLawBoundUserInterface.cs @@ -2,7 +2,6 @@ using System.Linq; using Content.Shared.Silicons.Laws; using Content.Shared.Silicons.Laws.Components; using JetBrains.Annotations; -using Robust.Client.UserInterface; namespace Content.Client.Silicons.Laws.Ui; @@ -23,7 +22,18 @@ public sealed class SiliconLawBoundUserInterface : BoundUserInterface { base.Open(); - _menu = this.CreateWindow(); + _menu = new(); + + _menu.OnClose += Close; + _menu.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Close(); } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/SprayPainter/UI/SprayPainterBoundUserInterface.cs b/Content.Client/SprayPainter/UI/SprayPainterBoundUserInterface.cs index 7d6a6cf2a5..e8442d2390 100644 --- a/Content.Client/SprayPainter/UI/SprayPainterBoundUserInterface.cs +++ b/Content.Client/SprayPainter/UI/SprayPainterBoundUserInterface.cs @@ -1,6 +1,6 @@ using Content.Shared.SprayPainter; using Content.Shared.SprayPainter.Components; -using Robust.Client.UserInterface; +using Robust.Client.GameObjects; using Robust.Client.UserInterface.Controls; namespace Content.Client.SprayPainter.UI; @@ -10,6 +10,9 @@ public sealed class SprayPainterBoundUserInterface : BoundUserInterface [ViewVariables] private SprayPainterWindow? _window; + [ViewVariables] + private SprayPainterSystem? _painter; + public SprayPainterBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) { } @@ -18,15 +21,27 @@ public sealed class SprayPainterBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + if (!EntMan.TryGetComponent(Owner, out var comp)) + return; + _window = new SprayPainterWindow(); + + _painter = EntMan.System(); + + _window.OnClose += Close; _window.OnSpritePicked = OnSpritePicked; _window.OnColorPicked = OnColorPicked; - if (EntMan.TryGetComponent(Owner, out SprayPainterComponent? comp)) - { - _window.Populate(EntMan.System().Entries, comp.Index, comp.PickedColor, comp.ColorPalette); - } + _window.Populate(_painter.Entries, comp.Index, comp.PickedColor, comp.ColorPalette); + + _window.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + _window?.Dispose(); } private void OnSpritePicked(ItemList.ItemListSelectedEventArgs args) diff --git a/Content.Client/StationRecords/GeneralStationRecordConsoleBoundUserInterface.cs b/Content.Client/StationRecords/GeneralStationRecordConsoleBoundUserInterface.cs index e7bab71e38..720a2efb9d 100644 --- a/Content.Client/StationRecords/GeneralStationRecordConsoleBoundUserInterface.cs +++ b/Content.Client/StationRecords/GeneralStationRecordConsoleBoundUserInterface.cs @@ -1,5 +1,4 @@ using Content.Shared.StationRecords; -using Robust.Client.UserInterface; namespace Content.Client.StationRecords; @@ -16,12 +15,15 @@ public sealed class GeneralStationRecordConsoleBoundUserInterface : BoundUserInt { base.Open(); - _window = this.CreateWindow(); + _window = new(); _window.OnKeySelected += key => SendMessage(new SelectStationRecord(key)); _window.OnFiltersChanged += (type, filterValue) => SendMessage(new SetStationRecordFilter(type, filterValue)); _window.OnDeleted += id => SendMessage(new DeleteStationRecord(id)); + _window.OnClose += Close; + + _window.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) @@ -33,4 +35,11 @@ public sealed class GeneralStationRecordConsoleBoundUserInterface : BoundUserInt _window?.UpdateState(cast); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + _window?.Close(); + } } diff --git a/Content.Client/Store/Ui/StoreBoundUserInterface.cs b/Content.Client/Store/Ui/StoreBoundUserInterface.cs index 7ed67f7b5d..0010aedd96 100644 --- a/Content.Client/Store/Ui/StoreBoundUserInterface.cs +++ b/Content.Client/Store/Ui/StoreBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Shared.Store; using JetBrains.Annotations; using System.Linq; using Content.Shared.Store.Components; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client.Store.Ui; @@ -27,10 +26,13 @@ public sealed class StoreBoundUserInterface : BoundUserInterface protected override void Open() { - _menu = this.CreateWindow(); + _menu = new StoreMenu(); if (EntMan.TryGetComponent(Owner, out var store)) _menu.Title = Loc.GetString(store.Name); + _menu.OpenCentered(); + _menu.OnClose += Close; + _menu.OnListingButtonPressed += (_, listing) => { SendMessage(new StoreBuyListingMessage(listing)); @@ -75,6 +77,15 @@ public sealed class StoreBoundUserInterface : BoundUserInterface } } + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + _menu?.Close(); + _menu?.Dispose(); + } + private void UpdateListingsWithSearchFilter() { if (_menu == null) diff --git a/Content.Client/Strip/StrippingMenu.cs b/Content.Client/Strip/StrippingMenu.cs index 1c46b4be35..eea867b794 100644 --- a/Content.Client/Strip/StrippingMenu.cs +++ b/Content.Client/Strip/StrippingMenu.cs @@ -1,3 +1,4 @@ +using Content.Client.Inventory; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.Timing; @@ -10,12 +11,14 @@ namespace Content.Client.Strip public LayoutContainer InventoryContainer = new(); public BoxContainer HandsContainer = new() { Orientation = LayoutOrientation.Horizontal }; public BoxContainer SnareContainer = new(); + private StrippableBoundUserInterface _bui; public bool Dirty = true; - public event Action? OnDirty; - - public StrippingMenu() + public StrippingMenu(string title, StrippableBoundUserInterface bui) { + Title = title; + _bui = bui; + var box = new BoxContainer() { Orientation = LayoutOrientation.Vertical, Margin = new Thickness(0, 8) }; Contents.AddChild(box); box.AddChild(SnareContainer); @@ -36,7 +39,7 @@ namespace Content.Client.Strip return; Dirty = false; - OnDirty?.Invoke(); + _bui.UpdateMenu(); } } } diff --git a/Content.Client/SurveillanceCamera/UI/SurveillanceCameraMonitorBoundUi.cs b/Content.Client/SurveillanceCamera/UI/SurveillanceCameraMonitorBoundUi.cs index e3646c00cc..9132dd6ed5 100644 --- a/Content.Client/SurveillanceCamera/UI/SurveillanceCameraMonitorBoundUi.cs +++ b/Content.Client/SurveillanceCamera/UI/SurveillanceCameraMonitorBoundUi.cs @@ -1,7 +1,6 @@ using Content.Client.Eye; using Content.Shared.SurveillanceCamera; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.SurveillanceCamera.UI; @@ -26,12 +25,20 @@ public sealed class SurveillanceCameraMonitorBoundUserInterface : BoundUserInter { base.Open(); - _window = this.CreateWindow(); + _window = new SurveillanceCameraMonitorWindow(); + + if (State != null) + { + UpdateState(State); + } + + _window.OpenCentered(); _window.CameraSelected += OnCameraSelected; _window.SubnetOpened += OnSubnetRequest; _window.CameraRefresh += OnCameraRefresh; _window.SubnetRefresh += OnSubnetRefresh; + _window.OnClose += Close; _window.CameraSwitchTimer += OnCameraSwitchTimer; _window.CameraDisconnect += OnCameraDisconnect; } diff --git a/Content.Client/Thief/ThiefBackpackBoundUserInterface.cs b/Content.Client/Thief/ThiefBackpackBoundUserInterface.cs index 0631d98993..37384daafe 100644 --- a/Content.Client/Thief/ThiefBackpackBoundUserInterface.cs +++ b/Content.Client/Thief/ThiefBackpackBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Thief; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Thief; @@ -16,9 +15,21 @@ public sealed class ThiefBackpackBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.OnApprove += SendApprove; - _window.OnSetChange += SendChangeSelected; + _window = new ThiefBackpackMenu(this); + _window.OnClose += Close; + _window.OpenCentered(); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + return; + + if (_window != null) + _window.OnClose -= Close; + + _window?.Dispose(); } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/Thief/ThiefBackpackMenu.xaml.cs b/Content.Client/Thief/ThiefBackpackMenu.xaml.cs index aaee357617..543772c704 100644 --- a/Content.Client/Thief/ThiefBackpackMenu.xaml.cs +++ b/Content.Client/Thief/ThiefBackpackMenu.xaml.cs @@ -12,42 +12,46 @@ public sealed partial class ThiefBackpackMenu : FancyWindow [Dependency] private readonly IEntitySystemManager _sysMan = default!; private readonly SpriteSystem _spriteSystem; - public event Action? OnApprove; - public event Action? OnSetChange; + private readonly ThiefBackpackBoundUserInterface _owner; - public ThiefBackpackMenu() + public ThiefBackpackMenu(ThiefBackpackBoundUserInterface owner) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _spriteSystem = _sysMan.GetEntitySystem(); - ApproveButton.OnPressed += args => + _owner = owner; + + ApproveButton.OnButtonDown += (args) => { - OnApprove?.Invoke(); + _owner.SendApprove(); }; } public void UpdateState(ThiefBackpackBoundUserInterfaceState state) { - SetsGrid.DisposeAllChildren(); - var selectedNumber = 0; - foreach (var (set, info) in state.Sets) + SetsGrid.RemoveAllChildren(); + int count = 0; + int selectedNumber = 0; + foreach (var set in state.Sets) { - var child = new ThiefBackpackSet(info, _spriteSystem); + var child = new ThiefBackpackSet(set.Value, _spriteSystem); child.SetButton.OnButtonDown += (args) => { - OnSetChange?.Invoke(set); + _owner.SendChangeSelected(set.Key); }; SetsGrid.AddChild(child); - if (info.Selected) + count++; + + if (set.Value.Selected) selectedNumber++; } Description.Text = Loc.GetString("thief-backpack-window-description", ("maxCount", state.MaxSelectedSets)); SelectedSets.Text = Loc.GetString("thief-backpack-window-selected", ("selectedCount", selectedNumber), ("maxCount", state.MaxSelectedSets)); - ApproveButton.Disabled = selectedNumber != state.MaxSelectedSets; + ApproveButton.Disabled = selectedNumber == state.MaxSelectedSets ? false : true; } } diff --git a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs index 4ae74a5d65..4702f8f365 100644 --- a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs +++ b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankBoundUserInterface.cs @@ -1,7 +1,5 @@ using Content.Shared.Atmos.Components; using JetBrains.Annotations; -using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.UserInterface.Systems.Atmos.GasTank { @@ -15,7 +13,7 @@ namespace Content.Client.UserInterface.Systems.Atmos.GasTank { } - public void SetOutputPressure(float value) + public void SetOutputPressure(in float value) { SendMessage(new GasTankSetPressureMessage { @@ -31,10 +29,9 @@ namespace Content.Client.UserInterface.Systems.Atmos.GasTank protected override void Open() { base.Open(); - _window = this.CreateWindow(); - _window.SetTitle(EntMan.GetComponent(Owner).EntityName); - _window.OnOutputPressure += SetOutputPressure; - _window.OnToggleInternals += ToggleInternals; + _window = new GasTankWindow(this, EntMan.GetComponent(Owner).EntityName); + _window.OnClose += Close; + _window.OpenCentered(); } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs index 12eeaa55de..c23850a650 100644 --- a/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs +++ b/Content.Client/UserInterface/Systems/Atmos/GasTank/GasTankWindow.cs @@ -15,28 +15,23 @@ namespace Content.Client.UserInterface.Systems.Atmos.GasTank; public sealed class GasTankWindow : BaseWindow { - [Dependency] private readonly IResourceCache _cache = default!; - private readonly RichTextLabel _lblPressure; private readonly FloatSpinBox _spbPressure; private readonly RichTextLabel _lblInternals; private readonly Button _btnInternals; - private readonly Label _topLabel; - public event Action? OnOutputPressure; - public event Action? OnToggleInternals; - - public GasTankWindow() + public GasTankWindow(GasTankBoundUserInterface owner, string uidName) { Control contentContainer; BoxContainer topContainer; TextureButton btnClose; + var resourceCache = IoCManager.Resolve(); var rootContainer = new LayoutContainer { Name = "GasTankRoot" }; AddChild(rootContainer); MouseFilter = MouseFilterMode.Stop; - var panelTex = _cache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"); + var panelTex = resourceCache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png"); var back = new StyleBoxTexture { Texture = panelTex, @@ -83,17 +78,7 @@ public sealed class GasTankWindow LayoutContainer.SetAnchorPreset(topContainerWrap, LayoutContainer.LayoutPreset.Wide); - var font = _cache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13); - - _topLabel = new Label - { - FontOverride = font, - FontColorOverride = StyleNano.NanoGold, - VerticalAlignment = VAlignment.Center, - HorizontalExpand = true, - HorizontalAlignment = HAlignment.Left, - Margin = new Thickness(0, 0, 20, 0), - }; + var font = resourceCache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13); var topRow = new BoxContainer { @@ -101,7 +86,16 @@ public sealed class GasTankWindow Margin = new Thickness(4, 2, 12, 2), Children = { - _topLabel, + (new Label + { + Text = uidName, + FontOverride = font, + FontColorOverride = StyleNano.NanoGold, + VerticalAlignment = VAlignment.Center, + HorizontalExpand = true, + HorizontalAlignment = HAlignment.Left, + Margin = new Thickness(0, 0, 20, 0), + }), (btnClose = new TextureButton { StyleClasses = {DefaultWindow.StyleClassWindowCloseButton}, @@ -174,22 +168,17 @@ public sealed class GasTankWindow // Handlers _spbPressure.OnValueChanged += args => { - OnOutputPressure?.Invoke(args.Value); + owner.SetOutputPressure(args.Value); }; _btnInternals.OnPressed += args => { - OnToggleInternals?.Invoke(); + owner.ToggleInternals(); }; btnClose.OnPressed += _ => Close(); } - public void SetTitle(string name) - { - _topLabel.Text = name; - } - public void UpdateState(GasTankBoundUserInterfaceState state) { _lblPressure.SetMarkup(Loc.GetString("gas-tank-window-tank-pressure-text", ("tankPressure", $"{state.TankPressure:0.##}"))); diff --git a/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs b/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs index eafab84ed6..17ddba77ff 100644 --- a/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs +++ b/Content.Client/VendingMachines/VendingMachineBoundUserInterface.cs @@ -2,7 +2,6 @@ using Content.Client.VendingMachines.UI; using Content.Shared.VendingMachines; using Robust.Client.UserInterface.Controls; using System.Linq; -using Robust.Client.UserInterface; namespace Content.Client.VendingMachines { @@ -29,14 +28,15 @@ namespace Content.Client.VendingMachines _cachedInventory = vendingMachineSys.GetAllInventory(Owner); - _menu = this.CreateWindow(); - _menu.OpenCenteredLeft(); - _menu.Title = EntMan.GetComponent(Owner).EntityName; + _menu = new VendingMachineMenu { Title = EntMan.GetComponent(Owner).EntityName }; + _menu.OnClose += Close; _menu.OnItemSelected += OnItemSelected; _menu.OnSearchChanged += OnSearchChanged; _menu.Populate(_cachedInventory, out _cachedFilteredIndex); + + _menu.OpenCenteredLeft(); } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/VoiceMask/VoiceMaskBoundUserInterface.cs b/Content.Client/VoiceMask/VoiceMaskBoundUserInterface.cs index 891804674d..f700c6663b 100644 --- a/Content.Client/VoiceMask/VoiceMaskBoundUserInterface.cs +++ b/Content.Client/VoiceMask/VoiceMaskBoundUserInterface.cs @@ -1,13 +1,12 @@ using Content.Shared.VoiceMask; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; using Robust.Shared.Prototypes; namespace Content.Client.VoiceMask; public sealed class VoiceMaskBoundUserInterface : BoundUserInterface { - [Dependency] private readonly IPrototypeManager _protomanager = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; [ViewVariables] private VoiceMaskNameChangeWindow? _window; @@ -20,11 +19,12 @@ public sealed class VoiceMaskBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); - _window.ReloadVerbs(_protomanager); + _window = new(_proto); + _window.OpenCentered(); _window.OnNameChange += OnNameSelected; _window.OnVerbChange += verb => SendMessage(new VoiceMaskChangeVerbMessage(verb)); + _window.OnClose += Close; } private void OnNameSelected(string name) diff --git a/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs b/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs index 0dc41f807a..16a28f9d9b 100644 --- a/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs +++ b/Content.Client/VoiceMask/VoiceMaskNameChangeWindow.xaml.cs @@ -17,7 +17,7 @@ public sealed partial class VoiceMaskNameChangeWindow : FancyWindow private string? _verb; - public VoiceMaskNameChangeWindow() + public VoiceMaskNameChangeWindow(IPrototypeManager proto) { RobustXamlLoader.Load(this); @@ -32,10 +32,12 @@ public sealed partial class VoiceMaskNameChangeWindow : FancyWindow SpeechVerbSelector.SelectId(args.Id); }; + ReloadVerbs(proto); + AddVerbs(); } - public void ReloadVerbs(IPrototypeManager proto) + private void ReloadVerbs(IPrototypeManager proto) { foreach (var verb in proto.EnumeratePrototypes()) { diff --git a/Content.Client/Weapons/Melee/UI/MeleeSpeechBoundUserInterface.cs b/Content.Client/Weapons/Melee/UI/MeleeSpeechBoundUserInterface.cs index 3f01808c42..f3e0c0a539 100644 --- a/Content.Client/Weapons/Melee/UI/MeleeSpeechBoundUserInterface.cs +++ b/Content.Client/Weapons/Melee/UI/MeleeSpeechBoundUserInterface.cs @@ -1,6 +1,5 @@ using Robust.Client.GameObjects; using Content.Shared.Speech.Components; -using Robust.Client.UserInterface; namespace Content.Client.Weapons.Melee.UI; @@ -20,10 +19,17 @@ public sealed class MeleeSpeechBoundUserInterface : BoundUserInterface { base.Open(); - _window = this.CreateWindow(); + _window = new MeleeSpeechWindow(); + if (State != null) + UpdateState(State); + + _window.OpenCentered(); + + _window.OnClose += Close; _window.OnBattlecryEntered += OnBattlecryChanged; } + private void OnBattlecryChanged(string newBattlecry) { SendMessage(new MeleeSpeechBattlecryChangedMessage(newBattlecry)); diff --git a/Content.Client/Wires/UI/WiresBoundUserInterface.cs b/Content.Client/Wires/UI/WiresBoundUserInterface.cs index edf1a2d377..5a8869a204 100644 --- a/Content.Client/Wires/UI/WiresBoundUserInterface.cs +++ b/Content.Client/Wires/UI/WiresBoundUserInterface.cs @@ -1,6 +1,5 @@ using Content.Shared.Wires; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Wires.UI { @@ -16,8 +15,10 @@ namespace Content.Client.Wires.UI protected override void Open() { base.Open(); - _menu = this.CreateWindow(); - _menu.OnAction += PerformAction; + + _menu = new WiresMenu(this); + _menu.OnClose += Close; + _menu.OpenCenteredLeft(); } protected override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/Wires/UI/WiresMenu.cs b/Content.Client/Wires/UI/WiresMenu.cs index eccc548297..7bccc20861 100644 --- a/Content.Client/Wires/UI/WiresMenu.cs +++ b/Content.Client/Wires/UI/WiresMenu.cs @@ -1,3 +1,4 @@ +using System; using System.Numerics; using Content.Client.Examine; using Content.Client.Resources; @@ -11,6 +12,10 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.Animations; using Robust.Shared.Input; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using Robust.Shared.Random; using static Robust.Client.UserInterface.Controls.BoxContainer; namespace Content.Client.Wires.UI @@ -19,6 +24,8 @@ namespace Content.Client.Wires.UI { [Dependency] private readonly IResourceCache _resourceCache = default!; + public WiresBoundUserInterface Owner { get; } + private readonly Control _wiresHBox; private readonly Control _topContainer; private readonly Control _statusContainer; @@ -28,12 +35,11 @@ namespace Content.Client.Wires.UI public TextureButton CloseButton { get; set; } - public event Action? OnAction; - - public WiresMenu() + public WiresMenu(WiresBoundUserInterface owner) { IoCManager.InjectDependencies(this); + Owner = owner; var rootContainer = new LayoutContainer {Name = "WireRoot"}; AddChild(rootContainer); @@ -251,12 +257,12 @@ namespace Content.Client.Wires.UI control.WireClicked += () => { - OnAction?.Invoke(wire.Id, wire.IsCut ? WiresAction.Mend : WiresAction.Cut); + Owner.PerformAction(wire.Id, wire.IsCut ? WiresAction.Mend : WiresAction.Cut); }; control.ContactsClicked += () => { - OnAction?.Invoke(wire.Id, WiresAction.Pulse); + Owner.PerformAction(wire.Id, WiresAction.Pulse); }; } diff --git a/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleBoundUserInterface.cs b/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleBoundUserInterface.cs index c7a74815b6..2538caf6eb 100644 --- a/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleBoundUserInterface.cs +++ b/Content.Client/Xenoarchaeology/Ui/AnalysisConsoleBoundUserInterface.cs @@ -1,7 +1,6 @@ using Content.Shared.Xenoarchaeology.Equipment; using JetBrains.Annotations; using Robust.Client.GameObjects; -using Robust.Client.UserInterface; namespace Content.Client.Xenoarchaeology.Ui; @@ -19,7 +18,10 @@ public sealed class AnalysisConsoleBoundUserInterface : BoundUserInterface { base.Open(); - _consoleMenu = this.CreateWindow(); + _consoleMenu = new AnalysisConsoleMenu(); + + _consoleMenu.OnClose += Close; + _consoleMenu.OpenCentered(); _consoleMenu.OnServerSelectionButtonPressed += () => {