Skip to content

Commit

Permalink
Merge pull request #304 from Spendesk/release/1.18.3
Browse files Browse the repository at this point in the history
Release/1.18.3
  • Loading branch information
Scythe14 authored Nov 24, 2023
2 parents e121e76 + 845c392 commit 05c477c
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 2 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[versions]
grapes-version = '1.18.2'
grapes-version = '1.18.3'
androidMinSdk = "21"
androidTargetSdk = "34"
androidCompileSdk = "34"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
package com.spendesk.grapes.compose.gauge

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.spendesk.grapes.compose.theme.GrapesTheme

/**
* @author : dany
* @since : 26/10/2023, Thu
**/

@Immutable
object GrapesGaugeDefaults {
const val GaugeAddDelimiter = true
val GaugeStrippedWidth = 5.dp
}

sealed class Gauge(open val progress: Float) {
data class Solid(
override val progress: Float,
val color: Color,
val addDelimiter: Boolean = GrapesGaugeDefaults.GaugeAddDelimiter
) : Gauge(progress)

data class Stripped(
override val progress: Float,
val stripeColor: Color,
val stripeColorSecondary: Color,
val stripeWidth: Dp = GrapesGaugeDefaults.GaugeStrippedWidth,
val addDelimiter: Boolean = GrapesGaugeDefaults.GaugeAddDelimiter
) : Gauge(progress)
}

/**
* Displays a list of gauges.
*
* @param backgroundColor the background color of the gauge.
* @param gauges the list of gauges to display. The gauges will automatically be sorted by progress in order to have the right visibility without any additional work.
* @param modifier the modifier to apply to this layout.
*/
@Composable
fun GrapesGauge(
backgroundColor: Color,
gauges: List<Gauge>,
modifier: Modifier = Modifier,
clipShape: Shape = RoundedCornerShape(GrapesTheme.dimensions.borderRadiusNormal),
) {
GrapesGaugeContainer(
modifier = modifier,
backgroundColor = backgroundColor,
clipShape = clipShape,
content = {
gauges
.sortedByDescending { it.progress }
.forEachIndexed { index, gauge ->
when (gauge) {
is Gauge.Solid -> {
GrapesGauge(
progress = gauge.progress,
color = gauge.color,
addDelimiter = gauge.addDelimiter
)
}

is Gauge.Stripped -> {
GrapesGaugeStripped(
progress = gauge.progress,
stripeColor = gauge.stripeColor,
stripeColorSecondary = gauge.stripeColorSecondary,
addDelimiter = gauge.addDelimiter
)
}
}
}
})
}

@Composable
private fun GrapesGaugeContainer(
backgroundColor: Color,
clipShape: Shape,
modifier: Modifier = Modifier,
content: @Composable (() -> Unit),
) {
Box(
modifier = modifier
.clip(clipShape)
.background(backgroundColor)
.fillMaxWidth()
.height(GrapesTheme.dimensions.gaugeHeight)
) {
content()
}
}

@Composable
private fun GrapesGauge(
progress: Float,
color: Color,
modifier: Modifier = Modifier,
addDelimiter: Boolean = true
) {
Row {
Box(
modifier = modifier
.background(color)
.fillMaxHeight()
.fillMaxWidth(progress)
)
if (addDelimiter) {
GrapesGaugeDelimiter()
}
}
}

@Composable
private fun GrapesGaugeStripped(
progress: Float,
stripeColor: Color,
stripeColorSecondary: Color,
modifier: Modifier = Modifier,
addDelimiter: Boolean = true
) {
Row {
Box(
modifier = modifier
.background(createStripeGauge(stripeColor, stripeColorSecondary, 5.dp))
.fillMaxHeight()
.fillMaxWidth(progress)
)
if (addDelimiter) {
GrapesGaugeDelimiter()
}
}
}

@Composable
private fun GrapesGaugeDelimiter() {
Box(
modifier = Modifier
.fillMaxHeight()
.width(GrapesTheme.dimensions.gaugeDelimiterWidth)
.background(GrapesTheme.colors.mainWhite)
)
}

