1###############################################################################
2#
3# ChartDoughnut - A class for writing the Excel XLSX Doughnut charts.
4#
5# SPDX-License-Identifier: BSD-2-Clause
6#
7# Copyright (c) 2013-2025, John McNamara, jmcnamara@cpan.org
8#
9
10from warnings import warn
11
12from xlsxwriter import chart_pie
13
14
15class ChartDoughnut(chart_pie.ChartPie):
16 """
17 A class for writing the Excel XLSX Doughnut charts.
18
19
20 """
21
22 ###########################################################################
23 #
24 # Public API.
25 #
26 ###########################################################################
27
28 def __init__(self) -> None:
29 """
30 Constructor.
31
32 """
33 super().__init__()
34
35 self.rotation = 0
36 self.hole_size = 50
37
38 def set_hole_size(self, size: int) -> None:
39 """
40 Set the Doughnut chart hole size.
41
42 Args:
43 size: 10 <= size <= 90.
44
45 Returns:
46 Nothing.
47
48 """
49 if size is None:
50 return
51
52 # Ensure the size is in Excel's range.
53 if size < 10 or size > 90:
54 warn("Chart hole size '{size}' outside Excel range: 10 <= size <= 90")
55 return
56
57 self.hole_size = int(size)
58
59 ###########################################################################
60 #
61 # Private API.
62 #
63 ###########################################################################
64
65 def _write_chart_type(self, args) -> None:
66 # Override the virtual superclass method with a chart specific method.
67 # Write the c:doughnutChart element.
68 self._write_doughnut_chart()
69
70 ###########################################################################
71 #
72 # XML methods.
73 #
74 ###########################################################################
75
76 def _write_doughnut_chart(self) -> None:
77 # Write the <c:doughnutChart> element. Over-ridden method to remove
78 # axis_id code since Doughnut charts don't require val and cat axes.
79 self._xml_start_tag("c:doughnutChart")
80
81 # Write the c:varyColors element.
82 self._write_vary_colors()
83
84 # Write the series elements.
85 for data in self.series:
86 self._write_ser(data)
87
88 # Write the c:firstSliceAng element.
89 self._write_first_slice_ang()
90
91 # Write the c:holeSize element.
92 self._write_c_hole_size()
93
94 self._xml_end_tag("c:doughnutChart")
95
96 def _write_c_hole_size(self) -> None:
97 # Write the <c:holeSize> element.
98 attributes = [("val", self.hole_size)]
99
100 self._xml_empty_tag("c:holeSize", attributes)