diff --git a/lib/pages/field_trip/bindings/field_trip_bindings.dart b/lib/pages/field_trip/bindings/field_trip_bindings.dart index c8c96b6..0a4f6fc 100644 --- a/lib/pages/field_trip/bindings/field_trip_bindings.dart +++ b/lib/pages/field_trip/bindings/field_trip_bindings.dart @@ -1,7 +1,7 @@ import 'package:get/get.dart'; import 'package:terepi_seged/pages/field_trip/presentations/controllers/field_trip_controller.dart'; -class HomeBinding extends Bindings { +class FieldTripBinding extends Bindings { @override void dependencies() { Get.lazyPut(() => FieldTripController()); diff --git a/lib/pages/field_trip/presentations/controllers/field_trip_controller.dart b/lib/pages/field_trip/presentations/controllers/field_trip_controller.dart index 180d0a3..7890233 100644 --- a/lib/pages/field_trip/presentations/controllers/field_trip_controller.dart +++ b/lib/pages/field_trip/presentations/controllers/field_trip_controller.dart @@ -1,3 +1,162 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map_polygon_editor/polygon_editor/polygon_editor_controller.dart'; import 'package:get/get.dart'; +import 'package:latlong2/latlong.dart'; -class FieldTripController extends GetxController {} +class FieldTripController extends GetxController { + RxBool mapIsInitialized = false.obs; + RxBool mapInEditorMode = false.obs; + RxBool mapInPointEditorMode = false.obs; + + final pointNotes = [].obs; + final polylineNotes = >[].obs; + final polygonNotes = >[].obs; + + late final MapController mapController; + late final MapOptions mapOptions; + late final PolygonEditorController polygonEditorController; + + final PolygonLabelPlacementCalculator _labelPlacementCalculator = + const PolygonLabelPlacementCalculator.centroid(); + + @override + void onInit() async { + // TODO: implement onInit + super.onInit(); + + mapOptions = MapOptions( + onLongPress: (tapPosition, point) { + if (mapInEditorMode.value) { + polygonEditorController.addPoint(point); + } + if (mapInPointEditorMode.value) { + savePointNote(point: point); + } + }, + keepAlive: true, + ); + + polylineNotes.add( + Polyline( + points: [ + const LatLng(47.65, 19.00), + const LatLng(47.64, 19.02), + const LatLng(47.69, 19.22), + ], + strokeWidth: 8, + color: const Color.fromARGB(255, 227, 238, 71), + hitValue: ( + title: 'Purple Line', + subtitle: 'Nothing really special here...', + ), + ), + ); + + polygonEditorController = + PolygonEditorController(mode: PolygonEditorMode.polygon); + + mapController = MapController(); + + mapIsInitialized.value = true; + } + + @override + void dispose() { + // TODO: implement dispose + polygonEditorController.dispose(); + super.dispose(); + } + + void cancelEditorController() { + polygonEditorController.clear(); + mapInEditorMode.value = false; + } + + void startPolygonEdition() { + polygonEditorController.clear(); + polygonEditorController.setMode(PolygonEditorMode.polygon); + mapInEditorMode.value = true; + } + + void startPolylineEdition() { + polygonEditorController.clear(); + polygonEditorController.setMode(PolygonEditorMode.line); + mapInEditorMode.value = true; + } + + void startPointEdition() { + mapInPointEditorMode.value = true; + } + + void saveNote() { + 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}"); + + Polyline polyline = Polyline( + points: polygonEditorController.points, + color: Colors.red, + strokeWidth: 8, + // hitValue: ( + // title: 'Purple Line', + // subtitle: 'Nothing really special here...', + // ), + ); + 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(); + mapInEditorMode.value = false; + } + if (polygonEditorController.mode == PolygonEditorMode.polygon) { + print( + "Points number in polygon: ${polygonEditorController.points.length}"); + + Polygon polygon = Polygon( + points: polygonEditorController.points, + color: Colors.purple, + borderColor: Colors.yellow, + borderStrokeWidth: 4, + label: 'Label!', + 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(); + mapInEditorMode.value = false; + } + } + + void savePointNote({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); + pointNotes.refresh(); + update(); + mapInPointEditorMode.value = false; + } +} diff --git a/lib/pages/field_trip/presentations/views/fiels_trip_view.dart b/lib/pages/field_trip/presentations/views/fiels_trip_view.dart index ed8405a..d06177e 100644 --- a/lib/pages/field_trip/presentations/views/fiels_trip_view.dart +++ b/lib/pages/field_trip/presentations/views/fiels_trip_view.dart @@ -1,4 +1,8 @@ +import 'package:flutter_map/flutter_map.dart'; +import 'package:flutter_map_location_marker/flutter_map_location_marker.dart'; +import 'package:flutter_map_polygon_editor/polygon_editor.dart'; import 'package:get/get.dart'; +import 'package:latlong2/latlong.dart'; import 'package:terepi_seged/pages/field_trip/presentations/controllers/field_trip_controller.dart'; import 'package:flutter/material.dart'; @@ -7,6 +11,103 @@ class FieldTripView extends GetView { @override Widget build(BuildContext context) { - return Container(); + return Scaffold( + resizeToAvoidBottomInset: false, + extendBody: true, + appBar: AppBar( + title: const Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Terepbejárás'), + ], + )), + body: Column( + children: [ + Expanded( + child: Stack(children: [ + Obx(() => controller.mapIsInitialized.value + ? FlutterMap( + mapController: controller.mapController, + options: controller.mapOptions, + children: [ + TileLayer( + urlTemplate: + 'http://{s}.google.com/vt/lyrs=s,h&x={x}&y={y}&z={z}', + subdomains: const ['mt0', 'mt1', 'mt2', 'mt3'], + maxNativeZoom: 18, + ), + CurrentLocationLayer( + alignPositionOnUpdate: AlignOnUpdate.once, + ), + MarkerLayer(markers: controller.pointNotes), + PolylineLayer( + polylines: controller.polylineNotes, + ), + PolygonLayer( + polygons: controller.polygonNotes, + useAltRendering: true, + ), + // PolylineLayer(polylines: [ + // Polyline( + // points: [ + // const LatLng(47.65, 19.00), + // const LatLng(47.64, 19.02), + // const LatLng(47.69, 19.22), + // ], + // strokeWidth: 8, + // color: const Color(0xFF60399E), + // hitValue: ( + // title: 'Purple Line', + // subtitle: 'Nothing really special here...', + // ), + // ), + // ]), + PolygonEditor( + controller: controller.polygonEditorController, + throttleDuration: Duration.zero) + ], + ) + : const Center(child: CircularProgressIndicator())), + Positioned( + bottom: 3, + right: 3, + child: Row( + children: [ + IconButton.filled( + iconSize: 32, + onPressed: () { + controller.startPointEdition(); + }, + icon: const Icon(Icons.flag)), + IconButton.filled( + iconSize: 32, + onPressed: () { + controller.startPolylineEdition(); + }, + icon: const Icon(Icons.polyline)), + IconButton.filled( + iconSize: 32, + onPressed: () { + controller.startPolygonEdition(); + }, + icon: const Icon(Icons.border_outer)), + IconButton.filled( + iconSize: 32, + onPressed: () { + controller.saveNote(); + }, + icon: const Icon(Icons.done)), + IconButton.filled( + iconSize: 32, + onPressed: () { + controller.cancelEditorController(); + }, + icon: const Icon(Icons.cancel)) + ], + )) + ])) + ], + ), + ); } } diff --git a/lib/pages/home/presentation/views/home_view.dart b/lib/pages/home/presentation/views/home_view.dart index 5222d4e..3d0dcb7 100644 --- a/lib/pages/home/presentation/views/home_view.dart +++ b/lib/pages/home/presentation/views/home_view.dart @@ -55,6 +55,22 @@ class HomeView extends GetView { // child: const Text('RTCM teszt')) ], ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + TextButton( + onPressed: () async { + Get.toNamed("/field_trip"); + }, + child: Text('Field trip')), + TextButton( + onPressed: () async { + Get.toNamed("/tracking"); + }, + child: Text('Tracking')) + ])), Padding( padding: const EdgeInsets.only(top: 10.0), child: Row( diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index 8951a83..67a44dc 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -1,6 +1,8 @@ import 'package:get/get.dart'; import 'package:terepi_seged/pages/bleutooth/bindings/bluetooth_bindings.dart'; import 'package:terepi_seged/pages/bleutooth/presentation/views/bluetooth_test_view.dart'; +import 'package:terepi_seged/pages/field_trip/bindings/field_trip_bindings.dart'; +import 'package:terepi_seged/pages/field_trip/presentations/views/fiels_trip_view.dart'; import 'package:terepi_seged/pages/home/bindings/home_bindings.dart'; import 'package:terepi_seged/pages/home/presentation/views/home_view.dart'; import 'package:terepi_seged/pages/map/bindings/map_bindings.dart'; @@ -20,6 +22,8 @@ import 'package:terepi_seged/pages/socket_test/bindings/socket_test_bindings.dar import 'package:terepi_seged/pages/socket_test/presentation/views/socket_test_view.dart'; import 'package:terepi_seged/pages/start/bindings/start_page_bindings.dart'; import 'package:terepi_seged/pages/start/presentation/views/start_page.dart'; +import 'package:terepi_seged/pages/tracking/bindings/tracking_bindings.dart'; +import 'package:terepi_seged/pages/tracking/presentation/views/tracking_view.dart'; import '../pages/map_test/bindings/map_test_bindings.dart'; import '../pages/map_test/presentation/views/map_test_view.dart'; @@ -79,6 +83,14 @@ class AppPages { GetPage( name: Routes.MAPSURVEY, binding: MapSurveyBinding(), - page: () => const MapSurveyView()) + page: () => const MapSurveyView()), + GetPage( + name: Routes.FIELDTRIP, + binding: FieldTripBinding(), + page: () => const FieldTripView()), + GetPage( + name: Routes.TRACKING, + binding: TrackingBinding(), + page: () => const TrackingView()) ]; } diff --git a/lib/routes/app_routes.dart b/lib/routes/app_routes.dart index 32b0f0e..49663b5 100644 --- a/lib/routes/app_routes.dart +++ b/lib/routes/app_routes.dart @@ -15,6 +15,8 @@ abstract class Routes { static const PROPERTYLIST = '/property_list'; static const MEASUREDDATA = '/measured_data'; static const MAPSURVEY = '/map_survey'; + static const FIELDTRIP = '/field_trip'; + static const TRACKING = '/tracking'; static const MAPADDPOINTDIALOG = "/map_add_point_dialog"; } diff --git a/pubspec.yaml b/pubspec.yaml index 09601e6..448c4e7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -29,6 +29,7 @@ environment: dependencies: cupertino_icons: ^1.0.8 flutter_map: ^8.2.2 + flutter_map_polygon_editor: ^0.1.2 flutter_bluetooth_serial: ^0.4.0 get: ^4.7.2 latlong2: ^0.9.1