refactor the potlatch 2 code to look more MVC wrt the API parts
authorDave Stubbs <osm@randomjunk.co.uk>
Sun, 31 May 2009 19:44:55 +0000 (19:44 +0000)
committerDave Stubbs <osm@randomjunk.co.uk>
Sun, 31 May 2009 19:44:55 +0000 (19:44 +0000)
17 files changed:
halcyon.mxml
net/systemeD/halcyon/AMFConnection.as [deleted file]
net/systemeD/halcyon/Connection.as [deleted file]
net/systemeD/halcyon/Map.as
net/systemeD/halcyon/Node.as [deleted file]
net/systemeD/halcyon/POI.as
net/systemeD/halcyon/WayUI.as [moved from net/systemeD/halcyon/Way.as with 70% similarity]
net/systemeD/halcyon/connection/AMFConnection.as [new file with mode: 0755]
net/systemeD/halcyon/connection/Connection.as [new file with mode: 0755]
net/systemeD/halcyon/connection/Entity.as [new file with mode: 0644]
net/systemeD/halcyon/connection/EntityEvent.as [new file with mode: 0644]
net/systemeD/halcyon/connection/Node.as [new file with mode: 0644]
net/systemeD/halcyon/connection/Relation.as [new file with mode: 0644]
net/systemeD/halcyon/connection/RelationMember.as [new file with mode: 0644]
net/systemeD/halcyon/connection/TagList.as [new file with mode: 0644]
net/systemeD/halcyon/connection/Way.as [new file with mode: 0644]
net/systemeD/halcyon/connection/XMLConnection.as [new file with mode: 0644]

index 706fe06f80d200036307c6bba9e8ac47bf53b344..ec1c18ca3be54a22fe5b1afa82f4e6ded82f6276 100755 (executable)
 <!-- applicationComplete -->
 <!-- rawChildren -->
 
