using Content.Shared.PDA; using Robust.Shared.Utility; using Content.Shared.CartridgeLoader; using Content.Client.Message; using Content.Shared.AlertLevel; using Content.Shared.GameTicking; using Robust.Client.UserInterface; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface.XAML; using Robust.Client.UserInterface.Controls; using Robust.Shared.Timing; namespace Content.Client.PDA { [GenerateTypedNameReferences] public sealed partial class PdaMenu : PdaWindow { [Dependency] private IClipboardManager _clipboard = null!; [Dependency] private IGameTiming _gameTiming = default!; [Dependency] private IEntitySystemManager _entitySystem = default!; private readonly AlertLevelSystem _alert = default!; private readonly GameTicker _gameTicker; public const int HomeView = 0; public const int ProgramListView = 1; public const int SettingsView = 2; public const int ProgramContentView = 3; private string _pdaOwner = Loc.GetString("comp-pda-ui-unknown"); private string _owner = Loc.GetString("comp-pda-ui-unknown"); private string _jobTitle = Loc.GetString("comp-pda-ui-unassigned"); private string _stationName = Loc.GetString("comp-pda-ui-unknown"); private string _alertLevel = Loc.GetString("comp-pda-ui-unknown"); private string _instructions = Loc.GetString("comp-pda-ui-unknown"); private int _currentView; public event Action? OnProgramItemPressed; public event Action? OnUninstallButtonPressed; public event Action? OnInstallButtonPressed; public PdaMenu() { IoCManager.InjectDependencies(this); _alert = _entitySystem.GetEntitySystem(); _gameTicker = _entitySystem.GetEntitySystem(); RobustXamlLoader.Load(this); ViewContainer.OnChildAdded += control => control.Visible = false; HomeButton.IconTexture = new SpriteSpecifier.Texture(new("/Textures/Interface/home.png")); FlashLightToggleButton.IconTexture = new SpriteSpecifier.Texture(new("/Textures/Interface/light.png")); EjectPenButton.IconTexture = new SpriteSpecifier.Texture(new("/Textures/Interface/pencil.png")); EjectIdButton.IconTexture = new SpriteSpecifier.Texture(new("/Textures/Interface/eject.png")); EjectPaiButton.IconTexture = new SpriteSpecifier.Texture(new("/Textures/Interface/pai.png")); ProgramCloseButton.IconTexture = new SpriteSpecifier.Texture(new("/Textures/Interface/Nano/cross.svg.png")); HomeButton.OnPressed += _ => ToHomeScreen(); ProgramListButton.OnPressed += _ => { HomeButton.IsCurrent = false; ProgramListButton.IsCurrent = true; SettingsButton.IsCurrent = false; ProgramTitle.IsCurrent = false; ChangeView(ProgramListView); }; SettingsButton.OnPressed += _ => { HomeButton.IsCurrent = false; ProgramListButton.IsCurrent = false; SettingsButton.IsCurrent = true; ProgramTitle.IsCurrent = false; ChangeView(SettingsView); }; ProgramTitle.OnPressed += _ => { HomeButton.IsCurrent = false; ProgramListButton.IsCurrent = false; SettingsButton.IsCurrent = false; ProgramTitle.IsCurrent = true; ChangeView(ProgramContentView); }; ProgramCloseButton.OnPressed += _ => { HideProgramHeader(); ToHomeScreen(); }; PdaOwnerButton.OnPressed += _ => { _clipboard.SetText(_pdaOwner); }; IdInfoButton.OnPressed += _ => { _clipboard.SetText(_owner + ", " + _jobTitle); }; StationNameButton.OnPressed += _ => { _clipboard.SetText(_stationName); }; StationAlertLevelButton.OnPressed += _ => { _clipboard.SetText(_alertLevel); }; StationTimeButton.OnPressed += _ => { var stationTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan); _clipboard.SetText((stationTime.ToString("hh\\:mm\\:ss"))); }; StationAlertLevelInstructionsButton.OnPressed += _ => { _clipboard.SetText(_instructions); }; HideAllViews(); ToHomeScreen(); } public void UpdateState(PdaUpdateState state) { FlashLightToggleButton.IsActive = state.FlashlightEnabled; if (state.PdaOwnerInfo.ActualOwnerName != null) { _pdaOwner = state.PdaOwnerInfo.ActualOwnerName; PdaOwnerLabel.SetMarkup(Loc.GetString("comp-pda-ui-owner", ("actualOwnerName", FormattedMessage.RemoveMarkupPermissive(_pdaOwner)))); PdaOwnerLabel.Visible = true; } else { PdaOwnerLabel.Visible = false; } if (state.PdaOwnerInfo.IdOwner != null || state.PdaOwnerInfo.JobTitle != null) { _owner = state.PdaOwnerInfo.IdOwner ?? Loc.GetString("comp-pda-ui-unknown"); _jobTitle = state.PdaOwnerInfo.JobTitle ?? Loc.GetString("comp-pda-ui-unassigned"); IdInfoLabel.SetMarkup(Loc.GetString("comp-pda-ui", ("owner", FormattedMessage.RemoveMarkupPermissive(_owner)), ("jobTitle", FormattedMessage.RemoveMarkupPermissive(_jobTitle)))); } else { IdInfoLabel.SetMarkup(Loc.GetString("comp-pda-ui-blank")); } _stationName = state.StationName ?? Loc.GetString("comp-pda-ui-unknown"); StationNameLabel.SetMarkup(Loc.GetString("comp-pda-ui-station", ("station", _stationName))); var stationTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan); StationTimeLabel.SetMarkup(Loc.GetString("comp-pda-ui-station-time", ("time", stationTime.ToString("hh\\:mm\\:ss")))); var alertColor = state.PdaOwnerInfo.StationAlertColor; (_alertLevel, _, _instructions) = _alert.AlertLevelData(state.PdaOwnerInfo.StationAlertLevel); StationAlertLevelLabel.SetMarkup(Loc.GetString( "comp-pda-ui-station-alert-level", ("color", alertColor), ("level", _alertLevel) )); StationAlertLevelInstructions.SetMarkup(Loc.GetString( "comp-pda-ui-station-alert-level-instructions", ("instructions", _instructions)) ); AddressLabel.Text = state.Address?.ToUpper() ?? " - "; EjectIdButton.IsActive = state.PdaOwnerInfo.IdOwner != null || state.PdaOwnerInfo.JobTitle != null; EjectPenButton.IsActive = state.HasPen; EjectPaiButton.IsActive = state.HasPai; ActivateMusicButton.Visible = state.CanPlayMusic; ShowUplinkButton.Visible = state.HasUplink; LockUplinkButton.Visible = state.HasUplink; } public void UpdateAvailablePrograms(List<(EntityUid, CartridgeComponent)> programs) { if (programs.Count == 0) { ProgramList.RemoveAllChildren(); ProgramList.AddChild(new Label() { Text = Loc.GetString("comp-pda-io-no-programs-available"), HorizontalAlignment = HAlignment.Center, VerticalAlignment = VAlignment.Center, VerticalExpand = true }); return; } if (ProgramList.ChildCount >= 1 && ProgramList.Children[0] is Label label) { label.Orphan(); } while (ProgramList.ChildCount > programs.Count) { ProgramList.Children[ProgramList.ChildCount - 1].Orphan(); } for (var i = 0; i < programs.Count; i++) { var cartridge = programs[i]; if (i < ProgramList.ChildCount) { var currentItem = ProgramList.Children[i]; if (currentItem is PdaProgramItem programItem) { programItem.SetCartridge(cartridge); continue; } DebugTools.Assert(i == ProgramList.ChildCount-1); currentItem.Orphan(); } var item = new PdaProgramItem(cartridge); item.OnProgramItemPressed += uid => OnProgramItemPressed?.Invoke(uid); item.OnUninstallButtonPressed += uid => OnUninstallButtonPressed?.Invoke(uid); item.OnInstallButtonPressed += uid => OnInstallButtonPressed?.Invoke(uid); ProgramList.AddChild(item); } //Add a filler item to the last row when it only contains one item if (programs.Count % 2 == 0) ProgramList.AddChild(new Control() { HorizontalExpand = true }); } /// /// Changes the current view to the home screen (view 0) and sets the tabs `IsCurrent` flag accordingly /// public void ToHomeScreen() { HomeButton.IsCurrent = true; ProgramListButton.IsCurrent = false; SettingsButton.IsCurrent = false; ProgramTitle.IsCurrent = false; ChangeView(HomeView); } /// /// Hides the program title and close button. /// public void HideProgramHeader() { ProgramTitle.IsCurrent = false; ProgramTitle.Visible = false; ProgramCloseButton.Visible = false; ProgramListButton.Visible = true; SettingsButton.Visible = true; } /// /// Changes the current view to the program content view (view 3), sets the program title and sets the tabs `IsCurrent` flag accordingly /// public void ToProgramView(string title) { HomeButton.IsCurrent = false; ProgramListButton.IsCurrent = false; SettingsButton.IsCurrent = false; ProgramTitle.IsCurrent = false; ProgramTitle.IsCurrent = true; ProgramTitle.Visible = true; ProgramCloseButton.Visible = true; ProgramListButton.Visible = false; SettingsButton.Visible = false; ProgramTitle.LabelText = title; ChangeView(ProgramContentView); } /// /// Changes the current view to the given view number /// public void ChangeView(int view) { if (ViewContainer.ChildCount <= view) return; ViewContainer.GetChild(_currentView).Visible = false; ViewContainer.GetChild(view).Visible = true; _currentView = view; } private void HideAllViews() { var views = ViewContainer.Children; foreach (var view in views) { view.Visible = false; } } protected override void Draw(DrawingHandleScreen handle) { base.Draw(handle); var stationTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan); StationTimeLabel.SetMarkup(Loc.GetString("comp-pda-ui-station-time", ("time", stationTime.ToString("hh\\:mm\\:ss")))); } } }