drawDataLabelWithBackground method
void
drawDataLabelWithBackground()
Implementation
void drawDataLabelWithBackground(
int index,
Canvas canvas,
String dataLabel,
Size size,
Offset offset,
int angle,
TextStyle style,
Paint fillPaint,
Paint strokePaint,
Path connectorPath,
List<RRect> previousRect,
) {
final SfChartThemeData chartThemeData = parent!.chartThemeData!;
final ThemeData themeData = parent!.themeData!;
final int segmentsLastIndex = segments.length - 1;
final int dataPointIndex = segmentsLastIndex - index;
final ChartSegment segment = segments[dataPointIndex];
Color surfaceColor = dataLabelSurfaceColor(fillPaint.color, dataPointIndex,
dataLabelSettings.labelPosition, chartThemeData, themeData, segment);
TextStyle effectiveTextStyle = saturatedTextStyle(surfaceColor, style);
final EdgeInsets margin = dataLabelSettings.margin;
final Radius radius = Radius.circular(dataLabelSettings.borderRadius);
Offset finalOffset = offset;
final List<Offset> points = segments[segmentsLastIndex - index].points;
bool isOverlapRight = false;
final double startPoint = (points[1].dx + points[2].dx) / 2;
ChartDataLabelPosition labelPosition = dataLabelSettings.labelPosition;
const int labelPadding = 2;
const int connectorPadding = 15;
final List<Rect> labels = <Rect>[];
final List<Offset> connectorPoints = segments[0].points;
final double connectorLength = _calculateConnectorLength(
connectorPoints,
dataLabelSettings,
);
final Paint connectorPaint = Paint()
..color = dataLabelSettings.connectorLineSettings.color ??
segments[segmentsLastIndex - index].fillPaint.color
..strokeWidth = dataLabelSettings.connectorLineSettings.width
..style = PaintingStyle.stroke;
if ((yValues[index] == 0 && !dataLabelSettings.showZeroValue) ||
yValues[index].isNaN ||
!segments[segmentsLastIndex - index].isVisible) {
return;
}
for (int i = segmentsLastIndex; i >= 0; i--) {
final Rect region = _calculateSegmentRect(segmentAt(i).points, i);
labels.add(Rect.fromLTWH(
region.left + region.width / 2 - (size.width / 2) - labelPadding,
region.top + region.height / 2 - (size.height / 2) - labelPadding,
size.width + (2 * labelPadding),
size.height + (2 * labelPadding)));
}
if (!offset.dx.isNaN && !offset.dy.isNaN) {
if (dataLabel.isNotEmpty) {
if (fillPaint.color != Colors.transparent ||
(strokePaint.color != const Color.fromARGB(0, 25, 5, 5) &&
strokePaint.strokeWidth > 0)) {
RRect labelRect =
_calculateRect(offset, labelPadding, margin, size, labelPosition);
final Rect region = _calculateSegmentRect(
segments[segmentsLastIndex - index].points,
segmentsLastIndex - index);
final bool isDataLabelCollide = (_findingCollision(
labels[index], previousRect, region)) &&
dataLabelSettings.labelPosition != ChartDataLabelPosition.outside;
if (isDataLabelCollide) {
switch (dataLabelSettings.overflowMode) {
case OverflowMode.trim:
dataLabel = _getTrimmedText(dataLabel, labels[index],
finalOffset, region, effectiveTextStyle);
final Size trimSize =
measureText(dataLabel, effectiveTextStyle);
finalOffset = Offset(
finalOffset.dx + size.width / 2 - trimSize.width / 2,
finalOffset.dy + size.height / 2 - trimSize.height / 2);
labelRect = RRect.fromRectAndRadius(
Rect.fromLTWH(
finalOffset.dx - labelPadding,
finalOffset.dy - labelPadding,
trimSize.width + (2 * labelPadding),
trimSize.height + (2 * labelPadding)),
radius);
break;
case OverflowMode.hide:
dataLabel = '';
break;
case OverflowMode.shift:
break;
// ignore: no_default_cases
default:
break;
}
}
final bool isIntersect = _isFunnelLabelIntersectInside(index, labels);
if (isIntersect &&
dataLabelSettings.labelPosition ==
ChartDataLabelPosition.inside &&
dataLabelSettings.color == null &&
!dataLabelSettings.useSeriesColor) {
if (style.color == Colors.transparent) {
surfaceColor = dataLabelSurfaceColor(
fillPaint.color,
dataPointIndex,
ChartDataLabelPosition.outside,
chartThemeData,
themeData,
segment);
effectiveTextStyle = saturatedTextStyle(surfaceColor, style);
}
}
if ((isIntersect &&
labelPosition == ChartDataLabelPosition.inside &&
dataLabelSettings.labelIntersectAction ==
LabelIntersectAction.hide) ||
dataLabel == '' ||
(index == 0 &&
(dataLabelSettings.overflowMode == OverflowMode.hide ||
dataLabelSettings.overflowMode == OverflowMode.trim))) {
return;
} else if (isIntersect &&
labelPosition == ChartDataLabelPosition.inside &&
dataLabelSettings.labelIntersectAction ==
LabelIntersectAction.none) {
} else if ((isDataLabelCollide &&
dataLabelSettings.overflowMode == OverflowMode.shift) ||
isIntersect ||
(dataLabelSettings.labelPosition ==
ChartDataLabelPosition.outside)) {
labelPosition = ChartDataLabelPosition.outside;
offset =
dataLabelSettings.labelPosition == ChartDataLabelPosition.inside
? Offset((points[0].dx + points[1].dx) / 2 - size.width / 2,
(points[0].dy + points[2].dy) / 2 - size.height / 2)
: offset;
finalOffset = dataLabelSettings.labelPosition ==
ChartDataLabelPosition.outside
? offset
: offset + Offset(connectorLength + size.width / 2, 0);
labelRect = _calculateRect(
finalOffset, labelPadding, margin, size, labelPosition);
connectorPath = _calculateConnectorPath(index, finalOffset, size);
if (_plotAreaBounds.right < labelRect.right) {
isOverlapRight = true;
labelRect = RRect.fromRectAndRadius(
Rect.fromLTRB(
_plotAreaBounds.right - labelRect.width - labelPadding,
labelRect.top,
_plotAreaBounds.right - labelPadding,
labelRect.bottom),
radius);
}
final RRect previous = previousRect.isEmpty
? labelRect
: previousRect[previousRect.length - 1];
final bool isIntersectOutside =
_isFunnelLabelIntersectOutside(labelRect, previous);
if (!isIntersectOutside && isOverlapRight) {
finalOffset = Offset(labelRect.left,
(labelRect.top + labelRect.height / 2) - size.height / 2);
connectorPath = _calculateConnectorPath(index, finalOffset, size);
}
if (dataLabelSettings.labelIntersectAction ==
LabelIntersectAction.hide &&
isIntersectOutside) {
return;
} else if (isIntersectOutside &&
dataLabelSettings.labelIntersectAction ==
LabelIntersectAction.shift) {
labelRect = RRect.fromRectAndRadius(
Rect.fromLTWH(
labelRect.left,
previous.top - labelPadding - labelRect.height,
labelRect.width,
labelRect.height),
radius);
connectorPath = Path()
..moveTo(startPoint, finalOffset.dy + size.height / 2)
..lineTo(labelRect.left - connectorPadding,
finalOffset.dy + size.height / 2)
..lineTo(labelRect.left, labelRect.top + labelRect.height / 2);
}
finalOffset = Offset(labelRect.left + margin.left,
(labelRect.top + labelRect.height / 2) - size.height / 2);
}
previousRect.add(labelRect);
if (labelRect.top < dataLabelSettings.margin.top) {
return;
}
if (labelPosition == ChartDataLabelPosition.outside) {
canvas.drawPath(connectorPath, connectorPaint);
}
canvas.save();
canvas.translate(labelRect.center.dx, labelRect.center.dy);
canvas.rotate((angle * pi) / 180);
canvas.translate(-labelRect.center.dx, -labelRect.center.dy);
if (strokePaint.color != Colors.transparent &&
strokePaint.strokeWidth > 0) {
canvas.drawRRect(labelRect, strokePaint);
}
if (fillPaint.color != Colors.transparent) {
canvas.drawRRect(labelRect, fillPaint);
}
canvas.restore();
}
}
}
drawDataLabel(canvas, dataLabel, finalOffset, effectiveTextStyle, angle);
}