make Toolbox act on multiple selections (and light up accordingly)
authorRichard Fairhurst <richard@systemed.net>
Sat, 13 Nov 2010 11:16:17 +0000 (11:16 +0000)
committerRichard Fairhurst <richard@systemed.net>
Sat, 13 Nov 2010 11:16:17 +0000 (11:16 +0000)
net/systemeD/potlatch2/Toolbox.mxml
net/systemeD/potlatch2/controller/ControllerState.as
net/systemeD/potlatch2/controller/SelectedMultiple.as
net/systemeD/potlatch2/controller/SelectedWay.as
net/systemeD/potlatch2/tools/Circularise.as
net/systemeD/potlatch2/tools/Quadrilateralise.as
net/systemeD/potlatch2/tools/Straighten.as

index 5482251..eb8ab09 100644 (file)
@@ -8,46 +8,46 @@
        paddingLeft="4" paddingTop="4" layout="absolute" >
 
                <mx:Image data="@Embed('../../../embedded/close_small.png')"
-                   includeInLayout="false" id="toolboxClose" click="toggle();" 
-                   y="-6" x="205" />
+                       includeInLayout="false" id="toolboxClose" click="toggle();" 
+                       y="-6" x="205" />
 
-        <mx:Button icon="@Embed('../../../embedded/delete.svg')"
+               <mx:Button icon="@Embed('../../../embedded/delete.svg')"
                        click='doDelete();' 
                        enabled="{canDo('delete')}" 
                        alpha="{getAlpha('delete')}" 
                        toolTip="{deleteToolTipText()}" 
                        width="28" height="28" textAlign="left" y="4" x="6" paddingLeft="6" paddingRight="0" />
-        <mx:Button icon="@Embed('../../../embedded/direction.svg')" 
-            click='doReverseDirection();'
+               <mx:Button icon="@Embed('../../../embedded/direction.svg')" 
+                       click='doReverseDirection();'
                        enabled="{canDo('reverseDirection')}" 
                        alpha="{getAlpha('reverseDirection')}" 
                        toolTip="Reverse direction (V)" 
                        width="28" height="28" textAlign="left" y="4" x="36" paddingLeft="8" paddingRight="0" />
-        <mx:Button icon="@Embed('../../../embedded/cut.svg')" 
-               click='doSplit();'
+               <mx:Button icon="@Embed('../../../embedded/cut.svg')" 
+                          click='doSplit();'
                        enabled="{canDo('split')}" 
                        alpha="{getAlpha('split')}" 
                        toolTip="Split way (X)" 
                        width="28" height="28" textAlign="left" y="4" x="66" paddingLeft="8" paddingRight="0" />
-        <mx:Button icon="@Embed('../../../embedded/straighten.svg')" 
+               <mx:Button icon="@Embed('../../../embedded/straighten.svg')" 
                        click='doStraighten();' 
                        enabled="{canDo('straighten')}" 
                        alpha="{getAlpha('straighten')}" 
                        toolTip="Straighten way" 
                        width="28" height="28" textAlign="left" y="4" x="96" paddingLeft="5" paddingRight="0" />
-        <mx:Button icon="@Embed('../../../embedded/circle.svg')" 
+               <mx:Button icon="@Embed('../../../embedded/circle.svg')" 
                        click='doCircularise();' 
                        enabled="{canDo('circularise')}" 
                        alpha="{getAlpha('circularise')}" 
                        toolTip="Make circular" 
                        width="28" height="28" textAlign="left" y="4" x="126" paddingLeft="4" paddingRight="0" />
-        <mx:Button icon="@Embed('../../../embedded/quadrilateralise.svg')" 
+               <mx:Button icon="@Embed('../../../embedded/quadrilateralise.svg')" 
                        click='doQuadrilateralise();' 
                        enabled="{canDo('quadrilateralise')}" 
                        alpha="{getAlpha('quadrilateralise')}" 
                        toolTip="Make right-angled" 
                        width="28" height="28" textAlign="left" y="4" x="156" paddingLeft="6" paddingRight="0" />
-        <mx:Button icon="@Embed('../../../embedded/parallel.svg')" 
+               <mx:Button icon="@Embed('../../../embedded/parallel.svg')" 
                        click='doParallelise();' 
                        enabled="{canDo('parallelise')}" 
                        alpha="{getAlpha('parallelise')}" 
                import flash.events.Event;
                import flash.events.MouseEvent;
                import net.systemeD.halcyon.connection.*;
