@@ -23,9 +23,9 @@ package com.github.yamin8000.gauge.main
2323
2424import androidx.compose.foundation.Canvas
2525import androidx.compose.foundation.layout.BoxWithConstraints
26+ import androidx.compose.foundation.layout.aspectRatio
2627import androidx.compose.foundation.layout.padding
2728import androidx.compose.foundation.layout.size
28- import androidx.compose.material3.MaterialTheme
2929import androidx.compose.runtime.Composable
3030import androidx.compose.runtime.remember
3131import androidx.compose.ui.Modifier
@@ -35,14 +35,15 @@ import androidx.compose.ui.graphics.Color
3535import androidx.compose.ui.graphics.StrokeCap
3636import androidx.compose.ui.graphics.drawscope.DrawScope
3737import androidx.compose.ui.graphics.drawscope.Stroke
38- import androidx.compose.ui.platform.LocalConfiguration
38+ import androidx.compose.ui.platform.LocalDensity
3939import androidx.compose.ui.text.TextMeasurer
4040import androidx.compose.ui.text.TextStyle
4141import androidx.compose.ui.text.drawText
4242import androidx.compose.ui.text.rememberTextMeasurer
4343import androidx.compose.ui.unit.Dp
4444import androidx.compose.ui.unit.dp
4545import com.github.yamin8000.gauge.ui.color.GaugeArcColors
46+ import com.github.yamin8000.gauge.ui.color.GaugeColors
4647import com.github.yamin8000.gauge.ui.color.GaugeNeedleColors
4748import com.github.yamin8000.gauge.ui.color.GaugeTicksColors
4849import com.github.yamin8000.gauge.ui.style.GaugeArcStyle
@@ -52,6 +53,7 @@ import com.github.yamin8000.gauge.util.translate
5253import com.github.yamin8000.gauge.util.translate2
5354import java.text.DecimalFormat
5455import kotlin.math.cos
56+ import kotlin.math.max
5557import kotlin.math.sin
5658
5759/* *
@@ -63,16 +65,9 @@ import kotlin.math.sin
6365 * @param modifier refer to [Modifier]
6466 * @param valueUnit unit of the Gauge's value like %, km/h or etc
6567 * @param decimalFormat decimal formatter for value text
66- * @param totalSize total size of this [Gauge] as a Composable
67- * @param borderInset Gauge's inset relative to the border
6868 * @param numerics refer to [GaugeNumerics]
6969 * @param style refer to [GaugeStyle]
70- * @param borderColor
71- * @param centerCircleColor
72- * @param needleColors
73- * @param arcColors
74- * @param ticksColors
75- * @param ticksColorProvider a lambda for fine tune of individual tick's
70+ * @param ticksColorProvider a lambda for fine tuning of individual tick's
7671 * color
7772 * @param arcColorsProvider a lambda for fine tune of arc colors
7873 * @throws IllegalArgumentException when some parameters are inconsistent
@@ -84,90 +79,72 @@ fun Gauge(
8479 modifier : Modifier = Modifier ,
8580 valueUnit : String = "",
8681 decimalFormat : DecimalFormat = DecimalFormat ().apply { maximumFractionDigits = 2 },
87- totalSize : Dp = LocalConfiguration .current.screenWidthDp.dp,
88- borderInset : Dp = 4.dp,
8982 numerics : GaugeNumerics ,
90- style : GaugeStyle = GaugeStyle (
91- borderWidth = totalSize.value / 30f,
92- needleStyle = GaugeNeedleStyle (
93- ringWidth = totalSize.value / 30f
94- )
95- ),
96- borderColor : Color = MaterialTheme .colorScheme.primaryContainer,
97- centerCircleColor : Color = MaterialTheme .colorScheme.tertiary,
98- valueColor : Color = MaterialTheme .colorScheme.primary,
99- needleColors : GaugeNeedleColors = GaugeNeedleColors (
100- needle = MaterialTheme .colorScheme.primary,
101- ring = MaterialTheme .colorScheme.tertiaryContainer
102- ),
103- arcColors : GaugeArcColors = GaugeArcColors (
104- off = MaterialTheme .colorScheme.inversePrimary,
105- on = MaterialTheme .colorScheme.primary
106- ),
107- ticksColors : GaugeTicksColors = GaugeTicksColors (
108- smallTicks = MaterialTheme .colorScheme.inversePrimary,
109- bigTicks = MaterialTheme .colorScheme.primary,
110- bigTicksLabels = MaterialTheme .colorScheme.primary
111- ),
83+ style : GaugeStyle = GaugeStyle (),
84+ colors : GaugeColors = GaugeColors .defaultColors(),
11285 ticksColorProvider : (List <Pair <Int , Color >>) -> List <Pair <Int , Color >> = { it },
113- arcColorsProvider : (GaugeArcColors , Float , ClosedFloatingPointRange <Float >) -> GaugeArcColors = { _, _, _ -> arcColors }
86+ arcColorsProvider : (GaugeArcColors , Float , ClosedFloatingPointRange <Float >) -> GaugeArcColors = { _, _, _ -> colors.arc }
11487) {
11588 require(value in numerics.valueRange) { " Gauge value: $value is out of Gauge Value range ${numerics.valueRange} " }
11689 require(numerics.sweepAngle in 1 .. 360 ) { " Sweep angle: ${numerics.sweepAngle} must be from 1 to 360" }
11790
11891 BoxWithConstraints (
119- modifier = modifier.padding(8 .dp),
92+ modifier = modifier
93+ .padding(8 .dp)
94+ .aspectRatio(1f ),
12095 content = {
12196 val textMeasurer = rememberTextMeasurer()
122- val size = if (totalSize > maxWidth) maxWidth
123- else if (totalSize > maxHeight) maxHeight
124- else totalSize
97+ val density = LocalDensity .current
98+ val size = with (density) { max(maxWidth.toPx(), maxHeight.toPx()).toDp() }
12599 val totalAngle = numerics.startAngle + numerics.sweepAngle
126100 val arcSizeFraction = remember { .9f }
101+
127102 Canvas (
128103 modifier = Modifier .size(size),
129104 onDraw = {
130- val borderOffset = Offset (borderInset.toPx() / 2 , borderInset.toPx() / 2 )
105+ val safeSize = this @Canvas.size.maxDimension - style.borderWidth
106+ val safeOffset = Offset (style.borderWidth / 2f , style.borderWidth / 2f )
131107 if (style.hasBorder) {
132108 drawCircle(
133- color = borderColor ,
109+ color = colors.border ,
134110 center = center,
135- style = Stroke (style.borderWidth)
111+ style = Stroke (style.borderWidth),
112+ radius = safeSize / 2f
136113 )
137114 }
138115 if (style.hasValueText) {
139116 drawCompatibleText(
140117 textMeasurer = textMeasurer,
141118 text = decimalFormat.format(value).trim(),
142119 topLeft = center.plus(Offset (0f , size.toPx() / 8 )),
143- color = valueColor ,
144- totalSize = size
120+ color = colors.value ,
121+ totalSize = safeSize.toDp()
145122 )
146123 drawCompatibleText(
147124 textMeasurer = textMeasurer,
148125 text = valueUnit.trim(),
149126 topLeft = center.plus(Offset (0f , size.toPx() / 7 )),
150- color = valueColor ,
151- totalSize = size
127+ color = colors.value ,
128+ totalSize = safeSize.toDp()
152129 )
153130 }
154131 drawTicks(
155- borderOffset = borderOffset ,
132+ offset = safeOffset ,
156133 numerics = numerics,
157134 totalAngle = totalAngle,
158- colors = ticksColors ,
159- size = size - borderInset ,
135+ colors = colors.ticks ,
136+ size = safeSize.toDp() ,
160137 textMeasurer = textMeasurer,
161138 hasNumbers = style.arcStyle.bigTicksHasLabels,
162139 ticksColorProvider = ticksColorProvider
163140 )
164141 if (style.arcStyle.hasArcs) {
165142 drawArcs(
166- borderOffset = borderOffset ,
167- size = size - borderInset ,
143+ offset = safeOffset ,
144+ size = safeSize.toDp() ,
168145 style = style.arcStyle,
169146 arcSizeFraction = arcSizeFraction,
170- colors = arcColors ,
147+ colors = colors.arc ,
171148 numerics = numerics,
172149 value = value,
173150 valueRange = numerics.valueRange,
@@ -177,18 +154,18 @@ fun Gauge(
177154 }
178155 if (style.needleStyle.hasNeedle) {
179156 drawNeedle(
180- borderOffset = borderOffset ,
157+ offset = safeOffset ,
181158 style = style.needleStyle,
182- colors = needleColors ,
183- size = size - borderInset ,
159+ colors = colors.needle ,
160+ size = safeSize.toDp() ,
184161 value = value,
185162 numerics = numerics,
186163 totalAngle = totalAngle
187164 )
188165 }
189166 drawCircle(
190- color = centerCircleColor ,
191- radius = (size - borderInset).toPx() / 50 ,
167+ color = colors.centerCircle ,
168+ radius = safeSize / 50 ,
192169 center = center
193170 )
194171 }
@@ -198,7 +175,7 @@ fun Gauge(
198175}
199176
200177private fun DrawScope.drawNeedle (
201- borderOffset : Offset ,
178+ offset : Offset ,
202179 style : GaugeNeedleStyle ,
203180 colors : GaugeNeedleColors ,
204181 size : Dp ,
@@ -227,7 +204,7 @@ private fun DrawScope.drawNeedle(
227204 val endOffset = Offset (
228205 x.minus(cos.times(size.toPx() / 20f )),
229206 y.minus(sin.times(size.toPx() / 20f ))
230- ).plus(borderOffset )
207+ ).plus(offset )
231208 drawLine(
232209 color = colors.needle,
233210 start = center,
@@ -245,7 +222,7 @@ private fun DrawScope.drawNeedle(
245222}
246223
247224private fun DrawScope.drawTicks (
248- borderOffset : Offset ,
225+ offset : Offset ,
249226 numerics : GaugeNumerics ,
250227 totalAngle : Int ,
251228 colors : GaugeTicksColors ,
@@ -288,12 +265,6 @@ private fun DrawScope.drawTicks(
288265 y.minus(sin.times(tickEndRatio))
289266 )
290267
291- val textEndRatio = size.toPx().div(4.25f )
292- var textOffset = Offset (
293- x.minus(cos.times(textEndRatio)),
294- y.minus(sin.times(textEndRatio))
295- )
296-
297268 if (isSmallTick) {
298269 drawLine(
299270 color = tickColor,
@@ -302,8 +273,8 @@ private fun DrawScope.drawTicks(
302273 start = Offset (
303274 x.minus(cos.times(startRatio)),
304275 y.minus(sin.times(startRatio))
305- ).plus(borderOffset ),
306- end = tickEndOffset.plus(borderOffset )
276+ ).plus(offset ),
277+ end = tickEndOffset.plus(offset )
307278 )
308279 }
309280 if (hasNumbers && isBigTick) {
@@ -313,6 +284,11 @@ private fun DrawScope.drawTicks(
313284 fontSize = size.toSp() / textSizeFactor
314285 )
315286 val textLayout = textMeasurer.measure(" $value " , textStyle)
287+ val textEndRatio = size.toPx().div(4.25f )
288+ var textOffset = Offset (
289+ x.minus(cos.times(textEndRatio)),
290+ y.minus(sin.times(textEndRatio))
291+ )
316292 textOffset = textOffset.minus(
317293 Offset (
318294 textLayout.size.width.toFloat() / 2 ,
@@ -325,15 +301,15 @@ private fun DrawScope.drawTicks(
325301 drawText(
326302 textMeasurer = textMeasurer,
327303 text = " $value " ,
328- topLeft = textOffset.plus(borderOffset) ,
304+ topLeft = textOffset,
329305 style = textStyle
330306 )
331307 }
332308 }
333309}
334310
335311private fun DrawScope.drawArcs (
336- borderOffset : Offset ,
312+ offset : Offset ,
337313 size : Dp ,
338314 style : GaugeArcStyle ,
339315 arcSizeFraction : Float ,
@@ -370,7 +346,7 @@ private fun DrawScope.drawArcs(
370346 useCenter = false ,
371347 style = arcStroke,
372348 size = arcSize,
373- topLeft = arcTopLeft.plus(borderOffset )
349+ topLeft = arcTopLeft.plus(offset )
374350 )
375351 val alpha = value / valueRange.endInclusive
376352 drawArc(
@@ -385,7 +361,7 @@ private fun DrawScope.drawArcs(
385361 useCenter = false ,
386362 style = arcStroke,
387363 size = arcSize,
388- topLeft = arcTopLeft.plus(borderOffset )
364+ topLeft = arcTopLeft.plus(offset )
389365 )
390366}
391367
0 commit comments