Merge remote-tracking branch 'gravitystorm/history'
authorRichard Fairhurst <richard@systemeD.net>
Sun, 25 Mar 2012 15:52:18 +0000 (16:52 +0100)
committerRichard Fairhurst <richard@systemeD.net>
Sun, 25 Mar 2012 15:52:18 +0000 (16:52 +0100)
48 files changed:
build.xml
l10n/map/LocalizationMap.mxml
lib/YahooMap-0.9.4.swc [deleted file]
net/systemeD/halcyon/DebugURLRequest.as [deleted file]
net/systemeD/halcyon/FileBank.as [new file with mode: 0755]
net/systemeD/halcyon/ImageBank.as [deleted file]
net/systemeD/halcyon/MarkerUI.as
net/systemeD/halcyon/NestedXMLLoader.as
net/systemeD/halcyon/NodeUI.as
net/systemeD/halcyon/WayUI.as
net/systemeD/halcyon/connection/Trace.as
net/systemeD/halcyon/connection/XMLConnection.as
net/systemeD/halcyon/styleparser/NestedCSSLoader.as
net/systemeD/halcyon/styleparser/RuleSet.as
net/systemeD/halcyon/styleparser/StyleChooser.as
net/systemeD/potlatch2/BackgroundSelector.mxml
net/systemeD/potlatch2/CustomLocaleCommand.as [new file with mode: 0644]
net/systemeD/potlatch2/Preloader.as
net/systemeD/potlatch2/StyleSelector.mxml
net/systemeD/potlatch2/TagGrid.mxml
net/systemeD/potlatch2/TagViewer.mxml
net/systemeD/potlatch2/Yahoo.as [deleted file]
net/systemeD/potlatch2/collections/Imagery.as
net/systemeD/potlatch2/collections/Stylesheets.as
net/systemeD/potlatch2/collections/VectorBackgrounds.as
net/systemeD/potlatch2/controller/DrawWay.as
net/systemeD/potlatch2/controller/SelectedParallelWay.as
net/systemeD/potlatch2/dialogs/BackgroundDialog.mxml [moved from net/systemeD/potlatch2/BackgroundDialog.mxml with 87% similarity]
net/systemeD/potlatch2/dialogs/MyGpxDialog.mxml [moved from net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml with 52% similarity]
net/systemeD/potlatch2/dialogs/OptionsDialog.mxml [moved from net/systemeD/potlatch2/options/OptionsDialog.mxml with 100% similarity]
net/systemeD/potlatch2/dialogs/VectorSourceDialog.mxml [moved from net/systemeD/potlatch2/VectorSourceDialog.mxml with 52% similarity]
net/systemeD/potlatch2/history/HistoryDialog.mxml
net/systemeD/potlatch2/mapfeatures/Feature.as
net/systemeD/potlatch2/mapfeatures/MapFeatures.as
net/systemeD/potlatch2/mapfeatures/editors/Choice.as
net/systemeD/potlatch2/mapfeatures/editors/ChoiceEditorFactory.as
net/systemeD/potlatch2/mapfeatures/editors/RestrictionRenderer.mxml
net/systemeD/potlatch2/panels/DragAndDropPanel.mxml [new file with mode: 0644]
net/systemeD/potlatch2/save/OAuthPanel.mxml
net/systemeD/potlatch2/save/SaveManager.as
net/systemeD/potlatch2/utils/CachedDataLoader.as [deleted file]
net/systemeD/potlatch2/utils/GpxImporter.as
net/systemeD/potlatch2/utils/Importer.as
net/systemeD/potlatch2/utils/KmlImporter.as
net/systemeD/potlatch2/utils/OsmImporter.as
net/systemeD/potlatch2/utils/ShpImporter.as
potlatch2.mxml
resources/map_features.xml

index 7b9ec07688e90108f2076f03ff1a321af5fce6b4..66c43c3eebf79b21f0f2235f381269de6a4fcf37 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -68,6 +68,7 @@
       <arg line="-external-library-path=lib/"/>
       <arg line="-external-library-path=${FLEX_HOME}/frameworks/libs/"/>
       <arg line="-external-library-path=${FLEX_HOME}/frameworks/libs/player/10.2/"/>
+      <arg line="-compiler.theme ${flexlib}/themes/Halo/halo.swc"/>
       <arg line="-lenient"/>
       <arg line="-target-player=10.2.0"/>
       <arg line="-exclude-classes=${org_classes},${it_classes},${hxasm_classes},${com_classes}"/>
