From 364f0b745ca0fd1879356e43261d1ab106c30ade Mon Sep 17 00:00:00 2001 From: Patrick Michalik <120058021+patrickmichalik@users.noreply.github.com> Date: Thu, 28 Mar 2024 09:15:26 +0100 Subject: [PATCH] Add initial version of `ColumnCartesianLayer.ColumnProvider` Co-authored-by: Patryk Goworowski --- .../sample/previews/ContainedChartsPreview.kt | 5 +- .../vico/sample/previews/Previews.kt | 3 +- ...dColumnChartsWithNegativeValuesPreviews.kt | 13 +- .../vico/sample/showcase/charts/Chart4.kt | 15 +- .../vico/sample/showcase/charts/Chart5.kt | 4 +- .../vico/sample/showcase/charts/Chart6.kt | 5 +- .../vico/sample/showcase/charts/Chart8.kt | 18 +- .../chart/layer/ColumnCartesianLayer.kt | 80 +++++---- .../core/chart/layer/ColumnCartesianLayer.kt | 167 ++++++++++++++---- .../vico/views/theme/ChartStyleExtensions.kt | 4 +- 10 files changed, 223 insertions(+), 91 deletions(-) diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ContainedChartsPreview.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ContainedChartsPreview.kt index 0352c722f..7e166ccb2 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ContainedChartsPreview.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ContainedChartsPreview.kt @@ -39,6 +39,7 @@ import com.patrykandpatrick.vico.core.axis.AxisItemPlacer import com.patrykandpatrick.vico.core.axis.AxisPosition.Vertical import com.patrykandpatrick.vico.core.axis.AxisPosition.Vertical.End import com.patrykandpatrick.vico.core.axis.AxisPosition.Vertical.Start +import com.patrykandpatrick.vico.core.chart.layer.ColumnCartesianLayer import com.patrykandpatrick.vico.core.component.shape.Shapes import com.patrykandpatrick.vico.core.component.shape.shader.DynamicShaders import com.patrykandpatrick.vico.core.marker.Marker @@ -59,8 +60,8 @@ private val markerMap: Map @Composable private fun getColumnLayer(verticalAxisPosition: Vertical? = null) = rememberColumnCartesianLayer( - columns = - listOf( + columnProvider = + ColumnCartesianLayer.ColumnProvider.series( rememberLineComponent( color = Color.Black, thickness = 8.dp, diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/Previews.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/Previews.kt index 788ff80b4..bfe93daa9 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/Previews.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/Previews.kt @@ -49,6 +49,7 @@ import com.patrykandpatrick.vico.compose.component.shape.shader.verticalGradient import com.patrykandpatrick.vico.compose.component.shape.toVicoShape import com.patrykandpatrick.vico.compose.dimensions.dimensionsOf import com.patrykandpatrick.vico.core.axis.vertical.VerticalAxis +import com.patrykandpatrick.vico.core.chart.layer.ColumnCartesianLayer import com.patrykandpatrick.vico.core.chart.values.AxisValueOverrider import com.patrykandpatrick.vico.core.component.shape.DashedShape import com.patrykandpatrick.vico.core.component.shape.Shapes.pillShape @@ -73,7 +74,7 @@ public fun ColumnChartCard(): Unit = chart = rememberCartesianChart( rememberColumnCartesianLayer( - listOf( + ColumnCartesianLayer.ColumnProvider.series( rememberLineComponent( color = colors.primary, thickness = 8.dp, diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/StackedColumnChartsWithNegativeValuesPreviews.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/StackedColumnChartsWithNegativeValuesPreviews.kt index 30ea6090d..b6b26a5ad 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/StackedColumnChartsWithNegativeValuesPreviews.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/StackedColumnChartsWithNegativeValuesPreviews.kt @@ -34,7 +34,6 @@ import com.patrykandpatrick.vico.compose.component.rememberTextComponent import com.patrykandpatrick.vico.core.axis.AxisItemPlacer import com.patrykandpatrick.vico.core.chart.layer.ColumnCartesianLayer import com.patrykandpatrick.vico.core.chart.values.AxisValueOverrider -import com.patrykandpatrick.vico.core.component.shape.LineComponent import com.patrykandpatrick.vico.core.model.CartesianChartModel import com.patrykandpatrick.vico.core.model.ColumnCartesianLayerModel import com.patrykandpatrick.vico.sample.showcase.rememberMarker @@ -48,10 +47,10 @@ private val model = }, ) -private val columns: List +private val columnProvider @Composable get() = - listOf( + ColumnCartesianLayer.ColumnProvider.series( rememberLineComponent(color = Color(0xFF494949), thickness = 8.dp), rememberLineComponent(color = Color(0xFF7C7A7A), thickness = 8.dp), rememberLineComponent(color = Color(0xFFFF5D73), thickness = 8.dp), @@ -67,7 +66,7 @@ public fun StackedColumnChartWithNegativeValues() { chart = rememberCartesianChart( rememberColumnCartesianLayer( - columns = columns, + columnProvider = columnProvider, mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), startAxis = @@ -90,7 +89,7 @@ public fun StackedColumnChartWithNegativeValuesAndDataLabels() { chart = rememberCartesianChart( rememberColumnCartesianLayer( - columns = columns, + columnProvider = columnProvider, dataLabel = rememberTextComponent(), mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), @@ -113,7 +112,7 @@ public fun StackedColumnChartWithNegativeValuesAndAxisValuesOverridden() { chart = rememberCartesianChart( rememberColumnCartesianLayer( - columns = columns, + columnProvider = columnProvider, axisValueOverrider = AxisValueOverrider.fixed(minY = 1f, maxY = 4f), mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), @@ -136,7 +135,7 @@ public fun StackedColumnChartWithNegativeValuesAndAxisValuesOverridden2() { chart = rememberCartesianChart( rememberColumnCartesianLayer( - columns = columns, + columnProvider = columnProvider, axisValueOverrider = AxisValueOverrider.fixed(minY = -2f, maxY = 0f), mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart4.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart4.kt index 56c366f1c..39c6bb4d9 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart4.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart4.kt @@ -35,6 +35,7 @@ import com.patrykandpatrick.vico.compose.component.rememberLineComponent import com.patrykandpatrick.vico.compose.component.shape.roundedCornerShape import com.patrykandpatrick.vico.compose.component.shape.shader.color import com.patrykandpatrick.vico.core.chart.DefaultPointConnector +import com.patrykandpatrick.vico.core.chart.layer.ColumnCartesianLayer import com.patrykandpatrick.vico.core.component.shape.Shapes import com.patrykandpatrick.vico.core.component.shape.shader.DynamicShaders import com.patrykandpatrick.vico.core.model.CartesianChartModelProducer @@ -91,10 +92,16 @@ private fun ComposeChart4( chart = rememberCartesianChart( rememberColumnCartesianLayer( - columns = - columnColors.map { - rememberLineComponent(color = it, thickness = 8.dp, shape = Shapes.roundedCornerShape(2.dp)) - }, + columnProvider = + ColumnCartesianLayer.ColumnProvider.series( + columnColors.map { color -> + rememberLineComponent( + color = color, + thickness = 8.dp, + shape = Shapes.roundedCornerShape(2.dp), + ) + }, + ), ), rememberLineCartesianLayer( lines = diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart5.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart5.kt index 0bc4a6441..8378e3de5 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart5.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart5.kt @@ -87,8 +87,8 @@ private fun ComposeChart5( chart = rememberCartesianChart( rememberColumnCartesianLayer( - columns = - listOf( + columnProvider = + ColumnCartesianLayer.ColumnProvider.series( rememberLineComponent( color = color1, thickness = COLUMN_THICKNESS_DP.dp, diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart6.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart6.kt index 78e78cbde..e8f0263e2 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart6.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart6.kt @@ -38,6 +38,7 @@ import com.patrykandpatrick.vico.compose.dimensions.dimensionsOf import com.patrykandpatrick.vico.core.axis.AxisPosition import com.patrykandpatrick.vico.core.axis.formatter.AxisValueFormatter import com.patrykandpatrick.vico.core.axis.horizontal.HorizontalAxis +import com.patrykandpatrick.vico.core.chart.layer.ColumnCartesianLayer import com.patrykandpatrick.vico.core.component.shape.Shapes import com.patrykandpatrick.vico.core.model.CartesianChartModelProducer import com.patrykandpatrick.vico.core.model.columnSeries @@ -94,7 +95,9 @@ private fun ComposeChart6( chart = rememberCartesianChart( rememberColumnCartesianLayer( - columnColors.map { rememberLineComponent(color = it, thickness = 8.dp, shape = shape) }, + ColumnCartesianLayer.ColumnProvider.series( + columnColors.map { rememberLineComponent(color = it, thickness = 8.dp, shape = shape) }, + ), ), startAxis = rememberStartAxis(), bottomAxis = rememberBottomAxis(valueFormatter = bottomAxisValueFormatter), diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart8.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart8.kt index 74213cb18..87b2b7eec 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart8.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart8.kt @@ -95,14 +95,16 @@ private fun ComposeChart8( chart = rememberCartesianChart( rememberColumnCartesianLayer( - columns = - columnChartColors.map { color -> - rememberLineComponent( - color = color, - thickness = 8.dp, - shape = Shapes.roundedCornerShape(40), - ) - }, + columnProvider = + ColumnCartesianLayer.ColumnProvider.series( + columnChartColors.map { color -> + rememberLineComponent( + color = color, + thickness = 8.dp, + shape = Shapes.roundedCornerShape(40), + ) + }, + ), mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, verticalAxisPosition = AxisPosition.Vertical.Start, ), diff --git a/vico/compose/src/main/java/com/patrykandpatrick/vico/compose/chart/layer/ColumnCartesianLayer.kt b/vico/compose/src/main/java/com/patrykandpatrick/vico/compose/chart/layer/ColumnCartesianLayer.kt index 8c3837e56..941f070d5 100644 --- a/vico/compose/src/main/java/com/patrykandpatrick/vico/compose/chart/layer/ColumnCartesianLayer.kt +++ b/vico/compose/src/main/java/com/patrykandpatrick/vico/compose/chart/layer/ColumnCartesianLayer.kt @@ -24,8 +24,6 @@ import com.patrykandpatrick.vico.compose.component.rememberLineComponent import com.patrykandpatrick.vico.compose.theme.vicoTheme import com.patrykandpatrick.vico.core.Defaults import com.patrykandpatrick.vico.core.axis.AxisPosition -import com.patrykandpatrick.vico.core.axis.vertical.VerticalAxis -import com.patrykandpatrick.vico.core.chart.layer.CartesianLayer import com.patrykandpatrick.vico.core.chart.layer.ColumnCartesianLayer import com.patrykandpatrick.vico.core.chart.layer.ColumnCartesianLayer.MergeMode import com.patrykandpatrick.vico.core.chart.values.AxisValueOverrider @@ -40,34 +38,19 @@ import com.patrykandpatrick.vico.core.model.drawing.ColumnCartesianLayerDrawingM import com.patrykandpatrick.vico.core.model.drawing.DefaultDrawingModelInterpolator import com.patrykandpatrick.vico.core.model.drawing.DrawingModelInterpolator -/** - * Creates a [ColumnCartesianLayer]. - * - * @param columns the [LineComponent] instances to use for columns. This list is iterated through as many times - * as necessary for each column collection. If the list contains a single element, all columns have the same appearance. - * @param spacing the distance between neighboring column collections. - * @param innerSpacing the distance between neighboring grouped columns. - * @param mergeMode defines how columns should be drawn in column collections. - * @param dataLabel an optional [TextComponent] to use for data labels. - * @param dataLabelVerticalPosition the vertical position of data labels relative to the top of their - * respective columns. - * @param dataLabelValueFormatter the [ValueFormatter] to use for data labels. - * @param dataLabelRotationDegrees the rotation of data labels (in degrees). - * @param axisValueOverrider overrides the _x_ and _y_ ranges. - * @param verticalAxisPosition the position of the [VerticalAxis] with which the [ColumnCartesianLayer] should be - * associated. Use this for independent [CartesianLayer] scaling. - * @param drawingModelInterpolator interpolates the [ColumnCartesianLayer]’s [ColumnCartesianLayerDrawingModel]s. - */ +/** Creates and remembers a [ColumnCartesianLayer]. */ @Composable public fun rememberColumnCartesianLayer( - columns: List = - vicoTheme.cartesianLayerColors.map { color -> - rememberLineComponent( - color, - Defaults.COLUMN_WIDTH.dp, - Shapes.roundedCornerShape(Defaults.COLUMN_ROUNDNESS_PERCENT), - ) - }, + columnProvider: ColumnCartesianLayer.ColumnProvider = + ColumnCartesianLayer.ColumnProvider.series( + vicoTheme.cartesianLayerColors.map { color -> + rememberLineComponent( + color, + Defaults.COLUMN_WIDTH.dp, + Shapes.roundedCornerShape(Defaults.COLUMN_ROUNDNESS_PERCENT), + ) + }, + ), spacing: Dp = Defaults.COLUMN_OUTSIDE_SPACING.dp, innerSpacing: Dp = Defaults.COLUMN_INSIDE_SPACING.dp, mergeMode: (ExtraStore) -> MergeMode = { MergeMode.Grouped }, @@ -81,8 +64,8 @@ public fun rememberColumnCartesianLayer( DrawingModelInterpolator = remember { DefaultDrawingModelInterpolator() }, ): ColumnCartesianLayer = - remember { ColumnCartesianLayer() }.apply { - this.columns = columns + remember { ColumnCartesianLayer(columnProvider) }.apply { + this.columnProvider = columnProvider this.spacingDp = spacing.value this.innerSpacingDp = innerSpacing.value this.mergeMode = mergeMode @@ -94,3 +77,40 @@ public fun rememberColumnCartesianLayer( this.verticalAxisPosition = verticalAxisPosition this.drawingModelInterpolator = drawingModelInterpolator } + +/** + * Creates and remembers a [ColumnCartesianLayer] with the provided column [LineComponent]s ([columns]). One + * [LineComponent] is used per series. The [LineComponent]s and series are associated by index. If there are more series + * than [LineComponent]s, [columns] is iterated multiple times. + */ +@Composable +@Suppress("DeprecatedCallableAddReplaceWith") +@Deprecated("Replace `columns = ...` with `columnProvider = ColumnCartesianLayer.ColumnProvider.series(...)`.") +public fun rememberColumnCartesianLayer( + columns: List, + spacing: Dp = Defaults.COLUMN_OUTSIDE_SPACING.dp, + innerSpacing: Dp = Defaults.COLUMN_INSIDE_SPACING.dp, + mergeMode: (ExtraStore) -> MergeMode = { MergeMode.Grouped }, + verticalAxisPosition: AxisPosition.Vertical? = null, + dataLabel: TextComponent? = null, + dataLabelVerticalPosition: VerticalPosition = VerticalPosition.Top, + dataLabelValueFormatter: ValueFormatter = remember { DecimalFormatValueFormatter() }, + dataLabelRotationDegrees: Float = 0f, + axisValueOverrider: AxisValueOverrider = remember { AxisValueOverrider.auto() }, + drawingModelInterpolator: + DrawingModelInterpolator = + remember { DefaultDrawingModelInterpolator() }, +): ColumnCartesianLayer = + rememberColumnCartesianLayer( + ColumnCartesianLayer.ColumnProvider.series(columns), + spacing, + innerSpacing, + mergeMode, + verticalAxisPosition, + dataLabel, + dataLabelVerticalPosition, + dataLabelValueFormatter, + dataLabelRotationDegrees, + axisValueOverrider, + drawingModelInterpolator, + ) diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/chart/layer/ColumnCartesianLayer.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/chart/layer/ColumnCartesianLayer.kt index fa7ad0b9e..3c5215b54 100644 --- a/vico/core/src/main/java/com/patrykandpatrick/vico/core/chart/layer/ColumnCartesianLayer.kt +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/chart/layer/ColumnCartesianLayer.kt @@ -48,24 +48,22 @@ import com.patrykandpatrick.vico.core.model.forEachInIndexed import kotlin.math.abs /** - * [ColumnCartesianLayer] displays data as vertical bars. It can group and stack columns. + * Displays data as vertical bars. * - * @param columns the [LineComponent] instances to use for columns. This list is iterated through as many times - * as necessary for each column collection. If the list contains a single element, all columns have the same appearance. - * @param spacingDp the distance between neighboring column collections. - * @param innerSpacingDp the distance between neighboring grouped columns. - * @param mergeMode defines how columns should be drawn in column collections. - * @param verticalAxisPosition the position of the [VerticalAxis] with which the [ColumnCartesianLayer] should be + * @property columnProvider provides the column [LineComponent]s. + * @property spacingDp the spacing between neighboring column collections. + * @property innerSpacingDp the spacing between neighboring grouped columns. + * @property mergeMode defines how columns should be drawn in column collections. + * @property verticalAxisPosition the position of the [VerticalAxis] with which the [ColumnCartesianLayer] should be * associated. Use this for independent [CartesianLayer] scaling. - * @param dataLabel an optional [TextComponent] to use for data labels. - * @param dataLabelVerticalPosition the vertical position of data labels relative to the top of their - * respective columns. - * @param dataLabelValueFormatter the [ValueFormatter] to use for data labels. - * @param dataLabelRotationDegrees the rotation of data labels (in degrees). - * @param drawingModelInterpolator interpolates the [ColumnCartesianLayer]’s [ColumnCartesianLayerDrawingModel]s. + * @property dataLabel the [TextComponent] for the data labels. Use `null` for no data labels. + * @property dataLabelVerticalPosition the vertical position of each data label relative to its column’s top edge. + * @property dataLabelValueFormatter the [ValueFormatter] for the data labels. + * @property dataLabelRotationDegrees the rotation of the data labels (in degrees). + * @property drawingModelInterpolator interpolates the [ColumnCartesianLayer]’s [ColumnCartesianLayerDrawingModel]s. */ public open class ColumnCartesianLayer( - public var columns: List, + public var columnProvider: ColumnProvider, public var spacingDp: Float = Defaults.COLUMN_OUTSIDE_SPACING, public var innerSpacingDp: Float = Defaults.COLUMN_INSIDE_SPACING, public var mergeMode: (ExtraStore) -> MergeMode = { MergeMode.Grouped }, @@ -78,25 +76,62 @@ public open class ColumnCartesianLayer( DrawingModelInterpolator = DefaultDrawingModelInterpolator(), ) : BaseCartesianLayer() { + /** Creates a [ColumnCartesianLayer] with a common [LineComponent] ([column]) for all columns. */ + @Deprecated( + "Use the primary constructor. Replace `column = ...` with `columnProvider = " + + "ColumnCartesianLayer.ColumnProvider.series(...)`.", + ) + public constructor( + column: LineComponent, + spacingDp: Float = Defaults.COLUMN_OUTSIDE_SPACING, + verticalAxisPosition: AxisPosition.Vertical? = null, + ) : this( + columnProvider = ColumnProvider.series(column), + spacingDp = spacingDp, + verticalAxisPosition = verticalAxisPosition, + ) + /** - * Creates a [ColumnCartesianLayer] with a common style for all columns. - * - * @param column a [LineComponent] defining the appearance of the columns. - * @param spacingDp the distance between neighboring column collections. - * @param verticalAxisPosition the position of the [VerticalAxis] with which the [ColumnCartesianLayer] should - * be associated. Use this for independent [CartesianLayer] scaling. + * Creates a [ColumnCartesianLayer] with the provided column [LineComponent]s ([columns]). One [LineComponent] is + * used per series. The [LineComponent]s and series are associated by index. If there are more series than + * [LineComponent]s, [columns] is iterated multiple times. */ + @Deprecated("Replace `columns = ...` with `columnProvider = ColumnCartesianLayer.ColumnProvider.series(...)`.") public constructor( - column: LineComponent, + columns: List, spacingDp: Float = Defaults.COLUMN_OUTSIDE_SPACING, + innerSpacingDp: Float = Defaults.COLUMN_INSIDE_SPACING, + mergeMode: (ExtraStore) -> MergeMode = { MergeMode.Grouped }, verticalAxisPosition: AxisPosition.Vertical? = null, - ) : this(columns = listOf(column), spacingDp = spacingDp, verticalAxisPosition = verticalAxisPosition) + dataLabel: TextComponent? = null, + dataLabelVerticalPosition: VerticalPosition = VerticalPosition.Top, + dataLabelValueFormatter: ValueFormatter = DecimalFormatValueFormatter(), + dataLabelRotationDegrees: Float = 0f, + drawingModelInterpolator: + DrawingModelInterpolator = + DefaultDrawingModelInterpolator(), + ) : this( + ColumnProvider.series(columns), + spacingDp, + innerSpacingDp, + mergeMode, + verticalAxisPosition, + dataLabel, + dataLabelVerticalPosition, + dataLabelValueFormatter, + dataLabelRotationDegrees, + drawingModelInterpolator, + ) /** - * Creates a [ColumnCartesianLayer] instance with [columns] set to an empty list. The list must be populated before - * the chart is drawn. + * Creates a [ColumnCartesianLayer] with no column [LineComponent]s. `columnProvider` must be updated before the + * [ColumnCartesianLayer] is used. */ - public constructor() : this(emptyList()) + @Deprecated( + "Use the primary constructor.", + ReplaceWith("ColumnCartesianLayer(ColumnCartesianLayer.ColumnProvider.series())"), + ) + public constructor() : this(ColumnProvider.series()) protected val stackInfo: MutableMap = mutableMapOf() @@ -107,6 +142,22 @@ public open class ColumnCartesianLayer( protected val drawingModelKey: ExtraStore.Key = ExtraStore.Key() + /** + * The column [LineComponent]s. One [LineComponent] is used per series. The [LineComponent]s and series are + * associated by index. If there are more series than [LineComponent]s, this list is iterated multiple times. + */ + @Deprecated( + "Use `columnProvider` instead. More information: https://patrykandpatrick.com/vico/releases/2.0.0-alpha.13.", + ) + public var columns: List + get() = + checkNotNull(columnProvider as? ColumnProvider.Companion.Series) { + "`columns` is deprecated and can’t be used with custom `ColumnProvider`s." + }.columns + set(value) { + columnProvider = ColumnProvider.series(value) + } + override val entryLocationMap: HashMap> = HashMap() override fun drawInternal( @@ -134,7 +185,6 @@ public open class ColumnCartesianLayer( var drawingStart: Float var height: Float var columnCenterX: Float - var column: LineComponent var columnTop: Float var columnBottom: Float val zeroLinePosition = bounds.bottom + yRange.minY / yRange.length * bounds.height() @@ -142,7 +192,6 @@ public open class ColumnCartesianLayer( model.series.forEachIndexed { index, entryCollection -> - column = columns.getRepeating(index) drawingStart = getDrawingStart(index, model.series.size, mergeMode) - horizontalScroll entryCollection.forEachInIndexed(chartValues.minX..chartValues.maxX) { entryIndex, entry, _ -> @@ -151,9 +200,11 @@ public open class ColumnCartesianLayer( height = (columnInfo?.height ?: (abs(entry.y) / yRange.length)) * bounds.height() val xSpacingMultiplier = (entry.x - chartValues.minX) / chartValues.xStep check(xSpacingMultiplier % 1f == 0f) { "Each entry’s x value must be a multiple of the x step." } - columnCenterX = drawingStart + - (horizontalDimensions.xSpacing * xSpacingMultiplier + column.thicknessDp.half.pixels * zoom) * - layoutDirectionMultiplier + val column = columnProvider.getColumn(entry, index, model.extraStore) + columnCenterX = drawingStart + ( + horizontalDimensions.xSpacing * xSpacingMultiplier + + columnProvider.getWidestSeriesColumn(index, model.extraStore).thicknessDp.half.pixels * zoom + ) * layoutDirectionMultiplier when (mergeMode) { MergeMode.Stacked -> { @@ -394,7 +445,11 @@ public open class ColumnCartesianLayer( ): Float = when (mergeMode) { MergeMode.Stacked -> - columns.take(entryCollectionSize).maxOf { it.thicknessDp.pixels } + (0.. + columnProvider.getWidestSeriesColumn(seriesIndex, chartValues.model.extraStore).thicknessDp + } + .pixels MergeMode.Grouped -> getCumulatedThickness(entryCollectionSize) + innerSpacingDp.pixels * (entryCollectionSize - 1) @@ -420,10 +475,10 @@ public open class ColumnCartesianLayer( protected open fun MeasureContext.getCumulatedThickness(count: Int): Float { var thickness = 0f - for (i in 0..) : ColumnProvider { + override fun getColumn( + entry: ColumnCartesianLayerModel.Entry, + seriesIndex: Int, + extraStore: ExtraStore, + ): LineComponent = columns.getRepeating(seriesIndex) + + override fun getWidestSeriesColumn( + seriesIndex: Int, + extraStore: ExtraStore, + ): LineComponent = columns.getRepeating(seriesIndex) + } + + /** + * Uses one [LineComponent] per series. The [LineComponent]s ([columns]) and series are associated by index. + * If there are more series than [LineComponent]s, [columns] is iterated multiple times. + */ + public fun series(columns: List): ColumnProvider = Series(columns) + + /** + * Uses one [LineComponent] per series. The [LineComponent]s ([columns]) and series are associated by index. + * If there are more series than [LineComponent]s, the [LineComponent] list is iterated multiple times. + */ + public fun series(vararg columns: LineComponent): ColumnProvider = series(columns.toList()) + } + } } diff --git a/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ChartStyleExtensions.kt b/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ChartStyleExtensions.kt index 46fcc3996..1c15de9df 100644 --- a/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ChartStyleExtensions.kt +++ b/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ChartStyleExtensions.kt @@ -39,8 +39,8 @@ internal fun TypedArray.getColumnCartesianLayer( getInteger(R.styleable.ColumnCartesianLayerStyle_mergeMode, 0) .let(ColumnCartesianLayer.MergeMode.entries::get) ColumnCartesianLayer( - columns = - listOf( + columnProvider = + ColumnCartesianLayer.ColumnProvider.series( getNestedTypedArray( context = context, resourceId = R.styleable.ColumnCartesianLayerStyle_column1,