cool vector background layer stuff!
authorRichard Fairhurst <richard@systemed.net>
Thu, 8 Jul 2010 21:11:02 +0000 (21:11 +0000)
committerRichard Fairhurst <richard@systemed.net>
Thu, 8 Jul 2010 21:11:02 +0000 (21:11 +0000)
TODO.txt
net/systemeD/halcyon/Map.as
net/systemeD/halcyon/vectorlayers/CustomVectorLayer.as
net/systemeD/halcyon/vectorlayers/VectorLayer.as
net/systemeD/potlatch2/BackgroundSelector.mxml
net/systemeD/potlatch2/VectorSourceDialog.mxml
net/systemeD/potlatch2/utils/GpxImporter.as
net/systemeD/potlatch2/utils/Importer.as
net/systemeD/potlatch2/utils/ShpImporter.as

index 433c5c6..271ef23 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -2,6 +2,10 @@ Potlatch 2: main outstanding issues
 -----------------------------------
 ** = required before P2 goes live
 
+
+** Slash and burn trace statements
+** Remove SimpleVectorLayer and move CustomVectorLayer into VectorLayer
+
 == Core geometry ==
 
 * P1-style J (join) / shift-J (unjoin)
@@ -13,7 +17,7 @@ Potlatch 2: main outstanding issues
 
 * TagTransform (cf http://wiki.openstreetmap.org/wiki/Osmosis/TagTransform)
 * Import from OSM (is this worth sharing with the XML API stuff?)
-* Load GPX from API
+* Load GPX from API (probably into a designated 'GPX' layer which is automatically created)
 
 == Saving ==
 
@@ -22,13 +26,13 @@ Potlatch 2: main outstanding issues
 
 == Tag editing ==
 
-** Turn restriction editor needs to lose the scrollbars
 * initialiseEditors is quite slow (typically 150ms)
 * If a select name is too long then, the select menu seems to give a horizontal scrollbar instead of the name of the item e.g. cuisine#Coffee Shop
 * Bug where the wrong feature is used, when an item that is dragged from the list when an POI has no icon.
 
 == UI ==
 
+** Clicking the menu on the SuperTabNavigator appears to boggle it completely
 * Escape should rewind the entity to how it was before the current ControllerState. (Record a position in the undo stack when exiting a ControllerState, and escape would rewind to that)
 * Potlatch 1-style "floaty warnings"
 * Custom imagery dialog fixes
@@ -64,7 +68,6 @@ Requested enhancements
 
 == Tag editing ==
 
-* Checkboxes, for example what you can recycle, or whether something is a bridge or tunnel
 * Ability to specify that a node should be a point in a way, for example for crossings
 * Ability to say that it's unlikely/impossible to have a way that is a bridge and a tunnel at the same time.
 * It would be useful to have fields that only allow numbers in a non-destructive way, for example for step_count or capacity.
@@ -72,6 +75,10 @@ Requested enhancements
 * The area of pois for dragging on to the map should have a search, with synonyms.
 * If you have both inputSets names and buildingAddress, and name= key is filled in then the basic tab will get both, surely only name should be shown and building name should be ignored e.g. cafes. [Actually this was an issue of addr: being missing from one of them, however this may still be a problem for other overlapping inputSets]
 
+== Turn restrictions ==
+
+* Splitting a way should have smart turn restriction behaviour - i.e. only retain the relation in that part of the way which joins the via point.
+
 == UI ==
 
 * Mouse wheel zooming
index 155c3e2..a27e112 100755 (executable)
@@ -71,7 +71,7 @@ package net.systemeD.halcyon {
                public var showall:Boolean=true;                                // show all objects, even if unstyled?
                
                public var connection:Connection;                               // server connection
-               public var vectorlayers:Array=[];                               // VectorLayer objects 
+               public var vectorlayers:Object={};                              // VectorLayer objects 
 
                public const TILESPRITE:uint=0;
                public const VECTORSPRITE:uint=1;
index fb73e84..d2b5a5e 100644 (file)
@@ -12,9 +12,14 @@ package net.systemeD.halcyon.vectorlayers {
 
        public class CustomVectorLayer extends VectorLayer {
 
-               public function CustomVectorLayer(n:String,m:Map,style:String) {
-                       super(n,m);
-                       paint.ruleset=new RuleSet(m.MINSCALE,m.MAXSCALE,paint.redraw);
+               public function CustomVectorLayer(name:String,map:Map,style:String) {
+                       super(name,map);
+                       this.style=style;
+                       redrawFromCSS(style);
+               }
+               
+               public function redrawFromCSS(style:String):void {
+                       paint.ruleset=new RuleSet(map.MINSCALE,map.MAXSCALE,paint.redraw);
                        paint.ruleset.loadFromCSS(style);
                }
        }
index 87c4713..0c1c70a 100644 (file)
@@ -10,6 +10,8 @@ package net.systemeD.halcyon.vectorlayers {
                public var map:Map;
                public var paint:MapPaint;                                              // sprites
                public var name:String;
+               public var url:String;
+               public var style:String='';
 
                public var ways:Object=new Object();                    // geodata
                public var nodes:Object=new Object();                   //  |
@@ -81,6 +83,12 @@ package net.systemeD.halcyon.vectorlayers {
                        }
                        return newWay;
                }
+               
+               public function blank():void {
+                       for each (var node:Node in nodes) { paint.deleteNodeUI(node); }
+                       for each (var way:Way in ways) { paint.deleteWayUI(way); }
+                       relations={}; nodes={}; ways={};
+               }
 
        }
 }
index 3e01311..d041601 100644 (file)
@@ -12,7 +12,7 @@
 
        <mx:HBox>
        <mx:Button label="Edit..." click="new BackgroundDialog().init('Background imagery',background,Application.application.theController.imagery);" />
-       <mx:Button label="Vector file" click="new VectorSourceDialog().init();" />
+       <mx:Button label="Vector file..." click="new VectorSourceDialog().init();" />
        </mx:HBox>
 
        <mx:Script><![CDATA[
index 941a6aa..8edee5f 100644 (file)
@@ -3,8 +3,55 @@
         xmlns:mx="http://www.adobe.com/2006/mxml" 
         layout="vertical" showCloseButton="true"
         horizontalAlign="center" title="Load vector file"
-        width="350" height="250" verticalGap="0">
+        width="400" height="350" verticalGap="0">
+
+       <mx:DataGrid editable="true" width="100%" height="100%" id="dataGrid" 
+               dataProvider="{vectorLayers}" itemEditEnd="dataEdited(event)">
+           <mx:columns>
+               <mx:DataGridColumn editable="false" dataField="visible" headerText="Show" width="45">
+                               <mx:itemRenderer>
+                                       <mx:Component>
+                                               <mx:CheckBox selectedField="isSelected"
+                                                                        click="data.isSelected=!data.isSelected; this.parent.parent.dispatchEvent(new Event('visibility_changed'));" 
+                                                                        paddingLeft="5"/>
+                                       </mx:Component>
+                               </mx:itemRenderer>
+                       </mx:DataGridColumn>
+               <mx:DataGridColumn editable="true"  dataField="name"  headerText="Name"/>
+               <mx:DataGridColumn editable="false" dataField="url"   headerText="URL"/>
+               <mx:DataGridColumn editable="false" dataField="style" headerText="Style">
+                               <mx:itemRenderer>
+                                       <mx:Component>
+                                       <mx:ComboBox
+                                                       selectedItem="{outerDocument.whichStyle(data)}"
+                                               change="outerDocument.styleEdited(data.name,selectedItem.data)"
+                                               dataProvider="{outerDocument.styles}" />
+                                       </mx:Component>
+                               </mx:itemRenderer>
+                       </mx:DataGridColumn>
+           </mx:columns>
+       </mx:DataGrid>
+       <mx:HBox horizontalAlign="right" width="100%">
+               <mx:LinkButton label="Delete" click="removeVectorLayer()" enabled="{dataGrid.selectedItem != null? true : false}"/>
+       </mx:HBox>
+
+       <mx:VBox width="100%" paddingTop="10">
+               <mx:Label htmlText="&lt;b&gt;Add new vector layer&lt;/b&gt;" />
+               <mx:HBox>
+                       <mx:RadioButtonGroup id="filetype" />
+                       <mx:RadioButton width="100%" groupName="{filetype}" value="gpx" id="gpx" label="GPX" selected="true" />
+                       <mx:RadioButton width="100%" groupName="{filetype}" value="shp" id="shp" label="Shapefile" />
+                       <mx:CheckBox width="100%" label="Simplify paths" selected="true" id="simplify" />
+               </mx:HBox>
+               <mx:HBox>
+                       <mx:Text text="URL:"/>
+                       <mx:TextInput width="100%" id="src" text="" />
+                       <mx:Button label="Load" click="loadFiles(src.text, shp.selected?'shp':'gpx', simplify.selected);" enabled="{src.text == '' ? false : true}"/>
+               </mx:HBox>
+       </mx:VBox>
+
   <mx:Script><![CDATA[
+
        import net.systemeD.halcyon.Map;
        import net.systemeD.halcyon.Globals;
        import net.systemeD.halcyon.vectorlayers.*;
        import net.systemeD.potlatch2.utils.GpxImporter;
        import net.systemeD.potlatch2.utils.ShpImporter;
     import mx.managers.PopUpManager;
+    import mx.events.DataGridEvent;
     import mx.events.CloseEvent;
     import mx.core.Application;
+       import mx.collections.ArrayCollection;
+       import mx.controls.Alert;
+
+       private var map:Map;
+
+       public function styleEdited(name:String,stylesheet:String):void {
+               map.vectorlayers[name].style=stylesheet;
+               map.vectorlayers[name].redrawFromCSS(stylesheet)
+       }
+
 
     public function init():void {
         PopUpManager.addPopUp(this, Application(Application.application), true);
         PopUpManager.centerPopUp(this);
         this.addEventListener(CloseEvent.CLOSE, vectorDialog_close);
+               dataGrid.addEventListener("visibility_changed", toggleVisibility);
+               map = Globals.vars.root;
+               dispatchEvent(new Event("layers_changed"));
     }
+
+       public function whichStyle(item:Object):Object {
+               for each (var style:Object in styles) {
+                       if (style.data==item.style) { return style; }
+               }
+               return {};
+       }
+
+       [Bindable(event="bogus")]
+       public function get styles():ArrayCollection {
+               return new ArrayCollection(Application.application.theController.stylesheets);
+       }
+
+       [Bindable(event="layers_changed")]
+       private function get vectorLayers():Array {
+               var v:Array=[];
+               for (var a:String in map.vectorlayers) {
+                       var vl:VectorLayer=map.vectorlayers[a];
+                       v.push( { name:a, visible:vl.paint.visible, url:vl.url, style:vl.style } );
+               }
+               return v;
+       }
+       
+       private function toggleVisibility(event:Event):void {
+               map.vectorlayers[dataGrid.selectedItem.name].paint.visible = !map.vectorlayers[dataGrid.selectedItem.name].paint.visible;
+       }
+       
+       private function dataEdited(event:DataGridEvent):void {
+               if (event.dataField=='name') {
+                       // Rename field
+                       var a:String=dataGrid.selectedItem.name;
+                       var b:String=dataGrid.itemEditorInstance['text'];       // this is, unbelievably, how you get data within an itemEditEnd event
+                       if (a==b || map.vectorlayers[b]) {
+                               event.preventDefault();
+                       } else {
+                               map.vectorlayers[b]=map.vectorlayers[a];
+                               delete map.vectorlayers[a];
+                       }
+                       dispatchEvent(new Event("layers_changed"));
+               }
+       }
+
+       private function removeVectorLayer():void {
+               var a:String=dataGrid.selectedItem.name;
+               map.vectorlayers[a].blank();
+               delete map.vectorlayers[a];
+               dispatchEvent(new Event("layers_changed"));
+       }
     
     private function vectorDialog_close(evt:CloseEvent):void {
         PopUpManager.removePopUp(this);
     }
 
        private function loadFiles(url:String,filetype:String,simplify:Boolean):void {
-        PopUpManager.removePopUp(this);
-               var theMap:Map = Globals.vars.root;
-               var vectorlayer:CustomVectorLayer=new CustomVectorLayer(url,theMap,"potlatch.css");
-               theMap.vectorlayers.push(vectorlayer);
-               theMap.vectorbg.addChild(vectorlayer.paint);
+               var vectorlayer:CustomVectorLayer=new CustomVectorLayer(url,map,"potlatch.css");
+               vectorlayer.url=url;
+               map.vectorlayers[url]=vectorlayer;
+               map.vectorbg.addChild(vectorlayer.paint);
 
                if (filetype=='gpx') {
-                       var gpx:GpxImporter=new GpxImporter(vectorlayer, vectorlayer.paint, [url], simplify);
+                       var gpx:GpxImporter=new GpxImporter(vectorlayer, vectorlayer.paint, [url], filesLoaded, simplify);
                } else {
                        var re:RegExp=/.shp$/i; url=url.replace(re,'');
                        var shp:ShpImporter=new ShpImporter(vectorlayer,
                                                            vectorlayer.paint,
-                                                           [url+".shp",url+".shx",url+".dbf"], simplify);
+                                                           [url+".shp",url+".shx",url+".dbf"], filesLoaded, simplify);
+               }
+       }
+       
+       public function filesLoaded(success:Boolean,message:String=null):void {
+               if (success) {
+                       dispatchEvent(new Event("layers_changed"));
+               } else {
+                       Alert.show(message, 'Error', mx.controls.Alert.OK);
                }
        }
 
               ]]>
   </mx:Script>
-  <mx:Text>
-    <mx:text>
-      Input the URL of a file to import.
-    </mx:text>
-  </mx:Text>
-  <mx:TextInput width="100%" id="src" text="" />
-  <mx:RadioButtonGroup id="filetype" />
-  <mx:RadioButton width="100%" groupName="{filetype}" value="shp" id="shp" label="Shapefile" selected="true" />
-  <mx:RadioButton width="100%" groupName="{filetype}" value="gpx" id="gpx" label="GPX" />
-  <mx:CheckBox width="100%" label="Simplify paths" selected="true" id="simplify" />
-  <mx:ControlBar>
-    <mx:Spacer width="100%"/>
-    <mx:Button label="Load" click="loadFiles(src.text, shp.selected?'shp':'gpx', simplify.selected);" enabled="{src.text == '' ? false : true}"/>
-  </mx:ControlBar>
-
 </mx:TitleWindow>
index a125c30..874e289 100644 (file)
@@ -8,8 +8,8 @@ package net.systemeD.potlatch2.utils {
 
        public class GpxImporter extends Importer {
 
-               public function GpxImporter(container:*, paint:MapPaint, filenames:Array, simplify:Boolean=false) {
-                       super(container,paint,filenames,simplify);
+               public function GpxImporter(container:*, paint:MapPaint, filenames:Array, callback:Function=null, simplify:Boolean=false) {
+                       super(container,paint,filenames,callback,simplify);
                }
 
                override protected function doImport(): void {
@@ -19,14 +19,11 @@ package net.systemeD.potlatch2.utils {
                        var file:XML=new XML(files[0]);
 
                        for each (var trk:XML in file.child("trk")) {
-                               trace("trk");
                                for each (var trkseg:XML in trk.child("trkseg")) {
-                                       trace("trkseg");
                                        var way:Way;
                                        var nodestring:Array=[];
                                        for each (var trkpt:XML in trkseg.child("trkpt")) {
                                                nodestring.push(container.createNode({}, trkpt.@lat, trkpt.@lon));
-                                               trace("adding point at "+trkpt.@lat+","+trkpt.@lon);
                                        }
                                        if (nodestring.length>0) {
                                                way=container.createWay({}, nodestring);
index 1caca65..6f4f474 100644 (file)
@@ -20,13 +20,14 @@ package net.systemeD.potlatch2.utils {
                protected var callback:Function;
                protected var simplify:Boolean;
 
-               public function Importer(container:*, paint:MapPaint, filenames:Array, simplify:Boolean) {
+               public function Importer(container:*, paint:MapPaint, filenames:Array, callback:Function, simplify:Boolean) {
                        Globals.vars.root.addDebug("starting importer"); 
                        Globals.vars.root.addDebug("container is "+container);
                        Globals.vars.root.addDebug("paint is "+paint);
                        this.container = container;
                        this.paint = paint;
                        this.filenames=filenames;
+                       this.callback=callback;
                        this.simplify=simplify;
 
                        var sp:uint=0;
@@ -36,10 +37,11 @@ package net.systemeD.potlatch2.utils {
                                var loader:ExtendedURLLoader = new ExtendedURLLoader();
                                loader.info['file']=sp;
                                loader.dataFormat=URLLoaderDataFormat.BINARY;
-                               loader.addEventListener(Event.COMPLETE,                                         fileLoaded);
-                               loader.addEventListener(HTTPStatusEvent.HTTP_STATUS,            httpStatusHandler);
-                               loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,      securityErrorHandler);
-                               loader.addEventListener(IOErrorEvent.IO_ERROR,                          ioErrorHandler);
+                               loader.addEventListener(Event.COMPLETE,fileLoaded);
+                               if (callback!=null) {
+                                       loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,      securityErrorHandler);
+                                       loader.addEventListener(IOErrorEvent.IO_ERROR,                          ioErrorHandler);
+                               }
                                loader.load(new URLRequest(fn));
                                sp++;
                        }
@@ -52,15 +54,15 @@ package net.systemeD.potlatch2.utils {
                        if (filesloaded==filenames.length) { 
                                doImport();
                                paint.updateEntityUIs(container.getObjectsByBbox(paint.map.edge_l, paint.map.edge_r, paint.map.edge_t, paint.map.edge_b), false, false);
+                               if (callback!=null) { callback(true); }
                        }
                }
                
                protected function doImport():void {
                }
 
-               protected function httpStatusHandler( event:HTTPStatusEvent ):void { Globals.vars.root.addDebug("httpstatusevent"); }
-               protected function securityErrorHandler( event:SecurityErrorEvent ):void { Globals.vars.root.addDebug("securityerrorevent"); }
-               protected function ioErrorHandler( event:IOErrorEvent ):void { Globals.vars.root.addDebug("ioerrorevent"); }
+               protected function securityErrorHandler( event:SecurityErrorEvent ):void { callback(false,"You don't have permission to open that file."); }
+               protected function ioErrorHandler( event:IOErrorEvent ):void { callback(false,"The file could not be loaded."); }
 
        }
 }
index 9fc32ca..bc3e742 100644 (file)
@@ -10,8 +10,8 @@ package net.systemeD.potlatch2.utils {
 
        public class ShpImporter extends Importer {
 
-               public function ShpImporter(container:*, paint:MapPaint, filenames:Array, simplify:Boolean=false) {
-                       super(container,paint,filenames,simplify);
+               public function ShpImporter(container:*, paint:MapPaint, filenames:Array, callback:Function=null, simplify:Boolean=false) {
+                       super(container,paint,filenames,callback,simplify);
                }
 
                override protected function doImport(): void {