-           import net.systemeD.potlatch2.controller.*;
-           import net.systemeD.potlatch2.tools.*;
+               import net.systemeD.potlatch2.controller.*;
+               import net.systemeD.potlatch2.tools.*;
 
                private var controller:EditController;
 
                public function init(controller:EditController):void {
                        this.controller=controller;
-            /* check if the toolbox was explictly turned off in a previous session */
-            if( SharedObject.getLocal("user_state").data['toolbox_visible'] == false) {
-              this.visible = false;
-            }
+                       /* check if the toolbox was explictly turned off in a previous session */
+                       if( SharedObject.getLocal("user_state").data['toolbox_visible'] == false) {
+                         this.visible = false;
+                       }
                }
 
                override protected function createChildren():void {
                
                public function toggle():void {
                        this.visible=!this.visible;
-            var obj:SharedObject = SharedObject.getLocal("user_state");
-            obj.setProperty("toolbox_visible",this.visible);
-            obj.flush();
+                       var obj:SharedObject = SharedObject.getLocal("user_state");
+                       obj.setProperty("toolbox_visible",this.visible);
+                       obj.flush();
                }
                
                // --------------------------------------------------------------------------------
                // Enable/disable toolbox buttons
                // (ideally we'd use CSS to set alpha in disabled state, but Flex's CSS
-               //  capabilities aren't up to it)
+               //      capabilities aren't up to it)
                
-        [Bindable(event="updateSkin")]
+               [Bindable(event="updateSkin")]
                public function canDo(op:String):Boolean {
                        if (controller.state.selectCount==0) return false;
 
-                       var entity:Entity=controller.state.firstSelected;
                        switch (op) {
                                case 'delete':                          return true;
-                               case 'reverseDirection':        return (entity is Way);
-                               case 'quadrilateralise':        return (entity is Way && Way(entity).isArea());
-                               case 'straighten':                      return (entity is Way && !Way(entity).isArea());
-                               case 'circularise':                     return (entity is Way && Way(entity).isArea());
+                               case 'reverseDirection':        return controller.state.hasSelectedWays();
+                               case 'quadrilateralise':        return controller.state.hasSelectedAreas();
+                               case 'straighten':                      return controller.state.hasSelectedUnclosedWays();
+                               case 'circularise':                     return controller.state.hasSelectedAreas();
                                case 'split':                           return (controller.state is SelectedWayNode);
-                               case 'parallelise':                     return (entity is Way);
+                               case 'parallelise':                     return (controller.state is SelectedWay);
                        }
                        return false;
                }
 
-        [Bindable(event="updateAlpha")]
+               [Bindable(event="updateAlpha")]
                public function getAlpha(op:String):Number {
                        if (canDo(op)) { return 1; }
                        return 0.5;
                }
 
-        [Bindable(event="updateSkin")]
-        private function deleteToolTipText():String {
+               [Bindable(event="updateSkin")]
+               private function deleteToolTipText():String {
                        var entity:Entity=controller.state.firstSelected;
-            if (entity is Node) { return "Delete Node (Delete)"; }
-            if (entity is Way && Way(entity).isArea()) { return "Delete Area (Shift+Delete)"; }
-            if (entity is Way) { return "Delete Way (Shift+Delete)"; }
-            return "Delete Item"; // When nothing is selected
-        }
+                       if (entity is Node) { return "Delete Node (Delete)"; }
+                       if (entity is Way && Way(entity).isArea()) { return "Delete Area (Shift+Delete)"; }
+                       if (entity is Way) { return "Delete Way (Shift+Delete)"; }
+                       return "Delete Item"; // When nothing is selected
+               }
 
                // --------------------------------------------------------------------------------
                // Individual toolbox actions
 
                public function doDelete():void {
-            var undo:CompositeUndoableAction = new CompositeUndoableAction("Delete objects");
+                       var undo:CompositeUndoableAction = new CompositeUndoableAction("Delete objects");
                        for each (var entity:Entity in controller.state.selection) {
                                if (entity is Node) { controller.connection.unregisterPOI(Node(entity)); }
                                entity.remove(undo.push);
                        }
-            MainUndoStack.getGlobalStack().addAction(undo);
+                       MainUndoStack.getGlobalStack().addAction(undo);
 
                        if (controller.state is SelectedWayNode) {
                                controller.setState(new SelectedWay(SelectedWayNode(controller.state).selectedWay));
                        }
                }
 
-        public function doReverseDirection():void {
-                       if (controller.state is SelectedWay) {
-                Way(controller.state.firstSelected).reverseNodes(MainUndoStack.getGlobalStack().addAction);
-            }
-        }
+               public function doReverseDirection():void {
+                       var undo:CompositeUndoableAction = new CompositeUndoableAction("Reverse direction of objects");
+                       for each (var way:Way in controller.state.selectedWays) {
+                               way.reverseNodes(undo.push);
+                       }
+                       MainUndoStack.getGlobalStack().addAction(undo);
+               }
 
                public function doQuadrilateralise():void {
-                       if (controller.state is SelectedWay) {
-                               Quadrilateralise.quadrilateralise(Way(controller.state.firstSelected));
+                       var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects right-angled");
+                       for each (var way:Way in controller.state.selectedWays) {
+                               Quadrilateralise.quadrilateralise(way, undo.push);
                        }
+                       MainUndoStack.getGlobalStack().addAction(undo);
                }
 
                public function doStraighten():void {
-                       if (controller.state is SelectedWay) {
-                               Straighten.straighten(Way(controller.state.firstSelected),controller.map);
+                       var undo:CompositeUndoableAction = new CompositeUndoableAction("Straighten objects");
+                       for each (var way:Way in controller.state.selectedWays) {
+                               Straighten.straighten(way, controller.map, undo.push);
                        }
+                       MainUndoStack.getGlobalStack().addAction(undo);
                }
 
                public function doCircularise():void {
-                       if (controller.state is SelectedWay) {
-                               Circularise.circularise(Way(controller.state.firstSelected),controller.map);
+                       var undo:CompositeUndoableAction = new CompositeUndoableAction("Make objects circular ");
+                       for each (var way:Way in controller.state.selectedWays) {
+                               Circularise.circularise(way, controller.map, undo.push);
                        }
+                       MainUndoStack.getGlobalStack().addAction(undo);
                }
 
                public function doSplit():void {
                }
 
 
-    ]]>
+       ]]>
 </mx:Script>   
 </mx:Panel>
