@@ -19,26 +19,27 @@ import androidx.compose.runtime.saveable.rememberSaveable
1919import androidx.compose.ui.Modifier
2020import androidx.compose.ui.geometry.Size
2121import androidx.compose.ui.graphics.Color
22+ import androidx.compose.ui.graphics.NativeCanvas
2223import androidx.compose.ui.graphics.nativeCanvas
2324import androidx.compose.ui.graphics.toArgb
2425import androidx.compose.ui.input.pointer.pointerInput
2526import androidx.compose.ui.platform.LocalContext
2627import androidx.compose.ui.semantics.contentDescription
2728import androidx.compose.ui.semantics.semantics
2829import androidx.compose.ui.unit.dp
30+ import co.yml.charts.common.components.accessibility.AccessibilityBottomSheetDialog
31+ import co.yml.charts.common.components.accessibility.SliceInfo
32+ import co.yml.charts.common.extensions.collectIsTalkbackEnabledAsState
33+ import co.yml.charts.common.model.PlotType
34+ import co.yml.charts.ui.piechart.PieChartConstants.NO_SELECTED_SLICE
2935import co.yml.charts.ui.piechart.models.PieChartConfig
3036import co.yml.charts.ui.piechart.models.PieChartData
3137import co.yml.charts.ui.piechart.utils.convertTouchEventPointToAngle
3238import co.yml.charts.ui.piechart.utils.proportion
3339import co.yml.charts.ui.piechart.utils.sweepAngles
34- import co.yml.charts.common.components.accessibility.AccessibilityBottomSheetDialog
35- import co.yml.charts.common.components.accessibility.SliceInfo
36- import co.yml.charts.common.extensions.collectIsTalkbackEnabledAsState
37- import co.yml.charts.common.model.PlotType
3840import kotlinx.coroutines.launch
3941import kotlin.math.roundToInt
4042
41-
4243/* *
4344 * Compose function for Drawing Donut chart
4445 * @param modifier : All modifier related property
@@ -71,7 +72,7 @@ fun DonutPieChart(
7172 }
7273
7374 var activePie by rememberSaveable {
74- mutableStateOf(- 1 )
75+ mutableStateOf(NO_SELECTED_SLICE )
7576 }
7677 val accessibilitySheetState =
7778 rememberModalBottomSheetState(initialValue = ModalBottomSheetValue .Hidden )
@@ -89,9 +90,9 @@ fun DonutPieChart(
8990 Surface (
9091 modifier = modifier
9192 ) {
92- BoxWithConstraints (
93- modifier = modifier
94- .aspectRatio(1f )
93+ val boxModifier = if (pieChartConfig.isClickOnSliceEnabled) {
94+ modifier
95+ .aspectRatio(ratio = 1f )
9596 .background(pieChartConfig.backgroundColor)
9697 .semantics {
9798 contentDescription = pieChartConfig.accessibilityConfig.chartDescription
@@ -102,7 +103,17 @@ fun DonutPieChart(
102103 accessibilitySheetState.show()
103104 }
104105 }
105- }) {
106+ }
107+ } else {
108+ modifier
109+ .aspectRatio(1f )
110+ .semantics {
111+ contentDescription = pieChartConfig.accessibilityConfig.chartDescription
112+ }
113+ }
114+ BoxWithConstraints (
115+ modifier = boxModifier
116+ ) {
106117
107118 val sideSize = Integer .min(constraints.maxWidth, constraints.maxHeight)
108119 val padding = (sideSize * pieChartConfig.chartPadding) / 100f
@@ -120,12 +131,11 @@ fun DonutPieChart(
120131 }
121132 }
122133
123- Canvas (
124- modifier = Modifier
134+ val canvasModifier = if (pieChartConfig.isClickOnSliceEnabled) {
135+ Modifier
125136 .width(sideSize.dp)
126137 .height(sideSize.dp)
127138 .pointerInput(true ) {
128-
129139 detectTapGestures {
130140 val clickedAngle = convertTouchEventPointToAngle(
131141 sideSize.toFloat(),
@@ -135,14 +145,23 @@ fun DonutPieChart(
135145 )
136146 progressSize.forEachIndexed { index, item ->
137147 if (clickedAngle <= item) {
138- if (activePie != index)
139- activePie = index
148+ activePie = if (activePie != index)
149+ index
150+ else
151+ NO_SELECTED_SLICE
140152 onSliceClick(pieChartData.slices[index])
141153 return @detectTapGestures
142154 }
143155 }
144156 }
145157 }
158+ } else {
159+ Modifier
160+ .width(sideSize.dp)
161+ .height(sideSize.dp)
162+ }
163+ Canvas (
164+ modifier = canvasModifier
146165
147166 ) {
148167
@@ -163,22 +182,54 @@ fun DonutPieChart(
163182 )
164183 sAngle + = arcProgress
165184 }
166-
167- if (activePie != - 1 && pieChartConfig.percentVisible)
168- drawContext.canvas.nativeCanvas.apply {
169- val fontSize = pieChartConfig.percentageFontSize.toPx()
170- drawText(
171- " ${proportions[activePie].roundToInt()} %" ,
172- (sideSize / 2 ) + fontSize / 4 , (sideSize / 2 ) + fontSize / 3 ,
173- Paint ().apply {
174- color = pieChartConfig.percentColor.toArgb()
175- textSize = fontSize
176- textAlign = Paint .Align .CENTER
177- typeface = pieChartConfig.percentageTypeface
178-
185+ when {
186+ activePie != - 1 && pieChartConfig.labelVisible -> {
187+ val selectedSlice = pieChartData.slices[activePie]
188+ drawContext.canvas.nativeCanvas.apply {
189+ val fontSize = pieChartConfig.labelFontSize.toPx()
190+ var isValue = false
191+ val textToDraw = when (pieChartConfig.labelType) {
192+ PieChartConfig .LabelType .PERCENTAGE -> " ${
193+ proportions[activePie].roundToInt()
194+ } %"
195+ PieChartConfig .LabelType .VALUE -> {
196+ isValue = true
197+ selectedSlice.value.toString()
198+ }
199+ }
200+ val labelColor = when (pieChartConfig.labelColorType) {
201+ PieChartConfig .LabelColorType .SPECIFIED_COLOR -> pieChartConfig.labelColor
202+ PieChartConfig .LabelColorType .SLICE_COLOR -> selectedSlice.color
179203 }
180- )
204+ val shouldShowUnit = isValue && pieChartConfig.sumUnit.isNotEmpty()
205+ drawLabel(
206+ canvas = this ,
207+ pieChartConfig = pieChartConfig,
208+ labelColor = labelColor,
209+ shouldShowUnit = shouldShowUnit,
210+ fontSize = fontSize,
211+ textToDraw = textToDraw,
212+ sideSize = sideSize
213+ )
214+ }
181215 }
216+ activePie == - 1 && pieChartConfig.isSumVisible -> {
217+ drawContext.canvas.nativeCanvas.apply {
218+ val fontSize = pieChartConfig.labelFontSize.toPx()
219+ val textToDraw = " $sumOfValues "
220+ drawLabel(
221+ canvas = this ,
222+ pieChartConfig = pieChartConfig,
223+ labelColor = pieChartConfig.labelColor,
224+ shouldShowUnit = pieChartConfig.sumUnit.isNotEmpty(),
225+ fontSize = fontSize,
226+ textToDraw = textToDraw,
227+ sideSize = sideSize
228+ )
229+ }
230+ }
231+
232+ }
182233 }
183234 }
184235 if (isTalkBackEnabled) {
@@ -204,3 +255,36 @@ fun DonutPieChart(
204255 }
205256 }
206257}
258+
259+ private fun drawLabel (
260+ canvas : NativeCanvas ,
261+ pieChartConfig : PieChartConfig ,
262+ labelColor : Color ,
263+ shouldShowUnit : Boolean ,
264+ fontSize : Float ,
265+ textToDraw : String ,
266+ sideSize : Int
267+ ) {
268+ val paint = Paint ().apply {
269+ color = labelColor.toArgb()
270+ textSize = fontSize
271+ textAlign = Paint .Align .CENTER
272+ typeface = pieChartConfig.labelTypeface
273+ }
274+ val x = (sideSize / 2 ).toFloat()
275+ var y: Float = (sideSize / 2 ).toFloat() + fontSize / 3
276+ if (shouldShowUnit)
277+ y - = (paint.fontSpacing / 4 )
278+ canvas.drawText(
279+ textToDraw,
280+ x, y,
281+ paint
282+ )
283+ y + = paint.fontSpacing
284+ canvas.drawText(
285+ pieChartConfig.sumUnit,
286+ x,
287+ y,
288+ paint
289+ )
290+ }
0 commit comments