feat(tahuantinsuyu): coord labels con minutos + control en panel

- Precisión a minutos: `format_coord_compact` ahora emite
  "DD°MM'{signo}" (ej. "14°56'"). Trabaja en minutos enteros para
  evitar drift de floats acumulado, hace rollover correcto a través
  de bordes de signo (29°60' → 0° del siguiente) y wrap-around de
  ángulos negativos. 5 tests verdes:
  * 0° → "0°00'"
  * 14.9333° → "14°56'"
  * 29.9995° → "0°00'" (carry-over)
  * 270° → "0°00'"
  * -10° → "20°00'" (wrap)

- Toggle en panel: nuevo `Control::Toggle` "Coordenadas (grado°min')"
  en NatalModule, default ON, hotkey C. Sincronización bidireccional:
  panel → canvas via `set_show_coords` (idempotente, no emite),
  canvas → panel via nuevo evento `CanvasEvent::ShowCoordsChanged`
  que el shell traduce a `panel.set_toggle("natal","show_coords",…)`.
  Sin loop porque el setter no emite.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-18 16:49:34 +00:00
parent 8ede06f8c4
commit 86c5fd8653
3 changed files with 86 additions and 9 deletions
+14
View File
@@ -847,6 +847,14 @@ impl Shell {
self.panel
.update(cx, |p, cx| p.set_toggle("natal", key, *visible, cx));
}
CanvasEvent::ShowCoordsChanged(visible) => {
// Sync el toggle del panel para que coincida con la
// hotkey C. No persist — los coord labels son una
// preferencia visual, no parte del module_state.
self.panel.update(cx, |p, cx| {
p.set_toggle("natal", "show_coords", *visible, cx)
});
}
CanvasEvent::ChartRequested(_) => {
// Fase 7: doble click sobre un thumbnail abre la carta.
}
@@ -920,6 +928,12 @@ impl Shell {
if let Some(k) = kind {
self.canvas
.update(cx, |c, cx| c.set_layer_visible(k, bool_val, cx));
} else if key == "show_coords" {
// Coord labels viven en el canvas (no son una
// capa pintada como otros show_*). Sync sin
// recompose ni persist en module_state.
self.canvas
.update(cx, |c, cx| c.set_show_coords(bool_val, cx));
} else {
// Filtros: actualizar module_configs + recompose.
let entry = self