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