From 99582b773ebe1b0e39240fc608135a1742b4fa73 Mon Sep 17 00:00:00 2001 From: Julian Rex Date: Mon, 12 Feb 2018 11:36:03 -0500 Subject: [ios] Made reason bitmask private, created public enum, and provided a mapping from the bitmask to enum --- platform/ios/CHANGELOG.md | 2 +- platform/ios/ios.xcodeproj/project.pbxproj | 18 +++-- platform/ios/src/MGLCameraChange.h | 35 --------- platform/ios/src/MGLCameraChangeReason.h | 54 +++++++++++++ platform/ios/src/MGLCameraChangeReason_Private.h | 42 ++++++++++ platform/ios/src/MGLMapView.mm | 99 +++++++++++++++++++----- platform/ios/src/MGLMapViewDelegate.h | 2 +- 7 files changed, 190 insertions(+), 62 deletions(-) delete mode 100644 platform/ios/src/MGLCameraChange.h create mode 100644 platform/ios/src/MGLCameraChangeReason.h create mode 100644 platform/ios/src/MGLCameraChangeReason_Private.h diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 49476f5917..3aa9ea1b85 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -5,7 +5,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT ## 3.7.4 * Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141)) -* Provide optional delegate methods that provide a reason for a camera change. These are called in preference over the existing methods that do not have the parameter. ([#11151](https://github.com/mapbox/mapbox-gl-native/pull/11151)) +* Added optional delegate methods that provide a reason for a camera change. These are called in preference over the existing methods that do not have the parameter. ([#11151](https://github.com/mapbox/mapbox-gl-native/pull/11151)) ## 3.7.3 - January 10, 2018 diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 202872d01a..fe3eb8a4a7 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -251,8 +251,10 @@ AC518E00201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */; }; AC518E03201BB56000EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; }; AC518E04201BB56100EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; }; - CA55CD41202C16AA00CE7095 /* MGLCameraChange.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChange.h */; settings = {ATTRIBUTES = (Public, ); }; }; - CA55CD42202C16AA00CE7095 /* MGLCameraChange.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChange.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; }; + CAA106B92030C17300D80CD6 /* MGLCameraChangeReason_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CAA106B82030C17300D80CD6 /* MGLCameraChangeReason_Private.h */; }; + CAA106BA2030C17300D80CD6 /* MGLCameraChangeReason_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = CAA106B82030C17300D80CD6 /* MGLCameraChangeReason_Private.h */; }; DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */; }; @@ -758,7 +760,8 @@ 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = ""; }; AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = ""; }; AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = ""; }; - CA55CD3E202C16AA00CE7095 /* MGLCameraChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChange.h; sourceTree = ""; }; + CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChangeReason.h; sourceTree = ""; }; + CAA106B82030C17300D80CD6 /* MGLCameraChangeReason_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChangeReason_Private.h; sourceTree = ""; }; DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = ""; }; DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = ""; }; DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = ""; }; @@ -1458,7 +1461,8 @@ DA8848881CBB036000AB86E3 /* SMCalloutView */, DAD165851CF4D08B001FF4B9 /* Telemetry */, 355ADFF91E9281C300F3939D /* Views */, - CA55CD3E202C16AA00CE7095 /* MGLCameraChange.h */, + CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */, + CAA106B82030C17300D80CD6 /* MGLCameraChangeReason_Private.h */, DA704CC01F65A475004B3F28 /* MGLMapAccessibilityElement.h */, DA704CC11F65A475004B3F28 /* MGLMapAccessibilityElement.mm */, DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */, @@ -1768,7 +1772,7 @@ 350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */, DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */, 404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */, - CA55CD41202C16AA00CE7095 /* MGLCameraChange.h in Headers */, + CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */, 1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */, DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */, 35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */, @@ -1833,6 +1837,7 @@ DA88488B1CBB037E00AB86E3 /* SMCalloutView.h in Headers */, DA8847FE1CBAFA5100AB86E3 /* MGLTypes.h in Headers */, DA8847F11CBAFA5100AB86E3 /* MGLGeometry.h in Headers */, + CAA106B92030C17300D80CD6 /* MGLCameraChangeReason_Private.h in Headers */, DA8848221CBAFA6200AB86E3 /* MGLOfflineRegion_Private.h in Headers */, 35136D4C1D4277FC00C20EFD /* MGLSource.h in Headers */, 3566C76C1D4A8DFA008152BC /* MGLRasterSource.h in Headers */, @@ -1889,6 +1894,7 @@ 353933FC1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */, 3566C76D1D4A8DFA008152BC /* MGLRasterSource.h in Headers */, DAED38641D62D0FC00D7640F /* NSURL+MGLAdditions.h in Headers */, + CAA106BA2030C17300D80CD6 /* MGLCameraChangeReason_Private.h in Headers */, DABFB85E1CBE99E500D62B32 /* MGLAnnotation.h in Headers */, DABFB8641CBE99E500D62B32 /* MGLOfflineStorage.h in Headers */, DAD165791CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */, @@ -1901,7 +1907,7 @@ 3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */, 35D3A1E71E9BE7EC002B38EE /* MGLScaleBar.h in Headers */, 35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */, - CA55CD42202C16AA00CE7095 /* MGLCameraChange.h in Headers */, + CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */, DABFB86D1CBE9A0F00D62B32 /* MGLAnnotationImage.h in Headers */, DABFB8721CBE9A0F00D62B32 /* MGLUserLocation.h in Headers */, 927FBD001F4DB05500F8BF1F /* MGLMapSnapshotter.h in Headers */, diff --git a/platform/ios/src/MGLCameraChange.h b/platform/ios/src/MGLCameraChange.h deleted file mode 100644 index c2f7728f2c..0000000000 --- a/platform/ios/src/MGLCameraChange.h +++ /dev/null @@ -1,35 +0,0 @@ -#import "MGLFoundation.h" - -typedef NS_OPTIONS(NSUInteger, MGLCameraChangeReason) -{ - /// No reason for the camera move is specified. - MGLCameraChangeReasonNone = 0, - - /// Set when a public API that moves the camera is called. This may be set for some gestures - MGLCameraChangeReasonProgrammatic = 1 << 0, - - /// User tapped the compass to reset to North - MGLCameraChangeReasonResetNorth = 1 << 1,// Tap on compass - - /// User panned the map. - MGLCameraChangeReasonGesturePan = 1 << 2, - - /// User pinched to zoom in/out - MGLCameraChangeReasonGesturePinch = 1 << 3, - - // User rotated the map - MGLCameraChangeReasonGestureRotate = 1 << 4, - - /// User zoomed the map in - MGLCameraChangeReasonGestureZoomIn = 1 << 5,// One finger double tap - - /// User zoomed the map out - MGLCameraChangeReasonGestureZoomOut = 1 << 6,// Two finger single tap - - /// User long pressed on the map for a quick zoom - MGLCameraChangeReasonGestureQuickZoom = 1 << 7,// Long press - - // User panned with two fingers to tilt the map - MGLCameraChangeReasonGesturePitch = 1 << 8// Two finger drag -}; - diff --git a/platform/ios/src/MGLCameraChangeReason.h b/platform/ios/src/MGLCameraChangeReason.h new file mode 100644 index 0000000000..5fb990afdd --- /dev/null +++ b/platform/ios/src/MGLCameraChangeReason.h @@ -0,0 +1,54 @@ +#import "MGLFoundation.h" + +/** + Reasons describing why a camera move occurred. + + Values of this type are passed to the `MGLMapView`'s delegate in the following methods: + + - `-mapView:shouldChangeFromCamera:toCamera:reason:` + - `-mapView:regionWillChangeWithReason:animated:` + - `-mapView:regionIsChangingWithReason:` + - `-mapView:regionDidChangeWithReason:animated:` + + It's important to note that it's almost impossible to perform a rotate without zooming (in or out), + so when you want to check for a pan vs a rotation, it's important to ensure you check + MGLCameraChangeReasonGesturePan against MGLCameraChangeReasonGestureRotateAndZoom. +*/ +typedef NS_ENUM(NSUInteger, MGLCameraChangeReason) +{ + /// The reason for the camera change is invalid. This is considered an error. + MGLCameraChangeReasonInvalid, + + /// Set when a public API that moves the camera is called. + MGLCameraChangeReasonProgrammatic, + + /// The user panned the map. + MGLCameraChangeReasonGesturePan, + + /// The user rotated the map. This is also used when the user resets the map orientation by tapping + /// on the compass. Note that since it's almost impossible to rotate without zooming, you should + /// also check against MGLCameraChangeReasonGestureRotateAndZoom + MGLCameraChangeReasonGestureRotate, + + /// The user zoomed the map. This is used when pinching the map, double tapping and for the one + /// finger drag zoom gesture. + MGLCameraChangeReasonGestureZoom, + + /// The user panned and rotated the map, without lifting their fingers. + MGLCameraChangeReasonGesturePanAndRotate, + + /// The user rotated and zoomed the map. You will see this value when rotating the map without a + /// deliberate zoom. See also MGLCameraChangeReasonGestureRotate. + MGLCameraChangeReasonGestureRotateAndZoom, + + /// The user panned and zoomed the map, without lifting their fingers. + MGLCameraChangeReasonGesturePanAndZoom, + + /// The user panned, rotated and zoomed the map, without lifting their fingers. + MGLCameraChangeReasonGesturePanRotateAndZoom, + + /// The user dragged the map with two fingers to tilt the map. + MGLCameraChangeReasonGestureTilt +}; + + diff --git a/platform/ios/src/MGLCameraChangeReason_Private.h b/platform/ios/src/MGLCameraChangeReason_Private.h new file mode 100644 index 0000000000..4c058b1d61 --- /dev/null +++ b/platform/ios/src/MGLCameraChangeReason_Private.h @@ -0,0 +1,42 @@ +#import "MGLFoundation.h" + +/** + Internal bitmask values used to represent ongoing gestures and API calls that triggers a camera + change. + + At the end of a camera movement, the resulting bitmask is mapped to one of the public + MGLCameraChangeReason enum values and passed to the delegate camera change methods. + */ +typedef NS_OPTIONS(NSUInteger, MGLCameraChangeReasonBitmask) +{ + /// The default value. Set at the start, and reset when a camera move has completed. + MGLCameraChangeReasonBitmaskNone = 0, + + /// Set when a public API that moves the camera is called. This may be set for some gestures, + /// for example, when the user taps the compass to reset north. + MGLCameraChangeReasonBitmaskProgrammatic = 1 << 0, + + /// The user tapped the compass to reset the map orientation so North is up. + MGLCameraChangeReasonBitmaskResetNorth = 1 << 1, + + /// The user panned the map. + MGLCameraChangeReasonBitmaskGesturePan = 1 << 2, + + /// The user pinched to zoom in/out. + MGLCameraChangeReasonBitmaskGesturePinch = 1 << 3, + + /// The user rotated the map. + MGLCameraChangeReasonBitmaskGestureRotate = 1 << 4, + + /// The user zoomed the map in. (One finger double tap.) + MGLCameraChangeReasonBitmaskGestureZoomIn = 1 << 5, + + /// The user zoomed the map out. (Two finger single tap.) + MGLCameraChangeReasonBitmaskGestureZoomOut = 1 << 6, + + /// The user long pressed on the map for a quick zoom. (Single tap, then long press and drag up/down.) + MGLCameraChangeReasonBitmaskGestureOneFingerZoom = 1 << 7, + + // The user panned with two fingers to tilt the map. (Two finger drag.) + MGLCameraChangeReasonBitmaskGestureTwoFingerDrag = 1 << 8 +}; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index d2496d8627..90a67840fe 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -41,6 +41,8 @@ #import "MGLMultiPoint_Private.h" #import "MGLOfflineStorage_Private.h" #import "MGLFoundation_Private.h" +#import "MGLCameraChangeReason_Private.h" + #import "MGLRendererFrontend.h" #import "MGLRendererConfiguration.h" @@ -209,7 +211,9 @@ public: @property (nonatomic) UILongPressGestureRecognizer *quickZoom; @property (nonatomic) UIPanGestureRecognizer *twoFingerDrag; -@property (nonatomic) MGLCameraChangeReason cameraChangeReason; +/// Camera change reason handling. +@property (nonatomic) MGLCameraChangeReasonBitmask cameraChangeReasonBitmask; +@property (nonatomic, readonly) MGLCameraChangeReason cameraChangeReason; /// Mapping from reusable identifiers to annotation images. @property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImagesByIdentifier; @@ -555,7 +559,7 @@ public: options.padding = padding; options.zoom = 0; - _cameraChangeReason = MGLCameraChangeReasonNone; + _cameraChangeReasonBitmask = MGLCameraChangeReasonBitmaskNone; _mbglMap->jumpTo(options); _pendingLatitude = NAN; @@ -1243,7 +1247,7 @@ public: - (void)handleCompassTapGesture:(__unused id)sender { - self.cameraChangeReason |= MGLCameraChangeReasonResetNorth; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskResetNorth; [self resetNorthAnimated:YES]; @@ -1296,6 +1300,8 @@ public: // Check delegates first if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:reason:)]) { + + return [self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:newCamera reason:self.cameraChangeReason]; } else if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]) @@ -1316,7 +1322,7 @@ public: MGLMapCamera *oldCamera = self.camera; - self.cameraChangeReason |= MGLCameraChangeReasonGesturePan; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGesturePan; if (pan.state == UIGestureRecognizerStateBegan) { @@ -1386,7 +1392,7 @@ public: CGPoint centerPoint = [self anchorPointForGesture:pinch]; MGLMapCamera *oldCamera = self.camera; - self.cameraChangeReason |= MGLCameraChangeReasonGesturePinch; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskGesturePinch; if (pinch.state == UIGestureRecognizerStateBegan) { @@ -1485,7 +1491,7 @@ public: CGPoint centerPoint = [self anchorPointForGesture:rotate]; MGLMapCamera *oldCamera = self.camera; - self.cameraChangeReason |= MGLCameraChangeReasonGestureRotate; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonGestureRotate; if (rotate.state == UIGestureRecognizerStateBegan) { @@ -1671,7 +1677,7 @@ public: if (doubleTap.state == UIGestureRecognizerStateEnded) { - self.cameraChangeReason |= MGLCameraChangeReasonGestureZoomIn; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskGestureZoomIn; MGLMapCamera *oldCamera = self.camera; @@ -1708,7 +1714,7 @@ public: _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonGestureZoomOut; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskGestureZoomOut; if (twoFingerTap.state == UIGestureRecognizerStateBegan) { @@ -1747,7 +1753,7 @@ public: _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonGestureQuickZoom; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskGestureOneFingerZoom; if (quickZoom.state == UIGestureRecognizerStateBegan) { @@ -1792,7 +1798,7 @@ public: _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonGesturePitch; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskGestureTwoFingerDrag; if (twoFingerDrag.state == UIGestureRecognizerStateBegan) { @@ -1980,6 +1986,7 @@ public: - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { + // If you update these, please check to see if `-cameraChangeReason` needs updating. NSArray *validSimultaneousGestures = @[ self.pan, self.pinch, self.rotate ]; return ([validSimultaneousGestures containsObject:gestureRecognizer] && [validSimultaneousGestures containsObject:otherGestureRecognizer]); @@ -2889,7 +2896,7 @@ public: { self.userTrackingMode = MGLUserTrackingModeNone; - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; [self _setCenterCoordinate:centerCoordinate edgePadding:self.contentInset zoomLevel:zoomLevel direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil completionHandler:completion]; } @@ -2941,7 +2948,7 @@ public: _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; _mbglMap->easeTo(cameraOptions, animationOptions); } @@ -2966,7 +2973,7 @@ public: if (zoomLevel == self.zoomLevel) return; _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; CGFloat duration = animated ? MGLAnimationDuration : 0; @@ -3057,7 +3064,7 @@ public: { self.userTrackingMode = MGLUserTrackingModeNone; - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; [self _setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:completion]; } @@ -3109,7 +3116,7 @@ public: [self willChangeValueForKey:@"visibleCoordinateBounds"]; _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; _mbglMap->easeTo(cameraOptions, animationOptions); [self didChangeValueForKey:@"visibleCoordinateBounds"]; @@ -3144,7 +3151,7 @@ public: CGFloat duration = animated ? MGLAnimationDuration : 0; - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; if (self.userTrackingMode == MGLUserTrackingModeNone) { @@ -3231,7 +3238,7 @@ public: [self willChangeValueForKey:@"camera"]; _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:edgePadding]; _mbglMap->easeTo(cameraOptions, animationOptions); @@ -3290,7 +3297,7 @@ public: [self willChangeValueForKey:@"camera"]; _mbglMap->cancelTransitions(); - self.cameraChangeReason |= MGLCameraChangeReasonProgrammatic; + self.cameraChangeReasonBitmask |= MGLCameraChangeReasonBitmaskProgrammatic; mbgl::CameraOptions cameraOptions = [self cameraOptionsObjectForAnimatingToCamera:camera edgePadding:insets]; _mbglMap->flyTo(cameraOptions, animationOptions); @@ -3456,9 +3463,61 @@ public: - (void)resetCameraChangeReason { - self.cameraChangeReason = MGLCameraChangeReasonNone; + self.cameraChangeReasonBitmask = MGLCameraChangeReasonBitmaskNone; +} + +- (MGLCameraChangeReason)cameraChangeReason +{ + static NSDictionary *reasonMap = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + reasonMap = + @{ + // Pan, Rotate and Pinch can all be recognized simultaneously + @(MGLCameraChangeReasonBitmaskGesturePan) : @(MGLCameraChangeReasonGesturePan), + @(MGLCameraChangeReasonBitmaskGestureRotate) : @(MGLCameraChangeReasonGestureRotate), + @(MGLCameraChangeReasonBitmaskGesturePinch) : @(MGLCameraChangeReasonGestureZoom), + + @(MGLCameraChangeReasonBitmaskGesturePan|MGLCameraChangeReasonBitmaskGestureRotate) : @(MGLCameraChangeReasonGesturePanAndRotate), + @(MGLCameraChangeReasonBitmaskGesturePan|MGLCameraChangeReasonBitmaskGesturePinch) : @(MGLCameraChangeReasonGesturePanAndZoom), + @(MGLCameraChangeReasonBitmaskGestureRotate|MGLCameraChangeReasonBitmaskGesturePinch) : @(MGLCameraChangeReasonGestureRotateAndZoom), + + @(MGLCameraChangeReasonBitmaskGesturePan|MGLCameraChangeReasonBitmaskGestureRotate|MGLCameraChangeReasonBitmaskGesturePinch) : @(MGLCameraChangeReasonGesturePanRotateAndZoom), + + // Tilt + @(MGLCameraChangeReasonBitmaskGestureTwoFingerDrag) : @(MGLCameraChangeReasonGestureTilt), + + // Custom gestures that can map to existing reasons + @(MGLCameraChangeReasonBitmaskResetNorth|MGLCameraChangeReasonBitmaskProgrammatic) : @(MGLCameraChangeReasonGestureRotate), + @(MGLCameraChangeReasonBitmaskGestureZoomIn) : @(MGLCameraChangeReasonGestureZoom), + @(MGLCameraChangeReasonBitmaskGestureZoomOut) : @(MGLCameraChangeReasonGestureZoom), + @(MGLCameraChangeReasonBitmaskGestureOneFingerZoom) : @(MGLCameraChangeReasonGestureZoom), + }; + }); + + // For the end user we provide an enum for the change reason, so we need to map from our internal + // mask to this enum. We don't cover all possible combinations since only a subset of gestures + // can be recognized simultaneously. If you change -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: + // then please be sure to make sure this method is updated if necessary. + + NSNumber *reason = reasonMap[@(self.cameraChangeReasonBitmask)]; + if (reason) + { + return (MGLCameraChangeReason)[reason unsignedIntegerValue]; + } + else if (self.cameraChangeReasonBitmask & MGLCameraChangeReasonBitmaskProgrammatic) + { + return MGLCameraChangeReasonProgrammatic; + } + else + { + NSAssert(0, @"Camera change reason: %ld missing from mapping table.", self.cameraChangeReasonBitmask); + return MGLCameraChangeReasonInvalid; + } } + #pragma mark - Styling - - (NS_ARRAY_OF(NSURL *) *)bundledStyleURLs @@ -5467,6 +5526,8 @@ public: if (respondsToSelectorWithReason) { + + [self.delegate mapView:self regionDidChangeWithReason:self.cameraChangeReason animated:animated]; } else if (respondsToSelector) diff --git a/platform/ios/src/MGLMapViewDelegate.h b/platform/ios/src/MGLMapViewDelegate.h index abb2e9be03..eca01853ff 100644 --- a/platform/ios/src/MGLMapViewDelegate.h +++ b/platform/ios/src/MGLMapViewDelegate.h @@ -1,7 +1,7 @@ #import #import "MGLTypes.h" -#import "MGLCameraChange.h" +#import "MGLCameraChangeReason.h" NS_ASSUME_NONNULL_BEGIN -- cgit v1.2.1