Skip to content

Commit

Permalink
Make CartesianMarker-related updates (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickmichalik committed Mar 31, 2024
1 parent ac8deca commit 908fbfb
Show file tree
Hide file tree
Showing 23 changed files with 452 additions and 449 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ import com.patrykandpatrick.vico.core.cartesian.CartesianMeasureContext
import com.patrykandpatrick.vico.core.cartesian.dimensions.HorizontalDimensions
import com.patrykandpatrick.vico.core.cartesian.insets.Insets
import com.patrykandpatrick.vico.core.cartesian.marker.CartesianMarker
import com.patrykandpatrick.vico.core.common.component.CartesianMarkerComponent
import com.patrykandpatrick.vico.core.cartesian.marker.DefaultCartesianMarker
import com.patrykandpatrick.vico.core.common.component.TextComponent
import com.patrykandpatrick.vico.core.common.extension.copyColor
import com.patrykandpatrick.vico.core.common.shape.Corner
import com.patrykandpatrick.vico.core.common.shape.Shapes

@Composable
internal fun rememberMarker(
labelPosition: CartesianMarkerComponent.LabelPosition = CartesianMarkerComponent.LabelPosition.Top,
labelPosition: DefaultCartesianMarker.LabelPosition = DefaultCartesianMarker.LabelPosition.Top,
): CartesianMarker {
val labelBackgroundShape = Shapes.markerCorneredShape(Corner.FullyRounded)
val labelBackground =
Expand Down Expand Up @@ -82,18 +82,18 @@ internal fun rememberMarker(
shape = Shapes.dashedShape(shape = Shapes.pillShape, dashLength = 8.dp, gapLength = 4.dp),
)
return remember(label, labelPosition, indicator, guideline) {
object : CartesianMarkerComponent(label, labelPosition, indicator, guideline) {
init {
indicatorSizeDp = 36f
onApplyEntryColor = { entryColor ->
indicatorRearComponent.color = entryColor.copyColor(alpha = .15f)
with(indicatorCenterComponent) {
color = entryColor
setShadow(radius = 12f, color = entryColor)
}
}
}

object : DefaultCartesianMarker(
label = label,
labelPosition = labelPosition,
indicator = indicator,
indicatorSizeDp = 36f,
setIndicatorColor = { color ->
indicatorRearComponent.color = color.copyColor(alpha = .15f)
indicatorCenterComponent.color = color
indicatorCenterComponent.setShadow(radius = 12f, color = color)
},
guideline = guideline,
) {
override fun getInsets(
context: CartesianMeasureContext,
outInsets: Insets,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ import com.patrykandpatrick.vico.compose.common.shader.color
import com.patrykandpatrick.vico.core.cartesian.HorizontalLayout
import com.patrykandpatrick.vico.core.cartesian.axis.VerticalAxis
import com.patrykandpatrick.vico.core.cartesian.layer.LineCartesianLayer
import com.patrykandpatrick.vico.core.cartesian.marker.DefaultCartesianMarker
import com.patrykandpatrick.vico.core.cartesian.model.CartesianChartModelProducer
import com.patrykandpatrick.vico.core.cartesian.model.lineSeries
import com.patrykandpatrick.vico.core.cartesian.values.AxisValueOverrider
import com.patrykandpatrick.vico.core.common.component.CartesianMarkerComponent
import com.patrykandpatrick.vico.core.common.shader.DynamicShaders
import com.patrykandpatrick.vico.core.common.shape.Shapes
import com.patrykandpatrick.vico.databinding.Chart3Binding
Expand Down Expand Up @@ -122,7 +122,7 @@ private fun ComposeChart3(
),
modelProducer = modelProducer,
modifier = modifier,
marker = rememberMarker(CartesianMarkerComponent.LabelPosition.AroundPoint),
marker = rememberMarker(DefaultCartesianMarker.LabelPosition.AroundPoint),
runInitialAnimation = false,
horizontalLayout = HorizontalLayout.fullWidth(),
zoomState = rememberVicoZoomState(zoomEnabled = false),
Expand All @@ -134,7 +134,7 @@ private fun ViewChart3(
modelProducer: CartesianChartModelProducer,
modifier: Modifier,
) {
val marker = rememberMarker(CartesianMarkerComponent.LabelPosition.AroundPoint)
val marker = rememberMarker(DefaultCartesianMarker.LabelPosition.AroundPoint)

AndroidViewBinding(Chart3Binding::inflate, modifier) {
with(chartView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ internal fun CartesianChartHostImpl(
with(LocalContext.current) { ::spToPx },
chartValues,
)
val lastMarkerEntryModels = remember { mutableStateOf(emptyList<CartesianMarker.EntryModel>()) }
val previousMarkerEntries = remember { mutableStateOf(emptyList<CartesianMarker.Entry>()) }

val elevationOverlayColor = vicoTheme.elevationOverlayColor.toArgb()
val (wasMarkerVisible, setWasMarkerVisible) = remember { mutableStateOf(false) }
Expand Down Expand Up @@ -287,8 +287,8 @@ internal fun CartesianChartHostImpl(
markerVisibilityChangeListener = markerVisibilityChangeListener,
wasMarkerVisible = wasMarkerVisible,
setWasMarkerVisible = setWasMarkerVisible,
lastMarkerEntryModels = lastMarkerEntryModels.value,
onMarkerEntryModelsChange = lastMarkerEntryModels.component2(),
previousEntries = previousMarkerEntries.value,
onEntriesChanged = previousMarkerEntries.component2(),
)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2024 by Patryk Goworowski and Patrick Michalik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.patrykandpatrick.vico.compose.cartesian.marker

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.patrykandpatrick.vico.core.cartesian.marker.CartesianMarkerLabelFormatter
import com.patrykandpatrick.vico.core.cartesian.marker.DefaultCartesianMarker
import com.patrykandpatrick.vico.core.cartesian.marker.DefaultCartesianMarkerLabelFormatter
import com.patrykandpatrick.vico.core.common.component.Component
import com.patrykandpatrick.vico.core.common.component.LineComponent
import com.patrykandpatrick.vico.core.common.component.TextComponent

/** Creates and remembers a [DefaultCartesianMarker]. */
@Composable
public fun rememberDefaultCartesianMarker(
label: TextComponent,
labelFormatter: CartesianMarkerLabelFormatter = remember { DefaultCartesianMarkerLabelFormatter() },
labelPosition: DefaultCartesianMarker.LabelPosition = DefaultCartesianMarker.LabelPosition.Top,
indicator: Component? = null,
indicatorSize: Dp = 0.dp,
setIndicatorColor: ((Int) -> Unit)? = null,
guideline: LineComponent? = null,
): DefaultCartesianMarker =
remember(label, labelFormatter, labelPosition, indicator, indicatorSize, setIndicatorColor, guideline) {
DefaultCartesianMarker(
label,
labelFormatter,
labelPosition,
indicator,
indicatorSize.value,
setIndicatorColor,
guideline,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,8 @@ import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.patrykandpatrick.vico.core.common.Defaults.SHADOW_COLOR
import com.patrykandpatrick.vico.core.common.component.CartesianMarkerComponent
import com.patrykandpatrick.vico.core.common.component.ShapeComponent

/**
* The indicator size.
*/
public var CartesianMarkerComponent.indicatorSize: Dp
get() = indicatorSizeDp.dp
set(value) {
indicatorSizeDp = value.value
}

/**
* Applies a drop shadow to this [ShapeComponent].
*
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,10 @@ import com.patrykandpatrick.vico.core.cartesian.values.ChartValues
import com.patrykandpatrick.vico.core.cartesian.values.MutableChartValues
import com.patrykandpatrick.vico.core.common.MutableExtraStore
import com.patrykandpatrick.vico.core.common.dimension.BoundsAware
import com.patrykandpatrick.vico.core.common.extension.getEntryModel
import com.patrykandpatrick.vico.core.common.extension.inClip
import com.patrykandpatrick.vico.core.common.extension.set
import com.patrykandpatrick.vico.core.common.extension.setAll
import com.patrykandpatrick.vico.core.common.extension.updateAll
import com.patrykandpatrick.vico.core.common.legend.Legend
import java.util.TreeMap

/**
* A chart based on a Cartesian coordinate plane, composed of [CartesianLayer]s.
Expand All @@ -62,6 +59,7 @@ public open class CartesianChart(
private val tempInsets = Insets()
private val axisManager = AxisManager()
private val virtualLayout = VirtualLayout(axisManager)
private val _markerEntries = mutableMapOf<Float, MutableList<CartesianMarker.Entry>>()

private val drawingModelAndLayerConsumer =
object : ModelAndLayerConsumer {
Expand All @@ -72,7 +70,7 @@ public open class CartesianChart(
layer: CartesianLayer<T>,
) {
layer.draw(context, model ?: return)
entryLocationMap.updateAll(layer.entryLocationMap)
layer.markerEntries.forEach { _markerEntries.getOrPut(it.key) { mutableListOf() }.add(it.value) }
}
}

Expand Down Expand Up @@ -124,10 +122,8 @@ public open class CartesianChart(
*/
public val chartInsetters: Collection<ChartInsetter> = persistentMarkers.values

/**
* Links _x_ values to [CartesianMarker.EntryModel]s.
*/
public val entryLocationMap: TreeMap<Float, MutableList<CartesianMarker.EntryModel>> = TreeMap()
/** Links pixel _x_ values to [CartesianMarker.Entry] instances. */
public val markerEntries: Map<Float, List<CartesianMarker.Entry>> = _markerEntries

/**
* The start axis.
Expand Down Expand Up @@ -174,7 +170,7 @@ public open class CartesianChart(
bounds: RectF,
marker: CartesianMarker?,
) {
entryLocationMap.clear()
_markerEntries.clear()
model.forEachWithLayer(
horizontalDimensionUpdateModelAndLayerConsumer.apply {
this.context = context
Expand Down Expand Up @@ -208,9 +204,8 @@ public open class CartesianChart(
decorations.forEach { it.onDrawAboveChart(context, bounds) }
}
persistentMarkers.forEach { (x, marker) ->
entryLocationMap.getEntryModel(x)?.let { model ->
marker.draw(context, bounds, model, context.chartValues)
}
val entries = markerEntries.values.filter { entries -> entries.first().x == x }.flatten()
if (entries.isNotEmpty()) marker.draw(context, entries)
}
legend?.draw(context, bounds)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import com.patrykandpatrick.vico.core.cartesian.marker.CartesianMarker
import com.patrykandpatrick.vico.core.cartesian.marker.CartesianMarkerVisibilityChangeListener
import com.patrykandpatrick.vico.core.common.DrawContext
import com.patrykandpatrick.vico.core.common.Point
import com.patrykandpatrick.vico.core.common.extension.getClosestMarkerEntryModel
import com.patrykandpatrick.vico.core.common.extension.findClosestPositiveValue

/** @suppress */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
Expand Down Expand Up @@ -75,34 +75,21 @@ public fun CartesianChartDrawContext.drawMarker(
markerVisibilityChangeListener: CartesianMarkerVisibilityChangeListener?,
wasMarkerVisible: Boolean,
setWasMarkerVisible: (Boolean) -> Unit,
lastMarkerEntryModels: List<CartesianMarker.EntryModel>,
onMarkerEntryModelsChange: (List<CartesianMarker.EntryModel>) -> Unit,
previousEntries: List<CartesianMarker.Entry>,
onEntriesChanged: (List<CartesianMarker.Entry>) -> Unit,
) {
markerTouchPoint
?.let(chart.entryLocationMap::getClosestMarkerEntryModel)
?.let { markerEntryModels ->
marker.draw(
context = this,
bounds = chart.bounds,
markedEntries = markerEntryModels,
chartValues = chartValues,
)
?.let { chart.markerEntries[chart.markerEntries.keys.findClosestPositiveValue(it.x)] }
?.let { entries ->
marker.draw(this, entries)
if (wasMarkerVisible.not()) {
markerVisibilityChangeListener?.onMarkerShown(
marker = marker,
markerEntryModels = markerEntryModels,
)
markerVisibilityChangeListener?.onMarkerShown(marker, entries)
setWasMarkerVisible(true)
}
val didMarkerMove = lastMarkerEntryModels.hasMoved(markerEntryModels)
val didMarkerMove = previousEntries.hasMoved(entries)
if (wasMarkerVisible && didMarkerMove) {
onMarkerEntryModelsChange(markerEntryModels)
if (lastMarkerEntryModels.isNotEmpty()) {
markerVisibilityChangeListener?.onMarkerMoved(
marker = marker,
markerEntryModels = markerEntryModels,
)
}
onEntriesChanged(entries)
if (previousEntries.isNotEmpty()) markerVisibilityChangeListener?.onMarkerMoved(marker, entries)
}
} ?: marker
.takeIf { wasMarkerVisible }
Expand All @@ -112,7 +99,6 @@ public fun CartesianChartDrawContext.drawMarker(
}
}

private fun List<CartesianMarker.EntryModel>.xPosition(): Float? = firstOrNull()?.entry?.x
private fun List<CartesianMarker.Entry>.xPosition() = firstOrNull()?.x

private fun List<CartesianMarker.EntryModel>.hasMoved(other: List<CartesianMarker.EntryModel>): Boolean =
xPosition() != other.xPosition()
private fun List<CartesianMarker.Entry>.hasMoved(other: List<CartesianMarker.Entry>) = xPosition() != other.xPosition()
Loading

0 comments on commit 908fbfb

Please sign in to comment.