@lugg/maps 1.0.0-beta.3 → 1.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/README.md +3 -0
  2. package/android/src/main/java/com/luggmaps/LuggCalloutView.kt +4 -2
  3. package/android/src/main/java/com/luggmaps/LuggCalloutViewManager.kt +4 -3
  4. package/android/src/main/java/com/luggmaps/LuggCircleView.kt +85 -0
  5. package/android/src/main/java/com/luggmaps/LuggCircleViewManager.kt +79 -0
  6. package/android/src/main/java/com/luggmaps/LuggGroundOverlayView.kt +81 -0
  7. package/android/src/main/java/com/luggmaps/LuggGroundOverlayViewManager.kt +82 -0
  8. package/android/src/main/java/com/luggmaps/LuggMapView.kt +49 -0
  9. package/android/src/main/java/com/luggmaps/LuggMapViewManager.kt +31 -0
  10. package/android/src/main/java/com/luggmaps/LuggMarkerView.kt +23 -0
  11. package/android/src/main/java/com/luggmaps/LuggMarkerViewManager.kt +13 -0
  12. package/android/src/main/java/com/luggmaps/LuggPackage.kt +4 -1
  13. package/android/src/main/java/com/luggmaps/LuggTileOverlayView.kt +92 -0
  14. package/android/src/main/java/com/luggmaps/LuggTileOverlayViewManager.kt +80 -0
  15. package/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +451 -17
  16. package/android/src/main/java/com/luggmaps/core/MapProviderDelegate.kt +14 -0
  17. package/android/src/main/java/com/luggmaps/events/CirclePressEvent.kt +12 -0
  18. package/android/src/main/java/com/luggmaps/events/GroundOverlayPressEvent.kt +12 -0
  19. package/android/src/main/java/com/luggmaps/events/TileOverlayPressEvent.kt +12 -0
  20. package/android/src/main/java/com/luggmaps/extensions/ViewExtensions.kt +11 -0
  21. package/ios/LuggCalloutView.h +1 -1
  22. package/ios/LuggCalloutView.mm +21 -11
  23. package/ios/LuggCircleView.h +31 -0
  24. package/ios/LuggCircleView.mm +133 -0
  25. package/ios/LuggGroundOverlayView.h +30 -0
  26. package/ios/LuggGroundOverlayView.mm +125 -0
  27. package/ios/LuggMapView.mm +84 -2
  28. package/ios/LuggMarkerView.h +3 -0
  29. package/ios/LuggMarkerView.mm +23 -0
  30. package/ios/LuggTileOverlayView.h +31 -0
  31. package/ios/LuggTileOverlayView.mm +130 -0
  32. package/ios/core/AppleMapProvider.mm +595 -17
  33. package/ios/core/GoogleMapProvider.mm +390 -28
  34. package/ios/core/MapProviderDelegate.h +20 -1
  35. package/ios/events/CirclePressEvent.h +20 -0
  36. package/ios/events/GroundOverlayPressEvent.h +20 -0
  37. package/ios/events/TileOverlayPressEvent.h +20 -0
  38. package/lib/module/MapView.js +11 -0
  39. package/lib/module/MapView.js.map +1 -1
  40. package/lib/module/MapView.web.js +3 -0
  41. package/lib/module/MapView.web.js.map +1 -1
  42. package/lib/module/components/Circle.js +46 -0
  43. package/lib/module/components/Circle.js.map +1 -0
  44. package/lib/module/components/Circle.types.js +4 -0
  45. package/lib/module/components/Circle.types.js.map +1 -0
  46. package/lib/module/components/Circle.web.js +79 -0
  47. package/lib/module/components/Circle.web.js.map +1 -0
  48. package/lib/module/components/GroundOverlay.js +45 -0
  49. package/lib/module/components/GroundOverlay.js.map +1 -0
  50. package/lib/module/components/GroundOverlay.types.js +4 -0
  51. package/lib/module/components/GroundOverlay.types.js.map +1 -0
  52. package/lib/module/components/GroundOverlay.web.js +77 -0
  53. package/lib/module/components/GroundOverlay.web.js.map +1 -0
  54. package/lib/module/components/Marker.js +22 -4
  55. package/lib/module/components/Marker.js.map +1 -1
  56. package/lib/module/components/Marker.web.js +20 -7
  57. package/lib/module/components/Marker.web.js.map +1 -1
  58. package/lib/module/components/TileOverlay.js +44 -0
  59. package/lib/module/components/TileOverlay.js.map +1 -0
  60. package/lib/module/components/TileOverlay.types.js +4 -0
  61. package/lib/module/components/TileOverlay.types.js.map +1 -0
  62. package/lib/module/components/TileOverlay.web.js +69 -0
  63. package/lib/module/components/TileOverlay.web.js.map +1 -0
  64. package/lib/module/components/index.js +3 -0
  65. package/lib/module/components/index.js.map +1 -1
  66. package/lib/module/components/index.web.js +3 -0
  67. package/lib/module/components/index.web.js.map +1 -1
  68. package/lib/module/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  69. package/lib/module/fabric/LuggCircleViewNativeComponent.ts +25 -0
  70. package/lib/module/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  71. package/lib/module/fabric/LuggMapViewNativeComponent.ts +9 -1
  72. package/lib/module/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  73. package/lib/module/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  74. package/lib/module/index.js +3 -0
  75. package/lib/module/index.js.map +1 -1
  76. package/lib/module/index.web.js +3 -0
  77. package/lib/module/index.web.js.map +1 -1
  78. package/lib/typescript/src/MapView.d.ts.map +1 -1
  79. package/lib/typescript/src/MapView.types.d.ts +36 -1
  80. package/lib/typescript/src/MapView.types.d.ts.map +1 -1
  81. package/lib/typescript/src/MapView.web.d.ts.map +1 -1
  82. package/lib/typescript/src/components/Circle.d.ts +10 -0
  83. package/lib/typescript/src/components/Circle.d.ts.map +1 -0
  84. package/lib/typescript/src/components/Circle.types.d.ts +33 -0
  85. package/lib/typescript/src/components/Circle.types.d.ts.map +1 -0
  86. package/lib/typescript/src/components/Circle.web.d.ts +3 -0
  87. package/lib/typescript/src/components/Circle.web.d.ts.map +1 -0
  88. package/lib/typescript/src/components/GroundOverlay.d.ts +10 -0
  89. package/lib/typescript/src/components/GroundOverlay.d.ts.map +1 -0
  90. package/lib/typescript/src/components/GroundOverlay.types.d.ts +35 -0
  91. package/lib/typescript/src/components/GroundOverlay.types.d.ts.map +1 -0
  92. package/lib/typescript/src/components/GroundOverlay.web.d.ts +3 -0
  93. package/lib/typescript/src/components/GroundOverlay.web.d.ts.map +1 -0
  94. package/lib/typescript/src/components/Marker.d.ts +6 -3
  95. package/lib/typescript/src/components/Marker.d.ts.map +1 -1
  96. package/lib/typescript/src/components/Marker.types.d.ts +18 -6
  97. package/lib/typescript/src/components/Marker.types.d.ts.map +1 -1
  98. package/lib/typescript/src/components/Marker.web.d.ts +3 -2
  99. package/lib/typescript/src/components/Marker.web.d.ts.map +1 -1
  100. package/lib/typescript/src/components/TileOverlay.d.ts +10 -0
  101. package/lib/typescript/src/components/TileOverlay.d.ts.map +1 -0
  102. package/lib/typescript/src/components/TileOverlay.types.d.ts +36 -0
  103. package/lib/typescript/src/components/TileOverlay.types.d.ts.map +1 -0
  104. package/lib/typescript/src/components/TileOverlay.web.d.ts +3 -0
  105. package/lib/typescript/src/components/TileOverlay.web.d.ts.map +1 -0
  106. package/lib/typescript/src/components/index.d.ts +7 -1
  107. package/lib/typescript/src/components/index.d.ts.map +1 -1
  108. package/lib/typescript/src/components/index.web.d.ts +6 -0
  109. package/lib/typescript/src/components/index.web.d.ts.map +1 -1
  110. package/lib/typescript/src/fabric/LuggCalloutViewNativeComponent.d.ts +1 -1
  111. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts +18 -0
  112. package/lib/typescript/src/fabric/LuggCircleViewNativeComponent.d.ts.map +1 -0
  113. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts +21 -0
  114. package/lib/typescript/src/fabric/LuggGroundOverlayViewNativeComponent.d.ts.map +1 -0
  115. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts +6 -1
  116. package/lib/typescript/src/fabric/LuggMapViewNativeComponent.d.ts.map +1 -1
  117. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts +8 -1
  118. package/lib/typescript/src/fabric/LuggMarkerViewNativeComponent.d.ts.map +1 -1
  119. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts +21 -0
  120. package/lib/typescript/src/fabric/LuggTileOverlayViewNativeComponent.d.ts.map +1 -0
  121. package/lib/typescript/src/index.d.ts +9 -3
  122. package/lib/typescript/src/index.d.ts.map +1 -1
  123. package/lib/typescript/src/index.web.d.ts +7 -1
  124. package/lib/typescript/src/index.web.d.ts.map +1 -1
  125. package/lib/typescript/src/types.d.ts +0 -4
  126. package/lib/typescript/src/types.d.ts.map +1 -1
  127. package/package.json +5 -2
  128. package/src/MapView.tsx +11 -0
  129. package/src/MapView.types.ts +85 -1
  130. package/src/MapView.web.tsx +11 -0
  131. package/src/components/Circle.tsx +52 -0
  132. package/src/components/Circle.types.ts +33 -0
  133. package/src/components/Circle.web.tsx +93 -0
  134. package/src/components/GroundOverlay.tsx +47 -0
  135. package/src/components/GroundOverlay.types.ts +36 -0
  136. package/src/components/GroundOverlay.web.tsx +85 -0
  137. package/src/components/Marker.tsx +32 -6
  138. package/src/components/Marker.types.ts +19 -6
  139. package/src/components/Marker.web.tsx +191 -148
  140. package/src/components/TileOverlay.tsx +44 -0
  141. package/src/components/TileOverlay.types.ts +37 -0
  142. package/src/components/TileOverlay.web.tsx +95 -0
  143. package/src/components/index.ts +10 -0
  144. package/src/components/index.web.ts +9 -0
  145. package/src/fabric/LuggCalloutViewNativeComponent.ts +1 -1
  146. package/src/fabric/LuggCircleViewNativeComponent.ts +25 -0
  147. package/src/fabric/LuggGroundOverlayViewNativeComponent.ts +29 -0
  148. package/src/fabric/LuggMapViewNativeComponent.ts +9 -1
  149. package/src/fabric/LuggMarkerViewNativeComponent.ts +14 -2
  150. package/src/fabric/LuggTileOverlayViewNativeComponent.ts +30 -0
  151. package/src/index.ts +12 -1
  152. package/src/index.web.ts +15 -0
  153. package/src/types.ts +0 -5
