fuzzyworld

haunt / commit

Fix distance labels not updating: notify all rows on readings change

56247a852e0aab062ca990c4b7254dcd308cc8b6 · Pavel Safronov · 2026-05-13 13:08:36 -0700 · parents cffb2c436e7a

Fix distance labels not updating: notify all rows on readings change

Scale map viewport to named points only, not 'you'; adaptive grid step

Named points (routers, lights, pinned devices) define the viewport — 'you'
wandering far away no longer collapses everything into a tiny cluster at the
top. Grid labels use adaptive step (1/2/5/10 m) based on range so the y-axis
doesn't show 16 crowded labels when the span is large.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
 .../java/net/fuzzyworld/haunt/debug/MapView.kt     | 42 ++++++++++++++++------
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/app/src/main/java/net/fuzzyworld/haunt/debug/MapView.kt b/app/src/main/java/net/fuzzyworld/haunt/debug/MapView.kt
index 2559cf2..e623c83 100644
--- a/app/src/main/java/net/fuzzyworld/haunt/debug/MapView.kt
+++ b/app/src/main/java/net/fuzzyworld/haunt/debug/MapView.kt
@@ -194,10 +194,16 @@ class MapView @JvmOverloads constructor(
         }
 
         val padPx = 72f
-        val minX = (allCoords.minOf { it.first } - 1.0).coerceAtLeast(0.0)
-        val maxX = allCoords.maxOf { it.first } + 1.0
-        val minY = (allCoords.minOf { it.second } - 1.0).coerceAtLeast(0.0)
-        val maxY = allCoords.maxOf { it.second } + 1.0
+
+        // Scale is determined by named points + history only — "you" does not expand the viewport.
+        // This keeps saved points visible and spread out even when you wander far from them.
+        val anchorCoords = savedCoords.map { it.second } + lightCoords.map { it.second } + historyCoords
+        val scaleCoords = anchorCoords.ifEmpty { listOfNotNull(currentCoords) }
+
+        val minX = (scaleCoords.minOf { it.first } - 1.0).coerceAtLeast(0.0)
+        val maxX = scaleCoords.maxOf { it.first } + 1.0
+        val minY = (scaleCoords.minOf { it.second } - 1.0).coerceAtLeast(0.0)
+        val maxY = scaleCoords.maxOf { it.second } + 1.0
 
         val scaleX = (width - 2 * padPx) / (maxX - minX).toFloat()
         val scaleY = (height - 2 * padPx) / (maxY - minY).toFloat()
@@ -205,16 +211,32 @@ class MapView @JvmOverloads constructor(
         fun sx(x: Double) = padPx + ((x - minX) * scaleX).toFloat()
         fun sy(y: Double) = padPx + ((y - minY) * scaleY).toFloat()
 
+        // Adaptive grid step so labels don't crowd when range is large
+        fun gridStep(range: Double) = when {
+            range > 50 -> 10
+            range > 20 -> 5
+            range > 10 -> 2
+            else -> 1
+        }
+        val stepX = gridStep(maxX - minX)
+        val stepY = gridStep(maxY - minY)
+
         // Grid
-        for (gx in minX.roundToInt()..maxX.roundToInt()) {
-            canvas.drawLine(sx(gx.toDouble()), 0f, sx(gx.toDouble()), height.toFloat(), gridPaint)
+        val gxFirst = (minX / stepX).toInt()
+        val gxLast  = (maxX / stepX).toInt()
+        for (gi in gxFirst..gxLast) {
+            val wx = gi * stepX.toDouble()
+            canvas.drawLine(sx(wx), 0f, sx(wx), height.toFloat(), gridPaint)
             dimLabelPaint.textAlign = Paint.Align.CENTER
-            canvas.drawText("${gx}m", sx(gx.toDouble()), height - 6f, dimLabelPaint)
+            canvas.drawText("${wx.roundToInt()}m", sx(wx), height - 6f, dimLabelPaint)
         }
-        for (gy in minY.roundToInt()..maxY.roundToInt()) {
-            canvas.drawLine(0f, sy(gy.toDouble()), width.toFloat(), sy(gy.toDouble()), gridPaint)
+        val gyFirst = (minY / stepY).toInt()
+        val gyLast  = (maxY / stepY).toInt()
+        for (gi in gyFirst..gyLast) {
+            val wy = gi * stepY.toDouble()
+            canvas.drawLine(0f, sy(wy), width.toFloat(), sy(wy), gridPaint)
             dimLabelPaint.textAlign = Paint.Align.LEFT
-            canvas.drawText("${gy}m", 4f, sy(gy.toDouble()) - 6f, dimLabelPaint)
+            canvas.drawText("${wy.roundToInt()}m", 4f, sy(wy) - 6f, dimLabelPaint)
         }
 
         // History trail — drawn first so it appears behind everything else