From 9d26b4953211a560e7847c8a3bd0e2678e6c9be9 Mon Sep 17 00:00:00 2001 From: Eoin Mcloughlin Date: Tue, 3 Sep 2024 21:13:55 +0100 Subject: [PATCH 1/2] Add algorithm from ss14#30292 to ItemList, for use in other UIs --- .../UserInterface/Controls/ItemList.cs | 55 ++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/Robust.Client/UserInterface/Controls/ItemList.cs b/Robust.Client/UserInterface/Controls/ItemList.cs index 053d05c61de..b885cbee529 100644 --- a/Robust.Client/UserInterface/Controls/ItemList.cs +++ b/Robust.Client/UserInterface/Controls/ItemList.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.Contracts; @@ -176,6 +176,59 @@ public void Insert(int index, Item item) _scrollBar.MoveToEnd(); } + /// + /// Replace the current list of items with the items in newItems. + /// newItems should be in the order which they should appear in the list. + /// Provided the existing items have not been re-ordered relative to each + /// other, Any items which already exist in the list are not destroyed, + /// which maintains consistency of scrollbars, selected items, etc. + /// + /// The list of items to update this list to + /// Comparison function to compare existing to new items. + public void SetItems(List newItems, Comparison itemCmp) + { + // Walk through the existing items in this list and in newItems + // in parallel to synchronize our items with those in newItems. + int i = this.Count - 1; + int j = newItems.Count - 1; + while(i >= 0 && j >= 0) + { + var cmpResult = itemCmp(this[i], newItems[j]); + if (cmpResult == 0) + { + // This item exists in both our list and `newItems`. Nothing to do. + i--; + j--; + } + else if (cmpResult > 0) + { + // Item exists in our list, but not in `newItems`. Remove it. + RemoveAt(i); + i--; + } + else if (cmpResult < 0) + { + // A new entry which doesn't exist in our list. Insert it. + Insert(i + 1, newItems[j]); + j--; + } + } + + // Any remaining items in our list don't exist in `newItems`, so remove them + while (i >= 0) + { + RemoveAt(i); + i--; + } + + // And finally, any remaining items in `newItems`, don't exist in our list. Create them. + while (j >= 0) + { + Insert(0, newItems[j]); + j--; + } + } + // Without this attribute, this would compile into a property called "Item", causing problems with the Item class. [System.Runtime.CompilerServices.IndexerName("IndexItem")] public Item this[int index] From c5cb32474bc238c4e56ad449df565cba747926ff Mon Sep 17 00:00:00 2001 From: Eoin Mcloughlin Date: Mon, 4 Nov 2024 20:15:40 +0000 Subject: [PATCH 2/2] Add overload for common case of comparing items by their text label --- .../UserInterface/Controls/ItemList.cs | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Robust.Client/UserInterface/Controls/ItemList.cs b/Robust.Client/UserInterface/Controls/ItemList.cs index b885cbee529..985b6e031d1 100644 --- a/Robust.Client/UserInterface/Controls/ItemList.cs +++ b/Robust.Client/UserInterface/Controls/ItemList.cs @@ -178,12 +178,24 @@ public void Insert(int index, Item item) /// /// Replace the current list of items with the items in newItems. - /// newItems should be in the order which they should appear in the list. + /// newItems should be in the order which they should appear in the list, + /// and items are considered equal if the Item text is equal in each item. + /// /// Provided the existing items have not been re-ordered relative to each - /// other, Any items which already exist in the list are not destroyed, + /// other, any items which already exist in the list are not destroyed, /// which maintains consistency of scrollbars, selected items, etc. /// /// The list of items to update this list to + public void SetItems(List newItems) + { + SetItems(newItems, (a,b) => string.Compare(a.Text, b.Text)); + } + + /// + /// + /// This variant allows for a custom equality operator to compare items, when + /// comparing the Item text is not desired. + /// /// Comparison function to compare existing to new items. public void SetItems(List newItems, Comparison itemCmp) { @@ -214,14 +226,14 @@ public void SetItems(List newItems, Comparison itemCmp) } } - // Any remaining items in our list don't exist in `newItems`, so remove them + // Any remaining items in our list don't exist in `newItems` so remove them while (i >= 0) { RemoveAt(i); i--; } - // And finally, any remaining items in `newItems`, don't exist in our list. Create them. + // And finally, any remaining items in `newItems` don't exist in our list. Create them. while (j >= 0) { Insert(0, newItems[j]);