1 package net.systemeD.halcyon {
3 import flash.display.Sprite;
4 import flash.display.DisplayObject;
5 import net.systemeD.halcyon.NodeUI;
6 import net.systemeD.halcyon.WayUI;
7 import net.systemeD.halcyon.connection.*;
8 import net.systemeD.halcyon.styleparser.RuleSet;
9 import net.systemeD.halcyon.Globals;
11 public class MapPaint extends Sprite {
14 public var minlayer:int;
15 public var maxlayer:int;
16 public var ruleset:RuleSet; // rules
17 public var wayuis:Object=new Object(); // sprites for ways and (POI/tagged) nodes
18 public var nodeuis:Object=new Object(); // |
19 public var isBackground:Boolean = true; // is it a background layer or the core paint object?
20 public var sublayerIndex:Object={}; // hash of index->position
22 private const VERYBIG:Number=Math.pow(2,16);
23 private static const NO_LAYER:int=-99999; // same as NodeUI
27 public function MapPaint(map:Map,minlayer:int,maxlayer:int) {
31 this.minlayer=minlayer;
32 this.maxlayer=maxlayer;
37 for (l=minlayer; l<=maxlayer; l++) { // each layer (10 is +5, 0 is -5)
38 s = getPaintSprite(); // |
39 s.addChild(getPaintSprite()); // | 0 fill
40 s.addChild(getPaintSprite()); // | 1 casing
41 var t:Sprite = getPaintSprite(); // | 2 stroke
42 t.addChild(getPaintSprite()); // | | sublayer
44 s.addChild(getPaintSprite()); // | 3 names
49 for (l=minlayer; l<=maxlayer; l++) { // each layer (21 is +5, 11 is -5)
50 s = getHitSprite(); // |
51 s.addChild(getHitSprite()); // | 0 way hit tests
52 s.addChild(getHitSprite()); // | 1 node hit tests
57 public function getPaintSpriteAt(l:int):Sprite {
58 return getChildAt(l-minlayer) as Sprite;
61 public function getHitSpriteAt(l:int):Sprite {
62 return getChildAt((l-minlayer) + (maxlayer-minlayer+1)) as Sprite;
65 public function get ready():Boolean {
66 if (!ruleset) { return false; }
67 if (!ruleset.loaded) { return false; }
71 public function sublayer(layer:int,sublayer:Number):Sprite {
74 var index:String, ix:Number;
75 if (!sublayerIndex.hasOwnProperty(sublayer)) {
76 // work out which position to add at
77 var lowestAbove:Number=VERYBIG;
78 var lowestAbovePos:int=-1;
79 var indexLength:uint=0;
80 for (index in sublayerIndex) {
82 if (ix>sublayer && ix<lowestAbove) {
84 lowestAbovePos=sublayerIndex[index];
88 if (lowestAbovePos==-1) { lowestAbovePos=indexLength; }
91 for (var i:int=minlayer; i<=maxlayer; i++) {
92 l=getChildAt(i-minlayer);
93 o=(l as Sprite).getChildAt(2);
94 (o as Sprite).addChildAt(getPaintSprite(),lowestAbovePos);
98 // (we do it in this rather indirect way because if you alter sublayerIndex directly
99 // within the loop, it confuses the iterator)
100 var toUpdate:Array=[];
101 for (index in sublayerIndex) {
103 if (ix>sublayer) { toUpdate.push(index); }
105 for each (index in toUpdate) { sublayerIndex[index]++; }
106 sublayerIndex[sublayer]=lowestAbovePos;
109 l=getChildAt(layer-minlayer);
110 o=(l as Sprite).getChildAt(2);
111 return ((o as Sprite).getChildAt(sublayerIndex[sublayer]) as Sprite);
114 public function updateEntityUIs(o:Object, redraw:Boolean, remove:Boolean):void {
115 var way:Way, poi:Node;
117 for each (way in o.waysInside) {
118 if (!wayuis[way.id]) { createWayUI(way); }
119 else if (redraw) { wayuis[way.id].recalculate(); wayuis[way.id].redraw(); }
123 for each (way in o.waysOutside) {
124 if (wayuis[way.id] && !wayuis[way.id].purgable) {
125 if (redraw) { wayuis[way.id].recalculate(); wayuis[way.id].redraw(); }
132 for each (poi in o.poisInside) {
133 if (!nodeuis[poi.id]) { createNodeUI(poi); }
134 else if (redraw) { nodeuis[poi.id].redraw(); }
138 for each (poi in o.poisOutside) {
139 if (nodeuis[poi.id] && !nodeuis[poi.id].purgable) {
140 if (redraw) { nodeuis[poi.id].redraw(); }
148 public function createWayUI(way:Way):WayUI {
149 if (!wayuis[way.id]) {
150 wayuis[way.id]=new WayUI(way,this);
151 way.addEventListener(Connection.WAY_DELETED, wayDeleted);
153 return wayuis[way.id];
156 public function wayDeleted(event:EntityEvent):void {
157 deleteWayUI(event.entity as Way);
160 public function deleteWayUI(way:Way):void {
161 way.removeEventListener(Connection.WAY_DELETED, wayDeleted);
162 if (wayuis[way.id]) {
163 wayuis[way.id].redrawMultis();
164 wayuis[way.id].removeSprites();
165 wayuis[way.id].removeEventListeners();
166 delete wayuis[way.id];
168 for (var i:uint=0; i<way.length; i++) {
169 var node:Node=way.getNode(i);
170 if (nodeuis[node.id]) { deleteNodeUI(node); }
174 public function createNodeUI(node:Node,rotation:Number=0,layer:int=NO_LAYER,stateClasses:Object=null):NodeUI {
175 if (!nodeuis[node.id]) {
176 nodeuis[node.id]=new NodeUI(node,this,rotation,layer,stateClasses);
177 node.addEventListener(Connection.NODE_DELETED, nodeDeleted);
179 for (var state:String in stateClasses) {
180 nodeuis[node.id].setStateClass(state,stateClasses[state]);
182 nodeuis[node.id].redraw();
184 return nodeuis[node.id];
187 public function nodeDeleted(event:EntityEvent):void {
188 deleteNodeUI(event.entity as Node);
191 public function deleteNodeUI(node:Node):void {
192 if (!nodeuis[node.id]) { return; }
193 node.removeEventListener(Connection.NODE_DELETED, nodeDeleted);
194 nodeuis[node.id].removeSprites();
195 nodeuis[node.id].removeEventListeners();
196 delete nodeuis[node.id];
199 public function renumberWayUI(way:Way,oldID:Number):void {
200 if (!wayuis[oldID]) { return; }
201 wayuis[way.id]=wayuis[oldID];
202 delete wayuis[oldID];
205 public function renumberNodeUI(node:Node,oldID:Number):void {
206 if (!nodeuis[oldID]) { return; }
207 nodeuis[node.id]=nodeuis[oldID];
208 delete nodeuis[oldID];
211 private function getPaintSprite():Sprite {
212 var s:Sprite = new Sprite();
213 s.mouseEnabled = false;
214 s.mouseChildren = false;
218 private function getHitSprite():Sprite {
219 var s:Sprite = new Sprite();
223 public function redraw():void {
224 for each (var w:WayUI in wayuis) { w.recalculate(); w.invalidateStyleList(); w.redraw(); }
225 /* sometimes (e.g. in Map.setStyle) Mappaint.redrawPOIs() is called immediately afterwards anyway. FIXME? */
226 for each (var p:NodeUI in nodeuis) { p.invalidateStyleList(); p.redraw(); }
229 public function redrawPOIs():void {
230 for each (var p:NodeUI in nodeuis) { p.invalidateStyleList(); p.redraw(); }
233 public function findSource():VectorLayer {
235 for each (v in map.vectorlayers) {
236 if (v.paint==this) { return v; }