diff options
Diffstat (limited to 'ios/app/MBXViewController.mm')
-rw-r--r-- | ios/app/MBXViewController.mm | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/ios/app/MBXViewController.mm b/ios/app/MBXViewController.mm new file mode 100644 index 0000000000..4945b73cc5 --- /dev/null +++ b/ios/app/MBXViewController.mm @@ -0,0 +1,266 @@ +#import "MBXViewController.h" + +#import <mbgl/ios/MGLMapView.h> + +#import <mbgl/platform/darwin/settings_nsuserdefaults.hpp> + +#import <CoreLocation/CoreLocation.h> + +static UIColor *const kTintColor = [UIColor colorWithRed:0.120 green:0.550 blue:0.670 alpha:1.000]; + +static NSDictionary *const kStyles = @{ + @"bright-v6": @"Bright", + @"basic-v6": @"Basic", + @"outdoors-v6": @"Outdoors", + @"satellite-v6": @"Satellite" +}; + +@interface MBXViewController () <UIActionSheetDelegate, CLLocationManagerDelegate> + +@property (nonatomic) MGLMapView *mapView; +@property (nonatomic) CLLocationManager *locationManager; + +@end + +@implementation MBXViewController + +mbgl::Settings_NSUserDefaults *settings = nullptr; + +#pragma mark - Setup + +- (id)init +{ + self = [super init]; + + if (self) + { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveState:) name:UIApplicationDidEnterBackgroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(restoreState:) name:UIApplicationWillEnterForegroundNotification object:nil]; + } + + return self; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + NSString *accessToken = [[NSProcessInfo processInfo] environment][@"MAPBOX_ACCESS_TOKEN"]; + if (accessToken) { + // Store to preferences so that we can launch the app later on without having to specify + // token. + [[NSUserDefaults standardUserDefaults] setObject:accessToken forKey:@"access_token"]; + } else { + // Try to retrieve from preferences, maybe we've stored them there previously and can reuse + // the token. + accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"access_token"]; + } + + if ( ! accessToken) NSLog(@"No access token set. Mapbox vector tiles won't work."); + + self.mapView = [[MGLMapView alloc] initWithFrame:self.view.bounds accessToken:accessToken]; + self.mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + [self.view addSubview:self.mapView]; + + self.mapView.viewControllerForLayoutGuides = self; + + self.view.tintColor = kTintColor; + self.navigationController.navigationBar.tintColor = kTintColor; + self.mapView.tintColor = kTintColor; + + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"settings.png"] + style:UIBarButtonItemStylePlain + target:self + action:@selector(showSettings)]; + + UIButton *titleButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [titleButton setFrame:CGRectMake(0, 0, 120, 40)]; + [titleButton setTitle:[[kStyles allValues] firstObject] forState:UIControlStateNormal]; + [titleButton setTitleColor:kTintColor forState:UIControlStateNormal]; + [titleButton addTarget:self action:@selector(cycleStyles) forControlEvents:UIControlEventTouchUpInside]; + self.navigationItem.titleView = titleButton; + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"locateUser.png"] + style:UIBarButtonItemStylePlain + target:self + action:@selector(locateUser)]; + + settings = new mbgl::Settings_NSUserDefaults(); + [self restoreState:nil]; +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" + +- (void)saveState:(NSNotification *)notification +{ + if (self.mapView && settings) + { + settings->longitude = self.mapView.centerCoordinate.longitude; + settings->latitude = self.mapView.centerCoordinate.latitude; + settings->zoom = self.mapView.zoomLevel; + settings->bearing = self.mapView.direction; + settings->debug = self.mapView.isDebugActive; + settings->save(); + } +} + +- (void)restoreState:(NSNotification *)notification +{ + if (self.mapView && settings) { + settings->load(); + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(settings->latitude, settings->longitude) zoomLevel:settings->zoom animated:NO]; + self.mapView.direction = settings->bearing; + [self.mapView setDebugActive:settings->debug]; + } +} + +#pragma clang diagnostic pop + +- (NSUInteger)supportedInterfaceOrientations +{ + return UIInterfaceOrientationMaskAll; +} + +#pragma mark - Actions + +- (void)showSettings +{ + UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"Map Settings" + delegate:self + cancelButtonTitle:@"Cancel" + destructiveButtonTitle:nil + otherButtonTitles:@"Reset North", @"Reset Position", @"Toggle Debug", nil]; + + [sheet showFromBarButtonItem:self.navigationItem.leftBarButtonItem animated:YES]; +} + +- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex +{ + if (buttonIndex == actionSheet.firstOtherButtonIndex) + { + [self.mapView resetNorth]; + } + else if (buttonIndex == actionSheet.firstOtherButtonIndex + 1) + { + [self.mapView resetPosition]; + } + else if (buttonIndex == actionSheet.firstOtherButtonIndex + 2) + { + [self.mapView toggleDebug]; + } +} + +- (void)cycleStyles +{ + UIButton *titleButton = (UIButton *)self.navigationItem.titleView; + + NSString *styleName = [titleButton titleForState:UIControlStateNormal]; + + if ( ! styleName) + { + styleName = [[kStyles allKeys] firstObject]; + } + else + { + NSUInteger index = [[kStyles allValues] indexOfObject:styleName] + 1; + if (index == [[kStyles allKeys] count]) index = 0; + styleName = [[kStyles allKeys] objectAtIndex:index]; + } + + [self.mapView useBundledStyleNamed:styleName]; + + [titleButton setTitle:kStyles[styleName] forState:UIControlStateNormal]; +} + +- (void)locateUser +{ + if ( ! self.locationManager) + { + self.locationManager = [CLLocationManager new]; + self.locationManager.delegate = self; + } + + if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) + { + [[[UIAlertView alloc] initWithTitle:@"Authorization Denied" + message:@"Please enable location services for this app in Privacy settings." + delegate:nil + cancelButtonTitle:nil otherButtonTitles:@"OK", nil] show]; + } + else + { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) + { + if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) + { + [self.locationManager startUpdatingLocation]; + } + else + { + [_locationManager requestWhenInUseAuthorization]; + } + } + else + { + [self.locationManager startUpdatingLocation]; + } +#else + [self.locationManager startUpdatingLocation]; +#endif + } +} + +#pragma mark - Destruction + +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + if (settings) + { + [self saveState:nil]; + delete settings; + settings = nullptr; + } +} + +#pragma mark - Location + +- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status +{ + switch (status) + { + case kCLAuthorizationStatusAuthorizedAlways: +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 + case kCLAuthorizationStatusAuthorizedWhenInUse: +#endif + { + [manager startUpdatingLocation]; + break; + } + default: + { + } + } +} + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" + +- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations +{ + CLLocation *latestLocation = locations.lastObject; + + if ([latestLocation distanceFromLocation:[[CLLocation alloc] initWithLatitude:self.mapView.centerCoordinate.latitude longitude:self.mapView.centerCoordinate.longitude]] > 100) + { + [self.mapView setCenterCoordinate:CLLocationCoordinate2DMake(latestLocation.coordinate.latitude, latestLocation.coordinate.longitude) zoomLevel:17 animated:YES]; + } + + [self.locationManager stopUpdatingLocation]; +} + +#pragma clang diagnostic pop + +@end |