change relation.appendMember to use the undo system, and update various places as...
[potlatch2.git] / net / systemeD / halcyon / NodeUI.as
1 package net.systemeD.halcyon {
2
3         import flash.display.*;
4         import flash.events.*;
5         import flash.text.AntiAliasType;
6         import flash.text.GridFitType;
7         import flash.text.TextField;
8         import flash.text.TextFormat;
9         import flash.geom.Matrix;
10         import flash.geom.Point;
11         import net.systemeD.halcyon.styleparser.*;
12     import net.systemeD.halcyon.connection.*;
13         import net.systemeD.halcyon.Globals;
14         
15         public class NodeUI extends EntityUI {
16                 
17                 public var loaded:Boolean=false;
18                 private var iconnames:Object={};                        // name of icon on each sublayer
19                 private var heading:Number=0;                           // heading within way
20                 private var rotation:Number=0;                          // rotation applied to this POI
21                 private static const NO_LAYER:int=-99999;
22
23                 public function NodeUI(node:Node, paint:MapPaint, heading:Number=0, layer:int=NO_LAYER, stateClasses:Object=null) {
24                         super(node,paint);
25                         if (layer==NO_LAYER) { this.layer=paint.maxlayer; } else { this.layer=layer; }
26                         this.heading = heading;
27                         if (stateClasses) {
28                                 for (var state:String in stateClasses) {
29                                         if (stateClasses[state]) { this.stateClasses[state]=stateClasses[state]; }
30                                 }
31                         }
32                         entity.addEventListener(Connection.NODE_MOVED, nodeMoved);
33             entity.addEventListener(Connection.NODE_ALTERED, nodeAltered);
34             attachRelationListeners();
35                         redraw();
36                 }
37                 
38                 public function removeEventListeners():void {
39                         removeGenericEventListeners();
40                         entity.removeEventListener(Connection.NODE_MOVED, nodeMoved);
41             entity.removeEventListener(Connection.NODE_ALTERED, nodeAltered);
42                 }
43
44                 public function nodeMoved(event:Event):void {
45                     updatePosition();
46                 }
47
48         private function nodeAltered(event:Event):void {
49             redraw();
50         }
51
52                 override public function doRedraw():Boolean {
53                         if (!paint.ready) { return false; }
54                         if (entity.deleted) { return false; }
55
56                         var tags:Object = entity.getTagsCopy();
57                         setStateClass('poi', !entity.hasParentWays);
58             setStateClass('hasTags', entity.hasInterestingTags());
59             setStateClass('dupe', Node(entity).isDupe());
60                         tags=applyStateClasses(tags);
61                         if (!styleList || !styleList.isValidAt(paint.map.scale)) {
62                                 styleList=paint.ruleset.getStyles(entity,tags,paint.map.scale); 
63                         }
64
65                         var suggestedLayer:Number=styleList.layerOverride();
66                         if (!isNaN(suggestedLayer)) { layer=suggestedLayer; }
67
68                         var inWay:Boolean=entity.hasParentWays;
69                         var hasStyles:Boolean=styleList.hasStyles();
70                         
71                         removeSprites(); iconnames={};
72                         return renderFromStyle(tags);
73                 }
74
75                 private function renderFromStyle(tags:Object):Boolean {
76                         var r:Boolean=false;                    // ** rendered
77                         var maxwidth:Number=4;                  // biggest width
78                         var w:Number;
79                         var icon:Sprite;
80                         interactive=false;
81                         for each (var sublayer:Number in styleList.sublayers) {
82
83                                 if (styleList.pointStyles[sublayer]) {
84                                         var s:PointStyle=styleList.pointStyles[sublayer];
85                                         interactive||=s.interactive;
86                                         r=true;
87                                         if (s.rotation) { rotation=s.rotation; }
88                                         if (s.icon_image!=iconnames[sublayer]) {
89                                                 if (s.icon_image=='square') {
90                                                         // draw square
91                                                         icon=new Sprite();
92                                                         addToLayer(icon,STROKESPRITE,sublayer);
93                                                         w=styleIcon(icon,sublayer);
94                                                         icon.graphics.drawRect(0,0,w,w);
95                                                         if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
96                                                         iconnames[sublayer]='_square';
97
98                                                 } else if (s.icon_image=='circle') {
99                                                         // draw circle
100                                                         icon=new Sprite();
101                                                         addToLayer(icon,STROKESPRITE,sublayer);
102                                                         w=styleIcon(icon,sublayer);
103                                                         icon.graphics.drawCircle(w,w,w);
104                                                         if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
105                                                         iconnames[sublayer]='_circle';
106
107                                                 } else if (paint.ruleset.images[s.icon_image]) {
108                                                         // 'load' icon (actually just from library)
109                                                         var loader:ExtendedLoader = new ExtendedLoader();
110                                                         loader.info['sublayer']=sublayer;
111                                                         loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadedIcon);
112                                                         loader.loadBytes(paint.ruleset.images[s.icon_image]);
113                                                         iconnames[sublayer]=s.icon_image;
114                                                 }
115                                         }
116                                 }
117
118                                 // name sprite
119                                 var a:String='', t:TextStyle;
120                                 if (styleList.textStyles[sublayer]) {
121                                         t=styleList.textStyles[sublayer];
122                                         interactive||=t.interactive;
123                                         a=tags[t.text];
124                                 }
125
126                                 if (a) { 
127                                         var name:Sprite=new Sprite();
128                                         addToLayer(name,NAMESPRITE);
129                                         t.writeNameLabel(name,a,0,0);
130                     loaded=true;
131                                 }
132                         }
133                         if (!r) { return false; }
134                         if (interactive) { addHitSprite(maxwidth); }
135                         updatePosition();
136                         return true;
137                 }
138
139
140                 private function styleIcon(icon:Sprite, sublayer:Number):Number {
141                         loaded=true;
142
143                         // get colours
144                         if (styleList.shapeStyles[sublayer]) {
145                                 var s:ShapeStyle=styleList.shapeStyles[sublayer];
146                                 if (!isNaN(s.color)) { icon.graphics.beginFill(s.color, s.opacity ? s.opacity : 1);
147                                         }
148                                 if (s.casing_width || !isNaN(s.casing_color)) {
149                                         icon.graphics.lineStyle(s.casing_width ? s.casing_width : 1,
150                                                                                         s.casing_color ? s.casing_color : 0,
151                                                                                         s.casing_opacity ? s.casing_opacity : 1);
152                                 }
153                         }
154
155                         // return width
156                         return styleList.pointStyles[sublayer].icon_width;
157                 }
158
159                 private function addHitSprite(w:uint):void {
160             hitzone = new Sprite();
161             hitzone.graphics.lineStyle(4, 0x000000, 1, false, "normal", CapsStyle.ROUND, JointStyle.ROUND);
162                         hitzone.graphics.beginFill(0);
163                         hitzone.graphics.drawRect(0,0,w,w);
164                         hitzone.visible = false;
165                         setListenSprite();
166                 }
167
168                 private function loadedIcon(event:Event):void {
169                         var icon:Sprite=new Sprite();
170                         var sublayer:Number=event.target.loader.info['sublayer'];
171                         addToLayer(icon,STROKESPRITE,sublayer);
172                         icon.addChild(Bitmap(event.target.content));
173                         addHitSprite(icon.width);
174                         loaded=true;
175                         updatePosition();
176                 }
177
178                 private function updatePosition():void {
179                         if (!loaded) { return; }
180
181                         for (var i:uint=0; i<sprites.length; i++) {
182                                 var d:DisplayObject=sprites[i];
183                                 d.x=0; d.y=0; d.rotation=0;
184
185                                 var m:Matrix=new Matrix();
186                                 m.translate(-d.width/2,-d.height/2);
187                                 m.rotate(rotation);
188                                 m.translate(paint.map.lon2coord(Node(entity).lon),paint.map.latp2coord(Node(entity).latp));
189                                 d.transform.matrix=m;
190                         }
191                 }
192         }
193 }