Full reticle interaction state machine (idle/snapped/editing), matching the HTML prototype's mode variable: - idle: reticle shows "+", tap drops a new waypoint at the map center. - snapped: after any pan ends, if the map center lands within the reticle's on-screen radius (converted to meters at the current zoom/latitude) of an existing waypoint, the view auto-recenters onto it and the reticle switches to a pencil icon. Tap to enter editing. - editing: reticle shows a checkmark; panning the map now live-updates the target waypoint's position (drag-to-reposition) instead of moving the camera "away" from it, and the HaloMenu radial menu appears. HaloMenu: three ring-wedge hit regions (custom ClipPath/CustomClipper, angles/radii taken from the prototype's buildRingWedgePath) for Loiter/Landing/Remove, with Material icons standing in for the demonstrator's hand-drawn SVGs. Loiter/Landing toggle the waypoint's action and drop back to snapped; Remove deletes it and returns to idle. MissionMap now draws a straight white polyline connecting all waypoints in order (the physically-grounded straight-line + fillet-arc geometry from doc 3.7/4.6 is still open - this is a straight-line placeholder) plus a dashed rubber-band preview from the last waypoint to the live map center while idle. Note on porting from Leaflet: flutter_map's MapController.move() emits MapEventMove, not MapEventMoveEnd, so (unlike the prototype's panTo()) the auto-recenter-on-snap doesn't re-trigger snap detection - no "autoPanning" guard flag was needed. Verified with flutter analyze, flutter test (three new tests: halo menu open/close, remove, loiter toggle - the wedge tap tests had to target the icon's exact center via tapAt(), since a wedge's bounding-box center falls outside its actual donut-segment hit area), and a full manual pass on the Pixel_10a emulator: idle -> add -> snap (auto-recenter confirmed) -> edit -> drag-reposition (confirmed via re-snap after further panning showing the moved position, not the original one) -> halo remove -> back to idle, plus the connecting line rendering correctly between two waypoints set far apart. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
31 lines
981 B
Dart
31 lines
981 B
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Zentrales Steuerelement zum Setzen/Editieren von Wegpunkten
|
|
/// (HTML-Demonstrator: #centerCluster/#reticleBtn), fixiert in der
|
|
/// Bildschirmmitte. Die Karte wird darunter verschoben. Icon wechselt je
|
|
/// nach Modus: "+" (idle, neuer Wegpunkt), Stift (snapped, zum Bearbeiten
|
|
/// antippen), Haken (editing, bestaetigen).
|
|
class ReticleButton extends StatelessWidget {
|
|
const ReticleButton({super.key, required this.icon, required this.onTap});
|
|
|
|
final IconData icon;
|
|
final VoidCallback onTap;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GestureDetector(
|
|
onTap: onTap,
|
|
child: Container(
|
|
width: 55,
|
|
height: 55,
|
|
decoration: BoxDecoration(
|
|
shape: BoxShape.circle,
|
|
color: Colors.black.withValues(alpha: 0.68),
|
|
border: Border.all(color: Colors.white, width: 2),
|
|
),
|
|
child: Icon(icon, color: Colors.white, size: 26),
|
|
),
|
|
);
|
|
}
|
|
}
|