Skip to content

Commit

Permalink
Make fixes related to CandlestickCartesianLayer XML attributes (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickmichalik committed Apr 1, 2024
1 parent c3e4c2f commit db4da49
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 171 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,26 @@

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 {
val filledBody = LineComponent(color, thicknessDp)
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,
Expand All @@ -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,
)
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand All @@ -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
}
4 changes: 4 additions & 0 deletions vico/views/src/main/res/values/candlestick_chart_attrs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
<attr name="candlestickLayerStyle" format="reference" />

<declare-styleable name="CandlestickLayerStyle">
<attr name="candleStyle" format="enum">
<enum name="absolute" value="0" />
<enum name="absoluteRelative" value="1" />
</attr>
<attr name="bullishCandleStyle" format="reference" />
<attr name="neutralCandleStyle" format="reference" />
<attr name="bearishCandleStyle" format="reference" />
Expand Down

0 comments on commit db4da49

Please sign in to comment.