Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios, macos] Added delegate method to restrict movement
Browse files Browse the repository at this point in the history
Added a way for the delegate to restrict where the user can move within the map using gestures.

Fixes #2457.
  • Loading branch information
1ec5 authored and fabian-guerra committed Jan 27, 2017
1 parent 7637b85 commit 4b85fa6
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 7 deletions.
11 changes: 6 additions & 5 deletions platform/ios/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Fixed an issue that caused an assertion failure if a `MGLShapeCollection` (a GeoJSON GeometryCollection) was created with an empty array of shapes. ([#7632](https://github.com/mapbox/mapbox-gl-native/pull/7632))
* Improved the precision of annotations at zoom levels greater than 18. ([#5517](https://github.com/mapbox/mapbox-gl-native/pull/5517))

### User interactivity

* Added a method to MGLMapViewDelegate, `-mapView:shouldChangeFromCamera:toCamera:`, that you can implement to restrict which parts the user can navigate to using gestures. ([#5584](https://github.com/mapbox/mapbox-gl-native/pull/5584))
* The UITapGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a tap does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246))
* As the user zooms in, tiles from lower zoom levels are scaled up until tiles for higher zoom levels are loaded. ([#5143](https://github.com/mapbox/mapbox-gl-native/pull/5143))

### Networking and offline maps

* Fixed an issue preventing an MGLMapView from loading tiles while an offline pack is downloading. ([#6446](https://github.com/mapbox/mapbox-gl-native/pull/6446))
Expand All @@ -112,14 +118,9 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT

### Other changes

* Raster tiles such as those from Mapbox Satellite are now cached, eliminating flashing while panning back and forth. ([#7091](https://github.com/mapbox/mapbox-gl-native/pull/7091))
* Improved the performance of symbol style layers. ([#7025](https://github.com/mapbox/mapbox-gl-native/pull/7025))
* As the user zooms in, tiles from lower zoom levels are scaled up until tiles for higher zoom levels are loaded. ([#5143](https://github.com/mapbox/mapbox-gl-native/pull/5143))
* Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794))
* MGLMapDebugOverdrawVisualizationMask no longer has any effect in Release builds of the SDK. This debug mask has been disabled for performance reasons. ([#5555](https://github.com/mapbox/mapbox-gl-native/pull/5555))
* Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879))
* The UITapGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a tap does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246))
* Fixed issues related to the visibility of sources in viewports less than 512 pixels wide or tall. ([#7438](https://github.com/mapbox/mapbox-gl-native/pull/7438))

## 3.3.7 - November 17, 2016

Expand Down
10 changes: 10 additions & 0 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,8 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan

_mbglMap->cancelTransitions();

MGLMapCamera *oldCamera = self.camera;
BOOL didChangeCamera = NO;
if (pan.state == UIGestureRecognizerStateBegan)
{
[self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
Expand All @@ -1214,6 +1216,7 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan
CGPoint delta = [pan translationInView:pan.view];
_mbglMap->moveBy({ delta.x, delta.y });
[pan setTranslation:CGPointZero inView:pan.view];
didChangeCamera = YES;

[self notifyMapChange:mbgl::MapChangeRegionIsChanging];
}
Expand Down Expand Up @@ -1246,6 +1249,13 @@ - (void)handlePanGesture:(UIPanGestureRecognizer *)pan
MGLEventKeyZoomLevel: @(zoom)
}];
}

if (didChangeCamera
&& [self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera])
{
self.camera = oldCamera;
}
}

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch
Expand Down
19 changes: 19 additions & 0 deletions platform/ios/src/MGLMapViewDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,25 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated;

/**
Asks the delegate whether the map view should be allowed to change from the
existing camera to the new camera in response to a user gesture.
This method is called as soon as the user gesture is recognized. It is not
called in response to a programmatic camera change, such as by setting the
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
@param mapView The map view that the user is manipulating.
@param oldCamera The camera representing the viewpoint at the moment the
gesture is recognized. If this method returns `NO`, the map view’s camera
continues to be this camera.
@param newCamera The expected camera after the gesture completes. If this
method returns `YES`, this camera becomes the map view’s camera.
@return A Boolean value indicating whether the map view should stay at
`oldCamera` or change to `newCamera`.
*/
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;

#pragma mark Loading the Map

/**
Expand Down
8 changes: 6 additions & 2 deletions platform/macos/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox
* Improved style parsing performance. ([#6170](https://github.com/mapbox/mapbox-gl-native/pull/6170))
* Improved feature querying performance. ([#6514](https://github.com/mapbox/mapbox-gl-native/pull/6514))
* Fixed an issue where shapes that cannot currently be visually represented as annotations were still shown on the map as point annotations. ([#6764](https://github.com/mapbox/mapbox-gl-native/issues/6764))
* Raster tiles such as those from Mapbox Satellite are now cached, eliminating flashing while panning back and forth. ([#7091](https://github.com/mapbox/mapbox-gl-native/pull/7091))

### Annotations

Expand All @@ -81,6 +82,11 @@ This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox
* Fixed an issue that caused an assertion failure if a `MGLShapeCollection` (a GeoJSON GeometryCollection) was created with an empty array of shapes. ([#7632](https://github.com/mapbox/mapbox-gl-native/pull/7632))
* Improved the precision of annotations at zoom levels greater than 18. ([#5517](https://github.com/mapbox/mapbox-gl-native/pull/5517))

### User interactivity

* Added a method to MGLMapViewDelegate, `-mapView:shouldChangeFromCamera:toCamera:`, that you can implement to restrict which parts the user can navigate to using gestures. ([#5584](https://github.com/mapbox/mapbox-gl-native/pull/5584))
* The NSClickGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a click does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246))

### Networking and offline maps

* Fixed an issue preventing an MGLMapView from loading tiles while an offline pack is downloading. ([#6446](https://github.com/mapbox/mapbox-gl-native/pull/6446))
Expand All @@ -94,11 +100,9 @@ This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox

### Other changes

* Raster tiles such as those from Mapbox Satellite are now cached, eliminating flashing while panning back and forth. ([#7091](https://github.com/mapbox/mapbox-gl-native/pull/7091))
* Fixed an issue where the map view’s center would always be calculated as if the view occupied the entire window. ([#6102](https://github.com/mapbox/mapbox-gl-native/pull/6102))
* Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794))
* Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879))
* The NSClickGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a click does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246))

## 0.2.1 - July 19, 2016

Expand Down
32 changes: 32 additions & 0 deletions platform/macos/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -988,8 +988,13 @@ - (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate animated:(B
- (void)offsetCenterCoordinateBy:(NSPoint)delta animated:(BOOL)animated {
[self willChangeValueForKey:@"centerCoordinate"];
_mbglMap->cancelTransitions();
MGLMapCamera *oldCamera = self.camera;
_mbglMap->moveBy({ delta.x, delta.y },
MGLDurationInSecondsFromTimeInterval(animated ? MGLAnimationDuration : 0));
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
self.camera = oldCamera;
}
[self didChangeValueForKey:@"centerCoordinate"];
}

Expand Down Expand Up @@ -1036,8 +1041,13 @@ - (void)zoomBy:(double)zoomDelta animated:(BOOL)animated {
- (void)scaleBy:(double)scaleFactor atPoint:(NSPoint)point animated:(BOOL)animated {
[self willChangeValueForKey:@"centerCoordinate"];
[self willChangeValueForKey:@"zoomLevel"];
MGLMapCamera *oldCamera = self.camera;
mbgl::ScreenCoordinate center(point.x, self.bounds.size.height - point.y);
_mbglMap->scaleBy(scaleFactor, center, MGLDurationInSecondsFromTimeInterval(animated ? MGLAnimationDuration : 0));
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
self.camera = oldCamera;
}
[self didChangeValueForKey:@"zoomLevel"];
[self didChangeValueForKey:@"centerCoordinate"];
}
Expand Down Expand Up @@ -1372,15 +1382,25 @@ - (void)handlePanGesture:(NSPanGestureRecognizer *)gestureRecognizer {
_directionAtBeginningOfGesture = self.direction;
_pitchAtBeginningOfGesture = _mbglMap->getPitch();
} else if (gestureRecognizer.state == NSGestureRecognizerStateChanged) {
MGLMapCamera *oldCamera = self.camera;
BOOL didChangeCamera = NO;
mbgl::ScreenCoordinate center(startPoint.x, self.bounds.size.height - startPoint.y);
if (self.rotateEnabled) {
CLLocationDirection newDirection = _directionAtBeginningOfGesture - delta.x / 10;
[self willChangeValueForKey:@"direction"];
_mbglMap->setBearing(newDirection, center);
didChangeCamera = YES;
[self didChangeValueForKey:@"direction"];
}
if (self.pitchEnabled) {
_mbglMap->setPitch(_pitchAtBeginningOfGesture + delta.y / 5, center);
didChangeCamera = YES;
}

if (didChangeCamera
&& [self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
self.camera = oldCamera;
}
}
} else if (self.scrollEnabled) {
Expand Down Expand Up @@ -1420,7 +1440,12 @@ - (void)handleMagnificationGesture:(NSMagnificationGestureRecognizer *)gestureRe
if (gestureRecognizer.magnification > -1) {
[self willChangeValueForKey:@"zoomLevel"];
[self willChangeValueForKey:@"centerCoordinate"];
MGLMapCamera *oldCamera = self.camera;
_mbglMap->setScale(_scaleAtBeginningOfGesture * (1 + gestureRecognizer.magnification), center);
if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
self.camera = oldCamera;
}
[self didChangeValueForKey:@"centerCoordinate"];
[self didChangeValueForKey:@"zoomLevel"];
}
Expand Down Expand Up @@ -1495,9 +1520,16 @@ - (void)handleRotationGesture:(NSRotationGestureRecognizer *)gestureRecognizer {
_mbglMap->setGestureInProgress(true);
_directionAtBeginningOfGesture = self.direction;
} else if (gestureRecognizer.state == NSGestureRecognizerStateChanged) {
MGLMapCamera *oldCamera = self.camera;

NSPoint rotationPoint = [gestureRecognizer locationInView:self];
mbgl::ScreenCoordinate center(rotationPoint.x, self.bounds.size.height - rotationPoint.y);
_mbglMap->setBearing(_directionAtBeginningOfGesture + gestureRecognizer.rotationInDegrees, center);

if ([self.delegate respondsToSelector:@selector(mapView:shouldChangeFromCamera:toCamera:)]
&& ![self.delegate mapView:self shouldChangeFromCamera:oldCamera toCamera:self.camera]) {
self.camera = oldCamera;
}
} else if (gestureRecognizer.state == NSGestureRecognizerStateEnded
|| gestureRecognizer.state == NSGestureRecognizerStateCancelled) {
_mbglMap->setGestureInProgress(false);
Expand Down
19 changes: 19 additions & 0 deletions platform/macos/src/MGLMapViewDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)mapView:(MGLMapView *)mapView cameraDidChangeAnimated:(BOOL)animated;

/**
Asks the delegate whether the map view should be allowed to change from the
existing camera to the new camera in response to a user gesture.
This method is called as soon as the user gesture is recognized. It is not
called in response to a programmatic camera change, such as by setting the
`centerCoordinate` property or calling `-flyToCamera:completionHandler:`.
@param mapView The map view that the user is manipulating.
@param oldCamera The camera representing the viewpoint at the moment the
gesture is recognized. If this method returns `NO`, the map view’s camera
continues to be this camera.
@param newCamera The expected camera after the gesture completes. If this
method returns `YES`, this camera becomes the map view’s camera.
@return A Boolean value indicating whether the map view should stay at
`oldCamera` or change to `newCamera`.
*/
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera;

#pragma mark Loading the Map

/**
Expand Down

0 comments on commit 4b85fa6

Please sign in to comment.