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