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 ChartSegment segment = segments[index];
Color surfaceColor = dataLabelSurfaceColor(
fillPaint.color,
index,
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[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<Offset> connectorPoints = segments[segments.length - 1].points;
final List<Rect> labels = <Rect>[];
final double connectorLength = _calculateConnectorLength(
connectorPoints,
dataLabelSettings,
);
final Paint connectorPaint =
Paint()
..color =
dataLabelSettings.connectorLineSettings.color ??
segments[index].fillPaint.color
..strokeWidth = dataLabelSettings.connectorLineSettings.width
..style = PaintingStyle.stroke;
if ((yValues[index] == 0 && !dataLabelSettings.showZeroValue) ||
yValues[index].isNaN ||
!segments[index].isVisible) {
return;
}
for (int i = 0; i < segments.length; i++) {
final List<Offset> points = segmentAt(i).points;
final Offset point = Offset(
(points[0].dx + points[1].dx) / 2,
(points[0].dy + points[2].dy) / 2,
);
labels.add(
Rect.fromLTWH(
point.dx - (size.width / 2) - labelPadding,
point.dy - (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[index].points,
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 = _isDataLabelIntersectInside(index, labels);
if (isIntersect &&
dataLabelSettings.labelPosition ==
ChartDataLabelPosition.inside &&
dataLabelSettings.color == null &&
!dataLabelSettings.useSeriesColor) {
if (style.color == Colors.transparent) {
surfaceColor = dataLabelSurfaceColor(
fillPaint.color,
index,
ChartDataLabelPosition.outside,
chartThemeData,
themeData,
segment,
);
effectiveTextStyle = saturatedTextStyle(surfaceColor, style);
}
}
if ((isIntersect &&
labelPosition == ChartDataLabelPosition.inside &&
dataLabelSettings.labelIntersectAction ==
LabelIntersectAction.hide) ||
dataLabel == '') {
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;
finalOffset =
dataLabelSettings.labelPosition ==
ChartDataLabelPosition.outside
? offset
: offset + Offset(connectorLength + size.width / 2, 0);
labelRect = _calculateRect(
finalOffset,
labelPadding,
margin,
size,
labelPosition,
);
connectorPath = _drawConnectorPath(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 = _isDataLabelIntersectOutside(
labelRect,
previous,
);
if (!isIntersectOutside && isOverlapRight) {
finalOffset = Offset(
labelRect.left,
(labelRect.top + labelRect.height / 2) - size.height / 2,
);
connectorPath = _drawConnectorPath(index, finalOffset, size);
}
if (dataLabelSettings.labelIntersectAction ==
LabelIntersectAction.hide &&
isIntersectOutside) {
return;
} else if ((isIntersectOutside &&
dataLabelSettings.labelIntersectAction ==
LabelIntersectAction.shift) ||
(isOverlapRight && isIntersectOutside) ||
(isOverlapRight &&
dataLabelSettings.labelPosition ==
ChartDataLabelPosition.outside &&
index != 0)) {
labelRect = RRect.fromRectAndRadius(
Rect.fromLTWH(
labelRect.left,
previous.bottom + 2,
labelRect.width,
labelRect.height,
),
radius,
);
connectorPath =
Path()
..moveTo(startPoint, finalOffset.dy + size.height / 2)
..lineTo(
labelRect.left - connectorPadding,
labelRect.top + labelRect.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 (_plotAreaBounds.height < labelRect.bottom + labelPadding) {
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);
}