@Composable
private fun createStripeGauge(
stripeColor: Color,
stripeBg: Color,
stripeWidth: Dp
): Brush {
val stripeWidthPx = with(LocalDensity.current) { stripeWidth.toPx() }
val brushSizePx = 2 * stripeWidthPx
val stripeStart = stripeWidthPx / brushSizePx

return Brush.linearGradient(
stripeStart to stripeBg,
stripeStart to stripeColor,
start = Offset(0f, 0f),
end = Offset(brushSizePx, brushSizePx),
tileMode = TileMode.Repeated
)
}

@Composable
@Preview(showBackground = true)
private fun GaugePreview() {
GrapesTheme {
Column(verticalArrangement = Arrangement.spacedBy(GrapesTheme.dimensions.paddingXSmall)) {
GrapesGauge(
modifier = Modifier.padding(16.dp),
backgroundColor = GrapesTheme.colors.mainNeutralLighter,
gauges = listOf(
Gauge.Solid(progress = 0.2f, color = GrapesTheme.colors.mainPrimaryDark),
Gauge.Solid(progress = 0.5f, color = GrapesTheme.colors.mainWarningNormal),
Gauge.Solid(progress = 0.8f, color = GrapesTheme.colors.mainAlertDark)
)

)
GrapesGauge(
modifier = Modifier.padding(16.dp),
backgroundColor = GrapesTheme.colors.mainNeutralLighter,
gauges = listOf(
Gauge.Solid(progress = 0.2f, color = GrapesTheme.colors.mainPrimaryDark)
)
)
GrapesGauge(
modifier = Modifier.padding(16.dp),
backgroundColor = GrapesTheme.colors.mainNeutralLighter,
gauges = listOf(
Gauge.Stripped(progress = 0.8f, stripeColor = GrapesTheme.colors.mainWarningLighter, stripeColorSecondary = GrapesTheme.colors.mainWarningNormal)
)
)
GrapesGauge(
modifier = Modifier.padding(16.dp),
backgroundColor = GrapesTheme.colors.mainNeutralLighter,
gauges = listOf(
Gauge.Solid(progress = 0.2f, color = GrapesTheme.colors.mainWarningNormal),
Gauge.Stripped(progress = 0.5f, stripeColor = GrapesTheme.colors.mainWarningLighter, stripeColorSecondary = GrapesTheme.colors.mainWarningNormal)
)
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ data class GrapesDimensions(

val borderLarge: Dp = 2.0.dp,

val borderRadiusSmall: Dp = 2.dp,
val borderRadiusNormal: Dp = 4.dp,

val paddingXSmall: Dp = 4.dp,
val paddingSmall: Dp = 8.dp,
val paddingMedium: Dp = 12.dp,
Expand All @@ -25,7 +28,10 @@ data class GrapesDimensions(
val elevationNormal: Dp = 8.dp,

val iconNormal: Dp = 16.dp,
val iconLarge: Dp = 32.dp
val iconLarge: Dp = 32.dp,

val gaugeHeight: Dp = 16.dp,
val gaugeDelimiterWidth: Dp = 2.dp
)

internal val LocalGrapesDimensions = staticCompositionLocalOf { GrapesDimensions() }
10 changes: 10 additions & 0 deletions library-compose/src/main/res/drawable/ic_action_settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,14.14 L6.32,16a8.08,8.08 0,0 1,-2.79 -1.15l0.13,-2.51 -2.5,0.13A8.13,8.13 0,0 1,0 9.68L1.86,8 0,6.32a8,8 0,0 1,1.15 -2.79l2.51,0.13 -0.13,-2.5A8.13,8.13 0,0 1,6.32 0L8,1.86 9.68,0c1.01,0.21 1.95,0.6 2.79,1.15l-0.13,2.51 2.5,-0.13A8.1,8.1 0,0 1,16 6.32L14.14,8 16,9.68a8.08,8.08 0,0 1,-1.15 2.79l-2.51,-0.13 0.13,2.5A8.1,8.1 0,0 1,9.68 16L8,14.14ZM11.33,8a3.33,3.33 0,1 1,-6.66 0,3.33 3.33,0 0,1 6.66,0Z"
android:fillColor="#17114E"
android:fillType="evenOdd"/>
</vector>

0 comments on commit 05c477c

Please sign in to comment.