Prevent parallel way creation leaving entries in Undo stack if way creation is aborted.
[potlatch2.git] / net / systemeD / potlatch2 / controller / SelectedParallelWay.as
1 package net.systemeD.potlatch2.controller {
2         import flash.events.*;
3         import flash.display.Stage;
4     import net.systemeD.halcyon.connection.*;
5     import net.systemeD.halcyon.Map;
6         import net.systemeD.potlatch2.tools.Parallelise;
7         import net.systemeD.halcyon.connection.actions.*;
8
9     /** The state midway during the use of the "parallelise tool", where a parallel way has been created but is stuck to the 
10     * mouse cursor, allowing the user to choose how far from the original way it should go. This transforms it in the process. */
11     public class SelectedParallelWay extends SelectedWay {
12                 private var startlon:Number;
13                 private var startlatp:Number;
14                 private var parallelise:Parallelise;
15                 private var originalWay:Way;
16
17         /** Initialises by parallelising the originalWay. */
18         public function SelectedParallelWay(originalWay:Way) {
19                         this.originalWay = originalWay;
20                         parallelise = new Parallelise(originalWay);
21                         super (parallelise.parallelWay);
22         }
23
24         override public function processMouseEvent(event:MouseEvent, entity:Entity):ControllerState {
25                         if (event.type==MouseEvent.MOUSE_MOVE || event.type==MouseEvent.MOUSE_UP) {
26                                 var lon:Number =controller.map.coord2lon(controller.map.mouseX);
27                                 var latp:Number=controller.map.coord2latp(controller.map.mouseY);
28                                 parallelise.draw(distanceFromWay(lon,latp));
29                         }
30                         if (event.type==MouseEvent.MOUSE_UP) {
31                                 return new SelectedWay(firstSelected as Way);
32                         }
33                         return this;
34         }
35
36                 /** Cancel parallel way creation if ESC pressed. */
37                 override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
38                         if (event.keyCode==27) {                        // Escape
39                                 Way(firstSelected).remove(MainUndoStack.getGlobalStack().addAction);
40                                 // Parallel way wasn't created, so remove it from undo history.
41                                 MainUndoStack.getGlobalStack().removeLastIfAction(DeleteWayAction);
42                 MainUndoStack.getGlobalStack().removeLastIfAction(CreateEntityAction);
43                                 
44                                 return new NoSelection();
45                         }
46                         var cs:ControllerState = sharedKeyboardEvents(event);
47                         return cs ? cs : this;
48                 }
49
50                 private function sgn(a:Number):Number {
51                         if (a==0) return 0;
52                         if (a<0) return -1;
53                         return 1;
54                 }
55                 
56                 private function distanceFromWay(lon:Number,latp:Number):Number {
57                         var i:uint, ax:Number, ay:Number, bx:Number, by:Number, l:Number;
58                         var ad:Number, bd:Number;
59                         var r:Number, px:Number, py:Number;
60                         var furthdist:Number=-1; var furthsgn:int=1;
61                         for (i=0; i<originalWay.length-1; i++) {
62                                 ax=originalWay.getNode(i).lon;
63                                 ay=originalWay.getNode(i).latp;
64                                 bx=originalWay.getNode(i+1).lon;
65                                 by=originalWay.getNode(i+1).latp;
66
67                                 ad=Math.sqrt(Math.pow(lon-ax,2)+Math.pow(latp-ay,2));   // distance to ax,ay
68                                 bd=Math.sqrt(Math.pow(bx-lon,2)+Math.pow(by-latp,2));   // distance to bx,by
69                                 l =Math.sqrt(Math.pow(bx-ax ,2)+Math.pow(by-ay  ,2));   // length of segment
70                                 r =ad/(ad+bd);                                                                                  // proportion along segment
71                                 px=ax+r*(bx-ax); py=ay+r*(by-ay);                                               // nearest point on line
72                                 r=Math.sqrt(Math.pow(px-lon,2)+Math.pow(py-latp,2));    // distance from px,py to lon,latp
73
74                                 if (furthdist<0 || furthdist>r) {
75                                         furthdist=r; 
76                                         furthsgn=sgn((bx-ax)*(latp-ay)-(by-ay)*(lon-ax));
77                                 }
78                         }
79                         return furthdist*furthsgn;
80                 }
81
82                 /** Creates the WayUI for the parallel way. */
83                 override public function enterState():void {
84                         selection=[parallelise.parallelWay];
85                         layer.createWayUI(firstSelected as Way);
86                         startlon =controller.map.coord2lon(controller.map.mouseX);
87                         startlatp=controller.map.coord2latp(controller.map.mouseY);
88         }
89                 /** Unselects. */
90                 override public function exitState(newState:ControllerState):void {
91             clearSelection(newState);
92         }
93
94         override public function toString():String {
95             return "SelectedParallelWay";
96         }
97     }
98 }