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,
);
}