diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ColumnChartsWithNegativeValuesPreviews.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ColumnChartsWithNegativeValuesPreviews.kt index 79cd2e3d7..62f8cffa8 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ColumnChartsWithNegativeValuesPreviews.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/ColumnChartsWithNegativeValuesPreviews.kt @@ -48,7 +48,9 @@ public fun SingleColumnChartWithNegativeValues() { rememberCartesianChart( rememberColumnCartesianLayer(), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 9) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 9 }) }, + ), bottomAxis = rememberBottomAxis(), persistentMarkers = mapOf(2f to marker, 3f to marker), ), @@ -82,7 +84,9 @@ public fun SingleColumnChartWithNegativeValuesAndAxisValuesOverridden() { rememberCartesianChart( rememberColumnCartesianLayer(axisValueOverrider = AxisValueOverrider.fixed(minY = 1f, maxY = 4f)), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 4) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 4 }) }, + ), bottomAxis = rememberBottomAxis(), ), model = model, @@ -99,7 +103,9 @@ public fun SingleColumnChartWithNegativeValuesAndAxisValuesOverridden2() { rememberCartesianChart( rememberColumnCartesianLayer(axisValueOverrider = AxisValueOverrider.fixed(minY = -2f, maxY = 0f)), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 3) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 3 }) }, + ), bottomAxis = rememberBottomAxis(), ), model = model, 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 40689e38c..c5299bfcf 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 @@ -90,14 +90,14 @@ private val startAxis: Axis @Composable get() = rememberStartAxis( label = rememberTextComponent(color = Color.Black), - itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 5) }, + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 5 }) }, ) private val endAxis: Axis @Composable get() = rememberEndAxis( label = rememberTextComponent(color = Color.DarkGray), - itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 7) }, + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 7 }) }, ) @Composable diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/LineChartsWithNegativeValuesPreviews.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/LineChartsWithNegativeValuesPreviews.kt index 7cd1423fc..0077c3db9 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/LineChartsWithNegativeValuesPreviews.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/previews/LineChartsWithNegativeValuesPreviews.kt @@ -68,7 +68,7 @@ public fun SingleLineChartWithNegativeValues() { ), startAxis = rememberStartAxis( - itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 4) }, + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 4 }) }, guideline = axisLineComponent(), ), bottomAxis = @@ -117,7 +117,9 @@ public fun SingleLineChartWithNegativeValuesAndAxisValuesOverridden() { rememberCartesianChart( rememberLineCartesianLayer(axisValueOverrider = AxisValueOverrider.fixed(minY = 1f, maxY = 4f)), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 4) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 4 }) }, + ), bottomAxis = rememberBottomAxis(), ), model = model, @@ -134,7 +136,9 @@ public fun SingleLineChartWithNegativeValuesAndAxisValuesOverridden2() { rememberCartesianChart( rememberLineCartesianLayer(axisValueOverrider = AxisValueOverrider.fixed(minY = -2f, maxY = 0f)), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 3) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 3 }) }, + ), bottomAxis = rememberBottomAxis(), ), model = model, 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 cee16e3f2..6972e0f26 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 @@ -71,7 +71,9 @@ public fun StackedColumnChartWithNegativeValues() { mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 8) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 8 }) }, + ), bottomAxis = rememberBottomAxis(), persistentMarkers = mapOf(2f to marker, 3f to marker), ), @@ -93,7 +95,9 @@ public fun StackedColumnChartWithNegativeValuesAndDataLabels() { mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 8) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 8 }) }, + ), bottomAxis = rememberBottomAxis(), ), model = model, @@ -114,7 +118,9 @@ public fun StackedColumnChartWithNegativeValuesAndAxisValuesOverridden() { mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 4) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 4 }) }, + ), bottomAxis = rememberBottomAxis(), ), model = model, @@ -135,7 +141,9 @@ public fun StackedColumnChartWithNegativeValuesAndAxisValuesOverridden2() { mergeMode = { ColumnCartesianLayer.MergeMode.Stacked }, ), startAxis = - rememberStartAxis(itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 3) }), + rememberStartAxis( + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 3 }) }, + ), bottomAxis = rememberBottomAxis(), ), model = model, diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart2.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart2.kt index 3fae914c8..39a8d5215 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart2.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart2.kt @@ -144,5 +144,5 @@ private val horizontalLayout = scalableStartPaddingDp = DefaultDimens.COLUMN_OUTSIDE_SPACING.half, scalableEndPaddingDp = DefaultDimens.COLUMN_OUTSIDE_SPACING.half, ) -private val startAxisItemPlacer = AxisItemPlacer.Vertical.default(MAX_START_AXIS_ITEM_COUNT) +private val startAxisItemPlacer = AxisItemPlacer.Vertical.default({ MAX_START_AXIS_ITEM_COUNT }) private val bottomAxisItemPlacer = AxisItemPlacer.Horizontal.default(BOTTOM_AXIS_ITEM_SPACING, BOTTOM_AXIS_ITEM_OFFSET) 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 9666ef435..08ea4a1fd 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 @@ -120,4 +120,4 @@ private val color1 = Color(COLOR_1_CODE) private val color2 = Color(COLOR_2_CODE) private val color3 = Color(COLOR_3_CODE) private val chartColors = listOf(color1, color2, color3) -private val startAxisItemPlacer = AxisItemPlacer.Vertical.default(MAX_START_AXIS_ITEM_COUNT) +private val startAxisItemPlacer = AxisItemPlacer.Vertical.default({ MAX_START_AXIS_ITEM_COUNT }) diff --git a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart9.kt b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart9.kt index 13d1b8da4..f1ec42a9f 100644 --- a/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart9.kt +++ b/sample/src/main/java/com/patrykandpatrick/vico/sample/showcase/charts/Chart9.kt @@ -147,7 +147,7 @@ private fun ComposeChart9(modelProducer: CartesianChartModelProducer) { ) }, ), - itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = 4) }, + itemPlacer = remember { AxisItemPlacer.Vertical.default(maxItemCount = { 4 }) }, ), bottomAxis = rememberBottomAxis( diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/AxisItemPlacer.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/AxisItemPlacer.kt index 4d88ac27c..6bba0a7bc 100644 --- a/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/AxisItemPlacer.kt +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/AxisItemPlacer.kt @@ -27,6 +27,7 @@ import com.patrykandpatrick.vico.core.chart.draw.ChartDrawContext import com.patrykandpatrick.vico.core.chart.layout.HorizontalLayout import com.patrykandpatrick.vico.core.chart.values.ChartValues import com.patrykandpatrick.vico.core.context.MeasureContext +import com.patrykandpatrick.vico.core.model.CartesianChartModel /** * Determines for what values an [Axis] is to display labels, ticks, and guidelines. @@ -181,6 +182,7 @@ public interface AxisItemPlacer { * Returns the top inset required by the [VerticalAxis]. */ public fun getTopVerticalAxisInset( + context: MeasureContext, verticalLabelPosition: VerticalAxis.VerticalLabelPosition, maxLabelHeight: Float, maxLineThickness: Float, @@ -190,6 +192,7 @@ public interface AxisItemPlacer { * Returns the bottom inset required by the [VerticalAxis]. */ public fun getBottomVerticalAxisInset( + context: MeasureContext, verticalLabelPosition: VerticalAxis.VerticalLabelPosition, maxLabelHeight: Float, maxLineThickness: Float, @@ -205,7 +208,7 @@ public interface AxisItemPlacer { * shifted tick will then be aligned with this axis, and the shifted guideline will be hidden. */ public fun default( - maxItemCount: Int = DEF_LABEL_COUNT, + maxItemCount: (CartesianChartModel) -> Int = { DEF_LABEL_COUNT }, shiftTopLines: Boolean = true, ): Vertical = DefaultVerticalAxisItemPlacer(maxItemCount, shiftTopLines) } diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/DefaultVerticalAxisItemPlacer.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/DefaultVerticalAxisItemPlacer.kt index 391875ac7..86dee97d8 100644 --- a/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/DefaultVerticalAxisItemPlacer.kt +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/DefaultVerticalAxisItemPlacer.kt @@ -22,16 +22,13 @@ import com.patrykandpatrick.vico.core.chart.draw.ChartDrawContext import com.patrykandpatrick.vico.core.chart.values.ChartValues import com.patrykandpatrick.vico.core.context.MeasureContext import com.patrykandpatrick.vico.core.extension.half +import com.patrykandpatrick.vico.core.model.CartesianChartModel import kotlin.math.max internal class DefaultVerticalAxisItemPlacer( - private val maxItemCount: Int, + private val maxItemCount: (CartesianChartModel) -> Int, private val shiftTopLines: Boolean, ) : AxisItemPlacer.Vertical { - init { - require(maxItemCount >= 0) { "`maxItemCount` must be nonnegative." } - } - override fun getShiftTopLines(chartDrawContext: ChartDrawContext): Boolean = shiftTopLines override fun getLabelValues( @@ -47,12 +44,13 @@ internal class DefaultVerticalAxisItemPlacer( maxLabelHeight: Float, position: AxisPosition.Vertical, ): List { + val maxItemCount = context.maxItemCount if (maxItemCount == 0) return emptyList() val yRange = context.chartValues.getYRange(position) return if (yRange.minY * yRange.maxY >= 0) { - getSimpleLabelValues(axisHeight, maxLabelHeight, yRange) + getSimpleLabelValues(maxItemCount, axisHeight, maxLabelHeight, yRange) } else { - getMixedLabelValues(axisHeight, maxLabelHeight, yRange) + getMixedLabelValues(maxItemCount, axisHeight, maxLabelHeight, yRange) } } @@ -65,11 +63,12 @@ internal class DefaultVerticalAxisItemPlacer( } override fun getTopVerticalAxisInset( + context: MeasureContext, verticalLabelPosition: VerticalAxis.VerticalLabelPosition, maxLabelHeight: Float, maxLineThickness: Float, ) = when { - maxItemCount == 0 -> 0f + context.maxItemCount == 0 -> 0f verticalLabelPosition == VerticalAxis.VerticalLabelPosition.Top -> maxLabelHeight + (if (shiftTopLines) maxLineThickness else -maxLineThickness).half @@ -81,12 +80,13 @@ internal class DefaultVerticalAxisItemPlacer( } override fun getBottomVerticalAxisInset( + context: MeasureContext, verticalLabelPosition: VerticalAxis.VerticalLabelPosition, maxLabelHeight: Float, maxLineThickness: Float, ): Float = when { - maxItemCount == 0 -> 0f + context.maxItemCount == 0 -> 0f verticalLabelPosition == VerticalAxis.VerticalLabelPosition.Top -> maxLineThickness verticalLabelPosition == VerticalAxis.VerticalLabelPosition.Center -> @@ -96,6 +96,7 @@ internal class DefaultVerticalAxisItemPlacer( } private fun getSimpleLabelValues( + maxItemCount: Int, axisHeight: Float, maxLabelHeight: Float, yRange: ChartValues.YRange, @@ -109,6 +110,7 @@ internal class DefaultVerticalAxisItemPlacer( } private fun getMixedLabelValues( + maxItemCount: Int, axisHeight: Float, maxLabelHeight: Float, yRange: ChartValues.YRange, @@ -144,4 +146,7 @@ internal class DefaultVerticalAxisItemPlacer( } return values } + + private val MeasureContext.maxItemCount: Int + get() = maxItemCount(chartValues.model).also { require(it >= 0) { "`maxItemCount` must be nonnegative." } } } diff --git a/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/VerticalAxis.kt b/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/VerticalAxis.kt index 9f152b4ca..0982c181e 100644 --- a/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/VerticalAxis.kt +++ b/vico/core/src/main/java/com/patrykandpatrick/vico/core/axis/vertical/VerticalAxis.kt @@ -240,8 +240,20 @@ public class VerticalAxis( val maxLabelHeight = getMaxLabelHeight() val maxLineThickness = maxOf(axisThickness, tickThickness) outInsets.set( - top = itemPlacer.getTopVerticalAxisInset(verticalLabelPosition, maxLabelHeight, maxLineThickness), - bottom = itemPlacer.getBottomVerticalAxisInset(verticalLabelPosition, maxLabelHeight, maxLineThickness), + top = + itemPlacer.getTopVerticalAxisInset( + context, + verticalLabelPosition, + maxLabelHeight, + maxLineThickness, + ), + bottom = + itemPlacer.getBottomVerticalAxisInset( + context, + verticalLabelPosition, + maxLabelHeight, + maxLineThickness, + ), ) } diff --git a/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ThemeHandler.kt b/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ThemeHandler.kt index ad46d79db..49b474632 100644 --- a/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ThemeHandler.kt +++ b/vico/views/src/main/java/com/patrykandpatrick/vico/views/theme/ThemeHandler.kt @@ -262,11 +262,13 @@ internal class ThemeHandler( } } - private fun TypedArray.getVerticalAxisItemPlacer(): AxisItemPlacer.Vertical = - AxisItemPlacer.Vertical.default( - maxItemCount = getInteger(R.styleable.Axis_maxVerticalAxisItemCount, DEF_LABEL_COUNT), + private fun TypedArray.getVerticalAxisItemPlacer(): AxisItemPlacer.Vertical { + val maxItemCount = getInteger(R.styleable.Axis_maxVerticalAxisItemCount, DEF_LABEL_COUNT) + return AxisItemPlacer.Vertical.default( + maxItemCount = { maxItemCount }, shiftTopLines = getBoolean(R.styleable.Axis_shiftTopVerticalAxisLines, true), ) + } private fun TypedArray.getStartAxis(): AxisRenderer? = if (getBoolean(R.styleable.CartesianChartView_showStartAxis, false)) {