ASDocs for SelectedWay and ControllerState. Make some keycodes more readable.
[potlatch2.git] / net / systemeD / potlatch2 / EditController.as
1 package net.systemeD.potlatch2 {
2     import net.systemeD.halcyon.Map;
3     import net.systemeD.halcyon.MapController;
4     import net.systemeD.halcyon.MapEvent;
5     import net.systemeD.halcyon.connection.*;
6     import net.systemeD.halcyon.VectorLayer;
7     import net.systemeD.potlatch2.controller.*;
8     import net.systemeD.potlatch2.FunctionKeyManager;
9         import mx.managers.CursorManager;
10     import flash.external.ExternalInterface;
11     import flash.events.*;
12         import flash.geom.*;
13         import flash.ui.Keyboard;
14
15     public class EditController implements MapController {
16
17         private var _map:Map;
18         public var tagViewer:TagViewer;
19                 private var toolbox:Toolbox;
20         
21         public var state:ControllerState;
22         private var _connection:Connection;
23         
24                 private var keys:Object={};
25                 public var clipboards:Object={};
26                 public var cursorsEnabled:Boolean=true;
27         private var maximised:Boolean=false;
28         private var maximiseFunction:String;
29         private var minimiseFunction:String;
30         private var moveFunction:String;
31
32                 [Embed(source="../../../embedded/pen.png")]             public var pen:Class;
33                 [Embed(source="../../../embedded/pen_x.png")]           public var pen_x:Class;
34                 [Embed(source="../../../embedded/pen_o.png")]           public var pen_o:Class;
35                 [Embed(source="../../../embedded/pen_so.png")]          public var pen_so:Class;
36                 [Embed(source="../../../embedded/pen_plus.png")]        public var pen_plus:Class;
37                 
38         public function EditController(map:Map, tagViewer:TagViewer, toolbox:Toolbox) {
39             this._map = map;
40             setState(new NoSelection());
41             this.tagViewer = tagViewer;
42                         this.toolbox = toolbox;
43                         this.toolbox.init(this);
44             this.maximiseFunction = Connection.getParam("maximise_function", null);
45             this.minimiseFunction = Connection.getParam("minimise_function", null);
46             this.moveFunction = Connection.getParam("move_function", null);
47
48             map.parent.addEventListener(MouseEvent.MOUSE_MOVE, mapMouseEvent);
49             map.parent.addEventListener(MouseEvent.MOUSE_UP, mapMouseEvent);
50             map.parent.addEventListener(MouseEvent.MOUSE_DOWN, mapMouseEvent);
51             map.parent.addEventListener(MouseEvent.MOUSE_WHEEL, mapMouseEvent);
52             map.parent.addEventListener(MouseEvent.CLICK, mapMouseEvent);
53             map.parent.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
54             map.parent.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
55
56             if (this.moveFunction) {
57                 map.addEventListener(MapEvent.MOVE, moveHandler);
58             }
59         }
60
61         public function setActive():void {
62             map.setController(this);
63             _connection = map.connection;
64         }
65
66         public function get map():Map {
67             return _map;
68         }
69         
70         public function get connection():Connection {
71             return _connection;
72         }
73
74         /**
75         * Updates the various user interfaces that change when the selection changes.
76         * Currently this is the TagViewer and the Toolbox
77         *
78         * @param layer Optionally pass the layer of the currently selected entity, eg for BugLayers
79         */
80                 public function updateSelectionUI(layer:VectorLayer = null):void {
81                         tagViewer.setEntity(state.selection, layer);
82                         toolbox.updateSelectionUI();
83                 }
84         
85         private function keyDownHandler(event:KeyboardEvent):void {
86                         keys[event.keyCode]=true;
87                 }
88
89         private function keyUpHandler(event:KeyboardEvent):void {
90             trace("key code "+event.keyCode);
91                         if (keys[event.keyCode]) { delete keys[event.keyCode]; }
92                         if (FunctionKeyManager.instance().handleKeypress(event.keyCode)) { return; }
93             
94             if (event.keyCode == 77) { toggleSize(); } // 'M'
95             var newState:ControllerState = state.processKeyboardEvent(event);
96             setState(newState);            
97                 }
98
99                 public function keyDown(key:Number):Boolean {
100                         return Boolean(keys[key]);
101                 }
102
103         private function mapMouseEvent(event:MouseEvent):void {
104             if (isInteractionEvent(event)) map.stage.focus = map.parent;
105             if (event.type==MouseEvent.MOUSE_UP && map.dragstate==map.DRAGGING) { return; }
106             
107             var mapLoc:Point = map.globalToLocal(new Point(event.stageX, event.stageY));
108             event.localX = mapLoc.x;
109             event.localY = mapLoc.y;
110
111             var newState:ControllerState = state.processMouseEvent(event, null);
112             setState(newState);
113         }
114         
115         public function entityMouseEvent(event:MouseEvent, entity:Entity):void {
116             if (isInteractionEvent(event)) map.stage.focus = map.parent;
117             event.stopPropagation();
118                 
119             var mapLoc:Point = map.globalToLocal(new Point(event.stageX, event.stageY));
120             event.localX = mapLoc.x;
121             event.localY = mapLoc.y;
122
123             var newState:ControllerState = state.processMouseEvent(event, entity);
124             setState(newState);
125         }
126
127                 private function isInteractionEvent(event:MouseEvent):Boolean {
128                         switch (event.type) {
129                                 case MouseEvent.ROLL_OUT:       return false;
130                                 case MouseEvent.ROLL_OVER:      return false;
131                                 case MouseEvent.MOUSE_OUT:      return false;
132                                 case MouseEvent.MOUSE_OVER:     return false;
133                                 case MouseEvent.MOUSE_MOVE:     return false;
134                 }
135                         return true;
136                 }
137
138         public function setState(newState:ControllerState):void {
139             if ( newState == state )
140                 return;
141                 
142             if ( state != null )
143                 state.exitState(newState);
144             newState.setController(this);
145             newState.setPreviousState(state);
146             state = newState;
147             state.enterState();
148         }
149
150                 public function findStateForSelection(sel:Array):ControllerState {
151                         if (sel.length==0) { return new NoSelection(); }
152                         else if (sel.length>1) { return new SelectedMultiple(sel); }
153                         else if (sel[0] is Way) { return new SelectedWay(sel[0]); }
154                         else if (sel[0] is Node && Node(sel[0]).hasParentWays) {
155                                 var way:Way=sel[0].parentWays[0] as Way;
156                                 return new SelectedWayNode(way, way.indexOfNode(sel[0] as Node));
157                         } else {
158                                 return new SelectedPOINode(sel[0] as Node);
159                         }
160                 }
161
162                 public function setCursor(cursor:Class):void {
163                         CursorManager.removeAllCursors();
164                         if (cursor && cursorsEnabled) { CursorManager.setCursor(cursor,2,-4,0); }
165                 }
166
167         private function toggleSize():void {
168             if (maximised) {
169                 if (minimiseFunction) {
170                     ExternalInterface.call(minimiseFunction);
171                 }
172
173                 maximised = false;
174             } else {
175                 if (maximiseFunction) {
176                     ExternalInterface.call(maximiseFunction);
177                 }
178
179                 maximised = true;
180             }
181         }
182
183                 private function moveHandler(event:MapEvent):void {
184                         ExternalInterface.call(this.moveFunction,
185                                    event.params.lon, event.params.lat, event.params.scale,
186                                    event.params.minlon, event.params.minlat,
187                                    event.params.maxlon, event.params.maxlat);
188                 }
189
190     }
191     
192 }