Skip to content

Commit

Permalink
Short-circuit index check if possible.
Browse files Browse the repository at this point in the history
Not a 100% ideal solution, but should improve things.

Fixes #223.
  • Loading branch information
grokys committed Oct 6, 2023
1 parent bbe7806 commit cd84bef
Showing 1 changed file with 36 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public IndexPath AnchorIndex
get => _anchorIndex;
set
{
if (!TryGetItemAt(value, out _))
if (!IsValidIndex(value))
return;
using var update = BatchUpdate();
update.Operation.AnchorIndex = value;
Expand All @@ -101,7 +101,7 @@ public IndexPath RangeAnchorIndex
get => _rangeAnchorIndex;
set
{
if (!TryGetItemAt(value, out _))
if (!IsValidIndex(value))
return;
using var update = BatchUpdate();
update.Operation.RangeAnchorIndex = value;
Expand Down Expand Up @@ -201,37 +201,6 @@ public bool IsSelected(IndexPath index)
public void Select(IndexPath index) => Select(index, updateRangeAnchorIndex: false);

protected internal abstract IEnumerable<T>? GetChildren(T node);

protected virtual bool TryGetItemAt(IndexPath index, out T? result)
{
var items = (IReadOnlyList<T>?)_root.ItemsView;
var count = index.Count;

for (var i = 0; i < count; ++i)
{
if (items is null)
{
result = default;
return false;
}

var j = index[i];

if (j < items.Count)
{
if (i == count - 1)
{
result = items[j];
return true;
}
else
items = GetChildren(items[j]) as IReadOnlyList<T>;
}
}

result = default;
return false;
}

protected virtual void OnSourceCollectionChangeFinished()
{
Expand Down Expand Up @@ -411,7 +380,7 @@ private IndexPath GetFirstSelectedIndex(TreeSelectionNode<T> node, IndexRanges?

private void Select(IndexPath index, bool updateRangeAnchorIndex)
{
if (index == default || !TryGetItemAt(index, out _))
if (index == default || !IsValidIndex(index))
return;

using var update = BatchUpdate();
Expand Down Expand Up @@ -539,6 +508,39 @@ private int CommitDeselect(IndexRanges selectedRanges)
return result;
}

private bool IsValidIndex(IndexPath index)
{
// If we already have a parent node for the index then we can short-circuit the check.
if (GetNode(index[..^1]) is { } node && node.Source is ICollection source)
return index[^1] < source.Count;

// Otherwise we need to walk the tree to check that the index is valid.
var items = (IReadOnlyList<T>?)_root.ItemsView;
var count = index.Count;

for (var i = 0; i < count; ++i)
{
if (items is null)
{
return false;
}

var j = index[i];

if (j < items.Count)
{
if (i == count - 1)
{
return true;
}
else
items = GetChildren(items[j]) as IReadOnlyList<T>;
}
}

return false;
}

internal static bool ShiftIndex(IndexPath parentIndex, int shiftIndex, int shiftDelta, ref IndexPath path)
{
if (parentIndex.IsAncestorOf(path) && path[parentIndex.Count] >= shiftIndex)
Expand Down

0 comments on commit cd84bef

Please sign in to comment.