+    <mx:HDividedBox width="100%" height="100%">
+
+      <mx:VBox height="100%">
+        <mx:Button label="+" click="theMap.zoomIn();"/>
+        <mx:Button label="-" click="theMap.zoomOut();"/>
+      </mx:VBox>
+      <mx:Canvas id="map_area" clipContent="true"/>
+    </mx:HDividedBox>
+
        <mx:Script><![CDATA[
                import net.systemeD.halcyon.*;
                import flash.system.Security;
                import flash.events.MouseEvent;
                import flash.display.Sprite;
                import mx.core.IChildList;
+        import mx.containers.Canvas;
+
+        public var theMap:Map;
 
                private function initApp():void {
 
-                       Globals.vars.root=rawChildren;                  // set up global reference to root level
-                       var _root:IChildList=rawChildren;               // convenient local shorthand
+                       Globals.vars.root=map_area.rawChildren;                 // set up global reference to root level
+                       var _root:IChildList=map_area.rawChildren;              // convenient local shorthand
 
                        // map backdrop object
-                       var b:Sprite=new Sprite();
-                       b.graphics.beginFill(0xFFFFEA,100);
-                       b.graphics.drawRect(0,0,200,200);
-                       b.graphics.endFill();
+            var b:Canvas = new Canvas();
+            b.height=200; b.width=200;
+            b.setStyle("backgroundColor", 0xFFFFEA);
+                       //var b:Sprite=new Sprite();
+                       //b.graphics.beginFill(0xFFFFEA,100);
+                       //b.graphics.drawRect(0,0,200,200);
+                       //b.graphics.endFill();
                        _root.addChild(b);
 
                        // add map
-                       var theMap:Map=new Map();
+                       theMap=new Map();
                        theMap.backdrop=b;
                        _root.addChild(theMap);
 
@@ -64,9 +79,9 @@
 
                        // add debug field
                        var t:TextField=new TextField();
-                       t.width=400; t.height=100; t.border=true; 
-                       t.multiline=true;
-                       _root.addChild(t);
+                       //t.width=400; t.height=100; t.border=true; 
+                       //t.multiline=true;
+                       //_root.addChild(t);
                        Globals.vars.debug=t;
                }
 
diff --git a/net/systemeD/halcyon/AMFConnection.as b/net/systemeD/halcyon/AMFConnection.as
deleted file mode 100755 (executable)
index 19cca2e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-package net.systemeD.halcyon {
-
-       import flash.system.Security;
-       import flash.net.*;
-
-       public class AMFConnection extends Connection {
-
-               public var readConnection:NetConnection;
-               public var writeConnection:NetConnection;
-               
-               // ------------------------------------------------------------
-               // Constructor for new AMFConnection
-
-               public function AMFConnection(readURL:String,writeURL:String,policyURL:String='') {
-
-                       if (policyURL!='') { Security.loadPolicyFile(policyURL); }
-
-                       readConnection=new NetConnection();
-                       readConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
-                       readConnection.connect(readURL);
-                       
-                       writeConnection=new NetConnection();
-                       writeConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
-                       writeConnection.connect(writeURL);
-                       
-               }
-
-               public function getEnvironment(responder:Responder):void {
-                       readConnection.call("getpresets",responder,"en");
-               }
-               
-               public function getBbox(left:Number,right:Number,
-                                                               top:Number,bottom:Number,
-                                                               responder:Responder):void {
-                       readConnection.call("whichways",responder,left,bottom,right,top);
-               }
-
-               public function getWay(id:uint,responder:Responder):void {
-                       readConnection.call("getway",responder,id);
-               }
-
-       }
-}
diff --git a/net/systemeD/halcyon/Connection.as b/net/systemeD/halcyon/Connection.as
deleted file mode 100755 (executable)
index f5dfd09..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-package net.systemeD.halcyon {
-       public class Connection {
-       }
-}
index 5caa1b5ecec5a712a1b2d0a1fdd2896f0ffdb682..8830de308b9f351b5bb66452d89cc70eab3808cd 100755 (executable)
@@ -6,9 +6,12 @@ package net.systemeD.halcyon {
        import flash.display.Shape;
        import flash.display.Stage;
        import flash.events.*;
-       import net.systemeD.halcyon.styleparser.*;
        import flash.net.*;
-       
+
+    import net.systemeD.halcyon.connection.*;
+    import net.systemeD.halcyon.connection.EntityEvent;
+       import net.systemeD.halcyon.styleparser.*;
+
     public class Map extends Sprite {
 
                public const MASTERSCALE:Number=5825.4222222222;// master map scale - how many Flash pixels in 1 degree longitude
@@ -56,7 +59,7 @@ package net.systemeD.halcyon {
                
                public var backdrop:Object;                                             // reference to backdrop sprite
                
-               public var connection:AMFConnection;                    // server connection
+               public var connection:Connection;                       // server connection
 
                // ------------------------------------------------------------------------------------------
                // Map constructor function
@@ -73,16 +76,15 @@ package net.systemeD.halcyon {
                        s=new Sprite(); addChild(s);                            // 11 - POIs
                        s=new Sprite(); addChild(s);                            // 12 - shields
 
-                       connection=new AMFConnection(
-                               "http://127.0.0.1:3000/api/0.6/amf/read",
-                               "http://127.0.0.1:3000/api/0.6/amf/write",
-                               "http://127.0.0.1:3000/api/crossdomain.xml");
+                       connection= Connection.getConnection();
+            connection.addEventListener(Connection.NEW_WAY, newWayCreated);
+            connection.addEventListener(Connection.NEW_POI, newPOICreated);
                        connection.getEnvironment(new Responder(gotEnvironment,connectionError));
 
         }
 
                public function gotEnvironment(r:Object):void {
-                       init(52.022,-1.2745);
+                       init(51.45889,-0.21476);
                }
 
                // ------------------------------------------------------------------------------------------
@@ -145,8 +147,8 @@ package net.systemeD.halcyon {
                // Resize map size based on current stage and height
 
                public function updateSize():void {
-                       mapwidth =stage.stageWidth; mask.width=mapwidth; backdrop.width=mapwidth;
-                       mapheight=stage.stageHeight; mask.height=mapheight; backdrop.height=mapheight;
+                       mapwidth =stage.stageWidth; backdrop.width=mapwidth; mask.width=mapwidth;
+                       mapheight=stage.stageHeight; backdrop.height=mapheight; mask.height=mapheight;
                }
 
                // ------------------------------------------------------------------------------------------
@@ -159,9 +161,10 @@ package net.systemeD.halcyon {
                        bigedge_l=edge_l; bigedge_r=edge_r;
                        bigedge_b=edge_b; bigedge_t=edge_t;
                        addDebug("Calling with "+edge_l+"-"+edge_r+", "+edge_t+"-"+edge_b);
-                       connection.getBbox(edge_l,edge_r,edge_t,edge_b,new Responder(gotBbox,connectionError));
+                       connection.loadBbox(edge_l,edge_r,edge_t,edge_b);
                }
 
+/*
                public function gotBbox(r:Object):void {
                        addDebug("got whichways");
                        var code:uint         =r.shift(); if (code) { connectionError(); return; }
@@ -186,16 +189,29 @@ package net.systemeD.halcyon {
 
                        addDebug("waylist is "+waylist);
                }
+*/
 
+        private function newWayCreated(event:EntityEvent):void {
+            var way:Way = event.entity as Way;
+            ways[way.id] = new WayUI(way, this);
+        }
+
+        private function newPOICreated(event:EntityEvent):void {
+            var node:Node = event.entity as Node;
+            pois[node.id] = new POI(node, this);
+        }
 
                // ------------------------------------------------------------------------------------------
                // Redraw all items, zoom in and out
                
                public function redraw():void {
-                       addDebug("redrawing");
-                       var s:String='';
-                       for each (var w:Way in ways) { w.redraw(); s+=w.id+","; }
-                       addDebug(s);
+//                     addDebug("redrawing");
+//                     var s:String='';
+                       for each (var w:WayUI in ways) {
+                w.redraw();
+//                s+=w.id+",";
+            }
+//                     addDebug(s);
                        // ** do POIs, etc.
                }
 
diff --git a/net/systemeD/halcyon/Node.as b/net/systemeD/halcyon/Node.as
deleted file mode 100755 (executable)
index 5a6682a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.systemeD.halcyon {
-       public class Node extends Object {
-               public var lon:Number;                  // raw longitude
-               public var latp:Number;                 // projected latitude
-               public var tags:Object;
-               public var tagged:Boolean;
-               public var id:int;
-               public var version:uint;
-               public var clean:Boolean;
-
-               public function Node(id:int,lon:Number,latp:Number,tags:Object,version:uint) {
-                       this.id=id;
-                       this.lon=lon;
-                       this.latp=latp;
-                       this.tags=tags;
-//                     this.tagged=hasTags();
-                       this.version=version;
-                       this.clean=false;               // set to true if just loaded from server
-               }
-       }
-}
index fddb8b46c76505820fbaf4884f281eae9ea6d821..8b215b7d6d35d54b14ce6faa5db1f3d81295267b 100644 (file)
@@ -1,5 +1,7 @@
 package net.systemeD.halcyon {
 
+    import net.systemeD.halcyon.connection.Node;
+
        public class POI extends Object {
 
                import flash.display.*;
@@ -8,12 +10,7 @@ package net.systemeD.halcyon {
                import flash.text.TextFormat;
                import net.systemeD.halcyon.styleparser.*;
 
-               public var id:int;
-               public var tags:Object;
-               public var clean:Boolean=true;                          // altered since last upload?
-               public var uploading:Boolean=false;                     // currently uploading?
-               public var locked:Boolean=false;                        // locked against upload?
-               public var version:uint=0;                                      // version number?
+        private var node:Node;
                public var map:Map;                                                     // reference to parent map
                public var icon:Sprite;                                         // instance in display list
                public var name:Sprite;                                         //  |
@@ -22,20 +19,14 @@ package net.systemeD.halcyon {
                public static var DejaVu:Class;
                public var nameformat:TextFormat;
 
-               public function POI(id:int,version:int,lon:Number,lat:Number,tags:Object,map:Map) {
-                       this.id=id;
-                       this.version=version;
-                       this.map=map;
-                       if (tags==null) { tags=new Object(); }
-                       this.tags=tags;
-map.addDebug("POI "+id);
-                       if (map.nodes[id]) {
-                               // ** already exists - do stuff if it's moved, or in a way
-                       } else {
-                               map.nodes[id]=new Node(id,lon,map.lat2latp(lat),tags,version);
-                       }
+               public function POI(node:Node, map:Map) {
+                       this.map = map;
+                       this.node = node;
+
+map.addDebug("POI "+node.id);
 
                        // place icon on map
+            var tags:Object = node.getTagsCopy();
                        var styles:Array=map.ruleset.getStyle(true,tags,map.scale);
                        var ps:PointStyle=styles[1];
 
@@ -54,8 +45,8 @@ map.addDebug("placing "+ps.icon);
 map.addDebug("loadedIcon");
                        var bitmap:Bitmap = Bitmap(event.target.content);
                        var l:DisplayObject=map.getChildAt(11);
-                       bitmap.x=map.lon2coord(map.nodes[id].lon);
-                       bitmap.y=map.latp2coord(map.nodes[id].latp);
+                       bitmap.x=map.lon2coord(node.lon);
+                       bitmap.y=map.latp2coord(node.latp);
                        Sprite(l).addChild(bitmap);
                }
                
similarity index 70%
rename from net/systemeD/halcyon/Way.as
rename to net/systemeD/halcyon/WayUI.as
index 64672d26065d6388a323026fe2899063b69ac16b..c9dfb937f6a708ff3b7eeee424e9a5cd473d92a9 100755 (executable)
@@ -1,6 +1,5 @@
 package net.systemeD.halcyon {
 
-       import flash.net.*;
        import flash.display.*;
        import flash.geom.Matrix;
        import flash.geom.Point;
@@ -10,18 +9,13 @@ package net.systemeD.halcyon {
        import flash.text.TextField;
        import flash.text.TextFormat;
        import net.systemeD.halcyon.styleparser.*;
+    import net.systemeD.halcyon.connection.*;
 
-       public class Way extends Object {
+       public class WayUI {
+        private var way:Way;
 
-               public var id:int;
-               public var path:Array;
                public var pathlength:Number;                           // length of path
 
-               public var tags:Object;
-               public var clean:Boolean=true;                          // altered since last upload?
-               public var uploading:Boolean=false;                     // currently uploading?
-               public var locked:Boolean=false;                        // locked against upload?
-               public var version:uint=0;                                      // version number?
                public var layer:int=0;                                         // map layer
                public var map:Map;                                                     // reference to parent map
                public var stroke:Sprite;                                       // instance in display list
@@ -37,50 +31,28 @@ package net.systemeD.halcyon {
                public static var DejaVu:Class;
                public var nameformat:TextFormat;
 
-//             public var depth:int=-1;                                        // child id ('depth') of sprite: -1=undrawn
-//             public var historic:Boolean=false;                      // is this an undeleted, not-uploaded way?
-//             public var checkconnections:Boolean=false;      // check shared nodes on reload
-//             public var mergedways:Array;
 
-               public function Way(id:int,version:int,map:Map) {
-                       this.id=id;
-                       this.version=version;
-                       this.map=map;
-               }
-
-               // ------------------------------------------------------------------------------------------
-               // Load from server
-
-               public function load(connection:AMFConnection):void {
-                       connection.getWay(id,new Responder(gotWay,null));
-                       // ** should be connectionError, not null
+               public function WayUI(way:Way, map:Map) {
+                       this.way = way;
+                       this.map = map;
+            init();
                }
                
-               public function gotWay(r:Object):void {
-                       var lx:Number,ly:Number;
-                       var code:uint     =r.shift(); if (code) { map.connectionError(); return; }
-                       var message:String=r.shift();
-                       clean=true;
-                       locked=false;
-                       tags=r[2];
-                       version=r[3];
-//                     this.historic=false;
-//                     removeNodeIndex();
-//                     resetBbox();
-                       path=[];
+               private function init():void {
+                       var lx:Number, ly:Number;
                        pathlength=0;
                        
-                       for each (var p:Array in r[1]) {
-//                             updateBbox(p[0],p[1]);
-                               if (!isNaN(lx)) { pathlength+=Math.sqrt( Math.pow(p[0]-lx,2)+Math.pow(p[1]-ly,2) ) };
-                               lx=p[0]; ly=p[1];
-                               var n:uint=p[2];
-                               // ** what to do if node exists?
-                               map.nodes[n]=new Node(n, p[0], map.lat2latp(p[1]), p[3], p[4]);
-                               map.nodes[n].clean=true;
-                               path.push(map.nodes[n]);
-//                             map.nodes[id].addWay(this.id);
+                       for ( var i:uint = 0; i < way.length; i++ ) {
+                var node:Node = way.getNode(i);
+                var lat:Number = node.lat;
+                var lon:Number = node.lon;
+//                             updateBbox(lon, lat);
+                               if ( !isNaN(lx) ) {
+                    pathlength += Math.sqrt( Math.pow(lon-lx,2)+Math.pow(lat-ly,2) );
+                }
+                               lx=lon; ly=lat;
                        }
+
                        pathlength*=map.scalefactor;
                        redraw();
                        // ** various other stuff
@@ -90,10 +62,12 @@ package net.systemeD.halcyon {
                // Redraw
 
                public function redraw():void {
+            var tags:Object = way.getTagsCopy();
 
                        // ** remove previous version from any layer
                        layer=5;
-                       if (tags['layer']) { layer=Math.min(Math.max(tags['layer']+5,-5),5)+5; }
+                       if ( tags['layer'] )
+                layer=Math.min(Math.max(tags['layer']+5,-5),5)+5;
 
                        // find/create sprites
                        if (stroke) {
@@ -110,7 +84,7 @@ package net.systemeD.halcyon {
                        var f:Graphics=fill.graphics;
 
                        // set style
-                       var styles:Array=map.ruleset.getStyle(false,tags,map.scale);
+                       var styles:Array=map.ruleset.getStyle(false, tags, map.scale);
 
                        // ShapeStyle
                        // ** do line-caps/joints
@@ -133,19 +107,29 @@ package net.systemeD.halcyon {
                        }
 
                        // draw line
-                       if (doFill            ) { f.beginFill(fill_colour,fill_opacity); }
-                       if (doStroke          ) { g.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp)); }
-                       if (doFill || doCasing) { f.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp)); }
+                       if (doFill)
+                f.beginFill(fill_colour,fill_opacity);
+                       if (doStroke)
+                g.moveTo(map.lon2coord(way.getNode(0).lon), map.latp2coord(way.getNode(0).latp));
+                       if (doFill || doCasing)
+                f.moveTo(map.lon2coord(way.getNode(0).lon), map.latp2coord(way.getNode(0).latp));
 
-                       if (doDashed) { dashedLine(g,ss.stroke_dashArray); }
-                       else if (doStroke) { solidLine(g); }
+                       if (doDashed)
+                dashedLine(g,ss.stroke_dashArray);
+                       else if (doStroke)
+                solidLine(g);
                        
-                       if (doDashedCasing) { dashedLine(f,ss.casing_dashArray); f.lineStyle(); }
+                       if (doDashedCasing) {
+                dashedLine(f,ss.casing_dashArray);
+                f.lineStyle();
+            }
                        if (doFill) {
                                f.beginFill(fill_colour,fill_opacity); 
                                solidLine(f);
                                f.endFill(); 
-                       } else if (doCasing && !doDashedCasing) { solidLine(f); }
+                       } else if (doCasing && !doDashedCasing) {
+                solidLine(f);
+            }
 
                        // TextStyle
                        // ** do pull-out
@@ -169,9 +153,11 @@ package net.systemeD.halcyon {
                // Draw solid polyline
                
                private function solidLine(g:Graphics):void {
-                       g.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp));
-                       for (var i:uint=1; i<path.length; i++) {
-                               g.lineTo(map.lon2coord(path[i].lon),map.latp2coord(path[i].latp));
+            var node:Node = way.getNode(0);
+                       g.moveTo(map.lon2coord(node.lon), map.latp2coord(node.latp));
+                       for (var i:uint = 1; i < way.length; i++) {
+                node = way.getNode(i);
+                               g.lineTo(map.lon2coord(node.lon), map.latp2coord(node.latp));
                        }
                }
 
@@ -183,16 +169,23 @@ package net.systemeD.halcyon {
                        var curx:Number, cury:Number;
                        var dx:Number, dy:Number, segleft:Number=0;
                        var i:int=0;
-                       g.moveTo(map.lon2coord(path[0].lon),map.latp2coord(path[0].latp));
-                       while (i<path.length-1 || segleft>0) {
+
+            var node:Node = way.getNode(0);
+            var nextNode:Node = way.getNode(0);
+                       g.moveTo(map.lon2coord(node.lon), map.latp2coord(node.latp));
+                       while (i < way.length-1 || segleft>0) {
                                if (dashleft<=0) {      // should be ==0
                                        if (dc.length==0) { dc=dashes.slice(0); }
                                        dashleft=dc.shift();
                                        draw=!draw;
                                }
                                if (segleft<=0) {       // should be ==0
-                                       curx=map.lon2coord(path[i].lon ); dx=map.lon2coord(path[i+1].lon )-curx;
-                                       cury=map.latp2coord(path[i].latp); dy=map.latp2coord(path[i+1].latp)-cury;
+                    node = way.getNode(i);
+                    nextNode = way.getNode(i+1);
+                                       curx=map.lon2coord(node.lon);
+                    dx=map.lon2coord(nextNode.lon)-curx;
+                                       cury=map.latp2coord(node.latp);
+                    dy=map.latp2coord(nextNode.latp)-cury;
                                        a=Math.atan2(dy,dx); xc=Math.cos(a); yc=Math.sin(a);
                                        segleft=Math.sqrt(dx*dx+dy*dy);
                                        i++;
@@ -227,13 +220,13 @@ package net.systemeD.halcyon {
                        var totallen:Number = t*pathlength;
                        var curlen:Number = 0;
                        var dx:Number, dy:Number, seglen:Number;
-                       for (var i:int=1; i<path.length; i++){
-                               dx=map.lon2coord(path[i].lon )-map.lon2coord(path[i-1].lon );
-                               dy=map.latp2coord(path[i].latp)-map.latp2coord(path[i-1].latp);
+                       for (var i:int = 1; i < way.length; i++){
+                               dx=map.lon2coord(way.getNode(i).lon)-map.lon2coord(way.getNode(i-1).lon);
+                               dy=map.latp2coord(way.getNode(i).latp)-map.latp2coord(way.getNode(i-1).latp);
                                seglen=Math.sqrt(dx*dx+dy*dy);
                                if (totallen > curlen+seglen) { curlen+=seglen; continue; }
-                               return new Array(map.lon2coord(path[i-1].lon )+(totallen-curlen)/seglen*dx,
-                                                                map.latp2coord(path[i-1].latp)+(totallen-curlen)/seglen*dy,
+                               return new Array(map.lon2coord(way.getNode(i-1).lon)+(totallen-curlen)/seglen*dx,
+                                                                map.latp2coord(way.getNode(i-1).latp)+(totallen-curlen)/seglen*dy,
                                                                 Math.atan2(dy,dx));
                        }
                        return new Array(0, 0, 0);
diff --git a/net/systemeD/halcyon/connection/AMFConnection.as b/net/systemeD/halcyon/connection/AMFConnection.as
new file mode 100755 (executable)
index 0000000..7474c41
--- /dev/null
@@ -0,0 +1,127 @@
+package net.systemeD.halcyon.connection {
+
+    import flash.events.Event;
+    import flash.net.URLLoader;
+    import flash.net.URLRequest;
+
+       import flash.system.Security;
+       import flash.net.*;
+
+       public class AMFConnection extends Connection {
+
+               public var readConnection:NetConnection;
+               public var writeConnection:NetConnection;
+               private var mapLoader:URLLoader;
+
+               // ------------------------------------------------------------
+               // Constructor for new AMFConnection
+
+               public function AMFConnection() {
+
+                       if (Connection.policyURL!='')
+                Security.loadPolicyFile(Connection.policyURL);
+
+                       readConnection=new NetConnection();
+                       readConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
+                       readConnection.connect(Connection.apiBaseURL+"amf/read");
+                       
+                       writeConnection=new NetConnection();
+                       writeConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
+                       writeConnection.connect(Connection.apiBaseURL+"amf/write");
+                       
+               }
+
+               override public function getEnvironment(responder:Responder):void {
+                       readConnection.call("getpresets",responder,"en");
+               }
+               
+               override public function loadBbox(left:Number,right:Number,
+                                                               top:Number,bottom:Number):void {
+                       readConnection.call("whichways",new Responder(gotBbox, error),left,bottom,right,top);
+               }
+
+        private function gotBbox(r:Object):void {
+                       var code:uint         =r.shift();
+            if (code) {
+                error(new Array(r.shift()));
+                return;
+            }
+
+                       var message:String    =r.shift();
+                       var waylist:Array     =r[0];
+                       var pointlist:Array   =r[1];
+                       var relationlist:Array=r[2];
+                       var id:Number, version:uint;
+
+                       for each (var w:Array in waylist) {
+                               id=Number(w[0]);
+                version=uint(w[1]);
+
+                var way:Way = getWay(id);
+                if ( way == null ) {
+                    loadWay(id);
+                }
+                       }
+
+                       for each (var p:Array in pointlist) {
+                               id = Number(w[0]);
+                version = uint(w[4]);
+
+                var node:Node = getNode(id);
+                if ( node == null ) {
+                    var lat:Number = Number(w[2]);
+                    var lon:Number = Number(w[1]);
+                    var tags:Object = w[3];
+                    node = new Node(id, version, tags, lat, lon);
+                    setNode(node);
+                }
+                registerPOI(node);
+                       }
+        }
+
+        private function error(r:Object):void {}
+
+               private function loadWay(id:uint):void {
+                       readConnection.call("getway",new Responder(gotWay, error),id);
+               }
+
+               private function gotWay(r:Object):void {
+                       var code:uint = r.shift();
+            if (code) {
+                error(new Array(r.shift()));
+                return;
+            }
+
+                       var message:String=r.shift();
+            var id:Number = Number(r[0]);
+                       var version:uint = uint(r[3]);
+
+            var way:Way = getWay(id);
+            if ( way != null )
+                return;
+
+            var nodesAMF:Array = r[1];
+                       var tags:Object = r[2];
+                       
+            var nodes:Array = [];
+                       for each (var p:Array in nodesAMF) {
+                var nodeID:Number = Number(p[2]);
+                var nodeVersion:uint = uint(p[4]);
+
+                var node:Node = getNode(nodeID);
+                if ( node == null ) {
+                    var lon:Number = Number(p[0]);
+                    var lat:Number = Number(p[1]);
+                    var nodeTags:Object = p[3];
+                    node = new Node(nodeID, nodeVersion, nodeTags, lat, lon);
+                    setNode(node);
+                }
+                nodes.push(node);
+                       }
+
+            way = new Way(id, version, tags, nodes);
+            setWay(way);
+               }
+
+       }
+}
diff --git a/net/systemeD/halcyon/connection/Connection.as b/net/systemeD/halcyon/connection/Connection.as
new file mode 100755 (executable)
index 0000000..37bc8d5
--- /dev/null
@@ -0,0 +1,134 @@
+package net.systemeD.halcyon.connection {
+
+    import flash.net.*;
+
+    import flash.events.EventDispatcher;
+    import flash.events.Event;
+
+       public class Connection extends EventDispatcher {
+
+        private static var CONNECTION_TYPE:String = "AMF";
+        private static var connectionInstance:Connection = null;
+
+        protected static var policyURL:String = "http://127.0.0.1:3000/api/crossdomain.xml";
+        protected static var apiBaseURL:String = "http://127.0.0.1:3000/api/0.6/";
+
+        public static function getConnection():Connection {
+            if ( connectionInstance == null ) {
+                if ( CONNECTION_TYPE == "XML" )
+                    connectionInstance = new XMLConnection();
+                else
+                    connectionInstance = new AMFConnection();
+            }
+            return connectionInstance;
+        }
+
+               public function getEnvironment(responder:Responder):void {}
+
+        // connection events
+        public static var NEW_NODE:String = "new_node";
+        public static var NEW_WAY:String = "new_way";
+        public static var NEW_RELATION:String = "new_relation";
+        public static var NEW_POI:String = "new_poi";
+
+        // store the data we download
+        private var negativeID:Number = -1;
+        private var nodes:Object = {};
+        private var ways:Object = {};
+        private var relations:Object = {};
+        private var pois:Array = [];
+
+        protected function get nextNegative():Number {
+            return negativeID--;
+        }
+
+        protected function setNode(node:Node):void {
+            nodes[node.id] = node;
+            dispatchEvent(new EntityEvent(NEW_NODE, node));
+        }
+
+        protected function setWay(way:Way):void {
+            ways[way.id] = way;
+            dispatchEvent(new EntityEvent(NEW_WAY, way));
+        }
+
+        protected function setRelation(relation:Relation):void {
+            relations[relation.id] = relation;
+            dispatchEvent(new EntityEvent(NEW_RELATION, relation));
+        }
+
+        protected function registerPOI(node:Node):void {
+            if ( pois.indexOf(node) < 0 ) {
+                pois.push(node);
+                dispatchEvent(new EntityEvent(NEW_POI, node));
+            }
+        }
+
+        protected function unregisterPOI(node:Node):void {
+            var index:uint = pois.indexOf(node)
+            if ( index >= 0 ) {
+                pois.splice(index,1);
+            }
+        }
+
+        public function getNode(id:Number):Node {
+            return nodes[id];
+        }
+
+        public function getWay(id:Number):Way {
+            return ways[id];
+        }
+
+        public function getRelation(id:Number):Relation {
+            return relations[id];
+        }
+
+        public function createNode(tags:Object, lat:Number, lon:Number):Node {
+            var node:Node = new Node(nextNegative, 0, tags, lat, lon);
+            setNode(node);
+            return node;
+        }
+
+        public function createWay(tags:Object, nodes:Array):Way {
+            var way:Way = new Way(nextNegative, 0, tags, nodes.concat());
+            setWay(way);
+            return way;
+        }
+
+        public function createRelation(tags:Object, members:Array):Relation {
+            var relation:Relation = new Relation(nextNegative, 0, tags, members.concat());
+            setRelation(relation);
+            return relation;
+        }
+
+        public function getAllNodeIDs():Array {
+            var list:Array = [];
+            for each (var node:Node in nodes)
+                list.push(node.id);
+            return list;
+        }
+
+        public function getAllWayIDs():Array {
+            var list:Array = [];
+            for each (var way:Way in ways)
+                list.push(way.id);
+            return list;
+        }
+
+        public function getAllRelationIDs():Array {
+            var list:Array = [];
+            for each (var relation:Relation in relations)
+                list.push(relation.id);
+            return list;
+        }
+
+        // these are functions that the Connection implementation is expected to
+        // provide. This class has some generic helpers for the implementation.
+               public function loadBbox(left:Number, right:Number,
+                                                               top:Number, bottom:Number):void {
+           }
+    }
+
+}
+
+
diff --git a/net/systemeD/halcyon/connection/Entity.as b/net/systemeD/halcyon/connection/Entity.as
new file mode 100644 (file)
index 0000000..7078ad7
--- /dev/null
@@ -0,0 +1,49 @@
+package net.systemeD.halcyon.connection {
+
+    public class Entity {
+        private var _id:Number;
+        private var _version:uint;
+        private var tags:Object = {};
+
+        public function Entity(id:Number, version:uint, tags:Object) {
+            this._id = id;
+            this._version = version;
+            this.tags = tags;
+        }
+
+        public function get id():Number {
+            return _id;
+        }
+
+        public function get version():uint {
+            return _version;
+        }
+
+        public function hasTags():Boolean {
+            for (var key:String in tags)
+                return true;
+            return false;
+        }
+
+        public function getTag(key:String):String {
+            return tags[key];
+        }
+
+        public function setTag(key:String, value:String):void {
+            tags[key] = value;
+        }
+
+        public function getTagList():TagList {
+            return new TagList(tags);
+        }
+
+        public function getTagsCopy():Object {
+            var copy:Object = {};
+            for (var key:String in tags )
+                copy[key] = tags[key];
+            return copy;
+        }
+
+    }
+
+}
diff --git a/net/systemeD/halcyon/connection/EntityEvent.as b/net/systemeD/halcyon/connection/EntityEvent.as
new file mode 100644 (file)
index 0000000..1484b26
--- /dev/null
@@ -0,0 +1,18 @@
+package net.systemeD.halcyon.connection {
+
+    import flash.events.Event;
+
+    public class EntityEvent extends Event {
+        private var item:Entity;
+
+        public function EntityEvent(type:String, item:Entity) {
+            super(type);
+            this.item = item;
+        }
+
+        public function get entity():Entity {
+            return item;
+        }
+    }
+
+}
diff --git a/net/systemeD/halcyon/connection/Node.as b/net/systemeD/halcyon/connection/Node.as
new file mode 100644 (file)
index 0000000..c78c111
--- /dev/null
@@ -0,0 +1,44 @@
+package net.systemeD.halcyon.connection {
+
+    public class Node extends Entity {
+        private var _lat:Number;
+        private var _latproj:Number;
+        private var _lon:Number;
+
+        public function Node(id:Number, version:uint, tags:Object, lat:Number, lon:Number) {
+            super(id, version, tags);
+            this.lat = lat;
+            this.lon = lon;
+        }
+
+        public function get lat():Number {
+            return _lat;
+        }
+
+        public function get latp():Number {
+            return _latproj;
+        }
+
+        public function get lon():Number {
+            return _lon;
+        }
+
+        public function set lat(lat:Number):void {
+            this._lat = lat;
+            this._latproj = lat2latp(lat);
+        }
+
+        public function set lon(lon:Number):void {
+            this._lon = lon;
+        }
+
+        public function toString():String {
+            return "Node("+id+"@"+version+"): "+lat+","+lon+" "+getTagList();
+        }
+
+        public static function lat2latp(lat:Number):Number {
+            return 180/Math.PI * Math.log(Math.tan(Math.PI/4+lat*(Math.PI/180)/2));
+        }
+    }
+
+}
diff --git a/net/systemeD/halcyon/connection/Relation.as b/net/systemeD/halcyon/connection/Relation.as
new file mode 100644 (file)
index 0000000..58cdc90
--- /dev/null
@@ -0,0 +1,37 @@
+package net.systemeD.halcyon.connection {
+
+    public class Relation extends Entity {
+        private var members:Array;
+
+        public function Relation(id:Number, version:uint, tags:Object, members:Array) {
+            super(id, version, tags);
+            this.members = members;
+        }
+
+        public function get length():uint {
+            return members.length;
+        }
+
+        public function getMember(index:uint):RelationMember {
+            return members[index];
+        }
+
+        public function setMember(index:uint, member:RelationMember):void {
+            members.splice(index, 1, member);
+        }
+
+        public function insertMember(index:uint, member:RelationMember):void {
+            members.splice(index, 0, member);
+        }
+
+        public function appendMember(member:RelationMember):uint {
+            members.push(member);
+            return members.length;
+        }
+
+        public function removeMember(index:uint):void {
+            members.splice(index, 1);
+        }
+    }
+
+}
diff --git a/net/systemeD/halcyon/connection/RelationMember.as b/net/systemeD/halcyon/connection/RelationMember.as
new file mode 100644 (file)
index 0000000..6bf81ae
--- /dev/null
@@ -0,0 +1,21 @@
+package net.systemeD.halcyon.connection {
+
+    public class RelationMember {
+        private var _entity:Entity;
+        private var _role:String;
+
+        public function RelationMember(entity:Entity, role:String) {
+            this._entity = entity;
+            this._role = role;
+        }
+
+        public function get entity():Entity {
+            return _entity;
+        }
+
+        public function get role():String {
+            return _role;
+        }
+    }
+
+}
diff --git a/net/systemeD/halcyon/connection/TagList.as b/net/systemeD/halcyon/connection/TagList.as
new file mode 100644 (file)
index 0000000..65ebad0
--- /dev/null
@@ -0,0 +1,34 @@
+package net.systemeD.halcyon.connection {
+
+    public class TagList {
+        private var keys:Array = [];
+        private var tags:Object;
+
+        public function TagList(tags:Object) {
+            this.tags = tags;
+            for (var key:String in tags) {
+                keys.push(key);
+            }
+        }
+
+        public function get length():uint {
+            return keys.length;
+        }
+
+        public function getTagKey(index:uint):String {
+            return keys[index];
+        }
+
+        public function getTagValue(index:uint):String {
+            return tags[keys[index]];
+        }
+
+        public function toString():String {
+            var str:String = "{";
+            for (var i:uint = 0; i < length; i++)
+                str += "\""+getTagKey(i) + "=" + getTagValue(i) + "\",";
+            return str+"}";
+        }
+    }
+
+}
diff --git a/net/systemeD/halcyon/connection/Way.as b/net/systemeD/halcyon/connection/Way.as
new file mode 100644 (file)
index 0000000..02a3cbf
--- /dev/null
@@ -0,0 +1,38 @@
+package net.systemeD.halcyon.connection {
+
+    public class Way extends Entity {
+        private var nodes:Array;
+
+        public function Way(id:Number, version:uint, tags:Object, nodes:Array) {
+            super(id, version, tags);
+            this.nodes = nodes;
+        }
+
+        public function get length():uint {
+            return nodes.length;
+        }
+        
+        public function getNode(index:uint):Node {
+            return nodes[index];
+        }
+
+        public function insertNode(index:uint, node:Node):void {
+            nodes.splice(index, 0, node);
+        }
+
+        public function appendNode(node:Node):uint {
+            nodes.push(node);
+            return nodes.length;
+        }
+
+        public function removeNode(index:uint):void {
+            nodes.splice(index, 1);
+        }
+
+        public function toString():String {
+            return "Way("+id+"@"+version+"): "+getTagList()+
+                     " "+nodes.map(function(item:Node,index:int, arr:Array):String {return item.id.toString();}).join(",");
+        }
+    }
+
+}
diff --git a/net/systemeD/halcyon/connection/XMLConnection.as b/net/systemeD/halcyon/connection/XMLConnection.as
new file mode 100644 (file)
index 0000000..2d05fb2
--- /dev/null
@@ -0,0 +1,85 @@
+package net.systemeD.halcyon.connection {
+
+    import flash.events.Event;
+    import flash.net.URLLoader;
+    import flash.net.URLRequest;
+
+       import flash.system.Security;
+       import flash.net.*;
+
+
+       public class XMLConnection extends Connection {
+
+        public var readConnection:NetConnection;
+
+               public function XMLConnection() {
+
+                       if (Connection.policyURL!='')
+                Security.loadPolicyFile(Connection.policyURL);
+
+                       readConnection=new NetConnection();
+                       readConnection.objectEncoding = flash.net.ObjectEncoding.AMF0;
+                       readConnection.connect(Connection.apiBaseURL+"amf/read");
+                       
+               }
+
+               override public function getEnvironment(responder:Responder):void {
+                       readConnection.call("getpresets",responder,"en");
+               }
+               
+               override public function loadBbox(left:Number,right:Number,
+                                                               top:Number,bottom:Number):void {
+            var mapVars:URLVariables = new URLVariables();
+            mapVars.bbox= left+","+bottom+","+right+","+top;
+
+            var mapRequest:URLRequest = new URLRequest(Connection.apiBaseURL+"map");
+            mapRequest.data = mapVars;
+
+            var mapLoader:URLLoader = new URLLoader();
+            mapLoader.addEventListener(Event.COMPLETE, loadedMap);
+            mapLoader.load(mapRequest);
+               }
+
+        private function parseTags(tagElements:XMLList):Object {
+            var tags:Object = {};
+            for each (var tagEl:XML in tagElements)
+                tags[tagEl.@k] = tagEl.@v;
+            return tags;
+        }
+
+        private function loadedMap(event:Event):void {
+            var map:XML = new XML(URLLoader(event.target).data);
+            var id:Number;
+            var version:uint;
+            var tags:Object;
+
+            for each(var nodeData:XML in map.node) {
+                id = Number(nodeData.@id);
+                version = uint(nodeData.@version);
+
+                var node:Node = getNode(id);
+                if ( node == null ) {
+                    var lat:Number = Number(nodeData.@lat);
+                    var lon:Number = Number(nodeData.@lon);
+                    tags = parseTags(nodeData.tag);
+                    setNode(new Node(id, version, tags, lat, lon));
+                }
+            }
+
+            for each(var data:XML in map.way) {
+                id = Number(data.@id);
+                version = uint(data.@version);
+
+                var way:Way = getWay(id);
+                if ( way == null ) {
+                    var nodes:Array = [];
+                    for each(var nd:XML in data.nd)
+                        nodes.push(getNode(Number(nd.@ref)));
+                    tags = parseTags(data.tag);
+                    setWay(new Way(id, version, tags, nodes));
+                }
+            }
+        }
+
+       }
+}