[osx] Annotation tooltips
Annotations can optionally have tooltips. osxapp has an option, off by default, to assign a (localized) tooltip to each dropped pin.
This commit is contained in:
committed by
Minh Nguyễn
parent
96145ef170
commit
f542d7b2a7
@@ -1,5 +1,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreLocation/CoreLocation.h>
|
||||
#import <TargetConditionals.h>
|
||||
|
||||
#import "MGLTypes.h"
|
||||
|
||||
@@ -29,6 +30,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* This string is displayed in the callout for the associated annotation. */
|
||||
@property (nonatomic, readonly, copy, nullable) NSString *subtitle;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
|
||||
/** The string containing the annotation’s tooltip. */
|
||||
@property (nonatomic, readonly, copy, nullable) NSString *toolTip;
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -15,6 +15,13 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/** The subtitle of the shape annotation. The default value of this property is `nil`. */
|
||||
@property (nonatomic, copy, nullable) NSString *subtitle;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
|
||||
/** The tooltip of the shape annotation. The default value of this property is `nil`. */
|
||||
@property (nonatomic, copy, nullable) NSString *toolTip;
|
||||
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -20,6 +20,10 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken
|
||||
|
||||
@implementation AppDelegate {
|
||||
NSPoint _mouseLocationForMapViewContextMenu;
|
||||
NSUInteger _droppedPinCounter;
|
||||
NSNumberFormatter *_spellOutNumberFormatter;
|
||||
|
||||
BOOL _showsToolTipsOnDroppedPins;
|
||||
}
|
||||
|
||||
#pragma mark Lifecycle
|
||||
@@ -64,6 +68,8 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken
|
||||
[self showPreferences:nil];
|
||||
}
|
||||
|
||||
_spellOutNumberFormatter = [[NSNumberFormatter alloc] init];
|
||||
|
||||
NSPressGestureRecognizer *pressGestureRecognizer = [[NSPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePressGesture:)];
|
||||
[self.mapView addGestureRecognizer:pressGestureRecognizer];
|
||||
}
|
||||
@@ -204,6 +210,8 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken
|
||||
[self.mapView reloadStyle:sender];
|
||||
}
|
||||
|
||||
#pragma mark Debug methods
|
||||
|
||||
- (IBAction)toggleTileBoundaries:(id)sender {
|
||||
self.mapView.debugMask ^= MGLMapDebugTileBoundariesMask;
|
||||
}
|
||||
@@ -220,6 +228,10 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken
|
||||
self.mapView.debugMask ^= MGLMapDebugCollisionBoxesMask;
|
||||
}
|
||||
|
||||
- (IBAction)toggleShowsToolTipsOnDroppedPins:(id)sender {
|
||||
_showsToolTipsOnDroppedPins = !_showsToolTipsOnDroppedPins;
|
||||
}
|
||||
|
||||
#pragma mark Help methods
|
||||
|
||||
- (IBAction)showShortcuts:(id)sender {
|
||||
@@ -267,6 +279,11 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken
|
||||
DroppedPinAnnotation *annotation = [[DroppedPinAnnotation alloc] init];
|
||||
annotation.coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
|
||||
annotation.title = @"Dropped Pin";
|
||||
_spellOutNumberFormatter.numberStyle = NSNumberFormatterSpellOutStyle;
|
||||
if (_showsToolTipsOnDroppedPins) {
|
||||
NSString *formattedNumber = [_spellOutNumberFormatter stringFromNumber:@(++_droppedPinCounter)];
|
||||
annotation.toolTip = formattedNumber;
|
||||
}
|
||||
[self.mapView addAnnotation:annotation];
|
||||
[self.mapView selectAnnotation:annotation animated:YES];
|
||||
}
|
||||
@@ -356,6 +373,11 @@ static NSString * const MGLMapboxAccessTokenDefaultsKey = @"MGLMapboxAccessToken
|
||||
menuItem.title = isShown ? @"Hide Collision Boxes" : @"Show Collision Boxes";
|
||||
return YES;
|
||||
}
|
||||
if (menuItem.action == @selector(toggleShowsToolTipsOnDroppedPins:)) {
|
||||
BOOL isShown = _showsToolTipsOnDroppedPins;
|
||||
menuItem.title = isShown ? @"Hide Tooltips on Dropped Pins" : @"Show Tooltips on Dropped Pins";
|
||||
return YES;
|
||||
}
|
||||
if (menuItem.action == @selector(showShortcuts:)) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application">
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject">
|
||||
<connections>
|
||||
<outlet property="delegate" destination="Voe-Tx-rLC" id="z9N-Fm-MUP"/>
|
||||
</connections>
|
||||
@@ -456,6 +456,13 @@
|
||||
<action selector="toggleCollisionBoxes:" target="-1" id="EYa-7n-iWZ"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="dYw-bb-tr1"/>
|
||||
<menuItem title="Show Tooltips on Dropped Pins" id="uir-Rx-zmw">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="toggleShowsToolTipsOnDroppedPins:" target="-1" id="1YC-Co-QQ6"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
|
||||
@@ -591,6 +591,7 @@ public:
|
||||
[self updateZoomControls];
|
||||
[self updateCompass];
|
||||
[self updateAnnotationCallouts];
|
||||
[self updateToolTips];
|
||||
|
||||
if ([self.delegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)]) {
|
||||
BOOL animated = change == mbgl::MapChangeRegionDidChangeAnimated;
|
||||
@@ -1150,6 +1151,8 @@ public:
|
||||
_annotationContextsByAnnotationID[shapeAnnotationIDs[i]] = context;
|
||||
}
|
||||
}
|
||||
|
||||
[self updateToolTips];
|
||||
}
|
||||
|
||||
- (void)installAnnotationImage:(MGLAnnotationImage *)annotationImage {
|
||||
@@ -1212,6 +1215,8 @@ public:
|
||||
}
|
||||
|
||||
_mbglMap->removeAnnotations(annotationIDsToRemove);
|
||||
|
||||
[self updateToolTips];
|
||||
}
|
||||
|
||||
- (id <MGLAnnotation>)selectedAnnotation {
|
||||
@@ -1242,8 +1247,7 @@ public:
|
||||
-_unionedAnnotationImageSize.height / 2);
|
||||
queryRect = NSInsetRect(queryRect, -MGLAnnotationImagePaddingForHitTest,
|
||||
-MGLAnnotationImagePaddingForHitTest);
|
||||
mbgl::LatLngBounds queryBounds = [self convertRectToLatLngBounds:queryRect];
|
||||
std::vector<MGLAnnotationID> nearbyAnnotations = _mbglMap->getPointAnnotationsInBounds(queryBounds);
|
||||
std::vector<MGLAnnotationID> nearbyAnnotations = [self annotationIDsInRect:queryRect];
|
||||
|
||||
if (nearbyAnnotations.size()) {
|
||||
NSRect hitRect = NSInsetRect({ point, NSZeroSize },
|
||||
@@ -1296,6 +1300,11 @@ public:
|
||||
return hitAnnotationID;
|
||||
}
|
||||
|
||||
- (std::vector<MGLAnnotationID>)annotationIDsInRect:(NSRect)rect {
|
||||
mbgl::LatLngBounds queryBounds = [self convertRectToLatLngBounds:rect];
|
||||
return _mbglMap->getPointAnnotationsInBounds(queryBounds);
|
||||
}
|
||||
|
||||
- (NS_ARRAY_OF(id <MGLAnnotation>) *)selectedAnnotations {
|
||||
id <MGLAnnotation> selectedAnnotation = self.selectedAnnotation;
|
||||
return selectedAnnotation ? @[selectedAnnotation] : @[];
|
||||
@@ -1509,6 +1518,36 @@ public:
|
||||
[self removeAnnotations:overlays];
|
||||
}
|
||||
|
||||
#pragma mark Tooltips
|
||||
|
||||
- (void)updateToolTips {
|
||||
[self removeAllToolTips];
|
||||
|
||||
std::vector<MGLAnnotationID> annotationIDs = [self annotationIDsInRect:self.bounds];
|
||||
for (MGLAnnotationID annotationID : annotationIDs) {
|
||||
MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithID:annotationID];
|
||||
id <MGLAnnotation> annotation = [self annotationWithID:annotationID];
|
||||
if (annotation.toolTip.length) {
|
||||
NSImage *image = annotationImage.image;
|
||||
NSRect annotationRect = [self frameOfImage:image
|
||||
centeredAtCoordinate:annotation.coordinate];
|
||||
annotationRect = NSOffsetRect(image.alignmentRect, annotationRect.origin.x, annotationRect.origin.y);
|
||||
if (!NSIsEmptyRect(annotationRect)) {
|
||||
[self addToolTipRect:annotationRect owner:self userData:(void *)(NSUInteger)annotationID];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)view:(__unused NSView *)view stringForToolTip:(__unused NSToolTipTag)tag point:(__unused NSPoint)point userData:(void *)data {
|
||||
if ((NSUInteger)data >= MGLAnnotationNotFound) {
|
||||
return nil;
|
||||
}
|
||||
MGLAnnotationID annotationID = (NSUInteger)data;
|
||||
id <MGLAnnotation> annotation = [self annotationWithID:annotationID];
|
||||
return annotation.toolTip;
|
||||
}
|
||||
|
||||
#pragma mark Interface Builder methods
|
||||
|
||||
- (void)prepareForInterfaceBuilder {
|
||||
|
||||
Reference in New Issue
Block a user