| // Copyright 2013 The Flutter 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 "FLTGoogleMapTileOverlayController.h" |
| #import "JsonConversions.h" |
| |
| static void InterpretTileOverlayOptions(NSDictionary *data, |
| id<FLTGoogleMapTileOverlayOptionsSink> sink, |
| NSObject<FlutterPluginRegistrar> *registrar) { |
| NSNumber *visible = data[@"visible"]; |
| if (visible != nil) { |
| [sink setVisible:visible.boolValue]; |
| } |
| |
| NSNumber *transparency = data[@"transparency"]; |
| if (transparency != nil) { |
| [sink setTransparency:transparency.floatValue]; |
| } |
| |
| NSNumber *zIndex = data[@"zIndex"]; |
| if (zIndex != nil) { |
| [sink setZIndex:zIndex.intValue]; |
| } |
| |
| NSNumber *fadeIn = data[@"fadeIn"]; |
| if (fadeIn != nil) { |
| [sink setFadeIn:fadeIn.boolValue]; |
| } |
| |
| NSNumber *tileSize = data[@"tileSize"]; |
| if (tileSize != nil) { |
| [sink setTileSize:tileSize.integerValue]; |
| } |
| } |
| |
| @interface FLTGoogleMapTileOverlayController () |
| |
| @property(strong, nonatomic) GMSTileLayer *layer; |
| @property(weak, nonatomic) GMSMapView *mapView; |
| |
| @end |
| |
| @implementation FLTGoogleMapTileOverlayController |
| |
| - (instancetype)initWithTileLayer:(GMSTileLayer *)tileLayer mapView:(GMSMapView *)mapView { |
| self = [super init]; |
| if (self) { |
| self.layer = tileLayer; |
| self.mapView = mapView; |
| } |
| return self; |
| } |
| |
| - (void)removeTileOverlay { |
| self.layer.map = nil; |
| } |
| |
| - (void)clearTileCache { |
| [self.layer clearTileCache]; |
| } |
| |
| - (NSDictionary *)getTileOverlayInfo { |
| NSMutableDictionary *info = [[NSMutableDictionary alloc] init]; |
| BOOL visible = self.layer.map != nil; |
| info[@"visible"] = @(visible); |
| info[@"fadeIn"] = @(self.layer.fadeIn); |
| float transparency = 1.0 - self.layer.opacity; |
| info[@"transparency"] = @(transparency); |
| info[@"zIndex"] = @(self.layer.zIndex); |
| return info; |
| } |
| |
| #pragma mark - FLTGoogleMapTileOverlayOptionsSink methods |
| |
| - (void)setFadeIn:(BOOL)fadeIn { |
| self.layer.fadeIn = fadeIn; |
| } |
| |
| - (void)setTransparency:(float)transparency { |
| float opacity = 1.0 - transparency; |
| self.layer.opacity = opacity; |
| } |
| |
| - (void)setVisible:(BOOL)visible { |
| self.layer.map = visible ? self.mapView : nil; |
| } |
| |
| - (void)setZIndex:(int)zIndex { |
| self.layer.zIndex = zIndex; |
| } |
| |
| - (void)setTileSize:(NSInteger)tileSize { |
| self.layer.tileSize = tileSize; |
| } |
| @end |
| |
| @interface FLTTileProviderController () |
| |
| @property(weak, nonatomic) FlutterMethodChannel *methodChannel; |
| @property(copy, nonatomic, readwrite) NSString *tileOverlayId; |
| |
| @end |
| |
| @implementation FLTTileProviderController |
| |
| - (instancetype)init:(FlutterMethodChannel *)methodChannel tileOverlayId:(NSString *)tileOverlayId { |
| self = [super init]; |
| if (self) { |
| self.methodChannel = methodChannel; |
| self.tileOverlayId = tileOverlayId; |
| } |
| return self; |
| } |
| |
| #pragma mark - GMSTileLayer method |
| |
| - (void)requestTileForX:(NSUInteger)x |
| y:(NSUInteger)y |
| zoom:(NSUInteger)zoom |
| receiver:(id<GMSTileReceiver>)receiver { |
| [self.methodChannel |
| invokeMethod:@"tileOverlay#getTile" |
| arguments:@{ |
| @"tileOverlayId" : self.tileOverlayId, |
| @"x" : @(x), |
| @"y" : @(y), |
| @"zoom" : @(zoom) |
| } |
| result:^(id _Nullable result) { |
| UIImage *tileImage; |
| if ([result isKindOfClass:[NSDictionary class]]) { |
| FlutterStandardTypedData *typedData = (FlutterStandardTypedData *)result[@"data"]; |
| if (typedData == nil) { |
| tileImage = kGMSTileLayerNoTile; |
| } else { |
| tileImage = [UIImage imageWithData:typedData.data]; |
| } |
| } else { |
| if ([result isKindOfClass:[FlutterError class]]) { |
| FlutterError *error = (FlutterError *)result; |
| NSLog(@"Can't get tile: errorCode = %@, errorMessage = %@, details = %@", |
| [error code], [error message], [error details]); |
| } |
| if ([result isKindOfClass:[FlutterMethodNotImplemented class]]) { |
| NSLog(@"Can't get tile: notImplemented"); |
| } |
| tileImage = kGMSTileLayerNoTile; |
| } |
| |
| [receiver receiveTileWithX:x y:y zoom:zoom image:tileImage]; |
| }]; |
| } |
| |
| @end |
| |
| @interface FLTTileOverlaysController () |
| |
| @property(strong, nonatomic) NSMutableDictionary *tileOverlayIdToController; |
| @property(weak, nonatomic) FlutterMethodChannel *methodChannel; |
| @property(weak, nonatomic) NSObject<FlutterPluginRegistrar> *registrar; |
| @property(weak, nonatomic) GMSMapView *mapView; |
| |
| @end |
| |
| @implementation FLTTileOverlaysController |
| |
| - (instancetype)init:(FlutterMethodChannel *)methodChannel |
| mapView:(GMSMapView *)mapView |
| registrar:(NSObject<FlutterPluginRegistrar> *)registrar { |
| self = [super init]; |
| if (self) { |
| self.methodChannel = methodChannel; |
| self.mapView = mapView; |
| self.tileOverlayIdToController = [[NSMutableDictionary alloc] init]; |
| self.registrar = registrar; |
| } |
| return self; |
| } |
| |
| - (void)addTileOverlays:(NSArray *)tileOverlaysToAdd { |
| for (NSDictionary *tileOverlay in tileOverlaysToAdd) { |
| NSString *tileOverlayId = [FLTTileOverlaysController getTileOverlayId:tileOverlay]; |
| FLTTileProviderController *tileProvider = |
| [[FLTTileProviderController alloc] init:self.methodChannel tileOverlayId:tileOverlayId]; |
| FLTGoogleMapTileOverlayController *controller = |
| [[FLTGoogleMapTileOverlayController alloc] initWithTileLayer:tileProvider |
| mapView:self.mapView]; |
| InterpretTileOverlayOptions(tileOverlay, controller, self.registrar); |
| self.tileOverlayIdToController[tileOverlayId] = controller; |
| } |
| } |
| |
| - (void)changeTileOverlays:(NSArray *)tileOverlaysToChange { |
| for (NSDictionary *tileOverlay in tileOverlaysToChange) { |
| NSString *tileOverlayId = [FLTTileOverlaysController getTileOverlayId:tileOverlay]; |
| FLTGoogleMapTileOverlayController *controller = self.tileOverlayIdToController[tileOverlayId]; |
| if (!controller) { |
| continue; |
| } |
| InterpretTileOverlayOptions(tileOverlay, controller, self.registrar); |
| } |
| } |
| - (void)removeTileOverlayIds:(NSArray *)tileOverlayIdsToRemove { |
| for (NSString *tileOverlayId in tileOverlayIdsToRemove) { |
| FLTGoogleMapTileOverlayController *controller = self.tileOverlayIdToController[tileOverlayId]; |
| if (!controller) { |
| continue; |
| } |
| [controller removeTileOverlay]; |
| [self.tileOverlayIdToController removeObjectForKey:tileOverlayId]; |
| } |
| } |
| |
| - (void)clearTileCache:(NSString *)tileOverlayId { |
| FLTGoogleMapTileOverlayController *controller = self.tileOverlayIdToController[tileOverlayId]; |
| if (!controller) { |
| return; |
| } |
| [controller clearTileCache]; |
| } |
| |
| - (nullable NSDictionary *)getTileOverlayInfo:(NSString *)tileverlayId { |
| if (self.tileOverlayIdToController[tileverlayId] == nil) { |
| return nil; |
| } |
| return [self.tileOverlayIdToController[tileverlayId] getTileOverlayInfo]; |
| } |
| |
| + (NSString *)getTileOverlayId:(NSDictionary *)tileOverlay { |
| return tileOverlay[@"tileOverlayId"]; |
| } |
| |
| @end |