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 (var arcElements in arcElementsList) {
    _previousOutsideLabelY = null;
    _previousLabelLeftOfChart = null;

    for (var 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;

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

      // Set the max width and text style.
      if (calculatedLabelPosition == ArcLabelPosition.inside) {
        labelElement.textStyle = datumInsideLabelStyle;
        labelElement.maxWidth = insideArcWidth;
      } else {
        // calculatedLabelPosition == LabelPosition.outside
        labelElement.textStyle = datumOutsideLabelStyle;
        labelElement.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);
          }
        }
      }
    }
  }
}