getSelectionGeometry method
Gets the combined SelectionGeometry for child Selectables.
Implementation
@protected
SelectionGeometry getSelectionGeometry() {
if (currentSelectionEndIndex == -1 || currentSelectionStartIndex == -1 || selectables.isEmpty) {
// There is no valid selection.
return SelectionGeometry(status: SelectionStatus.none, hasContent: selectables.isNotEmpty);
}
if (!_extendSelectionInProgress) {
currentSelectionStartIndex = _adjustSelectionIndexBasedOnSelectionGeometry(
currentSelectionStartIndex,
currentSelectionEndIndex,
);
currentSelectionEndIndex = _adjustSelectionIndexBasedOnSelectionGeometry(
currentSelectionEndIndex,
currentSelectionStartIndex,
);
}
// Need to find the non-null start selection point.
SelectionGeometry startGeometry = selectables[currentSelectionStartIndex].value;
final bool forwardSelection = currentSelectionEndIndex >= currentSelectionStartIndex;
int startIndexWalker = currentSelectionStartIndex;
while (startIndexWalker != currentSelectionEndIndex &&
startGeometry.startSelectionPoint == null) {
startIndexWalker += forwardSelection ? 1 : -1;
startGeometry = selectables[startIndexWalker].value;
}
SelectionPoint? startPoint;
if (startGeometry.startSelectionPoint != null) {
final Matrix4 startTransform = getTransformFrom(selectables[startIndexWalker]);
final Offset start = MatrixUtils.transformPoint(
startTransform,
startGeometry.startSelectionPoint!.localPosition,
);
// It can be NaN if it is detached or off-screen.
if (start.isFinite) {
startPoint = SelectionPoint(
localPosition: start,
lineHeight: startGeometry.startSelectionPoint!.lineHeight,
handleType: startGeometry.startSelectionPoint!.handleType,
);
}
}
// Need to find the non-null end selection point.
SelectionGeometry endGeometry = selectables[currentSelectionEndIndex].value;
int endIndexWalker = currentSelectionEndIndex;
while (endIndexWalker != currentSelectionStartIndex && endGeometry.endSelectionPoint == null) {
endIndexWalker += forwardSelection ? -1 : 1;
endGeometry = selectables[endIndexWalker].value;
}
SelectionPoint? endPoint;
if (endGeometry.endSelectionPoint != null) {
final Matrix4 endTransform = getTransformFrom(selectables[endIndexWalker]);
final Offset end = MatrixUtils.transformPoint(
endTransform,
endGeometry.endSelectionPoint!.localPosition,
);
// It can be NaN if it is detached or off-screen.
if (end.isFinite) {
endPoint = SelectionPoint(
localPosition: end,
lineHeight: endGeometry.endSelectionPoint!.lineHeight,
handleType: endGeometry.endSelectionPoint!.handleType,
);
}
}
// Need to collect selection rects from selectables ranging from the
// currentSelectionStartIndex to the currentSelectionEndIndex.
final List<Rect> selectionRects = <Rect>[];
final Rect? drawableArea =
hasSize ? Rect.fromLTWH(0, 0, containerSize.width, containerSize.height) : null;
for (int index = currentSelectionStartIndex; index <= currentSelectionEndIndex; index++) {
final List<Rect> currSelectableSelectionRects = selectables[index].value.selectionRects;
final List<Rect> selectionRectsWithinDrawableArea =
currSelectableSelectionRects
.map((Rect selectionRect) {
final Matrix4 transform = getTransformFrom(selectables[index]);
final Rect localRect = MatrixUtils.transformRect(transform, selectionRect);
return drawableArea?.intersect(localRect) ?? localRect;
})
.where((Rect selectionRect) {
return selectionRect.isFinite && !selectionRect.isEmpty;
})
.toList();
selectionRects.addAll(selectionRectsWithinDrawableArea);
}
return SelectionGeometry(
startSelectionPoint: startPoint,
endSelectionPoint: endPoint,
selectionRects: selectionRects,
status: startGeometry != endGeometry ? SelectionStatus.uncollapsed : startGeometry.status,
// Would have at least one selectable child.
hasContent: true,
);
}