// // MapViewController.m // Geopher Lite // // Created by Jeremy on 7/11/09. // Copyright 2009 Stone Software. All rights reserved. // #import "MapViewController.h" #import "PinAnnotation.h" #import "RootViewController.h" #import "LocatorModel.h" @implementation MapViewController @synthesize map, spinWheel, rootController, targetLocation, backButton, currentPosButton, targetButton, typeButton; #pragma mark - - (void)mapViewDidFailLoadingMap:(MKMapView *)mapView withError:(NSError *)error { [spinWheel stopAnimating]; NSLog(@"Animation stopped with error: %s", [error localizedDescription]); } - (void)mapViewWillStartLoadingMap:(MKMapView *)mapView { [spinWheel startAnimating]; } - (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView { [spinWheel stopAnimating]; } #pragma mark - - (IBAction) toggleType:(id)sender { MKMapType theType = map.mapType; // rotate through the map types if (theType == MKMapTypeStandard) theType = MKMapTypeHybrid; else if (theType == MKMapTypeSatellite) theType = MKMapTypeStandard; else if (theType == MKMapTypeHybrid) theType = MKMapTypeSatellite; map.mapType = theType; } - (void) centerOnLocation:(CLLocation*)location { // set the new coordinates [map setCenterCoordinate:location.coordinate animated:YES]; } - (IBAction) centerOnTarget:(id)sender { MKMapView* mapView = self.map; // get the locations and then the number of pixels from those locations they are apart. CLLocationCoordinate2D targetCoord = [[LocatorModel sharedInstance].targetLocation coordinate]; CLLocationCoordinate2D userLocation = [[[self.map userLocation] location] coordinate]; CGPoint userPt = [mapView convertCoordinate:userLocation toPointToView:mapView]; CGPoint targetPt = [mapView convertCoordinate:targetCoord toPointToView:mapView]; CGSize size; size.width = MAX(userPt.x, targetPt.x) - MIN(userPt.x, targetPt.x); size.height = MAX(userPt.y, targetPt.y) - MIN(userPt.y, targetPt.y); if (!CGRectContainsPoint(self.view.frame, targetPt) || !CGRectContainsPoint(self.view.frame, userPt)) { CLLocationCoordinate2D southWest = targetCoord; CLLocationCoordinate2D northEast = southWest; southWest.latitude = MIN(southWest.latitude, userLocation.latitude); southWest.longitude = MIN(southWest.longitude, userLocation.longitude); northEast.latitude = MAX(northEast.latitude, userLocation.latitude); northEast.longitude = MAX(northEast.longitude, userLocation.longitude); CLLocation *locSouthWest = [[CLLocation alloc] initWithLatitude:southWest.latitude longitude:southWest.longitude]; CLLocation *locNorthEast = [[CLLocation alloc] initWithLatitude:northEast.latitude longitude:northEast.longitude]; // This is a diag distance (if you wanted tighter you could do NE-NW or NE-SE) CLLocationDistance meters = [locSouthWest distanceFromLocation:locNorthEast]; MKCoordinateRegion region; region.center.latitude = (southWest.latitude + northEast.latitude) / 2.0; region.center.longitude = (southWest.longitude + northEast.longitude) / 2.0; region.span.latitudeDelta = meters / 111319.5; double degreeRatio = fabs(region.center.longitude) / 180.0; region.span.longitudeDelta = (meters / 111319.5) * (1.0 - degreeRatio); region = [mapView regionThatFits:region]; [mapView setRegion:region animated:YES]; [locSouthWest release]; [locNorthEast release]; } else // otherwise simply center on the point. { [self centerOnLocation:[LocatorModel sharedInstance].targetLocation]; } } - (IBAction) centerOnSelf:(id)sender { [self centerOnLocation:[LocatorModel sharedInstance].currentLocation]; } - (IBAction) goBack:(id)sender { // hide the flipside toolbar RootViewController* root = [g_AppDelegate rootViewController]; [root.flipsideNavigationBar setHidden:NO]; // set up the curl animation [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.6]; [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:root.flipsideViewController.view cache:YES]; // set back up the flipside view [root.flipsideViewController viewWillAppear:YES]; [self viewWillDisappear:YES]; [self.view removeFromSuperview]; [self viewDidDisappear:YES]; [root.flipsideViewController viewDidAppear:YES]; // animate [UIView commitAnimations]; // turn off the GPS if it's off in the prefs to conserve battery. if ([[NSUserDefaults standardUserDefaults] stringForKey:kAlwaysOnGPSKey] == NO) { [[LocatorModel sharedInstance].locationManager stopUpdatingLocation]; [[LocatorModel sharedInstance].locationManager stopUpdatingHeading]; } [self release]; } #pragma mark - - (void)viewDidLoad { [super viewDidLoad]; MKCoordinateRegion region; region.center.latitude = [LocatorModel sharedInstance].currentLocation.coordinate.latitude; region.center.longitude = [LocatorModel sharedInstance].currentLocation.coordinate.longitude; region.span.latitudeDelta = 0.005; region.span.longitudeDelta = 0.005; [map setRegion:region animated:YES]; NSMutableString* coordStr = [[NSMutableString alloc] init]; // set the target coordinates in the bottom text field [coordStr appendString:[[LocatorModel sharedInstance] currentLatitudeText: NO]]; [coordStr appendString:@", "]; [coordStr appendString:[[LocatorModel sharedInstance] currentLongitudeText: NO]]; [targetLocation setText:coordStr]; // apparently I don't need a current location as the built in map will do it for you. For now // just add the target as a pin. CLLocationCoordinate2D loc; NSMutableString* str = [[NSMutableString alloc] init]; loc.latitude = [LocatorModel sharedInstance].targetLocation.coordinate.latitude; loc.longitude = [LocatorModel sharedInstance].targetLocation.coordinate.longitude; PinAnnotation* target = [[PinAnnotation alloc] initWithCoordinate:loc]; // fill in tooltip-esque name of the cache if ([[rootController.cacheIDTextView text] isEqualToString:@"GC"] == NO && [[rootController.cacheIDTextView text] length] > 0) { [str appendString:@"Geocache "]; [str appendString:[rootController.cacheIDTextView text]]; } else { [str appendString:@"Target Location"]; } // now set the text on the tooltip (callout) popup target.currentTitle = str; target.currentSubTitle = coordStr; // cleanup memory [coordStr release]; [str release]; // now make the pin with the "target" we set up above. MKPinAnnotationView* targetPin = [[MKPinAnnotationView alloc] initWithAnnotation:target reuseIdentifier:@"targetPin"]; targetPin.pinColor = MKPinAnnotationColorPurple; targetPin.animatesDrop = YES; targetPin.canShowCallout = YES; [map addAnnotation:target]; [target release]; [targetPin release]; } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } - (void)viewDidUnload { // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (void)dealloc { [super dealloc]; } @end