@@ -1,8 +1,17 @@
1
1
  #import "AppleMapProvider.h"
2
+
3
+ using facebook::react::LuggMapViewInsetAdjustment;
4
+ using facebook::react::LuggMapViewMapType;
5
+ using facebook::react::LuggMapViewPoiFilterMode;
6
+ using facebook::react::LuggMapViewTheme;
7
+
2
8
  #import "../LuggCalloutView.h"
9
+ #import "../LuggCircleView.h"
10
+ #import "../LuggGroundOverlayView.h"
3
11
  #import "../LuggMarkerView.h"
4
12
  #import "../LuggPolygonView.h"
5
13
  #import "../LuggPolylineView.h"
14
+ #import "../LuggTileOverlayView.h"
6
15
  #import "../extensions/MKMapView+Zoom.h"
7
16
  #import "LuggAnnotationView.h"
8
17
  #import "MKPolylineAnimator.h"
@@ -19,12 +28,90 @@
19
28
  @implementation AppleMarkerAnnotation
20
29
  @end
21
30
 
31
+ @interface GroundImageOverlay : NSObject <MKOverlay>
32
+ @property(nonatomic, assign) CLLocationCoordinate2D coordinate;
33
+ @property(nonatomic, assign) MKMapRect boundingMapRect;
34
+ @property(nonatomic, strong) UIImage *image;
35
+ @property(nonatomic, assign) CGFloat opacity;
36
+ @end
37
+
38
+ @implementation GroundImageOverlay
39
+ @end
40
+
41
+ @interface BoundedTileOverlay : MKTileOverlay
42
+ @property(nonatomic, assign) CLLocationCoordinate2D southwest;
43
+ @property(nonatomic, assign) CLLocationCoordinate2D northeast;
44
+ @end
45
+
46
+ @implementation BoundedTileOverlay
47
+
48
+ static double tileToLat(NSInteger y, NSInteger z) {
49
+ double n = M_PI - 2.0 * M_PI * y / pow(2.0, z);
50
+ return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
51
+ }
52
+
53
+ static double tileToLng(NSInteger x, NSInteger z) {
54
+ return x / pow(2.0, z) * 360.0 - 180.0;
55
+ }
56
+
57
+ - (void)loadTileAtPath:(MKTileOverlayPath)path
58
+ result:(void (^)(NSData *_Nullable, NSError *_Nullable))result {
59
+ double tileSW_lat = tileToLat(path.y + 1, path.z);
60
+ double tileNE_lat = tileToLat(path.y, path.z);
61
+ double tileSW_lng = tileToLng(path.x, path.z);
62
+ double tileNE_lng = tileToLng(path.x + 1, path.z);
63
+
64
+ if (tileNE_lat < self.southwest.latitude ||
65
+ tileSW_lat > self.northeast.latitude ||
66
+ tileNE_lng < self.southwest.longitude ||
67
+ tileSW_lng > self.northeast.longitude) {
68
+ result(nil, nil);
69
+ return;
70
+ }
71
+
72
+ [super loadTileAtPath:path result:result];
73
+ }
74
+
75
+ @end
76
+
77
+ @interface GroundImageOverlayRenderer : MKOverlayRenderer
78
+ @property(nonatomic, strong) UIImage *image;
79
+ @property(nonatomic, assign) CGFloat overlayOpacity;
80
+ @end
81
+
82
+ @implementation GroundImageOverlayRenderer
83
+
84
+ - (void)drawMapRect:(MKMapRect)mapRect
85
+ zoomScale:(MKZoomScale)zoomScale
86
+ inContext:(CGContextRef)context {
87
+ MKMapRect overlayRect = self.overlay.boundingMapRect;
88
+ CGRect drawRect = [self rectForMapRect:overlayRect];
89
+
90
+ CGContextSaveGState(context);
91
+ CGContextSetAlpha(context, self.overlayOpacity);
92
+
93
+ // Flip the context for UIImage drawing
94
+ CGContextTranslateCTM(context, drawRect.origin.x,
95
+ drawRect.origin.y + drawRect.size.height);
96
+ CGContextScaleCTM(context, 1.0, -1.0);
97
+
98
+ CGRect imageRect =
99
+ CGRectMake(0, 0, drawRect.size.width, drawRect.size.height);
100
+ CGContextDrawImage(context, imageRect, self.image.CGImage);
101
+
102
+ CGContextRestoreGState(context);
103
+ }
104
+
105
+ @end
106
+
22
107
  @implementation LuggAppleMapViewContent
