add 'interactive:no' property, improve clicking behaviour
[potlatch2.git] / net / systemeD / halcyon / EntityUI.as
1 package net.systemeD.halcyon {
2
3         import flash.display.*;
4         import flash.events.MouseEvent;
5         import flash.text.AntiAliasType;
6         import flash.text.GridFitType;
7         import net.systemeD.halcyon.Globals;
8         import net.systemeD.halcyon.styleparser.StyleList;
9         import net.systemeD.halcyon.styleparser.RuleSet;
10     import net.systemeD.halcyon.connection.*;
11
12         public class EntityUI {
13
14                 protected var entity:Entity;
15                 protected var sprites:Array=new Array();                // instances in display list
16         protected var listenSprite:Sprite=new Sprite(); // clickable sprite to receive events
17                 protected var stateClasses:Object=new Object(); // special context-sensitive classes, e.g. :hover
18                 protected var layer:int=0;                                              // map layer
19                 protected var suspended:Boolean=false;                  // suspend redrawing?
20                 protected var redrawDue:Boolean=false;                  // redraw called while suspended?
21                 protected var redrawStyleList:StyleList;                // stylelist to be used when redrawing?
22                 public var paint:MapPaint;                                              // reference to parent MapPaint
23                 public var ruleset:RuleSet;                                             // reference to ruleset in operation
24                 public var interactive:Boolean=true;                    // does object respond to clicks?
25
26                 protected const FILLSPRITE:uint=0;
27                 protected const CASINGSPRITE:uint=1;
28                 protected const STROKESPRITE:uint=2;
29                 protected const NAMESPRITE:uint=3;
30                 protected const WAYCLICKSPRITE:uint=4;
31                 protected const NODECLICKSPRITE:uint=5;
32
33                 public static const DEFAULT_TEXTFIELD_PARAMS:Object = {
34                         embedFonts: true,
35                         antiAliasType: AntiAliasType.ADVANCED,
36                         gridFitType: GridFitType.NONE
37                 };
38
39                 public function EntityUI(entity:Entity, paint:MapPaint) {
40                         this.entity=entity;
41                         this.paint=paint;
42             entity.addEventListener(Connection.TAG_CHANGED, tagChanged);
43                         entity.addEventListener(Connection.ADDED_TO_RELATION, relationAdded);
44                         entity.addEventListener(Connection.REMOVED_FROM_RELATION, relationRemoved);
45                         entity.addEventListener(Connection.SUSPEND_REDRAW, suspendRedraw);
46                         entity.addEventListener(Connection.RESUME_REDRAW, resumeRedraw);
47                         listenSprite.addEventListener(MouseEvent.CLICK, mouseEvent);
48                         listenSprite.addEventListener(MouseEvent.DOUBLE_CLICK, mouseEvent);
49                         listenSprite.addEventListener(MouseEvent.ROLL_OVER, mouseEvent);
50                         listenSprite.addEventListener(MouseEvent.MOUSE_OUT, mouseEvent);
51                         listenSprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseEvent);
52                         listenSprite.addEventListener(MouseEvent.MOUSE_UP, mouseEvent);
53                         listenSprite.addEventListener(MouseEvent.MOUSE_MOVE, mouseEvent);
54                 }
55
56
57                 // -----------------------------------------------------------------
58                 // Event listeners
59                 
60                 protected function attachRelationListeners():void {
61                     var relations:Array = entity.parentRelations;
62             for each(var relation:Relation in relations ) {
63                 relation.addEventListener(Connection.TAG_CHANGED, relationTagChanged);
64             }
65                 }
66
67                 protected function relationAdded(event:RelationMemberEvent):void {
68                     event.relation.addEventListener(Connection.TAG_CHANGED, relationTagChanged);
69                     redraw();
70                 }
71                 
72                 protected function relationRemoved(event:RelationMemberEvent):void {
73                     event.relation.removeEventListener(Connection.TAG_CHANGED, relationTagChanged);
74                     redraw();
75                 }
76                 
77         protected function tagChanged(event:TagEvent):void {
78             redraw();
79         }
80
81         protected function relationTagChanged(event:TagEvent):void {
82             redraw();
83         }
84                 
85         protected function mouseEvent(event:MouseEvent):void {
86                         paint.map.entityMouseEvent(event, entity);
87         }
88
89
90                 // -----------------------------------------------------------------
91
92                 // Add object (stroke/fill/roadname) to layer sprite
93                 
94                 protected function addToLayer(s:DisplayObject,t:uint,sublayer:int=-1):void {
95                         var l:DisplayObject, o:Sprite;
96                         if (sublayer!=-1) {
97                                 o=paint.sublayer(layer,sublayer);
98                         } else {
99                                 l=paint.getChildAt(layer-paint.minlayer);
100                                 o=(l as Sprite).getChildAt(t) as Sprite;
101                         }
102                         o.addChild(s);
103                         sprites.push(s);
104             if ( s is Sprite ) {
105                 Sprite(s).mouseChildren = false;
106                 Sprite(s).mouseEnabled = false;
107             }
108                 }
109
110
111                 public function removeSprites():void {
112                         while (sprites.length>0) {
113                                 var d:DisplayObject=sprites.pop();
114                                 if (d.parent) { d.parent.removeChild(d); }
115                         }
116                         listenSprite.hitArea=null;
117                 }
118
119                 protected function offsetSprites(x:Number, y:Number):void {
120                         for each (var d:DisplayObject in sprites) {
121                                 d.x=x; d.y=y;
122                         }
123                 }
124
125                 protected function setListenSprite(spriteContainer:uint, hitzone:Sprite):void {
126                         if (hitzone) {
127                                 if (!listenSprite.parent) { addToLayer(listenSprite, spriteContainer); }
128                     listenSprite.hitArea = hitzone;
129                     listenSprite.buttonMode = true;
130                     listenSprite.mouseChildren = true;
131                     listenSprite.mouseEnabled = true;
132                         } else {
133                                 if (listenSprite.parent) { listenSprite.parent.removeChild(listenSprite); }
134                         }
135                 }
136
137         public function setHighlight(stateType:String, isOn:*):void {
138             if ( isOn && stateClasses[stateType] == null ) {
139                 stateClasses[stateType] = isOn;
140             } else if ( !isOn && stateClasses[stateType] != null ) {
141                 delete stateClasses[stateType];
142             }
143         }
144
145                 protected function applyStateClasses(tags:Object):Object {
146             for (var stateKey:String in stateClasses) {
147                 tags[":"+stateKey] = 'yes';
148             }
149                         return tags;
150                 }
151                 
152                 public function toString():String {
153                         return "[EntityUI "+entity+"]";
154                 }
155
156                 // Redraw control
157                 
158                 public function redraw(sl:StyleList=null):Boolean {
159                         if (suspended) { redrawStyleList=sl; redrawDue=true; return false; }
160                         return doRedraw(sl);
161                 }
162                 
163                 public function doRedraw(sl:StyleList):Boolean {
164                         // to be overwritten
165                         return false;
166                 }
167                 
168                 public function suspendRedraw(event:EntityEvent):void {
169                         suspended=true;
170                         redrawDue=false;
171                 }
172                 
173                 public function resumeRedraw(event:EntityEvent):void {
174                         suspended=false;
175                         if (redrawDue) { 
176                                 doRedraw(redrawStyleList);
177                                 redrawDue=false;
178                                 redrawStyleList=null; 
179                         }
180                 }
181
182         }
183
184 }