using Content.Shared.StationRecords;
using Robust.Client.AutoGenerated;
using Robust.Client.Player;
+using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
using Robust.Shared.Utility;
+using System.Linq;
namespace Content.Client.CriminalRecords;
public Action<SecurityStatus, string>? OnDialogConfirmed;
private uint _maxLength;
- private bool _isPopulating;
private bool _access;
private uint? _selectedKey;
private CriminalRecord? _selectedRecord;
RecordListing.OnItemSelected += args =>
{
- if (_isPopulating || RecordListing[args.ItemIndex].Metadata is not uint cast)
+ if (RecordListing[args.ItemIndex].Metadata is not uint cast)
return;
OnKeySelected?.Invoke(cast);
RecordListing.OnItemDeselected += _ =>
{
- if (!_isPopulating)
- OnKeySelected?.Invoke(null);
+ OnKeySelected?.Invoke(null);
};
FilterType.OnItemSelected += eventArgs =>
FilterType.SelectId((int)_currentFilterType);
- // set up the records listing panel
- RecordListing.Clear();
-
- var hasRecords = state.RecordListing != null && state.RecordListing.Count > 0;
- NoRecords.Visible = !hasRecords;
- if (hasRecords)
- PopulateRecordListing(state.RecordListing!);
+ NoRecords.Visible = state.RecordListing == null || state.RecordListing.Count == 0;
+ PopulateRecordListing(state.RecordListing);
// set up the selected person's record
var selected = _selectedKey != null;
}
}
- private void PopulateRecordListing(Dictionary<uint, string> listing)
+ private void PopulateRecordListing(Dictionary<uint, string>? listing)
{
- _isPopulating = true;
+ if (listing == null)
+ {
+ RecordListing.Clear();
+ return;
+ }
+
+ var entries = listing.ToList();
+ entries.Sort((a, b) => string.Compare(a.Value, b.Value, StringComparison.Ordinal));
+ // `entries` now contains the definitive list of items which should be in
+ // our list of records and is in the order we want to present those items.
+
+ // Walk through the existing items in RecordListing and in the updated listing
+ // in parallel to synchronize the items in RecordListing with `entries`.
+ int i = RecordListing.Count - 1;
+ int j = entries.Count - 1;
+ while(i >= 0 && j >= 0)
+ {
+ var strcmp = string.Compare(RecordListing[i].Text, entries[j].Value, StringComparison.Ordinal);
+ if (strcmp == 0)
+ {
+ // This item exists in both RecordListing and `entries`. Nothing to do.
+ i--;
+ j--;
+ }
+ else if (strcmp > 0)
+ {
+ // Item exists in RecordListing, but not in `entries`. Remove it.
+ RecordListing.RemoveAt(i);
+ i--;
+ }
+ else if (strcmp < 0)
+ {
+ // A new entry which doesn't exist in RecordListing. Create it.
+ RecordListing.Insert(i + 1, new ItemList.Item(RecordListing){Text = entries[j].Value, Metadata = entries[j].Key});
+ j--;
+ }
+ }
- foreach (var (key, name) in listing)
+ // Any remaining items in RecordListing don't exist in `entries`, so remove them
+ while (i >= 0)
{
- var item = RecordListing.AddItem(name);
- item.Metadata = key;
- item.Selected = key == _selectedKey;
+ RecordListing.RemoveAt(i);
+ i--;
}
- _isPopulating = false;
- RecordListing.SortItemsByText();
+ // And finally, any remaining items in `entries`, don't exist in RecordListing. Create them.
+ while (j >= 0)
+ {
+ RecordListing.Insert(0, new ItemList.Item(RecordListing){Text = entries[j].Value, Metadata = entries[j].Key});
+ j--;
+ }
}
private void PopulateRecordContainer(GeneralStationRecord stationRecord, CriminalRecord criminalRecord)
private void FilterListingOfRecords(string text = "")
{
- if (!_isPopulating)
- {
- OnFiltersChanged?.Invoke(_currentFilterType, text);
- }
+ OnFiltersChanged?.Invoke(_currentFilterType, text);
}
private void SetStatus(SecurityStatus status)