using System; using System.Collections.Generic; namespace Avalonia.Controls { internal class SelectionModelChangeSet { private List _changes; public SelectionModelChangeSet(List changes) { _changes = changes; } public SelectionModelSelectionChangedEventArgs CreateEventArgs() { var deselectedCount = 0; var selectedCount = 0; foreach (var change in _changes) { deselectedCount += change.DeselectedCount; selectedCount += change.SelectedCount; } var deselectedIndices = new SelectedItems( _changes, deselectedCount, GetDeselectedIndexAt); var selectedIndices = new SelectedItems( _changes, selectedCount, GetSelectedIndexAt); var deselectedItems = new SelectedItems( _changes, deselectedCount, GetDeselectedItemAt); var selectedItems = new SelectedItems( _changes, selectedCount, GetSelectedItemAt); return new SelectionModelSelectionChangedEventArgs( deselectedIndices, selectedIndices, deselectedItems, selectedItems); } private IndexPath GetDeselectedIndexAt( List infos, int index) { static int GetCount(SelectionNodeOperation info) => info.DeselectedCount; static List GetRanges(SelectionNodeOperation info) => info.DeselectedRanges; return GetIndexAt(infos, index, GetCount, GetRanges); } private IndexPath GetSelectedIndexAt( List infos, int index) { static int GetCount(SelectionNodeOperation info) => info.SelectedCount; static List GetRanges(SelectionNodeOperation info) => info.SelectedRanges; return GetIndexAt(infos, index, GetCount, GetRanges); } private object GetDeselectedItemAt( List infos, int index) { static int GetCount(SelectionNodeOperation info) => info.DeselectedCount; static List GetRanges(SelectionNodeOperation info) => info.DeselectedRanges; return GetItemAt(infos, index, GetCount, GetRanges); } private object GetSelectedItemAt( List infos, int index) { static int GetCount(SelectionNodeOperation info) => info.SelectedCount; static List GetRanges(SelectionNodeOperation info) => info.SelectedRanges; return GetItemAt(infos, index, GetCount, GetRanges); } private IndexPath GetIndexAt( List infos, int index, Func getCount, Func> getRanges) { var currentIndex = 0; IndexPath path = default; foreach (var info in infos) { var currentCount = getCount(info); if (index >= currentIndex && index < currentIndex + currentCount) { int targetIndex = GetIndexAt(getRanges(info), index - currentIndex); path = info.Path.CloneWithChildIndex(targetIndex); break; } currentIndex += currentCount; } return path; } private object GetItemAt( List infos, int index, Func getCount, Func> getRanges) { var currentIndex = 0; object item = null; foreach (var info in infos) { var currentCount = getCount(info); if (index >= currentIndex && index < currentIndex + currentCount) { int targetIndex = GetIndexAt(getRanges(info), index - currentIndex); item = info.Items.GetAt(targetIndex); break; } currentIndex += currentCount; } return item; } private int GetIndexAt(List ranges, int index) { var currentIndex = 0; foreach (var range in ranges) { var currentCount = (range.End - range.Begin) + 1; if (index >= currentIndex && index < currentIndex + currentCount) { return range.Begin + (index - currentIndex); } currentIndex += currentCount; } throw new IndexOutOfRangeException(); } } }