Terepbejárás geometriák szerkesztése: kontrollpontok és tulajdonságok.
This commit is contained in:
@@ -23,8 +23,10 @@ import 'package:terepi_seged/controls/geoid_grid.dart';
|
||||
import 'package:terepi_seged/controls/wgs84_coordinate_formatter.dart';
|
||||
import 'package:terepi_seged/enums/map_edit_tool.dart';
|
||||
import 'package:terepi_seged/enums/map_survey_mode.dart';
|
||||
import 'package:terepi_seged/enums/note_type.dart';
|
||||
import 'package:terepi_seged/eov/convert_coordinate.dart';
|
||||
import 'package:terepi_seged/eov/eov.dart';
|
||||
import 'package:terepi_seged/models/note_item.dart';
|
||||
import 'package:terepi_seged/models/point_to_measure.dart';
|
||||
import 'package:terepi_seged/models/point_with_description_model.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@@ -32,11 +34,13 @@ import 'package:terepi_seged/pages/map_survey/presentations/views/measured_point
|
||||
import 'package:terepi_seged/pages/ntrip_settings/presentation/controllers/ntrip_settings_controller.dart';
|
||||
import 'package:terepi_seged/pages/ntrip_settings/presentation/views/ntrip_settings_sheet.dart';
|
||||
import 'package:terepi_seged/pages/tracking/presentation/controllers/tracking_controller.dart';
|
||||
import 'package:terepi_seged/services/app_database.dart';
|
||||
import 'package:terepi_seged/services/coord_converter_service.dart';
|
||||
import 'package:terepi_seged/services/gnss/gnss_connection.dart';
|
||||
import 'package:terepi_seged/services/gnss/gnss_device_service.dart';
|
||||
import 'package:terepi_seged/services/gnss/gnss_service.dart';
|
||||
import 'package:terepi_seged/services/ntrip_service.dart';
|
||||
import 'package:terepi_seged/services/project_service.dart';
|
||||
import 'package:terepi_seged/widgets/map_edit_tools/map_feature_save_sheet.dart';
|
||||
|
||||
class MapSurveyController extends GetxController {
|
||||
@@ -120,6 +124,9 @@ class MapSurveyController extends GetxController {
|
||||
|
||||
final MapController mapController = MapController();
|
||||
|
||||
final polylineHitNotifier = ValueNotifier<LayerHitResult<int>?>(null);
|
||||
final polygonHitNotifier = ValueNotifier<LayerHitResult<int>?>(null);
|
||||
|
||||
final currentLocationMarker = <Marker>[].obs;
|
||||
final pointNotesMarker = <Marker>[].obs;
|
||||
final pointsToMeasureMarker = <Marker>[].obs;
|
||||
@@ -166,8 +173,8 @@ class MapSurveyController extends GetxController {
|
||||
final activeEditTool = MapEditTool.none.obs;
|
||||
final editorPointCount = 0.obs;
|
||||
final pointNotes = <Marker>[].obs;
|
||||
final polylineNotes = <Polyline<Object>>[].obs;
|
||||
final polygonNotes = <Polygon<Object>>[].obs;
|
||||
final polylineNotes = <Polyline<int>>[].obs;
|
||||
final polygonNotes = <Polygon<int>>[].obs;
|
||||
|
||||
late final PolygonEditorController polygonEditorController;
|
||||
|
||||
@@ -181,6 +188,13 @@ class MapSurveyController extends GetxController {
|
||||
const PolygonLabelPlacementCalculator.centroid();
|
||||
|
||||
bool get isMapEditing => activeEditTool.value != MapEditTool.none;
|
||||
final selectedNoteItemId = Rx<int?>(null);
|
||||
final selectedNoteItemType = NoteType.line.obs;
|
||||
int? _editingNoteItemId;
|
||||
bool get isGeometryEditing => _editingNoteItemId != null;
|
||||
|
||||
// NoteItem? get selectedPoint =>
|
||||
// pointNotes.firstWhereOrNull((n) => n.id == selectedNoteItemId.value);
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────
|
||||
// Lifecycle
|
||||
@@ -229,6 +243,10 @@ class MapSurveyController extends GetxController {
|
||||
await _initStorage();
|
||||
|
||||
gpsHeightController.text = '1.8';
|
||||
|
||||
ever(ProjectService.to.activeProject, (_) => _loadNoteItems());
|
||||
|
||||
await _loadNoteItems();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -962,6 +980,9 @@ class MapSurveyController extends GetxController {
|
||||
void cancelEditing() {
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
_editingNoteItemId = null;
|
||||
selectedNoteItemId.value = null;
|
||||
editorPointCount.value = 0;
|
||||
}
|
||||
|
||||
void openFeatureList() {
|
||||
@@ -1005,73 +1026,437 @@ class MapSurveyController extends GetxController {
|
||||
//draftPoints.clear();
|
||||
}
|
||||
|
||||
Future<void> finishDraft() async {
|
||||
if (polygonEditorController.mode == PolygonEditorMode.line) {
|
||||
print("Points number in line: ${polygonEditorController.points.length}");
|
||||
print(
|
||||
"1. point coords: ${polygonEditorController.points[0].latitude} - ${polygonEditorController.points[0].longitude}");
|
||||
if (polygonEditorController.points.length < 2) return;
|
||||
Marker _markerFromNoteItem(NoteItem item) {
|
||||
return Marker(
|
||||
key: ValueKey('note_point_${item.id}'),
|
||||
point: item.points.first,
|
||||
width: 32.0,
|
||||
height: 32.0,
|
||||
child: GestureDetector(
|
||||
onTap: () => selectedNoteItem(item.id!),
|
||||
child: Obx(() {
|
||||
final isSelected = selectedNoteItemId.value == item.id;
|
||||
return Center(
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
width: isSelected ? 26.0 : 20.0,
|
||||
height: isSelected ? 26.0 : 20.0,
|
||||
decoration: BoxDecoration(
|
||||
color: item.color,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
width: isSelected ? 3.0 : 1.5,
|
||||
color: isSelected ? Colors.white : item.strokeColor),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.3),
|
||||
blurRadius: isSelected ? 8 : 3)
|
||||
]),
|
||||
));
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
// ── SQLite mentés ─────────────────────────────────────────────────
|
||||
|
||||
Polyline polyline = Polyline(
|
||||
points: List.from(polygonEditorController.points),
|
||||
color: activeEditColor.value,
|
||||
strokeWidth: activeEditStrokeWidth.value,
|
||||
// hitValue: (
|
||||
// title: 'Purple Line',
|
||||
// subtitle: 'Nothing really special here...',
|
||||
// ),
|
||||
Future<NoteItem?> _saveItem({
|
||||
required NoteType type,
|
||||
required List<LatLng> points,
|
||||
}) async {
|
||||
final projectId = ProjectService.to.activeProject.value?.id;
|
||||
|
||||
final item = NoteItem(
|
||||
projectId: projectId, // projekt nélkül is mentődik
|
||||
type: type,
|
||||
points: points,
|
||||
color: activeEditColor.value,
|
||||
opacity: activeEditOpacity.value,
|
||||
strokeWidth: activeEditStrokeWidth.value,
|
||||
strokeColor: activeEditStrokeColor.value,
|
||||
label: activeEditLabel.value,
|
||||
createdAt: DateTime.now(),
|
||||
);
|
||||
|
||||
try {
|
||||
final id = await AppDatabase.instance.insertNoteItem(item);
|
||||
// id-vel visszaadott NoteItem — a hitValue ehhez az id-hez kötődik
|
||||
return NoteItem(
|
||||
id: id,
|
||||
projectId: item.projectId,
|
||||
type: item.type,
|
||||
points: item.points,
|
||||
color: item.color,
|
||||
opacity: item.opacity,
|
||||
strokeWidth: item.strokeWidth,
|
||||
strokeColor: item.strokeColor,
|
||||
label: item.label,
|
||||
createdAt: item.createdAt,
|
||||
);
|
||||
polylineNotes.add(polyline);
|
||||
// polylineNotes.refresh();
|
||||
|
||||
print("Points number in polylineNotes: ${polylineNotes.length}");
|
||||
print(
|
||||
"1. point coords of polyline: ${polyline.points[0].latitude} - ${polyline.points[0].longitude}");
|
||||
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
if (polygonEditorController.mode == PolygonEditorMode.polygon) {
|
||||
print(
|
||||
"Points number in polygon: ${polygonEditorController.points.length}");
|
||||
|
||||
Polygon polygon = Polygon(
|
||||
points: List.from(polygonEditorController.points),
|
||||
color: activeEditColor.value.withValues(alpha: activeEditOpacity.value),
|
||||
borderColor: activeEditStrokeColor.value,
|
||||
borderStrokeWidth: activeEditStrokeWidth.value,
|
||||
label: activeEditLabel.value,
|
||||
labelPlacementCalculator: _labelPlacementCalculator,
|
||||
// hitValue: (
|
||||
// title: 'Basic Filled Polygon',
|
||||
// subtitle: 'Nothing really special here...',
|
||||
);
|
||||
|
||||
polygonNotes.add(polygon);
|
||||
//polygonNotes.refresh();
|
||||
//update();
|
||||
|
||||
print("Points number in polygonNotes: ${polygonNotes.length}");
|
||||
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
} catch (e) {
|
||||
print('_saveItem hiba: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void saveEditedPoint({required LatLng point}) {
|
||||
Marker marker = Marker(
|
||||
point: point,
|
||||
width: 15.0,
|
||||
height: 15.0,
|
||||
child: Container(
|
||||
width: 15.0,
|
||||
height: 15.0,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.amber[700],
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(width: 1.0, color: Colors.black)),
|
||||
));
|
||||
pointNotes.add(marker);
|
||||
// ── SQLite betöltés (onReady-ben hívandó) ─────────────────────────
|
||||
|
||||
Future<void> _loadNoteItems() async {
|
||||
final projectId = ProjectService.to.activeProject.value?.id;
|
||||
final items = await AppDatabase.instance.listNoteItems(projectId);
|
||||
|
||||
// Listák resetelése
|
||||
pointNotes.clear();
|
||||
polylineNotes.clear();
|
||||
polygonNotes.clear();
|
||||
|
||||
for (final item in items) {
|
||||
switch (item.type) {
|
||||
case NoteType.point:
|
||||
pointNotes.add(_markerFromNoteItem(item));
|
||||
case NoteType.line:
|
||||
polylineNotes.add(item.toPolyline());
|
||||
case NoteType.polygon:
|
||||
polygonNotes.add(item.toPolygon());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> finishDraft() async {
|
||||
if (_editingNoteItemId != null) {
|
||||
if (polygonEditorController.points.isEmpty) {
|
||||
await _finishStyleUpdate();
|
||||
} else {
|
||||
// ── FRISSÍTÉSI MÓD ──────────────────────────────────────────
|
||||
await _finishGeometryUpdate();
|
||||
}
|
||||
} else {
|
||||
// ── LÉTREHOZÁSI MÓD (eredeti logika) ────────────────────────
|
||||
await _finishCreate();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _finishStyleUpdate() async {
|
||||
final id = _editingNoteItemId!;
|
||||
final existing = await AppDatabase.instance.getNoteItem(id);
|
||||
if (existing == null) return;
|
||||
|
||||
final updated = existing.copyWith(
|
||||
color: activeEditColor.value,
|
||||
opacity: activeEditOpacity.value,
|
||||
strokeWidth: activeEditStrokeWidth.value,
|
||||
strokeColor: activeEditStrokeColor.value,
|
||||
label: activeEditLabel.value,
|
||||
);
|
||||
|
||||
await updateNoteItem(updated);
|
||||
_editingNoteItemId = null;
|
||||
}
|
||||
|
||||
Future<void> deleteEditingItem() async {
|
||||
final id = _editingNoteItemId;
|
||||
if (id == null) return;
|
||||
final item = await AppDatabase.instance.getNoteItem(id);
|
||||
if (item != null) await deleteNoteItem(item);
|
||||
_editingNoteItemId = null;
|
||||
selectedNoteItemId.value = null;
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
|
||||
// Future<void> finishDraft() async {
|
||||
// if (polygonEditorController.mode == PolygonEditorMode.line) {
|
||||
// print("Points number in line: ${polygonEditorController.points.length}");
|
||||
// print(
|
||||
// "1. point coords: ${polygonEditorController.points[0].latitude} - ${polygonEditorController.points[0].longitude}");
|
||||
// if (polygonEditorController.points.length < 2) return;
|
||||
|
||||
// final saved = await _saveItem(
|
||||
// type: NoteType.line,
|
||||
// points: List.from(polygonEditorController.points));
|
||||
|
||||
// if (saved != null) {
|
||||
// polylineNotes.add(saved.toPolyline());
|
||||
// }
|
||||
|
||||
// polygonEditorController.clear();
|
||||
// activeEditTool.value = MapEditTool.none;
|
||||
// }
|
||||
// if (polygonEditorController.mode == PolygonEditorMode.polygon) {
|
||||
// if (polygonEditorController.points.length < 3) return;
|
||||
|
||||
// final saved = await _saveItem(
|
||||
// type: NoteType.polygon,
|
||||
// points: List.from(polygonEditorController.points));
|
||||
|
||||
// if (saved != null) {
|
||||
// polygonNotes.add(saved.toPolygon());
|
||||
// }
|
||||
|
||||
// polygonEditorController.clear();
|
||||
// activeEditTool.value = MapEditTool.none;
|
||||
// }
|
||||
// }
|
||||
|
||||
void saveEditedPoint({required LatLng point}) {
|
||||
if (_editingNoteItemId != null) {
|
||||
// ── PONT FRISSÍTÉSI MÓD ──────────────────────────────────────
|
||||
final id = _editingNoteItemId!;
|
||||
_editingNoteItemId = null;
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
|
||||
AppDatabase.instance.getNoteItem(id).then((existing) async {
|
||||
if (existing == null) return;
|
||||
final updated = existing.copyWith(points: [point]);
|
||||
await updateNoteItem(updated);
|
||||
});
|
||||
} else {
|
||||
// ── ÚJ PONT LÉTREHOZÁS (eredeti logika) ─────────────────────
|
||||
_saveItem(
|
||||
type: NoteType.point,
|
||||
points: [point],
|
||||
).then((saved) {
|
||||
if (saved == null) return;
|
||||
pointNotes.add(_markerFromNoteItem(saved));
|
||||
});
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
}
|
||||
|
||||
// void saveEditedPoint({required LatLng point}) {
|
||||
// _saveItem(type: NoteType.point, points: [point]).then((saved) {
|
||||
// if (saved == null) return;
|
||||
// pointNotes.add(_markerFromNoteItem(saved));
|
||||
// });
|
||||
|
||||
// // Marker marker = Marker(
|
||||
// // point: point,
|
||||
// // width: 15.0,
|
||||
// // height: 15.0,
|
||||
// // child: Container(
|
||||
// // width: 15.0,
|
||||
// // height: 15.0,
|
||||
// // decoration: BoxDecoration(
|
||||
// // color: Colors.amber[700],
|
||||
// // shape: BoxShape.circle,
|
||||
// // border: Border.all(width: 1.0, color: Colors.black)),
|
||||
// // ));
|
||||
// //pointNotes.add(marker);
|
||||
// activeEditTool.value = MapEditTool.none;
|
||||
// }
|
||||
|
||||
Future<void> selectedNoteItem(int id) async {
|
||||
selectedNoteItemId.value = id;
|
||||
|
||||
final item = await AppDatabase.instance.getNoteItem(id);
|
||||
if (item == null) return;
|
||||
|
||||
_editingNoteItemId = item.id;
|
||||
activeEditColor.value = item.color;
|
||||
activeEditOpacity.value = item.opacity;
|
||||
activeEditStrokeWidth.value = item.strokeWidth;
|
||||
activeEditStrokeColor.value = item.strokeColor;
|
||||
activeEditLabel.value = item.label;
|
||||
activeEditTool.value = switch (item.type) {
|
||||
NoteType.point => MapEditTool.point,
|
||||
NoteType.line => MapEditTool.line,
|
||||
NoteType.polygon => MapEditTool.polygon
|
||||
};
|
||||
|
||||
Get.bottomSheet(
|
||||
DraggableScrollableSheet(
|
||||
initialChildSize: 0.52,
|
||||
minChildSize: 0.35,
|
||||
maxChildSize: 0.85,
|
||||
snap: true,
|
||||
snapSizes: const [0.35, 0.52, 0.85],
|
||||
expand: false,
|
||||
builder: (_, scrollCtrl) =>
|
||||
MapFeatureSaveSheet(ctrl: this, scrollCtrl: scrollCtrl)),
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
ignoreSafeArea: false)
|
||||
.whenComplete(() {
|
||||
selectedNoteItemId.value = null;
|
||||
//_editingNoteItemId = null;
|
||||
if (!isGeometryEditing) {
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void clearNoteItemSelection() {
|
||||
selectedNoteItemId.value = null;
|
||||
}
|
||||
|
||||
Future<void> updateNoteItem(NoteItem updated) async {
|
||||
await AppDatabase.instance.updateNoteItem(updated);
|
||||
|
||||
switch (updated.type) {
|
||||
case NoteType.line:
|
||||
final idx = polylineNotes.indexWhere((p) => p.hitValue == updated.id);
|
||||
if (idx >= 0) {
|
||||
polylineNotes[idx] = updated.toPolyline();
|
||||
polylineNotes.refresh();
|
||||
}
|
||||
case NoteType.polygon:
|
||||
final idx = polygonNotes.indexWhere((p) => p.hitValue == updated.id);
|
||||
if (idx >= 0) {
|
||||
polygonNotes[idx] = updated.toPolygon();
|
||||
polygonNotes.refresh();
|
||||
}
|
||||
case NoteType.point:
|
||||
final idx = _findPointMarkerIndex(updated.id!);
|
||||
if (idx >= 0) {
|
||||
pointNotes[idx] = _markerFromNoteItem(updated);
|
||||
pointNotes.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteNoteItem(NoteItem item) async {
|
||||
await AppDatabase.instance.deleteNoteItem(item.id!);
|
||||
|
||||
switch (item.type) {
|
||||
case NoteType.line:
|
||||
polylineNotes.removeWhere((p) => p.hitValue == item.id);
|
||||
case NoteType.polygon:
|
||||
polygonNotes.removeWhere((p) => p.hitValue == item.id);
|
||||
case NoteType.point:
|
||||
// Pontot tag-elt Key alapján keresünk
|
||||
final idx = _findPointMarkerIndex(item.id!);
|
||||
if (idx >= 0) pointNotes.removeAt(idx);
|
||||
}
|
||||
selectedNoteItemId.value = null;
|
||||
}
|
||||
|
||||
/// Pont marker indexének megkeresése.
|
||||
/// A marker Key-je hordozza a NoteItem id-t.
|
||||
int _findPointMarkerIndex(int noteId) {
|
||||
return pointNotes.indexWhere(
|
||||
(m) => m.key == ValueKey('note_point_$noteId'),
|
||||
);
|
||||
}
|
||||
// ── Geometria szerkesztés indítása ────────────────────────────────────
|
||||
|
||||
Future<void> startGeometryEdit() async {
|
||||
final id = _editingNoteItemId;
|
||||
if (id == null) return;
|
||||
|
||||
final item = await AppDatabase.instance.getNoteItem(id);
|
||||
if (item == null) return;
|
||||
|
||||
if (item.type == NoteType.point) {
|
||||
// Pontnál: régi törlése, új elhelyezés vár
|
||||
activeEditTool.value = MapEditTool.point;
|
||||
return;
|
||||
}
|
||||
|
||||
// Editor mód beállítása a típus szerint
|
||||
final editorMode = item.type == NoteType.line
|
||||
? PolygonEditorMode.line
|
||||
: PolygonEditorMode.polygon;
|
||||
|
||||
// PolygonEditorController újraindítása a meglévő pontokkal
|
||||
// Dispose → újra létrehozás szükséges ha a controller már él
|
||||
polygonEditorController.clear();
|
||||
polygonEditorController.setMode(editorMode);
|
||||
|
||||
// Meglévő pontok betöltése az editorba
|
||||
for (final point in item.points) {
|
||||
polygonEditorController.addPoint(point);
|
||||
}
|
||||
|
||||
editorPointCount.value = item.points.length;
|
||||
|
||||
// Szerkesztési mód aktiválása
|
||||
activeEditTool.value =
|
||||
item.type == NoteType.line ? MapEditTool.line : MapEditTool.polygon;
|
||||
}
|
||||
|
||||
// ── Geometria szerkesztés megszakítása ────────────────────────────────
|
||||
|
||||
void cancelGeometryEdit() {
|
||||
_editingNoteItemId = null;
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
editorPointCount.value = 0;
|
||||
}
|
||||
|
||||
Future<void> _finishGeometryUpdate() async {
|
||||
final id = _editingNoteItemId!;
|
||||
|
||||
if (polygonEditorController.points.length < _minPoints) {
|
||||
Get.snackbar(
|
||||
'Figyelem',
|
||||
'Nincs elég pont a geometriához.',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Meglévő elem lekérése az adatbázisból
|
||||
final existing = await AppDatabase.instance.getNoteItem(id);
|
||||
if (existing == null) return;
|
||||
|
||||
// Frissítés: csak a pontok változnak, a stílus marad
|
||||
final updated = existing.copyWith(
|
||||
points: List<LatLng>.from(polygonEditorController.points),
|
||||
// Ha a stílus is változott a szerkesztés közben:
|
||||
color: activeEditColor.value,
|
||||
opacity: activeEditOpacity.value,
|
||||
strokeWidth: activeEditStrokeWidth.value,
|
||||
strokeColor: activeEditStrokeColor.value,
|
||||
label: activeEditLabel.value,
|
||||
);
|
||||
|
||||
// SQLite + display lista frissítése
|
||||
await updateNoteItem(updated);
|
||||
|
||||
// Reset
|
||||
_editingNoteItemId = null;
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
editorPointCount.value = 0;
|
||||
|
||||
Get.snackbar(
|
||||
'Geometria frissítve',
|
||||
updated.label.isNotEmpty ? updated.label : '',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
duration: const Duration(seconds: 2),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _finishCreate() async {
|
||||
if (polygonEditorController.mode == PolygonEditorMode.line) {
|
||||
if (polygonEditorController.points.length < 2) return;
|
||||
|
||||
final saved = await _saveItem(
|
||||
type: NoteType.line,
|
||||
points: List.from(polygonEditorController.points),
|
||||
);
|
||||
if (saved != null) {
|
||||
polylineNotes.add(saved.toPolyline());
|
||||
}
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
|
||||
if (polygonEditorController.mode == PolygonEditorMode.polygon) {
|
||||
if (polygonEditorController.points.length < 3) return;
|
||||
|
||||
final saved = await _saveItem(
|
||||
type: NoteType.polygon,
|
||||
points: List.from(polygonEditorController.points),
|
||||
);
|
||||
if (saved != null) {
|
||||
polygonNotes.add(saved.toPolygon());
|
||||
}
|
||||
polygonEditorController.clear();
|
||||
activeEditTool.value = MapEditTool.none;
|
||||
}
|
||||
}
|
||||
|
||||
int get _minPoints {
|
||||
if (polygonEditorController.mode == PolygonEditorMode.line) return 2;
|
||||
return 3; // polygon
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,23 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
||||
controller.polygonEditorController.addPoint(point);
|
||||
}
|
||||
},
|
||||
onTap: (tapPosition, point) {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) return;
|
||||
if (controller.isMapEditing) return;
|
||||
final polygonHit = controller.polygonHitNotifier.value;
|
||||
if (polygonHit != null && polygonHit.hitValues.isNotEmpty) {
|
||||
final id = polygonHit.hitValues.first;
|
||||
controller.selectedNoteItem(id);
|
||||
return;
|
||||
}
|
||||
final polylineHit = controller.polylineHitNotifier.value;
|
||||
if (polylineHit != null && polylineHit.hitValues.isNotEmpty) {
|
||||
final id = polylineHit.hitValues.first;
|
||||
controller.selectedNoteItem(id);
|
||||
return;
|
||||
}
|
||||
controller.clearNoteItemSelection();
|
||||
},
|
||||
layers: [
|
||||
Obx(() =>
|
||||
MarkerLayer(markers: controller.currentLocationMarker.toList())),
|
||||
@@ -55,14 +72,6 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
||||
return _buildTrackLayer();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return PolygonEditor(
|
||||
controller: controller.polygonEditorController,
|
||||
throttleDuration: Duration.zero);
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
@@ -75,7 +84,9 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
return PolylineLayer(polylines: [...controller.polylineNotes]);
|
||||
return PolylineLayer(
|
||||
hitNotifier: controller.polylineHitNotifier,
|
||||
polylines: [...controller.polylineNotes]);
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
@@ -83,8 +94,56 @@ class MapSurveyView extends GetView<MapSurveyController> {
|
||||
}
|
||||
|
||||
return PolygonLayer(
|
||||
polygons: [...controller.polygonNotes], useAltRendering: true);
|
||||
})
|
||||
hitNotifier: controller.polygonHitNotifier,
|
||||
polygons: [...controller.polygonNotes],
|
||||
useAltRendering: true);
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final selectedId = controller.selectedNoteItemId.value;
|
||||
if (selectedId == null) return const SizedBox.shrink();
|
||||
|
||||
// Polygon kiemelés
|
||||
final selectedPolygon = controller.polygonNotes
|
||||
.where((p) => p.hitValue == selectedId)
|
||||
.firstOrNull;
|
||||
if (selectedPolygon != null) {
|
||||
return PolygonLayer(polygons: [
|
||||
Polygon(
|
||||
points: selectedPolygon.points,
|
||||
color: Colors.transparent,
|
||||
borderColor: Colors.white,
|
||||
borderStrokeWidth: selectedPolygon.borderStrokeWidth + 3,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
// Polyline kiemelés
|
||||
final selectedPolyline = controller.polylineNotes
|
||||
.where((p) => p.hitValue == selectedId)
|
||||
.firstOrNull;
|
||||
if (selectedPolyline != null) {
|
||||
return PolylineLayer(polylines: [
|
||||
Polyline(
|
||||
points: selectedPolyline.points,
|
||||
color: Colors.white.withOpacity(0.6),
|
||||
strokeWidth: selectedPolyline.strokeWidth + 4,
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
return const SizedBox.shrink();
|
||||
}),
|
||||
Obx(() {
|
||||
if (controller.mode.value != MapSurveyMode.fieldWalk) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return PolygonEditor(
|
||||
controller: controller.polygonEditorController,
|
||||
throttleDuration: Duration.zero);
|
||||
}),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
|
||||
Reference in New Issue
Block a user