index 3b8d9322b4187c524e4c73698061d8ca1ce4011f..c96738c0f9a0e37b31cbc97184ba345c61401bb6 100644 (file)
@@ -7,7 +7,7 @@
   <!-- Support for Locale ResourceBundle changes -->
   <mx:Script>
     <![CDATA[
-      import org.babelfx.commands.ExternalLocaleCommand;
+      import net.systemeD.potlatch2.CustomLocaleCommand;
       import org.babelfx.events.LocaleEvent;
       import mx.resources.ResourceManager;
       import mx.resources.IResourceManager;
@@ -22,7 +22,7 @@
       import net.systemeD.potlatch2.save.OAuthPanel;
       import net.systemeD.potlatch2.save.SaveDialog;
 
-      import net.systemeD.potlatch2.options.OptionsDialog;
+      import net.systemeD.potlatch2.dialogs.OptionsDialog;
 
       private function onLocaleChanged(event:Event):void {
           var rMngr : IResourceManager = ResourceManager.getInstance();
@@ -46,9 +46,9 @@
   </mx:Script>
 
   <commandFactory>
-    <factory:ClassFactory generator="{ExternalLocaleCommand}">
+    <factory:ClassFactory generator="{CustomLocaleCommand}">
       <factory:properties>
-        <mx:Object externalPath="locales/\{0\}.swf"/>
+        <mx:Object defaultExternalPath="locales/\{0\}.swf"/>
       </factory:properties>
     </factory:ClassFactory>
   </commandFactory>
diff --git a/lib/YahooMap-0.9.4.swc b/lib/YahooMap-0.9.4.swc
deleted file mode 100644 (file)
index ccecc5f..0000000
Binary files a/lib/YahooMap-0.9.4.swc and /dev/null differ
diff --git a/net/systemeD/halcyon/DebugURLRequest.as b/net/systemeD/halcyon/DebugURLRequest.as
deleted file mode 100644 (file)
index 7bbf018..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package net.systemeD.halcyon {
-
-       import flash.net.URLRequest;
-       import flash.net.URLRequestMethod;
-       import flash.system.Capabilities;
-       import net.systemeD.halcyon.Globals;
-
-    /**
-    * If nocache has been set to 'true' via FlashVars, this will make the URLRequest using
-    * POST rather than GET - thereby preventing FP from caching it.
-    *
-    * <p>Sadly we can't just subclass URLRequest, which is defined as final. So you need to create your
-    * new DebugURLRequest, then refer to its .request property.</p>
-    *
-    * <p>We use an evil Global because we don't know where loaderInfo.parameters will be.</p>
-    *
-    * @see http://www.ultrashock.com/forums/actionscript/force-reload-files-only-using-as3-123408.html
-    */
-
-       public class DebugURLRequest {
-
-               public var request:URLRequest;
-
-               public function DebugURLRequest(url:String=null) {
-                       request=new URLRequest(url);
-                       if (Globals.vars.hasOwnProperty('nocache') && Globals.vars.nocache) {
-                               request.method=URLRequestMethod.POST;
-                               request.data=true;
-                       }
-               }
-
-       }
-
-}
diff --git a/net/systemeD/halcyon/FileBank.as b/net/systemeD/halcyon/FileBank.as
new file mode 100755 (executable)
index 0000000..c79e2ba
--- /dev/null
@@ -0,0 +1,261 @@
+package net.systemeD.halcyon {
+    import flash.events.*;
+       import flash.display.*;
+       import flash.net.*;
+       import flash.utils.ByteArray;
+       import nochump.util.zip.*;
+
+       /*
+               FileBank stores and retrieves bitmap images and other files.
+               Images are internally stored as Loader. Other files are stored as strings.
+
+               See blog.yoz.sk/2009/10/bitmap-bitmapdata-bytearray/ for a really useful conversion guide!
+       */
+
+    public class FileBank extends EventDispatcher{
+               private var files:Object={};
+               private var filesRequested:uint=0;
+               private var filesReceived:uint=0;
+               private var zipsRequested:uint=0;
+               private var zipsReceived:uint=0;
+        private var zipCallbacks:Array=[];
+               
+               public static const FILES_LOADED:String="filesLoaded";
+               
+               private static const GLOBAL_INSTANCE:FileBank = new FileBank();
+               public static function getInstance():FileBank { return GLOBAL_INSTANCE; }
+
+               public function hasFile(name:String):Boolean {
+                       if (files[name]) return true;
+                       return false;
+               }
+
+        public function fileLoaded(name:String, callback:Function):Boolean {
+            var loaded:Boolean = false;
+            if (files[name]) {
+                if (files[name].info.callbacks) {
+                    files[name].info.callbacks.push(callback);
+                } else {
+                    loaded = true;
+                }
+            }
+            return loaded;
+        }
+
+        /* ==========================================================================================
+                  Add an individual file to bank (not from a .zip file)
+                  Used when we want to load a file for use later on (e.g. an image referenced in a stylesheet)
+                  ========================================================================================== */
+
+               public function addFromFile(filename:String, callback:Function = null):void {
+            if (files[filename]) {
+                if (callback != null) {
+                    if (files[filename].info.callbacks) {
+                        files[filename].info.callbacks.push(callback);
+                    } else {
+                        callback(this, filename);
+                    }
+                }
+            } else if (zipsRequested > zipsReceived) {
+                zipCallbacks.push(function ():void {
+                    addFromFile(filename, callback);
+                });
+            } else {
+                var request:URLRequest = new URLRequest(filename);
+                var loader:Object;
+                var loaderInfo:EventDispatcher;
+                
+                if (isImageType(filename)) {
+                    loader = new ExtendedLoader();
+                    loaderInfo = loader.contentLoaderInfo;
+                    loaderInfo.addEventListener(Event.COMPLETE, loadedImage);
+                } else {
+                    loader = loaderInfo = new ExtendedURLLoader();
+                    loaderInfo.addEventListener(Event.COMPLETE, loadedFile);
+                }
+
+                loader.info.filename = filename;
+                loader.info.callbacks = new Array();
+                
+                if (callback != null) {
+                    loader.info.callbacks.push(callback);
+                }
+
+                files[filename] = loader;
+
+                loaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
+                loaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
+                loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
+
+                filesRequested++;
+
+                loader.load(request);
+            }
+               }
+
+        public function onFilesLoaded(callback:Function):void {
+            if (filesRequested > filesReceived) {
+                addEventListener(FileBank.FILES_LOADED, function(e:Event):void {
+                    callback();
+                });
+            } else {
+                callback();
+            }
+        }
+
+        private function loadedImage(event:Event):void {
+                       fileLoadComplete(event.target.loader.info);
+        }
+        private function loadedFile(event:Event):void {
+                       fileLoadComplete(event.target.info);
+        }
+        private function fileLoadComplete(info:Object):void {
+            var callbacks:Array = info.callbacks;
+            info.callbacks = null;
+            while (callbacks.length > 0) {
+                var callback:Function = callbacks.shift();
+                callback(this, info.filename);
+            }
+
+            fileReceived();
+               }
+               private function httpStatusHandler(event:HTTPStatusEvent):void { }
+               private function securityErrorHandler(event:SecurityErrorEvent):void { 
+                       trace("securityErrorEvent: "+event.target.url);
+                       fileReceived();
+               }
+               private function ioErrorHandler(event:IOErrorEvent):void { 
+                       trace("ioErrorEvent: "+event.target.url); 
+                       fileReceived();
+               }
+               private function fileReceived():void {
+                       filesReceived++;
+                       if (filesReceived==filesRequested) { dispatchEvent(new Event(FILES_LOADED)); }
+               }
+
+               /* ==========================================================================================
+                  Add files to bank from .zip file
+                  ========================================================================================== */
+               
+               public function addFromZip(filename:String, prefix:String=""):void {
+                       var loader:URLLoader = new URLLoader();
+                       loader.dataFormat="binary";
+                       loader.addEventListener(Event.COMPLETE, function(e:Event):void { zipReady(e,prefix); } );
+            loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, zipSecurityErrorHandler);
+            loader.addEventListener(IOErrorEvent.IO_ERROR, zipIoErrorHandler);
+            zipsRequested++;
+            loader.load(new URLRequest(filename));
+               }
+               private function zipReady(event:Event, prefix:String):void {
+                       var zip:ZipFile = new ZipFile(event.target.data);
+                       for (var i:uint=0; i<zip.entries.length; i++) {
+                               var fileref:ZipEntry = zip.entries[i];
+                               var data:ByteArray = zip.getInput(fileref);
+                               if (isImageType(fileref.name)) {
+                                       // Store as an image
+                                       var loader:ExtendedLoader=new ExtendedLoader();
+                                       files[prefix+fileref.name]=loader;
+                    loader.info.filename = prefix+fileref.name;
+                                       loader.loadBytes(data);
+                               } else {
+                                       // Store as a document
+                                       var urlloader:ExtendedURLLoader=new ExtendedURLLoader();
+                                       files[prefix+fileref.name]=urlloader;
+                    urlloader.info.filename = prefix+fileref.name;
+                    urlloader.data = data.toString();
+                               }
+                       }
+            zipReceived();
+               }
+               private function zipSecurityErrorHandler(event:SecurityErrorEvent):void { 
+                       trace("securityErrorEvent: "+event.target.url);
+                       zipReceived();
+               }
+               private function zipIoErrorHandler(event:IOErrorEvent):void { 
+                       trace("ioErrorEvent: "+event.target.url); 
+                       zipReceived();
+               }
+               private function zipReceived():void {
+                       zipsReceived++;
+                       if (zipsReceived == zipsRequested) {
+                while (zipCallbacks.length > 0) {
+                    var callback:Function = zipCallbacks.shift();
+                    callback();
+                }
+            }
+               }
+               private function isImageType(filename:String):Boolean {
+                       if (filename.match(/\.jpe?g$/i) ||
+                               filename.match(/\.png$/i) ||
+                               filename.match(/\.gif$/i) ||
+                               filename.match(/\.swf$/i)) { return true; }
+                       return false;
+               }
+
+               /* ==========================================================================================
+                  Get files
+                  get(filename)
+                  getAsDisplayObject(filename)
+                  getAsBitmapData(filename)
+                  getAsByteArray(filename)
+                  ========================================================================================== */
+
+               public function get(name:String):String {
+                       return files[name];
+               }
+
+               public function getAsDisplayObject(name:String):DisplayObject {
+                       /* If the image hasn't loaded yet, then add an EventListener for when it does. */
+                       if (getWidth(name)==0) {
+                               var loader:Loader = new Loader();
+                               files[name].contentLoaderInfo.addEventListener(Event.COMPLETE,
+                                       function(e:Event):void { loaderReady(e, loader) });
+                               return loader;
+                       }
+                       /* Otherwise, create a new Bitmap, because just returning the raw Loader
+                          (i.e. files[name]) would only allow it to be added to one parent. (The other 
+                          way to do this would be by copying the bytes as loaderReady does.). */
+                       return new Bitmap(getAsBitmapData(name));
+               }
+               
+               public function getOriginalDisplayObject(name:String):DisplayObject {
+                       /* But if we're going to clone it later, this'll work fine. */
+                       return files[name];
+               }
+
+               private function loaderReady(event:Event, loader:Loader):void {
+                       /* The file has loaded, so we can copy the data from there into our new Loader */
+                       var info:LoaderInfo = event.target as LoaderInfo;
+                       loader.loadBytes(info.bytes);
+               }
+
+               public function getAsBitmapData(name:String):BitmapData {
+                       var bitmapData:BitmapData=new BitmapData(getWidth(name), getHeight(name), true, 0xFFFFFF);
+                       bitmapData.draw(files[name]);
+                       return bitmapData;
+               }
+               
+               public function getAsByteArray(name:String):ByteArray {
+                       return files[name].contentLoaderInfo.bytes;
+               }
+               
+               public function getAsString(name:String):String {
+                       return files[name].data;
+               }
+        
+               /* ==========================================================================================
+                  Get file information
+                  ========================================================================================== */
+
+               public function getWidth(name:String):int { 
+                       try { return files[name].contentLoaderInfo.width; }
+                       catch (error:Error) { } return 0;
+               }
+
+               public function getHeight(name:String):int { 
+                       try { return files[name].contentLoaderInfo.height; }
+                       catch (error:Error) { } return 0;
+               }
+
+       }
+}
diff --git a/net/systemeD/halcyon/ImageBank.as b/net/systemeD/halcyon/ImageBank.as
deleted file mode 100755 (executable)
index eca8547..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-package net.systemeD.halcyon {
-    import flash.events.*;
-       import flash.display.*;
-       import flash.net.*;
-       import flash.utils.ByteArray;
-       import nochump.util.zip.*;
-
-       /*
-               ImageBank stores and retrieves bitmap images.
-               All images are internally stored as Loader.
-
-               See blog.yoz.sk/2009/10/bitmap-bitmapdata-bytearray/ for a really useful conversion guide!
-       */
-
-    public class ImageBank extends EventDispatcher{
-               private var images:Object={};
-               private var imagesRequested:uint=0;
-               private var imagesReceived:uint=0;
-               
-               public static const IMAGES_LOADED:String="imagesLoaded";
-               public static const ZIP_LOADED:String="zipLoaded";
-               
-               private static const GLOBAL_INSTANCE:ImageBank = new ImageBank();
-               public static function getInstance():ImageBank { return GLOBAL_INSTANCE; }
-
-               public function hasImage(name:String):Boolean {
-                       if (images[name]) return true;
-                       return false;
-               }
-
-               /* ==========================================================================================
-                  Populate with images 
-                  ========================================================================================== */
-
-               public function loadImage(filename:String):void {
-                       if (images[filename]) return;
-                       imagesRequested++;
-
-                       var loader:Loader=new Loader();
-                       images[filename]=loader;
-                       var request:URLRequest=new URLRequest(filename);
-                       loader.contentLoaderInfo.addEventListener(Event.COMPLETE,                                               loadedImage);
-                       loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS,                  httpStatusHandler);
-                       loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,    securityErrorHandler);
-                       loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,                                ioErrorHandler);
-                       loader.load(request);
-               }
-
-               private function loadedImage(event:Event):void {
-                       imageReceived();
-               }
-               private function httpStatusHandler(event:HTTPStatusEvent):void { }
-               private function securityErrorHandler(event:SecurityErrorEvent):void { 
-                       trace("securityErrorEvent: "+event.target.url);
-                       imageReceived();
-               }
-               private function ioErrorHandler(event:IOErrorEvent):void { 
-                       trace("ioErrorEvent: "+event.target.url); 
-                       imageReceived();
-               }
-               private function imageReceived():void {
-                       imagesReceived++;
-                       if (imagesReceived==imagesRequested) { dispatchEvent(new Event(IMAGES_LOADED)); }
-               }
-
-               /* ==========================================================================================
-                  Load from .zip file
-                  ========================================================================================== */
-               
-               public function loadFromZip(filename:String, prefix:String=""):void {
-                       var loader:URLLoader = new URLLoader();
-                       loader.dataFormat="binary";
-                       loader.addEventListener(Event.COMPLETE, function(e:Event):void { zipReady(e,prefix); } );
-                       loader.load(new URLRequest(filename));
-               }
-               private function zipReady(event:Event, prefix:String):void {
-                       var zip:ZipFile = new ZipFile(event.target.data);
-                       for (var i:uint=0; i<zip.entries.length; i++) {
-                               var fileref:ZipEntry = zip.entries[i];
-                               var data:ByteArray = zip.getInput(fileref);
-                               var loader:Loader=new Loader();
-                               images[prefix+fileref.name]=loader;
-                               loader.loadBytes(data);
-                       }
-                       dispatchEvent(new Event(ZIP_LOADED));
-               }
-
-
-               /* ==========================================================================================
-                  Get images 
-                  getAsDisplayObject(filename)
-                  getAsBitmapData(filename)
-                  getAsByteArray(filename)
-                  ========================================================================================== */
-
-               public function getAsDisplayObject(name:String):DisplayObject {
-                       /* If the image hasn't loaded yet, then add an EventListener for when it does. */
-                       if (getWidth(name)==0) {
-                               var loader:Loader = new Loader();
-                               images[name].contentLoaderInfo.addEventListener(Event.COMPLETE,
-                                       function(e:Event):void { loaderReady(e, loader) });
-                               return loader;
-                       }
-                       /* Otherwise, create a new Bitmap, because just returning the raw Loader
-                          (i.e. images[name]) would only allow it to be added to one parent. (The other 
-                          way to do this would be by copying the bytes as loaderReady does.). */
-                       return new Bitmap(getAsBitmapData(name));
-               }
-               
-               public function getOriginalDisplayObject(name:String):DisplayObject {
-                       /* But if we're going to clone it later, this'll work fine. */
-                       return images[name];
-               }
-
-               private function loaderReady(event:Event, loader:Loader):void {
-                       /* The file has loaded, so we can copy the data from there into our new Loader */
-                       var info:LoaderInfo = event.target as LoaderInfo;
-                       loader.loadBytes(info.bytes);
-               }
-
-               public function getAsBitmapData(name:String):BitmapData {
-                       var bitmapData:BitmapData=new BitmapData(getWidth(name), getHeight(name), true, 0xFFFFFF);
-                       bitmapData.draw(images[name]);
-                       return bitmapData;
-               }
-               
-               public function getAsByteArray(name:String):ByteArray {
-                       return images[name].contentLoaderInfo.bytes;
-               }
-
-               /* ==========================================================================================
-                  Get file information
-                  ========================================================================================== */
-
-               public function getWidth(name:String):int { 
-                       try { return images[name].contentLoaderInfo.width; }
-                       catch (error:Error) { } return 0;
-               }
-
-               public function getHeight(name:String):int { 
-                       try { return images[name].contentLoaderInfo.height; }
-                       catch (error:Error) { } return 0;
-               }
-
-       }
-}
\ No newline at end of file
index 14801bc19265cb9ebe0be83a8ee1cf5fd7d34632..512d3398b36657e5aa4fdf06e31c64949cd467ac 100644 (file)
@@ -10,7 +10,7 @@ package net.systemeD.halcyon {
     import flash.geom.Point;
     import net.systemeD.halcyon.styleparser.*;
     import net.systemeD.halcyon.connection.*;
-    import net.systemeD.halcyon.ImageBank;
+    import net.systemeD.halcyon.FileBank;
 
     public class MarkerUI extends EntityUI {
 
@@ -100,9 +100,9 @@ package net.systemeD.halcyon {
                             icon.graphics.drawCircle(w,w,w);
                             if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
 
-                                               } else if (ImageBank.getInstance().hasImage(s.icon_image)) {
+                                               } else if (FileBank.getInstance().hasFile(s.icon_image)) {
                                                        // load icon from library
-                                                       icon.addChild(ImageBank.getInstance().getAsDisplayObject(s.icon_image));
+                                                       icon.addChild(FileBank.getInstance().getAsDisplayObject(s.icon_image));
 //                                                     addHitSprite(icon.width);                       // ** check this - we're doing it below too
 //                                                     loaded=true; updatePosition();          // ** check this
                                                        if (s.interactive) { maxwidth=Math.max(icon.width,maxwidth); }
index 51e9ec0f0e063df1763263803ca6ba4508c07ce5..94bc9f11d71285278c5ae057b208085ddae71741 100644 (file)
@@ -12,36 +12,29 @@ package net.systemeD.halcyon {
        *       onFeatureLoad can then access the XML via event.target.xml.
        */
 
+    import net.systemeD.halcyon.FileBank;
+
        import flash.events.*;
-    import flash.net.URLLoader;
-    import flash.net.URLRequest;
 
        public class NestedXMLLoader extends EventDispatcher {
                public var xml:XML = null;
-               private var url:String;
                private var count:int;
 
                public function NestedXMLLoader() {
                }
                
                public function load(url:String):void {
-                       this.url=url;
-                       var request:URLRequest=new URLRequest(url+"?d="+Math.random());
-                       var loader:URLLoader = new URLLoader();
-                       loader.addEventListener(Event.COMPLETE, fileLoaded);
-                       loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, fileError);
-                       loader.addEventListener(IOErrorEvent.IO_ERROR, fileError);
-                       loader.load(request);
+            FileBank.getInstance().addFromFile(url, fileLoaded);
                }
                
-               private function fileLoaded(event:Event):void {
-                       count=0;
-                       xml = new XML(URLLoader(event.target).data);
+               private function fileLoaded(fileBank:FileBank, filename:String):void {
+            count=1;
+                       xml = new XML(fileBank.getAsString(filename));
                        for each (var inc:XML in xml.descendants('include')) {
-                               replaceXML(inc);
                                count++;
+                               replaceXML(inc);
                        }
-                       if (count==0) { fireComplete(); }
+            decreaseCount();
                }
 
                private function replaceXML(inc:XML):void {
@@ -51,7 +44,7 @@ package net.systemeD.halcyon {
                                includeElement.parent().replace(findChildIndex(includeElement),event.target.xml);
                                decreaseCount();
                        });
-                       xmlLoader.load(inc.@file+"?d="+Math.random());
+                       xmlLoader.load(inc.@file);
                }
 
                private function findChildIndex(child:XML):int {
@@ -62,11 +55,6 @@ package net.systemeD.halcyon {
                        }
                        return -1;
                }
-
-               private function fileError(event:Event):void {
-                       // just fire a complete event so we don't get an error dialogue
-                       fireComplete();
-               }
                
                private function decreaseCount():void {
                        count--; if (count>0) return;
index 11bcc02fdd8a2daec449d3d49e43220927235333..9e26cc87571c1117f7355fb33a35addba7ed5077 100644 (file)
@@ -10,7 +10,7 @@ package net.systemeD.halcyon {
        import flash.geom.Point;
        import net.systemeD.halcyon.styleparser.*;
     import net.systemeD.halcyon.connection.*;
-    import net.systemeD.halcyon.ImageBank;
+    import net.systemeD.halcyon.FileBank;
        
        /** The graphical representation of a Node (including POIs and nodes that are part of Ways). */
        public class NodeUI extends EntityUI {
@@ -122,9 +122,9 @@ package net.systemeD.halcyon {
                                                        icon.graphics.drawCircle(w,w,w);
                                                        if (s.interactive) { maxwidth=Math.max(w,maxwidth); }
 
-                                               } else if (ImageBank.getInstance().hasImage(s.icon_image)) {
+                                               } else if (FileBank.getInstance().hasFile(s.icon_image)) {
                                                        // load icon from library
-                                                       icon.addChild(ImageBank.getInstance().getAsDisplayObject(s.icon_image));
+                                                       icon.addChild(FileBank.getInstance().getAsDisplayObject(s.icon_image));
 //                                                     addHitSprite(icon.width);                       // ** check this - we're doing it below too
                                                        loaded=true; updatePosition();          // ** check this
                                                        if (s.interactive) { maxwidth=Math.max(icon.width,maxwidth); }
index f7a5945247f0f140752c152fb14c158798d02540..990f43bbe946681b92ee50e37e46bcd95101cd0a 100644 (file)
@@ -9,7 +9,7 @@ package net.systemeD.halcyon {
        
        import net.systemeD.halcyon.connection.*;
        import net.systemeD.halcyon.styleparser.*;
-    import net.systemeD.halcyon.ImageBank;
+    import net.systemeD.halcyon.FileBank;
 
        /** The graphical representation of a Way. */ 
        public class WayUI extends EntityUI {
@@ -296,7 +296,7 @@ package net.systemeD.halcyon {
                                                fill=new Shape(); addToLayer(fill,FILLSPRITE,s.sublayer);
                                                fill.graphics.moveTo(x0,y0);
                                                if (s.fill_image) {
-                                                       fill.graphics.beginBitmapFill(ImageBank.getInstance().getAsBitmapData(s.fill_image));
+                                                       fill.graphics.beginBitmapFill(FileBank.getInstance().getAsBitmapData(s.fill_image));
                                                } else {
                                                        s.applyFill(fill.graphics);
                                                }
index d3bc0f2d8cb8f6bd325679d2040a6b70b921973e..bf785de8952f0b559240d281f8841c17d1cd364d 100644 (file)
@@ -46,6 +46,7 @@ package net.systemeD.halcyon.connection {
             _id = Number(xml.@id);
             _filename = xml.@name;
             _description = xml.description;
+            tags = [];
             for each(var tag:XML in xml.tag) {
               tags.push(String(tag));
             }
index 74fb3635167fdf7d2e61f4ddea11965a265158d6..6b5d8aeec2fed0af8473c91df9335f208ce4dc1a 100644 (file)
@@ -163,11 +163,19 @@ package net.systemeD.halcyon.connection {
            }
 
         private function changesetCreateComplete(event:Event):void {
-            // response should be a Number changeset id
-            var id:Number = Number(URLLoader(event.target).data);
+            var result:String = URLLoader(event.target).data;
+
+            if (result.match(/^^\d+$/)) {
+                // response should be a Number changeset id
+                var id:Number = Number(URLLoader(event.target).data);
             
-            // which means we now have a new changeset!
-            setActiveChangeset(new Changeset(this, id, lastUploadedChangesetTags));
+                // which means we now have a new changeset!
+                setActiveChangeset(new Changeset(this, id, lastUploadedChangesetTags));
+            } else {
+                var results:XML = XML(result);
+
+                throwServerError(results.message);
+            }
         }
 
         private function changesetCreateError(event:IOErrorEvent):void {
@@ -482,10 +490,15 @@ package net.systemeD.halcyon.connection {
                                function(e:Event):void { 
                        dispatchEvent(new Event(LOAD_COMPLETED));
                                        callback(e);
-                               }, errorOnMapLoad, mapLoadStatus); // needs error handlers
+                               }, errorOnTraceLoad, mapLoadStatus); // needs error handlers
             dispatchEvent(new Event(LOAD_STARTED)); //specifc to map or reusable?
         }
 
+        private function errorOnTraceLoad(event:Event):void {
+            trace("Trace load error");
+            dispatchEvent(new Event(LOAD_COMPLETED));
+               }
+
         /** Fetch the history for the given entity. The callback function will be given an array of entities of that type, representing the different versions */
         override public function fetchHistory(entity:Entity, callback:Function):void {
             if (entity.id >= 0) {
index b03f1b381de5fe3f29082a8e975cc397020986d8..1873d57655b1ebe8327c9c8f377b3e3e0359d781 100644 (file)
@@ -1,9 +1,8 @@
 package net.systemeD.halcyon.styleparser {
 
-       import flash.events.*;
-       import flash.net.URLLoader;
-       import flash.net.URLLoaderDataFormat;
-       import flash.net.URLRequest;
+    import net.systemeD.halcyon.FileBank;
+
+    import flash.events.*;
 
        /** A class permitting you to load CSS files containing 'import' rules, which will be 
                automatically replaced with the contents of the file.                                                                   <p>
@@ -18,9 +17,7 @@ package net.systemeD.halcyon.styleparser {
        */
 
        public class NestedCSSLoader extends EventDispatcher {
-               private var sourceCSS:String;
                public var css:String;
-               private var url:String;
                private var count:int;
 
                private static const IMPORT:RegExp=/@import\s*[^'"]*['"]([^'"]+)['"][^;]*;/g;           // '
@@ -29,28 +26,21 @@ package net.systemeD.halcyon.styleparser {
                }
                
                public function load(url:String):void {
-                       this.url=url;
-                       var request:URLRequest=new URLRequest(url+"?d="+Math.random());
-                       var loader:URLLoader = new URLLoader();
-                       loader.dataFormat = URLLoaderDataFormat.TEXT;
-                       loader.addEventListener(Event.COMPLETE, fileLoaded);
-                       loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, fileError);
-                       loader.addEventListener(IOErrorEvent.IO_ERROR, fileError);
-                       loader.load(request);
+            FileBank.getInstance().addFromFile(url, fileLoaded);
                }
                
-               private function fileLoaded(event:Event):void {
-                       sourceCSS=URLLoader(event.target).data;
-                       css=sourceCSS;
-                       count=0;
+               private function fileLoaded(fileBank:FileBank, filename:String):void {
+                       css = fileBank.getAsString(filename);
+                       count = 1;
 
-                       var result:Object=IMPORT.exec(sourceCSS);
-                       while (result!=null) {
+                       var results:Array = css.match(IMPORT);
+            while (results.length > 0) {
+                IMPORT.lastIndex = 0;
+                var result:Object = IMPORT.exec(results.shift());
                                count++;
                                replaceCSS(result[1],result[0]);
-                               result=IMPORT.exec(sourceCSS);
                        }
-                       if (count==0) { fireComplete(); }
+            decreaseCount();
                }
 
                private function replaceCSS(filename:String, toReplace:String):void {
@@ -60,13 +50,7 @@ package net.systemeD.halcyon.styleparser {
                                css=css.replace(replaceText,event.target.css);
                                decreaseCount();
                        });
-                       cssLoader.load(filename+"?d="+Math.random());
-               }
-
-               private function fileError(event:Event):void {
-                       // just fire a complete event so we don't get an error dialogue
-                       trace("Error while trying to load "+url);
-                       fireComplete();
+                       cssLoader.load(filename);
                }
                
                private function decreaseCount():void {
index 6a8d6a015fef1dda52b38a08015078c7a0bf23f5..be59b8d8dd47b7ec4349e7bcf1fb02e01df218af 100644 (file)
@@ -2,11 +2,8 @@ package net.systemeD.halcyon.styleparser {
 
        import flash.events.*;
        import flash.net.*;
-       import net.systemeD.halcyon.ExtendedLoader;
-       import net.systemeD.halcyon.ExtendedURLLoader;
-       import net.systemeD.halcyon.DebugURLRequest;
     import net.systemeD.halcyon.connection.Entity;
-    import net.systemeD.halcyon.ImageBank;
+    import net.systemeD.halcyon.FileBank;
 
     import net.systemeD.halcyon.connection.*;
 
@@ -294,7 +291,6 @@ package net.systemeD.halcyon.styleparser {
                /** Load all images referenced in the RuleSet (for example, icons or bitmap fills). */
                
                private function loadImages():void {
-                       ImageBank.getInstance().addEventListener(ImageBank.IMAGES_LOADED,doIconCallback);
                        var filename:String;
                        for each (var chooser:StyleChooser in choosers) {
                                for each (var style:Style in chooser.styles) {
@@ -304,13 +300,10 @@ package net.systemeD.halcyon.styleparser {
                                        else { continue; }
 
                                        if (filename!='square' && filename!='circle')
-                                               ImageBank.getInstance().loadImage(filename);
+                                               FileBank.getInstance().addFromFile(filename);
                                }
                        }
-               }
-               
-               private function doIconCallback(e:Event):void {
-                       iconCallback();
+            if (iconCallback!=null) { FileBank.getInstance().onFilesLoaded(iconCallback); }
                }
                
                // ------------------------------------------------------------------------------------------------
index 9d9d2f93fc4648a94287b5f8d3582eafedb6ff83..f0e95bc50745152858eabec3721315a1b5927622 100644 (file)
@@ -1,7 +1,7 @@
 package net.systemeD.halcyon.styleparser {
 
        import net.systemeD.halcyon.connection.Entity;
-    import net.systemeD.halcyon.ImageBank;
+    import net.systemeD.halcyon.FileBank;
 
        public class StyleChooser {
 
@@ -68,8 +68,8 @@ package net.systemeD.halcyon.styleparser {
                                                        if (PointStyle(r).icon_width && !PointStyle(r).evals['icon_width']) {
                                                                // ** FIXME: we should check this is the bit being used for 'square', 'circle' etc.
                                                                w=PointStyle(r).icon_width;
-                                                       } else if (PointStyle(r).icon_image && ImageBank.getInstance().hasImage(PointStyle(r).icon_image)) {
-                                                               w=ImageBank.getInstance().getWidth(PointStyle(r).icon_image);
+                                                       } else if (PointStyle(r).icon_image && FileBank.getInstance().hasFile(PointStyle(r).icon_image)) {
+                                                               w=FileBank.getInstance().getWidth(PointStyle(r).icon_image);
                                                        }
                                                        if (w>sl.maxwidth) { sl.maxwidth=w; }
                                                } else if (r is InstructionStyle) {
index 4b339d0e115b70c3519d5eb60ab3ece6ba48397c..082284fc086813866752db89973a83a56dda9cdf 100644 (file)
@@ -27,6 +27,7 @@
                import net.systemeD.halcyon.*;
                import net.systemeD.halcyon.connection.*;
                import net.systemeD.potlatch2.*;
+               import net.systemeD.potlatch2.dialogs.*;
                import net.systemeD.potlatch2.collections.Imagery;
                import mx.core.*;
                import mx.collections.ArrayCollection;
@@ -36,7 +37,6 @@
 
                public function setDimming(v:Boolean):void {
                        FlexGlobals.topLevelApplication.theMap.setDimming(dim.selected);
-                       FlexGlobals.topLevelApplication.yahoo.alpha = dim.selected ? 0.5 : 1;
                        var obj:SharedObject=SharedObject.getLocal("user_state");
                        obj.setProperty('background_dim',v);
                        obj.flush();
diff --git a/net/systemeD/potlatch2/CustomLocaleCommand.as b/net/systemeD/potlatch2/CustomLocaleCommand.as
new file mode 100644 (file)
index 0000000..b4b8160
--- /dev/null
@@ -0,0 +1,24 @@
+package net.systemeD.potlatch2 {
+    import org.babelfx.commands.ExternalLocaleCommand;
+    import net.systemeD.halcyon.Globals;
+
+    public class CustomLocaleCommand extends ExternalLocaleCommand {
+        public var defaultExternalPath:String;
+
+        override protected function loadLocale(locale:String):void {
+            externalPath = defaultExternalPath;
+
+            if (Globals.vars.locale_paths) {
+                for each (var path:String in Globals.vars.locale_paths.split(";")) {
+                    var args:Array = path.split("=");
+
+                    if (args[0] == locale) {
+                        externalPath = args[1];
+                    }
+                }
+            }
+
+            super.loadLocale(locale);
+        }
+    }
+}
index 583e610339e1e70a58657efe38c55654738efa2f..ebef62df03e06c52b442ffcc00ce53e7ed923bad 100644 (file)
@@ -6,7 +6,7 @@ package net.systemeD.potlatch2 {
     import flash.geom.Matrix;
     import flash.text.TextField;
     import flash.text.TextFormat;
-    import net.systemeD.halcyon.ImageBank;
+    import net.systemeD.halcyon.FileBank;
 
 
     public class Preloader extends net.systemeD.potlatch2.PreloaderDisplayBase {
@@ -21,9 +21,6 @@ package net.systemeD.potlatch2 {
         private var barFrame:Sprite;
         private var mainColor:uint=0x045966;
 
-               private var assetscount:uint=0;
-               private var queuedEvents:Array=[];
-
         public function Preloader()
         {
             super();
@@ -45,31 +42,16 @@ package net.systemeD.potlatch2 {
 
                        // request .zip files
                        if (loaderInfo.parameters['assets']) {
-                               ImageBank.getInstance().addEventListener(ImageBank.ZIP_LOADED, zipLoaded);
                                for each (var file:String in loaderInfo.parameters['assets'].split(';')) {
                                        var asset:Array=file.split('=');
-                                       assetscount++;
-                                       ImageBank.getInstance().loadFromZip(asset[0],asset[1]);
+                    if (asset.length == 1) {
+                        FileBank.getInstance().addFromZip(asset[0]);
+                    } else {
+                        FileBank.getInstance().addFromZip(asset[0], asset[1]);
+                    }
                                }
                        }
         }
-
-               override protected function initProgressHandler(e:Event):void {
-                       // We don't let anything happen until the .zips are loaded
-                       // see http://stackoverflow.com/questions/2773617/how-to-preload-a-file-in-flex-before-the-application-initializes
-                       if (assetscount>0) {
-                               queuedEvents.push(e);
-                               e.stopImmediatePropagation();
-                       }
-                       draw();
-               }
-               
-               private function zipLoaded(e:Event):void {
-                       assetscount--; if (assetscount>0) return;
-                       for each (var q:Event in queuedEvents) {
-                               dispatchEvent(q);
-                       }
-               }
                
         //this is our "animation" bit
         override protected function draw():void
index 057e6f817730232910f6ef0b85d1e6f134f9dd7c..331dd04c8dd9ca75764c63aff95b616c9ae26b31 100644 (file)
@@ -18,6 +18,7 @@
                import net.systemeD.halcyon.connection.*;
                import net.systemeD.potlatch2.*;
                import net.systemeD.potlatch2.collections.Stylesheets;
+               import net.systemeD.potlatch2.dialogs.*;
                import mx.core.*;
     ]]></fx:Script>
 </mx:VBox>
index 0d5df272b93f7e63b84f87f30e18c89c89d2c251..bed408f0905e606ccbeb9642ae17c8a61586ccad 100644 (file)
@@ -4,7 +4,7 @@
        Advanced tag grid
 -->
 
-<mx:DataGrid editable="true" doubleClickEnabled="true" doubleClick="addNewTag(event)"
+<mx:DataGrid editable="true" doubleClickEnabled="true" doubleClick="addNewTag(event)" sortableColumns="false"
     xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:controls="net.systemeD.controls.*"
        xmlns:mx="library://ns.adobe.com/flex/mx">
index dd1fefb1818bf7edbde868ebf8b1cdf6152399ea..96f733eb7ee8ebc9aff8870e1e57388f240ebe8a 100644 (file)
 
 <mx:ViewStack id="sidebar" width="100%" height="100%" creationPolicy="all">
 
-  <!-- Drag & drop icon panel -->
-
-  <mx:VBox id="dndPanel" width="100%" height="100%" horizontalScrollPolicy="off" styleName="dndPanelVbox">
-    <mx:Text id="dndPanelText" text="{dndPrompt}" width="100%" styleName="helpInfo" />
-       <mx:Repeater id="dndRep" dataProvider="{MapFeatures.getInstance().getCategoriesForType('point')}" styleName="dndRepeater">
-               <mx:HBox width="100%" styleName="dndPanelCategory">
-                       <mx:Label text="{dndRep.currentItem.name}:" styleName="dndPanelCategoryLabel"/>
-               </mx:HBox>
-
-               <mx:TileList dataProvider="{dndRep.currentItem.getFeaturesForType('point', true)}" width="100%" height="1"
-                                    rowHeight="32" columnWidth="32" updateComplete="resizePOIGrid(event)" styleName="dndPanelTileList">
-                       <mx:itemRenderer>
-                               <fx:Component>
-                                       <mx:VBox toolTip="{data.name}">
-                                               <fx:Script><![CDATA[
-                                                       import mx.events.DragEvent;
-                                                       import mx.managers.DragManager;
-                                                       import mx.core.DragSource;
-
-                                                       private function dragPOI(event:MouseEvent, tags:Array):void {
-                                                               if (outerDocument.controller.map.dragstate==outerDocument.controller.map.DRAGGING) return;
-
-                                                               // Get the drag initiator component from the event object.
-                                                               var dragInitiator:Image = event.currentTarget as Image;
-                                                               var dragSource:DragSource = new DragSource();
-                                                               dragSource.addData(tags, 'tags');
-                                                               dragSource.addData(event.target.parent.parent.parent.parent, 'container');
-
-                                                               var dragProxy:Image = new Image();
-                                                               dragProxy.source = dragInitiator.source;
-                                                               dragProxy.width = dragInitiator.width;   // must set width and height explicitly
-                                                               dragProxy.height = dragInitiator.height; // for non-embedded images
-                                                               DragManager.doDrag(dragInitiator, dragSource, event, dragProxy);
-                                                       }
-                                               ]]></fx:Script>
-                                               <mx:Image id="foo" source="{data.dndimage}" height="24" width="24" mouseMove="dragPOI(event, data.tags)" toolTip="{data.name}" />
-                                       </mx:VBox>
-                               </fx:Component>
-                       </mx:itemRenderer>
-               </mx:TileList>
-       </mx:Repeater>
-  </mx:VBox>
+  <sidepanel:DragAndDropPanel id="dndPanel" />
 
   <!-- Standard tagging panel -->
 
       private var tabIcons:Object= { Basic:tabIconBasic, Details:tabIconDetails, Address:tabIconAddress, Walk:tabIconWalk, Cycle:tabIconCycle, 
                                         Transport:tabIconTransport, Restrictions:tabIconRestrictions};
 
-      [Bindable]
-      public var dndPrompt:String="Add new points by dragging them onto the map";
-
       private var editorStackTabNavigator:TabNavigator;
       private var editorStackAccordion:Accordion;
       [Bindable] private var editorStack:Container;
       private var connection:Connection;
       private var currentCategorySelector:CategorySelector;
       private var categorySelectors:Object = {};       // hash of categorySelectors for each limitType
+      private var categorySelectorEntity:Entity;       // entity used to draw the categorySelector
       private var feature:Feature = null;
 
       private var rowData:Object;              // relation membership reference, needed so it's accessible from relation actions menu
                if (entities.length==0) {
                        // Nothing selected, so show drag-and-drop panel
                        sidebar.selectedChild = dndPanel;
+                       selectedEntity=null;
 
                } else if (entities.length==1) {
                        // Single entity selected, so show tag panel
+                       if (firstSelected!=null && selectedEntity!=firstSelected) { 
+                               firstSelected.addEventListener(Connection.TAG_CHANGED, tagChanged, false, 0, true);
+                       }
                        selectedEntity=firstSelected;
                        connection=firstSelected.connection;
-                       if (selectedEntity!=null) { selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged); }
                        if (advancedID!=null) { setupAdvanced(firstSelected); }
                        if (firstSelected is Relation) { stack.addChild(membersVBox); }
             if (selectedEntity is Marker && connection is BugConnection) {
                       && xor(!controller.map.getLayerForEntity(entities[0]).isBackground, !controller.map.getLayerForEntity(entities[1]).isBackground) ) {
             backgroundMergePanelContents.init(entities);
             sidebar.selectedChild = backgroundMergePanel;
+                       // ** FIXME: do we need to set selectedEntity here?
 
                } else if(isMultipleEditable(entities)) {
                        selectedEntity = new EntityCollection(entities);
-                       selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged);
+                       selectedEntity.addEventListener(Connection.TAG_CHANGED, tagChanged, false, 0, true);
             sidebar.selectedChild = multiplePanel;
                        setupMultiAdvanced(selectedEntity);
                        connection=entities[0].connection;
                } else {
                        //The selection contains elements which can't be edited all together.
                        sidebar.selectedChild = multipleInvalidPanel;
+                       selectedEntity=null;
                }
                UIComponent.resumeBackgroundProcessing();
       }
 
       private function refreshFeatureIcon():void {
           var oldFeature:Feature = feature;
+          var oldEntity:Entity = categorySelectorEntity;
+
           feature = selectedEntity == null ? null : mapFeatures.findMatchingFeature(selectedEntity);
-          if ( feature != oldFeature ) {
-              if ( oldFeature != null )
-                  oldFeature.removeEventListener("imageChanged", featureImageChanged);
-              if ( feature != null )
-                  feature.addEventListener("imageChanged", featureImageChanged);
+          if (oldFeature==feature && categorySelectorEntity==selectedEntity) {
+              updateCategoryImageAndText(selectedEntity,feature);
+              return;
           }
-          setCategorySelector(selectedEntity, feature);
+
+          categorySelectorEntity=selectedEntity;
+          if ( oldFeature != null ) { oldFeature.removeEventListener("imageChanged", featureImageChanged); }
+          if ( feature != null )    { feature.addEventListener("imageChanged", featureImageChanged); }
+                 setCategorySelector(selectedEntity, feature);
       }
 
       private function featureImageChanged(event:Event):void {
           setCategorySelector(selectedEntity, feature);
       }
 
+
       /** Set the icon, categorySelector and help text for the current entity. */
       private function setCategorySelector(entity:Entity, feature:Feature):void {
                        // Remove the "user has selected something" event listener from previous categorySelector,
                        currentCategorySelector=categorySelectors[lt];
                        currentCategorySelector.addEventListener("selectedType", changeFeatureType, false, 0, true);
 
-                       // Update surrounding icon/text display
+                       updateCategoryImageAndText(entity,feature);
+                       currentCategorySelector.setSelectedFeature(feature);
+
+                       // Set it as the popup, and make sure it's visible
+                       popupChange.popUp=currentCategorySelector;
+                       currentCategorySelector.visible=true;
+      }
+
+      private function updateCategoryImageAndText(entity:Entity, feature:Feature):void {
                        if (feature) {
                                iconImage.source = feature.image;
                                iconText.htmlText = feature.htmlDetails(entity);
                                popupChange.label = feature.name;
                                helpLabel.visible = feature.hasHelpURL();
-                               currentCategorySelector.setSelectedFeature(feature);
                        } else {
                                iconImage.source = null;
                                popupChange.label = "unknown";
                                } else {
                                        iconText.htmlText = "<b>No tags set</b><br/><font size='10pt'>Please use the menu below to define what this "+entity.getType()+" is</font>";
                                }
-                               currentCategorySelector.setSelectedFeature(null);
                        }
-
-                       // Set it as the popup, and make sure it's visible
-                       popupChange.popUp=currentCategorySelector;
-                       currentCategorySelector.visible=true;
-      }
+         }
 
          private function isMultipleEditable(entities:Array):Boolean {
                for each(var entity:Entity in entities) {
           UIComponent.resumeBackgroundProcessing();
       }
 
-       private function resizePOIGrid(event:Event):void {
-               var rows:Number=event.target.dataProvider.length/event.target.columnCount;
-               if (rows!=Math.floor(rows)) { rows=Math.floor(rows+1); }
-               event.target.height=rows*(event.target.rowHeight+1);
-       }
-
   ]]></fx:Script>
 </mx:VBox>
 
diff --git a/net/systemeD/potlatch2/Yahoo.as b/net/systemeD/potlatch2/Yahoo.as
deleted file mode 100644 (file)
index 7530324..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-package net.systemeD.potlatch2 {
-
-       import flash.display.*;
-       import net.systemeD.halcyon.Map;
-       import net.systemeD.halcyon.MapEvent;
-       import com.yahoo.maps.api.YahooMap;
-       import com.yahoo.maps.api.YahooMapEvent;
-       import com.yahoo.maps.api.core.location.LatLon;
-       
-    public class Yahoo extends YahooMap {
-
-               private var map:Map;
-               private static const token:String="f0a.sejV34HnhgIbNSmVHmndXFpijgGeun0fSIMG9428hW_ifF3pYKwbV6r9iaXojl1lU_dakekR";
-               private static const MAXZOOM:int=17;
-
-               private static const UNINITIALISED:uint=0;
-               private static const INITIALISING:uint=1;
-               private static const HIDDEN:uint=2;
-               private static const SHOWING:uint=3;
-               private var currentState:uint=UNINITIALISED;
-
-               private var _lat:Number;
-               private var _lon:Number;
-               private var _scale:Number;
-               private var offset_lat:Number=0;
-               private var offset_lon:Number=0;
-
-               public function Yahoo(map:Map) {
-                       super();
-                       currentState=UNINITIALISED;
-                       this.map=map;
-                       visible=false;
-               }
-               
-               public function show():void {
-                       visible=true;
-                       if (currentState==UNINITIALISED) {
-                               currentState=INITIALISING;
-                               this.addEventListener(YahooMapEvent.MAP_INITIALIZE, initHandler);
-                               this.init(token, map.mapwidth, map.mapheight);
-                               this.mapType="satellite";
-                               this.alpha=0.5;                         // ** FIXME - should take the value the user has chosen
-                               activateListeners();
-                       } else if (currentState==HIDDEN) { 
-                               currentState=SHOWING;
-                               moveto(map.centre_lat, map.centre_lon, map.scale);
-                               this.setSize(map.mapwidth,map.mapheight);
-                               activateListeners();
-                       }
-               }
-
-               public function hide():void {
-                       deactivateListeners();
-                       visible=false;
-                       if (currentState==SHOWING) currentState=HIDDEN;
-               }
-
-               private function activateListeners():void {
-                       map.addEventListener(MapEvent.MOVE, moveHandler);
-                       map.addEventListener(MapEvent.RESIZE, resizeHandler);
-                       map.addEventListener(MapEvent.NUDGE_BACKGROUND, nudgeHandler);
-               }
-               
-               private function deactivateListeners():void {
-                       map.removeEventListener(MapEvent.MOVE, moveHandler);
-                       map.removeEventListener(MapEvent.RESIZE, resizeHandler);
-                       map.removeEventListener(MapEvent.NUDGE_BACKGROUND, nudgeHandler);
-               }
-               
-               private function initHandler(event:YahooMapEvent):void {
-                       currentState=visible ? SHOWING : HIDDEN;
-                       if (map.centre_lat) { moveto(map.centre_lat, map.centre_lon, map.scale); }
-                       this.removeEventListener(YahooMapEvent.MAP_INITIALIZE, initHandler);
-               }
-
-               private function moveHandler(event:MapEvent):void {
-                       if (currentState!=SHOWING) { return; }
-                       moveto(event.params.lat, event.params.lon, event.params.scale);
-               }
-
-               private function moveto(lat:Number,lon:Number,scale:uint):void {
-                       if (scale>MAXZOOM) { visible=false; return; }
-                       _lat=lat; _lon=lon; _scale=scale;
-                       
-                       visible=true;
-                       this.zoomLevel=18-scale;
-                       this.centerLatLon=new LatLon(lat+offset_lat, lon+offset_lon);
-               }
-               
-               private function resizeHandler(event:MapEvent):void {
-                       moveto(map.centre_lat, map.centre_lon, map.scale);
-                       this.setSize(event.params.width, event.params.height);
-               }
-               
-               private function nudgeHandler(event:MapEvent):void {
-                       var cx:Number=map.lon2coord(map.centre_lon);
-                       var cy:Number=map.lat2coord(map.centre_lat);
-                       offset_lon+=map.coord2lon(cx-event.params.x)-map.centre_lon;
-                       offset_lat+=map.coord2lat(cy-event.params.y)-map.centre_lat;
-                       moveto(_lat,_lon,_scale);
-               }
-       }
-}
index f8abb7cff5f8868b57c8ab0db73f3a27885e7f33..6fbdb8ae3a4cad5ff291b46acf4359f6dec51d67 100644 (file)
@@ -4,16 +4,14 @@ package net.systemeD.potlatch2.collections {
        import flash.display.*;
        import flash.net.*;
        import flash.text.TextField;
-       import net.systemeD.halcyon.DebugURLRequest;
+       import net.systemeD.halcyon.FileBank;
        import net.systemeD.halcyon.Map;
        import net.systemeD.halcyon.MapEvent;
        import net.systemeD.potlatch2.FunctionKeyManager;
-       import net.systemeD.potlatch2.Yahoo;
        import mx.collections.ArrayCollection;
 
        /*
                There's lots of further tidying we can do:
-               - remove all the horrid Yahoo stuff
                - remove the backreferences to _map and send events instead
                but this will do for now and help remove the clutter from potlatch2.mxml.
        */
@@ -28,28 +26,23 @@ package net.systemeD.potlatch2.collections {
 
                private var _map:Map;
                private var _overlay:Sprite;
-               private var _yahoo:Yahoo;
 
                /* Load catalogue file */
 
-               public function init(map:Map, overlay:Sprite, yahoo:Yahoo):void {
+               public function init(map:Map, overlay:Sprite):void {
                        _map = map;
                        _overlay = overlay;
-                       _yahoo = yahoo;
 
                        // load imagery file
-               var request:DebugURLRequest = new DebugURLRequest("imagery.xml");
-               var loader:URLLoader = new URLLoader();
-               loader.addEventListener(Event.COMPLETE, onImageryLoad);
-               loader.load(request.request);
+            FileBank.getInstance().addFromFile("imagery.xml", onImageryLoad);
 
                        // create map listeners
                        map.addEventListener(MapEvent.MOVE, moveHandler);
                        map.addEventListener(MapEvent.RESIZE, resizeHandler);
                }
 
-        private function onImageryLoad(event:Event):void {
-                       var xml:XML = new XML(URLLoader(event.target).data);
+               private function onImageryLoad(fileBank:FileBank, filename:String):void {
+                       var xml:XML = new XML(fileBank.getAsString(filename));
                        var saved:Object = {};
                        var bg:Object;
                        if (SharedObject.getLocal("user_state").data['background_url']!=undefined) {
@@ -98,11 +91,12 @@ package net.systemeD.potlatch2.collections {
                        collection.forEach(function(bg:Object, index:int, array:Array):void {
                                if (bg.logo) {
                                        // load the logo
-                                       var loader:Loader = new Loader();
-                                       loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void { onLogoLoad(e,bg); });
-                                       loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
-                                       loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
-                                       loader.load(new URLRequest(bg.logo));
+                    FileBank.getInstance().addFromFile(bg.logo, function (fb:FileBank, name:String):void {
+                        bg.logoData = fb.getAsBitmapData(name);
+                        bg.logoWidth = fb.getWidth(name);
+                        bg.logoHeight = fb.getHeight(name);
+                        setLogo();
+                    });
                                }
                                if (bg.attribution_url) {
                                        // load the attribution
@@ -124,13 +118,6 @@ package net.systemeD.potlatch2.collections {
                        // placeholder error routine so exception isn't thrown
                }
                
-               public function onLogoLoad(e:Event, bg:Object):void {
-                       bg.logoData  = Bitmap(LoaderInfo(e.target).content).bitmapData;
-                       bg.logoWidth = e.target.loader.width;
-                       bg.logoHeight= e.target.loader.height;
-                       setLogo();
-               }
-               
                public function onAttributionLoad(e:Event,bg: Object):void {
                        // if we ever need to cope with non-Microsoft attribution, then this should look at bg.scheme
             default xml namespace = Namespace("http://schemas.microsoft.com/search/local/ws/rest/v1");
@@ -156,8 +143,7 @@ package net.systemeD.potlatch2.collections {
                public function setBackground(bg:Object):void {
                        // set background
                        _selected=bg;
-                       if (bg.url=='yahoo') { dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, {url:''})); _yahoo.show(); }
-                                       else { dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, bg      )); _yahoo.hide(); }
+                       dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, bg));
                        // update attribution and logo
                        _overlay.visible=bg.attribution || bg.logo || bg.terms_url;
                        setLogo(); setAttribution(); setTerms();
index 1ac3f63dd2c799ac284460df2881240f1a4485b0..209eac5c20e749bfaa7d7d600af78c0dea6eae13 100644 (file)
@@ -3,10 +3,9 @@ package net.systemeD.potlatch2.collections {
        import flash.events.EventDispatcher;
        import flash.events.Event;
        import flash.net.*;
-       import net.systemeD.halcyon.DebugURLRequest;
+       import net.systemeD.halcyon.FileBank;
        import net.systemeD.halcyon.Map;
        import net.systemeD.potlatch2.FunctionKeyManager;
-       import net.systemeD.potlatch2.Yahoo;
        import mx.collections.ArrayCollection;
 
        public class Stylesheets extends EventDispatcher {
@@ -28,14 +27,13 @@ package net.systemeD.potlatch2.collections {
                        _selected=_selected ? _selected : DEFAULT;
                        
                        // Load the stylesheet catalogue
-                       var request:DebugURLRequest = new DebugURLRequest("stylesheets.xml");
-                       var loader:URLLoader = new URLLoader();
-               loader.addEventListener(Event.COMPLETE, function(e:Event):void { onStylesheetsLoad(e,request_url); });
-               loader.load(request.request);
+            FileBank.getInstance().addFromFile("stylesheets.xml", function (fb:FileBank, name:String):void {
+                onStylesheetsLoad(fb, name, request_url);
+            });
                }
 
-               private function onStylesheetsLoad(event:Event, request_url:String=null):void {
-                       var xml:XML = new XML(URLLoader(event.target).data);
+               private function onStylesheetsLoad(fileBank:FileBank, filename:String, request_url:String=null):void {
+                       var xml:XML = new XML(fileBank.getAsString(filename));
                        var saved_url:String = SharedObject.getLocal("user_state").data['stylesheet_url'];
                        var saved_name:String= SharedObject.getLocal("user_state").data['stylesheet_name'];
                        if (request_url && request_url!=saved_url) { saved_url=request_url; saved_name='Custom'; }
index 34a4fcc681a166e47bd6a8ff36d7f9e3dba04672..0a8d61086548fd4d982f9a6800b0942e89a2952d 100644 (file)
@@ -6,7 +6,7 @@ package net.systemeD.potlatch2.collections {
        import net.systemeD.halcyon.Map;
        import net.systemeD.halcyon.MapPaint;
        import net.systemeD.halcyon.connection.Connection;
-       import net.systemeD.halcyon.DebugURLRequest;
+       import net.systemeD.halcyon.FileBank;
        import net.systemeD.potlatch2.utils.*;
                
        public class VectorBackgrounds extends EventDispatcher {
@@ -19,14 +19,11 @@ package net.systemeD.potlatch2.collections {
 
                public function init(map:Map):void {
                        _map = map;
-                       var request:DebugURLRequest = new DebugURLRequest("vectors.xml");
-                       var loader:URLLoader = new URLLoader();
-                       loader.addEventListener(Event.COMPLETE, onConfigLoad);
-                       loader.load(request.request);
+            FileBank.getInstance().addFromFile("vectors.xml", onConfigLoad);
                }
 
-               public function onConfigLoad(e:Event):void {
-                       var xml:XML = XML(e.target.data);
+               private function onConfigLoad(fileBank:FileBank, filename:String):void {
+                       var xml:XML = new XML(fileBank.getAsString(filename));
 
                        // reconstitute results as Array, as we can't run .forEach over an XMLList
                        var sets:Array = [];
@@ -75,13 +72,14 @@ package net.systemeD.potlatch2.collections {
                                                                                var gpx_url:String = String(set.url);
 
                                                                                var connection:Connection = new Connection(name, gpx_url, null, null);
-                                                                               var gpx:GpxImporter=new GpxImporter(connection, _map, [gpx_url],
+                                                                               var gpx:GpxImporter=new GpxImporter(connection, _map, 
                                                                                function(success:Boolean,message:String=null):void {
                                                                                        if (!success) return;
                                                                                        var paint:MapPaint = _map.addLayer(connection, "stylesheets/gpx.css");
                                                                                        paint.updateEntityUIs(false, false);
                                                                                        dispatchEvent(new Event("layers_changed"));
                                                                                }, false);
+                                                                               gpx.importFromRemoteFiles([gpx_url]);
                                                                        } else {
                                                                        trace("VectorBackgrounds: configured but not loaded isn't supported yet");
                                                                        }
index 0101db37570e16d7c3abf331c11448e5bbf9fef9..061046b3dffa7a525ad8e0caf1be0f312815ca54 100644 (file)
@@ -201,10 +201,7 @@ package net.systemeD.potlatch2.controller {
                protected function keyExitDrawing():ControllerState {
                        var cs:ControllerState=stopDrawing();
                        if (selectedWay.length==1) { 
-                               if (MainUndoStack.getGlobalStack().undoIfAction(BeginWayAction)) { 
-                                       return new NoSelection();
-                               }
-                               return deleteWay();
+                               return new NoSelection();
                        }
                        return cs;
                }
@@ -344,6 +341,10 @@ package net.systemeD.potlatch2.controller {
                        controller.setCursor("pen");
                }
                override public function exitState(newState:ControllerState):void {
+                       if (selectedWay.length==1 && !MainUndoStack.getGlobalStack().undoIfAction(BeginWayAction)) { 
+                               selectedWay.remove(MainUndoStack.getGlobalStack().addAction);
+                       }
+
             Way(firstSelected).removeEventListener(Connection.WAY_NODE_REMOVED, fixElastic);
             Way(firstSelected).removeEventListener(Connection.WAY_NODE_ADDED, fixElastic);
 
index 8ff494c41c8364e7cae4befb5f8fa69d029ff375..4e19bc091129767133a1aab1426db1b262d66f0d 100644 (file)
@@ -4,6 +4,7 @@ package net.systemeD.potlatch2.controller {
     import net.systemeD.halcyon.connection.*;
     import net.systemeD.halcyon.Map;
        import net.systemeD.potlatch2.tools.Parallelise;
+       import net.systemeD.halcyon.connection.actions.*;
 
     /** The state midway during the use of the "parallelise tool", where a parallel way has been created but is stuck to the 
     * mouse cursor, allowing the user to choose how far from the original way it should go. This transforms it in the process. */
@@ -36,6 +37,10 @@ package net.systemeD.potlatch2.controller {
                override public function processKeyboardEvent(event:KeyboardEvent):ControllerState {
                        if (event.keyCode==27) {                        // Escape
                                Way(firstSelected).remove(MainUndoStack.getGlobalStack().addAction);
+                               // Parallel way wasn't created, so remove it from undo history.
+                               MainUndoStack.getGlobalStack().removeLastIfAction(DeleteWayAction);
+                MainUndoStack.getGlobalStack().removeLastIfAction(CreateEntityAction);
+                               
                                return new NoSelection();
                        }
                        var cs:ControllerState = sharedKeyboardEvents(event);
similarity index 87%
rename from net/systemeD/potlatch2/BackgroundDialog.mxml
rename to net/systemeD/potlatch2/dialogs/BackgroundDialog.mxml
index 4c21149bcf385a106e9b8996a4d71ab64a4a8e97..dfca76ed40c6866a21c5e9698917dc5aa46ce112 100644 (file)
         <mx:DataGridColumn editable="false" headerText="Key" width="70">
                        <mx:itemRenderer>
                                <fx:Component>
-                               <mx:ComboBox
-                                       selectedItem="{FunctionKeyManager.instance().getKeyFor(outerDocument.title,data.name)}"
-                                   dataProvider="{FunctionKeyManager.fkeysCollection}"
-                                       change="FunctionKeyManager.instance().setKeyFromFString(selectedItem as String,outerDocument.title,data.name)" />
+                                       <mx:ComboBox
+                                               selectedItem="{FunctionKeyManager.instance().getKeyFor(outerDocument.title,data.name)}"
+                                           dataProvider="{FunctionKeyManager.fkeysCollection}"
+                                               change="FunctionKeyManager.instance().setKeyFromFString(selectedItem as String,outerDocument.title,data.name)">
+                                               <fx:Script><![CDATA[ import net.systemeD.potlatch2.FunctionKeyManager; ]]></fx:Script>
+                                       </mx:ComboBox>
                                </fx:Component>
                        </mx:itemRenderer>
                </mx:DataGridColumn>
similarity index 52%
rename from net/systemeD/potlatch2/mygpx/MyGpxDialog.mxml
rename to net/systemeD/potlatch2/dialogs/MyGpxDialog.mxml
index 019ab46561e3be61ddc81a191663fb195f8dbeb4..f024c27eb89fdde2fea8d3879b75597b0bf53c78 100644 (file)
@@ -1,11 +1,45 @@
 <?xml version="1.0" encoding="utf-8"?>
-<mx:TitleWindow
+<s:TitleWindow
         xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:mx="library://ns.adobe.com/flex/mx"
-        layout="vertical" showCloseButton="true"
-        horizontalAlign="center" title="My tracks"
-        width="600" height="400"
-        verticalGap="0">
+        xmlns:s="library://ns.adobe.com/flex/spark"
+        title="My tracks"
+        width="600" height="400">
+
+  <s:layout>
+    <s:VerticalLayout />
+  </s:layout>
+   
+  <s:HGroup width="100%" horizontalAlign="center" verticalAlign="middle" paddingTop="5">
+    <s:RichText text="Traces" id="results" />
+  </s:HGroup>
+  <s:DataGrid dataProvider="{traces}" width="100%" height="100%" id="traceGrid">
+    <s:columns>
+      <s:ArrayCollection>
+        <s:GridColumn editable="false" dataField="id" headerText="id" width="45"/>
+        <s:GridColumn editable="false" dataField="filename" headerText="filename"/>
+        <s:GridColumn editable="false" dataField="description" headerText="description"/>
+        <s:GridColumn editable="false" dataField="tagsText" headerText="tags"/>
+        <s:GridColumn editable="false">
+          <s:itemRenderer>
+            <fx:Component>
+              <s:GridItemRenderer>
+                <s:VGroup horizontalAlign="center" verticalAlign="middle" width="100%" height="100%">
+                  <s:Button label="Load"
+                      click="outerDocument.loadFile(data)"/>
+                </s:VGroup>
+              </s:GridItemRenderer>
+            </fx:Component>
+          </s:itemRenderer>
+        </s:GridColumn>
+      </s:ArrayCollection>
+    </s:columns>
+  </s:DataGrid>
+
+  <s:controlBarContent>
+    <s:Button label="Refresh List" click="fetchList(true)" />
+  </s:controlBarContent>
+
   <fx:Script><![CDATA[
     import mx.managers.PopUpManager;
     import mx.events.CloseEvent;
@@ -29,9 +63,9 @@
         PopUpManager.centerPopUp(this);
         this.addEventListener(CloseEvent.CLOSE, myGpxDialog_close);
 
-               // >>>> REFACTOR: really horrible way of getting both map and connection
+        // >>>> REFACTOR: really horrible way of getting both map and connection
         map = Globals.vars.root;
-               conn = map.editableLayer.connection;
+        conn = map.editableLayer.connection;
 
         conn.addEventListener(Connection.TRACES_LOADED, onTracesLoaded);
         SaveManager.ensureAccess(fetchList, conn);
 
     [Bindable(event="traces_loaded")]
     private function get traces():VectorCollection {
-               return new VectorCollection(conn.getTraces());
+        return new VectorCollection(conn.getTraces().sort(f).reverse());
     }
 
-    public function loadFile(t:Trace):void {
+    private function f(a:Trace, b:Trace):int {
+        return a.id - b.id
+    }
+
+    public function loadFile(o:Object):void {
+        var t:Trace = Trace(o);
         t.addToMap();
     }
 
     }
               ]]>
   </fx:Script>
-
-  <mx:Text text="Traces" id="results" />
-  <mx:DataGrid dataProvider="{traces}" width="100%" height="100%" id="traceGrid">
-    <mx:columns>
-            <mx:DataGridColumn editable="false" dataField="id" headerText="id" width="45"/>
-            <mx:DataGridColumn editable="false" dataField="filename" headerText="filename"/>
-            <mx:DataGridColumn editable="false" dataField="description" headerText="description"/>
-            <mx:DataGridColumn editable="false" dataField="tagsText" headerText="tags"/>
-            <mx:DataGridColumn editable="false">
-              <mx:itemRenderer>
-                <fx:Component>
-                  <mx:VBox>
-                    <mx:Button label="Load"
-                      click="parentDocument.loadFile(data)"/>
-                  </mx:VBox>
-                </fx:Component>
-              </mx:itemRenderer>
-            </mx:DataGridColumn>
-    </mx:columns>
-  </mx:DataGrid>
-  <mx:ControlBar>
-    <mx:Button label="Refresh List" click="fetchList(true)" />
-  </mx:ControlBar>
-</mx:TitleWindow>
\ No newline at end of file
+</s:TitleWindow>
\ No newline at end of file
similarity index 52%
rename from net/systemeD/potlatch2/VectorSourceDialog.mxml
rename to net/systemeD/potlatch2/dialogs/VectorSourceDialog.mxml
index 5f49e1042bf228653404cb851e4605f5549ad78c..615bd36df5b05726a84da333ff0a13fa02945b3a 100644 (file)
@@ -2,9 +2,10 @@
 <mx:TitleWindow
         xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:mx="library://ns.adobe.com/flex/mx"
+               xmlns:s="library://ns.adobe.com/flex/spark"
         layout="vertical" showCloseButton="true"
         horizontalAlign="center" title="Load vector file"
-        width="500" height="450" verticalGap="0">
+        width="630" height="450" verticalGap="0">
 
        <mx:DataGrid editable="true" width="100%" height="100%" id="dataGrid" 
                dataProvider="{vectorLayers}" itemEditEnd="dataEdited(event)">
                <mx:LinkButton label="Delete" click="removeLayer()" enabled="{dataGrid.selectedItem != null &amp;&amp; dataGrid.selectedItem.isBackground}"/>
        </mx:HBox>
 
-       <mx:VBox width="100%" paddingTop="10">
-               <mx:HRule width="100%" />
-               <!-- ** FIXME: this looks horrid - make into a nicely laid out form -->
-               <mx:Label text="Add new vector layer" fontSize="12" fontWeight="bold" />
-               <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="kml" id="kml" label="KML" />
-                       <mx:RadioButton width="100%" groupName="filetype" value="osm" id="osm" label="OSM" />
-                       <mx:RadioButton width="100%" groupName="filetype" value="shp" id="shp" label="Shapefile" />
-               </mx:HBox>
-               <mx:HBox>
-                       <mx:Label text="Shapefile projection:" />
-                       <mx:ComboBox id="projection"> 
-                               <mx:ArrayCollection>
-                                       <fx:Object label="Lat/long" data="" />
+       <fx:Declarations>
+               <s:RadioButtonGroup id="filetype" />
+       </fx:Declarations>
+       <s:Form id="addlayer" width="100%">
+               <s:FormHeading label="Add new vector layer" />
+
+               <s:FormItem label="File type:">
+                       <s:HGroup>
+                               <s:RadioButton groupName="filetype" value="gpx" id="gpx" label="GPX" selected="true" />
+                               <s:RadioButton groupName="filetype" value="kml" id="kml" label="KML" />
+                               <s:RadioButton groupName="filetype" value="osm" id="osm" label="OSM" />
+                               <s:RadioButton groupName="filetype" value="shp" id="shp" label="Shapefile" />
+                       </s:HGroup>
+                       <s:helpContent><s:Label text="Type of data to load"/></s:helpContent>
+               </s:FormItem>
+
+               <s:FormItem label="Projection:">
+                       <s:DropDownList id="projection" selectedIndex="0" width="200"> 
+                               <s:ArrayCollection>
+                                       <fx:Object label="Lat/long (EPSG:4326)" data="" />
                                        <fx:Object label="Ordnance Survey GB" data="EPSG:27700" />
                                        <fx:Object label="NAD83" data="EPSG:4269" />
-                               </mx:ArrayCollection>
-                       </mx:ComboBox>
-                       <mx:CheckBox width="100%" label="Simplify paths" id="simplify" />
-               </mx:HBox>
-               <mx:HBox>
-                       <mx:Text text="URL:"/>
-                       <mx:TextInput width="100%" id="src" text="" change="selectByExtension()" />
-                       <mx:Button label="Load" click="loadFiles(src.text, filetype.selectedValue.toString(), simplify.selected, projection.selectedItem.data);" enabled="{src.text == '' ? false : true}"/>
-               </mx:HBox>
-               <mx:HBox>
-                       <mx:Text text="Tag transform:"/>
-                       <mx:TextInput width="100%" id="transformsrc" text="{CSSTransform.getInstance().url}"/>
-                       <mx:Button label="Load" click="loadTransform(transformsrc.text);" enabled="{transformsrc.text == '' ? false : true}"/>
-                       <mx:Button label="Clear" click="clearTransform();" enabled="{transformsrc.text == '' ? false : true}"/>
-               </mx:HBox>
-       </mx:VBox>
+                               </s:ArrayCollection>
+                       </s:DropDownList>
+                       <s:helpContent><s:Label text="Shapefiles only"/></s:helpContent>
+               </s:FormItem>
+
+               <s:FormItem label="Simplify:">
+                       <s:CheckBox label="Enabled" id="simplify" />
+                       <s:helpContent><s:Label text="Reduce points in paths"/></s:helpContent>
+               </s:FormItem>
+
+        <s:FormItem label="File:">
+                       <s:HGroup>
+                               <s:Button label="Open..." click="loadFileLocal()" />
+                               <s:Rect width="20" height="1" />
+                   <s:TextInput id="src" text="" change="selectByExtension()" />
+                               <s:Button label="Fetch" click="loadFiles(src.text);" enabled="{src.text == '' ? false : true}"/>
+                       </s:HGroup>
+            <s:helpContent><s:Label text="URL of file to load" /></s:helpContent>
+        </s:FormItem>
+
+        <s:FormItem label="Tag transform:">
+                       <s:HGroup>
+                               <s:Button label="Open..." click="loadTransformLocal()" />
+                               <s:Rect width="20" height="1" />
+                               <s:TextInput id="transformsrc" text="{CSSTransform.getInstance().url}"/>
+                               <s:Button label="Fetch" click="loadTransform(transformsrc.text);" enabled="{transformsrc.text == '' ? false : true}"/>
+                               <s:Button label="Clear" click="clearTransform();"                 enabled="{transformsrc.text == '' ? false : true}"/>
+                       </s:HGroup>
+            <s:helpContent><s:Label text="MapCSS transformation file" /></s:helpContent>
+        </s:FormItem>
+
+       </s:Form>
 
   <fx:Script><![CDATA[
 
        import mx.controls.Alert;
 
        private var map:Map;
+       private var localFileReference:FileReference;
 
        public function styleEdited(name:String,stylesheet:String):void {
                map.findLayer(name).setStyle(stylesheet);
                return v;
        }
        
+       private function get selectedType():String {
+               return filetype.selectedValue.toString();
+       }
+       
        private function toggleVisibility(event:Event):void {
                map.findLayer(dataGrid.selectedItem.name).visible = !map.findLayer(dataGrid.selectedItem.name).visible;
        }
         PopUpManager.removePopUp(this);
     }
 
-       private function loadFiles(url:String,type:String,simplify:Boolean,projection:String=""):void {
+       /** Launch importer for remotely hosted files. */
+       private function loadFiles(url:String):void {
                var names:Array=url.split('/'); var name:String=names[names.length-1];
-               var stylesheet:String="stylesheets/potlatch.css";
-               if (type=='gpx') { stylesheet="stylesheets/gpx.css"; }
-
                var connection:Connection = new Connection(name, url, null, null, CSSTransform.getInstance());
-
-               var filesLoaded:Function = function(success:Boolean,message:String=null):void {
-                       if (success) {
-                               var paint:MapPaint = map.addLayer(connection, stylesheet);
-                               paint.updateEntityUIs(false, false);
-                               dispatchEvent(new Event("layers_changed"));
-                       } else {
-                               Alert.show(message, 'Error', mx.controls.Alert.OK);
-                       }
+               var importer:Importer = findImporter(connection);
+               if (selectedType=='shp') {
+                       var re:RegExp=/.shp$/i; url=url.replace(re,'');
+                       importer.importFromRemoteFiles([url+".shp",url+".shx",url+".dbf"]);
+               } else {
+                       importer.importFromRemoteFiles([url]);
                }
+       }
+       
+       /** Present an 'Open File' dialogue. */
+       private function loadFileLocal():void {
+               // note scoping issues - http://blog.wrench.com.au/2010/06/16/filereferenceload-keep-it-in-scope/
+               localFileReference=new FileReference(); 
+               var fileTypes:String=selectedType=='shp' ? "*.zip" : ("*.zip;*."+selectedType);
+               localFileReference.browse([new FileFilter(fileTypes,fileTypes)]); 
+               localFileReference.addEventListener(Event.SELECT, selectFileLocal);
+       }
+       
+       /** The user has chosen a file in the local 'Open File' dialogue. */
+       private function selectFileLocal(event:Event):void {
+               var connection:Connection = new Connection(localFileReference.name, '', null, null, CSSTransform.getInstance());
+               var importer:Importer = findImporter(connection);
+               importer.importFromLocalFile(localFileReference);
+       }
+       
+       /** Create an Importer object of the type selected by the user. */
+       private function findImporter(connection:Connection):Importer {
+               var simplifyPath:Boolean=simplify.selected;
+               var reproject:String=projection.selectedItem.data;
+               var stylesheet:String="stylesheets/potlatch.css"; if (selectedType=='gpx') { stylesheet="stylesheets/gpx.css"; }
 
-               if (type=='gpx') {
-                       var gpx:GpxImporter=new GpxImporter(connection, map, [url], filesLoaded, simplify);
-               } else if (type=='kml') {
-                       var kml:KmlImporter=new KmlImporter(connection, map, [url], filesLoaded, simplify);
-               } else if (type=='osm') {
-                       var osm:OsmImporter=new OsmImporter(connection, map, [url], filesLoaded, simplify);
+               switch (selectedType) {
+                       case 'gpx':     return new GpxImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet });
+                       case 'kml':     return new KmlImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet });
+                       case 'osm': return new OsmImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet });
+                       case 'shp': return new ShpImporter(connection, map, filesLoaded, simplifyPath, { stylesheet: stylesheet, projection: reproject });
+               }
+               return null;
+       }
+       
+       /** Callback routine when import has completed. */
+       private function filesLoaded(connection:Connection,options:Object,success:Boolean,message:String=null):void {
+               if (success) {
+                       var paint:MapPaint = map.addLayer(connection, options['stylesheet']);
+                       paint.updateEntityUIs(false, false);
+                       dispatchEvent(new Event("layers_changed"));
                } else {
-                       /* FIXME: 
-                          we're currently hardcoding the projection values. We could populate this directly from 
-                          proj4as, or better still, parse the WKT in the .PRJ file:
-                                       http://trac.osgeo.org/proj4js/ticket/47
-                                       http://trac.osgeo.org/proj4js/changeset/1873
-                       */
-                       var re:RegExp=/.shp$/i; url=url.replace(re,'');
-                       var shp:ShpImporter=new ShpImporter(connection,
-                                                           map,
-                                                           [url+".shp",url+".shx",url+".dbf"], filesLoaded, simplify, projection);
+                       Alert.show(message, 'Error', mx.controls.Alert.OK);
                }
        }
        
+       /** Load CSS transformation file from remote URL. */
        private function loadTransform(url:String):void {
                CSSTransform.getInstance().loadFromUrl(url);
        }
+       /** Load CSS transformation file from local disc. */
+       private function loadTransformLocal():void {
+               localFileReference=new FileReference(); 
+               localFileReference.browse([new FileFilter("MapCSS file","*.css;*.mapcss")]); 
+               localFileReference.addEventListener(Event.SELECT, selectTransformLocal);
+       }
+       private function selectTransformLocal(event:Event):void {
+               localFileReference.addEventListener(Event.COMPLETE, transformFileLoaded);
+               localFileReference.load();
+       }
+       private function transformFileLoaded(event:Event):void {
+               CSSTransform.getInstance().loadFromUrl(event.target.data);
+       }
+       /** Cancel CSS transformation. */
        private function clearTransform():void {
                CSSTransform.getInstance().clear();
        }
index 1d995810a8839dbe2a99fe7f26ba5f0fc6fd874d..6296b29135d663d7f83187d26713773026a0df14 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!---
     The History Dialog displays information about the history of an entity. As well as showing the different versions
-    of the entity, it displays synthetic history based on the entity's children. For example, the intermediate states
-    of a way while the nodes are rearranged are show.
+    of the entity, it displays synthetic history based on its children. For example, the intermediate states
+    of a way while the nodes are rearranged are shown.
 -->
 <s:TitleWindow
         xmlns:fx="http://ns.adobe.com/mxml/2009"
@@ -37,8 +37,7 @@
                 <fx:Component>
                   <s:GridItemRenderer>
                     <s:VGroup horizontalAlign="center" verticalAlign="middle" width="100%" height="100%">
-                      <s:Button label="Contact Mapper"
-                          click="parentDocument.message(data)"/>
+                      <s:Button label="Contact Mapper" click="parentDocument.parentDocument.message(data.user)"/>
                     </s:VGroup>
                   </s:GridItemRenderer>
                 </fx:Component>
@@ -51,7 +50,7 @@
 
 
   <s:controlBarContent>
-    <s:Button label="Revert" enabled="false" styleName="titleWindowButton" />
+    <!-- <s:Button label="Revert" enabled="false" styleName="titleWindowButton" /> -->
     <s:Spacer width="100%"/>
     <s:Button label="More Details..." enabled="{entity.id >= 0}" click="openEntityPage()" styleName="titleWindowButton" />
     <s:Button label="Cancel" click="PopUpManager.removePopUp(this);" styleName="titleWindowButton" />
         return null;
     }
 
-    public function message(entity:Entity):void {
-        if (entity.user != null) {
+    public function message(user:String):void {
+        if (user) {
             var urlBase:String = entity.connection.apiBase + '../../message/new/';
-            navigateToURL(new URLRequest(urlBase+entity.user), "potlatch_message");
+            navigateToURL(new URLRequest(urlBase+user), "potlatch_message");
         }
     }
     ]]>
index 0c246d2fb4b25c01a9e385b35f3823a1e9a4623b..8ae89c8ed5c33fa7bad87a6034ca2fcc14691426 100644 (file)
@@ -8,9 +8,8 @@ package net.systemeD.potlatch2.mapfeatures {
     import mx.core.BitmapAsset;
     import mx.graphics.codec.PNGEncoder;
     
-    import net.systemeD.halcyon.ImageBank;
+    import net.systemeD.halcyon.FileBank;
     import net.systemeD.halcyon.connection.Entity;
-    import net.systemeD.potlatch2.utils.CachedDataLoader;
 
         /** A "map feature" is sort of a template for a map entity. It consists of a few crucial key/value pairs that define the feature, so that
          * entities can be recognised. It also contains optional keys, with associated editing controls, that are defined as being appropriate
@@ -32,10 +31,23 @@ package net.systemeD.potlatch2.mapfeatures {
         public function Feature(mapFeatures:MapFeatures, _xml:XML) {
             this.mapFeatures = mapFeatures;
             this._xml = _xml;
+            loadImages();
             parseConditions();
             parseEditors();
         }
 
+        private function loadImages():void {
+            var icon:XMLList = _xml.icon;
+            if ( icon.length() > 0 ) {
+                if ( icon[0].hasOwnProperty("@dnd") ) {
+                    FileBank.getInstance().addFromFile(icon[0].@dnd);
+                }
+                if ( icon[0].hasOwnProperty("@image") ) {
+                    FileBank.getInstance().addFromFile(icon[0].@image);
+                }
+            }
+        }
+
         private function parseConditions():void {
             _tags = [];
            _withins = [];
@@ -138,6 +150,7 @@ package net.systemeD.potlatch2.mapfeatures {
         /** Fetches the feature's image, as defined by the icon element in the feature definition.
         * @param dnd if true, overrides the normal image and returns the one defined by the dnd property instead. */
         private function getImage(dnd:Boolean = false):ByteArray {
+            var fileBank:FileBank = FileBank.getInstance();
             var icon:XMLList = _xml.icon;
             var imageURL:String;
 
@@ -147,12 +160,12 @@ package net.systemeD.potlatch2.mapfeatures {
                 imageURL = icon[0].@image;
             }
 
-            if ( imageURL ) {
-                               if (ImageBank.getInstance().hasImage(imageURL)) {
-                                       return ImageBank.getInstance().getAsByteArray(imageURL)
-                               } else {
-                       return CachedDataLoader.loadData(imageURL, imageLoaded);
-                               }
+            if ( imageURL && fileBank.hasFile(imageURL) ) {
+                if (fileBank.fileLoaded(imageURL, imageLoaded)) {
+                    return fileBank.getAsByteArray(imageURL);
+                } else {
+                    return null;
+                }
             }
             var bitmap:BitmapAsset = new missingIconCls() as BitmapAsset;
             return new PNGEncoder().encode(bitmap.bitmapData);
@@ -166,7 +179,7 @@ package net.systemeD.potlatch2.mapfeatures {
                return point.length() > 0 && !(XML(point[0]).attribute("draganddrop")[0] == "no");
         }
 
-        private function imageLoaded(url:String, data:ByteArray):void {
+        private function imageLoaded(fileBank:FileBank, url:String):void {
             dispatchEvent(new Event("imageChanged"));
         }
 
index 5dc5b02d518cd1fb3f7f419645543875432e0143..98cd47c39fc422ddd82cbc98a14e4f7ae8ff9bc5 100644 (file)
@@ -4,6 +4,7 @@ package net.systemeD.potlatch2.mapfeatures {
     import flash.events.EventDispatcher;
     import flash.net.*;
     
+    import net.systemeD.halcyon.FileBank;
     import net.systemeD.halcyon.NestedXMLLoader;
     import net.systemeD.halcyon.connection.*;
 
index 2b390c1bbc6c900110b5e3ba91a4c5f4aa1d5ea4..891da56499d8df9ac70fe544218160f72e021add 100644 (file)
@@ -27,11 +27,6 @@ package net.systemeD.potlatch2.mapfeatures.editors {
                 _match = new RegExp("^("+matchStr+")$");
             }
         }
-        
-        public function imageLoaded(url:String, data:ByteArray):void {
-            icon = data;
-            dispatchEvent(new Event("iconLoaded"));
-        }
     }
 
 }
index 6beaa3d478e4f8296b8d7e0bd38ecc6ea11984f9..4cc1e0f2ca1ddb617b4d22550d9048da8027c360 100644 (file)
@@ -2,8 +2,9 @@ package net.systemeD.potlatch2.mapfeatures.editors {
 
     import net.systemeD.halcyon.connection.*;
     import net.systemeD.potlatch2.mapfeatures.*;
-    import net.systemeD.potlatch2.utils.CachedDataLoader;
+    import net.systemeD.halcyon.FileBank;
     import flash.display.*;
+    import flash.events.*;
 
        public class ChoiceEditorFactory extends SingleTagEditorFactory {
            public var choices:Array;
@@ -12,14 +13,22 @@ package net.systemeD.potlatch2.mapfeatures.editors {
             super(inputXML,"horizontal");
             
             choices = [];
+
+            var fileBank:FileBank = FileBank.getInstance();
+            
             for each( var choiceXML:XML in inputXML.choice ) {
                 var choice:Choice = new Choice();
                 choice.value = String(choiceXML.@value);
                 choice.description = String(choiceXML.@description);
                 choice.label = String(choiceXML.@text);
-                choice.icon = choiceXML.hasOwnProperty("@icon") ? 
-                    CachedDataLoader.loadData(String(choiceXML.@icon), choice.imageLoaded) : null;
                 choice.match = String(choiceXML.@match);
+                if (choiceXML.hasOwnProperty("@icon")) {
+                    var icon:String = String(choiceXML.@icon);
+                    fileBank.addFromFile(icon, function (fb:FileBank, name:String):void {
+                        choice.icon = fb.getAsByteArray(name);
+                        choice.dispatchEvent(new Event("iconLoaded"));
+                    });
+                }
                 choices.push(choice);
             }
         }
index 3d281cc6bb6810b647e5c5987287088dc0bf7ded..1fa9155ade5b273dbbd9a8982dbd01fbb35c32e4 100644 (file)
@@ -10,7 +10,7 @@
     <mx:Image x="0" y="0" source="@Embed('../../../../../embedded/restriction.svg')" />
     
     <mx:TextInput id="valueText" text="{data.value==null ? '--' : data.scalar}" editable="{data.isEditable}"
-        fontWeight="bold" fontSize="16" textAlign="center" borderStyle="none"
+        fontWeight="bold" fontSize="16" textAlign="center" borderStyle="none" backgroundAlpha="0"
         width="50" x="0" y="7" />
     
     <mx:Label id="unitText" text="{data.unit}"
diff --git a/net/systemeD/potlatch2/panels/DragAndDropPanel.mxml b/net/systemeD/potlatch2/panels/DragAndDropPanel.mxml
new file mode 100644 (file)
index 0000000..65f6f49
--- /dev/null
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<mx:VBox width="100%" height="100%" horizontalScrollPolicy="off" styleName="dndPanelVbox"
+    xmlns:fx="http://ns.adobe.com/mxml/2009"
+       xmlns:controls="net.systemeD.controls.*"
+       xmlns:mx="library://ns.adobe.com/flex/mx">
+
+       <mx:Text id="dndPanelText" text="{dndPrompt}" width="100%" styleName="helpInfo" />
+       <mx:Repeater id="dndRep" dataProvider="{MapFeatures.getInstance().getCategoriesForType('point')}" styleName="dndRepeater">
+               <mx:HBox width="100%" styleName="dndPanelCategory">
+                       <mx:Label text="{dndRep.currentItem.name}:" styleName="dndPanelCategoryLabel"/>
+                       <mx:Spacer width="100%" />
+                       <mx:Label click="showHide(event)" text="" />
+                       <mx:Image click="showHide(event)" source="{closedIcon}" />
+               </mx:HBox>
+
+               <mx:TileList dataProvider="{dndRep.currentItem.getFeaturesForType('point', true)}" width="100%" height="1"
+                            id="tl" dragEnabled="true" mouseDown="mouseDownHandler(event)" verticalScrollPolicy="off" 
+                            rowHeight="32" columnWidth="100" updateComplete="sizePOIGrid(event)" styleName="dndPanelTileList">
+                       <mx:itemRenderer>
+                               <fx:Component>
+                                       <mx:HBox toolTip="{data.name}" horizontalScrollPolicy="off" >
+                                               <mx:Image id="foo" source="{data.dndimage}" height="24" width="24" toolTip="{data.name}" />
+                                               <mx:Label text="{data.name}" />
+                                       </mx:HBox>
+                               </fx:Component>
+                       </mx:itemRenderer>
+               </mx:TileList>
+       </mx:Repeater>
+
+       <fx:Script><![CDATA[
+
+       import net.systemeD.potlatch2.mapfeatures.*;
+       import mx.core.DragSource;
+       import mx.managers.DragManager;
+       import mx.controls.Image;
+       import mx.controls.Button;
+       import mx.controls.TileList;
+       import mx.controls.scrollClasses.*;
+
+       [Bindable] [Embed(source="../../../../embedded/CollapsiblePanelAssets.swf", symbol="CollapseButtonDown")] private var openIcon:Class;
+       [Bindable] [Embed(source="../../../../embedded/CollapsiblePanelAssets.swf", symbol="CollapseButtonOver")] private var closedIcon:Class;
+
+       [Bindable] public var dndPrompt:String="Add new points by dragging them onto the map";
+
+       private var inited:Object={};
+       private static const MINIMISED_ROWS:uint=2;             // we could perhaps set this by category (e.g. two for shopping, one for tourism...)
+       private static const MINIMISED:uint=0;
+       private static const MAXIMISED:uint=1;
+       private static const TOO_SMALL:uint=2;
+       private static const ICON_WIDTH:uint=24;
+       private static const ICON_HEIGHT:uint=24;
+
+       /** Start POI drag-and-drop. */
+       private function mouseDownHandler(event:MouseEvent):void {
+               if (event.target is ScrollThumb || event.target is Button) return;
+
+               var item:Feature=Feature(TileList(event.currentTarget).selectedItem);
+               var dragInitiator:HBox = event.currentTarget.itemToItemRenderer(item);
+               var dragSource:DragSource = new DragSource();
+               dragSource.addData(item.tags, 'tags');
+               dragSource.addData(event.currentTarget, 'container');
+
+               var dragProxy:Image = new Image();
+               dragProxy.source = item.dndimage;
+               dragProxy.width = ICON_WIDTH;   // must set width and height explicitly
+               dragProxy.height = ICON_HEIGHT; // for non-embedded images
+
+               DragManager.doDrag(dragInitiator, dragSource, event, dragProxy);
+               TileList(event.currentTarget).selectedItem=null;
+       }
+
+       /** Handle user's click on show/hide label. */
+       public function showHide(event:Event):void {
+               // find out which tilelist was clicked
+               var theHBox:HBox=event.currentTarget.parent;
+               var pos:uint=theHBox.parent.getChildIndex(theHBox);
+               var tilelist:TileList=TileList(theHBox.parent.getChildAt(pos+1));
+               
+               // now adjust the number of rows
+               setHeight(tilelist,(isAtMaximumSize(tilelist)));
+       }
+
+       /** Set a POI grid to the correct size when it's created. Non-functional if called later. */
+       private function sizePOIGrid(event:Event):void {
+               var tilelist:TileList=TileList(event.target);
+               if (inited[tilelist]) { return; }
+               inited[tilelist]=true;
+               setHeight(tilelist,true);
+       }
+       
+       /** Set a POI grid to minimised or maximised state, and return the state it's been set to. */
+       private function setHeight(tilelist:TileList,minimise:Boolean):uint {
+               // Set required state
+               var rows:Number=rowsForAll(tilelist);
+               var state:uint;
+               if (rows<=MINIMISED_ROWS) { applyHeight(tilelist,rows); state=TOO_SMALL; }
+               else if (minimise) { applyHeight(tilelist,MINIMISED_ROWS); state=MINIMISED; }
+               else { applyHeight(tilelist,rows); state=MAXIMISED; }
+               
+               // Update the clickable label
+               var pos:uint=tilelist.parent.getChildIndex(tilelist);
+               var hbox:HBox=HBox(tilelist.parent.getChildAt(pos-1));
+               var label:Label=Label(hbox.getChildAt(2));
+               var button:Image=Image(hbox.getChildAt(3));
+               switch (state) {
+                       case TOO_SMALL: label.text="";         button.visible=false; break;
+                       case MINIMISED: label.text="Show all"; button.source =closedIcon; break;
+                       case MAXIMISED: label.text="Collapse"; button.source =openIcon; break;
+               }
+               return state;
+       }
+       
+       /** Called by setHeight to actually apply the row height to the Flex TileList object. */
+       private function applyHeight(tilelist:TileList,rows:uint):void {
+               tilelist.height=rows*(tilelist.rowHeight+1);
+       }
+       
+       /** Is the POI grid at its maximum size? */
+       private function isAtMaximumSize(tilelist:TileList):Boolean {
+               var size:Number=tilelist.height/(tilelist.rowHeight+1);
+               return (size==rowsForAll(tilelist));
+       }
+       
+       /** How many rows are required to show everything in this POI grid? */
+       private function rowsForAll(tilelist:TileList):Number {
+               var rows:Number=tilelist.dataProvider.length/tilelist.columnCount;
+               if (rows!=Math.floor(rows)) { rows=Math.floor(rows+1); }
+               return rows;
+       }
+
+       ]]></fx:Script>
+
+</mx:VBox>
index f345701fc16f4abda2de5d1123f5687c14e64399..2e629a804e1a2681278164e3c85ccac73c933bf0 100644 (file)
             var urlStr:Object = oauthRequest.buildRequest(sig, OAuthRequest.RESULT_TYPE_URL_STRING)
 
                        //register the "pressTry" function so the oAuth callback page can try to advance the editor directly to the next step
-                       ExternalInterface.addCallback("pressTry", pressTry);            
+            if (ExternalInterface.available) {
+                ExternalInterface.addCallback("pressTry", pressTry);
+            }
                        
             // build the actual request
             var urlReq:URLRequest = new URLRequest(String(urlStr));
index 9ea879df7d25a55d7acbe339a6302b8f1afbe24b..fd3214c756de96704ef8e9d2f5be229bffdd0a65 100644 (file)
@@ -6,6 +6,7 @@ package net.systemeD.potlatch2.save {
     import mx.core.Application;
     import mx.core.FlexGlobals;
     import net.systemeD.halcyon.connection.*;
+    import net.systemeD.potlatch2.controller.*;
     import org.iotashan.oauth.*;
 
     public class SaveManager {
@@ -22,6 +23,7 @@ package net.systemeD.potlatch2.save {
         }
 
         private function save(callback:Function, connection:Connection):void {
+                       FlexGlobals.topLevelApplication.theController.setState(new NoSelection());
                        _connection=connection;
             if (connection.hasAccessToken()) {
                 callback();
diff --git a/net/systemeD/potlatch2/utils/CachedDataLoader.as b/net/systemeD/potlatch2/utils/CachedDataLoader.as
deleted file mode 100644 (file)
index 0947c4b..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-package net.systemeD.potlatch2.utils {
-
-       import flash.events.*;
-       import flash.net.*;
-       import flash.utils.ByteArray;
-       import flash.display.BitmapData;
-       import mx.graphics.codec.PNGEncoder;
-
-    import net.systemeD.halcyon.ExtendedURLLoader;
-       import net.systemeD.halcyon.DebugURLRequest;
-
-       public class CachedDataLoader {
-
-        private static var allData:Object = {};
-        private static var requestsMade:Object = {};
-        private static var missingImage:ByteArray = null;
-        
-               public static function loadData(url:String, onLoadHandler:Function = null):ByteArray {
-                   var data:ByteArray = allData[url];
-                   if ( data != null )
-                       return data;
-                   
-                   var requests:Array = requestsMade[url];
-                   if ( requests == null ) {
-                       requests = [];
-                       requestsMade[url] = requests;
-
-                               var request:DebugURLRequest = new DebugURLRequest(url);
-                           var loader:ExtendedURLLoader = new ExtendedURLLoader();
-                   loader.info = url;
-                loader.addEventListener(Event.COMPLETE, imageLoaded);
-                loader.addEventListener(IOErrorEvent.IO_ERROR, imageLoadFailed);
-                loader.dataFormat = URLLoaderDataFormat.BINARY;
-                loader.load(request.request);
-                   }
-                   requests.push(onLoadHandler);
-                   
-                   return allData[url];
-               }
-
-        private static function imageLoaded(event:Event):void {
-            var loader:ExtendedURLLoader = ExtendedURLLoader(event.target);
-            var url:String = loader.info as String;
-            allData[url] = loader.data;
-            dispatchEvents(url);
-        }
-        
-        private static function imageLoadFailed(event:Event):void {
-            var loader:ExtendedURLLoader = ExtendedURLLoader(event.target);
-            var url:String = loader.info as String;
-            
-            allData[url] = getMissingImage();
-            dispatchEvents(url);
-        }
-        
-        private static function dispatchEvents(url:String):void {
-            var requests:Array = requestsMade[url];
-            for each ( var handler:Function in requests ) {
-                handler(url, allData[url]);
-            }
-            
-            delete requestsMade[url];
-        }
-        
-        private static function getMissingImage():ByteArray {
-            if ( missingImage == null ) {
-                var bitmap:BitmapData = new BitmapData(24, 24, false);
-                for ( var i:uint = 0; i < 24; i++ ) {
-                    bitmap.setPixel(i, i, 0xff0000);
-                    bitmap.setPixel(23-i, i, 0xff0000);
-                }
-                missingImage = new PNGEncoder().encode(bitmap);
-            }
-            return missingImage;
-        }
-       }
-}
index 5f0816c3cec636cae75cb5b07fc1e8d02947de8a..88dba75352d117206373d9d047a0e3ed535adb62 100644 (file)
@@ -12,8 +12,8 @@ package net.systemeD.potlatch2.utils {
     */
        public class GpxImporter extends Importer {
 
-               public function GpxImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) {
-                       super(connection,map,filenames,callback,simplify);
+               public function GpxImporter(connection:Connection, map:Map, callback:Function=null, simplify:Boolean=false, options:Object=null) {
+                       super(connection,map,callback,simplify,options);
                }
 
                override protected function doImport(push:Function): void {
index 665e627f9d374921f94fc83f6bfae6611ffaa48d..c3ff6605073142c0177e2f67007ba08050641b0b 100644 (file)
@@ -7,6 +7,8 @@ package net.systemeD.potlatch2.utils {
        import flash.display.LoaderInfo;
        import flash.events.*;
        import flash.net.*;
+       import flash.utils.ByteArray;
+       import nochump.util.zip.*;
 
        public class Importer {
 
@@ -14,22 +16,25 @@ package net.systemeD.potlatch2.utils {
         protected var map:Map;                  // map being used - used only in Simplify calls
 
                public var files:Array=[];
-               protected var filenames:Array;
+               protected var filenames:Array;                  // array of filenames _or_ FileReference objects
                protected var filesloaded:uint=0;
                protected var callback:Function;
                protected var simplify:Boolean;
+               protected var options:Object;
 
-               public function Importer(connection:Connection, map:Map, filenames:Array, callback:Function, simplify:Boolean) {
+               public function Importer(connection:Connection, map:Map, callback:Function, simplify:Boolean, options:Object) {
                        this.connection = connection;
                        this.map = map;
-                       this.filenames=filenames;
                        this.callback=callback;
                        this.simplify=simplify;
-
+                       this.options=options;
+               }
+               
+               public function importFromRemoteFiles(filenames:Array):void {
+                       this.filenames=filenames;
                        // Use forEach to avoid closure problem (http://stackoverflow.com/questions/422784/how-to-fix-closure-problem-in-actionscript-3-as3#3971784)
-                       filenames.forEach(function(fn:String, index:int, array:Array):void {
+                       filenames.forEach(function(file:String, index:int, array:Array):void {
                                trace("requesting file "+index);
-                               var request:URLRequest = new URLRequest(fn);
                                var loader:URLLoader = new URLLoader();
                                loader.dataFormat=URLLoaderDataFormat.BINARY;
                                loader.addEventListener(Event.COMPLETE,function(e:Event):void { fileLoaded(e,index); });
@@ -37,27 +42,61 @@ package net.systemeD.potlatch2.utils {
                                        loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,      securityErrorHandler);
                                        loader.addEventListener(IOErrorEvent.IO_ERROR,                          ioErrorHandler);
                                }
-                               loader.load(request);
+                               loader.load(new URLRequest(file));
                        });
                }
                
-               protected function fileLoaded(e:Event,filenum:uint):void {
-                       files[filenum]=e.target.data;
-                       filesloaded++;
-                       trace("loaded file "+filenum+" ("+filesloaded+"/"+filenames.length+")"); 
-                       if (filesloaded==filenames.length) {
-                var action:CompositeUndoableAction = new CompositeUndoableAction("Import layer "+connection.name);
-                               doImport(action.push);
-                               action.doAction(); // just do it, don't add to undo stack
-                               if (callback!=null) { callback(true); }
+               public function importFromLocalFile(file:FileReference):void {
+                       filenames=['local'];
+                       file.addEventListener(Event.COMPLETE, fileLoaded);
+                       file.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);
+                       file.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);
+                       file.load();
+               }
+               
+               protected function fileLoaded(e:Event,filenum:uint=0):void {
+                       var rawData:ByteArray=e.target.data;
+                       var firstFour:ByteArray=new ByteArray();
+                       rawData.readBytes(firstFour,0,4);
+                       rawData.position=0;
+                       
+                       if (firstFour.toString()=="PK"+String.fromCharCode(3)+String.fromCharCode(4)) {
+                               // Zip file (we assume there'll only be one of these...)
+                               var zip:ZipFile = new ZipFile(rawData);
+                               for (var i:uint=0; i<zip.entries.length; i++) {
+                                       filenames[i]=zip.entries[i].name;
+                                       files[i]=zip.getInput(zip.entries[i]);
+                                       filesloaded++;
+                               }
+                               runImporter();
+                       } else {
+                               // Standard file
+                               files[filenum]=rawData;
+                               filesloaded++;
+                               trace("loaded file "+filenum+" ("+filesloaded+"/"+filenames.length+")"); 
+                               if (filesloaded==filenames.length) { runImporter(); }
+                       }
+               }
+
+               private function runImporter():void {
+                       var action:CompositeUndoableAction = new CompositeUndoableAction("Import layer "+connection.name);
+                       doImport(action.push);
+                       action.doAction(); // just do it, don't add to undo stack
+                       if (callback!=null) { callback(connection,options,true); }
+               }
+
+               protected function getFileByName(regex:RegExp):* {
+                       for (var i:uint=0; i<filenames.length; i++) {
+                               if (filenames[i].match(regex)) { return files[i]; }
                        }
+                       return null;
                }
                
                protected function doImport(push:Function):void {
                }
 
-               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."); }
+               protected function securityErrorHandler( event:SecurityErrorEvent ):void { callback(connection,options,false,"You don't have permission to open that file."); }
+               protected function ioErrorHandler( event:IOErrorEvent ):void { callback(connection,options,false,"The file could not be loaded."); }
 
        }
 }
index 302fa8f758bb357239d6592851a8cb8c00bbef8e..f5ebe5c14d148c89146eb550252967bed7b6c689 100644 (file)
@@ -13,8 +13,8 @@ package net.systemeD.potlatch2.utils {
      */
     public class KmlImporter extends Importer {
 
-        public function KmlImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) {
-            super(connection, map, filenames, callback, simplify);
+        public function KmlImporter(connection:Connection, map:Map, callback:Function=null, simplify:Boolean=false, options:Object=null) {
+            super(connection, map, callback, simplify, options);
         }
 
         override protected function doImport(push:Function): void {
index 3e7b0c1a33d9eb4c356d996cacb35461effc4344..550024f5f84c0a1d5432cd0896a52a4bed5063ed 100644 (file)
@@ -6,8 +6,8 @@ package net.systemeD.potlatch2.utils {
 
        public class OsmImporter extends Importer {
 
-               public function OsmImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false) {
-                       super(connection,map,filenames,callback,simplify);
+               public function OsmImporter(connection:Connection, map:Map, callback:Function=null, simplify:Boolean=false, options:Object=null) {
+                       super(connection,map,callback,simplify,options);
                }
 
                override protected function doImport(push:Function):void {
index dd0cf6cee1a021af090aa35c9e5579dd34119d20..115ce404c24c7e4b51a819272f671f5ef8d47487 100644 (file)
@@ -8,20 +8,23 @@ package net.systemeD.potlatch2.utils {
        import net.systemeD.halcyon.connection.Node;
        import net.systemeD.halcyon.connection.Way;
        import net.systemeD.potlatch2.tools.Simplify;
+       import flash.utils.ByteArray;
 
        public class ShpImporter extends Importer {
 
                private var projection:String;
 
-               public function ShpImporter(connection:Connection, map:Map, filenames:Array, callback:Function=null, simplify:Boolean=false, projection:String="") {
-                       if (projection!='') this.projection=projection;
-                       super(connection,map,filenames,callback,simplify);
+               public function ShpImporter(connection:Connection, map:Map, callback:Function=null, simplify:Boolean=false, options:Object=null) {
+                       if (options[projection]) this.projection=options[projection];
+                       super(connection,map,callback,simplify,options);
                }
 
                override protected function doImport(push:Function): void {
                        // we load .shp as files[0], .shx as files[1], .dbf as files[2]
-                       var shp:ShpHeader=new ShpHeader(files[0]);
-                       var dbf:DbfHeader=new DbfHeader(files[2]);
+                       var shpFile:ByteArray=getFileByName(/.shp$/);
+                       var dbfFile:ByteArray=getFileByName(/.dbf$/);
+                       var shp:ShpHeader=new ShpHeader(shpFile);
+                       var dbf:DbfHeader=new DbfHeader(dbfFile);
 
                        if (projection) {
                                var proj:Proj4as=new Proj4as();
@@ -35,12 +38,12 @@ package net.systemeD.potlatch2.utils {
                        if (shp.shapeType==ShpType.SHAPE_POLYGON || shp.shapeType==ShpType.SHAPE_POLYLINE) {
 
                                // Loop through all polylines in the shape
-                               var polyArray:Array = ShpTools.readRecords(files[0]);
+                               var polyArray:Array = ShpTools.readRecords(shpFile);
                                for (var i:uint=0; i<polyArray.length; i++) {
 
                                        // Get attributes and create a tags hash
                                        // (note that dr.values is a Dictionary)
-                                       var dr:DbfRecord = DbfTools.getRecord(files[2], dbf, i);
+                                       var dr:DbfRecord = DbfTools.getRecord(dbfFile, dbf, i);
                                        var tags:Object={};
                                        for (key in dr.values) {
                                                v=dr.values[key];
index 87c1e5c1f3c95e941833598ed395539555c98d56..3fcc6f063da868fa0835ace42eb7e5f2c9377830 100644 (file)
@@ -99,9 +99,8 @@
                import net.systemeD.potlatch2.collections.*;
                import net.systemeD.potlatch2.controller.*;
                import net.systemeD.potlatch2.help.*;
-               import net.systemeD.potlatch2.options.*;
+               import net.systemeD.potlatch2.dialogs.*;
                import net.systemeD.potlatch2.utils.*;
-        import net.systemeD.potlatch2.mygpx.*;
                import net.systemeD.controls.FloatingAlert;
                import net.systemeD.controls.Spinner;
                import mx.managers.PopUpManager;
 
         public var theMap:Map;
         public var theController:EditController;
-               public var yahoo:Yahoo;
                public var trackLoader:TrackLoader;
                public var toolbox:Toolbox;
         public var bugLoader:BugLoader;
                private function startInit():void {
                        var loader:Loader = new Loader();
                        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, startApp);
-                       loader.load(new URLRequest("FontLibrary.swf"));
+            if (loaderInfo.parameters['font_library']) {
+                           loader.load(new URLRequest(loaderInfo.parameters['font_library']));
+            } else {
+                           loader.load(new URLRequest("FontLibrary.swf"));
+            }
 
             if (loaderInfo.parameters['locale'] && loaderInfo.parameters['locale']!='en_US') {
                 // we don't bother with localisation if the user is en_US, as P2 is in English by default
                 Globals.vars.locale = loaderInfo.parameters['locale'];
+                Globals.vars.locale_paths = loaderInfo.parameters['locale_paths'];
                 dispatchEvent(new LocaleEvent(LocaleEvent.LOAD_LOCALE, loaderInfo.parameters['locale']));
                 dispatchEvent(new LocaleEvent(LocaleEvent.LOAD_LOCALE, 'en_US')); // think en_US is default
                 resourceManager.localeChain = [loaderInfo.parameters['locale'], 'en_US'];
                        theMap.backdrop=b;
             theMap.updateSize(w,h);
                        theMap.addEventListener(MapEvent.SCALE, scaleHandler);
-
-                       yahoo=new Yahoo(theMap);
-                       yahoo.hide();
-                       _root.addChild(yahoo);
                        _root.addChild(theMap);
 
                        // Initialise stylesheets
                        theMap.tileset.blocks=[/google\./i];    // hard-coded block on Google tiles
                        theMap.tileset.setDimming(params['background_dim']    ==null ? true  : params['background_dim']);
                        theMap.tileset.setSharpen(params['background_sharpen']==null ? false : params['background_sharpen']);
-                       Imagery.instance().init(theMap, overlay, yahoo);
+                       Imagery.instance().init(theMap, overlay);
                        Imagery.instance().addEventListener(MapEvent.BUMP, bumpHandler);
                        Imagery.instance().addEventListener(CollectionEvent.SELECT,
                                function(e:CollectionEvent):void { theMap.tileset.init(e.data, e.data!=''); }
                 var gpx_url:String = loaderInfo.parameters['gpx_url'];
 
                 var connection:Connection = new Connection(name, gpx_url, null, null);
-                var gpx:GpxImporter=new GpxImporter(connection, theMap, [gpx_url],
+                var gpx:GpxImporter=new GpxImporter(connection, theMap,
                                                 function(success:Boolean,message:String=null):void {
                                                     if (!success) return;
                                                     var paint:MapPaint = theMap.addLayer(connection, "stylesheets/gpx.css");
                                                     paint.updateEntityUIs(false, false);
                                                     dispatchEvent(new Event("layers_changed"));
                                                 }, false);
+                               gpx.importFromRemoteFiles([gpx_url]);
                        }
 
                        // create GPS trackloader
index 2e296e964d95a5e66d6599169336ad37c7c3f50d..5d0a15ec4fe3763e123214fd535e9716819c9ad6 100644 (file)
@@ -48,7 +48,7 @@
    </inputSet> 
 
   <inputSet id="source">
-    <input type="freetext" category="Details" presence="onTagMatch" name="Source" key="source" description="The primary source of information for this object (GPS, survey, Yahoo, ...)" priority="lowest"/>
+    <input type="freetext" category="Details" presence="onTagMatch" name="Source" key="source" description="The primary source of information for this object (GPS, survey, Bing, ...)" priority="lowest"/>
   </inputSet>
 
   <inputSet id="designation">