e5226c454909a33b7b26004dd72d3f67c6fffc7b
[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 flash.geom.Point;
5     import net.systemeD.potlatch2.EditController;
6     import net.systemeD.halcyon.WayUI;
7     import net.systemeD.halcyon.connection.*;
8     import net.systemeD.halcyon.connection.actions.*;
9         import net.systemeD.halcyon.Globals;
10
11     public class SelectedWayNode extends ControllerState {
12                 private var parentWay:Way;
13                 private var initIndex:int;
14                 private var selectedIndex:int;
15         
16         public function SelectedWayNode(way:Way,index:int) {
17             parentWay = way;
18                         initIndex = index;
19         }
20  
21         protected function selectNode(way:Way,index:int):void {
22                         var node:Node=way.getNode(index);
23             if ( way == parentWay && node == firstSelected )
24                 return;
25
26             clearSelection(this);
27             controller.map.setHighlight(way, { hover: false });
28             controller.map.setHighlight(node, { selected: true });
29             controller.map.setHighlightOnNodes(way, { selectedway: true });
30             selection = [node]; parentWay = way;
31             controller.updateSelectionUI();
32                         selectedIndex = index; initIndex = index;
33         }
34                 
35         protected function clearSelection(newState:ControllerState):void {
36             if ( selectCount ) {
37                 controller.map.setHighlight(parentWay, { selected: false });
38                                 controller.map.setHighlight(firstSelected, { selected: false });
39                                 controller.map.setHighlightOnNodes(parentWay, { selectedway: false });
40                                 selection = [];
41                 if (!newState.isSelectionState()) { controller.updateSelectionUI(); }
42             }
43         }
44         
45         override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
46                         if (event.type==MouseEvent.MOUSE_MOVE || event.type==MouseEvent.ROLL_OVER || event.type==MouseEvent.MOUSE_OUT) { return this; }
47             var focus:Entity = getTopLevelFocusEntity(entity);
48
49             if ( event.type == MouseEvent.MOUSE_UP && entity is Node && event.shiftKey ) {
50                                 // start new way
51                 var way:Way = controller.connection.createWay({}, [entity],
52                     MainUndoStack.getGlobalStack().addAction);
53                 return new DrawWay(way, true, false);
54                         } else if ( event.type == MouseEvent.MOUSE_UP && entity is Node && focus == parentWay ) {
55                                 // select node within way
56                                 return selectOrEdit(parentWay, getNodeIndex(parentWay,Node(entity)));
57             } else if ( event.type == MouseEvent.MOUSE_DOWN && entity is Way && focus==parentWay && event.shiftKey) {
58                                 // insert node within way (shift-click)
59                         var d:DragWayNode=new DragWayNode(parentWay, -1, event, true);
60                                 d.forceDragStart();
61                                 return d;
62                         }
63                         var cs:ControllerState = sharedMouseEvents(event, entity);
64                         return cs ? cs : this;
65         }
66
67                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
68                         switch (event.keyCode) {
69                                 case 189:                                       return removeNode();                                    // '-'
70                                 case 88:                                        return splitWay();                                              // 'X'
71                                 case 82:                                        repeatTags(firstSelected); return this; // 'R'
72                                 case 87:                                        return new SelectedWay(parentWay);              // 'W'
73                                 case 191:                                       return cycleWays();                                             // '/'
74                 case 74:                    if (event.shiftKey) { return unjoin() }; return join();// 'J'
75                                 case Keyboard.BACKSPACE:        return deleteNode();
76                                 case Keyboard.DELETE:           return deleteNode();
77                         }
78                         var cs:ControllerState = sharedKeyboardEvents(event);
79                         return cs ? cs : this;
80                 }
81
82                 override public function get selectedWay():Way {
83                         return parentWay;
84                 }
85
86                 private function cycleWays():ControllerState {
87                         var wayList:Array=firstSelected.parentWays;
88                         if (wayList.length==1) { return this; }
89                         wayList.splice(wayList.indexOf(parentWay),1);
90                         return new SelectedWay(wayList[0],
91                                                new Point(controller.map.lon2coord(Node(firstSelected).lon),
92                                                          controller.map.latp2coord(Node(firstSelected).latp)),
93                                                wayList.concat(parentWay));
94                 }
95
96                 override public function enterState():void {
97             selectNode(parentWay,initIndex);
98                         controller.map.setPurgable(selection,false);
99                         Globals.vars.root.addDebug("**** -> "+this);
100         }
101                 override public function exitState(newState:ControllerState):void {
102             if (firstSelected.hasTags()) {
103               controller.clipboards['node']=firstSelected.getTagsCopy();
104             }
105                         controller.map.setPurgable(selection,true);
106             clearSelection(newState);
107                         Globals.vars.root.addDebug("**** <- "+this);
108         }
109
110         override public function toString():String {
111             return "SelectedWayNode";
112         }
113
114                 public static function selectOrEdit(selectedWay:Way, index:int):ControllerState {
115                         var isFirst:Boolean = false;
116                         var isLast:Boolean = false;
117                         var node:Node = selectedWay.getNode(index);
118                         isFirst = selectedWay.getNode(0) == node;
119                         isLast = selectedWay.getLastNode() == node;
120                         if ( isFirst == isLast )    // both == looped, none == central node 
121                             return new SelectedWayNode(selectedWay, index);
122                         else
123                             return new DrawWay(selectedWay, isLast, true);
124         }
125
126                 public function splitWay():ControllerState {
127                         // abort if start or end
128                         if (parentWay.getNode(0)    == firstSelected) { return this; }
129                         if (parentWay.getLastNode() == firstSelected) { return this; }
130
131                         controller.map.setHighlightOnNodes(parentWay, { selectedway: false } );
132                         controller.map.setPurgable([parentWay],true);
133             MainUndoStack.getGlobalStack().addAction(new SplitWayAction(parentWay, firstSelected as Node));
134
135                         return new SelectedWay(parentWay);
136                 }
137                 
138                 public function removeNode():ControllerState {
139                         if (firstSelected.numParentWays==1 && parentWay.hasOnceOnly(firstSelected as Node)) {
140                                 return deleteNode();
141                         }
142                         parentWay.removeNodeByIndex(selectedIndex, MainUndoStack.getGlobalStack().addAction);
143                         return new SelectedWay(parentWay);
144                 }
145                 
146                 public function deleteNode():ControllerState {
147                         controller.map.setPurgable(selection,true);
148                         firstSelected.remove(MainUndoStack.getGlobalStack().addAction);
149                         return new SelectedWay(parentWay);
150                 }
151
152         public function unjoin():ControllerState {
153             Node(firstSelected).unjoin(parentWay, MainUndoStack.getGlobalStack().addAction);
154             return this;
155         }
156
157         public function join():ControllerState {
158             // detect the ways that overlap this node
159             var p:Point = new Point(controller.map.lon2coord(Node(firstSelected).lon),
160                                              controller.map.latp2coord(Node(firstSelected).latp));
161             var q:Point = map.localToGlobal(p);
162             var ways:Array=[]; var w:Way;
163             for each (var wayui:WayUI in controller.map.paint.wayuis) {
164                 w=wayui.hitTest(q.x, q.y);
165                 if (w && w!=selectedWay) { ways.push(w); }
166             }
167
168             Node(firstSelected).join(ways,MainUndoStack.getGlobalStack().addAction);
169             return this;
170         }
171     }
172 }