Skip to content

Add DonutChart diagram type#113

Draft
johnjehiel wants to merge 2 commits intoMerrimanInd:devfrom
johnjehiel:feature/donut-chart
Draft

Add DonutChart diagram type#113
johnjehiel wants to merge 2 commits intoMerrimanInd:devfrom
johnjehiel:feature/donut-chart

Conversation

@johnjehiel
Copy link
Copy Markdown
Contributor

@johnjehiel johnjehiel commented Dec 21, 2025

This PR introduces a new DonutChart diagram type, built entirely from Object, Group, and a new DonutArc extended object, which is based on mxgraph.basic.partConcEllipse infographics shape.
The design closely follows the conventions and workflow established by PieChart and BarChart, while extending them with annotation-based labeling for greater flexibility.

Annotation-based design

class AnnotationPosition(Enum):
    INSIDE = 0.6
    MIDDLE = 1.0
    OUTSIDE = 1.4

@dataclass(frozen=True)
class ArcAnnotation:
    name: str = "Annotation"
    formatter: Callable[[str, float, float], str] = (
        lambda label, value, total: f"{value/total:.1%}"
    )
    position: Union[AnnotationPosition, float] = AnnotationPosition.MIDDLE
    text_format: Optional[TextFormat] = None

Instead of a single hard-coded label/value pair, DonutChart uses annotations:

  • Each arc can render multiple annotations
  • Each annotation controls:
    • Its own formatter
    • Its own radial position
  • Supported default positions:
    • INSIDE
    • MIDDLE
    • OUTSIDE
  • Custom radial offsets are also supported

This design avoids label/value overlap issues and gives users full control over presentation without workarounds.

Few example usages

Labels inside, values in the middle

chart = DonutChart(
    data=data,
    title="PERSONAL ACCOUNTING",
    ...
    annotations=[
        ArcAnnotation(
            name="Label",
            position=AnnotationPosition.INSIDE,
            formatter=lambda label, value, total: label,
        ),
        ArcAnnotation(
            name="Value",
            position=AnnotationPosition.MIDDLE,
            formatter=lambda label, value, total: f"{value/total:.1%}",
        ),
    ],
)
Screenshot 2025-12-21 202914

Labels and values in the middle

chart = DonutChart(
    data=data,
    title="PERSONAL ACCOUNTING",
    ...
    annotations=[
        ArcAnnotation(
            name="Label",
            position=AnnotationPosition.MIDDLE,
            formatter=lambda label, value, total: f"{label} ({value/total:.1%})",
        ),
    ],
)
Screenshot 2025-12-21 202926

Labels outside, values middle

chart = DonutChart(
    data=data,
    title="PERSONAL ACCOUNTING",
    ...
    annotations=[
        ArcAnnotation(
            name="Label",
            position=AnnotationPosition.OUTSIDE,
            formatter=lambda label, value, total: label,
        ),
        ArcAnnotation(
            name="Value",
            position=AnnotationPosition.MIDDLE,
            formatter=lambda label, value, total: f"{value/total:.1%}",
        ),
    ],
)
Screenshot 2025-12-21 202944

PR Roadmap

  • Addition of relevant infographic shapes ✔️
  • DiagramType ✔️
  • Development Scripts
  • Tests
  • Documentation / README update

Before proceeding with development scripts, tests and documentation, I’d appreciate a review of the current implementation, especially the annotation based design (which can also be extended to existing pie chart implementation).

- Add partial_concentric_ellipse shape to infographics library
- Introduce DonutArc extended object based on mxgraph.basic.partConcEllipse
- Add implementation for DonutChart
@ibirothe ibirothe linked an issue Dec 21, 2025 that may be closed by this pull request
@ibirothe
Copy link
Copy Markdown
Collaborator

This is gold! I love it.

Definitely going to add the annotation-based approach to PieChart once this is merged!

@ibirothe
Copy link
Copy Markdown
Collaborator

If there is one thing I could add to this, it would be the option to place the title either above (as in your examples) or in the middle of the donut (as this is something I see a lot, especially when having multiple DonutCharts alongside).

@ibirothe ibirothe changed the base branch from main to dev December 31, 2025 22:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DonutChart diagram type

2 participants