[osx] Drop Pin context menu item

This commit is contained in:
Minh Nguyễn
2015-12-01 09:45:29 -08:00
committed by Minh Nguyễn
parent cc35f5a2a7
commit 96145ef170
4 changed files with 96 additions and 57 deletions

View File

@@ -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;

View File

@@ -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];
}
}

View File

@@ -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"/>

View File

@@ -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;
}