WantedListUiFragment.cs 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. using System.Linq;
  2. using Content.Client.UserInterface.Controls;
  3. using Content.Shared.CriminalRecords.Systems;
  4. using Content.Shared.Security;
  5. using Content.Shared.StatusIcon;
  6. using Robust.Client.AutoGenerated;
  7. using Robust.Client.GameObjects;
  8. using Robust.Client.ResourceManagement;
  9. using Robust.Client.UserInterface;
  10. using Robust.Client.UserInterface.Controls;
  11. using Robust.Client.UserInterface.XAML;
  12. using Robust.Shared.Input;
  13. using Robust.Shared.Map;
  14. using Robust.Shared.Prototypes;
  15. using Robust.Shared.Utility;
  16. namespace Content.Client.CartridgeLoader.Cartridges;
  17. [GenerateTypedNameReferences]
  18. public sealed partial class WantedListUiFragment : BoxContainer
  19. {
  20. [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
  21. [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
  22. private readonly SpriteSystem _spriteSystem;
  23. private string? _selectedTargetName;
  24. private List<WantedRecord> _wantedRecords = new();
  25. public WantedListUiFragment()
  26. {
  27. RobustXamlLoader.Load(this);
  28. IoCManager.InjectDependencies(this);
  29. _spriteSystem = _entitySystem.GetEntitySystem<SpriteSystem>();
  30. SearchBar.OnTextChanged += OnSearchBarTextChanged;
  31. }
  32. private void OnSearchBarTextChanged(LineEdit.LineEditEventArgs args)
  33. {
  34. var found = !String.IsNullOrWhiteSpace(args.Text)
  35. ? _wantedRecords.FindAll(r =>
  36. r.TargetInfo.Name.Contains(args.Text) ||
  37. r.Status.ToString().Contains(args.Text, StringComparison.OrdinalIgnoreCase))
  38. : _wantedRecords;
  39. UpdateState(found, false);
  40. }
  41. public void UpdateState(List<WantedRecord> records, bool refresh = true)
  42. {
  43. if (records.Count == 0)
  44. {
  45. NoRecords.Visible = true;
  46. RecordsList.Visible = false;
  47. RecordUnselected.Visible = false;
  48. PersonContainer.Visible = false;
  49. _selectedTargetName = null;
  50. if (refresh)
  51. _wantedRecords.Clear();
  52. RecordsList.PopulateList(new List<ListData>());
  53. return;
  54. }
  55. NoRecords.Visible = false;
  56. RecordsList.Visible = true;
  57. RecordUnselected.Visible = true;
  58. PersonContainer.Visible = false;
  59. var dataList = records.Select(r => new StatusListData(r)).ToList();
  60. RecordsList.GenerateItem = GenerateItem;
  61. RecordsList.ItemPressed = OnItemSelected;
  62. RecordsList.PopulateList(dataList);
  63. if (refresh)
  64. _wantedRecords = records;
  65. }
  66. private void OnItemSelected(BaseButton.ButtonEventArgs args, ListData data)
  67. {
  68. if (data is not StatusListData(var record))
  69. return;
  70. FormattedMessage GetLoc(string fluentId, params (string,object)[] args)
  71. {
  72. var msg = new FormattedMessage();
  73. var fluent = Loc.GetString(fluentId, args);
  74. msg.AddMarkupPermissive(fluent);
  75. return msg;
  76. }
  77. // Set personal info
  78. PersonName.Text = record.TargetInfo.Name;
  79. TargetAge.SetMessage(GetLoc(
  80. "wanted-list-age-label",
  81. ("age", record.TargetInfo.Age)
  82. ));
  83. TargetJob.SetMessage(GetLoc(
  84. "wanted-list-job-label",
  85. ("job", record.TargetInfo.JobTitle.ToLower())
  86. ));
  87. TargetSpecies.SetMessage(GetLoc(
  88. "wanted-list-species-label",
  89. ("species", record.TargetInfo.Species.ToLower())
  90. ));
  91. TargetGender.SetMessage(GetLoc(
  92. "wanted-list-gender-label",
  93. ("gender", record.TargetInfo.Gender)
  94. ));
  95. // Set reason
  96. WantedReason.SetMessage(GetLoc(
  97. "wanted-list-reason-label",
  98. ("reason", record.Reason ?? Loc.GetString("wanted-list-unknown-reason-label"))
  99. ));
  100. // Set status
  101. PersonState.SetMessage(GetLoc(
  102. "wanted-list-status-label",
  103. ("status", record.Status.ToString().ToLower())
  104. ));
  105. // Set initiator
  106. InitiatorName.SetMessage(GetLoc(
  107. "wanted-list-initiator-label",
  108. ("initiator", record.Initiator ?? Loc.GetString("wanted-list-unknown-initiator-label"))
  109. ));
  110. // History table
  111. // Clear table if it exists
  112. HistoryTable.RemoveAllChildren();
  113. HistoryTable.AddChild(new Label()
  114. {
  115. Text = Loc.GetString("wanted-list-history-table-time-col"),
  116. StyleClasses = { "LabelSmall" },
  117. HorizontalAlignment = HAlignment.Center,
  118. });
  119. HistoryTable.AddChild(new Label()
  120. {
  121. Text = Loc.GetString("wanted-list-history-table-reason-col"),
  122. StyleClasses = { "LabelSmall" },
  123. HorizontalAlignment = HAlignment.Center,
  124. HorizontalExpand = true,
  125. });
  126. HistoryTable.AddChild(new Label()
  127. {
  128. Text = Loc.GetString("wanted-list-history-table-initiator-col"),
  129. StyleClasses = { "LabelSmall" },
  130. HorizontalAlignment = HAlignment.Center,
  131. });
  132. if (record.History.Count > 0)
  133. {
  134. HistoryTable.Visible = true;
  135. foreach (var history in record.History.OrderByDescending(h => h.AddTime))
  136. {
  137. HistoryTable.AddChild(new Label()
  138. {
  139. Text = $"{history.AddTime.Hours:00}:{history.AddTime.Minutes:00}:{history.AddTime.Seconds:00}",
  140. StyleClasses = { "LabelSmall" },
  141. VerticalAlignment = VAlignment.Top,
  142. });
  143. HistoryTable.AddChild(new RichTextLabel()
  144. {
  145. Text = $"[color=white]{history.Crime}[/color]",
  146. HorizontalExpand = true,
  147. VerticalAlignment = VAlignment.Top,
  148. StyleClasses = { "LabelSubText" },
  149. Margin = new(10f, 0f),
  150. });
  151. HistoryTable.AddChild(new RichTextLabel()
  152. {
  153. Text = $"[color=white]{history.InitiatorName}[/color]",
  154. StyleClasses = { "LabelSubText" },
  155. VerticalAlignment = VAlignment.Top,
  156. });
  157. }
  158. }
  159. RecordUnselected.Visible = false;
  160. PersonContainer.Visible = true;
  161. // Save selected item
  162. _selectedTargetName = record.TargetInfo.Name;
  163. }
  164. private void GenerateItem(ListData data, ListContainerButton button)
  165. {
  166. if (data is not StatusListData(var record))
  167. return;
  168. var box = new BoxContainer() { Orientation = LayoutOrientation.Horizontal, HorizontalExpand = true };
  169. var label = new Label() { Text = record.TargetInfo.Name };
  170. var rect = new TextureRect()
  171. {
  172. TextureScale = new(2.2f),
  173. VerticalAlignment = VAlignment.Center,
  174. HorizontalAlignment = HAlignment.Center,
  175. Margin = new(0f, 0f, 6f, 0f),
  176. };
  177. if (record.Status is not SecurityStatus.None)
  178. {
  179. var proto = "SecurityIcon" + record.Status switch
  180. {
  181. SecurityStatus.Detained => "Incarcerated",
  182. _ => record.Status.ToString(),
  183. };
  184. if (_prototypeManager.TryIndex<SecurityIconPrototype>(proto, out var prototype))
  185. {
  186. rect.Texture = _spriteSystem.Frame0(prototype.Icon);
  187. }
  188. }
  189. box.AddChild(rect);
  190. box.AddChild(label);
  191. button.AddChild(box);
  192. button.AddStyleClass(ListContainer.StyleClassListContainerButton);
  193. if (record.TargetInfo.Name.Equals(_selectedTargetName))
  194. {
  195. button.Pressed = true;
  196. // For some reason the event is not called when `Pressed` changed, call it manually.
  197. OnItemSelected(
  198. new(button, new(new(), BoundKeyState.Down, new(), false, new(), new())),
  199. data);
  200. }
  201. }
  202. }
  203. internal record StatusListData(WantedRecord Record) : ListData;