diff --git a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md index 1027affdf24a..fa0ac1051482 100644 --- a/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.6.0 + +* Move MethodChannel code to MethodChannelGoogleMapsFlutter (Flutter Platform Interface) + ## 0.5.25+3 * Rename 'Page' in the example app to avoid type conflict with the Flutter Framework. diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/google_maps_flutter.dart b/packages/google_maps_flutter/google_maps_flutter/lib/google_maps_flutter.dart index 5f3889f7b2f1..a17b30ca6226 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/google_maps_flutter.dart +++ b/packages/google_maps_flutter/google_maps_flutter/lib/google_maps_flutter.dart @@ -13,22 +13,36 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -part 'src/bitmap.dart'; -part 'src/callbacks.dart'; -part 'src/camera.dart'; -part 'src/cap.dart'; -part 'src/circle.dart'; -part 'src/circle_updates.dart'; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:google_maps_flutter_platform_interface/src/method_channel/method_channel_google_maps_flutter.dart'; + +export 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart' + show + ArgumentCallbacks, + ArgumentCallback, + BitmapDescriptor, + CameraPosition, + CameraPositionCallback, + CameraTargetBounds, + CameraUpdate, + Cap, + Circle, + CircleId, + InfoWindow, + JointType, + LatLng, + LatLngBounds, + MapStyleException, + MapType, + Marker, + MarkerId, + MinMaxZoomPreference, + PatternItem, + Polygon, + PolygonId, + Polyline, + PolylineId, + ScreenCoordinate; + part 'src/controller.dart'; part 'src/google_map.dart'; -part 'src/joint_type.dart'; -part 'src/location.dart'; -part 'src/marker.dart'; -part 'src/marker_updates.dart'; -part 'src/pattern_item.dart'; -part 'src/polygon.dart'; -part 'src/polygon_updates.dart'; -part 'src/polyline.dart'; -part 'src/polyline_updates.dart'; -part 'src/screen_coordinate.dart'; -part 'src/ui.dart'; diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart b/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart index 750bb69393e7..c87b2dacb09c 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart +++ b/packages/google_maps_flutter/google_maps_flutter/lib/src/controller.dart @@ -4,14 +4,20 @@ part of google_maps_flutter; +final GoogleMapsFlutterPlatform _googleMapsFlutterPlatform = + GoogleMapsFlutterPlatform.instance; + /// Controller for a single GoogleMap instance running on the host platform. class GoogleMapController { + /// The mapId for this controller + final int mapId; + GoogleMapController._( - this.channel, CameraPosition initialCameraPosition, - this._googleMapState, - ) : assert(channel != null) { - channel.setMethodCallHandler(_handleMethodCall); + this._googleMapState, { + @required this.mapId, + }) : assert(_googleMapsFlutterPlatform != null) { + _connectStreams(mapId); } /// Initialize control of a [GoogleMap] with [id]. @@ -24,72 +30,66 @@ class GoogleMapController { _GoogleMapState googleMapState, ) async { assert(id != null); - final MethodChannel channel = - MethodChannel('plugins.flutter.io/google_maps_$id'); - await channel.invokeMethod('map#waitForMap'); + await _googleMapsFlutterPlatform.init(id); return GoogleMapController._( - channel, initialCameraPosition, googleMapState, + mapId: id, ); } /// Used to communicate with the native platform. /// /// Accessible only for testing. + // TODO: Remove this once tests are migrated to not need this. @visibleForTesting - final MethodChannel channel; + MethodChannel get channel { + if (_googleMapsFlutterPlatform is MethodChannelGoogleMapsFlutter) { + return (_googleMapsFlutterPlatform as MethodChannelGoogleMapsFlutter) + .channel(mapId); + } + return null; + } final _GoogleMapState _googleMapState; - Future _handleMethodCall(MethodCall call) async { - switch (call.method) { - case 'camera#onMoveStarted': - if (_googleMapState.widget.onCameraMoveStarted != null) { - _googleMapState.widget.onCameraMoveStarted(); - } - break; - case 'camera#onMove': - if (_googleMapState.widget.onCameraMove != null) { - _googleMapState.widget.onCameraMove( - CameraPosition.fromMap(call.arguments['position']), - ); - } - break; - case 'camera#onIdle': - if (_googleMapState.widget.onCameraIdle != null) { - _googleMapState.widget.onCameraIdle(); - } - break; - case 'marker#onTap': - _googleMapState.onMarkerTap(call.arguments['markerId']); - break; - case 'marker#onDragEnd': - _googleMapState.onMarkerDragEnd(call.arguments['markerId'], - LatLng._fromJson(call.arguments['position'])); - break; - case 'infoWindow#onTap': - _googleMapState.onInfoWindowTap(call.arguments['markerId']); - break; - case 'polyline#onTap': - _googleMapState.onPolylineTap(call.arguments['polylineId']); - break; - case 'polygon#onTap': - _googleMapState.onPolygonTap(call.arguments['polygonId']); - break; - case 'circle#onTap': - _googleMapState.onCircleTap(call.arguments['circleId']); - break; - case 'map#onTap': - _googleMapState.onTap(LatLng._fromJson(call.arguments['position'])); - break; - case 'map#onLongPress': - _googleMapState - .onLongPress(LatLng._fromJson(call.arguments['position'])); - break; - default: - throw MissingPluginException(); + void _connectStreams(int mapId) { + if (_googleMapState.widget.onCameraMoveStarted != null) { + _googleMapsFlutterPlatform + .onCameraMoveStarted(mapId: mapId) + .listen((_) => _googleMapState.widget.onCameraMoveStarted()); } + if (_googleMapState.widget.onCameraMove != null) { + _googleMapsFlutterPlatform.onCameraMove(mapId: mapId).listen( + (CameraMoveEvent e) => _googleMapState.widget.onCameraMove(e.value)); + } + if (_googleMapState.widget.onCameraIdle != null) { + _googleMapsFlutterPlatform + .onCameraIdle(mapId: mapId) + .listen((_) => _googleMapState.widget.onCameraIdle()); + } + _googleMapsFlutterPlatform + .onMarkerTap(mapId: mapId) + .listen((MarkerTapEvent e) => _googleMapState.onMarkerTap(e.value)); + _googleMapsFlutterPlatform.onMarkerDragEnd(mapId: mapId).listen( + (MarkerDragEndEvent e) => + _googleMapState.onMarkerDragEnd(e.value, e.position)); + _googleMapsFlutterPlatform.onInfoWindowTap(mapId: mapId).listen( + (InfoWindowTapEvent e) => _googleMapState.onInfoWindowTap(e.value)); + _googleMapsFlutterPlatform + .onPolylineTap(mapId: mapId) + .listen((PolylineTapEvent e) => _googleMapState.onPolylineTap(e.value)); + _googleMapsFlutterPlatform + .onPolygonTap(mapId: mapId) + .listen((PolygonTapEvent e) => _googleMapState.onPolygonTap(e.value)); + _googleMapsFlutterPlatform + .onCircleTap(mapId: mapId) + .listen((CircleTapEvent e) => _googleMapState.onCircleTap(e.value)); + _googleMapsFlutterPlatform + .onTap(mapId: mapId) + .listen((MapTapEvent e) => _googleMapState.onTap(e.position)); + _googleMapsFlutterPlatform.onLongPress(mapId: mapId).listen( + (MapLongPressEvent e) => _googleMapState.onLongPress(e.position)); } /// Updates configuration options of the map user interface. @@ -98,14 +98,10 @@ class GoogleMapController { /// platform side. /// /// The returned [Future] completes after listeners have been notified. - Future _updateMapOptions(Map optionsUpdate) async { + Future _updateMapOptions(Map optionsUpdate) { assert(optionsUpdate != null); - await channel.invokeMethod( - 'map#update', - { - 'options': optionsUpdate, - }, - ); + return _googleMapsFlutterPlatform.updateMapOptions(optionsUpdate, + mapId: mapId); } /// Updates marker configuration. @@ -114,12 +110,10 @@ class GoogleMapController { /// platform side. /// /// The returned [Future] completes after listeners have been notified. - Future _updateMarkers(_MarkerUpdates markerUpdates) async { + Future _updateMarkers(MarkerUpdates markerUpdates) { assert(markerUpdates != null); - await channel.invokeMethod( - 'markers#update', - markerUpdates._toMap(), - ); + return _googleMapsFlutterPlatform.updateMarkers(markerUpdates, + mapId: mapId); } /// Updates polygon configuration. @@ -128,12 +122,10 @@ class GoogleMapController { /// platform side. /// /// The returned [Future] completes after listeners have been notified. - Future _updatePolygons(_PolygonUpdates polygonUpdates) async { + Future _updatePolygons(PolygonUpdates polygonUpdates) { assert(polygonUpdates != null); - await channel.invokeMethod( - 'polygons#update', - polygonUpdates._toMap(), - ); + return _googleMapsFlutterPlatform.updatePolygons(polygonUpdates, + mapId: mapId); } /// Updates polyline configuration. @@ -142,12 +134,10 @@ class GoogleMapController { /// platform side. /// /// The returned [Future] completes after listeners have been notified. - Future _updatePolylines(_PolylineUpdates polylineUpdates) async { + Future _updatePolylines(PolylineUpdates polylineUpdates) { assert(polylineUpdates != null); - await channel.invokeMethod( - 'polylines#update', - polylineUpdates._toMap(), - ); + return _googleMapsFlutterPlatform.updatePolylines(polylineUpdates, + mapId: mapId); } /// Updates circle configuration. @@ -156,32 +146,26 @@ class GoogleMapController { /// platform side. /// /// The returned [Future] completes after listeners have been notified. - Future _updateCircles(_CircleUpdates circleUpdates) async { + Future _updateCircles(CircleUpdates circleUpdates) { assert(circleUpdates != null); - await channel.invokeMethod( - 'circles#update', - circleUpdates._toMap(), - ); + return _googleMapsFlutterPlatform.updateCircles(circleUpdates, + mapId: mapId); } /// Starts an animated change of the map camera position. /// /// The returned [Future] completes after the change has been started on the /// platform side. - Future animateCamera(CameraUpdate cameraUpdate) async { - await channel.invokeMethod('camera#animate', { - 'cameraUpdate': cameraUpdate._toJson(), - }); + Future animateCamera(CameraUpdate cameraUpdate) { + return _googleMapsFlutterPlatform.animateCamera(cameraUpdate, mapId: mapId); } /// Changes the map camera position. /// /// The returned [Future] completes after the change has been made on the /// platform side. - Future moveCamera(CameraUpdate cameraUpdate) async { - await channel.invokeMethod('camera#move', { - 'cameraUpdate': cameraUpdate._toJson(), - }); + Future moveCamera(CameraUpdate cameraUpdate) { + return _googleMapsFlutterPlatform.moveCamera(cameraUpdate, mapId: mapId); } /// Sets the styling of the base map. @@ -197,23 +181,13 @@ class GoogleMapController { /// Also, refer [iOS](https://developers.google.com/maps/documentation/ios-sdk/style-reference) /// and [Android](https://developers.google.com/maps/documentation/android-sdk/style-reference) /// style reference for more information regarding the supported styles. - Future setMapStyle(String mapStyle) async { - final List successAndError = - await channel.invokeMethod>('map#setStyle', mapStyle); - final bool success = successAndError[0]; - if (!success) { - throw MapStyleException(successAndError[1]); - } + Future setMapStyle(String mapStyle) { + return _googleMapsFlutterPlatform.setMapStyle(mapStyle, mapId: mapId); } /// Return [LatLngBounds] defining the region that is visible in a map. - Future getVisibleRegion() async { - final Map latLngBounds = - await channel.invokeMapMethod('map#getVisibleRegion'); - final LatLng southwest = LatLng._fromJson(latLngBounds['southwest']); - final LatLng northeast = LatLng._fromJson(latLngBounds['northeast']); - - return LatLngBounds(northeast: northeast, southwest: southwest); + Future getVisibleRegion() { + return _googleMapsFlutterPlatform.getVisibleRegion(mapId: mapId); } /// Return [ScreenCoordinate] of the [LatLng] in the current map view. @@ -221,20 +195,16 @@ class GoogleMapController { /// A projection is used to translate between on screen location and geographic coordinates. /// Screen location is in screen pixels (not display pixels) with respect to the top left corner /// of the map, not necessarily of the whole screen. - Future getScreenCoordinate(LatLng latLng) async { - final Map point = await channel.invokeMapMethod( - 'map#getScreenCoordinate', latLng._toJson()); - return ScreenCoordinate(x: point['x'], y: point['y']); + Future getScreenCoordinate(LatLng latLng) { + return _googleMapsFlutterPlatform.getScreenCoordinate(latLng, mapId: mapId); } /// Returns [LatLng] corresponding to the [ScreenCoordinate] in the current map view. /// /// Returned [LatLng] corresponds to a screen location. The screen location is specified in screen /// pixels (not display pixels) relative to the top left of the map, not top left of the whole screen. - Future getLatLng(ScreenCoordinate screenCoordinate) async { - final List latLng = await channel.invokeMethod>( - 'map#getLatLng', screenCoordinate._toJson()); - return LatLng(latLng[0], latLng[1]); + Future getLatLng(ScreenCoordinate screenCoordinate) { + return _googleMapsFlutterPlatform.getLatLng(screenCoordinate, mapId: mapId); } /// Programmatically show the Info Window for a [Marker]. @@ -245,10 +215,10 @@ class GoogleMapController { /// * See also: /// * [hideMarkerInfoWindow] to hide the Info Window. /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. - Future showMarkerInfoWindow(MarkerId markerId) async { + Future showMarkerInfoWindow(MarkerId markerId) { assert(markerId != null); - await channel.invokeMethod( - 'markers#showInfoWindow', {'markerId': markerId.value}); + return _googleMapsFlutterPlatform.showMarkerInfoWindow(markerId, + mapId: mapId); } /// Programmatically hide the Info Window for a [Marker]. @@ -259,10 +229,10 @@ class GoogleMapController { /// * See also: /// * [showMarkerInfoWindow] to show the Info Window. /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. - Future hideMarkerInfoWindow(MarkerId markerId) async { + Future hideMarkerInfoWindow(MarkerId markerId) { assert(markerId != null); - await channel.invokeMethod( - 'markers#hideInfoWindow', {'markerId': markerId.value}); + return _googleMapsFlutterPlatform.hideMarkerInfoWindow(markerId, + mapId: mapId); } /// Returns `true` when the [InfoWindow] is showing, `false` otherwise. @@ -273,21 +243,19 @@ class GoogleMapController { /// * See also: /// * [showMarkerInfoWindow] to show the Info Window. /// * [hideMarkerInfoWindow] to hide the Info Window. - Future isMarkerInfoWindowShown(MarkerId markerId) async { + Future isMarkerInfoWindowShown(MarkerId markerId) { assert(markerId != null); - return await channel.invokeMethod('markers#isInfoWindowShown', - {'markerId': markerId.value}); + return _googleMapsFlutterPlatform.isMarkerInfoWindowShown(markerId, + mapId: mapId); } /// Returns the current zoom level of the map - Future getZoomLevel() async { - final double zoomLevel = - await channel.invokeMethod('map#getZoomLevel'); - return zoomLevel; + Future getZoomLevel() { + return _googleMapsFlutterPlatform.getZoomLevel(mapId: mapId); } /// Returns the image bytes of the map - Future takeSnapshot() async { - return await channel.invokeMethod('map#takeSnapshot'); + Future takeSnapshot() { + return _googleMapsFlutterPlatform.takeSnapshot(mapId: mapId); } } diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart b/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart index f6a413a82ffb..be15e2238b89 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart +++ b/packages/google_maps_flutter/google_maps_flutter/lib/src/google_map.dart @@ -10,14 +10,6 @@ part of google_maps_flutter; /// map is created. typedef void MapCreatedCallback(GoogleMapController controller); -/// Callback that receives updates to the camera position. -/// -/// This callback is triggered when the platform Google Map -/// registers a camera movement. -/// -/// This is used in [GoogleMap.onCameraMove]. -typedef void CameraPositionCallback(CameraPosition position); - /// A widget which displays a map with data obtained from the Google Maps service. class GoogleMap extends StatefulWidget { /// Creates a widget displaying data from Google Maps services. @@ -214,41 +206,26 @@ class _GoogleMapState extends State { final Map creationParams = { 'initialCameraPosition': widget.initialCameraPosition?.toMap(), 'options': _googleMapOptions.toMap(), - 'markersToAdd': _serializeMarkerSet(widget.markers), - 'polygonsToAdd': _serializePolygonSet(widget.polygons), - 'polylinesToAdd': _serializePolylineSet(widget.polylines), - 'circlesToAdd': _serializeCircleSet(widget.circles), + 'markersToAdd': serializeMarkerSet(widget.markers), + 'polygonsToAdd': serializePolygonSet(widget.polygons), + 'polylinesToAdd': serializePolylineSet(widget.polylines), + 'circlesToAdd': serializeCircleSet(widget.circles), }; - if (defaultTargetPlatform == TargetPlatform.android) { - return AndroidView( - viewType: 'plugins.flutter.io/google_maps', - onPlatformViewCreated: onPlatformViewCreated, - gestureRecognizers: widget.gestureRecognizers, - creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), - ); - } else if (defaultTargetPlatform == TargetPlatform.iOS) { - return UiKitView( - viewType: 'plugins.flutter.io/google_maps', - onPlatformViewCreated: onPlatformViewCreated, - gestureRecognizers: widget.gestureRecognizers, - creationParams: creationParams, - creationParamsCodec: const StandardMessageCodec(), - ); - } - - return Text( - '$defaultTargetPlatform is not yet supported by the maps plugin'); + return _googleMapsFlutterPlatform.buildView( + creationParams, + widget.gestureRecognizers, + onPlatformViewCreated, + ); } @override void initState() { super.initState(); _googleMapOptions = _GoogleMapOptions.fromWidget(widget); - _markers = _keyByMarkerId(widget.markers); - _polygons = _keyByPolygonId(widget.polygons); - _polylines = _keyByPolylineId(widget.polylines); - _circles = _keyByCircleId(widget.circles); + _markers = keyByMarkerId(widget.markers); + _polygons = keyByPolygonId(widget.polygons); + _polylines = keyByPolylineId(widget.polylines); + _circles = keyByCircleId(widget.circles); } @override @@ -278,32 +255,32 @@ class _GoogleMapState extends State { final GoogleMapController controller = await _controller.future; // ignore: unawaited_futures controller._updateMarkers( - _MarkerUpdates.from(_markers.values.toSet(), widget.markers)); - _markers = _keyByMarkerId(widget.markers); + MarkerUpdates.from(_markers.values.toSet(), widget.markers)); + _markers = keyByMarkerId(widget.markers); } void _updatePolygons() async { final GoogleMapController controller = await _controller.future; // ignore: unawaited_futures controller._updatePolygons( - _PolygonUpdates.from(_polygons.values.toSet(), widget.polygons)); - _polygons = _keyByPolygonId(widget.polygons); + PolygonUpdates.from(_polygons.values.toSet(), widget.polygons)); + _polygons = keyByPolygonId(widget.polygons); } void _updatePolylines() async { final GoogleMapController controller = await _controller.future; // ignore: unawaited_futures controller._updatePolylines( - _PolylineUpdates.from(_polylines.values.toSet(), widget.polylines)); - _polylines = _keyByPolylineId(widget.polylines); + PolylineUpdates.from(_polylines.values.toSet(), widget.polylines)); + _polylines = keyByPolylineId(widget.polylines); } void _updateCircles() async { final GoogleMapController controller = await _controller.future; // ignore: unawaited_futures controller._updateCircles( - _CircleUpdates.from(_circles.values.toSet(), widget.circles)); - _circles = _keyByCircleId(widget.circles); + CircleUpdates.from(_circles.values.toSet(), widget.circles)); + _circles = keyByCircleId(widget.circles); } Future onPlatformViewCreated(int id) async { @@ -318,45 +295,39 @@ class _GoogleMapState extends State { } } - void onMarkerTap(String markerIdParam) { - assert(markerIdParam != null); - final MarkerId markerId = MarkerId(markerIdParam); + void onMarkerTap(MarkerId markerId) { + assert(markerId != null); if (_markers[markerId]?.onTap != null) { _markers[markerId].onTap(); } } - void onMarkerDragEnd(String markerIdParam, LatLng position) { - assert(markerIdParam != null); - final MarkerId markerId = MarkerId(markerIdParam); + void onMarkerDragEnd(MarkerId markerId, LatLng position) { + assert(markerId != null); if (_markers[markerId]?.onDragEnd != null) { _markers[markerId].onDragEnd(position); } } - void onPolygonTap(String polygonIdParam) { - assert(polygonIdParam != null); - final PolygonId polygonId = PolygonId(polygonIdParam); + void onPolygonTap(PolygonId polygonId) { + assert(polygonId != null); _polygons[polygonId].onTap(); } - void onPolylineTap(String polylineIdParam) { - assert(polylineIdParam != null); - final PolylineId polylineId = PolylineId(polylineIdParam); + void onPolylineTap(PolylineId polylineId) { + assert(polylineId != null); if (_polylines[polylineId]?.onTap != null) { _polylines[polylineId].onTap(); } } - void onCircleTap(String circleIdParam) { - assert(circleIdParam != null); - final CircleId circleId = CircleId(circleIdParam); + void onCircleTap(CircleId circleId) { + assert(circleId != null); _circles[circleId].onTap(); } - void onInfoWindowTap(String markerIdParam) { - assert(markerIdParam != null); - final MarkerId markerId = MarkerId(markerIdParam); + void onInfoWindowTap(MarkerId markerId) { + assert(markerId != null); if (_markers[markerId]?.infoWindow?.onTap != null) { _markers[markerId].infoWindow.onTap(); } @@ -465,9 +436,9 @@ class _GoogleMapOptions { addIfNonNull('compassEnabled', compassEnabled); addIfNonNull('mapToolbarEnabled', mapToolbarEnabled); - addIfNonNull('cameraTargetBounds', cameraTargetBounds?._toJson()); + addIfNonNull('cameraTargetBounds', cameraTargetBounds?.toJson()); addIfNonNull('mapType', mapType?.index); - addIfNonNull('minMaxZoomPreference', minMaxZoomPreference?._toJson()); + addIfNonNull('minMaxZoomPreference', minMaxZoomPreference?.toJson()); addIfNonNull('rotateGesturesEnabled', rotateGesturesEnabled); addIfNonNull('scrollGesturesEnabled', scrollGesturesEnabled); addIfNonNull('tiltGesturesEnabled', tiltGesturesEnabled); diff --git a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml index 0f88a9a0ad18..58f0439cd01f 100644 --- a/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter/pubspec.yaml @@ -1,12 +1,14 @@ name: google_maps_flutter description: A Flutter plugin for integrating Google Maps in iOS and Android applications. homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter -version: 0.5.25+3 +version: 0.6.0 dependencies: flutter: sdk: flutter flutter_plugin_android_lifecycle: ^1.0.0 + google_maps_flutter_platform_interface: + path: ../google_maps_flutter_platform_interface dev_dependencies: flutter_test: @@ -27,6 +29,8 @@ flutter: pluginClass: GoogleMapsPlugin ios: pluginClass: FLTGoogleMapsPlugin + web: + default_package: google_maps_flutter_web environment: sdk: ">=2.0.0-dev.47.0 <3.0.0" diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md new file mode 100644 index 000000000000..0d8803f93540 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +* Initial release. diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/LICENSE b/packages/google_maps_flutter/google_maps_flutter_platform_interface/LICENSE new file mode 100644 index 000000000000..8940a4be1b58 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/README.md b/packages/google_maps_flutter/google_maps_flutter_platform_interface/README.md new file mode 100644 index 000000000000..6489ba39cbd8 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/README.md @@ -0,0 +1,26 @@ +# google_maps_flutter_platform_interface + +A common platform interface for the [`google_maps_flutter`][1] plugin. + +This interface allows platform-specific implementations of the `google_maps_flutter` +plugin, as well as the plugin itself, to ensure they are supporting the +same interface. + +# Usage + +To implement a new platform-specific implementation of `google_maps_flutter`, extend +[`GoogleMapsFlutterPlatform`][2] with an implementation that performs the +platform-specific behavior, and when you register your plugin, set the default +`GoogleMapsFlutterPlatform` by calling +`GoogleMapsFlutterPlatform.instance = MyPlatformGoogleMapsFlutter()`. + +# Note on breaking changes + +Strongly prefer non-breaking changes (such as adding a method to the interface) +over breaking changes for this package. + +See https://flutter.dev/go/platform-interface-breaking-changes for a discussion +on why a less-clean interface is preferable to a breaking change. + +[1]: ../google_maps_flutter +[2]: lib/google_maps_flutter_platform_interface.dart diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart new file mode 100644 index 000000000000..cb28b40470fd --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/google_maps_flutter_platform_interface.dart @@ -0,0 +1,7 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export 'src/platform_interface/google_maps_flutter_platform.dart'; +export 'src/types/types.dart'; +export 'src/events/map_event.dart'; diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/events/map_event.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/events/map_event.dart new file mode 100644 index 000000000000..c462b4b182e2 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/events/map_event.dart @@ -0,0 +1,153 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:google_maps_flutter_platform_interface/src/method_channel/method_channel_google_maps_flutter.dart'; + +/// Generic Event coming from the native side of Maps. +/// +/// All MapEvents contain the `mapId` that originated the event. This should +/// never be `null`. +/// +/// The `` on this event represents the type of the `value` that is +/// contained within the event. +/// +/// This class is used as a base class for all the events that might be +/// triggered from a Map, but it is never used directly as an event type. +/// +/// Do NOT instantiate new events like `MapEvent(mapId, val)` directly, +/// use a specific class instead: +/// +/// Do `class NewEvent extend MapEvent` when creating your own events. +/// See below for examples: `CameraMoveStartedEvent`, `MarkerDragEndEvent`... +/// These events are more semantic and pleasant to use than raw generics. They +/// can be (and in fact, are) filtered by the `instanceof`-operator. +/// +/// (See [MethodChannelGoogleMapsFlutter.onCameraMoveStarted], for example) +/// +/// If your event needs a `position`, alongside the `value`, do +/// `extends _PositionedMapEvent` instead. This adds a `LatLng position` +/// attribute. +/// +/// If your event *only* needs a `position`, do `extend _PositionedMapEvent` +/// do NOT `extend MapEvent`. The former lets consumers of these +/// events to access the `.position` property, rather than the more generic `.value` +/// yielded from the latter. +class MapEvent { + /// The ID of the Map this event is associated to. + final int mapId; + + /// The value wrapped by this event + final T value; + + /// Build a Map Event, that relates a mapId with a given value. + /// + /// The `mapId` is the id of the map that triggered the event. + /// `value` may be `null` in events that don't transport any meaningful data. + MapEvent(this.mapId, this.value); +} + +/// A `MapEvent` associated to a `position`. +class _PositionedMapEvent extends MapEvent { + /// The position where this event happened. + final LatLng position; + + /// Build a Positioned MapEvent, that relates a mapId and a position with a value. + /// + /// The `mapId` is the id of the map that triggered the event. + /// `value` may be `null` in events that don't transport any meaningful data. + _PositionedMapEvent(int mapId, this.position, T value) : super(mapId, value); +} + +// The following events are the ones exposed to the end user. They are semantic extensions +// of the two base classes above. +// +// These events are used to create the appropriate [Stream] objects, with information +// coming from the native side. + +/// An event fired when the Camera of a [mapId] starts moving. +class CameraMoveStartedEvent extends MapEvent { + /// Build a CameraMoveStarted Event triggered from the map represented by `mapId`. + CameraMoveStartedEvent(int mapId) : super(mapId, null); +} + +/// An event fired while the Camera of a [mapId] moves. +class CameraMoveEvent extends MapEvent { + /// Build a CameraMove Event triggered from the map represented by `mapId`. + /// + /// The `value` of this event is a [CameraPosition] object with the current position of the Camera. + CameraMoveEvent(int mapId, CameraPosition position) : super(mapId, position); +} + +/// An event fired when the Camera of a [mapId] becomes idle. +class CameraIdleEvent extends MapEvent { + /// Build a CameraIdle Event triggered from the map represented by `mapId`. + CameraIdleEvent(int mapId) : super(mapId, null); +} + +/// An event fired when a [Marker] is tapped. +class MarkerTapEvent extends MapEvent { + /// Build a MarkerTap Event triggered from the map represented by `mapId`. + /// + /// The `value` of this event is a [MarkerId] object that represents the tapped Marker. + MarkerTapEvent(int mapId, MarkerId markerId) : super(mapId, markerId); +} + +/// An event fired when an [InfoWindow] is tapped. +class InfoWindowTapEvent extends MapEvent { + /// Build an InfoWindowTap Event triggered from the map represented by `mapId`. + /// + /// The `value` of this event is a [MarkerId] object that represents the tapped InfoWindow. + InfoWindowTapEvent(int mapId, MarkerId markerId) : super(mapId, markerId); +} + +/// An event fired when a [Marker] is dragged to a new [LatLng]. +class MarkerDragEndEvent extends _PositionedMapEvent { + /// Build a MarkerDragEnd Event triggered from the map represented by `mapId`. + /// + /// The `position` on this event is the [LatLng] on which the Marker was dropped. + /// The `value` of this event is a [MarkerId] object that represents the moved Marker. + MarkerDragEndEvent(int mapId, LatLng position, MarkerId markerId) + : super(mapId, position, markerId); +} + +/// An event fired when a [Polyline] is tapped. +class PolylineTapEvent extends MapEvent { + /// Build an PolylineTap Event triggered from the map represented by `mapId`. + /// + /// The `value` of this event is a [PolylineId] object that represents the tapped Polyline. + PolylineTapEvent(int mapId, PolylineId polylineId) : super(mapId, polylineId); +} + +/// An event fired when a [Polygon] is tapped. +class PolygonTapEvent extends MapEvent { + /// Build an PolygonTap Event triggered from the map represented by `mapId`. + /// + /// The `value` of this event is a [PolygonId] object that represents the tapped Polygon. + PolygonTapEvent(int mapId, PolygonId polygonId) : super(mapId, polygonId); +} + +/// An event fired when a [Circle] is tapped. +class CircleTapEvent extends MapEvent { + /// Build an CircleTap Event triggered from the map represented by `mapId`. + /// + /// The `value` of this event is a [CircleId] object that represents the tapped Circle. + CircleTapEvent(int mapId, CircleId circleId) : super(mapId, circleId); +} + +/// An event fired when a Map is tapped. +class MapTapEvent extends _PositionedMapEvent { + /// Build an MapTap Event triggered from the map represented by `mapId`. + /// + /// The `position` of this event is the LatLng where the Map was tapped. + MapTapEvent(int mapId, LatLng position) : super(mapId, position, null); +} + +/// An event fired when a Map is long pressed. +class MapLongPressEvent extends _PositionedMapEvent { + /// Build an MapTap Event triggered from the map represented by `mapId`. + /// + /// The `position` of this event is the LatLng where the Map was long pressed. + MapLongPressEvent(int mapId, LatLng position) : super(mapId, position, null); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart new file mode 100644 index 000000000000..edbc51ab5afd --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/method_channel/method_channel_google_maps_flutter.dart @@ -0,0 +1,477 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/gestures.dart'; + +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:stream_transform/stream_transform.dart'; + +/// An implementation of [GoogleMapsFlutterPlatform] that uses [MethodChannel] to communicate with the native code. +/// +/// The `google_maps_flutter` plugin code itself never talks to the native code directly. It delegates +/// all those calls to an instance of a class that extends the GoogleMapsFlutterPlatform. +/// +/// The architecture above allows for platforms that communicate differently with the native side +/// (like web) to have a common interface to extend. +/// +/// This is the instance that runs when the native side talks to your Flutter app through MethodChannels, +/// like the Android and iOS platforms. +class MethodChannelGoogleMapsFlutter extends GoogleMapsFlutterPlatform { + // Keep a collection of id -> channel + // Every method call passes the int mapId + final Map _channels = {}; + + /// Accesses the MethodChannel associated to the passed mapId. + MethodChannel channel(int mapId) { + return _channels[mapId]; + } + + /// Initializes the platform interface with [id]. + /// + /// This method is called when the plugin is first initialized. + @override + Future init(int mapId) { + MethodChannel channel; + if (!_channels.containsKey(mapId)) { + channel = MethodChannel('plugins.flutter.io/google_maps_$mapId'); + channel.setMethodCallHandler( + (MethodCall call) => _handleMethodCall(call, mapId)); + _channels[mapId] = channel; + } + return channel.invokeMethod('map#waitForMap'); + } + + // The controller we need to broadcast the different events coming + // from handleMethodCall. + // + // It is a `broadcast` because multiple controllers will connect to + // different stream views of this Controller. + final StreamController _mapEventStreamController = + StreamController.broadcast(); + + // Returns a filtered view of the events in the _controller, by mapId. + Stream _events(int mapId) => + _mapEventStreamController.stream.where((event) => event.mapId == mapId); + + @override + Stream onCameraMoveStarted({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onCameraMove({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onCameraIdle({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onMarkerTap({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onInfoWindowTap({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onMarkerDragEnd({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onPolylineTap({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onPolygonTap({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onCircleTap({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onTap({@required int mapId}) { + return _events(mapId).whereType(); + } + + @override + Stream onLongPress({@required int mapId}) { + return _events(mapId).whereType(); + } + + Future _handleMethodCall(MethodCall call, int mapId) async { + switch (call.method) { + case 'camera#onMoveStarted': + _mapEventStreamController.add(CameraMoveStartedEvent(mapId)); + break; + case 'camera#onMove': + _mapEventStreamController.add(CameraMoveEvent( + mapId, + CameraPosition.fromMap(call.arguments['position']), + )); + break; + case 'camera#onIdle': + _mapEventStreamController.add(CameraIdleEvent(mapId)); + break; + case 'marker#onTap': + _mapEventStreamController.add(MarkerTapEvent( + mapId, + MarkerId(call.arguments['markerId']), + )); + break; + case 'marker#onDragEnd': + _mapEventStreamController.add(MarkerDragEndEvent( + mapId, + LatLng.fromJson(call.arguments['position']), + MarkerId(call.arguments['markerId']), + )); + break; + case 'infoWindow#onTap': + _mapEventStreamController.add(InfoWindowTapEvent( + mapId, + MarkerId(call.arguments['markerId']), + )); + break; + case 'polyline#onTap': + _mapEventStreamController.add(PolylineTapEvent( + mapId, + PolylineId(call.arguments['polylineId']), + )); + break; + case 'polygon#onTap': + _mapEventStreamController.add(PolygonTapEvent( + mapId, + PolygonId(call.arguments['polygonId']), + )); + break; + case 'circle#onTap': + _mapEventStreamController.add(CircleTapEvent( + mapId, + CircleId(call.arguments['circleId']), + )); + break; + case 'map#onTap': + _mapEventStreamController.add(MapTapEvent( + mapId, + LatLng.fromJson(call.arguments['position']), + )); + break; + case 'map#onLongPress': + _mapEventStreamController.add(MapLongPressEvent( + mapId, + LatLng.fromJson(call.arguments['position']), + )); + break; + default: + throw MissingPluginException(); + } + } + + /// Updates configuration options of the map user interface. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + @override + Future updateMapOptions( + Map optionsUpdate, { + @required int mapId, + }) { + assert(optionsUpdate != null); + return channel(mapId).invokeMethod( + 'map#update', + { + 'options': optionsUpdate, + }, + ); + } + + /// Updates marker configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + @override + Future updateMarkers( + MarkerUpdates markerUpdates, { + @required int mapId, + }) { + assert(markerUpdates != null); + return channel(mapId).invokeMethod( + 'markers#update', + markerUpdates.toJson(), + ); + } + + /// Updates polygon configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + @override + Future updatePolygons( + PolygonUpdates polygonUpdates, { + @required int mapId, + }) { + assert(polygonUpdates != null); + return channel(mapId).invokeMethod( + 'polygons#update', + polygonUpdates.toJson(), + ); + } + + /// Updates polyline configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + @override + Future updatePolylines( + PolylineUpdates polylineUpdates, { + @required int mapId, + }) { + assert(polylineUpdates != null); + return channel(mapId).invokeMethod( + 'polylines#update', + polylineUpdates.toJson(), + ); + } + + /// Updates circle configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + @override + Future updateCircles( + CircleUpdates circleUpdates, { + @required int mapId, + }) { + assert(circleUpdates != null); + return channel(mapId).invokeMethod( + 'circles#update', + circleUpdates.toJson(), + ); + } + + /// Starts an animated change of the map camera position. + /// + /// The returned [Future] completes after the change has been started on the + /// platform side. + @override + Future animateCamera( + CameraUpdate cameraUpdate, { + @required int mapId, + }) { + return channel(mapId) + .invokeMethod('camera#animate', { + 'cameraUpdate': cameraUpdate.toJson(), + }); + } + + /// Changes the map camera position. + /// + /// The returned [Future] completes after the change has been made on the + /// platform side. + @override + Future moveCamera( + CameraUpdate cameraUpdate, { + @required int mapId, + }) { + return channel(mapId).invokeMethod('camera#move', { + 'cameraUpdate': cameraUpdate.toJson(), + }); + } + + /// Sets the styling of the base map. + /// + /// Set to `null` to clear any previous custom styling. + /// + /// If problems were detected with the [mapStyle], including un-parsable + /// styling JSON, unrecognized feature type, unrecognized element type, or + /// invalid styler keys: [MapStyleException] is thrown and the current + /// style is left unchanged. + /// + /// The style string can be generated using [map style tool](https://mapstyle.withgoogle.com/). + /// Also, refer [iOS](https://developers.google.com/maps/documentation/ios-sdk/style-reference) + /// and [Android](https://developers.google.com/maps/documentation/android-sdk/style-reference) + /// style reference for more information regarding the supported styles. + @override + Future setMapStyle( + String mapStyle, { + @required int mapId, + }) async { + final List successAndError = await channel(mapId) + .invokeMethod>('map#setStyle', mapStyle); + final bool success = successAndError[0]; + if (!success) { + throw MapStyleException(successAndError[1]); + } + } + + /// Return the region that is visible in a map. + @override + Future getVisibleRegion({ + @required int mapId, + }) async { + final Map latLngBounds = await channel(mapId) + .invokeMapMethod('map#getVisibleRegion'); + final LatLng southwest = LatLng.fromJson(latLngBounds['southwest']); + final LatLng northeast = LatLng.fromJson(latLngBounds['northeast']); + + return LatLngBounds(northeast: northeast, southwest: southwest); + } + + /// Return point [Map] of the [screenCoordinateInJson] in the current map view. + /// + /// A projection is used to translate between on screen location and geographic coordinates. + /// Screen location is in screen pixels (not display pixels) with respect to the top left corner + /// of the map, not necessarily of the whole screen. + @override + Future getScreenCoordinate( + LatLng latLng, { + @required int mapId, + }) async { + final Map point = await channel(mapId) + .invokeMapMethod( + 'map#getScreenCoordinate', latLng.toJson()); + + return ScreenCoordinate(x: point['x'], y: point['y']); + } + + /// Returns [LatLng] corresponding to the [ScreenCoordinate] in the current map view. + /// + /// Returned [LatLng] corresponds to a screen location. The screen location is specified in screen + /// pixels (not display pixels) relative to the top left of the map, not top left of the whole screen. + @override + Future getLatLng( + ScreenCoordinate screenCoordinate, { + @required int mapId, + }) async { + final List latLng = await channel(mapId) + .invokeMethod>( + 'map#getLatLng', screenCoordinate.toJson()); + return LatLng(latLng[0], latLng[1]); + } + + /// Programmatically show the Info Window for a [Marker]. + /// + /// The `markerId` must match one of the markers on the map. + /// An invalid `markerId` triggers an "Invalid markerId" error. + /// + /// * See also: + /// * [hideMarkerInfoWindow] to hide the Info Window. + /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. + @override + Future showMarkerInfoWindow( + MarkerId markerId, { + @required int mapId, + }) { + assert(markerId != null); + return channel(mapId).invokeMethod( + 'markers#showInfoWindow', {'markerId': markerId.value}); + } + + /// Programmatically hide the Info Window for a [Marker]. + /// + /// The `markerId` must match one of the markers on the map. + /// An invalid `markerId` triggers an "Invalid markerId" error. + /// + /// * See also: + /// * [showMarkerInfoWindow] to show the Info Window. + /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. + @override + Future hideMarkerInfoWindow( + MarkerId markerId, { + @required int mapId, + }) { + assert(markerId != null); + return channel(mapId).invokeMethod( + 'markers#hideInfoWindow', {'markerId': markerId.value}); + } + + /// Returns `true` when the [InfoWindow] is showing, `false` otherwise. + /// + /// The `markerId` must match one of the markers on the map. + /// An invalid `markerId` triggers an "Invalid markerId" error. + /// + /// * See also: + /// * [showMarkerInfoWindow] to show the Info Window. + /// * [hideMarkerInfoWindow] to hide the Info Window. + @override + Future isMarkerInfoWindowShown( + MarkerId markerId, { + @required int mapId, + }) { + assert(markerId != null); + return channel(mapId).invokeMethod('markers#isInfoWindowShown', + {'markerId': markerId.value}); + } + + /// Returns the current zoom level of the map + @override + Future getZoomLevel({ + @required int mapId, + }) { + return channel(mapId).invokeMethod('map#getZoomLevel'); + } + + /// Returns the image bytes of the map + @override + Future takeSnapshot({ + @required int mapId, + }) { + return channel(mapId).invokeMethod('map#takeSnapshot'); + } + + /// This method builds the appropriate platform view where the map + /// can be rendered. + /// The `mapId` is passed as a parameter from the framework on the + /// `onPlatformViewCreated` callback. + @override + Widget buildView( + Map creationParams, + Set> gestureRecognizers, + PlatformViewCreatedCallback onPlatformViewCreated) { + if (defaultTargetPlatform == TargetPlatform.android) { + return AndroidView( + viewType: 'plugins.flutter.io/google_maps', + onPlatformViewCreated: onPlatformViewCreated, + gestureRecognizers: gestureRecognizers, + creationParams: creationParams, + creationParamsCodec: const StandardMessageCodec(), + ); + } else if (defaultTargetPlatform == TargetPlatform.iOS) { + return UiKitView( + viewType: 'plugins.flutter.io/google_maps', + onPlatformViewCreated: onPlatformViewCreated, + gestureRecognizers: gestureRecognizers, + creationParams: creationParams, + creationParamsCodec: const StandardMessageCodec(), + ); + } + return Text( + '$defaultTargetPlatform is not yet supported by the maps plugin'); + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart new file mode 100644 index 000000000000..b89d3420c68e --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/platform_interface/google_maps_flutter_platform.dart @@ -0,0 +1,314 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:typed_data'; + +import 'package:flutter/widgets.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; + +import 'package:google_maps_flutter_platform_interface/src/method_channel/method_channel_google_maps_flutter.dart'; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +/// The interface that platform-specific implementations of `google_maps_flutter` must extend. +/// +/// Avoid `implements` of this interface. Using `implements` makes adding any new +/// methods here a breaking change for end users of your platform! +/// +/// Do `extends GoogleMapsFlutterPlatform` instead, so new methods added here are +/// inherited in your code with the default implementation (that throws at runtime), +/// rather than breaking your users at compile time. +abstract class GoogleMapsFlutterPlatform extends PlatformInterface { + /// Constructs a GoogleMapsFlutterPlatform. + GoogleMapsFlutterPlatform() : super(token: _token); + + static final Object _token = Object(); + + static GoogleMapsFlutterPlatform _instance = MethodChannelGoogleMapsFlutter(); + + /// The default instance of [GoogleMapsFlutterPlatform] to use. + /// + /// Defaults to [MethodChannelGoogleMapsFlutter]. + static GoogleMapsFlutterPlatform get instance => _instance; + + /// Platform-specific plugins should set this with their own platform-specific + /// class that extends [GoogleMapsFlutterPlatform] when they register themselves. + static set instance(GoogleMapsFlutterPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + /// /// Initializes the platform interface with [id]. + /// + /// This method is called when the plugin is first initialized. + Future init(int mapId) { + throw UnimplementedError('init() has not been implemented.'); + } + + /// Updates configuration options of the map user interface. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + Future updateMapOptions( + Map optionsUpdate, { + @required int mapId, + }) { + throw UnimplementedError('updateMapOptions() has not been implemented.'); + } + + /// Updates marker configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + Future updateMarkers( + MarkerUpdates markerUpdates, { + @required int mapId, + }) { + throw UnimplementedError('updateMarkers() has not been implemented.'); + } + + /// Updates polygon configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + Future updatePolygons( + PolygonUpdates polygonUpdates, { + @required int mapId, + }) { + throw UnimplementedError('updatePolygons() has not been implemented.'); + } + + /// Updates polyline configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + Future updatePolylines( + PolylineUpdates polylineUpdates, { + @required int mapId, + }) { + throw UnimplementedError('updatePolylines() has not been implemented.'); + } + + /// Updates circle configuration. + /// + /// Change listeners are notified once the update has been made on the + /// platform side. + /// + /// The returned [Future] completes after listeners have been notified. + Future updateCircles( + CircleUpdates circleUpdates, { + @required int mapId, + }) { + throw UnimplementedError('updateCircles() has not been implemented.'); + } + + /// Starts an animated change of the map camera position. + /// + /// The returned [Future] completes after the change has been started on the + /// platform side. + Future animateCamera( + CameraUpdate cameraUpdate, { + @required int mapId, + }) { + throw UnimplementedError('animateCamera() has not been implemented.'); + } + + /// Changes the map camera position. + /// + /// The returned [Future] completes after the change has been made on the + /// platform side. + Future moveCamera( + CameraUpdate cameraUpdate, { + @required int mapId, + }) { + throw UnimplementedError('moveCamera() has not been implemented.'); + } + + /// Sets the styling of the base map. + /// + /// Set to `null` to clear any previous custom styling. + /// + /// If problems were detected with the [mapStyle], including un-parsable + /// styling JSON, unrecognized feature type, unrecognized element type, or + /// invalid styler keys: [MapStyleException] is thrown and the current + /// style is left unchanged. + /// + /// The style string can be generated using [map style tool](https://mapstyle.withgoogle.com/). + Future setMapStyle( + String mapStyle, { + @required int mapId, + }) { + throw UnimplementedError('setMapStyle() has not been implemented.'); + } + + /// Return the region that is visible in a map. + Future getVisibleRegion({ + @required int mapId, + }) { + throw UnimplementedError('getVisibleRegion() has not been implemented.'); + } + + /// Return [ScreenCoordinate] of the [LatLng] in the current map view. + /// + /// A projection is used to translate between on screen location and geographic coordinates. + /// Screen location is in screen pixels (not display pixels) with respect to the top left corner + /// of the map, not necessarily of the whole screen. + Future getScreenCoordinate( + LatLng latLng, { + @required int mapId, + }) { + throw UnimplementedError('getScreenCoordinate() has not been implemented.'); + } + + /// Returns [LatLng] corresponding to the [ScreenCoordinate] in the current map view. + /// + /// A projection is used to translate between on screen location and geographic coordinates. + /// Screen location is in screen pixels (not display pixels) with respect to the top left corner + /// of the map, not necessarily of the whole screen. + Future getLatLng( + ScreenCoordinate screenCoordinate, { + @required int mapId, + }) { + throw UnimplementedError('getLatLng() has not been implemented.'); + } + + /// Programmatically show the Info Window for a [Marker]. + /// + /// The `markerId` must match one of the markers on the map. + /// An invalid `markerId` triggers an "Invalid markerId" error. + /// + /// * See also: + /// * [hideMarkerInfoWindow] to hide the Info Window. + /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. + Future showMarkerInfoWindow( + MarkerId markerId, { + @required int mapId, + }) { + throw UnimplementedError( + 'showMarkerInfoWindow() has not been implemented.'); + } + + /// Programmatically hide the Info Window for a [Marker]. + /// + /// The `markerId` must match one of the markers on the map. + /// An invalid `markerId` triggers an "Invalid markerId" error. + /// + /// * See also: + /// * [showMarkerInfoWindow] to show the Info Window. + /// * [isMarkerInfoWindowShown] to check if the Info Window is showing. + Future hideMarkerInfoWindow( + MarkerId markerId, { + @required int mapId, + }) { + throw UnimplementedError( + 'hideMarkerInfoWindow() has not been implemented.'); + } + + /// Returns `true` when the [InfoWindow] is showing, `false` otherwise. + /// + /// The `markerId` must match one of the markers on the map. + /// An invalid `markerId` triggers an "Invalid markerId" error. + /// + /// * See also: + /// * [showMarkerInfoWindow] to show the Info Window. + /// * [hideMarkerInfoWindow] to hide the Info Window. + Future isMarkerInfoWindowShown( + MarkerId markerId, { + @required int mapId, + }) { + throw UnimplementedError('updateMapOptions() has not been implemented.'); + } + + /// Returns the current zoom level of the map + Future getZoomLevel({ + @required int mapId, + }) { + throw UnimplementedError('getZoomLevel() has not been implemented.'); + } + + /// Returns the image bytes of the map + Future takeSnapshot({ + @required int mapId, + }) { + throw UnimplementedError('takeSnapshot() has not been implemented.'); + } + + // The following are the 11 possible streams of data from the native side + // into the plugin + + /// The Camera started moving. + Stream onCameraMoveStarted({@required int mapId}) { + throw UnimplementedError('onCameraMoveStarted() has not been implemented.'); + } + + /// The Camera finished moving to a new [CameraPosition]. + Stream onCameraMove({@required int mapId}) { + throw UnimplementedError('onCameraMove() has not been implemented.'); + } + + /// The Camera is now idle. + Stream onCameraIdle({@required int mapId}) { + throw UnimplementedError('onCameraMove() has not been implemented.'); + } + + /// A [Marker] has been tapped. + Stream onMarkerTap({@required int mapId}) { + throw UnimplementedError('onMarkerTap() has not been implemented.'); + } + + /// An [InfoWindow] has been tapped. + Stream onInfoWindowTap({@required int mapId}) { + throw UnimplementedError('onInfoWindowTap() has not been implemented.'); + } + + /// A [Marker] has been dragged to a different [LatLng] position. + Stream onMarkerDragEnd({@required int mapId}) { + throw UnimplementedError('onMarkerDragEnd() has not been implemented.'); + } + + /// A [Polyline] has been tapped. + Stream onPolylineTap({@required int mapId}) { + throw UnimplementedError('onPolylineTap() has not been implemented.'); + } + + /// A [Polygon] has been tapped. + Stream onPolygonTap({@required int mapId}) { + throw UnimplementedError('onPolygonTap() has not been implemented.'); + } + + /// A [Circle] has been tapped. + Stream onCircleTap({@required int mapId}) { + throw UnimplementedError('onCircleTap() has not been implemented.'); + } + + /// A Map has been tapped at a certain [LatLng]. + Stream onTap({@required int mapId}) { + throw UnimplementedError('onTap() has not been implemented.'); + } + + /// A Map has been long-pressed at a certain [LatLng]. + Stream onLongPress({@required int mapId}) { + throw UnimplementedError('onLongPress() has not been implemented.'); + } + + /// Returns a widget displaying the map view + Widget buildView( + Map creationParams, + Set> gestureRecognizers, + PlatformViewCreatedCallback onPlatformViewCreated) { + throw UnimplementedError('buildView() has not been implemented.'); + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/bitmap.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart similarity index 94% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/bitmap.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart index 7cf5b2e25b7e..40581b43e065 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/bitmap.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/bitmap.dart @@ -2,7 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:async' show Future; +import 'dart:typed_data' show Uint8List; + +import 'package:flutter/material.dart' + show ImageConfiguration, AssetImage, AssetBundleImageKey; +import 'package:flutter/services.dart' show AssetBundle; /// Defines a bitmap image. For a marker, this class can be used to set the /// image of the marker icon. For a ground overlay, it can be used to set the @@ -107,9 +112,5 @@ class BitmapDescriptor { final dynamic _json; /// Convert the object to a Json format. - /// Used for testing only. - @visibleForTesting dynamic toJson() => _json; - - dynamic _toJson() => _json; } diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/callbacks.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/callbacks.dart similarity index 85% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/callbacks.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/callbacks.dart index 284c7134cbfb..c20ece5d6c7c 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/callbacks.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/callbacks.dart @@ -2,7 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'types.dart'; + +/// Callback that receives updates to the camera position. +/// +/// This callback is triggered when the platform Google Map +/// registers a camera movement. +/// +/// This is used in [GoogleMap.onCameraMove]. +typedef void CameraPositionCallback(CameraPosition position); /// Callback function taking a single argument. typedef void ArgumentCallback(T argument); diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/camera.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart similarity index 93% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/camera.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart index 043d0f8c9d78..10ea1e98846a 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/camera.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/camera.dart @@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues, Offset; + +import 'package:meta/meta.dart' show required; + +import 'types.dart'; /// The position of the map "camera", the view point from which the world is shown in the map view. /// @@ -61,7 +65,7 @@ class CameraPosition { /// Mainly for internal use when calling [CameraUpdate.newCameraPosition]. dynamic toMap() => { 'bearing': bearing, - 'target': target._toJson(), + 'target': target.toJson(), 'tilt': tilt, 'zoom': zoom, }; @@ -75,7 +79,7 @@ class CameraPosition { } return CameraPosition( bearing: json['bearing'], - target: LatLng._fromJson(json['target']), + target: LatLng.fromJson(json['target']), tilt: json['tilt'], zoom: json['zoom'], ); @@ -115,7 +119,7 @@ class CameraUpdate { /// Returns a camera update that moves the camera target to the specified /// geographical location. static CameraUpdate newLatLng(LatLng latLng) { - return CameraUpdate._(['newLatLng', latLng._toJson()]); + return CameraUpdate._(['newLatLng', latLng.toJson()]); } /// Returns a camera update that transforms the camera so that the specified @@ -125,7 +129,7 @@ class CameraUpdate { static CameraUpdate newLatLngBounds(LatLngBounds bounds, double padding) { return CameraUpdate._([ 'newLatLngBounds', - bounds._toList(), + bounds.toJson(), padding, ]); } @@ -134,7 +138,7 @@ class CameraUpdate { /// geographical location and zoom level. static CameraUpdate newLatLngZoom(LatLng latLng, double zoom) { return CameraUpdate._( - ['newLatLngZoom', latLng._toJson(), zoom], + ['newLatLngZoom', latLng.toJson(), zoom], ); } @@ -188,5 +192,6 @@ class CameraUpdate { final dynamic _json; - dynamic _toJson() => _json; + /// Converts this object to something serializable in JSON. + dynamic toJson() => _json; } diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/cap.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/cap.dart similarity index 88% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/cap.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/cap.dart index 1a6be1f3f528..68bf14c36408 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/cap.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/cap.dart @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'package:meta/meta.dart' show immutable; + +import 'types.dart'; /// Cap that can be applied at the start or end vertex of a [Polyline]. @immutable @@ -43,10 +45,11 @@ class Cap { }) { assert(bitmapDescriptor != null); assert(refWidth > 0.0); - return Cap._(['customCap', bitmapDescriptor._toJson(), refWidth]); + return Cap._(['customCap', bitmapDescriptor.toJson(), refWidth]); } final dynamic _json; - dynamic _toJson() => _json; + /// Converts this object to something serializable in JSON. + dynamic toJson() => _json; } diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/circle.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle.dart similarity index 89% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/circle.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle.dart index 3edfc88ed4e0..d1418a4c30b1 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/circle.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle.dart @@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'package:flutter/foundation.dart' show VoidCallback; +import 'package:flutter/material.dart' show Color, Colors; +import 'package:meta/meta.dart' show immutable, required; + +import 'types.dart'; /// Uniquely identifies a [Circle] among [GoogleMap] circles. /// @@ -119,7 +123,8 @@ class Circle { /// Creates a new [Circle] object whose values are the same as this instance. Circle clone() => copyWith(); - dynamic _toJson() { + /// Converts this object to something serializable in JSON. + dynamic toJson() { final Map json = {}; void addIfPresent(String fieldName, dynamic value) { @@ -131,7 +136,7 @@ class Circle { addIfPresent('circleId', circleId.value); addIfPresent('consumeTapEvents', consumeTapEvents); addIfPresent('fillColor', fillColor.value); - addIfPresent('center', center._toJson()); + addIfPresent('center', center.toJson()); addIfPresent('radius', radius); addIfPresent('strokeColor', strokeColor.value); addIfPresent('strokeWidth', strokeWidth); @@ -160,18 +165,3 @@ class Circle { @override int get hashCode => circleId.hashCode; } - -Map _keyByCircleId(Iterable circles) { - if (circles == null) { - return {}; - } - return Map.fromEntries(circles.map((Circle circle) => - MapEntry(circle.circleId, circle.clone()))); -} - -List> _serializeCircleSet(Set circles) { - if (circles == null) { - return null; - } - return circles.map>((Circle p) => p._toJson()).toList(); -} diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/circle_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle_updates.dart similarity index 73% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/circle_updates.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle_updates.dart index c977c4182c98..6f494423a38f 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/circle_updates.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/circle_updates.dart @@ -2,14 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues; + +import 'package:flutter/foundation.dart' show setEquals; + +import 'types.dart'; +import 'utils/circle.dart'; /// [Circle] update events to be applied to the [GoogleMap]. /// /// Used in [GoogleMapController] when the map is updated. -class _CircleUpdates { - /// Computes [_CircleUpdates] given previous and current [Circle]s. - _CircleUpdates.from(Set previous, Set current) { +// (Do not re-export) +class CircleUpdates { + /// Computes [CircleUpdates] given previous and current [Circle]s. + CircleUpdates.from(Set previous, Set current) { if (previous == null) { previous = Set.identity(); } @@ -18,8 +24,8 @@ class _CircleUpdates { current = Set.identity(); } - final Map previousCircles = _keyByCircleId(previous); - final Map currentCircles = _keyByCircleId(current); + final Map previousCircles = keyByCircleId(previous); + final Map currentCircles = keyByCircleId(current); final Set prevCircleIds = previousCircles.keys.toSet(); final Set currentCircleIds = currentCircles.keys.toSet(); @@ -54,11 +60,17 @@ class _CircleUpdates { circlesToChange = _circlesToChange; } + /// Set of Circles to be added in this update. Set circlesToAdd; + + /// Set of CircleIds to be removed in this update. Set circleIdsToRemove; + + /// Set of Circles to be changed in this update. Set circlesToChange; - Map _toMap() { + /// Converts this object to something serializable in JSON. + Map toJson() { final Map updateMap = {}; void addIfNonNull(String fieldName, dynamic value) { @@ -67,8 +79,8 @@ class _CircleUpdates { } } - addIfNonNull('circlesToAdd', _serializeCircleSet(circlesToAdd)); - addIfNonNull('circlesToChange', _serializeCircleSet(circlesToChange)); + addIfNonNull('circlesToAdd', serializeCircleSet(circlesToAdd)); + addIfNonNull('circlesToChange', serializeCircleSet(circlesToChange)); addIfNonNull('circleIdsToRemove', circleIdsToRemove.map((CircleId m) => m.value).toList()); @@ -79,7 +91,7 @@ class _CircleUpdates { bool operator ==(Object other) { if (identical(this, other)) return true; if (other.runtimeType != runtimeType) return false; - final _CircleUpdates typedOther = other; + final CircleUpdates typedOther = other; return setEquals(circlesToAdd, typedOther.circlesToAdd) && setEquals(circleIdsToRemove, typedOther.circleIdsToRemove) && setEquals(circlesToChange, typedOther.circlesToChange); diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/joint_type.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/joint_type.dart similarity index 94% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/joint_type.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/joint_type.dart index ced61ba77417..c7df0b298624 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/joint_type.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/joint_type.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'package:meta/meta.dart' show immutable; /// Joint types for [Polyline]. @immutable diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/location.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart similarity index 87% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/location.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart index ae299ce9583d..6b76a6d496ac 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/location.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/location.dart @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues; + +import 'package:meta/meta.dart'; /// A pair of latitude and longitude coordinates, stored as degrees. class LatLng { @@ -26,11 +28,13 @@ class LatLng { /// The longitude in degrees between -180.0 (inclusive) and 180.0 (exclusive). final double longitude; - dynamic _toJson() { + /// Converts this object to something serializable in JSON. + dynamic toJson() { return [latitude, longitude]; } - static LatLng _fromJson(dynamic json) { + /// Initialize a LatLng from an \[lat, lng\] array. + static LatLng fromJson(dynamic json) { if (json == null) { return null; } @@ -73,8 +77,9 @@ class LatLngBounds { /// The northeast corner of the rectangle. final LatLng northeast; - dynamic _toList() { - return [southwest._toJson(), northeast._toJson()]; + /// Converts this object to something serializable in JSON. + dynamic toJson() { + return [southwest.toJson(), northeast.toJson()]; } /// Returns whether this rectangle contains the given [LatLng]. @@ -102,8 +107,8 @@ class LatLngBounds { return null; } return LatLngBounds( - southwest: LatLng._fromJson(json[0]), - northeast: LatLng._fromJson(json[1]), + southwest: LatLng.fromJson(json[0]), + northeast: LatLng.fromJson(json[1]), ); } diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/marker.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker.dart similarity index 94% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/marker.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker.dart index 480f0a379c1e..9b57f9676334 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/marker.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker.dart @@ -2,7 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues, Offset; + +import 'package:flutter/foundation.dart' show ValueChanged, VoidCallback; +import 'package:meta/meta.dart' show immutable, required; + +import 'types.dart'; dynamic _offsetToJson(Offset offset) { if (offset == null) { @@ -262,7 +267,8 @@ class Marker { /// Creates a new [Marker] object whose values are the same as this instance. Marker clone() => copyWith(); - Map _toJson() { + /// Converts this object to something serializable in JSON. + Map toJson() { final Map json = {}; void addIfPresent(String fieldName, dynamic value) { @@ -277,9 +283,9 @@ class Marker { addIfPresent('consumeTapEvents', consumeTapEvents); addIfPresent('draggable', draggable); addIfPresent('flat', flat); - addIfPresent('icon', icon?._toJson()); + addIfPresent('icon', icon?.toJson()); addIfPresent('infoWindow', infoWindow?._toJson()); - addIfPresent('position', position?._toJson()); + addIfPresent('position', position?.toJson()); addIfPresent('rotation', rotation); addIfPresent('visible', visible); addIfPresent('zIndex', zIndex); @@ -316,18 +322,3 @@ class Marker { 'visible: $visible, zIndex: $zIndex, onTap: $onTap}'; } } - -Map _keyByMarkerId(Iterable markers) { - if (markers == null) { - return {}; - } - return Map.fromEntries(markers.map((Marker marker) => - MapEntry(marker.markerId, marker.clone()))); -} - -List> _serializeMarkerSet(Set markers) { - if (markers == null) { - return null; - } - return markers.map>((Marker m) => m._toJson()).toList(); -} diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/marker_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker_updates.dart similarity index 73% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/marker_updates.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker_updates.dart index d4a08255e069..bb6ea8813ea3 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/marker_updates.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/marker_updates.dart @@ -2,14 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues; + +import 'package:flutter/foundation.dart' show setEquals; + +import 'types.dart'; +import 'utils/marker.dart'; /// [Marker] update events to be applied to the [GoogleMap]. /// /// Used in [GoogleMapController] when the map is updated. -class _MarkerUpdates { - /// Computes [_MarkerUpdates] given previous and current [Marker]s. - _MarkerUpdates.from(Set previous, Set current) { +// (Do not re-export) +class MarkerUpdates { + /// Computes [MarkerUpdates] given previous and current [Marker]s. + MarkerUpdates.from(Set previous, Set current) { if (previous == null) { previous = Set.identity(); } @@ -18,8 +24,8 @@ class _MarkerUpdates { current = Set.identity(); } - final Map previousMarkers = _keyByMarkerId(previous); - final Map currentMarkers = _keyByMarkerId(current); + final Map previousMarkers = keyByMarkerId(previous); + final Map currentMarkers = keyByMarkerId(current); final Set prevMarkerIds = previousMarkers.keys.toSet(); final Set currentMarkerIds = currentMarkers.keys.toSet(); @@ -54,11 +60,17 @@ class _MarkerUpdates { markersToChange = _markersToChange; } + /// Set of Markers to be added in this update. Set markersToAdd; + + /// Set of MarkerIds to be removed in this update. Set markerIdsToRemove; + + /// Set of Markers to be changed in this update. Set markersToChange; - Map _toMap() { + /// Converts this object to something serializable in JSON. + Map toJson() { final Map updateMap = {}; void addIfNonNull(String fieldName, dynamic value) { @@ -67,8 +79,8 @@ class _MarkerUpdates { } } - addIfNonNull('markersToAdd', _serializeMarkerSet(markersToAdd)); - addIfNonNull('markersToChange', _serializeMarkerSet(markersToChange)); + addIfNonNull('markersToAdd', serializeMarkerSet(markersToAdd)); + addIfNonNull('markersToChange', serializeMarkerSet(markersToChange)); addIfNonNull('markerIdsToRemove', markerIdsToRemove.map((MarkerId m) => m.value).toList()); @@ -79,7 +91,7 @@ class _MarkerUpdates { bool operator ==(Object other) { if (identical(this, other)) return true; if (other.runtimeType != runtimeType) return false; - final _MarkerUpdates typedOther = other; + final MarkerUpdates typedOther = other; return setEquals(markersToAdd, typedOther.markersToAdd) && setEquals(markerIdsToRemove, typedOther.markerIdsToRemove) && setEquals(markersToChange, typedOther.markersToChange); diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/pattern_item.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/pattern_item.dart similarity index 86% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/pattern_item.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/pattern_item.dart index 82e8703d10e2..28c7ce9d33dd 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/pattern_item.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/pattern_item.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'package:meta/meta.dart' show immutable; /// Item used in the stroke pattern for a Polyline. @immutable @@ -30,5 +30,6 @@ class PatternItem { final dynamic _json; - dynamic _toJson() => _json; + /// Converts this object to something serializable in JSON. + dynamic toJson() => _json; } diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/polygon.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon.dart similarity index 90% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/polygon.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon.dart index 973667eece09..3b5e25060faf 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/polygon.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon.dart @@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'package:flutter/foundation.dart' show listEquals, VoidCallback; +import 'package:flutter/material.dart' show Color, Colors; +import 'package:meta/meta.dart' show immutable, required; + +import 'types.dart'; /// Uniquely identifies a [Polygon] among [GoogleMap] polygons. /// @@ -127,7 +131,8 @@ class Polygon { return copyWith(pointsParam: List.of(points)); } - dynamic _toJson() { + /// Converts this object to something serializable in JSON. + dynamic toJson() { final Map json = {}; void addIfPresent(String fieldName, dynamic value) { @@ -174,25 +179,8 @@ class Polygon { dynamic _pointsToJson() { final List result = []; for (final LatLng point in points) { - result.add(point._toJson()); + result.add(point.toJson()); } return result; } } - -Map _keyByPolygonId(Iterable polygons) { - if (polygons == null) { - return {}; - } - return Map.fromEntries(polygons.map((Polygon polygon) => - MapEntry(polygon.polygonId, polygon.clone()))); -} - -List> _serializePolygonSet(Set polygons) { - if (polygons == null) { - return null; - } - return polygons - .map>((Polygon p) => p._toJson()) - .toList(); -} diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/polygon_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon_updates.dart similarity index 73% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/polygon_updates.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon_updates.dart index 5a14c6b8ec5c..cc8b8e26c896 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/polygon_updates.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polygon_updates.dart @@ -2,14 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues; + +import 'package:flutter/foundation.dart' show setEquals; + +import 'types.dart'; +import 'utils/polygon.dart'; /// [Polygon] update events to be applied to the [GoogleMap]. /// /// Used in [GoogleMapController] when the map is updated. -class _PolygonUpdates { - /// Computes [_PolygonUpdates] given previous and current [Polygon]s. - _PolygonUpdates.from(Set previous, Set current) { +// (Do not re-export) +class PolygonUpdates { + /// Computes [PolygonUpdates] given previous and current [Polygon]s. + PolygonUpdates.from(Set previous, Set current) { if (previous == null) { previous = Set.identity(); } @@ -18,8 +24,8 @@ class _PolygonUpdates { current = Set.identity(); } - final Map previousPolygons = _keyByPolygonId(previous); - final Map currentPolygons = _keyByPolygonId(current); + final Map previousPolygons = keyByPolygonId(previous); + final Map currentPolygons = keyByPolygonId(current); final Set prevPolygonIds = previousPolygons.keys.toSet(); final Set currentPolygonIds = currentPolygons.keys.toSet(); @@ -54,11 +60,17 @@ class _PolygonUpdates { polygonsToChange = _polygonsToChange; } + /// Set of Polygons to be added in this update. Set polygonsToAdd; + + /// Set of PolygonIds to be removed in this update. Set polygonIdsToRemove; + + /// Set of Polygons to be changed in this update. Set polygonsToChange; - Map _toMap() { + /// Converts this object to something serializable in JSON. + Map toJson() { final Map updateMap = {}; void addIfNonNull(String fieldName, dynamic value) { @@ -67,8 +79,8 @@ class _PolygonUpdates { } } - addIfNonNull('polygonsToAdd', _serializePolygonSet(polygonsToAdd)); - addIfNonNull('polygonsToChange', _serializePolygonSet(polygonsToChange)); + addIfNonNull('polygonsToAdd', serializePolygonSet(polygonsToAdd)); + addIfNonNull('polygonsToChange', serializePolygonSet(polygonsToChange)); addIfNonNull('polygonIdsToRemove', polygonIdsToRemove.map((PolygonId m) => m.value).toList()); @@ -79,7 +91,7 @@ class _PolygonUpdates { bool operator ==(Object other) { if (identical(this, other)) return true; if (other.runtimeType != runtimeType) return false; - final _PolygonUpdates typedOther = other; + final PolygonUpdates typedOther = other; return setEquals(polygonsToAdd, typedOther.polygonsToAdd) && setEquals(polygonIdsToRemove, typedOther.polygonIdsToRemove) && setEquals(polygonsToChange, typedOther.polygonsToChange); diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/polyline.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline.dart similarity index 90% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/polyline.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline.dart index c27b19e2843e..ae5c3b976352 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/polyline.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline.dart @@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'package:flutter/foundation.dart' show listEquals, VoidCallback; +import 'package:flutter/material.dart' show Color, Colors; +import 'package:meta/meta.dart' show immutable, required; + +import 'types.dart'; /// Uniquely identifies a [Polyline] among [GoogleMap] polylines. /// @@ -169,7 +173,8 @@ class Polyline { ); } - dynamic _toJson() { + /// Converts this object to something serializable in JSON. + dynamic toJson() { final Map json = {}; void addIfPresent(String fieldName, dynamic value) { @@ -181,10 +186,10 @@ class Polyline { addIfPresent('polylineId', polylineId.value); addIfPresent('consumeTapEvents', consumeTapEvents); addIfPresent('color', color.value); - addIfPresent('endCap', endCap?._toJson()); + addIfPresent('endCap', endCap?.toJson()); addIfPresent('geodesic', geodesic); addIfPresent('jointType', jointType?.value); - addIfPresent('startCap', startCap?._toJson()); + addIfPresent('startCap', startCap?.toJson()); addIfPresent('visible', visible); addIfPresent('width', width); addIfPresent('zIndex', zIndex); @@ -225,7 +230,7 @@ class Polyline { dynamic _pointsToJson() { final List result = []; for (final LatLng point in points) { - result.add(point._toJson()); + result.add(point.toJson()); } return result; } @@ -234,27 +239,9 @@ class Polyline { final List result = []; for (final PatternItem patternItem in patterns) { if (patternItem != null) { - result.add(patternItem._toJson()); + result.add(patternItem.toJson()); } } return result; } } - -Map _keyByPolylineId(Iterable polylines) { - if (polylines == null) { - return {}; - } - return Map.fromEntries(polylines.map( - (Polyline polyline) => MapEntry( - polyline.polylineId, polyline.clone()))); -} - -List> _serializePolylineSet(Set polylines) { - if (polylines == null) { - return null; - } - return polylines - .map>((Polyline p) => p._toJson()) - .toList(); -} diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/polyline_updates.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline_updates.dart similarity index 74% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/polyline_updates.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline_updates.dart index ed972a51c8bf..f871928c0ac4 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/polyline_updates.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/polyline_updates.dart @@ -2,14 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues; + +import 'package:flutter/foundation.dart' show setEquals; + +import 'utils/polyline.dart'; +import 'types.dart'; /// [Polyline] update events to be applied to the [GoogleMap]. /// /// Used in [GoogleMapController] when the map is updated. -class _PolylineUpdates { - /// Computes [_PolylineUpdates] given previous and current [Polyline]s. - _PolylineUpdates.from(Set previous, Set current) { +// (Do not re-export) +class PolylineUpdates { + /// Computes [PolylineUpdates] given previous and current [Polyline]s. + PolylineUpdates.from(Set previous, Set current) { if (previous == null) { previous = Set.identity(); } @@ -19,9 +25,8 @@ class _PolylineUpdates { } final Map previousPolylines = - _keyByPolylineId(previous); - final Map currentPolylines = - _keyByPolylineId(current); + keyByPolylineId(previous); + final Map currentPolylines = keyByPolylineId(current); final Set prevPolylineIds = previousPolylines.keys.toSet(); final Set currentPolylineIds = currentPolylines.keys.toSet(); @@ -56,11 +61,17 @@ class _PolylineUpdates { polylinesToChange = _polylinesToChange; } + /// Set of Polylines to be added in this update. Set polylinesToAdd; + + /// Set of PolylineIds to be removed in this update. Set polylineIdsToRemove; + + /// Set of Polylines to be changed in this update. Set polylinesToChange; - Map _toMap() { + /// Converts this object to something serializable in JSON. + Map toJson() { final Map updateMap = {}; void addIfNonNull(String fieldName, dynamic value) { @@ -69,8 +80,8 @@ class _PolylineUpdates { } } - addIfNonNull('polylinesToAdd', _serializePolylineSet(polylinesToAdd)); - addIfNonNull('polylinesToChange', _serializePolylineSet(polylinesToChange)); + addIfNonNull('polylinesToAdd', serializePolylineSet(polylinesToAdd)); + addIfNonNull('polylinesToChange', serializePolylineSet(polylinesToChange)); addIfNonNull('polylineIdsToRemove', polylineIdsToRemove.map((PolylineId m) => m.value).toList()); @@ -81,7 +92,7 @@ class _PolylineUpdates { bool operator ==(Object other) { if (identical(this, other)) return true; if (other.runtimeType != runtimeType) return false; - final _PolylineUpdates typedOther = other; + final PolylineUpdates typedOther = other; return setEquals(polylinesToAdd, typedOther.polylinesToAdd) && setEquals(polylineIdsToRemove, typedOther.polylineIdsToRemove) && setEquals(polylinesToChange, typedOther.polylinesToChange); diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/screen_coordinate.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/screen_coordinate.dart similarity index 86% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/screen_coordinate.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/screen_coordinate.dart index e58abe9cefad..965db7969bc2 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/screen_coordinate.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/screen_coordinate.dart @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues; + +import 'package:meta/meta.dart' show immutable, required; /// Represents a point coordinate in the [GoogleMap]'s view. /// @@ -23,7 +25,8 @@ class ScreenCoordinate { /// Represents the number of pixels from the top of the [GoogleMap]. final int y; - dynamic _toJson() { + /// Converts this object to something serializable in JSON. + dynamic toJson() { return { "x": x, "y": y, diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/types.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/types.dart new file mode 100644 index 000000000000..e56c3a5dd646 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/types.dart @@ -0,0 +1,28 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// All the public types exposed by this package. +export 'bitmap.dart'; +export 'callbacks.dart'; +export 'camera.dart'; +export 'cap.dart'; +export 'circle_updates.dart'; +export 'circle.dart'; +export 'joint_type.dart'; +export 'location.dart'; +export 'marker_updates.dart'; +export 'marker.dart'; +export 'pattern_item.dart'; +export 'polygon_updates.dart'; +export 'polygon.dart'; +export 'polyline_updates.dart'; +export 'polyline.dart'; +export 'screen_coordinate.dart'; +export 'ui.dart'; + +// Export the utils, they're used by the Widget +export 'utils/circle.dart'; +export 'utils/marker.dart'; +export 'utils/polygon.dart'; +export 'utils/polyline.dart'; diff --git a/packages/google_maps_flutter/google_maps_flutter/lib/src/ui.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/ui.dart similarity index 92% rename from packages/google_maps_flutter/google_maps_flutter/lib/src/ui.dart rename to packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/ui.dart index 4b57ebd7440f..8d84171bac03 100644 --- a/packages/google_maps_flutter/google_maps_flutter/lib/src/ui.dart +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/ui.dart @@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -part of google_maps_flutter; +import 'dart:ui' show hashValues; + +import 'types.dart'; /// Type of map tiles to display. // Enum constants must be indexed to match the corresponding int constants of @@ -42,7 +44,8 @@ class CameraTargetBounds { /// Unbounded camera target. static const CameraTargetBounds unbounded = CameraTargetBounds(null); - dynamic _toJson() => [bounds?._toList()]; + /// Converts this object to something serializable in JSON. + dynamic toJson() => [bounds?.toJson()]; @override bool operator ==(dynamic other) { @@ -82,7 +85,8 @@ class MinMaxZoomPreference { static const MinMaxZoomPreference unbounded = MinMaxZoomPreference(null, null); - dynamic _toJson() => [minZoom, maxZoom]; + /// Converts this object to something serializable in JSON. + dynamic toJson() => [minZoom, maxZoom]; @override bool operator ==(dynamic other) { diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/circle.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/circle.dart new file mode 100644 index 000000000000..5c3af96f8e02 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/circle.dart @@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../types.dart'; + +/// Converts an [Iterable] of Circles in a Map of CircleId -> Circle. +Map keyByCircleId(Iterable circles) { + if (circles == null) { + return {}; + } + return Map.fromEntries(circles.map((Circle circle) => + MapEntry(circle.circleId, circle.clone()))); +} + +/// Converts a Set of Circles into something serializable in JSON. +List> serializeCircleSet(Set circles) { + if (circles == null) { + return null; + } + return circles.map>((Circle p) => p.toJson()).toList(); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/marker.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/marker.dart new file mode 100644 index 000000000000..7a2c76d8055b --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/marker.dart @@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../types.dart'; + +/// Converts an [Iterable] of Markers in a Map of MarkerId -> Marker. +Map keyByMarkerId(Iterable markers) { + if (markers == null) { + return {}; + } + return Map.fromEntries(markers.map((Marker marker) => + MapEntry(marker.markerId, marker.clone()))); +} + +/// Converts a Set of Markers into something serializable in JSON. +List> serializeMarkerSet(Set markers) { + if (markers == null) { + return null; + } + return markers.map>((Marker m) => m.toJson()).toList(); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polygon.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polygon.dart new file mode 100644 index 000000000000..9434ddaa077d --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polygon.dart @@ -0,0 +1,22 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../types.dart'; + +/// Converts an [Iterable] of Polygons in a Map of PolygonId -> Polygon. +Map keyByPolygonId(Iterable polygons) { + if (polygons == null) { + return {}; + } + return Map.fromEntries(polygons.map((Polygon polygon) => + MapEntry(polygon.polygonId, polygon.clone()))); +} + +/// Converts a Set of Polygons into something serializable in JSON. +List> serializePolygonSet(Set polygons) { + if (polygons == null) { + return null; + } + return polygons.map>((Polygon p) => p.toJson()).toList(); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polyline.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polyline.dart new file mode 100644 index 000000000000..9cef6319ddb5 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/lib/src/types/utils/polyline.dart @@ -0,0 +1,25 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../types.dart'; + +/// Converts an [Iterable] of Polylines in a Map of PolylineId -> Polyline. +Map keyByPolylineId(Iterable polylines) { + if (polylines == null) { + return {}; + } + return Map.fromEntries(polylines.map( + (Polyline polyline) => MapEntry( + polyline.polylineId, polyline.clone()))); +} + +/// Converts a Set of Polylines into something serializable in JSON. +List> serializePolylineSet(Set polylines) { + if (polylines == null) { + return null; + } + return polylines + .map>((Polyline p) => p.toJson()) + .toList(); +} diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml new file mode 100644 index 000000000000..2cd840b07e3a --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/pubspec.yaml @@ -0,0 +1,23 @@ +name: google_maps_flutter_platform_interface +description: A common platform interface for the google_maps_flutter plugin. +homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter/google_maps_flutter_platform_interface +# NOTE: We strongly prefer non-breaking changes, even at the expense of a +# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes +version: 1.0.0 + +dependencies: + flutter: + sdk: flutter + meta: ^1.0.5 + plugin_platform_interface: ^1.0.1 + stream_transform: ^1.2.0 + +dev_dependencies: + flutter_test: + sdk: flutter + mockito: ^4.1.1 + pedantic: ^1.8.0 + +environment: + sdk: ">=2.0.0-dev.28.0 <3.0.0" + flutter: ">=1.9.1+hotfix.4 <2.0.0" diff --git a/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_flutter_platform_test.dart b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_flutter_platform_test.dart new file mode 100644 index 000000000000..a003b94d544c --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_platform_interface/test/platform_interface/google_maps_flutter_platform_test.dart @@ -0,0 +1,71 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:mockito/mockito.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import 'package:google_maps_flutter_platform_interface/src/method_channel/method_channel_google_maps_flutter.dart'; +import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('$GoogleMapsFlutterPlatform', () { + test('$MethodChannelGoogleMapsFlutter() is the default instance', () { + expect(GoogleMapsFlutterPlatform.instance, + isInstanceOf()); + }); + + test('Cannot be implemented with `implements`', () { + expect(() { + GoogleMapsFlutterPlatform.instance = + ImplementsGoogleMapsFlutterPlatform(); + }, throwsA(isInstanceOf())); + }); + + test('Can be mocked with `implements`', () { + final GoogleMapsFlutterPlatformMock mock = + GoogleMapsFlutterPlatformMock(); + GoogleMapsFlutterPlatform.instance = mock; + }); + + test('Can be extended', () { + GoogleMapsFlutterPlatform.instance = ExtendsGoogleMapsFlutterPlatform(); + }); + }); + + group('$MethodChannelGoogleMapsFlutter', () { + const MethodChannel channel = + MethodChannel('plugins.flutter.io/google_maps_flutter'); + final List log = []; + channel.setMockMethodCallHandler((MethodCall methodCall) async { + log.add(methodCall); + }); + +// final MethodChannelGoogleMapsFlutter map = MethodChannelGoogleMapsFlutter(0); + + tearDown(() { + log.clear(); + }); + + test('foo', () async { +// await map.foo(); + expect( + log, + [], + ); + }); + }); +} + +class GoogleMapsFlutterPlatformMock extends Mock + with MockPlatformInterfaceMixin + implements GoogleMapsFlutterPlatform {} + +class ImplementsGoogleMapsFlutterPlatform extends Mock + implements GoogleMapsFlutterPlatform {} + +class ExtendsGoogleMapsFlutterPlatform extends GoogleMapsFlutterPlatform {}