Make quadralaterawhatsit work on selected waynodes, too. Add Q shortcut for both.
[potlatch2.git] / net / systemeD / potlatch2 / Toolbox.mxml
1 <?xml version="1.0" encoding="utf-8"?>
2 <mx:Panel
3         xmlns:mx="http://www.adobe.com/2006/mxml"
4         xmlns:potlatch2="net.systemeD.potlatch2.*"
5         height="76" width="129" layout="absolute"
6         styleName="theToolBox">
7
8                 <mx:Image data="@Embed('../../../embedded/close_small.png')"
9                         includeInLayout="false" id="toolboxClose" click="toggle();" 
10                         y="-6" x="115" />
11
12                 <!-- Top row -->
13
14                 <mx:Button icon="@Embed('../../../embedded/delete.svg')"
15                         click='doDelete();' 
16                         enabled="{canDo('delete')}" 
17                         alpha="{getAlpha('delete')}" 
18                         toolTip="{deleteToolTipText()}" 
19                         width="28" height="28" textAlign="left" y="4" x="6" paddingLeft="6" paddingRight="0" />
20                 <mx:Button icon="@Embed('../../../embedded/direction.svg')" 
21                         click='doReverseDirection();'
22                         enabled="{canDo('reverseDirection')}" 
23                         alpha="{getAlpha('reverseDirection')}" 
24                         toolTip="Reverse direction (V)" 
25                         width="28" height="28" textAlign="left" y="4" x="36" paddingLeft="8" paddingRight="0" />
26                 <mx:Button icon="@Embed('../../../embedded/cut.svg')" 
27                         click='doSplit();'
28                         enabled="{canDo('split')}" 
29                         alpha="{getAlpha('split')}" 
30                         toolTip="Split way (X)" 
31                         width="28" height="28" textAlign="left" y="4" x="66" paddingLeft="8" paddingRight="0" />
32                 <mx:Button icon="@Embed('../../../embedded/merge.svg')" 
33                         click='doMerge();'
34                         enabled="{canDo('merge')}" 
35                         alpha="{getAlpha('merge')}" 
36                         toolTip="Merge ways" 
37                         width="28" height="28" textAlign="left" y="4" x="96" paddingLeft="3" paddingRight="0" />
38
39                 <!-- Second row -->
40
41                 <mx:Button icon="@Embed('../../../embedded/straighten.svg')" 
42                         click='doStraighten();' 
43                         enabled="{canDo('straighten')}" 
44                         alpha="{getAlpha('straighten')}" 
45                         toolTip="Straighten way" 
46                         width="28" height="28" textAlign="left" y="34" x="6" paddingLeft="5" paddingRight="0" />
47                 <mx:Button icon="@Embed('../../../embedded/circle.svg')" 
48                         click='doCircularise();' 
49                         enabled="{canDo('circularise')}" 
50                         alpha="{getAlpha('circularise')}" 
51                         toolTip="Make circular" 
52                         width="28" height="28" textAlign="left" y="34" x="36" paddingLeft="4" paddingRight="0" />
53                 <mx:Button icon="@Embed('../../../embedded/quadrilateralise.svg')" 
54                         click='doQuadrilateralise();' 
55                         enabled="{canDo('quadrilateralise')}" 
56                         alpha="{getAlpha('quadrilateralise')}" 
57                         toolTip="Make right-angled" 
58                         width="28" height="28" textAlign="left" y="34" x="66" paddingLeft="6" paddingRight="0" />
59                 <mx:Button icon="@Embed('../../../embedded/parallel.svg')" 
60                         click='doParallelise();' 
61                         enabled="{canDo('parallelise')}" 
62                         alpha="{getAlpha('parallelise')}" 
63                         toolTip="Create parallel way (P)" 
64                         width="28" height="28" textAlign="left" y="34" x="96" paddingLeft="8" paddingRight="0" />
65
66         <mx:Script><![CDATA[
67
68                 import flash.events.Event;
69                 import flash.events.MouseEvent;
70                 import net.systemeD.halcyon.connection.*;
71                 import net.systemeD.halcyon.connection.actions.*;
72                 import net.systemeD.potlatch2.controller.*;
73                 import net.systemeD.potlatch2.tools.*;
74
75                 private var controller:EditController;
76
77                 public function init(controller:EditController):void {
78                         this.controller=controller;
79                         /* check if the toolbox was explictly turned off in a previous session */
80                         if( SharedObject.getLocal("user_state").data['toolbox_visible'] == false) {
81                           this.visible = false;
82                         }
83                 }
84
85                 override protected function createChildren():void {
86                         super.createChildren();
87                         super.titleBar.addEventListener(MouseEvent.MOUSE_DOWN,handleDown);
88                         super.titleBar.addEventListener(MouseEvent.MOUSE_UP,handleUp);
89                 }
90
91                 public function updateSelectionUI():void {
92                         dispatchEvent(new Event("updateSkin"));
93                         dispatchEvent(new Event("updateAlpha"));
94                 }
95
96                 private function handleDown(e:Event):void {
97                         this.startDrag();
98                 }
99
100                 private function handleUp(e:Event):void {
101                         this.stopDrag();
102                 }
103                 
104                 public function toggle():void {
105                         this.visible=!this.visible;
106                         var obj:SharedObject = SharedObject.getLocal("user_state");
107                         obj.setProperty("toolbox_visible",this.visible);
108                         obj.flush();
109                 }
110                 
111                 // --------------------------------------------------------------------------------
112                 // Enable/disable toolbox buttons
113                 // (ideally we'd use CSS to set alpha in disabled state, but Flex's CSS
114                 //      capabilities aren't up to it)
115                 
116                 [Bindable(event="updateSkin")]
117                 public function canDo(op:String):Boolean {
118                         if (controller.state.selectCount==0) return false;
119
120                         switch (op) {
121                                 case 'delete':                          return true;
122                                 case 'reverseDirection':        return controller.state.hasSelectedWays();
123                                 case 'quadrilateralise':        return (controller.state.hasSelectedAreas() || controller.state.hasSelectedWayNodesInAreas());
124                                 case 'straighten':                      return controller.state.hasSelectedUnclosedWays();
125                                 case 'circularise':                     return controller.state.hasSelectedAreas();
126                                 case 'split':                           return (controller.state is SelectedWayNode);
127                                 case 'parallelise':                     return (controller.state is SelectedWay);
128                                 case 'merge':                           return controller.state.hasAdjoiningWays();
129                         }
130                         return false;
131                 }
132
133                 [Bindable(event="updateAlpha")]
134                 public function getAlpha(op:String):Number {
135                         if (canDo(op)) { return 1; }
136                         return 0.5;
137                 }
138
139                 [Bindable(event="updateSkin")]
140                 private function deleteToolTipText():String {
141                         var entity:Entity=controller.state.firstSelected;
142                         if (entity is Node) { return "Delete Node (Delete)"; }
143                         if (entity is Way && Way(entity).isArea()) { return "Delete Area (Shift+Delete)"; }
144                         if (entity is Way) { return "Delete Way (Shift+Delete)"; }
145                         return "Delete Item"; // When nothing is selected
146                 }
147
148                 // --------------------------------------------------------------------------------
149                 // Individual toolbox actions
150
151                 public function doDelete():void {
152                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Delete objects");
153                         for each (var entity:Entity in controller.state.selection) {
154                                 if (entity is Node) { controller.connection.unregisterPOI(Node(entity)); }
155                                 entity.remove(undo.push);
156                         }
157                         MainUndoStack.getGlobalStack().addAction(undo);
158
159                         if (controller.state is SelectedWayNode) {
160                                 controller.setState(new SelectedWay(SelectedWayNode(controller.state).selectedWay));
161                         } else {
162                                 controller.setState(new NoSelection());
163                         }
164                 }
165                 
166                 public function doMerge():void {
167                         var changed:Boolean;
168                         var waylist:Array=controller.state.selectedWays;
169                         do {
170                                 // ** FIXME - we should have one CompositeUndoableAction for the whole caboodle,
171                                 // but that screws up the execution order and can make the merge not work
172                                 var undo:CompositeUndoableAction = new CompositeUndoableAction("Merge ways");
173                                 changed=tryMerge(waylist, undo);
174                                 MainUndoStack.getGlobalStack().addAction(undo);
175                         } while (changed==true);
176                         controller.setState(controller.findStateForSelection(waylist));
177                 }
178                 
179                 private function tryMerge(waylist:Array, undo:CompositeUndoableAction):Boolean {
180                         var way1:Way, way2:Way, del:uint;
181                         for (var i:uint=0; i<waylist.length; i++) {
182                                 for (var j:uint=0; j<waylist.length; j++) {
183                                         if (waylist[i]!=waylist[j]) {
184
185                                                 // Preserve positive IDs if we can
186                                                 if (waylist[i].id < waylist[j].id && waylist[i].id >= 0) {
187                                                         way1=waylist[i]; way2=waylist[j]; del=j;
188                                                 } else {
189                                                         way1=waylist[j]; way2=waylist[i]; del=i;
190                                                 }
191
192                                                 // Merge as appropriate
193                                                 if (way1.getNode(0)==way2.getNode(0)) {
194                                                         waylist.splice(del,1);
195                                                         undo.push(new MergeWaysAction(way1,way2,0,0));
196                                                         return true;
197                                                 } else if (way1.getNode(0)==way2.getLastNode()) { 
198                                                         waylist.splice(del,1);
199                                                         undo.push(new MergeWaysAction(way1,way2,0,way2.length-1));
200                                                         return true;
201                                                 } else if (way1.getLastNode()==way2.getNode(0)) {
202                                                         waylist.splice(del,1);
203                                                         undo.push(new MergeWaysAction(way1,way2,way1.length-1,0));
204                                                         return true;
205                                                 } else if (way1.getLastNode()==way2.getLastNode()) { 
206                                                         waylist.splice(del,1);
207                                                         undo.push(new MergeWaysAction(way1,way2,way1.length-1,way2.length-1));
208                                                         return true;
209                                                 }
210                                         }
211                                 }
212                         }
213                         return false;
214                 }
215
216                 public function doReverseDirection():void {
217                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Reverse direction of objects");
218                         for each (var way:Way in controller.state.selectedWays) {
219                                 way.reverseNodes(undo.push);
220                         }
221                         MainUndoStack.getGlobalStack().addAction(undo);
222                 }
223
224                 public function doQuadrilateralise():void {
225                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects right-angled");
226                         for each (var way:Way in controller.state.selectedWays) {
227                                 Quadrilateralise.quadrilateralise(way, undo.push);
228                         }
229             for each (var node:Node in controller.state.selectedNodes) {
230                 for each (var parentWay:Way in node.parentWays) {
231                   Quadrilateralise.quadrilateralise(parentWay, undo.push);
232                 }
233             }
234                         MainUndoStack.getGlobalStack().addAction(undo);
235                 }
236
237                 public function doStraighten():void {
238                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Straighten objects");
239                         for each (var way:Way in controller.state.selectedWays) {
240                                 Straighten.straighten(way, controller.map, undo.push);
241                         }
242                         MainUndoStack.getGlobalStack().addAction(undo);
243                 }
244
245                 public function doCircularise():void {
246                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects circular ");
247                         for each (var way:Way in controller.state.selectedWays) {
248                                 Circularise.circularise(way, controller.map, undo.push);
249                         }
250                         MainUndoStack.getGlobalStack().addAction(undo);
251                 }
252
253                 public function doSplit():void {
254                         if (controller.state is SelectedWayNode) {
255                                 controller.setState(SelectedWayNode(controller.state).splitWay());
256                         }
257                 }
258                 
259                 public function doParallelise():void {
260                         if (controller.state is SelectedWay) {
261                                 controller.setState(new SelectedParallelWay(Way(controller.state.firstSelected)));
262                         }
263                 }
264
265
266         ]]>
267 </mx:Script>    
268 </mx:Panel>