Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanwilliams committed Jun 10, 2009
0 parents commit 57208d6
Show file tree
Hide file tree
Showing 12 changed files with 355 additions and 0 deletions.
10 changes: 10 additions & 0 deletions MKMapItem.j
@@ -0,0 +1,10 @@

@implementation MKMapItem : CPObject
{
}

- (String)typeName
{
return [self className].substring(2);
}
@end
118 changes: 118 additions & 0 deletions MKMapScene.j
@@ -0,0 +1,118 @@
@import <Foundation/Foundation.j>
@import "MKMapView.j"

@implementation MKMapScene : CPObject
{
MKMapView _mapView @accessors(property=mapView);
CPMutableArray _mapItems;
CPURLConnection _readConnection;
}

- (id)initWithMapView:(MKMapView)mapView
{

if (self = [super init]) {
_mapView = mapView;
_mapItems = [[CPArray alloc] init];
}
return self;
}

- (String)json
{
return CPJSObjectCreateJSON({
mapItems: [self mapItemsAsJSObject]
});
}

- (BOOL)saveToURL:(CPURL)anURL
{
var request = [CPURLRequest requestWithURL:anURL];

[request setHTTPMethod:@"POST"];
[request setHTTPBody:"data=" + [self json]];

[request setValue:@"close" forHTTPHeaderField:@"Connection"];

//[request setValue:@"true" forHTTPHeaderField:@"x-cappuccino-overwrite"];

var connection = [CPURLConnection connectionWithRequest:request delegate:self];
}

- (BOOL)readFromURL:(CPURL)anURL
{

[_readConnection cancel];
_readConnection = [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:anURL] delegate:self];
}

- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
{
if (aConnection == _readConnection) {
alert('Load failed! ' + anError);
_readConnection = nil;
} else {
alert('Save failed! ' + anError);
}
}
- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)aData
{
if (aConnection == _readConnection) {
var aData = aData.replace('while(1);', '');
var mapItems = CPJSObjectCreateWithJSON(aData);
for (var i in mapItems) {
var mapItem = mapItems[i];
[self addMapItem:[[MKMarker alloc] initAtLocation:new GLatLng(mapItem.anchor.y, mapItem.anchor.x)]];
}
}
}
- (void)connectionDidFinishLoading:(CPURLConnection)aConnection
{
if (aConnection == _readConnection) {
alert('Loaded successfully!');
_readConnection = nil;
} else {
alert('Saved successfully!');
}
}




- (Object)mapItemsAsJSObject
{
var items = [];

var enumerator = [_mapItems objectEnumerator],
item;

while (item = [enumerator nextObject])
{
items.push({
'class': [item typeName],
'anchor': [[item location].lng(), [item location].lat()]
});
}
return items;
}

- (id)initWithCoder:(CPCoder)coder
{
if (self = [super init]) {
_mapItems = [coder decodeObjectForKey:@"mapItems"];
}
return self;
}

- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeObject:_mapItems forKey:@"mapItems"];
}

- (void)addMapItem:(MKMapItem)mapItem
{
[_mapItems addObject:mapItem];
[_mapView addMapItem:mapItem];
}

@end
164 changes: 164 additions & 0 deletions MKMapView.j
@@ -0,0 +1,164 @@
@import <AppKit/CPView.j>
@import "MKMapScene.j"
@import "MKMarker.j"

@implementation MKMapView : CPView
{
CPString _apiKey;
DOMElement _DOMMapElement;
JSObject _gMap @accessors(property=gMap);
MKMapScene _scene @accessors(property=scene);
BOOL _mapReady;
BOOL _googleAjaxLoaded;
}

- (id)initWithFrame:(CGRect)aFrame apiKey:(CPString)apiKey
{
_apiKey = apiKey;
if (self = [super initWithFrame:aFrame]) {
_scene = [[MKMapScene alloc] initWithMapView:self];

var bounds = [self bounds];
_DOMMapElement = document.createElement('div');
with (_DOMMapElement.style) {
position = "absolute";
left = "0px";
top = "0px";
width = "100%";
height = "100%";
}
_DOMElement.appendChild(_DOMMapElement);

// Piggy back on the CPJSONPConnection stuff to load in the Google AJAX loader.
var url = 'http://www.google.com/jsapi?key=' + _apiKey;
var request = [CPURLRequest requestWithURL:url];
var conn = [CPJSONPConnection sendRequest:request callback:"callback" delegate:self];
}

return self;
}

- (void)connection:(CPJSONPConnection)aConnection didReceiveData:(Object)data
{
_googleAjaxLoaded = YES;
//console.log("Google AJAX API has loaded");
// Google API has loaded, now load Google Maps API. The main reason for
// using this is to avoid polluting the global namespace with G* objects
function callback() {
if (_superview) {
[self createMap];
}
};
// Load Google Maps API v2.160
google.load('maps', '2.160', {callback: callback});
}

