drawDataLabelWithBackground method

void drawDataLabelWithBackground(
  1. int index,
  2. Canvas canvas,
  3. String dataLabel,
  4. Size size,
  5. Offset offset,
  6. int angle,
  7. TextStyle style,
  8. Paint fillPaint,
  9. Paint strokePaint,
  10. Path connectorPath,
  11. List<RRect> previousRect,
)

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