decorate method

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

Implementation

@override
void decorate(ArcRendererElementList<D> arcElements, 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.
  num? previousOutsideLabelY;
  bool? previousLabelLeftOfChart;

  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 innerPoint = Point<double>(
        arcElements.center.x + arcElements.innerRadius * cos(centerAngle),
        arcElements.center.y + arcElements.innerRadius * sin(centerAngle));

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

    //final bounds = element.bounds;
    final bounds = Rectangle<double>.fromPoints(innerPoint, 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 -
            leaderLineLength)
        .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,
            previousOutsideLabelY,
            previousLabelLeftOfChart);

        // List destructuring.
        if (l != null) {
          previousLabelLeftOfChart = l[0] as bool;
          previousOutsideLabelY = l[1] as int;
        }
      }
    }
  }
}