diff options
author | Julian Rex <julian.rex@mapbox.com> | 2018-02-19 22:28:13 -0500 |
---|---|---|
committer | Julian Rex <julian.rex@mapbox.com> | 2018-03-20 15:19:20 -0400 |
commit | a4e149431a218dc24b30541c940c6c1c0441a903 (patch) | |
tree | 099587441392b4a28b230a3e8593f4b575e26bdf | |
parent | 68fcbf0a7274516555bcc44f932c8bbe8f1eb073 (diff) | |
download | qtlocation-mapboxgl-a4e149431a218dc24b30541c940c6c1c0441a903.tar.gz |
[ios,macos] Removes check for on-screen in setSelectedAnnotations (#9790). Adds partial test.
-rw-r--r-- | platform/ios/CHANGELOG.md | 1 | ||||
-rw-r--r-- | platform/ios/app/MBXViewController.m | 57 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.h | 3 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 8 | ||||
-rw-r--r-- | platform/ios/test/MGLAnnotationViewTests.m | 61 | ||||
-rw-r--r-- | platform/macos/CHANGELOG.md | 1 | ||||
-rw-r--r-- | platform/macos/app/Base.lproj/MainMenu.xib | 18 | ||||
-rw-r--r-- | platform/macos/app/MapDocument.m | 60 | ||||
-rw-r--r-- | platform/macos/src/MGLMapView.h | 3 | ||||
-rw-r--r-- | platform/macos/src/MGLMapView.mm | 5 |
10 files changed, 195 insertions, 22 deletions
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 4288517265..fa5f1a7fab 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -36,6 +36,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Fixed an issue preventing `MGLAnnotationImage.image` from being updated. ([#10372](https://github.com/mapbox/mapbox-gl-native/pull/10372)) * Improved performance of `MGLAnnotationView`-backed annotations that have `scalesWithViewingDistance` enabled. ([#10951](https://github.com/mapbox/mapbox-gl-native/pull/10951)) * Fix an issue where a wrong annotation may selected if annotations were set close together. ([#11438](https://github.com/mapbox/mapbox-gl-native/pull/11438)) +* The `MGLMapView.selectedAnnotations` property (backed by `-[MGLMapView setSelectedAnnotations:]`) now selects annotations that are off-screen. ([#9790](https://github.com/mapbox/mapbox-gl-native/issues/9790)) ### Map snapshots diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index a472e3a221..fcdc9af2b3 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -54,6 +54,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsAnnotationsRows) { MBXSettingsAnnotationsQueryAnnotations, MBXSettingsAnnotationsCustomUserDot, MBXSettingsAnnotationsRemoveAnnotations, + MBXSettingsAnnotationSelectRandomOffscreenAnnotation, + MBXSettingsAnnotationCenterSelectedAnnotation }; typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) { @@ -340,6 +342,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @"Query Annotations", [NSString stringWithFormat:@"%@ Custom User Dot", (_customUserLocationAnnnotationEnabled ? @"Disable" : @"Enable")], @"Remove Annotations", + @"Select an offscreen annotation", + @"Center selected annotation" ]]; break; case MBXSettingsRuntimeStyling: @@ -468,6 +472,14 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { case MBXSettingsAnnotationsRemoveAnnotations: [self.mapView removeAnnotations:self.mapView.annotations]; break; + case MBXSettingsAnnotationSelectRandomOffscreenAnnotation: + [self selectAnOffscreenAnnotation]; + break; + + case MBXSettingsAnnotationCenterSelectedAnnotation: + [self centerSelectedAnnotation]; + break; + default: NSAssert(NO, @"All annotations setting rows should be implemented"); break; @@ -1551,6 +1563,51 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { [self presentViewController:alertController animated:YES completion:nil]; } +- (id<MGLAnnotation>)randomOffscreenAnnotation { + NSArray *annotations = self.mapView.annotations; + + if (annotations.count == 0) + return nil; + + NSArray *visibleAnnotations = self.mapView.visibleAnnotations; + + if (visibleAnnotations.count == annotations.count) + return nil; + + NSMutableArray *invisibleAnnotations = [annotations mutableCopy]; + + if (visibleAnnotations.count > 0) { + [invisibleAnnotations removeObjectsInArray:visibleAnnotations]; + } + + // Now pick a random offscreen annotation. + uint32_t index = arc4random_uniform((uint32_t)invisibleAnnotations.count); + return invisibleAnnotations[index]; +} + +- (void)selectAnOffscreenAnnotation { + id<MGLAnnotation> annotation = [self randomOffscreenAnnotation]; + [self.mapView selectAnnotation:annotation animated:NO]; + + // Alternative method to select the annotation (NOT ANIMATED). These two should do the same thing. + // self.mapView.selectedAnnotations = @[annotation]; + + NSAssert(self.mapView.selectedAnnotations.firstObject, @"The annotation was not selected"); +} + +- (void)centerSelectedAnnotation { + id<MGLAnnotation> annotation = self.mapView.selectedAnnotations.firstObject; + + if (!annotation) + return; + + CGPoint point = [self.mapView convertCoordinate:annotation.coordinate toPointToView:self.mapView]; + + // Animate, so that point becomes the the center + CLLocationCoordinate2D center = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; + [self.mapView setCenterCoordinate:center animated:YES]; +} + - (void)printTelemetryLogFile { NSString *fileContents = [NSString stringWithContentsOfFile:[self telemetryDebugLogFilePath] encoding:NSUTF8StringEncoding error:nil]; diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h index 52d28d871c..22fa58643d 100644 --- a/platform/ios/src/MGLMapView.h +++ b/platform/ios/src/MGLMapView.h @@ -1206,9 +1206,6 @@ MGL_EXPORT IB_DESIGNABLE /** Selects an annotation and displays a callout view for it. - If the given annotation is not visible within the current viewport, this - method has no effect. - @param annotation The annotation object to select. @param animated If `YES`, the callout view is animated into position. */ diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 6b47dc05f7..a639588caa 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -272,7 +272,7 @@ public: CADisplayLink *_displayLink; BOOL _needsDisplayRefresh; - NSUInteger _changeDelimiterSuppressionDepth; + NSInteger _changeDelimiterSuppressionDepth; /// Center coordinate of the pinch gesture on the previous iteration of the gesture. CLLocationCoordinate2D _previousPinchCenterCoordinate; @@ -4274,11 +4274,7 @@ public: if ([firstAnnotation isKindOfClass:[MGLMultiPoint class]]) return; - // Select the annotation if it’s visible. - if (MGLCoordinateInCoordinateBounds(firstAnnotation.coordinate, self.visibleCoordinateBounds)) - { - [self selectAnnotation:firstAnnotation animated:NO]; - } + [self selectAnnotation:firstAnnotation animated:NO]; } - (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated diff --git a/platform/ios/test/MGLAnnotationViewTests.m b/platform/ios/test/MGLAnnotationViewTests.m index fc4f35a9e1..128fab472e 100644 --- a/platform/ios/test/MGLAnnotationViewTests.m +++ b/platform/ios/test/MGLAnnotationViewTests.m @@ -57,6 +57,7 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu @property (nonatomic) XCTestExpectation *expectation; @property (nonatomic) MGLMapView *mapView; @property (nonatomic, weak) MGLAnnotationView *annotationView; +@property (nonatomic) NSInteger annotationSelectedCount; @end @implementation MGLAnnotationViewTests @@ -98,6 +99,61 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu XCTAssertNotNil(customAnnotationView); } +- (void)testSelectingOffscreenAnnotation +{ + // Partial test for https://github.com/mapbox/mapbox-gl-native/issues/9790 + + // This isn't quite the same as in updateAnnotationViews, but should be sufficient for this test. + MGLCoordinateBounds coordinateBounds = [_mapView convertRect:_mapView.bounds toCoordinateBoundsFromView:_mapView]; + + // -90 latitude is invalid. TBD. + BOOL anyOffscreen = NO; + NSInteger selectionCount = 0; + + for (NSInteger latitude = -89; latitude <= 90; latitude += 10) + { + for (NSInteger longitude = -180; longitude <= 180; longitude += 10) + { + MGLTestAnnotation *annotation = [[MGLTestAnnotation alloc] init]; + + annotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude); + [_mapView addAnnotation:annotation]; + + if (!(MGLCoordinateInCoordinateBounds(annotation.coordinate, coordinateBounds))) + anyOffscreen = YES; + + XCTAssertNil(_mapView.selectedAnnotations.firstObject, @"There should be no selected annotation"); + + // First selection + [_mapView selectAnnotation:annotation animated:NO]; + selectionCount++; + + XCTAssert(_mapView.selectedAnnotations.count == 1, @"There should only be 1 selected annotation"); + XCTAssertEqualObjects(_mapView.selectedAnnotations.firstObject, annotation, @"The annotation should be selected"); + + // Deselect + [_mapView deselectAnnotation:annotation animated:NO]; + XCTAssert(_mapView.selectedAnnotations.count == 0, @"There should be no selected annotations"); + + // Second selection + _mapView.selectedAnnotations = @[annotation]; + selectionCount++; + + XCTAssert(_mapView.selectedAnnotations.count == 1, @"There should be 1 selected annotation"); + XCTAssertEqualObjects(_mapView.selectedAnnotations.firstObject, annotation, @"The annotation should be selected"); + + // Deselect + [_mapView deselectAnnotation:annotation animated:NO]; + XCTAssert(_mapView.selectedAnnotations.count == 0, @"There should be no selected annotations"); + } + } + + XCTAssert(anyOffscreen, @"At least one of these annotations should be offscreen"); + XCTAssertEqual(selectionCount, self.annotationSelectedCount, @"-mapView:didSelectAnnotation: should be called for each selection"); +} + +#pragma mark - MGLMapViewDelegate - + - (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAnnotation>)annotation { MGLAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:MGLTestAnnotationReuseIdentifer]; @@ -117,4 +173,9 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu [_expectation fulfill]; } +- (void)mapView:(MGLMapView *)mapView didSelectAnnotation:(id<MGLAnnotation>)annotation +{ + self.annotationSelectedCount++; +} + @end diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 6de2a4e87e..4bbb2dfb63 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -37,6 +37,7 @@ * The `-[MGLMapView convertRect:toCoordinateBoundsFromView:]` method and the `MGLMapView.visibleCoordinateBounds` property’s getter now indicate that the coordinate bounds straddles the antimeridian by extending one side beyond ±180 degrees longitude. ([#11265](https://github.com/mapbox/mapbox-gl-native/pull/11265)) * Feature querying results now account for the `MGLSymbolStyleLayer.circleStrokeWidth` property. ([#10897](https://github.com/mapbox/mapbox-gl-native/pull/10897)) * Removed methods, properties, and constants that had been deprecated as of v0.6.1. ([#11205](https://github.com/mapbox/mapbox-gl-native/pull/11205)) +* The `MGLMapView.selectedAnnotations` property (backed by `-[MGLMapView setSelectedAnnotations:]`) now selects annotations that are off-screen. ([#9790](https://github.com/mapbox/mapbox-gl-native/issues/9790)) ## v0.6.1 - January 16, 2018 diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib index 4cf8d87653..64d776832f 100644 --- a/platform/macos/app/Base.lproj/MainMenu.xib +++ b/platform/macos/app/Base.lproj/MainMenu.xib @@ -545,7 +545,13 @@ <action selector="drawAnimatedAnnotation:" target="-1" id="CYM-WB-s97"/> </connections> </menuItem> - <menuItem title="Show All Annnotations" keyEquivalent="A" id="yMj-uM-8SN"> + <menuItem title="Select and Center Offscreen Annotation" id="Xy2-Cc-RUB"> + <modifierMask key="keyEquivalentModifierMask"/> + <connections> + <action selector="selectAndCenterOffscreenAnnotation:" target="-1" id="W0A-AH-NqK"/> + </connections> + </menuItem> + <menuItem title="Show All Annotations" keyEquivalent="A" id="yMj-uM-8SN"> <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/> <connections> <action selector="showAllAnnotations:" target="-1" id="ahr-OR-Em2"/> @@ -664,7 +670,7 @@ CA <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/> <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> <rect key="contentRect" x="109" y="131" width="350" height="84"/> - <rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/> + <rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/> <view key="contentView" id="eA4-n3-qPe"> <rect key="frame" x="0.0" y="0.0" width="350" height="84"/> <autoresizingMask key="autoresizingMask"/> @@ -740,7 +746,7 @@ CA <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" utility="YES"/> <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/> <rect key="contentRect" x="830" y="430" width="400" height="300"/> - <rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/> + <rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/> <view key="contentView" id="8ha-hw-zOD"> <rect key="frame" x="0.0" y="0.0" width="400" height="300"/> <autoresizingMask key="autoresizingMask"/> @@ -748,11 +754,11 @@ CA <scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q8b-0e-dLv"> <rect key="frame" x="-1" y="20" width="402" height="281"/> <clipView key="contentView" id="J9U-Yx-o2S"> - <rect key="frame" x="1" y="0.0" width="400" height="280"/> + <rect key="frame" x="1" y="0.0" width="400" height="265"/> <autoresizingMask key="autoresizingMask"/> <subviews> <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" autosaveColumns="NO" headerView="MAZ-Iq-hBi" id="Ato-Vu-HYT"> - <rect key="frame" x="0.0" y="0.0" width="423" height="257"/> + <rect key="frame" x="0.0" y="0.0" width="423" height="242"/> <autoresizingMask key="autoresizingMask"/> <size key="intercellSpacing" width="3" height="2"/> <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> @@ -891,7 +897,7 @@ CA </subviews> </clipView> <scroller key="horizontalScroller" verticalHuggingPriority="750" horizontal="YES" id="QLr-6P-Ogs"> - <rect key="frame" x="1" y="264" width="400" height="16"/> + <rect key="frame" x="1" y="265" width="400" height="15"/> <autoresizingMask key="autoresizingMask"/> </scroller> <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="q0K-eE-mzL"> diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m index 03557caca2..9127df9346 100644 --- a/platform/macos/app/MapDocument.m +++ b/platform/macos/app/MapDocument.m @@ -641,6 +641,63 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio repeats:YES]; } + +- (id<MGLAnnotation>)randomOffscreenAnnotation { + NSArray *annotations = self.mapView.annotations; + + if (annotations.count == 0) + return nil; + + // NOTE: This occasionally returns nil - see + // https://github.com/mapbox/mapbox-gl-native/issues/11296 + NSArray *visibleAnnotations = self.mapView.visibleAnnotations; + + NSLog(@"Number of visible annotations = %d", visibleAnnotations.count); + + if (visibleAnnotations.count == annotations.count) + return nil; + + NSMutableArray *invisibleAnnotations = [annotations mutableCopy]; + + if (visibleAnnotations.count > 0) { + [invisibleAnnotations removeObjectsInArray:visibleAnnotations]; + } + + // Now pick a random offscreen annotation. + uint32_t index = arc4random_uniform((uint32_t)invisibleAnnotations.count); + return invisibleAnnotations[index]; +} + +- (void)selectAnOffscreenAnnotation { + id<MGLAnnotation> annotation = [self randomOffscreenAnnotation]; + [self.mapView selectAnnotation:annotation]; + + // Alternative method to select the annotation. These two should do the same thing. +// self.mapView.selectedAnnotations = @[annotation]; + + NSAssert(self.mapView.selectedAnnotations.firstObject, @"The annotation was not selected"); +} + +- (void)centerSelectedAnnotation { + id<MGLAnnotation> annotation = self.mapView.selectedAnnotations.firstObject; + + if (!annotation) + return; + + CGPoint point = [self.mapView convertCoordinate:annotation.coordinate toPointToView:self.mapView]; + + // Animate, so that point becomes the the center + CLLocationCoordinate2D center = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; + [self.mapView setCenterCoordinate:center animated:YES]; +} + +- (IBAction)selectAndCenterOffscreenAnnotation:(id)sender { + [self selectAnOffscreenAnnotation]; + [self centerSelectedAnnotation]; +} + + + - (void)updateAnimatedAnnotation:(NSTimer *)timer { DroppedPinAnnotation *annotation = timer.userInfo; double angle = timer.fireDate.timeIntervalSinceReferenceDate; @@ -1111,6 +1168,9 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio if (menuItem.action == @selector(insertGraticuleLayer:)) { return ![self.mapView.style sourceWithIdentifier:@"graticule"]; } + if (menuItem.action == @selector(selectAndCenterOffscreenAnnotation:)) { + return YES; + } if (menuItem.action == @selector(showAllAnnotations:) || menuItem.action == @selector(removeAllAnnotations:)) { return self.mapView.annotations.count > 0; } diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h index 050145b80b..344052c310 100644 --- a/platform/macos/src/MGLMapView.h +++ b/platform/macos/src/MGLMapView.h @@ -727,9 +727,6 @@ MGL_EXPORT IB_DESIGNABLE /** Selects an annotation and displays a callout popover for it. - If the given annotation is not visible within the current viewport, this method - has no effect. - @param annotation The annotation object to select. */ - (void)selectAnnotation:(id <MGLAnnotation>)annotation; diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 353b2bf2f1..ffca1d30ad 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -2205,10 +2205,7 @@ public: return; } - // Select the annotation if it’s visible. - if (MGLCoordinateInCoordinateBounds(firstAnnotation.coordinate, self.visibleCoordinateBounds)) { - [self selectAnnotation:firstAnnotation]; - } + [self selectAnnotation:firstAnnotation]; } - (void)selectAnnotation:(id <MGLAnnotation>)annotation |