]> git.openstreetmap.org Git - potlatch2.git/blob - net/systemeD/potlatch2/controller/DrawWay.as
improve GPS track support
[potlatch2.git] / net / systemeD / potlatch2 / controller / DrawWay.as
1 package net.systemeD.potlatch2.controller {
2         import flash.events.*;
3         import flash.geom.*;
4         import flash.display.DisplayObject;
5         import flash.ui.Keyboard;
6         import net.systemeD.potlatch2.EditController;
7         import net.systemeD.halcyon.connection.*;
8         import net.systemeD.halcyon.Elastic;
9         import net.systemeD.halcyon.Globals;
10         import net.systemeD.halcyon.MapPaint;
11
12         public class DrawWay extends SelectedWay {
13                 private var elastic:Elastic;
14                 private var editEnd:Boolean;
15                 private var leaveNodeSelected:Boolean;
16                 private var lastClick:Entity=null;
17                 private var lastClickTime:Date;
18                 private var hoverEntity:Entity;                 // keep track of the currently rolled-over object, because
19                                                                                                 // Flash can fire a mouseDown from the map even if you
20                                                                                                 // haven't rolled out of the way
21                 
22                 public function DrawWay(way:Way, editEnd:Boolean, leaveNodeSelected:Boolean) {
23                         super(way);
24                         this.editEnd = editEnd;
25                         this.leaveNodeSelected = leaveNodeSelected;
26                         if (way.length==1 && way.getNode(0).parentWays.length==1) {
27                                 // drawing new way, so keep track of click in case creating a POI
28                                 lastClick=way.getNode(0);
29                                 lastClickTime=new Date();
30                         }
31                 }
32                 
33                 override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
34                         var mouse:Point;
35                         var node:Node;
36                         var paint:MapPaint = getMapPaint(DisplayObject(event.target));
37                         var isBackground:Boolean = paint && paint.isBackground;
38
39                         if (entity == null && hoverEntity) { entity=hoverEntity; }
40                         var focus:Entity = getTopLevelFocusEntity(entity);
41
42                         if ( event.type == MouseEvent.MOUSE_UP ) {
43                                 if ( entity == null || isBackground ) {
44                                         node = createAndAddNode(event);
45                                         resetElastic(node);
46                                         lastClick=node;
47                                 } else if ( entity is Node ) {
48                                         if (entity==lastClick && (new Date().getTime()-lastClickTime.getTime())<1000) {
49                                                 if (selectedWay.length==1 && selectedWay.getNode(0).parentWays.length==1) {
50                                                         // double-click to create new POI
51                                                         node=selectedWay.getNode(0);
52                                                         stopDrawing();
53                                                         node.setDeletedState(false);    // has just been deleted by stopDrawing
54                                                         controller.connection.registerPOI(node);
55                                                         return new SelectedPOINode(node);
56                                                 } else {
57                                                         // double-click at end of way
58                                                         return stopDrawing();
59                                                 }
60                                         } else {
61                                                 appendNode(entity as Node, MainUndoStack.getGlobalStack().addAction);
62                                                 controller.map.setHighlightOnNodes(focus as Way, { hoverway: false });
63                                                 controller.map.setHighlight(entity, { selectedway: true });
64                                                 resetElastic(entity as Node);
65                                                 lastClick=entity;
66                                                 if (selectedWay.getNode(0)==selectedWay.getNode(selectedWay.length-1)) {
67                                                         return new SelectedWay(selectedWay);
68                                                 }
69                                         }
70                                 } else if ( entity is Way ) {
71                                         if (entity as Way==selectedWay) {
72                                                 // add junction node - self-intersecting way
73                                     var lat:Number = controller.map.coord2lat(event.localY);
74                                     var lon:Number = controller.map.coord2lon(event.localX);
75                                     var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node");
76                                     node = controller.connection.createNode({}, lat, lon, undo.push);
77                                     selectedWay.insertNodeAtClosestPosition(node, true, undo.push);
78                                                 appendNode(node,undo.push);
79                                     MainUndoStack.getGlobalStack().addAction(undo);
80                                         } else {
81                                                 // add junction node - another way
82                                                 node = createAndAddNode(event);
83                                                 Way(entity).insertNodeAtClosestPosition(node, true,
84                                                     MainUndoStack.getGlobalStack().addAction);
85                                         }
86                                         resetElastic(node);
87                                         lastClick=node;
88                                         controller.map.setHighlightOnNodes(entity as Way, { hoverway: false });
89                                         controller.map.setHighlightOnNodes(selectedWay, { selectedway: true });
90                                 }
91                                 lastClickTime=new Date();
92                         } else if ( event.type == MouseEvent.MOUSE_MOVE ) {
93                                 mouse = new Point(
94                                                   controller.map.coord2lon(event.localX),
95                                                   controller.map.coord2latp(event.localY));
96                                 elastic.end = mouse;
97                         } else if ( event.type == MouseEvent.ROLL_OVER && !isBackground ) {
98                                 if (focus!=selectedWay) {
99                                         hoverEntity=focus;
100                                         controller.map.setHighlightOnNodes(focus as Way, { hoverway: true });
101                                 }
102                                 if (entity is Node && focus is Way && Way(focus).endsWith(Node(entity))) {
103                                         if (focus==selectedWay) { controller.setCursor(controller.pen_so); }
104                                                            else { controller.setCursor(controller.pen_o); }
105                                 } else if (entity is Node) {
106                                         controller.setCursor(controller.pen_x);
107                                 } else {
108                                         controller.setCursor(controller.pen_plus);
109                                 }
110                         } else if ( event.type == MouseEvent.MOUSE_OUT && !isBackground ) {
111                                 if (entity!=selectedWay) {
112                                         hoverEntity=null;
113                                         controller.map.setHighlightOnNodes(focus as Way, { hoverway: false });
114                                         // ** We could do with an optional way of calling WayUI.redraw to only do the nodes, which would be a
115                                         // useful optimisation.
116                                 }
117                                 controller.setCursor(controller.pen);
118                         }
119
120                         return this;
121                 }
122                 
123                 protected function resetElastic(node:Node):void {
124                         var mouse:Point = new Point(node.lon, node.latp);
125                         elastic.start = mouse;
126                         elastic.end = mouse;
127                 }
128
129                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
130                         switch (event.keyCode) {
131                                 case 13:                                        return stopDrawing();
132                                 case 27:                                        return stopDrawing();
133                                 case Keyboard.DELETE:           return backspaceNode(MainUndoStack.getGlobalStack().addAction);
134                                 case Keyboard.BACKSPACE:        return backspaceNode(MainUndoStack.getGlobalStack().addAction);
135                                 case 82:                                        repeatTags(selectedWay); return this;
136                         }
137                         var cs:ControllerState = sharedKeyboardEvents(event);
138                         return cs ? cs : this;
139                 }
140                 
141                 protected function stopDrawing():ControllerState {
142                         if ( hoverEntity ) {
143                                 controller.map.setHighlightOnNodes(hoverEntity as Way, { hoverway: false });
144                                 hoverEntity = null;
145                         }
146
147                         if ( selectedWay.length<2) {
148                                 controller.map.setHighlightOnNodes(selectedWay, { selectedway: false });
149                                 selectedWay.remove(MainUndoStack.getGlobalStack().addAction);
150                                 // delete controller.map.ways[selectedWay.id];
151                                 return new NoSelection();
152                         } else if ( leaveNodeSelected ) {
153                             return new SelectedWayNode(selectedWay, editEnd ? selectedWay.length - 1 : 0);
154                         } else {
155                             return new SelectedWay(selectedWay);
156                         }
157                         return this;
158                 }
159
160                 public function createAndAddNode(event:MouseEvent):Node {
161                     var undo:CompositeUndoableAction = new CompositeUndoableAction("Add node");
162                     
163                         var lat:Number = controller.map.coord2lat(event.localY);
164                         var lon:Number = controller.map.coord2lon(event.localX);
165                         var node:Node = controller.connection.createNode({}, lat, lon, undo.push);
166                         appendNode(node, undo.push);
167                         
168                         MainUndoStack.getGlobalStack().addAction(undo);
169                         controller.map.setHighlight(node, { selectedway: true });
170                         controller.map.setPurgable(node, false);
171                         return node;
172                 }
173                 
174                 protected function appendNode(node:Node, performAction:Function):void {
175                         if ( editEnd )
176                                 selectedWay.appendNode(node, performAction);
177                         else
178                                 selectedWay.insertNode(0, node, performAction);
179                 }
180                 
181                 protected function backspaceNode(performAction:Function):ControllerState {
182                         var node:Node;
183                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Remove node");
184                         var newDraw:int;
185                         if (editEnd) {
186                                 node=selectedWay.getNode(selectedWay.length-1);
187                                 selectedWay.removeNodeByIndex(selectedWay.length-1, undo.push);
188                                 newDraw=selectedWay.length-2;
189                         } else {
190                                 node=selectedWay.getNode(0);
191                                 selectedWay.removeNodeByIndex(0, undo.push);
192                                 newDraw=0;
193                         }
194                         if (node.numParentWays==1 && selectedWay.hasOnceOnly(node)) {
195                                 controller.map.setPurgable(node, true);
196                                 controller.connection.unregisterPOI(node);
197                                 node.remove(undo.push);
198                         }
199                         MainUndoStack.getGlobalStack().addAction(undo);
200
201                         if (newDraw>=0 && newDraw<=selectedWay.length-1) {
202                                 var mouse:Point = new Point(selectedWay.getNode(newDraw).lon, selectedWay.getNode(newDraw).latp);
203                                 elastic.start = mouse;
204                                 return this;
205                         } else {
206                                 return new NoSelection();
207                         }
208                 }
209                 
210                 override public function enterState():void {
211                         super.enterState();
212                         
213                         var node:Node = selectedWay.getNode(editEnd ? selectedWay.length - 1 : 0);
214                         var start:Point = new Point(node.lon, node.latp);
215                         elastic = new Elastic(controller.map, start, start);
216                         controller.setCursor(controller.pen);
217                         Globals.vars.root.addDebug("**** -> "+this);
218                 }
219                 override public function exitState(newState:ControllerState):void {
220                         super.exitState(newState);
221                         controller.setCursor(null);
222                         elastic.removeSprites();
223                         elastic = null;
224                         Globals.vars.root.addDebug("**** <- "+this);
225                 }
226                 override public function toString():String {
227                         return "DrawWay";
228                 }
229         }
230 }