index 4283728..28ae847 100644 (file)
@@ -172,6 +172,35 @@ package net.systemeD.potlatch2.controller {
                        return null;
                }
                
+               public function get selectedWays():Array {
+                       var selectedWays:Array=[];
+                       for each (var item:Entity in _selection) {
+                               if (item is Way) { selectedWays.push(item); }
+                       }
+                       return selectedWays;
+               }
+               
+               public function hasSelectedWays():Boolean {
+                       for each (var item:Entity in _selection) {
+                               if (item is Way) { return true; }
+                       }
+                       return false;
+               }
+               
+               public function hasSelectedAreas():Boolean {
+                       for each (var item:Entity in _selection) {
+                               if (item is Way && Way(item).isArea()) { return true; }
+                       }
+                       return false;
+               }
+               
+               public function hasSelectedUnclosedWays():Boolean {
+                       for each (var item:Entity in _selection) {
+                               if (item is Way && !Way(item).isArea()) { return true; }
+                       }
+                       return false;
+               }
+                       
                // Selection setters
                
                public function set selection(items:Array):void {
index 84b9224..45cd47b 100644 (file)
@@ -41,6 +41,11 @@ package net.systemeD.potlatch2.controller {
                        return cs ? cs : this;
                }
 
+               override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
+                       var cs:ControllerState = sharedKeyboardEvents(event);
+                       return cs ? cs : this;
+               }
+
                override public function enterState():void {
                        selection=initSelection.concat();
                        for each (var entity:Entity in selection) {
index fc2eeb2..b753843 100644 (file)
@@ -4,7 +4,6 @@ package net.systemeD.potlatch2.controller {
        import flash.ui.Keyboard;
     import net.systemeD.potlatch2.EditController;
     import net.systemeD.potlatch2.tools.Parallelise;
-    import net.systemeD.potlatch2.tools.Quadrilateralise;
     import net.systemeD.potlatch2.tools.Simplify;
     import net.systemeD.halcyon.connection.*;
        import net.systemeD.halcyon.MapPaint;
@@ -66,7 +65,6 @@ package net.systemeD.potlatch2.controller {
                override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
                        switch (event.keyCode) {
                                case 80:                                        return new SelectedParallelWay(firstSelected as Way);
-                               case 81:                                        Quadrilateralise.quadrilateralise(firstSelected as Way); return this;
                                case 82:                                        repeatTags(firstSelected); return this;
                 case 86:                    Way(firstSelected).reverseNodes(MainUndoStack.getGlobalStack().addAction); return this;
                 case 89:                    Simplify.simplify(firstSelected as Way, controller.map, true); return this;         
index c02999d..958a57c 100644 (file)
@@ -7,18 +7,19 @@ package net.systemeD.potlatch2.tools {
 
        public class Circularise {
 
-               public static function circularise(way:Way,map:Map):void {
+               public static function circularise(way:Way,map:Map,performAction:Function):void {
                        if (way.length<4) { return; }
 
                        var a:Node=way.getNode(0);
                        var b:Node=way.getNode(way.length-1);
                        if (a!=b) { return; }
 
-            new Circularise(way, map).run();
+            new Circularise(way, map, performAction).run();
         }
         
         private var way:Way;
         private var map:Map;
+               private var performAction:Function;
         
         // centre
         private var cx:Number=0;
@@ -34,9 +35,10 @@ package net.systemeD.potlatch2.tools {
         private var lats:Array = [];
                private var lons:Array = [];
 
-        function Circularise(way:Way, map:Map) {
+        function Circularise(way:Way, map:Map, performAction:Function) {
             this.way = way;
             this.map = map;
+                       this.performAction = performAction;
         }
         
         private function run():void {
@@ -93,7 +95,7 @@ package net.systemeD.potlatch2.tools {
                                i++;
                        }
 
-                       MainUndoStack.getGlobalStack().addAction(action);
+                       performAction(action);
                }
 
         private function calculateCentre():void {
index 1ac7ed6..f87b0ce 100644 (file)
@@ -13,13 +13,13 @@ package net.systemeD.potlatch2.tools {
      * thought it was successful and false if it failed. If it fails it does not
      * modify the way.
      */
-    public static function quadrilateralise(way:Way):Boolean {
+    public static function quadrilateralise(way:Way,performAction:Function):Boolean {
       // needs a closed way to work properly.
       if (!way.isArea()) {
        return false;
       }
 
-      var functor:Quadrilateralise = new Quadrilateralise(way);
+      var functor:Quadrilateralise = new Quadrilateralise(way,performAction);
       var score:Number = functor.goodness;
       for (var i:uint = 0; i < NUM_STEPS; ++i) {
        functor.step();
@@ -40,10 +40,12 @@ package net.systemeD.potlatch2.tools {
 
     private var way:Way;
     private var points:Array;
+    private var performAction:Function;
     
     // i wanted this to be private, but AS3 doesn't allow that. so please don't use it outside this package!
-    public function Quadrilateralise(way_:Way) {
+    public function Quadrilateralise(way_:Way, performAction_:Function) {
       way = way_;
+      performAction = performAction_;
       points = way.sliceNodes(0, way.length - 1).map(function (n:Node, i:int, a:Array) : Point {
          return new Point(n.lon, n.latp);
        });
@@ -116,7 +118,7 @@ package net.systemeD.potlatch2.tools {
       for (var i:uint = 0; i < points.length; ++i) {
         way.getNode(i).setLonLatp( points[i].x, points[i].y, moveAction.push);
       }
-      MainUndoStack.getGlobalStack().addAction( moveAction );
+      performAction(moveAction);
     }
   }
 }
index 7cf40e0..ea798ea 100644 (file)
@@ -7,7 +7,7 @@ package net.systemeD.potlatch2.tools {
 
        public class Straighten {
 
-               public static function straighten(way:Way,map:Map):void {
+               public static function straighten(way:Way,map:Map,performAction:Function):void {
                        if (way.length<3) { return; }
 
                        var a:Node=way.getNode(0);
@@ -41,7 +41,7 @@ package net.systemeD.potlatch2.tools {
                        }
                        for each (n in todelete) { n.remove(action.push); }
                        
-                       MainUndoStack.getGlobalStack().addAction(action);
+                       performAction(action);
                }
        }
 }