diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2015-12-01 09:45:29 -0800 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2015-12-13 17:26:53 -0800 |
commit | 96145ef1707516484913447de95f33a77d8a59eb (patch) | |
tree | 5892417ee1abef43ab06f18da82e7cd0fd4b76e1 | |
parent | cc35f5a2a7f78cabdb75f75966fb72fa5f447c62 (diff) | |
download | qtlocation-mapboxgl-96145ef1707516484913447de95f33a77d8a59eb.tar.gz |
[osx] Drop Pin context menu item
-rw-r--r-- | include/mbgl/osx/MGLMapView.h | 2 | ||||
-rw-r--r-- | platform/osx/app/AppDelegate.m | 18 | ||||
-rw-r--r-- | platform/osx/app/MainMenu.xib | 6 | ||||
-rw-r--r-- | platform/osx/sdk/MGLMapView.mm | 127 |
4 files changed, 96 insertions, 57 deletions
diff --git a/include/mbgl/osx/MGLMapView.h b/include/mbgl/osx/MGLMapView.h index 27c67bd38e..cb0df30f54 100644 --- a/include/mbgl/osx/MGLMapView.h +++ b/include/mbgl/osx/MGLMapView.h @@ -69,6 +69,8 @@ IB_DESIGNABLE - (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated; - (void)deselectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated; +- (id <MGLAnnotation>)annotationAtPoint:(NSPoint)point; + - (void)addOverlay:(id <MGLOverlay>)overlay; - (void)addOverlays:(NS_ARRAY_OF(id <MGLOverlay>) *)overlays; - (void)removeOverlay:(id <MGLOverlay>)overlay; diff --git a/platform/osx/app/AppDelegate.m b/platform/osx/app/AppDelegate.m index 4c8ce92ab7..4e6f0746ce 100644 --- a/platform/osx/app/AppDelegate.m +++ b/platform/osx/app/AppDelegate.m @@ -271,6 +271,14 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken [self.mapView selectAnnotation:annotation animated:YES]; } +- (IBAction)removePin:(NSMenuItem *)sender { + [self removePinAtPoint:_mouseLocationForMapViewContextMenu]; +} + +- (void)removePinAtPoint:(NSPoint)point { + [self.mapView removeAnnotation:[self.mapView annotationAtPoint:point]]; +} + #pragma mark User interface validation - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { @@ -319,6 +327,13 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken return YES; } if (menuItem.action == @selector(dropPin:)) { + BOOL isOverAnnotation = [self.mapView annotationAtPoint:_mouseLocationForMapViewContextMenu]; + menuItem.hidden = isOverAnnotation; + return YES; + } + if (menuItem.action == @selector(removePin:)) { + BOOL isOverAnnotation = [self.mapView annotationAtPoint:_mouseLocationForMapViewContextMenu]; + menuItem.hidden = !isOverAnnotation; return YES; } if (menuItem.action == @selector(toggleTileBoundaries:)) { @@ -423,7 +438,8 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken - (void)menuWillOpen:(NSMenu *)menu { if (menu == self.mapViewContextMenu) { - _mouseLocationForMapViewContextMenu = self.window.mouseLocationOutsideOfEventStream; + _mouseLocationForMapViewContextMenu = [self.window.contentView convertPoint:self.window.mouseLocationOutsideOfEventStream + toView:self.mapView]; } } diff --git a/platform/osx/app/MainMenu.xib b/platform/osx/app/MainMenu.xib index c96169b094..a47e7dcf75 100644 --- a/platform/osx/app/MainMenu.xib +++ b/platform/osx/app/MainMenu.xib @@ -669,6 +669,12 @@ <action selector="dropPin:" target="Voe-Tx-rLC" id="eDR-iw-JUG"/> </connections> </menuItem> + <menuItem title="Remove Pin" id="rgF-cY-qgP"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="removePin:" target="Voe-Tx-rLC" id="38n-9m-8Wp"/> + </connections> + </menuItem> </items> <connections> <outlet property="delegate" destination="Voe-Tx-rLC" id="MsV-YU-f4X"/> diff --git a/platform/osx/sdk/MGLMapView.mm b/platform/osx/sdk/MGLMapView.mm index 76ad50bd30..79067095e8 100644 --- a/platform/osx/sdk/MGLMapView.mm +++ b/platform/osx/sdk/MGLMapView.mm @@ -217,6 +217,7 @@ public: _annotationContextsByAnnotationID = {}; _selectedAnnotationID = MGLAnnotationNotFound; _lastSelectedAnnotationID = MGLAnnotationNotFound; + _annotationsNearbyLastClick = {}; mbgl::CameraOptions options; options.center = mbgl::LatLng(0, 0); @@ -873,62 +874,8 @@ public: return; } - // Look for any annotation near the click. An annotation is “near” if the - // distance between its center and the click is less than the maximum height - // or width of an installed annotation image. NSPoint gesturePoint = [gestureRecognizer locationInView:self]; - NSRect queryRect = NSInsetRect({ gesturePoint, NSZeroSize }, - -_unionedAnnotationImageSize.width / 2, - -_unionedAnnotationImageSize.height / 2); - queryRect = NSInsetRect(queryRect, -MGLAnnotationImagePaddingForHitTest, - -MGLAnnotationImagePaddingForHitTest); - mbgl::LatLngBounds queryBounds = [self convertRectToLatLngBounds:queryRect]; - std::vector<MGLAnnotationID> nearbyAnnotations = _mbglMap->getPointAnnotationsInBounds(queryBounds); - - if (nearbyAnnotations.size()) { - NSRect hitRect = NSInsetRect({ gesturePoint, NSZeroSize }, - -MGLAnnotationImagePaddingForHitTest, - -MGLAnnotationImagePaddingForHitTest); - mbgl::util::erase_if(nearbyAnnotations, [&](const MGLAnnotationID annotationID) { - NSAssert(_annotationContextsByAnnotationID.count(annotationID) != 0, @"Unknown annotation found nearby click"); - id <MGLAnnotation> annotation = [self annotationWithID:annotationID]; - if (!annotation) { - return true; - } - - MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithID:annotationID]; - if (!annotationImage.selectable) { - return true; - } - - NSRect annotationRect = [self frameOfImage:annotationImage.image - centeredAtCoordinate:annotation.coordinate]; - return !!![annotationImage.image hitTestRect:hitRect withImageDestinationRect:annotationRect - context:nil hints:nil flipped:NO]; - }); - } - - MGLAnnotationID hitAnnotationID = MGLAnnotationNotFound; - if (nearbyAnnotations.size()) { - std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end()); - - if (nearbyAnnotations == _annotationsNearbyLastClick) { - if (_lastSelectedAnnotationID == _annotationsNearbyLastClick.back() - || _lastSelectedAnnotationID == MGLAnnotationNotFound) { - hitAnnotationID = _annotationsNearbyLastClick.front(); - } else { - auto result = std::find(_annotationsNearbyLastClick.begin(), - _annotationsNearbyLastClick.end(), - _lastSelectedAnnotationID); - auto distance = std::distance(_annotationsNearbyLastClick.begin(), result); - hitAnnotationID = _annotationsNearbyLastClick[distance + 1]; - } - } else { - _annotationsNearbyLastClick = nearbyAnnotations; - hitAnnotationID = _annotationsNearbyLastClick.front(); - } - } - + MGLAnnotationID hitAnnotationID = [self annotationIDAtPoint:gesturePoint persistingResults:YES]; if (hitAnnotationID != MGLAnnotationNotFound) { if (hitAnnotationID != _selectedAnnotationID) { id <MGLAnnotation> annotation = [self annotationWithID:hitAnnotationID]; @@ -1282,6 +1229,73 @@ public: return self.annotationImagesByIdentifier[identifier]; } +- (id <MGLAnnotation>)annotationAtPoint:(NSPoint)point { + return [self annotationWithID:[self annotationIDAtPoint:point persistingResults:NO]]; +} + +- (MGLAnnotationID)annotationIDAtPoint:(NSPoint)point persistingResults:(BOOL)persist { + // Look for any annotation near the click. An annotation is “near” if the + // distance between its center and the click is less than the maximum height + // or width of an installed annotation image. + NSRect queryRect = NSInsetRect({ point, NSZeroSize }, + -_unionedAnnotationImageSize.width / 2, + -_unionedAnnotationImageSize.height / 2); + queryRect = NSInsetRect(queryRect, -MGLAnnotationImagePaddingForHitTest, + -MGLAnnotationImagePaddingForHitTest); + mbgl::LatLngBounds queryBounds = [self convertRectToLatLngBounds:queryRect]; + std::vector<MGLAnnotationID> nearbyAnnotations = _mbglMap->getPointAnnotationsInBounds(queryBounds); + + if (nearbyAnnotations.size()) { + NSRect hitRect = NSInsetRect({ point, NSZeroSize }, + -MGLAnnotationImagePaddingForHitTest, + -MGLAnnotationImagePaddingForHitTest); + mbgl::util::erase_if(nearbyAnnotations, [&](const MGLAnnotationID annotationID) { + NSAssert(_annotationContextsByAnnotationID.count(annotationID) != 0, @"Unknown annotation found nearby click"); + id <MGLAnnotation> annotation = [self annotationWithID:annotationID]; + if (!annotation) { + return true; + } + + MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithID:annotationID]; + if (!annotationImage.selectable) { + return true; + } + + NSRect annotationRect = [self frameOfImage:annotationImage.image + centeredAtCoordinate:annotation.coordinate]; + return !!![annotationImage.image hitTestRect:hitRect withImageDestinationRect:annotationRect + context:nil hints:nil flipped:NO]; + }); + } + + MGLAnnotationID hitAnnotationID = MGLAnnotationNotFound; + if (nearbyAnnotations.size()) { + std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end()); + + if (nearbyAnnotations == _annotationsNearbyLastClick) { + if (_lastSelectedAnnotationID == _annotationsNearbyLastClick.back() + || _lastSelectedAnnotationID == MGLAnnotationNotFound) { + hitAnnotationID = _annotationsNearbyLastClick.front(); + } else { + auto result = std::find(_annotationsNearbyLastClick.begin(), + _annotationsNearbyLastClick.end(), + _lastSelectedAnnotationID); + auto distance = std::distance(_annotationsNearbyLastClick.begin(), result); + hitAnnotationID = _annotationsNearbyLastClick[distance + 1]; + } + } else { + if (persist) { + _annotationsNearbyLastClick = nearbyAnnotations; + } + if (_annotationsNearbyLastClick.size()) { + hitAnnotationID = _annotationsNearbyLastClick.front(); + } + } + } + + return hitAnnotationID; +} + - (NS_ARRAY_OF(id <MGLAnnotation>) *)selectedAnnotations { id <MGLAnnotation> selectedAnnotation = self.selectedAnnotation; return selectedAnnotation ? @[selectedAnnotation] : @[]; @@ -1391,7 +1405,8 @@ public: } - (MGLAnnotationImage *)imageOfAnnotationWithID:(MGLAnnotationID)annotationID { - if (annotationID == MGLAnnotationNotFound) { + if (annotationID == MGLAnnotationNotFound + || _annotationContextsByAnnotationID.count(annotationID) == 0) { return nil; } |