From 5dd71d3c3048c1a521f65f3a2f7b13c9c0fed279 Mon Sep 17 00:00:00 2001 From: Jesse Crocker Date: Thu, 1 Dec 2016 11:50:20 -0800 Subject: =?UTF-8?q?[ios,=20macos]=20Make=20tap=20gesture=20recognizer=20fa?= =?UTF-8?q?il=20if=20it=20doesn=E2=80=99t=20do=20anything=20(#7246)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make tap gesture recognizer fail if it doesn’t do anything. * fix typo * Use the right nullable * update changelog * Make single click gesture recognizer fail if it doesn’t select an annotation * fix changelog typo * Remove singleTapGestureRecognizer from public header --- platform/ios/CHANGELOG.md | 1 + platform/ios/src/MGLMapView.mm | 64 +++++++++++++++++++++++++++++----------- platform/macos/CHANGELOG.md | 1 + platform/macos/src/MGLMapView.mm | 24 ++++++++++++--- 4 files changed, 69 insertions(+), 21 deletions(-) diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index b395fa6bb6..d904c3cebd 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -83,6 +83,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794)) * MGLMapDebugOverdrawVisualizationMask no longer has any effect in Release builds of the SDK. This debug mask has been disabled for performance reasons. ([#5555](https://github.com/mapbox/mapbox-gl-native/pull/5555)) * Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879)) +* The UITapGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a tap does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246)) ## 3.3.6 - November 9, 2016 diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 68a1196fa4..5c365ad87b 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -236,9 +236,8 @@ public: @property (nonatomic, readwrite) UIButton *attributionButton; @property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *attributionButtonConstraints; @property (nonatomic) UIActionSheet *attributionSheet; - @property (nonatomic, readwrite) MGLStyle *style; - +@property (nonatomic) UITapGestureRecognizer *singleTapGestureRecognizer; @property (nonatomic) UIPanGestureRecognizer *pan; @property (nonatomic) UIPinchGestureRecognizer *pinch; @property (nonatomic) UIRotationGestureRecognizer *rotate; @@ -502,9 +501,10 @@ public: doubleTap.numberOfTapsRequired = 2; [self addGestureRecognizer:doubleTap]; - UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)]; - [singleTap requireGestureRecognizerToFail:doubleTap]; - [self addGestureRecognizer:singleTap]; + _singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)]; + [_singleTapGestureRecognizer requireGestureRecognizerToFail:doubleTap]; + _singleTapGestureRecognizer.delegate = self; + [self addGestureRecognizer:_singleTapGestureRecognizer]; UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTapGesture:)]; twoFingerTap.numberOfTouchesRequired = 2; @@ -1398,6 +1398,27 @@ public: return; } + idannotation = [self annotationForGestureRecognizer:singleTap persistingResults:YES]; + if(annotation) + { + [self selectAnnotation:annotation animated:YES]; + } + else + { + [self deselectAnnotation:self.selectedAnnotation animated:YES]; + } +} + +/** + Returns the annotation that would be selected by a tap gesture recognizer. + + This is used when a gesture is recognized, and to check if the gesture should be recognized. + + @param singleTap An in progress tap gesture recognizer. + @param persist True to remember the cycleable set of annotations. @see annotationTagAtPoint:persistingResults + */ +- (nullable id )annotationForGestureRecognizer:(UITapGestureRecognizer*)singleTap persistingResults:(BOOL)persist +{ CGPoint tapPoint = [singleTap locationInView:self]; if (self.userLocationVisible) @@ -1412,19 +1433,19 @@ public: // Get the tap point within the custom hit test layer. tapPointForUserLocation = [singleTap locationInView:self.userLocationAnnotationView]; } - + CALayer *hitLayer = [self.userLocationAnnotationView.hitTestLayer hitTest:tapPointForUserLocation]; - + if (hitLayer) { if ( ! _userLocationAnnotationIsSelected) { - [self selectAnnotation:self.userLocation animated:YES]; + return self.userLocation; } - return; + return nil; } } - + // Handle the case of an offset annotation view by converting the tap point to be the geo location // of the annotation itself that the view represents for (MGLAnnotationView *view in self.annotationContainerView.annotationViews) @@ -1436,21 +1457,19 @@ public: } } } - - MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:tapPoint persistingResults:YES]; + + MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:tapPoint persistingResults:persist]; if (hitAnnotationTag != MGLAnnotationTagNotFound) { if (hitAnnotationTag != _selectedAnnotationTag) { id annotation = [self annotationWithTag:hitAnnotationTag]; NSAssert(annotation, @"Cannot select nonexistent annotation with tag %u", hitAnnotationTag); - [self selectAnnotation:annotation animated:YES]; + return annotation; } } - else - { - [self deselectAnnotation:self.selectedAnnotation animated:YES]; - } + + return nil; } - (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap @@ -1608,6 +1627,17 @@ public: } } } + else if (gestureRecognizer == _singleTapGestureRecognizer) + { + //Gesture will be recognized if it could deselect an annotation + if(!self.selectedAnnotation) + { + idannotation = [self annotationForGestureRecognizer:(UITapGestureRecognizer*)gestureRecognizer persistingResults:NO]; + if(!annotation) { + return NO; + } + } + } return YES; } diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 9675ec8447..37e51d7c58 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -57,6 +57,7 @@ * Fixed an issue where the map view’s center would always be calculated as if the view occupied the entire window. ([#6102](https://github.com/mapbox/mapbox-gl-native/pull/6102)) * Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794)) * Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879)) +* The NSClickGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a click does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246)) ## 0.2.1 - July 19, 2016 diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index ba07048262..204efd4987 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -145,7 +145,7 @@ public: NSString *imageReuseIdentifier; }; -@interface MGLMapView () +@interface MGLMapView () @property (nonatomic, readwrite) NSSegmentedControl *zoomControls; @property (nonatomic, readwrite) NSSlider *compass; @@ -172,6 +172,7 @@ public: NSPanGestureRecognizer *_panGestureRecognizer; NSMagnificationGestureRecognizer *_magnificationGestureRecognizer; NSRotationGestureRecognizer *_rotationGestureRecognizer; + NSClickGestureRecognizer *_singleClickRecognizer; double _scaleAtBeginningOfGesture; CLLocationDirection _directionAtBeginningOfGesture; CGFloat _pitchAtBeginningOfGesture; @@ -408,9 +409,10 @@ public: _panGestureRecognizer.delaysKeyEvents = YES; [self addGestureRecognizer:_panGestureRecognizer]; - NSClickGestureRecognizer *clickGestureRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(handleClickGesture:)]; - clickGestureRecognizer.delaysPrimaryMouseButtonEvents = NO; - [self addGestureRecognizer:clickGestureRecognizer]; + _singleClickRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(handleClickGesture:)]; + _singleClickRecognizer.delaysPrimaryMouseButtonEvents = NO; + _singleClickRecognizer.delegate = self; + [self addGestureRecognizer:_singleClickRecognizer]; NSClickGestureRecognizer *rightClickGestureRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightClickGesture:)]; rightClickGestureRecognizer.buttonMask = 0x2; @@ -1540,6 +1542,20 @@ public: return nil; } +#pragma mark NSGestureRecognizerDelegate methods +- (BOOL)gestureRecognizer:(NSGestureRecognizer *)gestureRecognizer shouldAttemptToRecognizeWithEvent:(NSEvent *)event { + if (gestureRecognizer == _singleClickRecognizer) { + if (!self.selectedAnnotation) { + NSPoint gesturePoint = [self convertPoint:[event locationInWindow] fromView:nil]; + MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:gesturePoint persistingResults:NO]; + if (hitAnnotationTag == MGLAnnotationTagNotFound) { + return NO; + } + } + } + return YES; +} + #pragma mark Keyboard events - (void)keyDown:(NSEvent *)event { -- cgit v1.2.1