using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.MapKit; // required
using MonoTouch.CoreLocation; // required
namespace MapKit01
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args);
}
}
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
MKReverseGeocoder geoCoder;
public CLLocation mylocation;
CLLocationManager locationManager;
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
mapType.ValueChanged += delegate {
if (mapType.SelectedSegment == 0)
mapView.MapType = MonoTouch.MapKit.MKMapType.Standard;
else if (mapType.SelectedSegment == 1)
mapView.MapType = MonoTouch.MapKit.MKMapType.Satellite;
else if (mapType.SelectedSegment == 2)
mapView.MapType = MonoTouch.MapKit.MKMapType.Hybrid;
};
textfieldLatitude.AllEditingEvents += delegate {
Console.WriteLine("alleditingevents");
};
textfieldLatitude.Ended += delegate { // move cursor to Longitude field
textfieldLongitude.BecomeFirstResponder();
};
textfieldLongitude.AllEditingEvents += delegate {
Console.WriteLine("alleditingevents");
};
textfieldLongitude.Ended += delegate { // hide keyboard
textfieldLongitude.ResignFirstResponder();
};
buttonCurrent.TouchDown += delegate { // reverse geocode CurrentLocation (from GPS)
Console.WriteLine("geoloc location set from LocationManager " + locationManager.Location.Coordinate.Latitude
+","+locationManager.Location.Coordinate.Longitude);
CLLocationCoordinate2D location2 = new CLLocationCoordinate2D(locationManager.Location.Coordinate.Latitude
,locationManager.Location.Coordinate.Longitude);
geoCoder = new MKReverseGeocoder(location2);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
};
buttonMap.TouchDown += delegate { // reverse geocode Map center point
Console.WriteLine("geoloc location set from MapView CenterCoordinate");
geoCoder = new MKReverseGeocoder(mapView.CenterCoordinate);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
};
buttonGeoloc.TouchDown += delegate { // reverse geocode Lat,Long typed by user
try
{
Console.WriteLine("geoloc location set in button " + textfieldLatitude.Text +","+ textfieldLongitude.Text);
CLLocationCoordinate2D location1 = new CLLocationCoordinate2D(
Convert.ToDouble(textfieldLatitude.Text),
Convert.ToDouble(textfieldLongitude.Text));
geoCoder = new MKReverseGeocoder(location1);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
} catch (Exception e)
{
Console.WriteLine("buttonGeoloc.TouchDown EXCEPTION:" + e.Message);
// Probably invalid keyboard input, just reset for now...
textfieldLatitude.Text = "-33.867139";
textfieldLongitude.Text = "151.207114";
}
};
buttonGo.TouchDown += delegate { // move map to Lat,Long typed by user
mapView.SetCenterCoordinate(new CLLocationCoordinate2D(
Convert.ToDouble(textfieldLatitude.Text),
Convert.ToDouble(textfieldLongitude.Text)),true);
};
buttonGoCurrent.TouchDown += delegate { // move map to Current Location (from GPS)
CLLocationCoordinate2D location3 = new CLLocationCoordinate2D(locationManager.Location.Coordinate.Latitude
,locationManager.Location.Coordinate.Longitude);
mapView.SetCenterCoordinate(location3,true);
};
Console.WriteLine("Setup mapView; don't use ShowsUserLocation as it too easy (but it works)");
//mapView.ShowsUserLocation = true;
mapView.MapType = MonoTouch.MapKit.MKMapType.Standard;
mapView.Delegate = new MapViewDelegate(this); // RegionChanged works, GetViewForAnnotation DOESN'T
locationManager = new CLLocationManager();
locationManager.Delegate = new LocationManagerDelegate(mapView, this);
locationManager.StartUpdatingLocation();
//locationManager.DesiredAccuracy = ??? // need the CONST values for this setting
// Perform the first ReverseGeocode as the app starts up! No reason, just because we can...
CLLocationCoordinate2D location = new CLLocationCoordinate2D(0,0);
location = new CLLocationCoordinate2D(-33.867139,151.207114);
Console.WriteLine("geoloc location set");
geoCoder = new MKReverseGeocoder(location);
geoCoder.Delegate = new GeoCoderDelegate(this);
geoCoder.Start();
// Annotation DOES NOT WORK at the moment...
MyAnnotation a = new MyAnnotation(
new CLLocationCoordinate2D(40.8148495,-73.6227325)
, "Home"
, "is where the heart is"
);
// This BREAKS - see the MapViewDelegate implementation below...
//mapView.AddAnnotation(a);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
/// <summary>
/// MonoTouch definition seemed to work without too much trouble
/// </summary>
private class LocationManagerDelegate: CLLocationManagerDelegate
{
private MKMapView _mapview;
private AppDelegate _appd;
private int _count = 0;
public LocationManagerDelegate(MKMapView mapview, AppDelegate appd)
{
_mapview = mapview;
_appd=appd;
Console.WriteLine("Delegate created");
}
/// <summary>
/// Whenever the GPS sends a new location, update text in label
/// and increment the 'count' of updates AND reset the map to that location
/// </summary>
public override void UpdatedLocation (CLLocationManager manager, CLLocation newLocation, CLLocation oldLocation)
{
//base.UpdatedLocation (manager, newLocation, oldLocation);
MKCoordinateSpan span = new MKCoordinateSpan(0.2,0.2);
MKCoordinateRegion region = new MKCoordinateRegion(newLocation.Coordinate,span);
_appd.mylocation = newLocation;
_mapview.SetRegion(region, true);
_appd.labelInfo.Text = "UserLocation (" + (_count++) + ") " + newLocation.Coordinate.Latitude + ", " + newLocation.Coordinate.Longitude;
Console.WriteLine("Location updated");
}
public override void Failed (CLLocationManager manager, NSError error)
{
_appd.labelInfo.Text = "Failed to find location";
Console.WriteLine("Failed to find location");
base.Failed (manager, error);
}
}
/// <summary>
/// Annotations are NOT working at present, so this is
/// here for testing. I have tried adding ExportAttribute
/// to title/subtitle _methods_ rather than overriding
/// the c# properties in the MonoTouch.MapKit.MKAnnotation
/// implementation - doesn't seem to help though...
/// </summary>
[Model]
[Register("MKAnnotation")]
public class MyAnnotation : MKAnnotation
{
private CLLocationCoordinate2D _coordinate;
private string _title, _subtitle;
[Export("coordinate")]
public override CLLocationCoordinate2D coordinate{get{ return _coordinate;}}
[Export("title")]
public string title () {return _title;}
//public override string Title {get {return _title;}}
[Export("subtitle")]
public string subtitle () {return _subtitle;}
//public override string Subtitle {get {return _subtitle;}}
public MyAnnotation (CLLocationCoordinate2D coord, string t, string s)
{
_coordinate=coord;
_title=t;
_subtitle=s;
}
}
/// <summary>
/// 'handler' for messages from ReverseGeocoderDelegate; pass in
/// reference to main window via ctor so we can chat with the UI
/// </summary>
[Register]
public class GeoCoderDelegate : MKReverseGeocoderDelegate
{
AppDelegate _appd;
public GeoCoderDelegate (AppDelegate appd)
{
_appd = appd;
}
/// <summary>
/// Not currently exposed by MonoTouch, ExportAttribute seems to work though
/// </summary>
[Export("reverseGeocoder:didFindPlacemark:")]
public void FoundPlacemark(MKReverseGeocoder geocoder, MKPlacemark placemark)
{
Console.WriteLine("Found placemark in " + placemark.Country);
//Console.WriteLine(placemark.Country);
//Console.WriteLine(placemark.AdministrativeArea);
//Console.WriteLine(placemark.SubAdministrativeArea);
//Console.WriteLine(placemark.Locality);
//Console.WriteLine(placemark.SubLocality);
//Console.WriteLine(placemark.PostalCode);
//Console.WriteLine(placemark.Thoroughfare);
//Console.WriteLine(placemark.SubThoroughfare);
Console.WriteLine(placemark.SubThoroughfare +placemark.Thoroughfare +placemark.SubLocality +placemark.Locality +placemark.SubAdministrativeArea +placemark.AdministrativeArea + placemark.Country
);
_appd.labelPlacemark.Text = placemark.SubThoroughfare+" "+placemark.Thoroughfare
+" " + placemark.Locality + " "+placemark.AdministrativeArea + " " + placemark.Country;
//_appd.mapView.AddAnnotation(placemark); // Can't do this, even though in ObjC you 'can' due to MKPlacemark implementing MKAnnotation @protocol
}
/// <summary>
/// Exposed by MonoTouch, just override to make it work
/// </summary>
public override void FailedWithError (MKReverseGeocoder gc, NSError error)
{
_appd.labelPlacemark.Text = "Reverse Geocoder " + error.LocalizedDescription;
Console.WriteLine("Reverse Geocoder failed");
}
}
/// <summary>
/// Had lots of problems with this class. RegionChanged did NOT work
/// without an ExportAttribute (caused stack dump).
/// </summary>
[Register]
public class MapViewDelegate : MKMapViewDelegate
{private AppDelegate _appd;
public MapViewDelegate (AppDelegate appd)
{
_appd = appd;
}
/// <summary>
/// When user moves the map, update lat,long text in label
/// </summary>
[Export("mapView:RegionDidChangeAnimated:")]
public override void RegionChanged (MKMapView mapView, bool animated)
{
Console.WriteLine("Region did change");
//base.RegionChanged (mapView, animated);
_appd.labelCurrent.Text = "Map Center " + mapView.CenterCoordinate.Latitude + ", " + mapView.CenterCoordinate.Longitude;
}
/// <summary>
/// No matter what I try with this method, it breaks...
/// </summary>
/// <remarks>
/// Got a SIGSEGV while executing native code. This usually indicates
/// a fatal error in the mono runtime or one of the native libraries
/// used by your application.
///
/// warning: Trying to remove a section from the ordered section list that did not exist at 0x2d2000.
/// warning: Could not find object file "/var/folders/-L/-LDuG6p1HfKIbOkyX-sSd++++TI/-Tmp-/tmp58110387.tmp/main.o" - no debug information available for "/var/folders/-L/-LDuG6p1HfKIbOkyX-sSd++++TI/-Tmp-/tmp58110387.tmp/main.m".
/// </remarks>
[Export("mapView:viewForAnnotation:")]
public override MKAnnotationView GetViewForAnnotation(MKMapView mapView, MKAnnotation annotation)
{
Console.WriteLine("attempt to get view for MKAnnotation " + annotation.coordinate.Latitude +", "+annotation.coordinate.Longitude);
var anv = mapView.DequeueReusableAnnotation("thislocation");
if (anv == null)
{
Console.WriteLine("creating new MKAnnotationView");
var pinanv = new MKPinAnnotationView();
//pinanv.AnimatesDrop = true;
//pinanv.PinColor = MKPinAnnotationColor.Green;
anv = pinanv;
}
else { anv.Annotation = annotation;
}
return anv;
//MKPinAnnotationView annView = new MKPinAnnotationView();
//annView.Annotation = annotation;
//annView.ReuseIdentifier = "currentloc";
//annView.AnimatesDrop = true;
//return annView;
}
}
}
}