| // 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 "GoogleMapController.h" | |
| #import "JsonConversions.h" | |
| #pragma mark - Conversion of JSON-like values sent via platform channels. Forward declarations. | |
| static NSDictionary* PositionToJson(GMSCameraPosition* position); | |
| static NSDictionary* PointToJson(CGPoint point); | |
| static NSArray* LocationToJson(CLLocationCoordinate2D position); | |
| static CGPoint ToCGPoint(NSDictionary* json); | |
| static GMSCameraPosition* ToOptionalCameraPosition(NSDictionary* json); | |
| static GMSCoordinateBounds* ToOptionalBounds(NSArray* json); | |
| static GMSCameraUpdate* ToCameraUpdate(NSArray* data); | |
| static NSDictionary* GMSCoordinateBoundsToJson(GMSCoordinateBounds* bounds); | |
| static void InterpretMapOptions(NSDictionary* data, id<FLTGoogleMapOptionsSink> sink); | |
| static double ToDouble(NSNumber* data) { return [FLTGoogleMapJsonConversions toDouble:data]; } | |
| @implementation FLTGoogleMapFactory { | |
| NSObject<FlutterPluginRegistrar>* _registrar; | |
| } | |
| - (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar { | |
| self = [super init]; | |
| if (self) { | |
| _registrar = registrar; | |
| } | |
| return self; | |
| } | |
| - (NSObject<FlutterMessageCodec>*)createArgsCodec { | |
| return [FlutterStandardMessageCodec sharedInstance]; | |
| } | |
| - (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame | |
| viewIdentifier:(int64_t)viewId | |
| arguments:(id _Nullable)args { | |
| return [[FLTGoogleMapController alloc] initWithFrame:frame | |
| viewIdentifier:viewId | |
| arguments:args | |
| registrar:_registrar]; | |
| } | |
| @end | |
| @implementation FLTGoogleMapController { | |
| GMSMapView* _mapView; | |
| int64_t _viewId; | |
| FlutterMethodChannel* _channel; | |
| BOOL _trackCameraPosition; | |
| NSObject<FlutterPluginRegistrar>* _registrar; | |
| // Used for the temporary workaround for a bug that the camera is not properly positioned at | |
| // initialization. https://github.com/flutter/flutter/issues/24806 | |
| // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. | |
| // https://github.com/flutter/flutter/issues/27550 | |
| BOOL _cameraDidInitialSetup; | |
| FLTMarkersController* _markersController; | |
| FLTPolygonsController* _polygonsController; | |
| FLTPolylinesController* _polylinesController; | |
| FLTCirclesController* _circlesController; | |
| } | |
| - (instancetype)initWithFrame:(CGRect)frame | |
| viewIdentifier:(int64_t)viewId | |
| arguments:(id _Nullable)args | |
| registrar:(NSObject<FlutterPluginRegistrar>*)registrar { | |
| if (self = [super init]) { | |
| _viewId = viewId; | |
| GMSCameraPosition* camera = ToOptionalCameraPosition(args[@"initialCameraPosition"]); | |
| _mapView = [GMSMapView mapWithFrame:frame camera:camera]; | |
| _mapView.accessibilityElementsHidden = NO; | |
| _trackCameraPosition = NO; | |
| InterpretMapOptions(args[@"options"], self); | |
| NSString* channelName = | |
| [NSString stringWithFormat:@"plugins.flutter.io/google_maps_%lld", viewId]; | |
| _channel = [FlutterMethodChannel methodChannelWithName:channelName | |
| binaryMessenger:registrar.messenger]; | |
| __weak __typeof__(self) weakSelf = self; | |
| [_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { | |
| if (weakSelf) { | |
| [weakSelf onMethodCall:call result:result]; | |
| } | |
| }]; | |
| _mapView.delegate = weakSelf; | |
| _registrar = registrar; | |
| _cameraDidInitialSetup = NO; | |
| _markersController = [[FLTMarkersController alloc] init:_channel | |
| mapView:_mapView | |
| registrar:registrar]; | |
| _polygonsController = [[FLTPolygonsController alloc] init:_channel | |
| mapView:_mapView | |
| registrar:registrar]; | |
| _polylinesController = [[FLTPolylinesController alloc] init:_channel | |
| mapView:_mapView | |
| registrar:registrar]; | |
| _circlesController = [[FLTCirclesController alloc] init:_channel | |
| mapView:_mapView | |
| registrar:registrar]; | |
| id markersToAdd = args[@"markersToAdd"]; | |
| if ([markersToAdd isKindOfClass:[NSArray class]]) { | |
| [_markersController addMarkers:markersToAdd]; | |
| } | |
| id polygonsToAdd = args[@"polygonsToAdd"]; | |
| if ([polygonsToAdd isKindOfClass:[NSArray class]]) { | |
| [_polygonsController addPolygons:polygonsToAdd]; | |
| } | |
| id polylinesToAdd = args[@"polylinesToAdd"]; | |
| if ([polylinesToAdd isKindOfClass:[NSArray class]]) { | |
| [_polylinesController addPolylines:polylinesToAdd]; | |
| } | |
| id circlesToAdd = args[@"circlesToAdd"]; | |
| if ([circlesToAdd isKindOfClass:[NSArray class]]) { | |
| [_circlesController addCircles:circlesToAdd]; | |
| } | |
| } | |
| return self; | |
| } | |
| - (UIView*)view { | |
| return _mapView; | |
| } | |
| - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { | |
| if ([call.method isEqualToString:@"map#show"]) { | |
| [self showAtX:ToDouble(call.arguments[@"x"]) Y:ToDouble(call.arguments[@"y"])]; | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"map#hide"]) { | |
| [self hide]; | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"camera#animate"]) { | |
| [self animateWithCameraUpdate:ToCameraUpdate(call.arguments[@"cameraUpdate"])]; | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"camera#move"]) { | |
| [self moveWithCameraUpdate:ToCameraUpdate(call.arguments[@"cameraUpdate"])]; | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"map#update"]) { | |
| InterpretMapOptions(call.arguments[@"options"], self); | |
| result(PositionToJson([self cameraPosition])); | |
| } else if ([call.method isEqualToString:@"map#getVisibleRegion"]) { | |
| if (_mapView != nil) { | |
| GMSVisibleRegion visibleRegion = _mapView.projection.visibleRegion; | |
| GMSCoordinateBounds* bounds = [[GMSCoordinateBounds alloc] initWithRegion:visibleRegion]; | |
| result(GMSCoordinateBoundsToJson(bounds)); | |
| } else { | |
| result([FlutterError errorWithCode:@"GoogleMap uninitialized" | |
| message:@"getVisibleRegion called prior to map initialization" | |
| details:nil]); | |
| } | |
| } else if ([call.method isEqualToString:@"map#getScreenCoordinate"]) { | |
| if (_mapView != nil) { | |
| CLLocationCoordinate2D location = [FLTGoogleMapJsonConversions toLocation:call.arguments]; | |
| CGPoint point = [_mapView.projection pointForCoordinate:location]; | |
| result(PointToJson(point)); | |
| } else { | |
| result([FlutterError errorWithCode:@"GoogleMap uninitialized" | |
| message:@"getScreenCoordinate called prior to map initialization" | |
| details:nil]); | |
| } | |
| } else if ([call.method isEqualToString:@"map#getLatLng"]) { | |
| if (_mapView != nil && call.arguments) { | |
| CGPoint point = ToCGPoint(call.arguments); | |
| CLLocationCoordinate2D latlng = [_mapView.projection coordinateForPoint:point]; | |
| result(LocationToJson(latlng)); | |
| } else { | |
| result([FlutterError errorWithCode:@"GoogleMap uninitialized" | |
| message:@"getLatLng called prior to map initialization" | |
| details:nil]); | |
| } | |
| } else if ([call.method isEqualToString:@"map#waitForMap"]) { | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"markers#update"]) { | |
| id markersToAdd = call.arguments[@"markersToAdd"]; | |
| if ([markersToAdd isKindOfClass:[NSArray class]]) { | |
| [_markersController addMarkers:markersToAdd]; | |
| } | |
| id markersToChange = call.arguments[@"markersToChange"]; | |
| if ([markersToChange isKindOfClass:[NSArray class]]) { | |
| [_markersController changeMarkers:markersToChange]; | |
| } | |
| id markerIdsToRemove = call.arguments[@"markerIdsToRemove"]; | |
| if ([markerIdsToRemove isKindOfClass:[NSArray class]]) { | |
| [_markersController removeMarkerIds:markerIdsToRemove]; | |
| } | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"polygons#update"]) { | |
| id polygonsToAdd = call.arguments[@"polygonsToAdd"]; | |
| if ([polygonsToAdd isKindOfClass:[NSArray class]]) { | |
| [_polygonsController addPolygons:polygonsToAdd]; | |
| } | |
| id polygonsToChange = call.arguments[@"polygonsToChange"]; | |
| if ([polygonsToChange isKindOfClass:[NSArray class]]) { | |
| [_polygonsController changePolygons:polygonsToChange]; | |
| } | |
| id polygonIdsToRemove = call.arguments[@"polygonIdsToRemove"]; | |
| if ([polygonIdsToRemove isKindOfClass:[NSArray class]]) { | |
| [_polygonsController removePolygonIds:polygonIdsToRemove]; | |
| } | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"polylines#update"]) { | |
| id polylinesToAdd = call.arguments[@"polylinesToAdd"]; | |
| if ([polylinesToAdd isKindOfClass:[NSArray class]]) { | |
| [_polylinesController addPolylines:polylinesToAdd]; | |
| } | |
| id polylinesToChange = call.arguments[@"polylinesToChange"]; | |
| if ([polylinesToChange isKindOfClass:[NSArray class]]) { | |
| [_polylinesController changePolylines:polylinesToChange]; | |
| } | |
| id polylineIdsToRemove = call.arguments[@"polylineIdsToRemove"]; | |
| if ([polylineIdsToRemove isKindOfClass:[NSArray class]]) { | |
| [_polylinesController removePolylineIds:polylineIdsToRemove]; | |
| } | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"circles#update"]) { | |
| id circlesToAdd = call.arguments[@"circlesToAdd"]; | |
| if ([circlesToAdd isKindOfClass:[NSArray class]]) { | |
| [_circlesController addCircles:circlesToAdd]; | |
| } | |
| id circlesToChange = call.arguments[@"circlesToChange"]; | |
| if ([circlesToChange isKindOfClass:[NSArray class]]) { | |
| [_circlesController changeCircles:circlesToChange]; | |
| } | |
| id circleIdsToRemove = call.arguments[@"circleIdsToRemove"]; | |
| if ([circleIdsToRemove isKindOfClass:[NSArray class]]) { | |
| [_circlesController removeCircleIds:circleIdsToRemove]; | |
| } | |
| result(nil); | |
| } else if ([call.method isEqualToString:@"map#isCompassEnabled"]) { | |
| NSNumber* isCompassEnabled = @(_mapView.settings.compassButton); | |
| result(isCompassEnabled); | |
| } else if ([call.method isEqualToString:@"map#isMapToolbarEnabled"]) { | |
| NSNumber* isMapToolbarEnabled = [NSNumber numberWithBool:NO]; | |
| result(isMapToolbarEnabled); | |
| } else if ([call.method isEqualToString:@"map#getMinMaxZoomLevels"]) { | |
| NSArray* zoomLevels = @[ @(_mapView.minZoom), @(_mapView.maxZoom) ]; | |
| result(zoomLevels); | |
| } else if ([call.method isEqualToString:@"map#isZoomGesturesEnabled"]) { | |
| NSNumber* isZoomGesturesEnabled = @(_mapView.settings.zoomGestures); | |
| result(isZoomGesturesEnabled); | |
| } else if ([call.method isEqualToString:@"map#isTiltGesturesEnabled"]) { | |
| NSNumber* isTiltGesturesEnabled = @(_mapView.settings.tiltGestures); | |
| result(isTiltGesturesEnabled); | |
| } else if ([call.method isEqualToString:@"map#isRotateGesturesEnabled"]) { | |
| NSNumber* isRotateGesturesEnabled = @(_mapView.settings.rotateGestures); | |
| result(isRotateGesturesEnabled); | |
| } else if ([call.method isEqualToString:@"map#isScrollGesturesEnabled"]) { | |
| NSNumber* isScrollGesturesEnabled = @(_mapView.settings.scrollGestures); | |
| result(isScrollGesturesEnabled); | |
| } else if ([call.method isEqualToString:@"map#isMyLocationButtonEnabled"]) { | |
| NSNumber* isMyLocationButtonEnabled = @(_mapView.settings.myLocationButton); | |
| result(isMyLocationButtonEnabled); | |
| } else if ([call.method isEqualToString:@"map#isTrafficEnabled"]) { | |
| NSNumber* isTrafficEnabled = @(_mapView.trafficEnabled); | |
| result(isTrafficEnabled); | |
| } else if ([call.method isEqualToString:@"map#setStyle"]) { | |
| NSString* mapStyle = [call arguments]; | |
| NSString* error = [self setMapStyle:mapStyle]; | |
| if (error == nil) { | |
| result(@[ @(YES) ]); | |
| } else { | |
| result(@[ @(NO), error ]); | |
| } | |
| } else { | |
| result(FlutterMethodNotImplemented); | |
| } | |
| } | |
| - (void)showAtX:(CGFloat)x Y:(CGFloat)y { | |
| _mapView.frame = | |
| CGRectMake(x, y, CGRectGetWidth(_mapView.frame), CGRectGetHeight(_mapView.frame)); | |
| _mapView.hidden = NO; | |
| } | |
| - (void)hide { | |
| _mapView.hidden = YES; | |
| } | |
| - (void)animateWithCameraUpdate:(GMSCameraUpdate*)cameraUpdate { | |
| [_mapView animateWithCameraUpdate:cameraUpdate]; | |
| } | |
| - (void)moveWithCameraUpdate:(GMSCameraUpdate*)cameraUpdate { | |
| [_mapView moveCamera:cameraUpdate]; | |
| } | |
| - (GMSCameraPosition*)cameraPosition { | |
| if (_trackCameraPosition) { | |
| return _mapView.camera; | |
| } else { | |
| return nil; | |
| } | |
| } | |
| #pragma mark - FLTGoogleMapOptionsSink methods | |
| - (void)setCamera:(GMSCameraPosition*)camera { | |
| _mapView.camera = camera; | |
| } | |
| - (void)setCameraTargetBounds:(GMSCoordinateBounds*)bounds { | |
| _mapView.cameraTargetBounds = bounds; | |
| } | |
| - (void)setCompassEnabled:(BOOL)enabled { | |
| _mapView.settings.compassButton = enabled; | |
| } | |
| - (void)setIndoorEnabled:(BOOL)enabled { | |
| _mapView.indoorEnabled = enabled; | |
| } | |
| - (void)setTrafficEnabled:(BOOL)enabled { | |
| _mapView.trafficEnabled = enabled; | |
| } | |
| - (void)setMapType:(GMSMapViewType)mapType { | |
| _mapView.mapType = mapType; | |
| } | |
| - (void)setMinZoom:(float)minZoom maxZoom:(float)maxZoom { | |
| [_mapView setMinZoom:minZoom maxZoom:maxZoom]; | |
| } | |
| - (void)setPaddingTop:(float)top left:(float)left bottom:(float)bottom right:(float)right { | |
| _mapView.padding = UIEdgeInsetsMake(top, left, bottom, right); | |
| } | |
| - (void)setRotateGesturesEnabled:(BOOL)enabled { | |
| _mapView.settings.rotateGestures = enabled; | |
| } | |
| - (void)setScrollGesturesEnabled:(BOOL)enabled { | |
| _mapView.settings.scrollGestures = enabled; | |
| } | |
| - (void)setTiltGesturesEnabled:(BOOL)enabled { | |
| _mapView.settings.tiltGestures = enabled; | |
| } | |
| - (void)setTrackCameraPosition:(BOOL)enabled { | |
| _trackCameraPosition = enabled; | |
| } | |
| - (void)setZoomGesturesEnabled:(BOOL)enabled { | |
| _mapView.settings.zoomGestures = enabled; | |
| } | |
| - (void)setMyLocationEnabled:(BOOL)enabled { | |
| _mapView.myLocationEnabled = enabled; | |
| } | |
| - (void)setMyLocationButtonEnabled:(BOOL)enabled { | |
| _mapView.settings.myLocationButton = enabled; | |
| } | |
| - (NSString*)setMapStyle:(NSString*)mapStyle { | |
| if (mapStyle == (id)[NSNull null] || mapStyle.length == 0) { | |
| _mapView.mapStyle = nil; | |
| return nil; | |
| } | |
| NSError* error; | |
| GMSMapStyle* style = [GMSMapStyle styleWithJSONString:mapStyle error:&error]; | |
| if (!style) { | |
| return [error localizedDescription]; | |
| } else { | |
| _mapView.mapStyle = style; | |
| return nil; | |
| } | |
| } | |
| #pragma mark - GMSMapViewDelegate methods | |
| - (void)mapView:(GMSMapView*)mapView willMove:(BOOL)gesture { | |
| [_channel invokeMethod:@"camera#onMoveStarted" arguments:@{@"isGesture" : @(gesture)}]; | |
| } | |
| - (void)mapView:(GMSMapView*)mapView didChangeCameraPosition:(GMSCameraPosition*)position { | |
| if (!_cameraDidInitialSetup) { | |
| // We suspected a bug in the iOS Google Maps SDK caused the camera is not properly positioned at | |
| // initialization. https://github.com/flutter/flutter/issues/24806 | |
| // This temporary workaround fix is provided while the actual fix in the Google Maps SDK is | |
| // still being investigated. | |
| // TODO(cyanglaz): Remove this temporary fix once the Maps SDK issue is resolved. | |
| // https://github.com/flutter/flutter/issues/27550 | |
| _cameraDidInitialSetup = YES; | |
| [mapView moveCamera:[GMSCameraUpdate setCamera:_mapView.camera]]; | |
| } | |
| if (_trackCameraPosition) { | |
| [_channel invokeMethod:@"camera#onMove" arguments:@{@"position" : PositionToJson(position)}]; | |
| } | |
| } | |
| - (void)mapView:(GMSMapView*)mapView idleAtCameraPosition:(GMSCameraPosition*)position { | |
| [_channel invokeMethod:@"camera#onIdle" arguments:@{}]; | |
| } | |
| - (BOOL)mapView:(GMSMapView*)mapView didTapMarker:(GMSMarker*)marker { | |
| NSString* markerId = marker.userData[0]; | |
| return [_markersController onMarkerTap:markerId]; | |
| } | |
| - (void)mapView:(GMSMapView*)mapView didEndDraggingMarker:(GMSMarker*)marker { | |
| NSString* markerId = marker.userData[0]; | |
| [_markersController onMarkerDragEnd:markerId coordinate:marker.position]; | |
| } | |
| - (void)mapView:(GMSMapView*)mapView didTapInfoWindowOfMarker:(GMSMarker*)marker { | |
| NSString* markerId = marker.userData[0]; | |
| [_markersController onInfoWindowTap:markerId]; | |
| } | |
| - (void)mapView:(GMSMapView*)mapView didTapOverlay:(GMSOverlay*)overlay { | |
| NSString* overlayId = overlay.userData[0]; | |
| if ([_polylinesController hasPolylineWithId:overlayId]) { | |
| [_polylinesController onPolylineTap:overlayId]; | |
| } else if ([_polygonsController hasPolygonWithId:overlayId]) { | |
| [_polygonsController onPolygonTap:overlayId]; | |
| } else if ([_circlesController hasCircleWithId:overlayId]) { | |
| [_circlesController onCircleTap:overlayId]; | |
| } | |
| } | |
| - (void)mapView:(GMSMapView*)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { | |
| [_channel invokeMethod:@"map#onTap" arguments:@{@"position" : LocationToJson(coordinate)}]; | |
| } | |
| - (void)mapView:(GMSMapView*)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { | |
| [_channel invokeMethod:@"map#onLongPress" arguments:@{@"position" : LocationToJson(coordinate)}]; | |
| } | |
| @end | |
| #pragma mark - Implementations of JSON conversion functions. | |
| static NSArray* LocationToJson(CLLocationCoordinate2D position) { | |
| return @[ @(position.latitude), @(position.longitude) ]; | |
| } | |
| static NSDictionary* PositionToJson(GMSCameraPosition* position) { | |
| if (!position) { | |
| return nil; | |
| } | |
| return @{ | |
| @"target" : LocationToJson([position target]), | |
| @"zoom" : @([position zoom]), | |
| @"bearing" : @([position bearing]), | |
| @"tilt" : @([position viewingAngle]), | |
| }; | |
| } | |
| static NSDictionary* PointToJson(CGPoint point) { | |
| return @{ | |
| @"x" : @((int)point.x), | |
| @"y" : @((int)point.y), | |
| }; | |
| } | |
| static NSDictionary* GMSCoordinateBoundsToJson(GMSCoordinateBounds* bounds) { | |
| if (!bounds) { | |
| return nil; | |
| } | |
| return @{ | |
| @"southwest" : LocationToJson([bounds southWest]), | |
| @"northeast" : LocationToJson([bounds northEast]), | |
| }; | |
| } | |
| static float ToFloat(NSNumber* data) { return [FLTGoogleMapJsonConversions toFloat:data]; } | |
| static CLLocationCoordinate2D ToLocation(NSArray* data) { | |
| return [FLTGoogleMapJsonConversions toLocation:data]; | |
| } | |
| static int ToInt(NSNumber* data) { return [FLTGoogleMapJsonConversions toInt:data]; } | |
| static BOOL ToBool(NSNumber* data) { return [FLTGoogleMapJsonConversions toBool:data]; } | |
| static CGPoint ToPoint(NSArray* data) { return [FLTGoogleMapJsonConversions toPoint:data]; } | |
| static GMSCameraPosition* ToCameraPosition(NSDictionary* data) { | |
| return [GMSCameraPosition cameraWithTarget:ToLocation(data[@"target"]) | |
| zoom:ToFloat(data[@"zoom"]) | |
| bearing:ToDouble(data[@"bearing"]) | |
| viewingAngle:ToDouble(data[@"tilt"])]; | |
| } | |
| static GMSCameraPosition* ToOptionalCameraPosition(NSDictionary* json) { | |
| return json ? ToCameraPosition(json) : nil; | |
| } | |
| static CGPoint ToCGPoint(NSDictionary* json) { | |
| double x = ToDouble(json[@"x"]); | |
| double y = ToDouble(json[@"y"]); | |
| return CGPointMake(x, y); | |
| } | |
| static GMSCoordinateBounds* ToBounds(NSArray* data) { | |
| return [[GMSCoordinateBounds alloc] initWithCoordinate:ToLocation(data[0]) | |
| coordinate:ToLocation(data[1])]; | |
| } | |
| static GMSCoordinateBounds* ToOptionalBounds(NSArray* data) { | |
| return (data[0] == [NSNull null]) ? nil : ToBounds(data[0]); | |
| } | |
| static GMSMapViewType ToMapViewType(NSNumber* json) { | |
| int value = ToInt(json); | |
| return (GMSMapViewType)(value == 0 ? 5 : value); | |
| } | |
| static GMSCameraUpdate* ToCameraUpdate(NSArray* data) { | |
| NSString* update = data[0]; | |
| if ([update isEqualToString:@"newCameraPosition"]) { | |
| return [GMSCameraUpdate setCamera:ToCameraPosition(data[1])]; | |
| } else if ([update isEqualToString:@"newLatLng"]) { | |
| return [GMSCameraUpdate setTarget:ToLocation(data[1])]; | |
| } else if ([update isEqualToString:@"newLatLngBounds"]) { | |
| return [GMSCameraUpdate fitBounds:ToBounds(data[1]) withPadding:ToDouble(data[2])]; | |
| } else if ([update isEqualToString:@"newLatLngZoom"]) { | |
| return [GMSCameraUpdate setTarget:ToLocation(data[1]) zoom:ToFloat(data[2])]; | |
| } else if ([update isEqualToString:@"scrollBy"]) { | |
| return [GMSCameraUpdate scrollByX:ToDouble(data[1]) Y:ToDouble(data[2])]; | |
| } else if ([update isEqualToString:@"zoomBy"]) { | |
| if (data.count == 2) { | |
| return [GMSCameraUpdate zoomBy:ToFloat(data[1])]; | |
| } else { | |
| return [GMSCameraUpdate zoomBy:ToFloat(data[1]) atPoint:ToPoint(data[2])]; | |
| } | |
| } else if ([update isEqualToString:@"zoomIn"]) { | |
| return [GMSCameraUpdate zoomIn]; | |
| } else if ([update isEqualToString:@"zoomOut"]) { | |
| return [GMSCameraUpdate zoomOut]; | |
| } else if ([update isEqualToString:@"zoomTo"]) { | |
| return [GMSCameraUpdate zoomTo:ToFloat(data[1])]; | |
| } | |
| return nil; | |
| } | |
| static void InterpretMapOptions(NSDictionary* data, id<FLTGoogleMapOptionsSink> sink) { | |
| NSArray* cameraTargetBounds = data[@"cameraTargetBounds"]; | |
| if (cameraTargetBounds) { | |
| [sink setCameraTargetBounds:ToOptionalBounds(cameraTargetBounds)]; | |
| } | |
| NSNumber* compassEnabled = data[@"compassEnabled"]; | |
| if (compassEnabled != nil) { | |
| [sink setCompassEnabled:ToBool(compassEnabled)]; | |
| } | |
| id indoorEnabled = data[@"indoorEnabled"]; | |
| if (indoorEnabled) { | |
| [sink setIndoorEnabled:ToBool(indoorEnabled)]; | |
| } | |
| id trafficEnabled = data[@"trafficEnabled"]; | |
| if (trafficEnabled) { | |
| [sink setTrafficEnabled:ToBool(trafficEnabled)]; | |
| } | |
| id mapType = data[@"mapType"]; | |
| if (mapType) { | |
| [sink setMapType:ToMapViewType(mapType)]; | |
| } | |
| NSArray* zoomData = data[@"minMaxZoomPreference"]; | |
| if (zoomData) { | |
| float minZoom = (zoomData[0] == [NSNull null]) ? kGMSMinZoomLevel : ToFloat(zoomData[0]); | |
| float maxZoom = (zoomData[1] == [NSNull null]) ? kGMSMaxZoomLevel : ToFloat(zoomData[1]); | |
| [sink setMinZoom:minZoom maxZoom:maxZoom]; | |
| } | |
| NSArray* paddingData = data[@"padding"]; | |
| if (paddingData) { | |
| float top = (paddingData[0] == [NSNull null]) ? 0 : ToFloat(paddingData[0]); | |
| float left = (paddingData[1] == [NSNull null]) ? 0 : ToFloat(paddingData[1]); | |
| float bottom = (paddingData[2] == [NSNull null]) ? 0 : ToFloat(paddingData[2]); | |
| float right = (paddingData[3] == [NSNull null]) ? 0 : ToFloat(paddingData[3]); | |
| [sink setPaddingTop:top left:left bottom:bottom right:right]; | |
| } | |
| NSNumber* rotateGesturesEnabled = data[@"rotateGesturesEnabled"]; | |
| if (rotateGesturesEnabled != nil) { | |
| [sink setRotateGesturesEnabled:ToBool(rotateGesturesEnabled)]; | |
| } | |
| NSNumber* scrollGesturesEnabled = data[@"scrollGesturesEnabled"]; | |
| if (scrollGesturesEnabled != nil) { | |
| [sink setScrollGesturesEnabled:ToBool(scrollGesturesEnabled)]; | |
| } | |
| NSNumber* tiltGesturesEnabled = data[@"tiltGesturesEnabled"]; | |
| if (tiltGesturesEnabled != nil) { | |
| [sink setTiltGesturesEnabled:ToBool(tiltGesturesEnabled)]; | |
| } | |
| NSNumber* trackCameraPosition = data[@"trackCameraPosition"]; | |
| if (trackCameraPosition != nil) { | |
| [sink setTrackCameraPosition:ToBool(trackCameraPosition)]; | |
| } | |
| NSNumber* zoomGesturesEnabled = data[@"zoomGesturesEnabled"]; | |
| if (zoomGesturesEnabled != nil) { | |
| [sink setZoomGesturesEnabled:ToBool(zoomGesturesEnabled)]; | |
| } | |
| NSNumber* myLocationEnabled = data[@"myLocationEnabled"]; | |
| if (myLocationEnabled != nil) { | |
| [sink setMyLocationEnabled:ToBool(myLocationEnabled)]; | |
| } | |
| NSNumber* myLocationButtonEnabled = data[@"myLocationButtonEnabled"]; | |
| if (myLocationButtonEnabled != nil) { | |
| [sink setMyLocationButtonEnabled:ToBool(myLocationButtonEnabled)]; | |
| } | |
| } |