prevent fallthrough to deleteNode if you press j without shift
[potlatch2.git] / net / systemeD / potlatch2 / controller / SelectedWayNode.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.halcyon.connection.*;
6     import net.systemeD.halcyon.connection.actions.*;
7         import net.systemeD.halcyon.Globals;
8
9     public class SelectedWayNode extends ControllerState {
10                 private var parentWay:Way;
11                 private var initIndex:int;
12                 private var selectedIndex:int;
13         
14         public function SelectedWayNode(way:Way,index:int) {
15             parentWay = way;
16                         initIndex = index;
17         }
18  
19         protected function selectNode(way:Way,index:int):void {
20                         var node:Node=way.getNode(index);
21             if ( way == parentWay && node == firstSelected )
22                 return;
23
24             clearSelection(this);
25             controller.map.setHighlight(way, { hover: false });
26             controller.map.setHighlight(node, { selected: true });
27             controller.map.setHighlightOnNodes(way, { selectedway: true });
28             selection = [node]; parentWay = way;
29             controller.updateSelectionUI();
30                         selectedIndex = index; initIndex = index;
31         }
32                 
33         protected function clearSelection(newState:ControllerState):void {
34             if ( selectCount ) {
35                 controller.map.setHighlight(parentWay, { selected: false });
36                                 controller.map.setHighlight(firstSelected, { selected: false });
37                                 controller.map.setHighlightOnNodes(parentWay, { selectedway: false });
38                                 selection = []; parentWay = null;
39                 if (!newState.isSelectionState()) { controller.updateSelectionUI(); }
40             }
41         }
42         
43         override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
44                         if (event.type==MouseEvent.MOUSE_MOVE || event.type==MouseEvent.ROLL_OVER || event.type==MouseEvent.MOUSE_OUT) { return this; }
45             var focus:Entity = getTopLevelFocusEntity(entity);
46
47             if ( event.type == MouseEvent.MOUSE_UP && entity is Node && event.shiftKey ) {
48                                 // start new way
49                 var way:Way = controller.connection.createWay({}, [entity],
50                     MainUndoStack.getGlobalStack().addAction);
51                 return new DrawWay(way, true, false);
52                         } else if ( event.type == MouseEvent.MOUSE_UP && entity is Node && focus == parentWay ) {
53                                 // select node within way
54                                 return selectOrEdit(parentWay, getNodeIndex(parentWay,Node(entity)));
55             } else if ( event.type == MouseEvent.MOUSE_DOWN && entity is Way && focus==parentWay && event.shiftKey) {
56                                 // insert node within way (shift-click)
57                         var d:DragWayNode=new DragWayNode(parentWay, -1, event, true);
58                                 d.forceDragStart();
59                                 return d;
60                         }
61                         var cs:ControllerState = sharedMouseEvents(event, entity);
62                         return cs ? cs : this;
63         }
64
65                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
66                         switch (event.keyCode) {
67                                 case 189:                                       return removeNode();                                    // '-'
68                                 case 88:                                        return splitWay();                                              // 'X'
69                                 case 82:                                        repeatTags(firstSelected); return this; // 'R'
70                                 case 87:                                        return new SelectedWay(parentWay);              // 'W'
71                 case 74:                    if (event.shiftKey) { return unjoin() }; return this;// 'J'
72                                 case Keyboard.BACKSPACE:        return deleteNode();
73                                 case Keyboard.DELETE:           return deleteNode();
74                         }
75                         var cs:ControllerState = sharedKeyboardEvents(event);
76                         return cs ? cs : this;
77                 }
78
79                 override public function get selectedWay():Way {
80                         return parentWay;
81                 }
82
83                 override public function enterState():void {
84             selectNode(parentWay,initIndex);
85                         controller.map.setPurgable(firstSelected,false);
86                         Globals.vars.root.addDebug("**** -> "+this);
87         }
88                 override public function exitState(newState:ControllerState):void {
89                         controller.clipboards['node']=firstSelected.getTagsCopy();
90                         controller.map.setPurgable(firstSelected,true);
91             clearSelection(newState);
92                         Globals.vars.root.addDebug("**** <- "+this);
93         }
94
95         override public function toString():String {
96             return "SelectedWayNode";
97         }
98
99                 public static function selectOrEdit(selectedWay:Way, index:int):ControllerState {
100                         var isFirst:Boolean = false;
101                         var isLast:Boolean = false;
102                         var node:Node = selectedWay.getNode(index);
103                         isFirst = selectedWay.getNode(0) == node;
104                         isLast = selectedWay.getLastNode() == node;
105                         if ( isFirst == isLast )    // both == looped, none == central node 
106                             return new SelectedWayNode(selectedWay, index);
107                         else
108                             return new DrawWay(selectedWay, isLast, true);
109         }
110
111                 public function splitWay():ControllerState {
112                         // abort if start or end
113                         if (parentWay.getNode(0)    == firstSelected) { return this; }
114                         if (parentWay.getLastNode() == firstSelected) { return this; }
115
116                         controller.map.setHighlightOnNodes(parentWay, { selectedway: false } );
117                         controller.map.setPurgable(parentWay,true);
118             MainUndoStack.getGlobalStack().addAction(new SplitWayAction(parentWay, firstSelected as Node));
119
120                         return new SelectedWay(parentWay);
121                 }
122                 
123                 public function removeNode():ControllerState {
124                         if (firstSelected.numParentWays==1 && parentWay.hasOnceOnly(firstSelected as Node)) {
125                                 return deleteNode();
126                         }
127                         parentWay.removeNodeByIndex(selectedIndex, MainUndoStack.getGlobalStack().addAction);
128                         return new SelectedWay(parentWay);
129                 }
130                 
131                 public function deleteNode():ControllerState {
132                         controller.map.setPurgable(firstSelected,true);
133                         firstSelected.remove(MainUndoStack.getGlobalStack().addAction);
134                         return new SelectedWay(parentWay);
135                 }
136
137         public function unjoin():ControllerState {
138             Node(firstSelected).unjoin(parentWay, MainUndoStack.getGlobalStack().addAction);
139             return this;
140         }
141
142     }
143 }