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