using System.Linq; using Content.Client.UserInterface.Controls; using Content.Shared.CriminalRecords.Systems; using Content.Shared.Security; using Content.Shared.StatusIcon; using Robust.Client.AutoGenerated; using Robust.Client.GameObjects; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Input; using Robust.Shared.Map; using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Client.CartridgeLoader.Cartridges; [GenerateTypedNameReferences] public sealed partial class WantedListUiFragment : BoxContainer { [Dependency] private readonly IEntitySystemManager _entitySystem = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private readonly SpriteSystem _spriteSystem; private string? _selectedTargetName; private List _wantedRecords = new(); public WantedListUiFragment() { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); _spriteSystem = _entitySystem.GetEntitySystem(); SearchBar.OnTextChanged += OnSearchBarTextChanged; } private void OnSearchBarTextChanged(LineEdit.LineEditEventArgs args) { var found = !String.IsNullOrWhiteSpace(args.Text) ? _wantedRecords.FindAll(r => r.TargetInfo.Name.Contains(args.Text) || r.Status.ToString().Contains(args.Text, StringComparison.OrdinalIgnoreCase)) : _wantedRecords; UpdateState(found, false); } public void UpdateState(List records, bool refresh = true) { if (records.Count == 0) { NoRecords.Visible = true; RecordsList.Visible = false; RecordUnselected.Visible = false; PersonContainer.Visible = false; _selectedTargetName = null; if (refresh) _wantedRecords.Clear(); RecordsList.PopulateList(new List()); return; } NoRecords.Visible = false; RecordsList.Visible = true; RecordUnselected.Visible = true; PersonContainer.Visible = false; var dataList = records.Select(r => new StatusListData(r)).ToList(); RecordsList.GenerateItem = GenerateItem; RecordsList.ItemPressed = OnItemSelected; RecordsList.PopulateList(dataList); if (refresh) _wantedRecords = records; } private void OnItemSelected(BaseButton.ButtonEventArgs args, ListData data) { if (data is not StatusListData(var record)) return; FormattedMessage GetLoc(string fluentId, params (string,object)[] args) { var msg = new FormattedMessage(); var fluent = Loc.GetString(fluentId, args); msg.AddMarkupPermissive(fluent); return msg; } // Set personal info PersonName.Text = record.TargetInfo.Name; TargetAge.SetMessage(GetLoc( "wanted-list-age-label", ("age", record.TargetInfo.Age) )); TargetJob.SetMessage(GetLoc( "wanted-list-job-label", ("job", record.TargetInfo.JobTitle.ToLower()) )); TargetSpecies.SetMessage(GetLoc( "wanted-list-species-label", ("species", record.TargetInfo.Species.ToLower()) )); TargetGender.SetMessage(GetLoc( "wanted-list-gender-label", ("gender", record.TargetInfo.Gender) )); // Set reason WantedReason.SetMessage(GetLoc( "wanted-list-reason-label", ("reason", record.Reason ?? Loc.GetString("wanted-list-unknown-reason-label")) )); // Set status PersonState.SetMessage(GetLoc( "wanted-list-status-label", ("status", record.Status.ToString().ToLower()) )); // Set initiator InitiatorName.SetMessage(GetLoc( "wanted-list-initiator-label", ("initiator", record.Initiator ?? Loc.GetString("wanted-list-unknown-initiator-label")) )); // History table // Clear table if it exists HistoryTable.RemoveAllChildren(); HistoryTable.AddChild(new Label() { Text = Loc.GetString("wanted-list-history-table-time-col"), StyleClasses = { "LabelSmall" }, HorizontalAlignment = HAlignment.Center, }); HistoryTable.AddChild(new Label() { Text = Loc.GetString("wanted-list-history-table-reason-col"), StyleClasses = { "LabelSmall" }, HorizontalAlignment = HAlignment.Center, HorizontalExpand = true, }); HistoryTable.AddChild(new Label() { Text = Loc.GetString("wanted-list-history-table-initiator-col"), StyleClasses = { "LabelSmall" }, HorizontalAlignment = HAlignment.Center, }); if (record.History.Count > 0) { HistoryTable.Visible = true; foreach (var history in record.History.OrderByDescending(h => h.AddTime)) { HistoryTable.AddChild(new Label() { Text = $"{history.AddTime.Hours:00}:{history.AddTime.Minutes:00}:{history.AddTime.Seconds:00}", StyleClasses = { "LabelSmall" }, VerticalAlignment = VAlignment.Top, }); HistoryTable.AddChild(new RichTextLabel() { Text = $"[color=white]{history.Crime}[/color]", HorizontalExpand = true, VerticalAlignment = VAlignment.Top, StyleClasses = { "LabelSubText" }, Margin = new(10f, 0f), }); HistoryTable.AddChild(new RichTextLabel() { Text = $"[color=white]{history.InitiatorName}[/color]", StyleClasses = { "LabelSubText" }, VerticalAlignment = VAlignment.Top, }); } } RecordUnselected.Visible = false; PersonContainer.Visible = true; // Save selected item _selectedTargetName = record.TargetInfo.Name; } private void GenerateItem(ListData data, ListContainerButton button) { if (data is not StatusListData(var record)) return; var box = new BoxContainer() { Orientation = LayoutOrientation.Horizontal, HorizontalExpand = true }; var label = new Label() { Text = record.TargetInfo.Name }; var rect = new TextureRect() { TextureScale = new(2.2f), VerticalAlignment = VAlignment.Center, HorizontalAlignment = HAlignment.Center, Margin = new(0f, 0f, 6f, 0f), }; if (record.Status is not SecurityStatus.None) { var proto = "SecurityIcon" + record.Status switch { SecurityStatus.Detained => "Incarcerated", _ => record.Status.ToString(), }; if (_prototypeManager.TryIndex(proto, out var prototype)) { rect.Texture = _spriteSystem.Frame0(prototype.Icon); } } box.AddChild(rect); box.AddChild(label); button.AddChild(box); button.AddStyleClass(ListContainer.StyleClassListContainerButton); if (record.TargetInfo.Name.Equals(_selectedTargetName)) { button.Pressed = true; // For some reason the event is not called when `Pressed` changed, call it manually. OnItemSelected( new(button, new(new(), BoundKeyState.Down, new(), false, new(), new())), data); } } } internal record StatusListData(WantedRecord Record) : ListData;