- (void)createMap
{
var GEvent = google.maps.Event,
GMap2 = google.maps.Map2,
GLatLng = google.maps.LatLng,
GPoint = google.maps.Point;

//console.log("Creating map");
_gMap = new GMap2(_DOMMapElement);
//_gMap.addMapType(G_SATELLITE_3D_MAP);
_gMap.setMapType(G_PHYSICAL_MAP);
_gMap.setUIToDefault();
_gMap.setCenter(new GLatLng(52, -1), 8);
_gMap.enableContinuousZoom();


// Horrible hack to fix dragging of th emap
function startDrag(ev)
{
if (_gMap._dragging) {
return;
}
_gMap._dragging = true;
_gMap._draggingHandlers = [
GEvent.addDomListener(document.body, 'mousemove', doDrag),
GEvent.addDomListener(document.body, 'mouseup', endDrag)
];
_gMap._dragStartLocation = new GPoint(ev.clientX, ev.clientY);
_gMap._dragStartCenter = _gMap.fromLatLngToDivPixel(_gMap.getCenter());
}
function doDrag(ev)
{
if (!_gMap._dragging) {
endDrag(ev);
return;
}

var currentLocation = new GPoint(ev.clientX, ev.clientY);
var x_diff = currentLocation.x - _gMap._dragStartLocation.x;
var y_diff = currentLocation.y - _gMap._dragStartLocation.y;
var x = _gMap._dragStartCenter.x - x_diff;
var y = _gMap._dragStartCenter.y - y_diff;

var newCenter = new GPoint(x, y);
var destination = _gMap.fromDivPixelToLatLng(newCenter);

_gMap.setCenter(destination);
_gMap._dragStartLocation = currentLocation;
_gMap._dragStartCenter = _gMap.fromLatLngToDivPixel(_gMap.getCenter());
}
function endDrag(ev)
{
if (_gMap._draggingHandlers) {
for (var i=0; i<_gMap._draggingHandlers.length; i++) {
GEvent.removeListener(_gMap._draggingHandlers[i]);
}
delete _gMap._draggingHandlers;
}
if (_gMap._dragging) {
delete _gMap._dragging;
}
}


var dragNode = _DOMMapElement.firstChild.firstChild;
GEvent.addDomListener(dragNode, 'mousedown', startDrag);

// Hack to get mouse up event to work
GEvent.addDomListener(document.body, 'mouseup', function() { GEvent.trigger(window, 'mouseup'); });

_mapReady = YES;
}
- (void)setFrameSize:(CGSize)aSize
{
[super setFrameSize:aSize];
var bounds = [self bounds];
if (_gMap) {
_gMap.checkResize();
}
}


- (void)viewDidMoveToSuperview
{
if (!_mapReady && _googleAjaxLoaded) {
[self createMap];
}
[super viewDidMoveToSuperview];
}

- (MKMarker)addMarker:(MKMarker)marker atLocation:(GLatLng)location
{
if (_mapReady) {
var gMarker = [marker gMarker];
gMarker.setLatLng(location);
_gMap.addOverlay(gMarker);
} else {
// TODO some sort of queue?
}
return marker;
}

- (void)addMapItem:(MKMapItem)mapItem
{
[mapItem addToMapView:self];
}

@end

57 changes: 57 additions & 0 deletions MKMarker.j
@@ -0,0 +1,57 @@
@import <AppKit/CPView.j>
@import "MKMapItem.j"

@implementation MKMarker : MKMapItem
{
GMarker _gMarker @accessors(property=gMarker);
GLatLng _location @accessors(property=location);
}

+ (MKMarker)marker
{
return [[MKMarker alloc] init];
}

- (id)initAtLocation:(GLatLng)aLocation
{
if (self = [super init]) {
_location = aLocation;

var flags = ['red', 'blue', 'green', 'black', 'yellow'];
// Pick a random flag
var colour = flags[Math.floor(Math.random()*5)];

var flagIcon = new GIcon();
flagIcon.image = "MapKit/Resources/flag-" + colour + ".png";
flagIcon.shadow = "MapKit/Resources/flag-shadow.png";
flagIcon.iconSize = new GSize(32, 32);
flagIcon.shadowSize = new GSize(43, 32);
flagIcon.iconAnchor = new GPoint(4, 30);
flagIcon.infoWindowAnchor = new GPoint(4, 1);

var markerOptions = { icon: flagIcon, draggable:true };
_gMarker = new GMarker(aLocation, markerOptions);

GEvent.addListener(_gMarker, 'dragend', function() { [self updateLocation]; });
}
return self;
}

- (void)updateLocation
{
_location = _gMarker.getLatLng();
}

- (void)addToMapView:(MKMapView)mapView
{
var googleMap = [mapView gMap];
googleMap.addOverlay(_gMarker);
}

- (void)encodeWithCoder:(CPCoder)coder
{
[coder encodeObject:[_location.lat(), _location.lng()] forKey:@"location"];
}

@end

6 changes: 6 additions & 0 deletions README
@@ -0,0 +1,6 @@
MapKit for Cappuccino
---------------------

A very early version of a Google Maps API abstraction layer written for Cappuccino.

Don't expect much of anything to work yet.
Binary file added Resources/flag-black.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/flag-blue.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/flag-green.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/flag-red.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/flag-shadow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/flag-yellow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Resources/flag.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 57208d6

Please sign in to comment.