add undo for creating stuff
[potlatch2.git] / net / systemeD / potlatch2 / controller / DrawWay.as
1 package net.systemeD.potlatch2.controller {
2         import flash.events.*;
3         import flash.geom.*;
4         import net.systemeD.potlatch2.EditController;
5         import net.systemeD.halcyon.connection.*;
6         import net.systemeD.halcyon.Elastic;
7         import net.systemeD.halcyon.Globals;
8
9         public class DrawWay extends SelectedWay {
10                 private var elastic:Elastic;
11                 private var editEnd:Boolean;
12                 private var leaveNodeSelected:Boolean;
13                 private var lastClick:Entity=null;
14                 private var lastClickTime:Date;
15                 
16                 public function DrawWay(way:Way, editEnd:Boolean, leaveNodeSelected:Boolean) {
17                         super(way);
18                         this.editEnd = editEnd;
19                         this.leaveNodeSelected = leaveNodeSelected;
20                         if (way.length==1 && way.getNode(0).parentWays.length==1) {
21                                 // drawing new way, so keep track of click in case creating a POI
22                                 lastClick=way.getNode(0);
23                                 lastClickTime=new Date();
24                         }
25                 }
26                 
27                 override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
28                         var mouse:Point;
29                         var node:Node;
30                         var focus:Entity = NoSelection.getTopLevelFocusEntity(entity);
31
32                         if ( event.type == MouseEvent.MOUSE_UP ) {
33                                 if ( entity == null ) {
34                                         node = createAndAddNode(event);
35                                         resetElastic(node);
36                                         lastClick=node;
37                                 } else if ( entity is Node ) {
38                                         if (entity==lastClick && (new Date().getTime()-lastClickTime.getTime())<1000) {
39                                                 if (selectedWay.length==1 && selectedWay.getNode(0).parentWays.length==1) {
40                                                         // double-click to create new POI
41                                                         node=selectedWay.getNode(0);
42                                                         stopDrawing();
43                                                         controller.connection.registerPOI(node);
44                                                         return new SelectedPOINode(node);
45                                                 } else {
46                                                         // double-click at end of way
47                                                         return stopDrawing();
48                                                 }
49                                         } else {
50                                                 appendNode(entity as Node, MainUndoStack.getGlobalStack().addAction);
51                                                 controller.map.setHighlight(focus, { showNodesHover: false });
52                                                 controller.map.setHighlight(selectedWay, { showNodes: true });
53                                                 resetElastic(entity as Node);
54                                                 lastClick=entity;
55                                                 if (selectedWay.getNode(0)==selectedWay.getNode(selectedWay.length-1)) {
56                                                         return new SelectedWay(selectedWay);
57                                                 }
58                                         }
59                                 } else if ( entity is Way ) {
60                                         node = createAndAddNode(event);
61                                         Way(entity).insertNodeAtClosestPosition(node, true,
62                                             MainUndoStack.getGlobalStack().addAction);
63                                         resetElastic(node);
64                                         lastClick=node;
65                                 }
66                                 lastClickTime=new Date();
67                         } else if ( event.type == MouseEvent.MOUSE_MOVE ) {
68                                 mouse = new Point(
69                                                   controller.map.coord2lon(event.localX),
70                                                   controller.map.coord2latp(event.localY));
71                                 elastic.end = mouse;
72                         } else if ( event.type == MouseEvent.ROLL_OVER && focus!=selectedWay) {
73                                 controller.map.setHighlight(focus, { showNodesHover: true });
74                         } else if ( event.type == MouseEvent.MOUSE_OUT  && focus!=selectedWay) {
75                                 controller.map.setHighlight(focus, { showNodesHover: false });
76                                 controller.map.setHighlight(selectedWay, { showNodes: true });
77                                 // ** this call to setHighlight(selectedWay) is necessary in case the hovered way (blue nodes)
78                                 // shares any nodes with the selected way (red nodes): if they do, they'll be wiped out by the
79                                 // first call.
80                                 // Ultimately we should fix this by referring to 'way :selected nodes' instead of 'nodes :selectedway'.
81                                 // But this will do for now.
82                                 // We could do with an optional way of calling WayUI.redraw to only do the nodes, which would be a
83                                 // useful optimisation.
84                         }
85
86                         return this;
87                 }
88                 
89                 protected function resetElastic(node:Node):void {
90                         var mouse:Point = new Point(node.lon, node.latp);
91                         elastic.start = mouse;
92                         elastic.end = mouse;
93                 }
94
95                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
96                         if ( event.keyCode == 13 || event.keyCode == 27 ) { return stopDrawing(); }
97                         return this;
98                 }
99                 
100                 protected function stopDrawing():ControllerState {
101                         if ( selectedWay.length<2) {
102                                 controller.map.setHighlight(selectedWay, { showNodes: false });
103                                 selectedWay.remove(MainUndoStack.getGlobalStack().addAction);
104                                 // delete controller.map.ways[selectedWay.id];
105                                 return new NoSelection();
106                         } else if ( leaveNodeSelected ) {
107                             return new SelectedWayNode(selectedWay, selectedWay.getNode(editEnd ? selectedWay.length - 1 : 0));
108                         } else {
109                             return new SelectedWay(selectedWay);
110                         }
111                         return this;
112                 }
113
114                 public function createAndAddNode(event:MouseEvent):Node {
115                     var undo:CompositeUndoableAction = new CompositeUndoableAction("Add node");
116                     
117                         var lat:Number = controller.map.coord2lat(event.localY);
118                         var lon:Number = controller.map.coord2lon(event.localX);
119                         var node:Node = controller.connection.createNode({}, lat, lon, undo.push);
120                         appendNode(node, undo.push);
121                         
122                         MainUndoStack.getGlobalStack().addAction(undo);
123                         return node;
124                 }
125                 
126                 protected function appendNode(node:Node, performAction:Function):void {
127                         if ( editEnd )
128                                 selectedWay.appendNode(node, performAction);
129                         else
130                                 selectedWay.insertNode(0, node, performAction);
131                 }
132                 
133                 override public function enterState():void {
134                         super.enterState();
135                         
136                         var node:Node = selectedWay.getNode(editEnd ? selectedWay.length - 1 : 0);
137                         var start:Point = new Point(node.lon, node.latp);
138                         elastic = new Elastic(controller.map, start, start);
139                         Globals.vars.root.addDebug("**** -> "+this);
140                 }
141                 override public function exitState():void {
142                         super.exitState();
143                         elastic.removeSprites();
144                         elastic = null;
145                         Globals.vars.root.addDebug("**** <- "+this);
146                 }
147                 override public function toString():String {
148                         return "DrawWay";
149                 }
150         }
151 }