moveTo method
Commits a programmatic move of key under newParent at index,
exactly as a pointer drop would: same mutation choice, same
live-space final-list index convention, same onReorder report.
Returns false, mutating and notifying NOTHING, when:
- a drag session is active (see below);
keyis absent or pending deletion;newParentis absent, pending deletion,keyitself, or one ofkey's descendants;- canAcceptDrop rejects the destination;
keyalready occupies that slot.
Refused during a drag on purpose. Mutating structure underneath a live session leaves it resolving against painted offsets that predate the change, collides with the commit script's first-wins FLIP baseline, and can strand the make-room gap on a slot that no longer exists. Callers that genuinely want to interrupt a drag should cancelDrag first.
Implementation
bool moveTo(
TKey key,
TKey? newParent, {
required int index,
bool animate = true,
}) {
if (_session != null) {
return false;
}
if (!_canCommit(key, newParent)) {
return false;
}
// Resolve the index the way [_applyMove] will, so an out-of-range
// request that clamps onto the node's current slot is recognised as
// the no-op it is rather than reported as a move.
final sameParent = treeController.getParent(key) == newParent;
final int destinationLength = newParent == null
? treeController.liveRootCount
: treeController.liveChildCount(newParent);
// The FINAL list excludes `key` only when it is already there.
final effectiveIndex = index.clamp(
0,
sameParent ? destinationLength - 1 : destinationLength,
);
if (sameParent && treeController.getIndexInParent(key) == effectiveIndex) {
return false;
}
if (canAcceptDrop != null &&
!canAcceptDrop!(
movingKey: key,
newParent: newParent,
index: effectiveIndex,
)) {
return false;
}
_fireOnReorder(
_applyMove(key, newParent, effectiveIndex, animate: animate),
);
return true;
}