Skip to content

Commit f65627d

Browse files
committed
Updates the MeasurementChart to include goal values in the Y-axis scaling calculation. This ensures that goal lines remain visible within the chart's viewport even when they fall outside the range of the measurement data, see #1288
1 parent 08ddbf1 commit f65627d

1 file changed

Lines changed: 22 additions & 5 deletions

File tree

android_app/app/src/main/java/com/health/openscale/ui/screen/components/MeasurementChart.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,14 @@ fun MeasurementChart(
330330
}
331331
}.collectAsStateWithLifecycle(initialValue = emptyList())
332332

333+
val goalValuesForScaling = remember(goalsToActuallyPlot, showGoalLinesSetting) {
334+
if (showGoalLinesSetting) {
335+
goalsToActuallyPlot.map { it.goalValue.toFloat() }
336+
} else {
337+
emptyList()
338+
}
339+
}
340+
333341
Column(modifier = modifier) {
334342
AnimatedVisibility(visible = effectiveShowTypeFilterRow) {
335343
MeasurementTypeFilterRow(
@@ -541,6 +549,7 @@ fun MeasurementChart(
541549
chartSeries = chartSeries,
542550
showDataPointsSetting = showDataPointsSetting,
543551
targetMeasurementTypeId = targetMeasurementTypeId,
552+
goalValuesForScaling = goalValuesForScaling
544553
)
545554

546555
val goalDecorations = if (showGoalLinesSetting) {
@@ -789,13 +798,15 @@ private fun rememberChartModelProducer(
789798
* @param chartSeries The complete list of processed series data to be plotted.
790799
* @param showDataPointsSetting Whether to display dots on the data points of the main series.
791800
* @param targetMeasurementTypeId A flag to indicate if the chart is in a focused "statistics" mode.
801+
* @param goalValuesForScaling A list of goal values to be used for scaling the Y-axis.
792802
* @return A list of [LineCartesianLayer]s to be rendered by the chart.
793803
*/
794804
@Composable
795805
private fun rememberChartLayers(
796806
chartSeries: List<ChartSeries>,
797807
showDataPointsSetting: Boolean,
798808
targetMeasurementTypeId: Int?,
809+
goalValuesForScaling: List<Float> = emptyList()
799810
): List<LineCartesianLayer> {
800811
// 1. Separate series and their colors into four distinct groups.
801812
val mainSeriesStart = remember(chartSeries) { chartSeries.filter { !it.isProjected && !it.type.isOnRightYAxis } }
@@ -809,16 +820,22 @@ private fun rememberChartLayers(
809820
val projectedColorsEnd = remember(projectedSeriesEnd) { projectedSeriesEnd.map { Color(it.type.color) } }
810821

811822
// 2. Create a shared range provider.
812-
val rangeProvider = remember {
823+
val rangeProvider = remember(goalValuesForScaling) {
813824
object : CartesianLayerRangeProvider {
814825
override fun getMinY(minY: Double, maxY: Double, extraStore: ExtraStore): Double {
815-
val r = maxY - minY
816-
return if (r == 0.0) minY - 1.0 else floor(minY - 0.1 * r)
826+
val allMinima = goalValuesForScaling.map { it.toDouble() } + minY
827+
val effectiveMin = allMinima.minOrNull() ?: minY
828+
829+
val delta = maxY - minY
830+
return if (delta == 0.0) effectiveMin - 1.0 else floor(effectiveMin - 0.1 * delta)
817831
}
818832

819833
override fun getMaxY(minY: Double, maxY: Double, extraStore: ExtraStore): Double {
820-
val r = maxY - minY
821-
return if (r == 0.0) maxY + 1.0 else ceil(maxY + 0.1 * r)
834+
val allMaxima = goalValuesForScaling.map { it.toDouble() } + maxY
835+
val effectiveMax = allMaxima.maxOrNull() ?: maxY
836+
837+
val delta = maxY - minY
838+
return if (delta == 0.0) effectiveMax + 1.0 else ceil(effectiveMax + 0.1 * delta)
822839
}
823840
}
824841
}

0 commit comments

Comments
 (0)