|
|
@ -252,7 +252,6 @@ namespace Avalonia.Layout |
|
|
(orientation == ScrollOrientation.Vertical ? ScrollOrientation.Horizontal : ScrollOrientation.Vertical) : |
|
|
(orientation == ScrollOrientation.Vertical ? ScrollOrientation.Horizontal : ScrollOrientation.Vertical) : |
|
|
orientation; |
|
|
orientation; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var windowStart = effectiveOrientation == ScrollOrientation.Vertical ? window.Y : window.X; |
|
|
var windowStart = effectiveOrientation == ScrollOrientation.Vertical ? window.Y : window.X; |
|
|
var windowEnd = effectiveOrientation == ScrollOrientation.Vertical ? window.Y + window.Height : window.X + window.Width; |
|
|
var windowEnd = effectiveOrientation == ScrollOrientation.Vertical ? window.Y + window.Height : window.X + window.Width; |
|
|
var firstElementStart = effectiveOrientation == ScrollOrientation.Vertical ? firstElementBounds.Y : firstElementBounds.X; |
|
|
var firstElementStart = effectiveOrientation == ScrollOrientation.Vertical ? firstElementBounds.Y : firstElementBounds.X; |
|
|
@ -273,53 +272,53 @@ namespace Avalonia.Layout |
|
|
switch (args.Action) |
|
|
switch (args.Action) |
|
|
{ |
|
|
{ |
|
|
case NotifyCollectionChangedAction.Add: |
|
|
case NotifyCollectionChangedAction.Add: |
|
|
{ |
|
|
{ |
|
|
OnItemsAdded(args.NewStartingIndex, args.NewItems.Count); |
|
|
OnItemsAdded(args.NewStartingIndex, args.NewItems.Count); |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case NotifyCollectionChangedAction.Replace: |
|
|
case NotifyCollectionChangedAction.Replace: |
|
|
{ |
|
|
|
|
|
int oldSize = args.OldItems.Count; |
|
|
|
|
|
int newSize = args.NewItems.Count; |
|
|
|
|
|
int oldStartIndex = args.OldStartingIndex; |
|
|
|
|
|
int newStartIndex = args.NewStartingIndex; |
|
|
|
|
|
|
|
|
|
|
|
if (oldSize == newSize && |
|
|
|
|
|
oldStartIndex == newStartIndex && |
|
|
|
|
|
IsDataIndexRealized(oldStartIndex) && |
|
|
|
|
|
IsDataIndexRealized(oldStartIndex + oldSize -1)) |
|
|
|
|
|
{ |
|
|
{ |
|
|
// Straight up replace of n items within the realization window.
|
|
|
int oldSize = args.OldItems.Count; |
|
|
// Removing and adding might causes us to lose the anchor causing us
|
|
|
int newSize = args.NewItems.Count; |
|
|
// to throw away all containers and start from scratch.
|
|
|
int oldStartIndex = args.OldStartingIndex; |
|
|
// Instead, we can just clear those items and set the element to
|
|
|
int newStartIndex = args.NewStartingIndex; |
|
|
// null (sentinel) and let the next measure get new containers for them.
|
|
|
|
|
|
var startRealizedIndex = GetRealizedRangeIndexFromDataIndex(oldStartIndex); |
|
|
if (oldSize == newSize && |
|
|
for (int realizedIndex = startRealizedIndex; realizedIndex < startRealizedIndex + oldSize; realizedIndex++) |
|
|
oldStartIndex == newStartIndex && |
|
|
|
|
|
IsDataIndexRealized(oldStartIndex) && |
|
|
|
|
|
IsDataIndexRealized(oldStartIndex + oldSize - 1)) |
|
|
{ |
|
|
{ |
|
|
var elementRef = _realizedElements[realizedIndex]; |
|
|
// Straight up replace of n items within the realization window.
|
|
|
|
|
|
// Removing and adding might causes us to lose the anchor causing us
|
|
|
if (elementRef != null) |
|
|
// to throw away all containers and start from scratch.
|
|
|
|
|
|
// Instead, we can just clear those items and set the element to
|
|
|
|
|
|
// null (sentinel) and let the next measure get new containers for them.
|
|
|
|
|
|
var startRealizedIndex = GetRealizedRangeIndexFromDataIndex(oldStartIndex); |
|
|
|
|
|
for (int realizedIndex = startRealizedIndex; realizedIndex < startRealizedIndex + oldSize; realizedIndex++) |
|
|
{ |
|
|
{ |
|
|
_context.RecycleElement(elementRef); |
|
|
var elementRef = _realizedElements[realizedIndex]; |
|
|
_realizedElements[realizedIndex] = null; |
|
|
|
|
|
|
|
|
if (elementRef != null) |
|
|
|
|
|
{ |
|
|
|
|
|
_context.RecycleElement(elementRef); |
|
|
|
|
|
_realizedElements[realizedIndex] = null; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
OnItemsRemoved(oldStartIndex, oldSize); |
|
|
|
|
|
OnItemsAdded(newStartIndex, newSize); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
else |
|
|
break; |
|
|
{ |
|
|
|
|
|
OnItemsRemoved(oldStartIndex, oldSize); |
|
|
|
|
|
OnItemsAdded(newStartIndex, newSize); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case NotifyCollectionChangedAction.Remove: |
|
|
case NotifyCollectionChangedAction.Remove: |
|
|
{ |
|
|
{ |
|
|
OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count); |
|
|
OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count); |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
|
|
|
|
|
|
case NotifyCollectionChangedAction.Reset: |
|
|
case NotifyCollectionChangedAction.Reset: |
|
|
ClearRealizedRange(); |
|
|
ClearRealizedRange(); |
|
|
@ -376,7 +375,7 @@ namespace Avalonia.Layout |
|
|
int backCutoffIndex = realizedRangeSize; |
|
|
int backCutoffIndex = realizedRangeSize; |
|
|
|
|
|
|
|
|
for (int i = 0; |
|
|
for (int i = 0; |
|
|
i<realizedRangeSize && |
|
|
i < realizedRangeSize && |
|
|
!Intersects(window, _realizedElementLayoutBounds[i], orientation); |
|
|
!Intersects(window, _realizedElementLayoutBounds[i], orientation); |
|
|
++i) |
|
|
++i) |
|
|
{ |
|
|
{ |
|
|
@ -391,7 +390,7 @@ namespace Avalonia.Layout |
|
|
--backCutoffIndex; |
|
|
--backCutoffIndex; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (backCutoffIndex<realizedRangeSize - 1) |
|
|
if (backCutoffIndex < realizedRangeSize - 1) |
|
|
{ |
|
|
{ |
|
|
ClearRealizedRange(backCutoffIndex + 1, realizedRangeSize - backCutoffIndex - 1); |
|
|
ClearRealizedRange(backCutoffIndex + 1, realizedRangeSize - backCutoffIndex - 1); |
|
|
} |
|
|
} |
|
|
@ -419,7 +418,7 @@ namespace Avalonia.Layout |
|
|
// to insert items.
|
|
|
// to insert items.
|
|
|
int lastRealizedDataIndex = _firstRealizedDataIndex + GetRealizedElementCount() - 1; |
|
|
int lastRealizedDataIndex = _firstRealizedDataIndex + GetRealizedElementCount() - 1; |
|
|
int newStartingIndex = index; |
|
|
int newStartingIndex = index; |
|
|
if (newStartingIndex > _firstRealizedDataIndex && |
|
|
if (newStartingIndex >= _firstRealizedDataIndex && |
|
|
newStartingIndex <= lastRealizedDataIndex) |
|
|
newStartingIndex <= lastRealizedDataIndex) |
|
|
{ |
|
|
{ |
|
|
// Inserted within the realized range
|
|
|
// Inserted within the realized range
|
|
|
|