From db4da4999c0765e3f20cccdc6f3fbd5f21e29625 Mon Sep 17 00:00:00 2001 From: Patrick Michalik <120058021+patrickmichalik@users.noreply.github.com> Date: Mon, 1 Apr 2024 15:56:30 +0200 Subject: [PATCH] Make fixes related to `CandlestickCartesianLayer` XML attributes (WIP) --- .../views/cartesian/CandlestickExtensions.kt | 59 +---- .../common/theme/ChartStyleExtensions.kt | 229 +++++++++--------- .../res/values/candlestick_chart_attrs.xml | 4 + 3 files changed, 121 insertions(+), 171 deletions(-) diff --git a/vico/views/src/main/java/com/patrykandpatrick/vico/views/cartesian/CandlestickExtensions.kt b/vico/views/src/main/java/com/patrykandpatrick/vico/views/cartesian/CandlestickExtensions.kt index faf6b8252..256fb2229 100644 --- a/vico/views/src/main/java/com/patrykandpatrick/vico/views/cartesian/CandlestickExtensions.kt +++ b/vico/views/src/main/java/com/patrykandpatrick/vico/views/cartesian/CandlestickExtensions.kt @@ -16,17 +16,18 @@ package com.patrykandpatrick.vico.views.cartesian -import android.content.Context import android.graphics.Color -import com.patrykandpatrick.vico.core.cartesian.layer.CandlestickCartesianLayer import com.patrykandpatrick.vico.core.cartesian.layer.CandlestickCartesianLayer.Candle -import com.patrykandpatrick.vico.core.cartesian.layer.absolute -import com.patrykandpatrick.vico.core.cartesian.layer.absoluteRelative import com.patrykandpatrick.vico.core.common.Defaults import com.patrykandpatrick.vico.core.common.component.LineComponent -import com.patrykandpatrick.vico.views.common.extension.defaultColors -private fun Candle.Companion.sharpFilledCandle( +private fun LineComponent.copyWithColor(color: Int) = + copy( + color = if (this.color == Color.TRANSPARENT) this.color else color, + strokeColor = if (this.strokeColor == Color.TRANSPARENT) this.color else color, + ) + +internal fun Candle.Companion.sharpFilledCandle( color: Int, thicknessDp: Float = Defaults.CANDLE_BODY_WIDTH_DP, ): Candle { @@ -34,7 +35,7 @@ private fun Candle.Companion.sharpFilledCandle( return Candle(body = filledBody) } -private fun Candle.Companion.sharpHollowCandle( +internal fun Candle.Companion.sharpHollowCandle( color: Int, thicknessDp: Float = Defaults.CANDLE_BODY_WIDTH_DP, strokeWidthDp: Float = Defaults.HOLLOW_CANDLE_STROKE_WIDTH_DP, @@ -50,51 +51,9 @@ private fun Candle.Companion.sharpHollowCandle( return Candle(body = hollowBody) } -private fun Candle.copyWithColor(color: Int) = +internal fun Candle.copyWithColor(color: Int) = Candle( body = body.copyWithColor(color), topWick = topWick.copyWithColor(color), bottomWick = bottomWick.copyWithColor(color), ) - -private fun LineComponent.copyWithColor(color: Int) = - copy( - color = if (this.color == Color.TRANSPARENT) this.color else color, - strokeColor = if (this.strokeColor == Color.TRANSPARENT) this.color else color, - ) - -internal fun CandlestickCartesianLayer.CandleProvider.Companion.absolute( - context: Context, - bullish: Candle = Candle.sharpFilledCandle(context.defaultColors.candlestickGreen.toInt()), - neutral: Candle = bullish.copyWithColor(context.defaultColors.candlestickGray.toInt()), - bearish: Candle = bullish.copyWithColor(context.defaultColors.candlestickRed.toInt()), -) = CandlestickCartesianLayer.CandleProvider.absolute(bullish, neutral, bearish) - -internal fun CandlestickCartesianLayer.CandleProvider.Companion.absoluteRelative( - context: Context, - absolutelyBullishRelativelyBullish: Candle = - Candle.sharpHollowCandle(context.defaultColors.candlestickGreen.toInt()), - absolutelyBullishRelativelyNeutral: Candle = - absolutelyBullishRelativelyBullish.copyWithColor(context.defaultColors.candlestickGray.toInt()), - absolutelyBullishRelativelyBearish: Candle = - absolutelyBullishRelativelyBullish.copyWithColor(context.defaultColors.candlestickRed.toInt()), - absolutelyNeutralRelativelyBullish: Candle = absolutelyBullishRelativelyBullish, - absolutelyNeutralRelativelyNeutral: Candle = absolutelyBullishRelativelyNeutral, - absolutelyNeutralRelativelyBearish: Candle = absolutelyBullishRelativelyBearish, - absolutelyBearishRelativelyBullish: Candle = - Candle.sharpFilledCandle(context.defaultColors.candlestickGreen.toInt()), - absolutelyBearishRelativelyNeutral: Candle = - absolutelyBearishRelativelyBullish.copyWithColor(context.defaultColors.candlestickGray.toInt()), - absolutelyBearishRelativelyBearish: Candle = - absolutelyBearishRelativelyBullish.copyWithColor(context.defaultColors.candlestickRed.toInt()), -) = CandlestickCartesianLayer.CandleProvider.absoluteRelative( - absolutelyBullishRelativelyBullish, - absolutelyBullishRelativelyNeutral, - absolutelyBullishRelativelyBearish, - absolutelyNeutralRelativelyBullish, - absolutelyNeutralRelativelyNeutral, - absolutelyNeutralRelativelyBearish, - absolutelyBearishRelativelyBullish, - absolutelyBearishRelativelyNeutral, - absolutelyBearishRelativelyBearish, -) diff --git a/vico/views/src/main/java/com/patrykandpatrick/vico/views/common/theme/ChartStyleExtensions.kt b/vico/views/src/main/java/com/patrykandpatrick/vico/views/common/theme/ChartStyleExtensions.kt index 126f5e4d8..57db738d4 100644 --- a/vico/views/src/main/java/com/patrykandpatrick/vico/views/common/theme/ChartStyleExtensions.kt +++ b/vico/views/src/main/java/com/patrykandpatrick/vico/views/common/theme/ChartStyleExtensions.kt @@ -30,6 +30,9 @@ import com.patrykandpatrick.vico.core.common.extension.getRepeating import com.patrykandpatrick.vico.core.common.position.VerticalPosition import com.patrykandpatrick.vico.core.common.shape.Shapes import com.patrykandpatrick.vico.views.R +import com.patrykandpatrick.vico.views.cartesian.copyWithColor +import com.patrykandpatrick.vico.views.cartesian.sharpFilledCandle +import com.patrykandpatrick.vico.views.cartesian.sharpHollowCandle import com.patrykandpatrick.vico.views.common.extension.defaultColors internal fun TypedArray.getColumnCartesianLayer( @@ -157,75 +160,88 @@ internal fun TypedArray.getLineCartesianLayer( } internal fun TypedArray.getCandlestickCartesianLayer(context: Context): CandlestickCartesianLayer { - val candles = + val green = context.defaultColors.candlestickGreen.toInt() + val gray = context.defaultColors.candlestickGray.toInt() + val red = context.defaultColors.candlestickRed.toInt() + val candleProvider = getNestedTypedArray( context, R.styleable.CartesianChartView_candlestickLayerStyle, R.styleable.CandlestickLayerStyle, ).use { typedArray -> - val hasAbsoluteRelativeCandleStyle = typedArray.hasAbsoluteRelativeCandleStyle() - val green = context.defaultColors.candlestickGreen.toInt() - val gray = context.defaultColors.candlestickGray.toInt() - val red = context.defaultColors.candlestickRed.toInt() - - if (hasAbsoluteRelativeCandleStyle) { - CandlestickCartesianLayer.CandleProvider.absoluteRelative( - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyBullishCandleStyle, - green, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyNeutralCandleStyle, - gray, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyBearishCandleStyle, - red, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyBullishCandleStyle, - green, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyNeutralCandleStyle, - gray, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyBearishCandleStyle, - red, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyBullishCandleStyle, - green, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyNeutralCandleStyle, - gray, - ), - typedArray.getCandle( - context, - R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyBearishCandleStyle, - red, - ), - ) - } else { - CandlestickCartesianLayer.CandleProvider.absolute( - typedArray.getCandle(context, R.styleable.CandlestickLayerStyle_bullishCandleStyle, green), - typedArray.getCandle(context, R.styleable.CandlestickLayerStyle_neutralCandleStyle, gray), - typedArray.getCandle(context, R.styleable.CandlestickLayerStyle_bearishCandleStyle, red), - ) + when (typedArray.getInteger(R.styleable.CandlestickLayerStyle_candleStyle, 0)) { + 0 -> { + val bullish = + typedArray.getCandle(context, R.styleable.CandlestickLayerStyle_bullishCandleStyle) + ?: CandlestickCartesianLayer.Candle.sharpFilledCandle(green) + CandlestickCartesianLayer.CandleProvider.absolute( + bullish = bullish, + neutral = + typedArray.getCandle(context, R.styleable.CandlestickLayerStyle_neutralCandleStyle) + ?: bullish.copyWithColor(gray), + bearish = + typedArray.getCandle(context, R.styleable.CandlestickLayerStyle_bearishCandleStyle) + ?: bullish.copyWithColor(red), + ) + } + 1 -> { + val absolutelyBullishRelativelyBullish = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyBullishCandleStyle, + ) ?: CandlestickCartesianLayer.Candle.sharpHollowCandle(green) + val absolutelyBullishRelativelyNeutral = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyNeutralCandleStyle, + ) ?: absolutelyBullishRelativelyBullish.copyWithColor(gray) + val absolutelyBullishRelativelyBearish = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyBearishCandleStyle, + ) ?: absolutelyBullishRelativelyBullish.copyWithColor(red) + val absolutelyBearishRelativelyBullish = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyBullishCandleStyle, + ) ?: CandlestickCartesianLayer.Candle.sharpFilledCandle(green) + CandlestickCartesianLayer.CandleProvider.absoluteRelative( + absolutelyBullishRelativelyBullish = absolutelyBullishRelativelyBullish, + absolutelyBullishRelativelyNeutral = absolutelyBullishRelativelyNeutral, + absolutelyBullishRelativelyBearish = absolutelyBullishRelativelyBearish, + absolutelyNeutralRelativelyBullish = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyBullishCandleStyle, + ) ?: absolutelyBullishRelativelyBullish, + absolutelyNeutralRelativelyNeutral = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyNeutralCandleStyle, + ) ?: absolutelyBullishRelativelyNeutral, + absolutelyNeutralRelativelyBearish = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyBearishCandleStyle, + ) ?: absolutelyBullishRelativelyBearish, + absolutelyBearishRelativelyBullish = absolutelyBearishRelativelyBullish, + absolutelyBearishRelativelyNeutral = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyNeutralCandleStyle, + ) ?: absolutelyBearishRelativelyBullish.copyWithColor(gray), + absolutelyBearishRelativelyBearish = + typedArray.getCandle( + context, + R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyBearishCandleStyle, + ) ?: absolutelyBearishRelativelyBullish.copyWithColor(red), + ) + } + else -> error("Unexpected `candleStyle` value.") } } return CandlestickCartesianLayer( - candles = candles, + candles = candleProvider, minCandleBodyHeightDp = getRawDimension( context, @@ -237,67 +253,38 @@ internal fun TypedArray.getCandlestickCartesianLayer(context: Context): Candlest ) } -private fun TypedArray.hasAbsoluteRelativeCandleStyle(): Boolean = - hasValue(R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyBullishCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyNeutralCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyBullishRelativelyBearishCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyBullishCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyNeutralCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyNeutralRelativelyBearishCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyBullishCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyNeutralCandleStyle) || - hasValue(R.styleable.CandlestickLayerStyle_absolutelyBearishRelativelyBearishCandleStyle) - private fun TypedArray.getCandle( context: Context, resourceId: Int, - defaultColor: Int, -): CandlestickCartesianLayer.Candle = - getNestedTypedArray(context, resourceId, R.styleable.CandleStyle).use { typedArray -> - val topWick = - if (typedArray.hasValue(R.styleable.CandleStyle_topWickStyle)) { - typedArray.getNestedTypedArray( - context = context, - resourceId = R.styleable.CandleStyle_topWickStyle, - styleableResourceId = R.styleable.LineComponent, - ).getLineComponent( - context = context, - defaultColor = defaultColor, - defaultThickness = Defaults.WICK_DEFAULT_WIDTH_DP, - ) - } else { - null - } - - val bottomWick = - if (typedArray.hasValue(R.styleable.CandleStyle_bottomWickStyle)) { - typedArray.getNestedTypedArray( - context = context, - resourceId = R.styleable.CandleStyle_bottomWickStyle, - styleableResourceId = R.styleable.LineComponent, - ).getLineComponent( - context = context, - defaultColor = defaultColor, - defaultThickness = Defaults.WICK_DEFAULT_WIDTH_DP, - ) - } else { - null - } - - val body = - typedArray.getNestedTypedArray( - context = context, - resourceId = R.styleable.CandleStyle_bodyStyle, - styleableResourceId = R.styleable.LineComponent, - ).getLineComponent( - context = context, - defaultColor = defaultColor, - defaultThickness = Defaults.CANDLE_BODY_WIDTH_DP, - ) - - CandlestickCartesianLayer.Candle( - body = body, - topWick = topWick ?: body.asWick(), - bottomWick = bottomWick ?: topWick ?: body.asWick(), - ) +): CandlestickCartesianLayer.Candle? = + if (hasValue(resourceId)) { + getNestedTypedArray(context, resourceId, R.styleable.CandleStyle).use { typedArray -> + val body = + typedArray + .getNestedTypedArray(context, R.styleable.CandleStyle_bodyStyle, R.styleable.LineComponent) + .getLineComponent(context = context, defaultThickness = Defaults.CANDLE_BODY_WIDTH_DP) + val topWick = + if (typedArray.hasValue(R.styleable.CandleStyle_topWickStyle)) { + typedArray + .getNestedTypedArray(context, R.styleable.CandleStyle_topWickStyle, R.styleable.LineComponent) + .getLineComponent(context) + } else { + body.asWick() + } + val bottomWick = + if (typedArray.hasValue(R.styleable.CandleStyle_bottomWickStyle)) { + typedArray + .getNestedTypedArray( + context, + R.styleable.CandleStyle_bottomWickStyle, + R.styleable.LineComponent, + ) + .getLineComponent(context) + } else { + topWick + } + CandlestickCartesianLayer.Candle(body, topWick, bottomWick) + } + } else { + null } diff --git a/vico/views/src/main/res/values/candlestick_chart_attrs.xml b/vico/views/src/main/res/values/candlestick_chart_attrs.xml index 67323fcf6..e2ba7081e 100644 --- a/vico/views/src/main/res/values/candlestick_chart_attrs.xml +++ b/vico/views/src/main/res/values/candlestick_chart_attrs.xml @@ -18,6 +18,10 @@ + + + +