23
108
  @end
24
109
 
25
110
  @interface AppleMapProvider () <
26
111
  LuggMarkerViewDelegate, LuggCalloutViewDelegate, LuggPolylineViewDelegate,
27
- LuggPolygonViewDelegate, UIGestureRecognizerDelegate>
112
+ LuggPolygonViewDelegate, LuggCircleViewDelegate,
113
+ LuggGroundOverlayViewDelegate, LuggTileOverlayViewDelegate,
114
+ UIGestureRecognizerDelegate>
28
115
  @end
29
116
 
30
117
  @implementation AppleMapProvider {
@@ -36,16 +123,25 @@
36
123
  double _maxZoom;
37
124
  NSMapTable<id<MKOverlay>, LuggPolylineView *> *_overlayToPolylineMap;
38
125
  NSMapTable<id<MKOverlay>, LuggPolygonView *> *_overlayToPolygonMap;
126
+ NSMapTable<id<MKOverlay>, LuggCircleView *> *_overlayToCircleMap;
127
+ NSMapTable<id<MKOverlay>, LuggGroundOverlayView *>
128
+ *_overlayToGroundOverlayMap;
129
+ NSMapTable<id<MKOverlay>, LuggTileOverlayView *> *_overlayToTileOverlayMap;
39
130
  UITapGestureRecognizer *_tapGesture;
40
131
  UILongPressGestureRecognizer *_longPressGesture;
41
132
  LuggMarkerView *_activeNonBubbledMarker;
42
133
  BOOL _isReselectingAnnotation;
134
+ BOOL _isProgrammaticSelect;
43
135
  // Edge insets animation
44
136
  CADisplayLink *_edgeInsetsDisplayLink;
45
137
  UIEdgeInsets _edgeInsetsFrom;
46
138
  UIEdgeInsets _edgeInsetsTo;
139
+ UIEdgeInsets _edgeInsetsCurrent;
47
140
  CFTimeInterval _edgeInsetsAnimationStart;
48
141
  CFTimeInterval _edgeInsetsAnimationDuration;
142
+ BOOL _poiEnabled;
143
+ LuggMapViewPoiFilterMode _poiFilterMode;
144
+ NSArray<NSString *> *_poiFilterCategories;
49
145
  }
50
146
 
51
147
  @synthesize delegate = _delegate;
@@ -54,6 +150,12 @@
54
150
  if (self = [super init]) {
55
151
  _overlayToPolylineMap = [NSMapTable strongToWeakObjectsMapTable];
56
152
  _overlayToPolygonMap = [NSMapTable strongToWeakObjectsMapTable];
153
+ _overlayToCircleMap = [NSMapTable strongToWeakObjectsMapTable];
154
+ _overlayToGroundOverlayMap = [NSMapTable strongToWeakObjectsMapTable];
155
+ _overlayToTileOverlayMap = [NSMapTable strongToWeakObjectsMapTable];
156
+ _poiEnabled = YES;
157
+ _poiFilterMode = LuggMapViewPoiFilterMode::Including;
158
+ _poiFilterCategories = @[];
57
159
  }
