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