Skip to content

Commit

Permalink
Make CartesianMarker-related fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickmichalik committed Apr 19, 2024
1 parent 42040a4 commit 691761a
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import com.patrykandpatrick.vico.core.common.data.MutableExtraStore
import com.patrykandpatrick.vico.core.common.inClip
import com.patrykandpatrick.vico.core.common.set
import com.patrykandpatrick.vico.core.common.setAll
import java.util.SortedMap

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

private val drawingModelAndLayerConsumer =
object : ModelAndLayerConsumer {
Expand Down Expand Up @@ -117,7 +118,9 @@ public open class CartesianChart(
public val chartInsetters: Collection<ChartInsetter> = persistentMarkers.values

/** Links _x_ values to [CartesianMarker.Target]s. */
public val markerTargets: Map<Float, List<CartesianMarker.Target>> = _markerTargets
@Suppress("UNCHECKED_CAST")
public val markerTargets: SortedMap<Float, List<CartesianMarker.Target>> =
_markerTargets as SortedMap<Float, List<CartesianMarker.Target>>

/**
* The start axis.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ public fun CartesianDrawContext.drawMarker(
if (previousX != null) visibilityListener?.onHidden(marker)
return null
}
var targets = chart.markerTargets.values.first()
var previousDistance = abs(markerTouchPoint.x - targets.first().canvasX)
for (i in 1..<chart.markerTargets.size) {
val potentialTargets = chart.markerTargets.values.elementAt(i)
val distance = abs(markerTouchPoint.x - potentialTargets.first().canvasX)
var targets = emptyList<CartesianMarker.Target>()
var previousDistance = Float.POSITIVE_INFINITY
for (xTargets in chart.markerTargets.values) {
val (distance, canvasXTargets) =
xTargets.groupBy { abs(markerTouchPoint.x - it.canvasX) }.toSortedMap().entries.first()
if (distance > previousDistance) break
targets = potentialTargets
targets = canvasXTargets
previousDistance = distance
}
marker.draw(this, targets)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public open class CandlestickCartesianLayer(
public companion object
}

private val _markerTargets = mutableMapOf<Float, CandlestickCartesianLayerMarkerTarget>()
private val _markerTargets = mutableMapOf<Float, List<CandlestickCartesianLayerMarkerTarget>>()

/**
* Holds information on the [CandlestickCartesianLayer]’s horizontal dimensions.
Expand All @@ -98,7 +98,7 @@ public open class CandlestickCartesianLayer(

protected val drawingModelKey: ExtraStore.Key<CandlestickCartesianLayerDrawingModel> = ExtraStore.Key()

override val markerTargets: Map<Float, CartesianMarker.Target> = _markerTargets
override val markerTargets: Map<Float, List<CartesianMarker.Target>> = _markerTargets

override fun drawInternal(
context: CartesianDrawContext,
Expand Down Expand Up @@ -193,20 +193,22 @@ public open class CandlestickCartesianLayer(
val limitedBodyBottomCanvasY = bodyBottomCanvasY.coerceIn(bounds.top, bounds.bottom)
val limitedBodyTopCanvasY = bodyTopCanvasY.coerceIn(bounds.top, bounds.bottom)
_markerTargets[entry.x] =
CandlestickCartesianLayerMarkerTarget(
x = entry.x,
canvasX = canvasX,
entry = entry,
openingCanvasY =
if (entry.absoluteChange == Change.Bullish) limitedBodyBottomCanvasY else limitedBodyTopCanvasY,
closingCanvasY =
if (entry.absoluteChange == Change.Bullish) limitedBodyTopCanvasY else limitedBodyBottomCanvasY,
lowCanvasY = lowCanvasY.coerceIn(bounds.top, bounds.bottom),
highCanvasY = highCanvasY.coerceIn(bounds.top, bounds.bottom),
openingColor = candle.body.solidOrStrokeColor,
closingColor = candle.body.solidOrStrokeColor,
lowColor = candle.bottomWick.solidOrStrokeColor,
highColor = candle.topWick.solidOrStrokeColor,
listOf(
CandlestickCartesianLayerMarkerTarget(
x = entry.x,
canvasX = canvasX,
entry = entry,
openingCanvasY =
if (entry.absoluteChange == Change.Bullish) limitedBodyBottomCanvasY else limitedBodyTopCanvasY,
closingCanvasY =
if (entry.absoluteChange == Change.Bullish) limitedBodyTopCanvasY else limitedBodyBottomCanvasY,
lowCanvasY = lowCanvasY.coerceIn(bounds.top, bounds.bottom),
highCanvasY = highCanvasY.coerceIn(bounds.top, bounds.bottom),
openingColor = candle.body.solidOrStrokeColor,
closingColor = candle.body.solidOrStrokeColor,
lowColor = candle.bottomWick.solidOrStrokeColor,
highColor = candle.topWick.solidOrStrokeColor,
),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import com.patrykandpatrick.vico.core.common.data.MutableExtraStore
*/
public interface CartesianLayer<T : CartesianLayerModel> : BoundsAware, ChartInsetter {
/** Links _x_ values to [CartesianMarker.Target]s. */
public val markerTargets: Map<Float, CartesianMarker.Target>
public val markerTargets: Map<Float, List<CartesianMarker.Target>>

/**
* Draws the [CartesianLayer].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public open class ColumnCartesianLayer(
DrawingModelInterpolator<ColumnCartesianLayerDrawingModel.ColumnInfo, ColumnCartesianLayerDrawingModel> =
DefaultDrawingModelInterpolator(),
) : BaseCartesianLayer<ColumnCartesianLayerModel>() {
private val _markerTargets = mutableMapOf<Float, MutableColumnCartesianLayerMarkerTarget>()
private val _markerTargets = mutableMapOf<Float, MutableList<MutableColumnCartesianLayerMarkerTarget>>()

protected val stackInfo: MutableMap<Float, StackInfo> = mutableMapOf()

Expand All @@ -87,7 +87,7 @@ public open class ColumnCartesianLayer(

protected val drawingModelKey: ExtraStore.Key<ColumnCartesianLayerDrawingModel> = ExtraStore.Key()

override val markerTargets: Map<Float, CartesianMarker.Target> = _markerTargets
override val markerTargets: Map<Float, List<CartesianMarker.Target>> = _markerTargets

override fun drawInternal(
context: CartesianDrawContext,
Expand Down Expand Up @@ -165,7 +165,7 @@ public open class ColumnCartesianLayer(
thicknessScale = zoom,
)
) {
updateMarkerTargets(entry, columnCenterX, columnSignificantY, column)
updateMarkerTargets(entry, columnCenterX, columnSignificantY, column, mergeMode)
column.drawVertical(this, columnTop, columnBottom, columnCenterX, zoom, drawingModel?.opacity ?: 1f)
}

Expand Down Expand Up @@ -310,16 +310,30 @@ public open class ColumnCartesianLayer(
canvasX: Float,
canvasY: Float,
column: LineComponent,
mergeMode: MergeMode,
) {
if (canvasX <= bounds.left - 1 || canvasX >= bounds.right + 1) return
_markerTargets
.getOrPut(entry.x) { MutableColumnCartesianLayerMarkerTarget(entry.x, canvasX) }
.columns +=
val targetColumn =
ColumnCartesianLayerMarkerTarget.Column(
entry,
canvasY.coerceIn(bounds.top, bounds.bottom),
column.solidOrStrokeColor,
)
when (mergeMode) {
MergeMode.Grouped ->
_markerTargets.getOrPut(entry.x) { mutableListOf() } +=
MutableColumnCartesianLayerMarkerTarget(entry.x, canvasX, mutableListOf(targetColumn))
MergeMode.Stacked ->
_markerTargets
.getOrPut(entry.x) { mutableListOf(MutableColumnCartesianLayerMarkerTarget(entry.x, canvasX)) }
.first()
.columns +=
ColumnCartesianLayerMarkerTarget.Column(
entry,
canvasY.coerceIn(bounds.top, bounds.bottom),
column.solidOrStrokeColor,
)
}
}

override fun updateChartValues(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public open class LineCartesianLayer(
}
}

private val _markerTargets = mutableMapOf<Float, MutableLineCartesianLayerMarkerTarget>()
private val _markerTargets = mutableMapOf<Float, List<MutableLineCartesianLayerMarkerTarget>>()

/**
* The [Path] used to draw the lines, each of which corresponds to a [LineSpec].
Expand All @@ -265,7 +265,7 @@ public open class LineCartesianLayer(

protected val drawingModelKey: ExtraStore.Key<LineCartesianLayerDrawingModel> = ExtraStore.Key()

override val markerTargets: Map<Float, CartesianMarker.Target> = _markerTargets
override val markerTargets: Map<Float, List<CartesianMarker.Target>> = _markerTargets

override fun drawInternal(
context: CartesianDrawContext,
Expand Down Expand Up @@ -349,7 +349,8 @@ public open class LineCartesianLayer(
if (canvasX <= bounds.left - 1 || canvasX >= bounds.right + 1) return
val limitedCanvasY = canvasY.coerceIn(bounds.top, bounds.bottom)
_markerTargets
.getOrPut(entry.x) { MutableLineCartesianLayerMarkerTarget(entry.x, canvasX) }
.getOrPut(entry.x) { listOf(MutableLineCartesianLayerMarkerTarget(entry.x, canvasX)) }
.first()
.points +=
LineCartesianLayerMarkerTarget.Point(
entry,
Expand Down

0 comments on commit 691761a

Please sign in to comment.