decorate method

  1. @override
void decorate(
  1. List<ArcRendererElementList<D>> arcElementsList,
  2. ChartCanvas canvas,
  3. GraphicsFactory graphicsFactory, {
  4. required Rectangle<num> drawBounds,
  5. required double animationPercent,
  6. bool rtl = false,
})

Implementation

@override
void decorate(
  List<ArcRendererElementList<D>> arcElementsList,
  ChartCanvas canvas,
  GraphicsFactory graphicsFactory, {
  required Rectangle drawBounds,
  required double animationPercent,
  bool rtl = false,
}) {
  // Only decorate the arcs when animation is at 100%.
  if (animationPercent != 1.0) {
    return;
  }

  // Create [TextStyle] from [TextStyleSpec] to be used by all the elements.
  // The [GraphicsFactory] is needed so it can't be created earlier.
  final insideLabelStyle =
      _getTextStyle(graphicsFactory, insideLabelStyleSpec);
  final outsideLabelStyle =
      _getTextStyle(graphicsFactory, outsideLabelStyleSpec);

  // Track the Y position of the previous outside label for collision
  // detection purposes.
  for (final arcElements in arcElementsList) {
    _previousOutsideLabelY = null;
    _previousLabelLeftOfChart = null;

    for (final element in arcElements.arcs) {
      final labelFn = element.series.labelAccessorFn;
      final datumIndex = element.index;
      final label = (labelFn != null) ? labelFn(datumIndex) : null;

      // If there are custom styles, use that instead of the default or the
      // style defined for the entire decorator.
      final datumInsideLabelStyle = _getDatumStyle(
        element.series.insideLabelStyleAccessorFn,
        datumIndex,
        graphicsFactory,
        defaultStyle: insideLabelStyle,
      );
      final datumOutsideLabelStyle = _getDatumStyle(
        element.series.outsideLabelStyleAccessorFn,
        datumIndex,
        graphicsFactory,
        defaultStyle: outsideLabelStyle,
      );

      // Skip calculation and drawing for this element if no label.
      if (label == null || label.isEmpty) {
        continue;
      }

      final arcAngle = element.endAngle - element.startAngle;

      final centerAngle = element.startAngle + (arcAngle / 2);

      final centerRadius = arcElements.innerRadius +
          ((arcElements.radius - arcElements.innerRadius) / 2);

      final outerPoint = Point<double>(
        arcElements.center.x + arcElements.radius * cos(centerAngle),
        arcElements.center.y + arcElements.radius * sin(centerAngle),
      );

      final bounds =
          Rectangle<double>.fromPoints(arcElements.center, outerPoint);

      // Get space available inside and outside the arc.
      final totalPadding = labelPadding * 2;
      final insideArcWidth = min(
        (((arcAngle * 180 / pi) / 360) * (2 * pi * centerRadius)).round(),
        (arcElements.radius - arcElements.innerRadius) - labelPadding,
      ).round();

      final leaderLineLength =
          showLeaderLines ? leaderLineStyleSpec.length : 0;

      final outsideArcWidth = ((drawBounds.width / 2) -
              bounds.width -
              totalPadding -
              // Half of the leader line is drawn inside the arc
              leaderLineLength / 2)
          .round();

      final labelElement = graphicsFactory.createTextElement(label)
        ..maxWidthStrategy = MaxWidthStrategy.ellipsize;

      final calculatedLabelPosition = calculateLabelPosition(
        labelElement,
        datumInsideLabelStyle,
        insideArcWidth,
        outsideArcWidth,
        element,
        labelPosition,
      );

      // Set the max width and text style.
      if (calculatedLabelPosition == ArcLabelPosition.inside) {
        labelElement
          ..textStyle = datumInsideLabelStyle
          ..maxWidth = insideArcWidth;
      } else {
        // calculatedLabelPosition == LabelPosition.outside
        labelElement
          ..textStyle = datumOutsideLabelStyle
          ..maxWidth = outsideArcWidth;
      }

      // Only calculate and draw label if there's actually space for the
      // label.
      if (labelElement.maxWidth! > 0) {
        // Calculate the start position of label based on [labelAnchor].
        if (calculatedLabelPosition == ArcLabelPosition.inside) {
          _drawInsideLabel(canvas, arcElements, labelElement, centerAngle);
        } else {
          final l = _drawOutsideLabel(
            canvas,
            drawBounds,
            arcElements,
            labelElement,
            centerAngle,
          );

          if (l != null) {
            updateCollisionDetectionParams(l);
          }
        }
      }
    }
  }
}