1 <?xml version="1.0" encoding="utf-8"?>
3 xmlns:mx="http://www.adobe.com/2006/mxml"
4 xmlns:potlatch2="net.systemeD.potlatch2.*"
5 borderThicknessRight="1" borderThicknessLeft="1" borderThicknessBottom="3"
6 title="Edit Pathways and Areas" layout="horizontal" styleName="theToolBox">
8 <!-- the animation effect that controls the rotation of the reverse arrow.
9 We could get more fancy by using previous angle in angleFrom, and a longer duration, to give a nice animated effect -->
10 <mx:Rotate id="rotate" angleFrom="{angle-1}" angleTo="{angle}" target="{arrowBox}" originX="{arrowBox.width/2}" originY="{arrowBox.height/2}" duration="4"/>
14 <mx:Button icon="@Embed('../../../embedded/delete.svg')"
16 enabled="{canDo('delete')}"
17 alpha="{getAlpha('delete')}"
18 toolTip="{deleteToolTipText()}"
19 width="24" height="24" />
21 <mx:HBox width="24" height="24" y="4" x="36" borderStyle="solid" cornerRadius="12" click="reverseClicked();" horizontalAlign="center" verticalAlign="middle">
22 <mx:ViewStack id="rotateButtonStack">
23 <mx:HBox id="arrowBoxWrapper"><!-- changing the viewstack back onto a rotated hbox causes positioning glitches, hence this wrapper -->
24 <!-- I can totally recommend adding borderStyle="solid" to arrowBox when debugging -->
25 <mx:HBox id="arrowBox" horizontalAlign="center" verticalAlign="middle" width="24" height="24">
26 <mx:Image id="arrow" source="@Embed('../../../embedded/arrow.svg')"
27 alpha="{getAlpha('reverseDirection')}"
28 toolTip="Reverse direction (V)"
29 width="22" height="22"/>
32 <mx:HBox id="clockwiseBox" horizontalAlign="center" verticalAlign="middle">
33 <mx:Image id="clockwise" source="@Embed('../../../embedded/clockwise.svg')"
34 alpha="{getAlpha('reverseDirection')}"
35 toolTip="Reverse direction (V)"
36 width="22" height="22" x="2" y="2"/>
38 <mx:HBox id="antiClockwiseBox" horizontalAlign="center" verticalAlign="middle">
39 <mx:Image id="anticlockwise" source="@Embed('../../../embedded/anti-clockwise.svg')"
40 click='doReverseDirection();'
41 enabled="{canDo('reverseDirection')}"
42 alpha="{getAlpha('reverseDirection')}"
43 toolTip="Reverse direction (V)"
44 width="22" height="22" x="2" y="2"/>
48 <mx:Button icon="@Embed('../../../embedded/cut.svg')"
50 enabled="{canDo('split')}"
51 alpha="{getAlpha('split')}"
52 toolTip="Split way (X)"
53 width="24" height="24" />
54 <mx:Button icon="@Embed('../../../embedded/merge.svg')"
56 enabled="{canDo('merge')}"
57 alpha="{getAlpha('merge')}"
59 width="24" height="24" />
63 <mx:Button icon="@Embed('../../../embedded/straighten.svg')"
64 click='doStraighten();'
65 enabled="{canDo('straighten')}"
66 alpha="{getAlpha('straighten')}"
67 toolTip="Straighten way"
68 width="24" height="24" />
69 <mx:Button icon="@Embed('../../../embedded/circle.svg')"
70 click='doCircularise();'
71 enabled="{canDo('circularise')}"
72 alpha="{getAlpha('circularise')}"
73 toolTip="Make circular"
74 width="24" height="24" />
75 <mx:Button icon="@Embed('../../../embedded/quadrilateralise.svg')"
76 click='doQuadrilateralise();'
77 enabled="{canDo('quadrilateralise')}"
78 alpha="{getAlpha('quadrilateralise')}"
79 toolTip="Make right-angled (Q)"
80 width="24" height="24" />
81 <mx:Button icon="@Embed('../../../embedded/parallel.svg')"
82 click='doParallelise();'
83 enabled="{canDo('parallelise')}"
84 alpha="{getAlpha('parallelise')}"
85 toolTip="Create parallel way (P)"
86 width="24" height="24" />
90 import flash.events.Event;
91 import flash.events.MouseEvent;
92 import net.systemeD.halcyon.connection.*;
93 import net.systemeD.halcyon.connection.actions.*;
94 import net.systemeD.potlatch2.controller.*;
95 import net.systemeD.potlatch2.tools.*;
97 private var controller:EditController;
100 public var angle:int=0;
102 public function init(controller:EditController):void {
103 this.controller=controller;
104 /* check if the toolbox was explictly turned off in a previous session */
105 if( SharedObject.getLocal("user_state").data['toolbox_visible'] == false) {
106 this.visible = false;
110 override protected function createChildren():void {
111 super.createChildren();
112 super.titleBar.addEventListener(MouseEvent.MOUSE_DOWN,handleDown);
115 public function updateSelectionUI():void {
116 dispatchEvent(new Event("updateSkin"));
117 dispatchEvent(new Event("updateAlpha"));
118 updateDirectionArrow();
121 private function handleDown(e:Event):void {
123 stage.addEventListener(MouseEvent.MOUSE_UP,handleUp);
126 private function handleUp(e:Event):void {
128 stage.removeEventListener(MouseEvent.MOUSE_UP,handleUp);
131 public function toggle():void {
132 this.visible=!this.visible;
133 var obj:SharedObject = SharedObject.getLocal("user_state");
134 obj.setProperty("toolbox_visible",this.visible);
138 // --------------------------------------------------------------------------------
139 // Enable/disable toolbox buttons
140 // (ideally we'd use CSS to set alpha in disabled state, but Flex's CSS
141 // capabilities aren't up to it)
143 [Bindable(event="updateSkin")]
144 public function canDo(op:String):Boolean {
145 if (controller.state.selectCount==0) return false;
148 case 'delete': return true;
149 case 'reverseDirection': return controller.state.hasSelectedWays();
150 case 'quadrilateralise': return (controller.state.hasSelectedAreas() || controller.state.hasSelectedWayNodesInAreas());
151 case 'straighten': return controller.state.hasSelectedUnclosedWays();
152 case 'circularise': return controller.state.hasSelectedAreas();
153 case 'split': return (controller.state is SelectedWayNode);
154 case 'parallelise': return (controller.state is SelectedWay);
155 case 'merge': return controller.state.hasAdjoiningWays();
160 [Bindable(event="updateAlpha")]
161 public function getAlpha(op:String):Number {
162 if (canDo(op)) { return 1; }
166 [Bindable(event="updateSkin")]
167 private function deleteToolTipText():String {
168 var entity:Entity=controller.state.firstSelected;
169 if (entity is Node) { return "Delete Node (Delete)"; }
170 if (entity is Way && Way(entity).isArea()) { return "Delete Area (Shift+Delete)"; }
171 if (entity is Way) { return "Delete Way (Shift+Delete)"; }
172 return "Delete Item"; // When nothing is selected
175 private function updateDirectionArrow():void {
176 if (controller.state is SelectedWay) {
177 var w:Way = Way(controller.state.firstSelected);
178 if (w) { // not entirely sure why this protection is necessary, but it appears so
180 // so Way.clockwise appears to give wrong results. Patches welcome, I guess, but for now...
181 w.clockwise? rotateButtonStack.selectedChild = antiClockwiseBox : rotateButtonStack.selectedChild = clockwiseBox;
183 rotateButtonStack.selectedChild = arrowBoxWrapper;
184 // reset and reposition back to the starting point relative to its parent
200 private function reverseClicked():void {
201 if(canDo('reverseDirection')) {
202 doReverseDirection();
206 // --------------------------------------------------------------------------------
207 // Individual toolbox actions
209 public function doDelete():void {
210 var undo:CompositeUndoableAction = new CompositeUndoableAction("Delete objects");
211 for each (var entity:Entity in controller.state.selection) {
212 if (entity is Node) { controller.connection.unregisterPOI(Node(entity)); }
213 entity.remove(undo.push);
215 MainUndoStack.getGlobalStack().addAction(undo);
217 if (controller.state is SelectedWayNode) {
218 controller.setState(new SelectedWay(SelectedWayNode(controller.state).selectedWay));
220 controller.setState(new NoSelection());
224 public function doMerge():void {
225 controller.setState(SelectedMultiple(controller.state).mergeWays());
228 public function doReverseDirection():void {
229 var undo:CompositeUndoableAction = new CompositeUndoableAction("Reverse direction of objects");
230 for each (var way:Way in controller.state.selectedWays) {
231 way.reverseNodes(undo.push);
233 MainUndoStack.getGlobalStack().addAction(undo);
236 public function doQuadrilateralise():void {
237 var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects right-angled");
238 for each (var way:Way in controller.state.selectedWays) {
239 Quadrilateralise.quadrilateralise(way, undo.push);
241 for each (var node:Node in controller.state.selectedNodes) {
242 for each (var parentWay:Way in node.parentWays) {
243 Quadrilateralise.quadrilateralise(parentWay, undo.push);
246 MainUndoStack.getGlobalStack().addAction(undo);
249 public function doStraighten():void {
250 var undo:CompositeUndoableAction = new CompositeUndoableAction("Straighten objects");
251 for each (var way:Way in controller.state.selectedWays) {
252 Straighten.straighten(way, controller.map, undo.push);
254 MainUndoStack.getGlobalStack().addAction(undo);
257 public function doCircularise():void {
258 var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects circular ");
259 for each (var way:Way in controller.state.selectedWays) {
260 Circularise.circularise(way, controller.map, undo.push);
262 MainUndoStack.getGlobalStack().addAction(undo);
265 public function doSplit():void {
266 if (controller.state is SelectedWayNode) {
267 controller.setState(SelectedWayNode(controller.state).splitWay());
271 public function doParallelise():void {
272 if (controller.state is SelectedWay) {
273 controller.setState(new SelectedParallelWay(Way(controller.state.firstSelected)));