Skip to content

Commit fa43b78

Browse files
committed
refactor WIP
1 parent 33eb304 commit fa43b78

File tree

4 files changed

+92
-77
lines changed

4 files changed

+92
-77
lines changed

Gauge/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2323

2424
private val artifact = "com.github.yamin8000.gauge"
25-
private val version = "1.0.4"
25+
private val version = "1.1.0"
2626

2727
plugins {
2828
id("com.android.library")

Gauge/src/main/java/com/github/yamin8000/gauge/main/Gauge.kt

Lines changed: 48 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ package com.github.yamin8000.gauge.main
2323

2424
import androidx.compose.foundation.Canvas
2525
import androidx.compose.foundation.layout.BoxWithConstraints
26+
import androidx.compose.foundation.layout.aspectRatio
2627
import androidx.compose.foundation.layout.padding
2728
import androidx.compose.foundation.layout.size
28-
import androidx.compose.material3.MaterialTheme
2929
import androidx.compose.runtime.Composable
3030
import androidx.compose.runtime.remember
3131
import androidx.compose.ui.Modifier
@@ -35,14 +35,15 @@ import androidx.compose.ui.graphics.Color
3535
import androidx.compose.ui.graphics.StrokeCap
3636
import androidx.compose.ui.graphics.drawscope.DrawScope
3737
import androidx.compose.ui.graphics.drawscope.Stroke
38-
import androidx.compose.ui.platform.LocalConfiguration
38+
import androidx.compose.ui.platform.LocalDensity
3939
import androidx.compose.ui.text.TextMeasurer
4040
import androidx.compose.ui.text.TextStyle
4141
import androidx.compose.ui.text.drawText
4242
import androidx.compose.ui.text.rememberTextMeasurer
4343
import androidx.compose.ui.unit.Dp
4444
import androidx.compose.ui.unit.dp
4545
import com.github.yamin8000.gauge.ui.color.GaugeArcColors
46+
import com.github.yamin8000.gauge.ui.color.GaugeColors
4647
import com.github.yamin8000.gauge.ui.color.GaugeNeedleColors
4748
import com.github.yamin8000.gauge.ui.color.GaugeTicksColors
4849
import com.github.yamin8000.gauge.ui.style.GaugeArcStyle
@@ -52,6 +53,7 @@ import com.github.yamin8000.gauge.util.translate
5253
import com.github.yamin8000.gauge.util.translate2
5354
import java.text.DecimalFormat
5455
import kotlin.math.cos
56+
import kotlin.math.max
5557
import 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

200177
private 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

247224
private 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

335311
private 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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.github.yamin8000.gauge.ui.color
2+
3+
import androidx.compose.material3.MaterialTheme
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.ui.graphics.Color
6+
7+
data class GaugeColors(
8+
val border: Color,
9+
val centerCircle: Color,
10+
val value: Color,
11+
val arc: GaugeArcColors,
12+
val needle: GaugeNeedleColors,
13+
val ticks: GaugeTicksColors
14+
) {
15+
companion object {
16+
17+
@Composable
18+
fun defaultColors() = GaugeColors(
19+
border = MaterialTheme.colorScheme.primaryContainer,
20+
centerCircle = MaterialTheme.colorScheme.tertiary,
21+
value = MaterialTheme.colorScheme.primary,
22+
arc = GaugeArcColors(
23+
off = MaterialTheme.colorScheme.inversePrimary,
24+
on = MaterialTheme.colorScheme.primary
25+
),
26+
needle = GaugeNeedleColors(
27+
needle = MaterialTheme.colorScheme.primary,
28+
ring = MaterialTheme.colorScheme.tertiaryContainer
29+
),
30+
ticks = GaugeTicksColors(
31+
smallTicks = MaterialTheme.colorScheme.inversePrimary,
32+
bigTicks = MaterialTheme.colorScheme.primary,
33+
bigTicksLabels = MaterialTheme.colorScheme.primary
34+
)
35+
)
36+
}
37+
}

app/src/main/java/com/github/yamin8000/gauge/MainActivity.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ import androidx.activity.compose.setContent
2727
import androidx.compose.foundation.layout.Column
2828
import androidx.compose.foundation.layout.fillMaxSize
2929
import androidx.compose.foundation.layout.padding
30+
import androidx.compose.foundation.layout.size
3031
import androidx.compose.foundation.rememberScrollState
3132
import androidx.compose.foundation.verticalScroll
3233
import androidx.compose.material3.Slider
3334
import androidx.compose.material3.Surface
3435
import androidx.compose.material3.Text
3536
import androidx.compose.runtime.getValue
3637
import androidx.compose.runtime.mutableFloatStateOf
38+
import androidx.compose.runtime.mutableStateOf
3739
import androidx.compose.runtime.remember
3840
import androidx.compose.runtime.setValue
3941
import androidx.compose.ui.Modifier
@@ -63,12 +65,12 @@ class MainActivity : ComponentActivity() {
6365
val configuration = LocalConfiguration.current
6466
val screenWidth = configuration.screenWidthDp.dp
6567
var value by remember { mutableFloatStateOf(15f) }
66-
var totalSize by remember { mutableFloatStateOf(350f) }
68+
var totalSize by remember { mutableStateOf(350.dp) }
6769
var strokeWidth by remember { mutableFloatStateOf(35f) }
6870
val valueRange = 10f..20f
6971
Gauge(
72+
modifier = Modifier.size(totalSize),
7073
value = value,
71-
totalSize = totalSize.dp,
7274
numerics = GaugeNumerics(
7375
startAngle = 120,
7476
sweepAngle = 300,
@@ -112,10 +114,10 @@ class MainActivity : ComponentActivity() {
112114
)
113115
Text("Total Size: $totalSize")
114116
Slider(
115-
value = totalSize,
117+
value = totalSize.value,
116118
valueRange = 0f..500f,
117119
onValueChange = {
118-
totalSize = it
120+
totalSize = it.dp
119121
}
120122
)
121123

0 commit comments

Comments
 (0)