58
160
  return self;
59
161
  }
@@ -147,15 +249,142 @@
147
249
  _mapView.showsUserLocation = enabled;
148
250
  }
149
251
 
150
- - (void)setTheme:(NSInteger)theme {
252
+ static MKPointOfInterestCategory poiCategoryFromString(NSString *string) {
253
+ static NSDictionary<NSString *, MKPointOfInterestCategory> *map;
254
+ static dispatch_once_t onceToken;
255
+ dispatch_once(&onceToken, ^{
256
+ map = @{
257
+ @"airport" : MKPointOfInterestCategoryAirport,
258
+ @"amusement-park" : MKPointOfInterestCategoryAmusementPark,
259
+ @"aquarium" : MKPointOfInterestCategoryAquarium,
260
+ @"atm" : MKPointOfInterestCategoryATM,
261
+ @"bakery" : MKPointOfInterestCategoryBakery,
262
+ @"bank" : MKPointOfInterestCategoryBank,
263
+ @"beach" : MKPointOfInterestCategoryBeach,
264
+ @"brewery" : MKPointOfInterestCategoryBrewery,
265
+ @"cafe" : MKPointOfInterestCategoryCafe,
266
+ @"campground" : MKPointOfInterestCategoryCampground,
267
+ @"car-rental" : MKPointOfInterestCategoryCarRental,
268
+ @"ev-charger" : MKPointOfInterestCategoryEVCharger,
269
+ @"fire-station" : MKPointOfInterestCategoryFireStation,
270
+ @"fitness-center" : MKPointOfInterestCategoryFitnessCenter,
271
+ @"food-market" : MKPointOfInterestCategoryFoodMarket,
272
+ @"gas-station" : MKPointOfInterestCategoryGasStation,
273
+ @"hospital" : MKPointOfInterestCategoryHospital,
274
+ @"hotel" : MKPointOfInterestCategoryHotel,
275
+ @"laundry" : MKPointOfInterestCategoryLaundry,
276
+ @"library" : MKPointOfInterestCategoryLibrary,
277
+ @"marina" : MKPointOfInterestCategoryMarina,
278
+ @"movie-theater" : MKPointOfInterestCategoryMovieTheater,
279
+ @"museum" : MKPointOfInterestCategoryMuseum,
280
+ @"national-park" : MKPointOfInterestCategoryNationalPark,
281
+ @"nightlife" : MKPointOfInterestCategoryNightlife,
282
+ @"park" : MKPointOfInterestCategoryPark,
283
+ @"parking" : MKPointOfInterestCategoryParking,
284
+ @"pharmacy" : MKPointOfInterestCategoryPharmacy,
285
+ @"police" : MKPointOfInterestCategoryPolice,
286
+ @"post-office" : MKPointOfInterestCategoryPostOffice,
287
+ @"public-transport" : MKPointOfInterestCategoryPublicTransport,
288
+ @"restaurant" : MKPointOfInterestCategoryRestaurant,
289
+ @"restroom" : MKPointOfInterestCategoryRestroom,
290
+ @"school" : MKPointOfInterestCategorySchool,
291
+ @"stadium" : MKPointOfInterestCategoryStadium,
292
+ @"store" : MKPointOfInterestCategoryStore,
293
+ @"theater" : MKPointOfInterestCategoryTheater,
294
+ @"university" : MKPointOfInterestCategoryUniversity,
295
+ @"winery" : MKPointOfInterestCategoryWinery,
296
+ @"zoo" : MKPointOfInterestCategoryZoo,
297
+ };
298
+ });
299
+ return map[string];
300
+ }
301
+
302
+ - (void)applyPoiFilter {
303
+ if (!_poiEnabled) {
304
+ _mapView.pointOfInterestFilter =
305
+ MKPointOfInterestFilter.filterExcludingAllCategories;
306
+ return;
307
+ }
308
+ if (_poiFilterCategories.count > 0) {
309
+ NSMutableArray<MKPointOfInterestCategory> *categories =
310
+ [NSMutableArray array];
311
+ for (NSString *name in _poiFilterCategories) {
312
+ MKPointOfInterestCategory category = poiCategoryFromString(name);
313
+ if (category) {
314
+ [categories addObject:category];
315
+ }
316
+ }
317
+ if (categories.count > 0) {
318
+ if (_poiFilterMode == LuggMapViewPoiFilterMode::Excluding) {
319
+ _mapView.pointOfInterestFilter = [[MKPointOfInterestFilter alloc]
320
+ initExcludingCategories:categories];
321
+ } else {
322
+ _mapView.pointOfInterestFilter = [[MKPointOfInterestFilter alloc]
323
+ initIncludingCategories:categories];
324
+ }
325
+ return;
326
+ }
327
+ }
328
+ _mapView.pointOfInterestFilter = nil;
329
+ }
330
+
331
+ - (void)setInsetAdjustment:(LuggMapViewInsetAdjustment)insetAdjustment {
332
+ BOOL automatic = (insetAdjustment == LuggMapViewInsetAdjustment::Automatic);
333
+ if (_mapView.insetsLayoutMarginsFromSafeArea == automatic)
334
+ return;
335
+
336
+ CLLocationCoordinate2D center = _mapView.centerCoordinate;
337
+ _mapView.insetsLayoutMarginsFromSafeArea = automatic;
338
+
339
+ dispatch_async(dispatch_get_main_queue(), ^{
340
+ [self->_mapView setCenterCoordinate:center animated:NO];
341
+ });
342
+ }
343
+
344
+ - (void)setPoiEnabled:(BOOL)enabled {
345
+ _poiEnabled = enabled;
346
+ [self applyPoiFilter];
347
+ }
348
+
349
+ - (void)setPoiFilterMode:(LuggMapViewPoiFilterMode)mode {
350
+ _poiFilterMode = mode;
351
+ [self applyPoiFilter];
352
+ }
353
+
354
+ - (void)setPoiFilterCategories:(NSArray<NSString *> *)categories {
355
+ _poiFilterCategories = categories;
356
+ [self applyPoiFilter];
357
+ }
358
+
359
+ - (void)setMapType:(LuggMapViewMapType)mapType {
360
+ switch (mapType) {
361
+ case LuggMapViewMapType::Satellite:
362
+ _mapView.mapType = MKMapTypeSatellite;
363
+ break;
364
+ case LuggMapViewMapType::Terrain:
365
+ _mapView.mapType = MKMapTypeStandard;
366
+ break;
367
+ case LuggMapViewMapType::Hybrid:
368
+ _mapView.mapType = MKMapTypeHybrid;
369
+ break;
370
+ case LuggMapViewMapType::MutedStandard:
371
+ _mapView.mapType = MKMapTypeMutedStandard;
372
+ break;
373
+ default:
374
+ _mapView.mapType = MKMapTypeStandard;
375
+ break;
376
+ }
377
+ }
378
+
379
+ - (void)setTheme:(LuggMapViewTheme)theme {
151
380
  switch (theme) {
152
- case 1: // Dark
381
+ case LuggMapViewTheme::Dark:
153
382
  _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
154
383
  break;
155
- case 0: // Light
384
+ case LuggMapViewTheme::Light:
156
385
  _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
157
386
  break;
158
- default: // System
387
+ default:
159
388
  _mapView.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
160
389
  break;
161
390
  }
@@ -182,6 +411,7 @@
182
411
  CGFloat deltaY = newOffsetY - oldOffsetY;
183
412
 
184
413
  _mapView.layoutMargins = edgeInsets;
414
+ _edgeInsetsCurrent = edgeInsets;
185
415
 
186
416
  if (deltaX != 0 || deltaY != 0) {
187
417
  CLLocationCoordinate2D currentCenter = _mapView.centerCoordinate;
@@ -232,7 +462,7 @@
232
462
  _edgeInsetsFrom.right +
233
463
  (_edgeInsetsTo.right - _edgeInsetsFrom.right) * t);
234
464
 
235
- [self setEdgeInsets:current oldEdgeInsets:_mapView.layoutMargins];
465
+ [self setEdgeInsets:current oldEdgeInsets:_edgeInsetsCurrent];
236
466
 
237
467
  if (progress >= 1.0) {
238
468
  [self stopEdgeInsetsAnimation];
@@ -315,6 +545,55 @@
315
545
  return nil;
316
546
  }
317
547
 
548
+ - (LuggCircleView *)hitTestCircleAtPoint:(CGPoint)point {
549
+ CLLocationCoordinate2D tapCoordinate = [_mapView convertPoint:point
550
+ toCoordinateFromView:_mapView];
551
+ CLLocation *tapLocation =
552
+ [[CLLocation alloc] initWithLatitude:tapCoordinate.latitude
553
+ longitude:tapCoordinate.longitude];
554
+
555
+ NSArray<id<MKOverlay>> *overlays = _mapView.overlays;
556
+ for (NSInteger i = overlays.count - 1; i >= 0; i--) {
557
+ id<MKOverlay> overlay = overlays[i];
558
+ if (![overlay isKindOfClass:[MKCircle class]])
559
+ continue;
560
+
561
+ LuggCircleView *circleView = [_overlayToCircleMap objectForKey:overlay];
562
+ if (!circleView || !circleView.tappable)
563
+ continue;
564
+
565
+ CLLocation *center =
566
+ [[CLLocation alloc] initWithLatitude:circleView.center.latitude
567
+ longitude:circleView.center.longitude];
568
+ CLLocationDistance distance = [tapLocation distanceFromLocation:center];
569
+ if (distance <= circleView.radius)
570
+ return circleView;
571
+ }
572
+ return nil;
573
+ }
574
+
575
+ - (LuggGroundOverlayView *)hitTestGroundOverlayAtPoint:(CGPoint)point {
576
+ CLLocationCoordinate2D tapCoordinate = [_mapView convertPoint:point
577
+ toCoordinateFromView:_mapView];
578
+
579
+ NSArray<id<MKOverlay>> *overlays = _mapView.overlays;
580
+ for (NSInteger i = overlays.count - 1; i >= 0; i--) {
581
+ id<MKOverlay> overlay = overlays[i];
582
+ if (![overlay isKindOfClass:[GroundImageOverlay class]])
583
+ continue;
584
+
585
+ LuggGroundOverlayView *view =
586
+ [_overlayToGroundOverlayMap objectForKey:overlay];
587
+ if (!view || !view.tappable)
588
+ continue;
589
+
590
+ MKMapPoint mapPoint = MKMapPointForCoordinate(tapCoordinate);
591
+ if (MKMapRectContainsPoint(overlay.boundingMapRect, mapPoint))
592
+ return view;
593
+ }
594
+ return nil;
595
+ }
596
+
318
597
  - (BOOL)hitTestAnnotationAtPoint:(CGPoint)point {
319
598
  for (id<MKAnnotation> annotation in _mapView.annotations) {
320
599
  MKAnnotationView *view = [_mapView viewForAnnotation:annotation];
@@ -349,6 +628,19 @@
349
628
  if ([self hitTestAnnotationAtPoint:point])
350
629
  return;
351
630
 
631
+ LuggGroundOverlayView *groundOverlayView =
632
+ [self hitTestGroundOverlayAtPoint:point];
633
+ if (groundOverlayView) {
634
+ [groundOverlayView emitPressEvent];
635
+ return;
636
+ }
637
+
638
+ LuggCircleView *circleView = [self hitTestCircleAtPoint:point];
639
+ if (circleView) {
640
+ [circleView emitPressEvent];
641
+ return;
642
+ }
643
+
352
644
  LuggPolygonView *polygonView = [self hitTestPolygonAtPoint:point];
353
645
  if (polygonView) {
354
646
  [polygonView emitPressEvent];
@@ -526,6 +818,37 @@
526
818
  return renderer;
527
819
  }
528
820
 
821
+ if ([overlay isKindOfClass:[MKCircle class]]) {
822
+ LuggCircleView *circleView = [_overlayToCircleMap objectForKey:overlay];
823
+ MKCircle *circle = (MKCircle *)overlay;
824
+
825
+ MKCircleRenderer *renderer =
826
+ [[MKCircleRenderer alloc] initWithCircle:circle];
827
+ if (circleView) {
828
+ renderer.fillColor = circleView.fillColor;
829
+ renderer.strokeColor = circleView.strokeColor;
830
+ renderer.lineWidth = circleView.strokeWidth;
831
+ circleView.renderer = renderer;
832
+ }
833
+ return renderer;
834
+ }
835
+
836
+ if ([overlay isKindOfClass:[GroundImageOverlay class]]) {
837
+ GroundImageOverlay *groundOverlay = (GroundImageOverlay *)overlay;
838
+ GroundImageOverlayRenderer *renderer =
839
+ [[GroundImageOverlayRenderer alloc] initWithOverlay:overlay];
840
+ renderer.image = groundOverlay.image;
841
+ renderer.overlayOpacity = groundOverlay.opacity;
842
+ return renderer;
843
+ }
844
+
845
+ if ([overlay isKindOfClass:[MKTileOverlay class]]) {
846
+ MKTileOverlay *tileOverlay = (MKTileOverlay *)overlay;
847
+ MKTileOverlayRenderer *renderer =
848
+ [[MKTileOverlayRenderer alloc] initWithTileOverlay:tileOverlay];
849
+ return renderer;
850
+ }
851
+
529
852
  return nil;
530
853
  }
531
854
 
@@ -538,9 +861,11 @@
538
861
  LuggMarkerView *markerView = annotation.markerView;
539
862
 
540
863
  if (markerView) {
541
- CGPoint point = [_mapView convertCoordinate:markerView.coordinate
542
- toPointToView:_mapView];
543
- [markerView emitPressEventWithPoint:point];
864
+ if (!_isProgrammaticSelect) {
865
+ CGPoint point = [_mapView convertCoordinate:markerView.coordinate
866
+ toPointToView:_mapView];
867
+ [markerView emitPressEventWithPoint:point];
868
+ }
544
869
 
545
870
  LuggCalloutView *calloutView = markerView.calloutView;
546
871
  if (calloutView && !calloutView.bubbled && calloutView.hasCustomContent) {
@@ -604,24 +929,23 @@
604
929
  if (contentSize.width <= 0 || contentSize.height <= 0)
605
930
  return;
606
931
 
607
- CGPoint anchor = calloutView.anchor;
932
+ CGPoint offset = calloutView.offset;
608
933
 
609
934
  AppleMarkerAnnotation *annotation =
610
935
  (AppleMarkerAnnotation *)_activeNonBubbledMarker.marker;
611
936
  MKAnnotationView *annotationView = annotation.annotationView;
612
937
 
613
938
  if (annotationView && contentView.superview == annotationView) {
614
- CGPoint center = CGPointMake(annotationView.bounds.size.width / 2.0 +
615
- contentSize.width * (0.5 - anchor.x),
616
- contentSize.height * (0.5 - anchor.y));
939
+ CGPoint center =
940
+ CGPointMake(annotationView.bounds.size.width / 2.0 + offset.x,
941
+ -contentSize.height / 2.0 + offset.y);
617
942
  contentView.center = center;
618
943
  } else {
619
944
  CGPoint point =
620
945
  [_mapView convertCoordinate:_activeNonBubbledMarker.coordinate
621
946
  toPointToView:_wrapperView];
622
- contentView.center =
623
- CGPointMake(point.x + contentSize.width * (0.5 - anchor.x),
624
- point.y + contentSize.height * (0.5 - anchor.y));
947
+ contentView.center = CGPointMake(
948
+ point.x + offset.x, point.y - contentSize.height / 2.0 + offset.y);
625
949
  }
626
950
 
627
951
  contentView.hidden = NO;
@@ -695,7 +1019,9 @@
695
1019
  if ([view.annotation isKindOfClass:[AppleMarkerAnnotation class]]) {
696
1020
  AppleMarkerAnnotation *annotation =
697
1021
  (AppleMarkerAnnotation *)view.annotation;
698
- [_mapView setCenterCoordinate:annotation.coordinate animated:YES];
1022
+ if (annotation.markerView.centerOnPress) {
1023
+ [_mapView setCenterCoordinate:annotation.coordinate animated:YES];
1024
+ }
699
1025
  }
700
1026
  }
701
1027
 
@@ -720,6 +1046,42 @@
720
1046
  calloutView.hasCustomContent ? calloutView.contentView : nil;
721
1047
  }
722
1048
 
1049
+ - (void)showCalloutForMarkerView:(LuggMarkerView *)markerView {
1050
+ LuggCalloutView *calloutView = markerView.calloutView;
1051
+ _isProgrammaticSelect = YES;
1052
+
1053
+ if (calloutView && calloutView.hasCustomContent) {
1054
+ [self dismissNonBubbledCallout];
1055
+ AppleMarkerAnnotation *annotation =
1056
+ (AppleMarkerAnnotation *)markerView.marker;
1057
+ if (!calloutView.bubbled) {
1058
+ [self showNonBubbledCallout:markerView];
1059
+ } else if (annotation) {
1060
+ [_mapView selectAnnotation:annotation animated:YES];
1061
+ }
1062
+ _isProgrammaticSelect = NO;
1063
+ return;
1064
+ }
1065
+
1066
+ if (markerView.title.length > 0) {
1067
+ AppleMarkerAnnotation *annotation =
1068
+ (AppleMarkerAnnotation *)markerView.marker;
1069
+ if (annotation) {
1070
+ [_mapView selectAnnotation:annotation animated:YES];
1071
+ }
1072
+ }
1073
+ _isProgrammaticSelect = NO;
1074
+ }
1075
+
1076
+ - (void)hideCalloutForMarkerView:(LuggMarkerView *)markerView {
1077
+ [self dismissNonBubbledCallout];
1078
+ AppleMarkerAnnotation *annotation =
1079
+ (AppleMarkerAnnotation *)markerView.marker;
1080
+ if (annotation) {
1081
+ [_mapView deselectAnnotation:annotation animated:YES];
1082
+ }
1083
+ }
1084
+
723
1085
  #pragma mark - MarkerViewDelegate
724
1086
 
725
1087
  - (void)markerViewDidLayout:(LuggMarkerView *)markerView {
@@ -764,6 +1126,24 @@
764
1126
  [self syncPolygonView:polygonView];
765
1127
  }
766
1128
 
1129
+ #pragma mark - CircleViewDelegate
1130
+
1131
+ - (void)circleViewDidUpdate:(LuggCircleView *)circleView {
1132
+ [self syncCircleView:circleView];
1133
+ }
1134
+
1135
+ #pragma mark - GroundOverlayViewDelegate
1136
+
1137
+ - (void)groundOverlayViewDidUpdate:(LuggGroundOverlayView *)groundOverlayView {
1138
+ [self syncGroundOverlayView:groundOverlayView];
1139
+ }
1140
+
1141
+ #pragma mark - TileOverlayViewDelegate
1142
+
1143
+ - (void)tileOverlayViewDidUpdate:(LuggTileOverlayView *)tileOverlayView {
1144
+ [self syncTileOverlayView:tileOverlayView];
1145
+ }
1146
+
767
1147
  #pragma mark - Marker Management
768
1148
 
769
1149
  - (void)addMarkerView:(LuggMarkerView *)markerView {
@@ -1087,6 +1467,196 @@
1087
1467
  return [interiorPolygons copy];
1088
1468
  }
1089
1469
 
1470
+ #pragma mark - Circle Management
1471
+
1472
+ - (void)addCircleView:(LuggCircleView *)circleView {
1473
+ circleView.delegate = self;
1474
+ [self addCircleOverlayToMap:circleView];
1475
+ }
1476
+
1477
+ - (void)removeCircleView:(LuggCircleView *)circleView {
1478
+ circleView.delegate = nil;
1479
+ MKCircle *circle = (MKCircle *)circleView.circle;
1480
+ if (circle) {
1481
+ [_overlayToCircleMap removeObjectForKey:circle];
1482
+ [_mapView removeOverlay:circle];
1483
+ circleView.circle = nil;
1484
+ }
1485
+ }
1486
+
1487
+ - (void)syncCircleView:(LuggCircleView *)circleView {
1488
+ if (!_mapView)
1489
+ return;
1490
+
1491
+ MKCircle *oldCircle = (MKCircle *)circleView.circle;
1492
+
1493
+ MKCircle *newCircle = [MKCircle circleWithCenterCoordinate:circleView.center
1494
+ radius:circleView.radius];
1495
+
1496
+ circleView.circle = newCircle;
1497
+ [_overlayToCircleMap setObject:circleView forKey:newCircle];
1498
+
1499
+ MKCircleRenderer *renderer = (MKCircleRenderer *)circleView.renderer;
1500
+ if (renderer && oldCircle) {
1501
+ [_overlayToCircleMap removeObjectForKey:oldCircle];
1502
+ [_mapView removeOverlay:oldCircle];
1503
+ [self insertOverlay:newCircle withZIndex:circleView.zIndex];
1504
+ circleView.renderer = nil;
1505
+ return;
1506
+ }
1507
+
1508
+ if (oldCircle) {
1509
+ [_overlayToCircleMap removeObjectForKey:oldCircle];
1510
+ [_mapView removeOverlay:oldCircle];
1511
+ }
1512
+ [self insertOverlay:newCircle withZIndex:circleView.zIndex];
1513
+ }
1514
+
1515
+ - (void)addCircleOverlayToMap:(LuggCircleView *)circleView {
1516
+ if (!_mapView)
1517
+ return;
1518
+
1519
+ MKCircle *circle = [MKCircle circleWithCenterCoordinate:circleView.center
1520
+ radius:circleView.radius];
1521
+
1522
+ circleView.circle = circle;
1523
+ [_overlayToCircleMap setObject:circleView forKey:circle];
1524
+ [self insertOverlay:circle withZIndex:circleView.zIndex];
1525
+ }
1526
+
1527
+ #pragma mark - Ground Overlay Management
1528
+
1529
+ - (void)addGroundOverlayView:(LuggGroundOverlayView *)groundOverlayView {
1530
+ groundOverlayView.delegate = self;
1531
+ [self syncGroundOverlayView:groundOverlayView];
1532
+ }
1533
+
1534
+ - (void)removeGroundOverlayView:(LuggGroundOverlayView *)groundOverlayView {
1535
+ groundOverlayView.delegate = nil;
1536
+ GroundImageOverlay *overlay = (GroundImageOverlay *)groundOverlayView.overlay;
1537
+ if (overlay) {
1538
+ [_overlayToGroundOverlayMap removeObjectForKey:overlay];
1539
+ [_mapView removeOverlay:overlay];
1540
+ groundOverlayView.overlay = nil;
1541
+ }
1542
+ }
1543
+
1544
+ - (void)syncGroundOverlayView:(LuggGroundOverlayView *)groundOverlayView {
1545
+ if (!_mapView)
1546
+ return;
1547
+
1548
+ NSString *imageUri = groundOverlayView.imageUri;
1549
+ if (imageUri.length == 0)
1550
+ return;
1551
+
1552
+ // Remove old overlay
1553
+ GroundImageOverlay *oldOverlay =
1554
+ (GroundImageOverlay *)groundOverlayView.overlay;
1555
+ if (oldOverlay) {
1556
+ [_overlayToGroundOverlayMap removeObjectForKey:oldOverlay];
1557
+ [_mapView removeOverlay:oldOverlay];
1558
+ groundOverlayView.overlay = nil;
1559
+ }
1560
+
1561
+ NSURL *url = [NSURL URLWithString:imageUri];
1562
+ if (!url)
1563
+ return;
1564
+
1565
+ __weak __typeof(self) weakSelf = self;
1566
+ __weak LuggGroundOverlayView *weakOverlayView = groundOverlayView;
1567
+ dispatch_async(
1568
+ dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
1569
+ NSData *data = [NSData dataWithContentsOfURL:url];
1570
+ UIImage *image = data ? [UIImage imageWithData:data] : nil;
1571
+ dispatch_async(dispatch_get_main_queue(), ^{
1572
+ [weakSelf addGroundOverlayToMap:weakOverlayView image:image];
1573
+ });
1574
+ });
1575
+ }
1576
+
1577
+ - (void)addGroundOverlayToMap:(LuggGroundOverlayView *)groundOverlayView
1578
+ image:(UIImage *)image {
1579
+ if (!_mapView || !groundOverlayView || !image)
1580
+ return;
1581
+
1582
+ MKMapPoint sw = MKMapPointForCoordinate(groundOverlayView.southwest);
1583
+ MKMapPoint ne = MKMapPointForCoordinate(groundOverlayView.northeast);
1584
+
1585
+ MKMapRect mapRect = MKMapRectMake(MIN(sw.x, ne.x), MIN(sw.y, ne.y),
1586
+ fabs(ne.x - sw.x), fabs(ne.y - sw.y));
1587
+
1588
+ CLLocationCoordinate2D center =
1589
+ CLLocationCoordinate2DMake((groundOverlayView.northeast.latitude +
1590
+ groundOverlayView.southwest.latitude) /
1591
+ 2.0,
1592
+ (groundOverlayView.northeast.longitude +
1593
+ groundOverlayView.southwest.longitude) /
1594
+ 2.0);
1595
+
1596
+ GroundImageOverlay *overlay = [[GroundImageOverlay alloc] init];
1597
+ overlay.coordinate = center;
1598
+ overlay.boundingMapRect = mapRect;
1599
+ overlay.image = image;
1600
+ overlay.opacity = groundOverlayView.opacity;
1601
+
1602
+ groundOverlayView.overlay = overlay;
1603
+ [_overlayToGroundOverlayMap setObject:groundOverlayView forKey:overlay];
1604
+ [self insertOverlay:overlay withZIndex:groundOverlayView.zIndex];
1605
+ }
1606
+
1607
+ #pragma mark - Tile Overlay Management
1608
+
1609
+ - (void)addTileOverlayView:(LuggTileOverlayView *)tileOverlayView {
1610
+ tileOverlayView.delegate = self;
1611
+ [self syncTileOverlayView:tileOverlayView];
1612
+ }
1613
+
1614
+ - (void)removeTileOverlayView:(LuggTileOverlayView *)tileOverlayView {
1615
+ tileOverlayView.delegate = nil;
1616
+ MKTileOverlay *overlay = (MKTileOverlay *)tileOverlayView.overlay;
1617
+ if (overlay) {
1618
+ [_overlayToTileOverlayMap removeObjectForKey:overlay];
1619
+ [_mapView removeOverlay:overlay];
1620
+ tileOverlayView.overlay = nil;
1621
+ }
1622
+ }
1623
+
1624
+ - (void)syncTileOverlayView:(LuggTileOverlayView *)tileOverlayView {
1625
+ if (!_mapView)
1626
+ return;
1627
+
1628
+ NSString *urlTemplate = tileOverlayView.urlTemplate;
1629
+ if (urlTemplate.length == 0)
1630
+ return;
1631
+
1632
+ // Remove old overlay
1633
+ MKTileOverlay *oldOverlay = (MKTileOverlay *)tileOverlayView.overlay;
1634
+ if (oldOverlay) {
1635
+ [_overlayToTileOverlayMap removeObjectForKey:oldOverlay];
1636
+ [_mapView removeOverlay:oldOverlay];
1637
+ tileOverlayView.overlay = nil;
1638
+ }
1639
+
1640
+ MKTileOverlay *tileOverlay;
1641
+ if (tileOverlayView.hasBounds) {
1642
+ BoundedTileOverlay *bounded =
1643
+ [[BoundedTileOverlay alloc] initWithURLTemplate:urlTemplate];
1644
+ bounded.southwest = tileOverlayView.southwest;
1645
+ bounded.northeast = tileOverlayView.northeast;
1646
+ tileOverlay = bounded;
1647
+ } else {
1648
+ tileOverlay = [[MKTileOverlay alloc] initWithURLTemplate:urlTemplate];
1649
+ }
1650
+
1651
+ tileOverlay.tileSize =
1652
+ CGSizeMake(tileOverlayView.tileSize, tileOverlayView.tileSize);
1653
+ tileOverlay.canReplaceMapContent = NO;
1654
+
1655
+ tileOverlayView.overlay = tileOverlay;
1656
+ [_overlayToTileOverlayMap setObject:tileOverlayView forKey:tileOverlay];
1657
+ [_mapView addOverlay:tileOverlay level:MKOverlayLevelAboveRoads];
1658
+ }
1659
+
1090
1660
  - (void)insertOverlay:(id<MKOverlay>)overlay withZIndex:(NSInteger)zIndex {
1091
1661
  if (zIndex == 0) {
1092
1662
  [_mapView addOverlay:overlay];
@@ -1102,10 +1672,18 @@
1102
1672
  [_overlayToPolylineMap objectForKey:overlays[i]];
1103
1673
  LuggPolygonView *existingPolygonView =
1104
1674
  [_overlayToPolygonMap objectForKey:overlays[i]];
1675
+ LuggCircleView *existingCircleView =
1676
+ [_overlayToCircleMap objectForKey:overlays[i]];
1677
+ LuggGroundOverlayView *existingGroundOverlayView =
1678
+ [_overlayToGroundOverlayMap objectForKey:overlays[i]];
1105
1679
  if (existingPolylineView) {
1106
1680
  existingZIndex = existingPolylineView.zIndex;
1107
1681
  } else if (existingPolygonView) {
1108
1682
  existingZIndex = existingPolygonView.zIndex;
1683
+ } else if (existingCircleView) {
1684
+ existingZIndex = existingCircleView.zIndex;
1685
+ } else if (existingGroundOverlayView) {
1686
+ existingZIndex = existingGroundOverlayView.zIndex;
1109
1687
  } else {
1110
1688
  continue;
1111
1689
  }