reorderChildren method
Reorders the children of parentKey to match orderedKeys.
orderedKeys must contain exactly the current live (non-pending-deletion)
children of parentKey. Expansion state, animation state, and measured
extents are preserved.
Implementation
void reorderChildren(TKey parentKey, List<TKey> orderedKeys) {
if (!_hasKey(parentKey)) {
throw ArgumentError.value(parentKey, "parentKey", "not found");
}
final currentChildren = _childListOf(parentKey) ?? <TKey>[];
final pendingChildren = <TKey>[];
final liveChildSet = <TKey>{};
for (final k in currentChildren) {
if (_isPendingDeletion(k)) {
pendingChildren.add(k);
} else {
liveChildSet.add(k);
}
}
// Validate in all build modes — see reorderRoots for rationale.
if (orderedKeys.length != liveChildSet.length ||
orderedKeys.toSet().length != orderedKeys.length ||
!liveChildSet.containsAll(orderedKeys)) {
throw ArgumentError.value(
orderedKeys,
"orderedKeys",
"must contain exactly the current live children of $parentKey with "
"no duplicates",
);
}
_setChildList(parentKey, [...orderedKeys, ...pendingChildren]);
bool needsVisibleRebuild =
_isExpandedKey(parentKey) && _ancestorsExpandedFast(parentKey);
if (!needsVisibleRebuild) {
// Even if the parent is not expanded, children may still be present
// in _visibleOrder because they are mid-animation (collapse in
// progress, pending-deletion exit). Those entries would otherwise
// retain the old order until the animation completes.
for (final child in _childListOf(parentKey)!) {
if (_hasOperationGroup(child) ||
_bulkAnimationGroup?.members.contains(child) == true ||
_hasStandalone(child)) {
needsVisibleRebuild = true;
break;
}
}
}
if (needsVisibleRebuild) {
_markVisibleOrderDirty();
}
// See reorderRoots: pure reorder — no builder output changes.
_notifyStructural(affectedKeys: const {});
}