Work in progress
[potlatch2.git] / net / systemeD / potlatch2 / controller / DragWayNode.as
1 package net.systemeD.potlatch2.controller {
2         import flash.events.*;
3     import net.systemeD.potlatch2.EditController;
4     import net.systemeD.halcyon.connection.*;
5         import net.systemeD.halcyon.WayUI;
6
7     public class DragWayNode extends ControllerState {
8         private var draggingNode:Node;
9                 private var draggingIndex:int;
10         private var isDraggingStarted:Boolean = false;
11                 private var isNew:Boolean = false;
12
13         private var downX:Number;
14         private var downY:Number;
15                 private var originalLat:Number;
16                 private var originalLon:Number;
17                 private var dragstate:uint=NOT_MOVED;
18                 private const NOT_DRAGGING:uint=0;
19                 private const NOT_MOVED:uint=1;
20                 private const DRAGGING:uint=2;
21                 
22                 private var parentWay:Way;
23                 private var initEvent:MouseEvent;
24         
25         public function DragWayNode(way:Way, index:int, event:MouseEvent, newNode:Boolean) {
26                         parentWay=way;
27                         draggingIndex=index;
28             downX = event.localX;
29             downY = event.localY;
30                         isNew = newNode;
31                         initEvent=event;
32                         // the rest of the init will be done during enterState, because we need the controller to be initialised
33         }
34
35         private function addNode(selectedWay:Way,event:MouseEvent):int {
36                         // find which other ways are under the mouse
37                         var ways:Array=[]; var w:Way;
38                         for each (var wayui:WayUI in editableLayer.wayuis) {
39                                 w=wayui.hitTest(event.stageX, event.stageY);
40                                 if (w && w!=selectedWay) { ways.push(w); }
41                         }
42
43             var lat:Number = controller.map.coord2lat(event.localY);
44             var lon:Number = controller.map.coord2lon(event.localX);
45             var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node");
46             var node:Node = controller.connection.createNode({}, lat, lon, undo.push);
47             var index:int = selectedWay.insertNodeAtClosestPosition(node, true, undo.push);
48                         for each (w in ways) { w.insertNodeAtClosestPosition(node, true, undo.push); }
49             MainUndoStack.getGlobalStack().addAction(undo);
50                         return index;
51         }
52
53  
54        override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
55
56             if (event.type==MouseEvent.MOUSE_UP) {
57                                 if (dragstate==DRAGGING) {
58                                         // mouse-up while dragging, so end drag
59                         return new SelectedWayNode(parentWay,draggingIndex);
60                                 } else if (event.shiftKey && !isNew) {
61                                         // start new way
62                                         var way:Way = controller.connection.createWay({}, [entity],
63                                             MainUndoStack.getGlobalStack().addAction);
64                                         return new DrawWay(way, true, false);
65                                 } else if (event.shiftKey && isNew) {
66                         return new SelectedWayNode(parentWay,draggingIndex);
67                                 } else {
68                                         // select node
69                                         dragstate=NOT_DRAGGING;
70                         return SelectedWayNode.selectOrEdit(parentWay, draggingIndex);
71                                 }
72
73                         } else if ( event.type == MouseEvent.MOUSE_MOVE) {
74                                 // dragging
75                                 if (dragstate==NOT_DRAGGING) {
76                                         return this;
77                                 } else if (dragstate==NOT_MOVED && Math.abs(downX - event.localX) < 3 && Math.abs(downY - event.localY) < 3) {
78                                         return this;
79                                 }
80                                 dragstate=DRAGGING;
81                 return dragTo(event);
82
83                         } else {
84                                 // event not handled
85                 return this;
86                         }
87         }
88
89                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
90                         if (event.keyCode==27) {
91                                 draggingNode.setLatLon( originalLat, originalLon, MainUndoStack.getGlobalStack().addAction );
92                 return new SelectedWayNode(parentWay,draggingIndex);
93                         }
94                         return this;
95                 }
96
97         private function dragTo(event:MouseEvent):ControllerState {
98                         draggingNode.setLatLon( controller.map.coord2lat(event.localY),
99                                     controller.map.coord2lon(event.localX),
100                                     MainUndoStack.getGlobalStack().addAction );
101             return this;
102         }
103         
104                 public function forceDragStart():void {
105                         dragstate=NOT_MOVED;
106                 }
107                 
108                 override public function get selectedWay():Way {
109                         return parentWay;
110                 }
111
112         override public function enterState():void {
113                         if (isNew && draggingIndex==-1) { draggingIndex=addNode(parentWay,initEvent); }
114             draggingNode = parentWay.getNode(draggingIndex);
115                         originalLat = draggingNode.lat;
116                         originalLon = draggingNode.lon;
117
118                         editableLayer.setHighlightOnNodes(parentWay, { selectedway: true } );
119                         editableLayer.limitWayDrawing(parentWay, draggingIndex);
120                         editableLayer.setHighlight(draggingNode, { selected: true } );
121                         editableLayer.protectWay(parentWay);
122                         editableLayer.limitWayDrawing(parentWay, NaN, draggingIndex);
123         }
124         override public function exitState(newState:ControllerState):void {
125                         editableLayer.unprotectWay(parentWay);
126                         editableLayer.limitWayDrawing(parentWay);
127                         editableLayer.setHighlightOnNodes(parentWay, { selectedway: false } );
128                         editableLayer.setHighlight(draggingNode, { selected: false } );
129         }
130         override public function toString():String {
131             return "DragWayNode";
132         }
133     }
134 }