add undo for creating stuff
[potlatch2.git] / net / systemeD / potlatch2 / controller / SelectedWay.as
1 package net.systemeD.potlatch2.controller {
2         import flash.events.*;
3         import flash.ui.Keyboard;
4     import net.systemeD.potlatch2.EditController;
5     import net.systemeD.potlatch2.tools.Quadrilateralise;
6     import net.systemeD.halcyon.connection.*;
7         import net.systemeD.halcyon.Globals;
8
9     public class SelectedWay extends ControllerState {
10         public var selectedWay:Way;
11         protected var initWay:Way;
12         
13         public function SelectedWay(way:Way) {
14             initWay = way;
15         }
16  
17         protected function selectWay(way:Way):void {
18             if ( way == selectedWay )
19                 return;
20
21             clearSelection();
22             controller.setSelectedEntity(way);
23             controller.map.setHighlight(way, { selected: true, showNodes: true, hover: false });
24             selectedWay = way;
25             initWay = way;
26         }
27
28         protected function clearSelection():void {
29             if ( selectedWay != null ) {
30                 controller.map.setHighlight(selectedWay, { selected: false, showNodes: false, hover: false });
31                 controller.setSelectedEntity(null);
32                 selectedWay = null;
33             }
34         }
35         
36         override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
37                         if (event.type==MouseEvent.MOUSE_MOVE || event.type==MouseEvent.ROLL_OVER || event.type==MouseEvent.MOUSE_OUT) { return this; }
38             var focus:Entity = NoSelection.getTopLevelFocusEntity(entity);
39
40             if ( event.type == MouseEvent.MOUSE_UP ) {
41                                 if ( entity is Node && event.shiftKey ) {
42                                         // start new way
43                     var way:Way = controller.connection.createWay({}, [entity],
44                         MainUndoStack.getGlobalStack().addAction);
45                     return new DrawWay(way, true, false);
46                                 } else if ( entity is Way && event.ctrlKey ) {
47                                         // merge way
48                                         mergeWith(entity as Way);
49                                 } else if ( entity is Way ) {
50                                         // select way
51                     selectWay(entity as Way);
52                 } else if ( focus == null && map.dragstate!=map.DRAGGING ) {
53                     return new NoSelection();
54                                 }
55             } else if ( event.type == MouseEvent.MOUSE_DOWN ) {
56                                 if ( entity is Way && focus==selectedWay && event.shiftKey) {
57                                         // insert node within way (shift-click)
58                     var d:DragWayNode=new DragWayNode(selectedWay, addNode(event), event, true);
59                                         d.forceDragStart();
60                                         return d;
61                                 } else if ( entity is Node && entity.hasParent(selectedWay) ) {
62                                         // select node within this way
63                     return new DragWayNode(selectedWay, Node(entity), event, false);
64                 } else if ( focus is Node ) {
65                                         // select POI node
66                                         return new DragPOINode(entity as Node,event,false);
67                 } else if ( entity is Node && focus is Way ) {
68                                         // select way node
69                                         return new DragWayNode(focus as Way,entity as Node,event,false);
70                                 }
71             }
72
73             return this;
74         }
75         
76                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
77                         switch (event.keyCode) {
78                                 case 81:                                        Quadrilateralise.quadrilateralise(selectedWay); return this;
79                                 case Keyboard.BACKSPACE:        if (event.shiftKey) { return deleteWay(); } break;
80                                 case Keyboard.DELETE:           if (event.shiftKey) { return deleteWay(); } break;
81                         }
82                         return this;
83                 }
84
85         protected function addNode(event:MouseEvent):Node {
86             trace("add node");
87             var lat:Number = controller.map.coord2lat(event.localY);
88             var lon:Number = controller.map.coord2lon(event.localX);
89             var undo:CompositeUndoableAction = new CompositeUndoableAction("Insert node");
90             var node:Node = controller.connection.createNode({}, lat, lon, undo.push);
91             selectedWay.insertNodeAtClosestPosition(node, true, undo.push);
92             MainUndoStack.getGlobalStack().addAction(undo);
93                         return node;
94         }
95
96                 protected function mergeWith(otherWay:Way):Boolean {
97                         var way1:Way;
98                         var way2:Way;
99                         if ( selectedWay.id < otherWay.id && selectedWay.id >= 0 ) {
100                             way1 = selectedWay;
101                             way2 = otherWay;
102                         } else {
103                             way1 = otherWay;
104                             way2 = selectedWay;
105                         }
106                         
107                         var undo:Function = MainUndoStack.getGlobalStack().addAction;
108                         
109                         // find common point
110                         if (way1 == way2) { return false; }
111                         if      (way1.getNode(0)   ==way2.getNode(0)   ) { way1.mergeWith(way2,0,0,undo); }
112                         else if (way1.getNode(0)   ==way2.getLastNode()) { way1.mergeWith(way2,0,way2.length-1,undo); }
113                         else if (way1.getLastNode()==way2.getNode(0)   ) { way1.mergeWith(way2,way1.length-1,0,undo); }
114                         else if (way1.getLastNode()==way2.getLastNode()) { way1.mergeWith(way2,way1.length-1,way2.length-1,undo); }
115                         return true;
116                 }
117         
118                 public function deleteWay():ControllerState {
119                         selectedWay.remove(MainUndoStack.getGlobalStack().addAction);
120                         return new NoSelection();
121                 }
122
123         override public function enterState():void {
124             selectWay(initWay);
125                         Globals.vars.root.addDebug("**** -> "+this+" "+selectedWay.id);
126         }
127         override public function exitState():void {
128             clearSelection();
129                         Globals.vars.root.addDebug("**** <- "+this);
130         }
131
132         override public function toString():String {
133             return "SelectedWay";
134         }
135
136     }
137 }