From b7b8baef9d30d31a757dbbc0fbb8cb2c5cf3585e Mon Sep 17 00:00:00 2001 From: Fabian Guerra Soto Date: Wed, 18 Oct 2017 15:18:54 -0400 Subject: [ios, macos] Add selection support to MGLMultiPoint annotations. (#9984) * [ios, macos] Add selection support to MGLMultiPoint annotations. * [ios, macos] Update changelogs. --- platform/macos/CHANGELOG.md | 1 + platform/macos/src/MGLMapView.mm | 75 ++++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 23 deletions(-) (limited to 'platform/macos') diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 31b3540a7c..4b3292c600 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -27,6 +27,7 @@ * Increased the default maximum zoom level from 20 to 22. ([#9835](https://github.com/mapbox/mapbox-gl-native/pull/9835)) * Added an `overlays` property to `MGLMapView`. ([#8617](https://github.com/mapbox/mapbox-gl-native/pull/8617)) * Added `-[MGLMapView cameraThatFitsShape:direction:edgePadding:]` to get a camera with zoom level and center coordinate computed to fit a shape. ([#10107](https://github.com/mapbox/mapbox-gl-native/pull/10107)) +* Added support selection of shape and polyline annotations.([#9984](https://github.com/mapbox/mapbox-gl-native/pull/9984)) ### Other changes diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 0aa5bdc9db..af8ddbbe11 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -1791,6 +1791,12 @@ public: } std::vector annotationTags = [self annotationTagsInRect:rect]; + std::vector shapeAnnotationTags = [self shapeAnnotationTagsInRect:rect]; + + if (shapeAnnotationTags.size()) { + annotationTags.insert(annotationTags.end(), shapeAnnotationTags.begin(), shapeAnnotationTags.end()); + } + if (annotationTags.size()) { NSMutableArray *annotations = [NSMutableArray arrayWithCapacity:annotationTags.size()]; @@ -2050,35 +2056,43 @@ public: queryRect = NSInsetRect(queryRect, -MGLAnnotationImagePaddingForHitTest, -MGLAnnotationImagePaddingForHitTest); std::vector nearbyAnnotations = [self annotationTagsInRect:queryRect]; + BOOL queryingShapeAnnotations = NO; + + if (!nearbyAnnotations.size()) { + nearbyAnnotations = [self shapeAnnotationTagsInRect:queryRect]; + queryingShapeAnnotations = YES; + } if (nearbyAnnotations.size()) { // Assume that the user is fat-fingering an annotation. NSRect hitRect = NSInsetRect({ point, NSZeroSize }, -MGLAnnotationImagePaddingForHitTest, -MGLAnnotationImagePaddingForHitTest); - - // Filter out any annotation whose image is unselectable or for which - // hit testing fails. - auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag annotationTag) { - id annotation = [self annotationWithTag:annotationTag]; - NSAssert(annotation, @"Unknown annotation found nearby click"); - if (!annotation) { - return true; - } - - MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag]; - if (!annotationImage.selectable) { - return true; - } - - // Filter out the annotation if the fattened finger didn’t land on a - // translucent or opaque pixel in the image. - NSRect annotationRect = [self frameOfImage:annotationImage.image - centeredAtCoordinate:annotation.coordinate]; - return !!![annotationImage.image hitTestRect:hitRect withImageDestinationRect:annotationRect - context:nil hints:nil flipped:NO]; - }); - nearbyAnnotations.resize(std::distance(nearbyAnnotations.begin(), end)); + + if (!queryingShapeAnnotations) { + // Filter out any annotation whose image is unselectable or for which + // hit testing fails. + auto end = std::remove_if(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag annotationTag) { + id annotation = [self annotationWithTag:annotationTag]; + NSAssert(annotation, @"Unknown annotation found nearby click"); + if (!annotation) { + return true; + } + + MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag]; + if (!annotationImage.selectable) { + return true; + } + + // Filter out the annotation if the fattened finger didn’t land on a + // translucent or opaque pixel in the image. + NSRect annotationRect = [self frameOfImage:annotationImage.image + centeredAtCoordinate:annotation.coordinate]; + return !!![annotationImage.image hitTestRect:hitRect withImageDestinationRect:annotationRect + context:nil hints:nil flipped:NO]; + }); + nearbyAnnotations.resize(std::distance(nearbyAnnotations.begin(), end)); + } } MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound; @@ -2149,6 +2163,14 @@ public: }); } +- (std::vector)shapeAnnotationTagsInRect:(NSRect)rect { + // Cocoa origin is at the lower-left corner. + return _rendererFrontend->getRenderer()->queryShapeAnnotations({ + { NSMinX(rect), NSHeight(self.bounds) - NSMaxY(rect) }, + { NSMaxX(rect), NSHeight(self.bounds) - NSMinY(rect) }, + }); +} + - (id )selectedAnnotation { if ( ! _annotationContextsByAnnotationTag.count(_selectedAnnotationTag) || _selectedAnnotationTag == MGLAnnotationTagNotFound) { @@ -2314,6 +2336,13 @@ public: if (!annotation) { return NSZeroRect; } + if ([annotation isKindOfClass:[MGLMultiPoint class]]) { + CLLocationCoordinate2D origin = annotation.coordinate; + CGPoint originPoint = [self convertCoordinate:origin toPointToView:self]; + return CGRectMake(originPoint.x, originPoint.y, MGLAnnotationImagePaddingForHitTest, MGLAnnotationImagePaddingForHitTest); + + } + NSImage *image = [self imageOfAnnotationWithTag:annotationTag].image; if (!image) { image = [self dequeueReusableAnnotationImageWithIdentifier:MGLDefaultStyleMarkerSymbolName].image; -- cgit v1.2.1