xref: /aosp_15_r20/frameworks/base/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/chart/PieChart.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settingslib.spa.widget.chart
18 
19 import android.view.ViewGroup
20 import android.widget.LinearLayout
21 import androidx.compose.animation.Crossfade
22 import androidx.compose.foundation.layout.Arrangement
23 import androidx.compose.foundation.layout.Column
24 import androidx.compose.foundation.layout.fillMaxWidth
25 import androidx.compose.foundation.layout.height
26 import androidx.compose.foundation.layout.padding
27 import androidx.compose.foundation.layout.wrapContentHeight
28 import androidx.compose.foundation.layout.wrapContentSize
29 import androidx.compose.material3.MaterialTheme
30 import androidx.compose.runtime.Composable
31 import androidx.compose.ui.Alignment
32 import androidx.compose.ui.Modifier
33 import androidx.compose.ui.graphics.Color
34 import androidx.compose.ui.graphics.toArgb
35 import androidx.compose.ui.unit.dp
36 import androidx.compose.ui.viewinterop.AndroidView
37 import com.github.mikephil.charting.charts.PieChart
38 import com.github.mikephil.charting.data.PieData
39 import com.github.mikephil.charting.data.PieDataSet
40 import com.github.mikephil.charting.data.PieEntry
41 
42 /**
43  * The chart settings model for [PieChart].
44  */
45 interface PieChartModel {
46     /**
47      * The chart data list for [PieChart].
48      */
49     val chartDataList: List<PieChartData>
50 
51     /**
52      * The center text in the hole of [PieChart].
53      */
54     val centerText: String?
55         get() = null
56 }
57 
58 val colorPalette = arrayListOf(
59     ColorPalette.blue.toArgb(),
60     ColorPalette.red.toArgb(),
61     ColorPalette.yellow.toArgb(),
62     ColorPalette.green.toArgb(),
63     ColorPalette.orange.toArgb(),
64     ColorPalette.cyan.toArgb(),
65     Color.Blue.toArgb()
66 )
67 
68 data class PieChartData(
69     var value: Float?,
70     var label: String?,
71 )
72 
73 @Composable
PieChartnull74 fun PieChart(pieChartModel: PieChartModel) {
75     PieChart(
76         chartDataList = pieChartModel.chartDataList,
77         centerText = pieChartModel.centerText,
78     )
79 }
80 
81 @Composable
PieChartnull82 fun PieChart(
83     chartDataList: List<PieChartData>,
84     modifier: Modifier = Modifier,
85     centerText: String? = null,
86 ) {
87     Column(
88         modifier = modifier
89             .fillMaxWidth()
90             .wrapContentHeight(),
91         horizontalAlignment = Alignment.CenterHorizontally,
92         verticalArrangement = Arrangement.Center
93     ) {
94         Column(
95             modifier = Modifier
96                 .padding(16.dp)
97                 .height(280.dp),
98             horizontalAlignment = Alignment.CenterHorizontally,
99             verticalArrangement = Arrangement.Center
100         ) {
101             val colorScheme = MaterialTheme.colorScheme
102             val labelTextColor = colorScheme.onSurfaceVariant.toArgb()
103             val labelTextSize = MaterialTheme.typography.bodyMedium.fontSize.value
104             val centerTextSize = MaterialTheme.typography.titleLarge.fontSize.value
105             Crossfade(targetState = chartDataList) { pieChartData ->
106                 AndroidView(factory = { context ->
107                     PieChart(context).apply {
108                         // Fixed settings.`
109                         layoutParams = LinearLayout.LayoutParams(
110                             ViewGroup.LayoutParams.MATCH_PARENT,
111                             ViewGroup.LayoutParams.MATCH_PARENT,
112                         )
113                         this.isRotationEnabled = false
114                         this.description.isEnabled = false
115                         this.legend.isEnabled = false
116                         this.setTouchEnabled(false)
117 
118                         this.isDrawHoleEnabled = true
119                         this.holeRadius = 90.0f
120                         this.setHoleColor(Color.Transparent.toArgb())
121                         this.setEntryLabelColor(labelTextColor)
122                         this.setEntryLabelTextSize(labelTextSize)
123                         this.setCenterTextSize(centerTextSize)
124                         this.setCenterTextColor(colorScheme.onSurface.toArgb())
125 
126                         // Customizable settings.
127                         this.centerText = centerText
128                     }
129                 },
130                     modifier = Modifier
131                         .wrapContentSize()
132                         .padding(4.dp), update = {
133                         updatePieChartWithData(it, pieChartData)
134                     })
135             }
136         }
137     }
138 }
139 
updatePieChartWithDatanull140 fun updatePieChartWithData(
141     chart: PieChart,
142     data: List<PieChartData>,
143 ) {
144     val entries = ArrayList<PieEntry>()
145     for (i in data.indices) {
146         val item = data[i]
147         entries.add(PieEntry(item.value ?: 0.toFloat(), item.label ?: ""))
148     }
149 
150     val ds = PieDataSet(entries, "")
151     ds.setDrawValues(false)
152     ds.colors = colorPalette
153     ds.sliceSpace = 2f
154     ds.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE
155     ds.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE
156     ds.valueLineColor = Color.Transparent.toArgb()
157     ds.valueLinePart1Length = 0.1f
158     ds.valueLinePart2Length = 0f
159 
160     val d = PieData(ds)
161     chart.data = d
162     chart.invalidate()
163 }
164