From 08d046536e242ed3b341f93ebbc4f0e7b9f897dd Mon Sep 17 00:00:00 2001 From: Dominik Roth Date: Sun, 9 Aug 2026 19:32:39 +0200 Subject: [PATCH] Fix cursor readout showing AZ/dist for points that are actually off the map _on_cursor_move() only checked map bounds for the coord label itself ('off map' vs a real grid ref), the AZ/distance-from-nest numbers next to it were computed and shown regardless, bearing_deg_point()/ distance_km_point() are happy to run on any raw km point, negative or past the 20x10 grid included, so a cursor genuinely off the map could still show what looked like a real reading. Now the whole label is just 'off map', no numbers, whenever point_to_coord() says there's no real grid position there. --- src/fenigma/app.py | 13 ++++++++++--- src/fenigma/grid_widget.py | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/fenigma/app.py b/src/fenigma/app.py index d13db6c..cc2b97f 100644 --- a/src/fenigma/app.py +++ b/src/fenigma/app.py @@ -692,14 +692,21 @@ class MainWindow(Adw.ApplicationWindow): self.cursor_label.set_label("") return coord = solver.point_to_coord(point_km) - coord_text = coord.label() if coord is not None else "off map" + if coord is None: + # Off the map entirely, AZ/dist are still mathematically + # defined for any raw km point (nothing stops that math from + # running on a negative or >20/>10 coordinate), showing them + # anyway would read as a real reading for a position that + # isn't actually on the map. + self.cursor_label.set_label("off map") + return nest = self.board.nest if nest.coord is not None: az = ballistics.bearing_deg_point(nest.coord.as_fraction(), point_km) dist = ballistics.distance_km_point(nest.coord.as_fraction(), point_km) - self.cursor_label.set_label(f"AZ {az:05.1f}° {dist:5.2f}km {coord_text}") + self.cursor_label.set_label(f"AZ {az:05.1f}° {dist:5.2f}km {coord.label()}") else: - self.cursor_label.set_label(coord_text) + self.cursor_label.set_label(coord.label()) # -- Nest ----------------------------------------------------------------- def _build_nest_popover(self, rebuild) -> Gtk.Widget: diff --git a/src/fenigma/grid_widget.py b/src/fenigma/grid_widget.py index e6493c0..b2d2a3a 100644 --- a/src/fenigma/grid_widget.py +++ b/src/fenigma/grid_widget.py @@ -7,6 +7,7 @@ stay in sync with the map (see app.py).""" from __future__ import annotations import math +from collections import namedtuple import gi @@ -29,6 +30,22 @@ LABEL_PAD = 8 # gap between a marker and its name label HOVER_RADIUS_PX = 12 OVERLAY_RAY_LENGTH_KM = 30.0 # long enough to cross the 20x10 map from any origin +MIN_ZOOM = 1.0 # the whole 20x10 map fits, the default +MAX_ZOOM = 10.0 +ZOOM_STEP = 1.15 # per scroll-wheel notch + +# Everything needed to convert between km-space (the 20x10 grid) and +# widget pixels for one frame, bundled so every draw/hit-test method +# takes one argument instead of threading cell_w/cell_h/grid_h/pan +# separately through a dozen call sites. cell_w/cell_h differ only when +# square_cells is off (the default): the map then stretches to fill the +# widget exactly, cell_w == cell_h only when the widget's own aspect +# ratio happens to match the grid's. pad_x/pad_y are the letterboxing +# margin added on whichever axis has leftover space when square_cells +# is on. ox/oy are the visible viewport's origin in km-space (0,0 +# unless zoomed in and panned). +_View = namedtuple("_View", "cell_w cell_h grid_w grid_h pad_x pad_y ox oy") + CATEGORY_COLOR = { "nest": (0.35, 0.60, 0.95), "spotter": (0.35, 0.78, 0.40),