From 9136f399ab1ade73f2e0e0cd6fcdf2b8fd282282 Mon Sep 17 00:00:00 2001 From: Joscha <34318751+josxha@users.noreply.github.com> Date: Sat, 14 Sep 2024 02:09:51 +0200 Subject: [PATCH] add getCamera() --- .../josxha/maplibre/MapLibreMapController.kt | 9 + .../com/github/josxha/maplibre/Pigeon.g.kt | 67 ++++- example/lib/controller_page.dart | 26 ++ ios/Classes/Pigeon.g.swift | 64 ++++- lib/maplibre.dart | 1 + lib/src/map_camera.dart | 29 ++ lib/src/map_controller.dart | 3 + lib/src/native/pigeon.g.dart | 261 +++++++++--------- lib/src/native/widget_state.dart | 11 + lib/src/web/interop/map.dart | 14 + lib/src/web/widget_state.dart | 8 + linux/pigeon.g.cc | 172 ++++++++++++ linux/pigeon.g.h | 86 +++++- macos/Classes/Pigeon.g.swift | 64 ++++- pigeons/pigeon.dart | 24 +- windows/runner/pigeon.g.cpp | 111 ++++++++ windows/runner/pigeon.g.h | 52 +++- 17 files changed, 865 insertions(+), 137 deletions(-) create mode 100644 lib/src/map_camera.dart diff --git a/android/src/main/kotlin/com/github/josxha/maplibre/MapLibreMapController.kt b/android/src/main/kotlin/com/github/josxha/maplibre/MapLibreMapController.kt index aabad5de..a2a1e406 100644 --- a/android/src/main/kotlin/com/github/josxha/maplibre/MapLibreMapController.kt +++ b/android/src/main/kotlin/com/github/josxha/maplibre/MapLibreMapController.kt @@ -1,6 +1,7 @@ package com.github.josxha.maplibre import LngLat +import MapCamera import MapLibreFlutterApi import MapLibreHostApi import MapOptions @@ -146,6 +147,14 @@ class MapLibreMapController( callback(Result.success(LngLat(latLng.longitude, latLng.latitude))) } + override fun getCamera(callback: (Result) -> Unit) { + val position = mapLibreMap.cameraPosition + val target = mapLibreMap.cameraPosition.target!! + val center = LngLat(target.longitude, target.latitude) + val camera = MapCamera(center, position.zoom, position.tilt, position.bearing) + callback(Result.success(camera)) + } + override fun addFillLayer(id: String, sourceId: String, callback: (Result) -> Unit) { mapLibreMap.style?.addLayer(FillLayer(id, sourceId)) callback(Result.success(Unit)) diff --git a/android/src/main/kotlin/com/github/josxha/maplibre/Pigeon.g.kt b/android/src/main/kotlin/com/github/josxha/maplibre/Pigeon.g.kt index fdc2e16c..c455ab52 100644 --- a/android/src/main/kotlin/com/github/josxha/maplibre/Pigeon.g.kt +++ b/android/src/main/kotlin/com/github/josxha/maplibre/Pigeon.g.kt @@ -94,7 +94,7 @@ data class MapOptions ( } /** - * A longitude/latitude coordinate object + * A longitude/latitude coordinate object. * * Generated class from Pigeon that represents data sent in messages. */ @@ -121,7 +121,7 @@ data class LngLat ( } /** - * A pixel location / location on the device screen + * A pixel location / location on the device screen. * * Generated class from Pigeon that represents data sent in messages. */ @@ -146,6 +146,37 @@ data class ScreenLocation ( ) } } + +/** + * The current position of the map camera. + * + * Generated class from Pigeon that represents data sent in messages. + */ +data class MapCamera ( + val center: LngLat, + val zoom: Double, + val tilt: Double, + val bearing: Double +) + { + companion object { + fun fromList(pigeonVar_list: List): MapCamera { + val center = pigeonVar_list[0] as LngLat + val zoom = pigeonVar_list[1] as Double + val tilt = pigeonVar_list[2] as Double + val bearing = pigeonVar_list[3] as Double + return MapCamera(center, zoom, tilt, bearing) + } + } + fun toList(): List { + return listOf( + center, + zoom, + tilt, + bearing, + ) + } +} private open class PigeonPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { @@ -164,6 +195,11 @@ private open class PigeonPigeonCodec : StandardMessageCodec() { ScreenLocation.fromList(it) } } + 132.toByte() -> { + return (readValue(buffer) as? List)?.let { + MapCamera.fromList(it) + } + } else -> super.readValueOfType(type, buffer) } } @@ -181,6 +217,10 @@ private open class PigeonPigeonCodec : StandardMessageCodec() { stream.write(131) writeValue(stream, value.toList()) } + is MapCamera -> { + stream.write(132) + writeValue(stream, value.toList()) + } else -> super.writeValue(stream, value) } } @@ -193,6 +233,11 @@ interface MapLibreHostApi { fun jumpTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, callback: (Result) -> Unit) /** Animate the viewport of the map to a new location. */ fun flyTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, durationMs: Long, callback: (Result) -> Unit) + /** + * Get the current camera position with the map center, zoom level, camera + * tilt and map rotation. + */ + fun getCamera(callback: (Result) -> Unit) /** Convert a coordinate to a location on the screen. */ fun toScreenLocation(lng: Double, lat: Double, callback: (Result) -> Unit) /** Convert a screen location to a coordinate. */ @@ -258,6 +303,24 @@ interface MapLibreHostApi { channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.maplibre.MapLibreHostApi.getCamera$separatedMessageChannelSuffix", codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + api.getCamera{ result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } run { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation$separatedMessageChannelSuffix", codec) if (api != null) { diff --git a/example/lib/controller_page.dart b/example/lib/controller_page.dart index 9eaffde8..571b9f54 100644 --- a/example/lib/controller_page.dart +++ b/example/lib/controller_page.dart @@ -63,6 +63,32 @@ class _ControllerPageState extends State { }, child: const Text('Fly to Iceland'), ), + OutlinedButton( + onPressed: () async { + final camera = await _controller.getCamera(); + debugPrint(camera.toString()); + if (context.mounted) { + await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('MapCenter'), + content: Text(''' +center: Position(lng: ${camera.center.lng}, lat: ${camera.center.lat}) +zoom: ${camera.zoom} +bearing: ${camera.bearing} +tilt: ${camera.tilt}'''), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('OK'), + ), + ], + ), + ); + } + }, + child: const Text('Get MapCamera'), + ), ], ), ), diff --git a/ios/Classes/Pigeon.g.swift b/ios/Classes/Pigeon.g.swift index bf0bbaa9..be6fe6d1 100644 --- a/ios/Classes/Pigeon.g.swift +++ b/ios/Classes/Pigeon.g.swift @@ -122,7 +122,7 @@ struct MapOptions { } } -/// A longitude/latitude coordinate object +/// A longitude/latitude coordinate object. /// /// Generated class from Pigeon that represents data sent in messages. struct LngLat { @@ -151,7 +151,7 @@ struct LngLat { } } -/// A pixel location / location on the device screen +/// A pixel location / location on the device screen. /// /// Generated class from Pigeon that represents data sent in messages. struct ScreenLocation { @@ -180,6 +180,41 @@ struct ScreenLocation { } } +/// The current position of the map camera. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct MapCamera { + var center: LngLat + var zoom: Double + var tilt: Double + var bearing: Double + + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> MapCamera? { + let center = pigeonVar_list[0] as! LngLat + let zoom = pigeonVar_list[1] as! Double + let tilt = pigeonVar_list[2] as! Double + let bearing = pigeonVar_list[3] as! Double + + return MapCamera( + center: center, + zoom: zoom, + tilt: tilt, + bearing: bearing + ) + } + func toList() -> [Any?] { + return [ + center, + zoom, + tilt, + bearing, + ] + } +} + private class PigeonPigeonCodecReader: FlutterStandardReader { override func readValue(ofType type: UInt8) -> Any? { switch type { @@ -189,6 +224,8 @@ private class PigeonPigeonCodecReader: FlutterStandardReader { return LngLat.fromList(self.readValue() as! [Any?]) case 131: return ScreenLocation.fromList(self.readValue() as! [Any?]) + case 132: + return MapCamera.fromList(self.readValue() as! [Any?]) default: return super.readValue(ofType: type) } @@ -206,6 +243,9 @@ private class PigeonPigeonCodecWriter: FlutterStandardWriter { } else if let value = value as? ScreenLocation { super.writeByte(131) super.writeValue(value.toList()) + } else if let value = value as? MapCamera { + super.writeByte(132) + super.writeValue(value.toList()) } else { super.writeValue(value) } @@ -233,6 +273,9 @@ protocol MapLibreHostApi { func jumpTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, completion: @escaping (Result) -> Void) /// Animate the viewport of the map to a new location. func flyTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, durationMs: Int64, completion: @escaping (Result) -> Void) + /// Get the current camera position with the map center, zoom level, camera + /// tilt and map rotation. + func getCamera(completion: @escaping (Result) -> Void) /// Convert a coordinate to a location on the screen. func toScreenLocation(lng: Double, lat: Double, completion: @escaping (Result) -> Void) /// Convert a screen location to a coordinate. @@ -294,6 +337,23 @@ class MapLibreHostApiSetup { } else { flyToChannel.setMessageHandler(nil) } + /// Get the current camera position with the map center, zoom level, camera + /// tilt and map rotation. + let getCameraChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.maplibre.MapLibreHostApi.getCamera\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + getCameraChannel.setMessageHandler { _, reply in + api.getCamera { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + getCameraChannel.setMessageHandler(nil) + } /// Convert a coordinate to a location on the screen. let toScreenLocationChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { diff --git a/lib/maplibre.dart b/lib/maplibre.dart index a5a67b6c..b8f9cda8 100644 --- a/lib/maplibre.dart +++ b/lib/maplibre.dart @@ -5,6 +5,7 @@ export 'package:geotypes/geotypes.dart'; export 'src/annotations.dart'; export 'src/layers.dart'; export 'src/map.dart'; +export 'src/map_camera.dart'; export 'src/map_controller.dart'; export 'src/map_options.dart'; export 'src/sources.dart'; diff --git a/lib/src/map_camera.dart b/lib/src/map_camera.dart new file mode 100644 index 00000000..6cc01fd3 --- /dev/null +++ b/lib/src/map_camera.dart @@ -0,0 +1,29 @@ +import 'package:geotypes/geotypes.dart'; + +/// The current camera position on the map. +class MapCamera { + /// Default constructor for a [MapCamera]. + const MapCamera({ + required this.center, + required this.zoom, + required this.tilt, + required this.bearing, + }); + + /// The position of the map center. + final Position center; + + /// The zoom level of the map. + final double zoom; + + /// The bearing of the map. + final double bearing; + + /// The camera tilt of the map. + final double tilt; + + @override + String toString() => 'MapCamera(' + 'center: Position(lng: ${center.lng}, lat: ${center.lat}), ' + 'zoom: $zoom, bearing: $bearing, tilt: $tilt)'; +} diff --git a/lib/src/map_controller.dart b/lib/src/map_controller.dart index 4f6ad8d4..bc31f00e 100644 --- a/lib/src/map_controller.dart +++ b/lib/src/map_controller.dart @@ -40,4 +40,7 @@ abstract interface class MapController { /// Add a new layer to the map. The source must be added before adding it to /// the map. Future addLayer(Layer layer); + + /// Get the current camera position on the map. + Future getCamera(); } diff --git a/lib/src/native/pigeon.g.dart b/lib/src/native/pigeon.g.dart index 29fe3126..694ebb22 100644 --- a/lib/src/native/pigeon.g.dart +++ b/lib/src/native/pigeon.g.dart @@ -15,8 +15,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse( - {Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -85,7 +84,7 @@ class MapOptions { } } -/// A longitude/latitude coordinate object +/// A longitude/latitude coordinate object. class LngLat { LngLat({ required this.lng, @@ -114,7 +113,7 @@ class LngLat { } } -/// A pixel location / location on the device screen +/// A pixel location / location on the device screen. class ScreenLocation { ScreenLocation({ required this.x, @@ -143,6 +142,44 @@ class ScreenLocation { } } +/// The current position of the map camera. +class MapCamera { + MapCamera({ + required this.center, + required this.zoom, + required this.tilt, + required this.bearing, + }); + + LngLat center; + + double zoom; + + double tilt; + + double bearing; + + Object encode() { + return [ + center, + zoom, + tilt, + bearing, + ]; + } + + static MapCamera decode(Object result) { + result as List; + return MapCamera( + center: result[0]! as LngLat, + zoom: result[1]! as double, + tilt: result[2]! as double, + bearing: result[3]! as double, + ); + } +} + + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -150,15 +187,18 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is MapOptions) { + } else if (value is MapOptions) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is LngLat) { + } else if (value is LngLat) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is ScreenLocation) { + } else if (value is ScreenLocation) { buffer.putUint8(131); writeValue(buffer, value.encode()); + } else if (value is MapCamera) { + buffer.putUint8(132); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -167,12 +207,14 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: return MapOptions.decode(readValue(buffer)!); - case 130: + case 130: return LngLat.decode(readValue(buffer)!); - case 131: + case 131: return ScreenLocation.decode(readValue(buffer)!); + case 132: + return MapCamera.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -183,11 +225,9 @@ class MapLibreHostApi { /// Constructor for [MapLibreHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - MapLibreHostApi( - {BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + MapLibreHostApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -195,22 +235,15 @@ class MapLibreHostApi { final String pigeonVar_messageChannelSuffix; /// Move the viewport of the map to a new location without any animation. - Future jumpTo({ - required LngLat? center, - required double? zoom, - required double? bearing, - required double? pitch, - }) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.maplibre.MapLibreHostApi.jumpTo$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + Future jumpTo({required LngLat? center, required double? zoom, required double? bearing, required double? pitch,}) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.jumpTo$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([center, zoom, bearing, pitch]) as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([center, zoom, bearing, pitch]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -225,24 +258,15 @@ class MapLibreHostApi { } /// Animate the viewport of the map to a new location. - Future flyTo({ - required LngLat? center, - required double? zoom, - required double? bearing, - required double? pitch, - required int durationMs, - }) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.maplibre.MapLibreHostApi.flyTo$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + Future flyTo({required LngLat? center, required double? zoom, required double? bearing, required double? pitch, required int durationMs,}) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.flyTo$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = await pigeonVar_channel - .send([center, zoom, bearing, pitch, durationMs]) - as List?; + final List? pigeonVar_replyList = + await pigeonVar_channel.send([center, zoom, bearing, pitch, durationMs]) as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -256,12 +280,39 @@ class MapLibreHostApi { } } + /// Get the current camera position with the map center, zoom level, camera + /// tilt and map rotation. + Future getCamera() async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.getCamera$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send(null) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as MapCamera?)!; + } + } + /// Convert a coordinate to a location on the screen. Future toScreenLocation(double lng, double lat) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -288,10 +339,8 @@ class MapLibreHostApi { /// Convert a screen location to a coordinate. Future toLngLat(double x, double y) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.maplibre.MapLibreHostApi.toLngLat$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.toLngLat$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -317,12 +366,9 @@ class MapLibreHostApi { } /// Add a fill layer to the map style. - Future addFillLayer( - {required String id, required String sourceId}) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.maplibre.MapLibreHostApi.addFillLayer$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + Future addFillLayer({required String id, required String sourceId}) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.addFillLayer$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -343,12 +389,9 @@ class MapLibreHostApi { } /// Add a circle layer to the map style. - Future addCircleLayer( - {required String id, required String sourceId}) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.maplibre.MapLibreHostApi.addCircleLayer$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + Future addCircleLayer({required String id, required String sourceId}) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.addCircleLayer$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -369,12 +412,9 @@ class MapLibreHostApi { } /// Add a GeoJSON source to the map style. - Future addGeoJsonSource( - {required String id, required String data}) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.maplibre.MapLibreHostApi.addGeoJsonSource$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( + Future addGeoJsonSource({required String id, required String data}) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.maplibre.MapLibreHostApi.addGeoJsonSource$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, @@ -417,19 +457,11 @@ abstract class MapLibreFlutterApi { /// Callback when the user performs a long lasting click on the map. void onLongClick(LngLat point); - static void setUp( - MapLibreFlutterApi? api, { - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) { - messageChannelSuffix = - messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + static void setUp(MapLibreFlutterApi? api, {BinaryMessenger? binaryMessenger, String messageChannelSuffix = '',}) { + messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.getOptions$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.getOptions$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { pigeonVar_channel.setMessageHandler(null); @@ -440,19 +472,15 @@ abstract class MapLibreFlutterApi { return wrapResponse(result: output); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onStyleLoaded$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onStyleLoaded$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { pigeonVar_channel.setMessageHandler(null); @@ -463,26 +491,22 @@ abstract class MapLibreFlutterApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onClick$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onClick$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onClick was null.'); + 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onClick was null.'); final List args = (message as List?)!; final LngLat? arg_point = (args[0] as LngLat?); assert(arg_point != null, @@ -492,26 +516,22 @@ abstract class MapLibreFlutterApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onSecondaryClick$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onSecondaryClick$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onSecondaryClick was null.'); + 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onSecondaryClick was null.'); final List args = (message as List?)!; final LngLat? arg_point = (args[0] as LngLat?); assert(arg_point != null, @@ -521,26 +541,22 @@ abstract class MapLibreFlutterApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onDoubleClick$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onDoubleClick$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onDoubleClick was null.'); + 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onDoubleClick was null.'); final List args = (message as List?)!; final LngLat? arg_point = (args[0] as LngLat?); assert(arg_point != null, @@ -550,26 +566,22 @@ abstract class MapLibreFlutterApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } } { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onLongClick$messageChannelSuffix', - pigeonChannelCodec, + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onLongClick$messageChannelSuffix', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (api == null) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onLongClick was null.'); + 'Argument for dev.flutter.pigeon.maplibre.MapLibreFlutterApi.onLongClick was null.'); final List args = (message as List?)!; final LngLat? arg_point = (args[0] as LngLat?); assert(arg_point != null, @@ -579,9 +591,8 @@ abstract class MapLibreFlutterApi { return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + } catch (e) { + return wrapResponse(error: PlatformException(code: 'error', message: e.toString())); } }); } diff --git a/lib/src/native/widget_state.dart b/lib/src/native/widget_state.dart index 074dab1a..be0a1a41 100644 --- a/lib/src/native/widget_state.dart +++ b/lib/src/native/widget_state.dart @@ -147,4 +147,15 @@ final class MapLibreMapStateNative extends State @override void onLongClick(pigeon.LngLat point) => _options.onLongClick?.call(Position(point.lng, point.lat)); + + @override + Future getCamera() async { + final camera = await _hostApi.getCamera(); + return MapCamera( + center: camera.center.toPosition(), + zoom: camera.zoom, + tilt: camera.tilt, + bearing: camera.bearing, + ); + } } diff --git a/lib/src/web/interop/map.dart b/lib/src/web/interop/map.dart index 45d7a0dd..61217340 100644 --- a/lib/src/web/interop/map.dart +++ b/lib/src/web/interop/map.dart @@ -43,6 +43,20 @@ extension type Map._(Camera _) implements Camera { /// Clean up and release all internal JS resources associated with this map. external void remove(); + + /// Returns the map's geographical centerpoint. + external LngLat getCenter(); + + /// Returns the map's current zoom level. + external num getZoom(); + + /// Returns the map's current bearing. The bearing is the compass direction + /// that is "up"; for example, a bearing of 90° orients the map so that + /// east is up. + external num getBearing(); + + /// Returns the map's current pitch (tilt). + external num getPitch(); } /// Anonymous MapOptions for the MapLibre JavaScript [Map]. diff --git a/lib/src/web/widget_state.dart b/lib/src/web/widget_state.dart index 23cc4bfb..cc579a9d 100644 --- a/lib/src/web/widget_state.dart +++ b/lib/src/web/widget_state.dart @@ -251,4 +251,12 @@ final class MapLibreMapStateWeb extends State ); } } + + @override + Future getCamera() async => MapCamera( + center: _map.getCenter().toPosition(), + zoom: _map.getZoom().toDouble(), + tilt: _map.getPitch().toDouble(), + bearing: _map.getBearing().toDouble(), + ); } diff --git a/linux/pigeon.g.cc b/linux/pigeon.g.cc index fa2cf540..58943ac5 100644 --- a/linux/pigeon.g.cc +++ b/linux/pigeon.g.cc @@ -220,6 +220,80 @@ static MaplibreScreenLocation* maplibre_screen_location_new_from_list(FlValue* v return maplibre_screen_location_new(x, y); } +struct _MaplibreMapCamera { + GObject parent_instance; + + MaplibreLngLat* center; + double zoom; + double tilt; + double bearing; +}; + +G_DEFINE_TYPE(MaplibreMapCamera, maplibre_map_camera, G_TYPE_OBJECT) + +static void maplibre_map_camera_dispose(GObject* object) { + MaplibreMapCamera* self = MAPLIBRE_MAP_CAMERA(object); + g_clear_object(&self->center); + G_OBJECT_CLASS(maplibre_map_camera_parent_class)->dispose(object); +} + +static void maplibre_map_camera_init(MaplibreMapCamera* self) { +} + +static void maplibre_map_camera_class_init(MaplibreMapCameraClass* klass) { + G_OBJECT_CLASS(klass)->dispose = maplibre_map_camera_dispose; +} + +MaplibreMapCamera* maplibre_map_camera_new(MaplibreLngLat* center, double zoom, double tilt, double bearing) { + MaplibreMapCamera* self = MAPLIBRE_MAP_CAMERA(g_object_new(maplibre_map_camera_get_type(), nullptr)); + self->center = MAPLIBRE_LNG_LAT(g_object_ref(center)); + self->zoom = zoom; + self->tilt = tilt; + self->bearing = bearing; + return self; +} + +MaplibreLngLat* maplibre_map_camera_get_center(MaplibreMapCamera* self) { + g_return_val_if_fail(MAPLIBRE_IS_MAP_CAMERA(self), nullptr); + return self->center; +} + +double maplibre_map_camera_get_zoom(MaplibreMapCamera* self) { + g_return_val_if_fail(MAPLIBRE_IS_MAP_CAMERA(self), 0.0); + return self->zoom; +} + +double maplibre_map_camera_get_tilt(MaplibreMapCamera* self) { + g_return_val_if_fail(MAPLIBRE_IS_MAP_CAMERA(self), 0.0); + return self->tilt; +} + +double maplibre_map_camera_get_bearing(MaplibreMapCamera* self) { + g_return_val_if_fail(MAPLIBRE_IS_MAP_CAMERA(self), 0.0); + return self->bearing; +} + +static FlValue* maplibre_map_camera_to_list(MaplibreMapCamera* self) { + FlValue* values = fl_value_new_list(); + fl_value_append_take(values, fl_value_new_custom_object(130, G_OBJECT(self->center))); + fl_value_append_take(values, fl_value_new_float(self->zoom)); + fl_value_append_take(values, fl_value_new_float(self->tilt)); + fl_value_append_take(values, fl_value_new_float(self->bearing)); + return values; +} + +static MaplibreMapCamera* maplibre_map_camera_new_from_list(FlValue* values) { + FlValue* value0 = fl_value_get_list_value(values, 0); + MaplibreLngLat* center = MAPLIBRE_LNG_LAT(fl_value_get_custom_value_object(value0)); + FlValue* value1 = fl_value_get_list_value(values, 1); + double zoom = fl_value_get_float(value1); + FlValue* value2 = fl_value_get_list_value(values, 2); + double tilt = fl_value_get_float(value2); + FlValue* value3 = fl_value_get_list_value(values, 3); + double bearing = fl_value_get_float(value3); + return maplibre_map_camera_new(center, zoom, tilt, bearing); +} + G_DECLARE_FINAL_TYPE(MaplibreMessageCodec, maplibre_message_codec, MAPLIBRE, MESSAGE_CODEC, FlStandardMessageCodec) struct _MaplibreMessageCodec { @@ -250,6 +324,13 @@ static gboolean maplibre_message_codec_write_maplibre_screen_location(FlStandard return fl_standard_message_codec_write_value(codec, buffer, values, error); } +static gboolean maplibre_message_codec_write_maplibre_map_camera(FlStandardMessageCodec* codec, GByteArray* buffer, MaplibreMapCamera* value, GError** error) { + uint8_t type = 132; + g_byte_array_append(buffer, &type, sizeof(uint8_t)); + g_autoptr(FlValue) values = maplibre_map_camera_to_list(value); + return fl_standard_message_codec_write_value(codec, buffer, values, error); +} + static gboolean maplibre_message_codec_write_value(FlStandardMessageCodec* codec, GByteArray* buffer, FlValue* value, GError** error) { if (fl_value_get_type(value) == FL_VALUE_TYPE_CUSTOM) { switch (fl_value_get_custom_type(value)) { @@ -259,6 +340,8 @@ static gboolean maplibre_message_codec_write_value(FlStandardMessageCodec* codec return maplibre_message_codec_write_maplibre_lng_lat(codec, buffer, MAPLIBRE_LNG_LAT(fl_value_get_custom_value_object(value)), error); case 131: return maplibre_message_codec_write_maplibre_screen_location(codec, buffer, MAPLIBRE_SCREEN_LOCATION(fl_value_get_custom_value_object(value)), error); + case 132: + return maplibre_message_codec_write_maplibre_map_camera(codec, buffer, MAPLIBRE_MAP_CAMERA(fl_value_get_custom_value_object(value)), error); } } @@ -310,6 +393,21 @@ static FlValue* maplibre_message_codec_read_maplibre_screen_location(FlStandardM return fl_value_new_custom_object(131, G_OBJECT(value)); } +static FlValue* maplibre_message_codec_read_maplibre_map_camera(FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, GError** error) { + g_autoptr(FlValue) values = fl_standard_message_codec_read_value(codec, buffer, offset, error); + if (values == nullptr) { + return nullptr; + } + + g_autoptr(MaplibreMapCamera) value = maplibre_map_camera_new_from_list(values); + if (value == nullptr) { + g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED, "Invalid data received for MessageData"); + return nullptr; + } + + return fl_value_new_custom_object(132, G_OBJECT(value)); +} + static FlValue* maplibre_message_codec_read_value_of_type(FlStandardMessageCodec* codec, GBytes* buffer, size_t* offset, int type, GError** error) { switch (type) { case 129: @@ -318,6 +416,8 @@ static FlValue* maplibre_message_codec_read_value_of_type(FlStandardMessageCodec return maplibre_message_codec_read_maplibre_lng_lat(codec, buffer, offset, error); case 131: return maplibre_message_codec_read_maplibre_screen_location(codec, buffer, offset, error); + case 132: + return maplibre_message_codec_read_maplibre_map_camera(codec, buffer, offset, error); default: return FL_STANDARD_MESSAGE_CODEC_CLASS(maplibre_message_codec_parent_class)->read_value_of_type(codec, buffer, offset, type, error); } @@ -444,6 +544,45 @@ static MaplibreMapLibreHostApiFlyToResponse* maplibre_map_libre_host_api_fly_to_ return self; } +G_DECLARE_FINAL_TYPE(MaplibreMapLibreHostApiGetCameraResponse, maplibre_map_libre_host_api_get_camera_response, MAPLIBRE, MAP_LIBRE_HOST_API_GET_CAMERA_RESPONSE, GObject) + +struct _MaplibreMapLibreHostApiGetCameraResponse { + GObject parent_instance; + + FlValue* value; +}; + +G_DEFINE_TYPE(MaplibreMapLibreHostApiGetCameraResponse, maplibre_map_libre_host_api_get_camera_response, G_TYPE_OBJECT) + +static void maplibre_map_libre_host_api_get_camera_response_dispose(GObject* object) { + MaplibreMapLibreHostApiGetCameraResponse* self = MAPLIBRE_MAP_LIBRE_HOST_API_GET_CAMERA_RESPONSE(object); + g_clear_pointer(&self->value, fl_value_unref); + G_OBJECT_CLASS(maplibre_map_libre_host_api_get_camera_response_parent_class)->dispose(object); +} + +static void maplibre_map_libre_host_api_get_camera_response_init(MaplibreMapLibreHostApiGetCameraResponse* self) { +} + +static void maplibre_map_libre_host_api_get_camera_response_class_init(MaplibreMapLibreHostApiGetCameraResponseClass* klass) { + G_OBJECT_CLASS(klass)->dispose = maplibre_map_libre_host_api_get_camera_response_dispose; +} + +static MaplibreMapLibreHostApiGetCameraResponse* maplibre_map_libre_host_api_get_camera_response_new(MaplibreMapCamera* return_value) { + MaplibreMapLibreHostApiGetCameraResponse* self = MAPLIBRE_MAP_LIBRE_HOST_API_GET_CAMERA_RESPONSE(g_object_new(maplibre_map_libre_host_api_get_camera_response_get_type(), nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_custom_object(132, G_OBJECT(return_value))); + return self; +} + +static MaplibreMapLibreHostApiGetCameraResponse* maplibre_map_libre_host_api_get_camera_response_new_error(const gchar* code, const gchar* message, FlValue* details) { + MaplibreMapLibreHostApiGetCameraResponse* self = MAPLIBRE_MAP_LIBRE_HOST_API_GET_CAMERA_RESPONSE(g_object_new(maplibre_map_libre_host_api_get_camera_response_get_type(), nullptr)); + self->value = fl_value_new_list(); + fl_value_append_take(self->value, fl_value_new_string(code)); + fl_value_append_take(self->value, fl_value_new_string(message != nullptr ? message : "")); + fl_value_append_take(self->value, details != nullptr ? fl_value_ref(details) : fl_value_new_null()); + return self; +} + G_DECLARE_FINAL_TYPE(MaplibreMapLibreHostApiToScreenLocationResponse, maplibre_map_libre_host_api_to_screen_location_response, MAPLIBRE, MAP_LIBRE_HOST_API_TO_SCREEN_LOCATION_RESPONSE, GObject) struct _MaplibreMapLibreHostApiToScreenLocationResponse { @@ -745,6 +884,17 @@ static void maplibre_map_libre_host_api_fly_to_cb(FlBasicMessageChannel* channel self->vtable->fly_to(center, zoom, bearing, pitch, duration_ms, handle, self->user_data); } +static void maplibre_map_libre_host_api_get_camera_cb(FlBasicMessageChannel* channel, FlValue* message_, FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { + MaplibreMapLibreHostApi* self = MAPLIBRE_MAP_LIBRE_HOST_API(user_data); + + if (self->vtable == nullptr || self->vtable->get_camera == nullptr) { + return; + } + + g_autoptr(MaplibreMapLibreHostApiResponseHandle) handle = maplibre_map_libre_host_api_response_handle_new(channel, response_handle); + self->vtable->get_camera(handle, self->user_data); +} + static void maplibre_map_libre_host_api_to_screen_location_cb(FlBasicMessageChannel* channel, FlValue* message_, FlBasicMessageChannelResponseHandle* response_handle, gpointer user_data) { MaplibreMapLibreHostApi* self = MAPLIBRE_MAP_LIBRE_HOST_API(user_data); @@ -831,6 +981,9 @@ void maplibre_map_libre_host_api_set_method_handlers(FlBinaryMessenger* messenge g_autofree gchar* fly_to_channel_name = g_strdup_printf("dev.flutter.pigeon.maplibre.MapLibreHostApi.flyTo%s", dot_suffix); g_autoptr(FlBasicMessageChannel) fly_to_channel = fl_basic_message_channel_new(messenger, fly_to_channel_name, FL_MESSAGE_CODEC(codec)); fl_basic_message_channel_set_message_handler(fly_to_channel, maplibre_map_libre_host_api_fly_to_cb, g_object_ref(api_data), g_object_unref); + g_autofree gchar* get_camera_channel_name = g_strdup_printf("dev.flutter.pigeon.maplibre.MapLibreHostApi.getCamera%s", dot_suffix); + g_autoptr(FlBasicMessageChannel) get_camera_channel = fl_basic_message_channel_new(messenger, get_camera_channel_name, FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(get_camera_channel, maplibre_map_libre_host_api_get_camera_cb, g_object_ref(api_data), g_object_unref); g_autofree gchar* to_screen_location_channel_name = g_strdup_printf("dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation%s", dot_suffix); g_autoptr(FlBasicMessageChannel) to_screen_location_channel = fl_basic_message_channel_new(messenger, to_screen_location_channel_name, FL_MESSAGE_CODEC(codec)); fl_basic_message_channel_set_message_handler(to_screen_location_channel, maplibre_map_libre_host_api_to_screen_location_cb, g_object_ref(api_data), g_object_unref); @@ -858,6 +1011,9 @@ void maplibre_map_libre_host_api_clear_method_handlers(FlBinaryMessenger* messen g_autofree gchar* fly_to_channel_name = g_strdup_printf("dev.flutter.pigeon.maplibre.MapLibreHostApi.flyTo%s", dot_suffix); g_autoptr(FlBasicMessageChannel) fly_to_channel = fl_basic_message_channel_new(messenger, fly_to_channel_name, FL_MESSAGE_CODEC(codec)); fl_basic_message_channel_set_message_handler(fly_to_channel, nullptr, nullptr, nullptr); + g_autofree gchar* get_camera_channel_name = g_strdup_printf("dev.flutter.pigeon.maplibre.MapLibreHostApi.getCamera%s", dot_suffix); + g_autoptr(FlBasicMessageChannel) get_camera_channel = fl_basic_message_channel_new(messenger, get_camera_channel_name, FL_MESSAGE_CODEC(codec)); + fl_basic_message_channel_set_message_handler(get_camera_channel, nullptr, nullptr, nullptr); g_autofree gchar* to_screen_location_channel_name = g_strdup_printf("dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation%s", dot_suffix); g_autoptr(FlBasicMessageChannel) to_screen_location_channel = fl_basic_message_channel_new(messenger, to_screen_location_channel_name, FL_MESSAGE_CODEC(codec)); fl_basic_message_channel_set_message_handler(to_screen_location_channel, nullptr, nullptr, nullptr); @@ -907,6 +1063,22 @@ void maplibre_map_libre_host_api_respond_error_fly_to(MaplibreMapLibreHostApiRes } } +void maplibre_map_libre_host_api_respond_get_camera(MaplibreMapLibreHostApiResponseHandle* response_handle, MaplibreMapCamera* return_value) { + g_autoptr(MaplibreMapLibreHostApiGetCameraResponse) response = maplibre_map_libre_host_api_get_camera_response_new(return_value); + g_autoptr(GError) error = nullptr; + if (!fl_basic_message_channel_respond(response_handle->channel, response_handle->response_handle, response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "MapLibreHostApi", "getCamera", error->message); + } +} + +void maplibre_map_libre_host_api_respond_error_get_camera(MaplibreMapLibreHostApiResponseHandle* response_handle, const gchar* code, const gchar* message, FlValue* details) { + g_autoptr(MaplibreMapLibreHostApiGetCameraResponse) response = maplibre_map_libre_host_api_get_camera_response_new_error(code, message, details); + g_autoptr(GError) error = nullptr; + if (!fl_basic_message_channel_respond(response_handle->channel, response_handle->response_handle, response->value, &error)) { + g_warning("Failed to send response to %s.%s: %s", "MapLibreHostApi", "getCamera", error->message); + } +} + void maplibre_map_libre_host_api_respond_to_screen_location(MaplibreMapLibreHostApiResponseHandle* response_handle, MaplibreScreenLocation* return_value) { g_autoptr(MaplibreMapLibreHostApiToScreenLocationResponse) response = maplibre_map_libre_host_api_to_screen_location_response_new(return_value); g_autoptr(GError) error = nullptr; diff --git a/linux/pigeon.g.h b/linux/pigeon.g.h index 478311d4..4bc51dd8 100644 --- a/linux/pigeon.g.h +++ b/linux/pigeon.g.h @@ -105,7 +105,7 @@ gboolean maplibre_map_options_get_listens_on_long_click(MaplibreMapOptions* obje /** * MaplibreLngLat: * - * A longitude/latitude coordinate object + * A longitude/latitude coordinate object. */ G_DECLARE_FINAL_TYPE(MaplibreLngLat, maplibre_lng_lat, MAPLIBRE, LNG_LAT, GObject) @@ -144,7 +144,7 @@ double maplibre_lng_lat_get_lat(MaplibreLngLat* object); /** * MaplibreScreenLocation: * - * A pixel location / location on the device screen + * A pixel location / location on the device screen. */ G_DECLARE_FINAL_TYPE(MaplibreScreenLocation, maplibre_screen_location, MAPLIBRE, SCREEN_LOCATION, GObject) @@ -180,6 +180,67 @@ double maplibre_screen_location_get_x(MaplibreScreenLocation* object); */ double maplibre_screen_location_get_y(MaplibreScreenLocation* object); +/** + * MaplibreMapCamera: + * + * The current position of the map camera. + */ + +G_DECLARE_FINAL_TYPE(MaplibreMapCamera, maplibre_map_camera, MAPLIBRE, MAP_CAMERA, GObject) + +/** + * maplibre_map_camera_new: + * center: field in this object. + * zoom: field in this object. + * tilt: field in this object. + * bearing: field in this object. + * + * Creates a new #MapCamera object. + * + * Returns: a new #MaplibreMapCamera + */ +MaplibreMapCamera* maplibre_map_camera_new(MaplibreLngLat* center, double zoom, double tilt, double bearing); + +/** + * maplibre_map_camera_get_center + * @object: a #MaplibreMapCamera. + * + * Gets the value of the center field of @object. + * + * Returns: the field value. + */ +MaplibreLngLat* maplibre_map_camera_get_center(MaplibreMapCamera* object); + +/** + * maplibre_map_camera_get_zoom + * @object: a #MaplibreMapCamera. + * + * Gets the value of the zoom field of @object. + * + * Returns: the field value. + */ +double maplibre_map_camera_get_zoom(MaplibreMapCamera* object); + +/** + * maplibre_map_camera_get_tilt + * @object: a #MaplibreMapCamera. + * + * Gets the value of the tilt field of @object. + * + * Returns: the field value. + */ +double maplibre_map_camera_get_tilt(MaplibreMapCamera* object); + +/** + * maplibre_map_camera_get_bearing + * @object: a #MaplibreMapCamera. + * + * Gets the value of the bearing field of @object. + * + * Returns: the field value. + */ +double maplibre_map_camera_get_bearing(MaplibreMapCamera* object); + G_DECLARE_FINAL_TYPE(MaplibreMapLibreHostApiResponseHandle, maplibre_map_libre_host_api_response_handle, MAPLIBRE, MAP_LIBRE_HOST_API_RESPONSE_HANDLE, GObject) /** @@ -190,6 +251,7 @@ G_DECLARE_FINAL_TYPE(MaplibreMapLibreHostApiResponseHandle, maplibre_map_libre_h typedef struct { void (*jump_to)(MaplibreLngLat* center, double* zoom, double* bearing, double* pitch, MaplibreMapLibreHostApiResponseHandle* response_handle, gpointer user_data); void (*fly_to)(MaplibreLngLat* center, double* zoom, double* bearing, double* pitch, int64_t duration_ms, MaplibreMapLibreHostApiResponseHandle* response_handle, gpointer user_data); + void (*get_camera)(MaplibreMapLibreHostApiResponseHandle* response_handle, gpointer user_data); void (*to_screen_location)(double lng, double lat, MaplibreMapLibreHostApiResponseHandle* response_handle, gpointer user_data); void (*to_lng_lat)(double x, double y, MaplibreMapLibreHostApiResponseHandle* response_handle, gpointer user_data); void (*add_fill_layer)(const gchar* id, const gchar* source_id, MaplibreMapLibreHostApiResponseHandle* response_handle, gpointer user_data); @@ -258,6 +320,26 @@ void maplibre_map_libre_host_api_respond_fly_to(MaplibreMapLibreHostApiResponseH */ void maplibre_map_libre_host_api_respond_error_fly_to(MaplibreMapLibreHostApiResponseHandle* response_handle, const gchar* code, const gchar* message, FlValue* details); +/** + * maplibre_map_libre_host_api_respond_get_camera: + * @response_handle: a #MaplibreMapLibreHostApiResponseHandle. + * @return_value: location to write the value returned by this method. + * + * Responds to MapLibreHostApi.getCamera. + */ +void maplibre_map_libre_host_api_respond_get_camera(MaplibreMapLibreHostApiResponseHandle* response_handle, MaplibreMapCamera* return_value); + +/** + * maplibre_map_libre_host_api_respond_error_get_camera: + * @response_handle: a #MaplibreMapLibreHostApiResponseHandle. + * @code: error code. + * @message: error message. + * @details: (allow-none): error details or %NULL. + * + * Responds with an error to MapLibreHostApi.getCamera. + */ +void maplibre_map_libre_host_api_respond_error_get_camera(MaplibreMapLibreHostApiResponseHandle* response_handle, const gchar* code, const gchar* message, FlValue* details); + /** * maplibre_map_libre_host_api_respond_to_screen_location: * @response_handle: a #MaplibreMapLibreHostApiResponseHandle. diff --git a/macos/Classes/Pigeon.g.swift b/macos/Classes/Pigeon.g.swift index bf0bbaa9..be6fe6d1 100644 --- a/macos/Classes/Pigeon.g.swift +++ b/macos/Classes/Pigeon.g.swift @@ -122,7 +122,7 @@ struct MapOptions { } } -/// A longitude/latitude coordinate object +/// A longitude/latitude coordinate object. /// /// Generated class from Pigeon that represents data sent in messages. struct LngLat { @@ -151,7 +151,7 @@ struct LngLat { } } -/// A pixel location / location on the device screen +/// A pixel location / location on the device screen. /// /// Generated class from Pigeon that represents data sent in messages. struct ScreenLocation { @@ -180,6 +180,41 @@ struct ScreenLocation { } } +/// The current position of the map camera. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct MapCamera { + var center: LngLat + var zoom: Double + var tilt: Double + var bearing: Double + + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> MapCamera? { + let center = pigeonVar_list[0] as! LngLat + let zoom = pigeonVar_list[1] as! Double + let tilt = pigeonVar_list[2] as! Double + let bearing = pigeonVar_list[3] as! Double + + return MapCamera( + center: center, + zoom: zoom, + tilt: tilt, + bearing: bearing + ) + } + func toList() -> [Any?] { + return [ + center, + zoom, + tilt, + bearing, + ] + } +} + private class PigeonPigeonCodecReader: FlutterStandardReader { override func readValue(ofType type: UInt8) -> Any? { switch type { @@ -189,6 +224,8 @@ private class PigeonPigeonCodecReader: FlutterStandardReader { return LngLat.fromList(self.readValue() as! [Any?]) case 131: return ScreenLocation.fromList(self.readValue() as! [Any?]) + case 132: + return MapCamera.fromList(self.readValue() as! [Any?]) default: return super.readValue(ofType: type) } @@ -206,6 +243,9 @@ private class PigeonPigeonCodecWriter: FlutterStandardWriter { } else if let value = value as? ScreenLocation { super.writeByte(131) super.writeValue(value.toList()) + } else if let value = value as? MapCamera { + super.writeByte(132) + super.writeValue(value.toList()) } else { super.writeValue(value) } @@ -233,6 +273,9 @@ protocol MapLibreHostApi { func jumpTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, completion: @escaping (Result) -> Void) /// Animate the viewport of the map to a new location. func flyTo(center: LngLat?, zoom: Double?, bearing: Double?, pitch: Double?, durationMs: Int64, completion: @escaping (Result) -> Void) + /// Get the current camera position with the map center, zoom level, camera + /// tilt and map rotation. + func getCamera(completion: @escaping (Result) -> Void) /// Convert a coordinate to a location on the screen. func toScreenLocation(lng: Double, lat: Double, completion: @escaping (Result) -> Void) /// Convert a screen location to a coordinate. @@ -294,6 +337,23 @@ class MapLibreHostApiSetup { } else { flyToChannel.setMessageHandler(nil) } + /// Get the current camera position with the map center, zoom level, camera + /// tilt and map rotation. + let getCameraChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.maplibre.MapLibreHostApi.getCamera\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + getCameraChannel.setMessageHandler { _, reply in + api.getCamera { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + getCameraChannel.setMessageHandler(nil) + } /// Convert a coordinate to a location on the screen. let toScreenLocationChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { diff --git a/pigeons/pigeon.dart b/pigeons/pigeon.dart index 733c1fe0..91762ca9 100644 --- a/pigeons/pigeon.dart +++ b/pigeons/pigeon.dart @@ -42,6 +42,11 @@ abstract interface class MapLibreHostApi { required int durationMs, }); + /// Get the current camera position with the map center, zoom level, camera + /// tilt and map rotation. + @async + MapCamera getCamera(); + /// Convert a coordinate to a location on the screen. @async ScreenLocation toScreenLocation(double lng, double lat); @@ -122,7 +127,7 @@ class MapOptions { final bool listensOnLongClick; } -/// A longitude/latitude coordinate object +/// A longitude/latitude coordinate object. class LngLat { const LngLat({required this.lng, required this.lat}); @@ -133,7 +138,7 @@ class LngLat { final double lat; } -/// A pixel location / location on the device screen +/// A pixel location / location on the device screen. class ScreenLocation { const ScreenLocation({required this.x, required this.y}); @@ -143,3 +148,18 @@ class ScreenLocation { /// The y coordinate final double y; } + +/// The current position of the map camera. +class MapCamera { + const MapCamera({ + required this.center, + required this.zoom, + required this.tilt, + required this.bearing, + }); + + final LngLat center; + final double zoom; + final double tilt; + final double bearing; +} diff --git a/windows/runner/pigeon.g.cpp b/windows/runner/pigeon.g.cpp index 28497538..7d6a4c00 100644 --- a/windows/runner/pigeon.g.cpp +++ b/windows/runner/pigeon.g.cpp @@ -257,6 +257,87 @@ ScreenLocation ScreenLocation::FromEncodableList(const EncodableList& list) { return decoded; } +// MapCamera + +MapCamera::MapCamera( + const LngLat& center, + double zoom, + double tilt, + double bearing) + : center_(std::make_unique(center)), + zoom_(zoom), + tilt_(tilt), + bearing_(bearing) {} + +MapCamera::MapCamera(const MapCamera& other) + : center_(std::make_unique(*other.center_)), + zoom_(other.zoom_), + tilt_(other.tilt_), + bearing_(other.bearing_) {} + +MapCamera& MapCamera::operator=(const MapCamera& other) { + center_ = std::make_unique(*other.center_); + zoom_ = other.zoom_; + tilt_ = other.tilt_; + bearing_ = other.bearing_; + return *this; +} + +const LngLat& MapCamera::center() const { + return *center_; +} + +void MapCamera::set_center(const LngLat& value_arg) { + center_ = std::make_unique(value_arg); +} + + +double MapCamera::zoom() const { + return zoom_; +} + +void MapCamera::set_zoom(double value_arg) { + zoom_ = value_arg; +} + + +double MapCamera::tilt() const { + return tilt_; +} + +void MapCamera::set_tilt(double value_arg) { + tilt_ = value_arg; +} + + +double MapCamera::bearing() const { + return bearing_; +} + +void MapCamera::set_bearing(double value_arg) { + bearing_ = value_arg; +} + + +EncodableList MapCamera::ToEncodableList() const { + EncodableList list; + list.reserve(4); + list.push_back(CustomEncodableValue(*center_)); + list.push_back(EncodableValue(zoom_)); + list.push_back(EncodableValue(tilt_)); + list.push_back(EncodableValue(bearing_)); + return list; +} + +MapCamera MapCamera::FromEncodableList(const EncodableList& list) { + MapCamera decoded( + std::any_cast(std::get(list[0])), + std::get(list[1]), + std::get(list[2]), + std::get(list[3])); + return decoded; +} + PigeonInternalCodecSerializer::PigeonInternalCodecSerializer() {} @@ -273,6 +354,9 @@ EncodableValue PigeonInternalCodecSerializer::ReadValueOfType( case 131: { return CustomEncodableValue(ScreenLocation::FromEncodableList(std::get(ReadValue(stream)))); } + case 132: { + return CustomEncodableValue(MapCamera::FromEncodableList(std::get(ReadValue(stream)))); + } default: return flutter::StandardCodecSerializer::ReadValueOfType(type, stream); } @@ -297,6 +381,11 @@ void PigeonInternalCodecSerializer::WriteValue( WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); return; } + if (custom_value->type() == typeid(MapCamera)) { + stream->WriteByte(132); + WriteValue(EncodableValue(std::any_cast(*custom_value).ToEncodableList()), stream); + return; + } } flutter::StandardCodecSerializer::WriteValue(value, stream); } @@ -386,6 +475,28 @@ void MapLibreHostApi::SetUp( channel.SetMessageHandler(nullptr); } } + { + BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.maplibre.MapLibreHostApi.getCamera" + prepended_suffix, &GetCodec()); + if (api != nullptr) { + channel.SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply& reply) { + try { + api->GetCamera([reply](ErrorOr&& output) { + if (output.has_error()) { + reply(WrapError(output.error())); + return; + } + EncodableList wrapped; + wrapped.push_back(CustomEncodableValue(std::move(output).TakeValue())); + reply(EncodableValue(std::move(wrapped))); + }); + } catch (const std::exception& exception) { + reply(WrapError(exception.what())); + } + }); + } else { + channel.SetMessageHandler(nullptr); + } + } { BasicMessageChannel<> channel(binary_messenger, "dev.flutter.pigeon.maplibre.MapLibreHostApi.toScreenLocation" + prepended_suffix, &GetCodec()); if (api != nullptr) { diff --git a/windows/runner/pigeon.g.h b/windows/runner/pigeon.g.h index ba1abb36..26ab9754 100644 --- a/windows/runner/pigeon.g.h +++ b/windows/runner/pigeon.g.h @@ -134,7 +134,7 @@ class MapOptions { }; -// A longitude/latitude coordinate object +// A longitude/latitude coordinate object. // // Generated class from Pigeon that represents data sent in messages. class LngLat { @@ -157,6 +157,7 @@ class LngLat { static LngLat FromEncodableList(const flutter::EncodableList& list); flutter::EncodableList ToEncodableList() const; friend class MapOptions; + friend class MapCamera; friend class MapLibreHostApi; friend class MapLibreFlutterApi; friend class PigeonInternalCodecSerializer; @@ -166,7 +167,7 @@ class LngLat { }; -// A pixel location / location on the device screen +// A pixel location / location on the device screen. // // Generated class from Pigeon that represents data sent in messages. class ScreenLocation { @@ -197,6 +198,50 @@ class ScreenLocation { }; +// The current position of the map camera. +// +// Generated class from Pigeon that represents data sent in messages. +class MapCamera { + public: + // Constructs an object setting all fields. + explicit MapCamera( + const LngLat& center, + double zoom, + double tilt, + double bearing); + + ~MapCamera() = default; + MapCamera(const MapCamera& other); + MapCamera& operator=(const MapCamera& other); + MapCamera(MapCamera&& other) = default; + MapCamera& operator=(MapCamera&& other) noexcept = default; + const LngLat& center() const; + void set_center(const LngLat& value_arg); + + double zoom() const; + void set_zoom(double value_arg); + + double tilt() const; + void set_tilt(double value_arg); + + double bearing() const; + void set_bearing(double value_arg); + + + private: + static MapCamera FromEncodableList(const flutter::EncodableList& list); + flutter::EncodableList ToEncodableList() const; + friend class MapLibreHostApi; + friend class MapLibreFlutterApi; + friend class PigeonInternalCodecSerializer; + std::unique_ptr center_; + double zoom_; + double tilt_; + double bearing_; + +}; + + class PigeonInternalCodecSerializer : public flutter::StandardCodecSerializer { public: PigeonInternalCodecSerializer(); @@ -237,6 +282,9 @@ class MapLibreHostApi { const double* pitch, int64_t duration_ms, std::function reply)> result) = 0; + // Get the current camera position with the map center, zoom level, camera + // tilt and map rotation. + virtual void GetCamera(std::function reply)> result) = 0; // Convert a coordinate to a location on the screen. virtual void ToScreenLocation( double lng,