collides method
Returns a CollisionReport
indicating if there are any collisions.
Implementation
@override
CollisionReport<D> collides(
List<Tick<D>>? ticks,
AxisOrientation? orientation,
) {
// TODO: Collision analysis for rotated labels are not
// supported yet.
// If there are no ticks, they do not collide.
if (ticks == null) {
return CollisionReport(
ticksCollide: false,
ticks: ticks,
alternateTicksUsed: false,
);
}
final vertical = orientation == AxisOrientation.left ||
orientation == AxisOrientation.right;
ticks = [
for (final tick in ticks)
if (tick.locationPx != null) tick,
]
// First sort ticks by smallest locationPx first (NOT sorted by value).
// This allows us to only check if a tick collides with the previous tick.
..sort((a, b) => a.locationPx!.compareTo(b.locationPx!));
var previousEnd = double.negativeInfinity;
var collides = false;
for (final tick in ticks) {
final tickSize = tick.textElement?.measurement;
final tickLocationPx = tick.locationPx!;
if (vertical) {
final adjustedHeight = (tickSize?.verticalSliceWidth ?? 0.0) +
minimumPaddingBetweenLabelsPx;
if (_defaultTickLabelAnchor == TickLabelAnchor.inside) {
if (identical(tick, ticks.first)) {
// Top most tick draws down from the location
collides = false;
previousEnd = tickLocationPx + adjustedHeight;
} else if (identical(tick, ticks.last)) {
// Bottom most tick draws up from the location
collides = previousEnd > tickLocationPx - adjustedHeight;
previousEnd = tickLocationPx;
} else {
// All other ticks is centered.
final halfHeight = adjustedHeight / 2;
collides = previousEnd > tickLocationPx - halfHeight;
previousEnd = tickLocationPx + halfHeight;
}
} else {
collides = previousEnd > tickLocationPx;
previousEnd = tickLocationPx + adjustedHeight;
}
} else {
// Use the text direction the ticks specified, unless the label anchor
// is set to [TickLabelAnchor.inside]. When 'inside' is set, the text
// direction is normalized such that the left most tick is drawn ltr,
// the last tick is drawn rtl, and all other ticks are in the center.
// This is not set until it is painted, so collision check needs to get
// the value also.
final textDirection = _normalizeHorizontalAnchor(
_defaultTickLabelAnchor,
chartContext.isRtl,
identical(tick, ticks.first),
identical(tick, ticks.last),
);
final adjustedWidth = (tickSize?.horizontalSliceWidth ?? 0.0) +
minimumPaddingBetweenLabelsPx;
switch (textDirection) {
case TextDirection.ltr:
collides = previousEnd > tickLocationPx;
previousEnd = tickLocationPx + adjustedWidth;
case TextDirection.rtl:
collides = previousEnd > (tickLocationPx - adjustedWidth);
previousEnd = tickLocationPx;
case TextDirection.center:
final halfWidth = adjustedWidth / 2;
collides = previousEnd > tickLocationPx - halfWidth;
previousEnd = tickLocationPx + halfWidth;
}
}
if (collides) {
return CollisionReport(
ticksCollide: true,
ticks: ticks,
alternateTicksUsed: false,
);
}
}
return CollisionReport(
ticksCollide: false,
ticks: ticks,
alternateTicksUsed: false,
);
}