Merge branch 'master' into snapshotserver
[potlatch2.git] / net / systemeD / potlatch2 / Toolbox.mxml
1 <?xml version="1.0" encoding="utf-8"?>
2 <mx:Panel
3     xmlns:fx="http://ns.adobe.com/mxml/2009"
4         xmlns:mx="library://ns.adobe.com/flex/mx"
5         xmlns:s="library://ns.adobe.com/flex/spark"
6         xmlns:potlatch2="net.systemeD.potlatch2.*"
7         height="76" width="129" layout="absolute"
8         styleName="theToolBox">
9
10                 <mx:Image data="@Embed('../../../embedded/close_small.png')"
11                         includeInLayout="false" id="toolboxClose" click="toggle();" 
12                         y="-6" x="115" />
13
14                 <!-- Top row -->
15
16                 <s:Button icon="@Embed('../../../embedded/delete.svg')"
17                         click='doDelete();' 
18                         enabled="{canDo('delete')}" 
19                         alpha="{getAlpha('delete')}" 
20                         toolTip="{deleteToolTipText()}" 
21                         width="28" height="28" y="4" x="6" />
22
23                 <mx:HBox id="reverseButton" width="28" height="28" y="4" x="36" borderStyle="none"
24                            horizontalAlign="center" verticalAlign="middle" toolTip="Reverse direction (V)">
25             <mx:ViewStack id="rotateButtonStack" creationPolicy="all">
26                 <mx:HBox id="arrowBoxWrapper">
27                                         <s:NavigatorContent width="28" height="28">
28                                                 <s:Button id="arrow" icon="{Arrow}" width="28" height="28" alpha="{getAlpha('reverseDirection')}" click="reverseClicked();"/>
29                                         </s:NavigatorContent>
30                 </mx:HBox>
31                 <mx:HBox id="clockwiseBox" horizontalAlign="center" verticalAlign="middle">
32                     <s:Button id="clockwise" icon="@Embed('../../../embedded/clockwise.svg')"
33                         alpha="{getAlpha('reverseDirection')}"
34                         width="28" height="28" click="reverseClicked();" />
35                 </mx:HBox>
36                 <mx:HBox id="antiClockwiseBox" horizontalAlign="center" verticalAlign="middle">
37                     <s:Button id="anticlockwise" icon="@Embed('../../../embedded/anti-clockwise.svg')"
38                         enabled="{canDo('reverseDirection')}"
39                         alpha="{getAlpha('reverseDirection')}"
40                         width="28" height="28" click="reverseClicked();" />
41                 </mx:HBox>
42             </mx:ViewStack>
43         </mx:HBox>
44                 <s:Button icon="@Embed('../../../embedded/cut.svg')"
45                         id="splitButton"
46                         click='doSplit();'
47                         enabled="{canDo('split')}" 
48                         alpha="{getAlpha('split')}" 
49                         toolTip="Split way (X)" 
50                         width="28" height="28" y="4" x="66" />
51                 <s:Button icon="@Embed('../../../embedded/merge.svg')"
52                         id="mergeButton"
53                         click='doMerge();'
54                         enabled="{canDo('merge')}" 
55                         alpha="{getAlpha('merge')}" 
56                         toolTip="Merge ways" 
57                         width="28" height="28" y="4" x="96" />
58
59                 <!-- Second row -->
60
61                 <s:Button icon="@Embed('../../../embedded/straighten.svg')"
62                         id="straightenButton"
63                         click='doStraighten();' 
64                         enabled="{canDo('straighten')}" 
65                         alpha="{getAlpha('straighten')}" 
66                         toolTip="Straighten way" 
67                         width="28" height="28" y="34" x="6" />
68                 <s:Button icon="@Embed('../../../embedded/circle.svg')"
69                         id="circulariseButton"
70                         click='doCircularise();' 
71                         enabled="{canDo('circularise')}" 
72                         alpha="{getAlpha('circularise')}" 
73                         toolTip="Make circular" 
74                         width="28" height="28" y="34" x="36" />
75                 <s:Button icon="@Embed('../../../embedded/quadrilateralise.svg')"
76                         id="quadrilateraliseButton"
77                         click='doQuadrilateralise();' 
78                         enabled="{canDo('quadrilateralise')}" 
79                         alpha="{getAlpha('quadrilateralise')}" 
80                         toolTip="Make right-angled (Q)"
81                         width="28" height="28" y="34" x="66" />
82                 <s:Button icon="@Embed('../../../embedded/parallel.svg')"
83                         id="parralleliseButton"
84                         click='doParallelise();' 
85                         enabled="{canDo('parallelise')}" 
86                         alpha="{getAlpha('parallelise')}" 
87                         toolTip="Create parallel way (P)" 
88                         width="28" height="28" y="34" x="96" />
89
90         <fx:Script><![CDATA[
91
92                 import flash.events.Event;
93                 import flash.events.MouseEvent;
94                 import net.systemeD.halcyon.connection.*;
95                 import net.systemeD.halcyon.connection.actions.*;
96                 import net.systemeD.potlatch2.controller.*;
97                 import net.systemeD.potlatch2.tools.*;
98                 import embedded.*;      // for FXG icons
99
100                 private var controller:EditController;
101
102         [Bindable]
103         public var angle:int=0;
104
105         public var deleteNode:String = "Delete Node (Delete)";
106         public var deleteArea:String = "Delete Area (Shift+Delete)";
107         public var deleteWay:String = "Delete Way (Shift+Delete)";
108         public var deleteItem:String = "Delete Item"; // When nothing is selected
109
110                 public function init(controller:EditController):void {
111                         this.controller=controller;
112                         /* check if the toolbox was explictly turned off in a previous session */
113                         if( SharedObject.getLocal("user_state").data['toolbox_visible'] == false) {
114                           this.visible = false;
115                         }
116                 }
117
118                 override protected function createChildren():void {
119                         super.createChildren();
120                         super.titleBar.addEventListener(MouseEvent.MOUSE_DOWN,handleDown);
121                 }
122
123                 public function updateSelectionUI():void {
124                         dispatchEvent(new Event("updateSkin"));
125                         dispatchEvent(new Event("updateAlpha"));
126                         updateDirectionArrow();
127                 }
128
129                 private function handleDown(e:Event):void {
130                         this.startDrag();
131                         stage.addEventListener(MouseEvent.MOUSE_UP,handleUp);
132                 }
133
134                 private function handleUp(e:Event):void {
135                         this.stopDrag();
136                         stage.removeEventListener(MouseEvent.MOUSE_UP,handleUp);
137                 }
138                 
139                 public function toggle():void {
140                         this.visible=!this.visible;
141                         var obj:SharedObject = SharedObject.getLocal("user_state");
142                         obj.setProperty("toolbox_visible",this.visible);
143                         obj.flush();
144                 }
145                 
146                 // --------------------------------------------------------------------------------
147                 // Enable/disable toolbox buttons
148                 // (ideally we'd use CSS to set alpha in disabled state, but Flex's CSS
149                 //      capabilities aren't up to it)
150                 
151                 [Bindable(event="updateSkin")]
152                 public function canDo(op:String):Boolean {
153                         if (controller.state.selectCount==0) return false;
154
155                         switch (op) {
156                                 case 'delete':                          return true;
157                                 case 'reverseDirection':        return controller.state.hasSelectedWays();
158                                 case 'quadrilateralise':        return (controller.state.hasSelectedAreas() || controller.state.hasSelectedWayNodesInAreas());
159                                 case 'straighten':                      return controller.state.hasSelectedUnclosedWays();
160                                 case 'circularise':                     return controller.state.hasSelectedAreas();
161                                 case 'split':                           return (controller.state is SelectedWayNode);
162                                 case 'parallelise':                     return (controller.state is SelectedWay);
163                                 case 'merge':                           return controller.state.hasAdjoiningWays();
164                         }
165                         return false;
166                 }
167
168                 [Bindable(event="updateAlpha")]
169                 public function getAlpha(op:String):Number {
170                         if (canDo(op)) { return 1; }
171                         return 0.5;
172                 }
173
174                 [Bindable(event="updateSkin")]
175                 private function deleteToolTipText():String {
176                         var entity:Entity=controller.state.firstSelected;
177                         if (entity is Node) { return deleteNode; }
178                         if (entity is Way && Way(entity).isArea()) { return deleteArea; }
179                         if (entity is Way) { return deleteWay; }
180                         return deleteItem; // When nothing is selected
181                 }
182
183         private function updateDirectionArrow():void {
184             if (controller.state is SelectedWay) {
185                 var w:Way = Way(controller.state.firstSelected);
186                 if (w) { // not entirely sure why this protection is necessary, but it appears so
187                     if (w.isArea()) {
188                         // so Way.clockwise appears to give wrong results. Patches welcome, I guess, but for now...
189                         w.clockwise? rotateButtonStack.selectedChild = antiClockwiseBox : rotateButtonStack.selectedChild = clockwiseBox;
190                     } else {
191                         rotateButtonStack.selectedChild = arrowBoxWrapper;
192                         arrow.iconDisplay.rotation=w.angle;
193                                                 arrow.iconDisplay.smooth=true;
194                     }
195                 }
196             }
197         }
198
199         private function reverseClicked():void {
200             if(canDo('reverseDirection')) {
201                 doReverseDirection();
202             }
203         }
204
205                 // --------------------------------------------------------------------------------
206                 // Individual toolbox actions
207
208                 public function doDelete():void {
209                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Delete objects");
210                         for each (var entity:Entity in controller.state.selection) {
211                                 if (entity is Node) { entity.connection.unregisterPOI(Node(entity)); }
212                                 entity.remove(undo.push);
213                         }
214                         MainUndoStack.getGlobalStack().addAction(undo);
215
216                         if (controller.state is SelectedWayNode) {
217                                 controller.setState(new SelectedWay(SelectedWayNode(controller.state).selectedWay));
218                         } else {
219                                 controller.setState(new NoSelection());
220                         }
221                 }
222                 
223                 public function doMerge():void {
224                         controller.setState(SelectedMultiple(controller.state).mergeWays());
225                 }
226
227                 public function doReverseDirection():void {
228                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Reverse direction of objects");
229                         for each (var way:Way in controller.state.selectedWays) {
230                                 way.reverseNodes(undo.push);
231                         }
232                         MainUndoStack.getGlobalStack().addAction(undo);
233                 }
234
235                 public function doQuadrilateralise():void {
236                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects right-angled");
237                         for each (var way:Way in controller.state.selectedWays) {
238                                 Quadrilateralise.quadrilateralise(way, undo.push);
239                         }
240             for each (var node:Node in controller.state.selectedNodes) {
241                 for each (var parentWay:Way in node.parentWays) {
242                   Quadrilateralise.quadrilateralise(parentWay, undo.push);
243                 }
244             }
245                         MainUndoStack.getGlobalStack().addAction(undo);
246                 }
247
248                 public function doStraighten():void {
249                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Straighten objects");
250                         for each (var way:Way in controller.state.selectedWays) {
251                                 Straighten.straighten(way, controller.map, undo.push);
252                         }
253                         MainUndoStack.getGlobalStack().addAction(undo);
254                 }
255
256                 public function doCircularise():void {
257                         var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects circular ");
258                         for each (var way:Way in controller.state.selectedWays) {
259                                 Circularise.circularise(way, controller.map, undo.push);
260                         }
261                         MainUndoStack.getGlobalStack().addAction(undo);
262                 }
263
264                 public function doSplit():void {
265                         if (controller.state is SelectedWayNode) {
266                                 controller.setState(SelectedWayNode(controller.state).splitWay());
267                         }
268                 }
269                 
270                 public function doParallelise():void {
271                         if (controller.state is SelectedWay) {
272                                 controller.setState(new SelectedParallelWay(Way(controller.state.firstSelected)));
273                         }
274                 }
275
276
277         ]]>
278 </fx:Script>
279 </mx:Panel>