Refactor the comments
[potlatch2.git] / net / systemeD / halcyon / connection / Trace.as
1 package net.systemeD.halcyon.connection {
2
3     import flash.events.EventDispatcher;
4     import flash.utils.Dictionary;
5     import flash.events.*;
6     import flash.net.URLLoader;
7
8     import net.systemeD.halcyon.connection.*;
9     import net.systemeD.halcyon.Map;
10     import net.systemeD.halcyon.Globals;
11     import net.systemeD.halcyon.MapPaint;
12
13     /**
14     * Implements trace objects loaded from the OSM API.
15     * See also potlatch2's utils GpxImporter.as and Importer.as classes, which can handle
16     * loading GPX files (and other formats) from arbitrary urls.
17     */
18     public class Trace extends EventDispatcher {
19         private var _id:Number;
20         private var _description:String;
21         private var tags:Array = []; // N.B. trace tags are NOT k/v pairs
22         private var _isLoaded:Boolean;
23         private var _filename:String;
24         private var _traceData:String;
25         private var map:Map;
26         private var _layer:MapPaint;
27         private var masterConnection:XMLConnection; // The authenticated connection
28         private var _connection:Connection; // The one we store our fake nodes/ways in.
29         private var simplify:Boolean = false;
30
31         private static const STYLESHEET:String="stylesheets/gpx.css";
32
33         /** Create a new trace.
34         * @param masterConnection The authenticated connection to communicate with the server
35         */
36         public function Trace(masterConnection:XMLConnection) {
37             this.masterConnection = masterConnection;
38             map = Globals.vars.root; // REFACTOR this prevents traces being added to arbitrary maps
39         }
40
41         /** Create a new trace, from the XML description given by the user/traces call.
42         * This only creates the object itself, the actual trace contents (trkseg etc) are
43         * lazily downloaded later. */
44         public function fromXML(xml:XML):Trace {
45             _id = Number(xml.@id);
46             _filename = xml.@name;
47             _description = xml.description;
48             for each(var tag:XML in xml.tag) {
49               tags.push(String(tag));
50             }
51             return this;
52         }
53
54         public function get id():Number {
55             return _id;
56         }
57
58         public function get description():String {
59             return _description;
60         }
61
62         public function get filename():String {
63             return _filename;
64         }
65
66         public function get tagsText():String {
67             return tags.join(", ");
68         }
69
70         private function fetchFromServer():void {
71             // todo - needs proper error handling
72             masterConnection.fetchTrace(id, saveTraceData);
73             dispatchEvent(new Event("loading_data"));
74         }
75
76         private function saveTraceData(event:Event):void {
77             _traceData = String(URLLoader(event.target).data);
78             dispatchEvent(new Event("loaded_data"));
79         }
80
81         private function get connection():Connection {
82             if (!_connection) {
83                 // create a new connection so that the ids don't impact the main layer.
84                 _connection = new Connection(filename, null, null, null);
85             }
86             return _connection
87         }
88
89         private function get layer():MapPaint {
90             if (!_layer) {
91                 // create a new layer for every trace, so they can be turned on/off individually
92                 _layer = map.addLayer(connection, STYLESHEET);
93             }
94             return _layer;
95         }
96
97         public function addToMap():void {
98             // this allows adding and removing traces from the map, without re-downloading
99             // the data from the server repeatedly.
100             if (!_isLoaded) {
101               addEventListener("loaded_data", processEvent);
102               fetchFromServer();
103               return;
104             } else {
105               process();
106             }
107         }
108
109         public function removeFromMap():void {
110             //todo
111         }
112
113         private function processEvent(e:Event):void {
114             removeEventListener("loaded_data", processEvent);
115             process();
116         }
117
118         private function process():void {
119             var file:XML = new XML(_traceData);
120             var action:CompositeUndoableAction = new CompositeUndoableAction("add trace objects");
121                         for each (var ns:Namespace in file.namespaceDeclarations()) {
122                                 if (ns.uri.match(/^http:\/\/www\.topografix\.com\/GPX\/1\/[01]$/)) {
123                                         default xml namespace = ns;
124                                 }
125                         }
126
127             for each (var trkseg:XML in file..trkseg) {
128                 var way:Way;
129                 var nodestring:Array = [];
130                 for each (var trkpt:XML in trkseg.trkpt) {
131                     nodestring.push(connection.createNode({}, trkpt.@lat, trkpt.@lon, action.push));
132                 }
133                 if (nodestring.length > 0) {
134                     way = connection.createWay({}, nodestring, action.push);
135                     //if (simplify) { Simplify.simplify(way, paint.map, false); }
136                 }
137             }
138
139             for each (var wpt:XML in file.wpt) {
140                 var tags:Object = {};
141                 for each (var tag:XML in wpt.children()) {
142                     tags[tag.name().localName]=tag.toString();
143                 }
144                 var node:Node = connection.createNode(tags, wpt.@lat, wpt.@lon, action.push);
145                                 connection.registerPOI(node);
146             }
147
148             action.doAction(); /* just do it, don't add to undo stack */
149                         default xml namespace = new Namespace("");
150             layer.updateEntityUIs(true, false);
151         }
152     }
153 }