|
|
|
@ -14,61 +14,144 @@ namespace Avalonia.Controls |
|
|
|
|
|
|
|
public SelectionModelSelectionChangedEventArgs CreateEventArgs() |
|
|
|
{ |
|
|
|
var deselectedCount = 0; |
|
|
|
var selectedCount = 0; |
|
|
|
|
|
|
|
foreach (var change in _changes) |
|
|
|
{ |
|
|
|
deselectedCount += change.DeselectedCount; |
|
|
|
selectedCount += change.SelectedCount; |
|
|
|
} |
|
|
|
|
|
|
|
var deselectedIndices = new SelectedItems<IndexPath, SelectionNodeOperation>( |
|
|
|
_changes, |
|
|
|
deselectedCount, |
|
|
|
GetDeselectedIndexAt); |
|
|
|
var selectedIndices = new SelectedItems<IndexPath, SelectionNodeOperation>( |
|
|
|
_changes, |
|
|
|
selectedCount, |
|
|
|
GetSelectedIndexAt); |
|
|
|
var deselectedItems = new SelectedItems<object, SelectionNodeOperation>( |
|
|
|
_changes, |
|
|
|
deselectedCount, |
|
|
|
GetDeselectedItemAt); |
|
|
|
var selectedItems = new SelectedItems<object, SelectionNodeOperation>( |
|
|
|
_changes, |
|
|
|
selectedCount, |
|
|
|
GetSelectedItemAt); |
|
|
|
|
|
|
|
return new SelectionModelSelectionChangedEventArgs( |
|
|
|
CreateIndices(x => x.DeselectedRanges), |
|
|
|
CreateIndices(x => x.SelectedRanges), |
|
|
|
CreateItems(x => x.DeselectedRanges), |
|
|
|
CreateItems(x => x.SelectedRanges)); |
|
|
|
deselectedIndices, |
|
|
|
selectedIndices, |
|
|
|
deselectedItems, |
|
|
|
selectedItems); |
|
|
|
} |
|
|
|
|
|
|
|
private IEnumerable<IndexPath> CreateIndices(Func<SelectionNodeOperation, List<IndexRange>?> selector) |
|
|
|
private IndexPath GetDeselectedIndexAt( |
|
|
|
List<SelectionNodeOperation> infos, |
|
|
|
int index) |
|
|
|
{ |
|
|
|
if (_changes == null) |
|
|
|
{ |
|
|
|
yield break; |
|
|
|
} |
|
|
|
static int GetCount(SelectionNodeOperation info) => info.DeselectedCount; |
|
|
|
static List<IndexRange> GetRanges(SelectionNodeOperation info) => info.DeselectedRanges; |
|
|
|
return GetIndexAt(infos, index, GetCount, GetRanges); |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var i in _changes) |
|
|
|
private IndexPath GetSelectedIndexAt( |
|
|
|
List<SelectionNodeOperation> infos, |
|
|
|
int index) |
|
|
|
{ |
|
|
|
static int GetCount(SelectionNodeOperation info) => info.SelectedCount; |
|
|
|
static List<IndexRange> GetRanges(SelectionNodeOperation info) => info.SelectedRanges; |
|
|
|
return GetIndexAt(infos, index, GetCount, GetRanges); |
|
|
|
} |
|
|
|
|
|
|
|
private object GetDeselectedItemAt( |
|
|
|
List<SelectionNodeOperation> infos, |
|
|
|
int index) |
|
|
|
{ |
|
|
|
static int GetCount(SelectionNodeOperation info) => info.DeselectedCount; |
|
|
|
static List<IndexRange> GetRanges(SelectionNodeOperation info) => info.DeselectedRanges; |
|
|
|
return GetItemAt(infos, index, GetCount, GetRanges); |
|
|
|
} |
|
|
|
|
|
|
|
private object GetSelectedItemAt( |
|
|
|
List<SelectionNodeOperation> infos, |
|
|
|
int index) |
|
|
|
{ |
|
|
|
static int GetCount(SelectionNodeOperation info) => info.SelectedCount; |
|
|
|
static List<IndexRange> GetRanges(SelectionNodeOperation info) => info.SelectedRanges; |
|
|
|
return GetItemAt(infos, index, GetCount, GetRanges); |
|
|
|
} |
|
|
|
|
|
|
|
private IndexPath GetIndexAt( |
|
|
|
List<SelectionNodeOperation> infos, |
|
|
|
int index, |
|
|
|
Func<SelectionNodeOperation, int> getCount, |
|
|
|
Func<SelectionNodeOperation, List<IndexRange>> getRanges) |
|
|
|
{ |
|
|
|
var currentIndex = 0; |
|
|
|
IndexPath path = default; |
|
|
|
|
|
|
|
foreach (var info in infos) |
|
|
|
{ |
|
|
|
var ranges = selector(i); |
|
|
|
var currentCount = getCount(info); |
|
|
|
|
|
|
|
if (ranges != null) |
|
|
|
if (index >= currentIndex && index < currentIndex + currentCount) |
|
|
|
{ |
|
|
|
foreach (var j in ranges) |
|
|
|
{ |
|
|
|
for (var k = j.Begin; k <= j.End; ++k) |
|
|
|
{ |
|
|
|
yield return i.Path.CloneWithChildIndex(k); |
|
|
|
} |
|
|
|
} |
|
|
|
int targetIndex = GetIndexAt(getRanges(info), index - currentIndex); |
|
|
|
path = info.Path.CloneWithChildIndex(targetIndex); |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
currentIndex += currentCount; |
|
|
|
} |
|
|
|
|
|
|
|
return path; |
|
|
|
} |
|
|
|
|
|
|
|
private IEnumerable<object> CreateItems(Func<SelectionNodeOperation, List<IndexRange>?> selector) |
|
|
|
private object GetItemAt( |
|
|
|
List<SelectionNodeOperation> infos, |
|
|
|
int index, |
|
|
|
Func<SelectionNodeOperation, int> getCount, |
|
|
|
Func<SelectionNodeOperation, List<IndexRange>> getRanges) |
|
|
|
{ |
|
|
|
if (_changes == null) |
|
|
|
var currentIndex = 0; |
|
|
|
object item = null; |
|
|
|
|
|
|
|
foreach (var info in infos) |
|
|
|
{ |
|
|
|
yield break; |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
var result = new List<object>(); |
|
|
|
return item; |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var i in _changes) |
|
|
|
private int GetIndexAt(List<IndexRange> ranges, int index) |
|
|
|
{ |
|
|
|
var currentIndex = 0; |
|
|
|
|
|
|
|
foreach (var range in ranges) |
|
|
|
{ |
|
|
|
var ranges = selector(i); |
|
|
|
var currentCount = (range.End - range.Begin) + 1; |
|
|
|
|
|
|
|
if (ranges != null && i.Items != null) |
|
|
|
if (index >= currentIndex && index < currentIndex + currentCount) |
|
|
|
{ |
|
|
|
foreach (var j in ranges) |
|
|
|
{ |
|
|
|
for (var k = j.Begin; k <= j.End; ++k) |
|
|
|
{ |
|
|
|
yield return i.Items.GetAt(k); |
|
|
|
} |
|
|
|
} |
|
|
|
return range.Begin + (index - currentIndex); |
|
|
|
} |
|
|
|
|
|
|
|
currentIndex += currentCount; |
|
|
|
} |
|
|
|
|
|
|
|
throw new IndexOutOfRangeException(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|