Add floating imagery window
authorRichard Fairhurst <richard@systemeD.net>
Sat, 18 Oct 2014 16:13:35 +0000 (17:13 +0100)
committerRichard Fairhurst <richard@systemeD.net>
Sat, 18 Oct 2014 16:13:35 +0000 (17:13 +0100)
net/systemeD/halcyon/Map.as
net/systemeD/halcyon/TileSet.as
net/systemeD/potlatch2/BackgroundSelector.mxml
net/systemeD/potlatch2/collections/Imagery.as
net/systemeD/potlatch2/controller/ControllerState.as
potlatch2.mxml

index 75b15c0..a3a613c 100644 (file)
@@ -80,12 +80,12 @@ package net.systemeD.halcyon {
                
                // ------------------------------------------------------------------------------------------
                /** Map constructor function */
                
                // ------------------------------------------------------------------------------------------
                /** Map constructor function */
-        public function Map() {
+        public function Map(overlay:Sprite) {
                        // Remove any existing sprites
                        while (numChildren) { removeChildAt(0); }
 
                        // Remove any existing sprites
                        while (numChildren) { removeChildAt(0); }
 
-                       // 900913 background
-                       tileset=new TileSet(this);
+                       // Tile background
+                       tileset=new TileSet(this,overlay);
                        addChild(tileset);
 
                        // Container for all MapPaint objects
                        addChild(tileset);
 
                        // Container for all MapPaint objects
@@ -134,7 +134,7 @@ package net.systemeD.halcyon {
                }
                
                /** Move the map to centre on a given latitude/longitude. */
                }
                
                /** Move the map to centre on a given latitude/longitude. */
-               private function updateCoordsFromLatLon(lat:Number,lon:Number):void {
+               public function updateCoordsFromLatLon(lat:Number,lon:Number):void {
                        var cy:Number=-(lat2coord(lat)-mapheight/2);
                        var cx:Number=-(lon2coord(lon)-mapwidth/2);
                        updateCoords(cx,cy);
                        var cy:Number=-(lat2coord(lat)-mapheight/2);
                        var cx:Number=-(lon2coord(lon)-mapwidth/2);
                        updateCoords(cx,cy);
@@ -327,7 +327,7 @@ package net.systemeD.halcyon {
                        if (scale!=MINSCALE) changeScale(scale-1);
                }
 
                        if (scale!=MINSCALE) changeScale(scale-1);
                }
 
-               private function changeScale(newscale:uint):void {
+               public function changeScale(newscale:uint):void {
                        scale=newscale;
                        this.dispatchEvent(new MapEvent(MapEvent.SCALE, {scale:scale}));
                        scalefactor=MASTERSCALE/Math.pow(2,13-scale);
                        scale=newscale;
                        this.dispatchEvent(new MapEvent(MapEvent.SCALE, {scale:scale}));
                        scalefactor=MASTERSCALE/Math.pow(2,13-scale);
index 8f81d7d..db541f5 100644 (file)
@@ -6,6 +6,14 @@ package net.systemeD.halcyon {
        import flash.net.*;
        import flash.system.LoaderContext;
        import flash.utils.Timer;
        import flash.net.*;
        import flash.system.LoaderContext;
        import flash.utils.Timer;
+       import flash.text.TextField;
+       import flash.text.TextFormat;
+
+       import net.systemeD.potlatch2.collections.*;
+       /* -------
+          This currently requires potlatch2.collections.Imagery and
+                                  potlatch2.collections.CollectionEvent which break Halcyon.
+          ------- */
 
     public class TileSet extends Sprite {
 
 
     public class TileSet extends Sprite {
 
@@ -26,7 +34,8 @@ package net.systemeD.halcyon {
                private var count:Number=0;                     // counter incremented to provide a/b/c/d tile swapping
                private static const ROUNDROBIN:RegExp =/\{switch\:([^}]+)\}/;
 
                private var count:Number=0;                     // counter incremented to provide a/b/c/d tile swapping
                private static const ROUNDROBIN:RegExp =/\{switch\:([^}]+)\}/;
 
-               private var map:Map;
+               private var _map:Map;
+               private var _overlay:Sprite;
                private const MAXTILESLOADED:uint=30;
 
                private var sharpenFilter:BitmapFilter = new ConvolutionFilter(3, 3, 
                private const MAXTILESLOADED:uint=30;
 
                private var sharpenFilter:BitmapFilter = new ConvolutionFilter(3, 3, 
@@ -36,10 +45,13 @@ package net.systemeD.halcyon {
                private var sharpening:Boolean = false;
                // http://flylib.com/books/en/2.701.1.170/1/
 
                private var sharpening:Boolean = false;
                // http://flylib.com/books/en/2.701.1.170/1/
 
-        public function TileSet(map:Map) {
-                       this.map=map;
+        public function TileSet(map:Map, overlay:Sprite) {
+                       _map=map;
+                       _overlay=overlay;
                        createSprites();
                        createSprites();
-                       map.addEventListener(MapEvent.NUDGE_BACKGROUND, nudgeHandler);
+                       _map.addEventListener(MapEvent.NUDGE_BACKGROUND, nudgeHandler);
+                       _map.addEventListener(MapEvent.MOVE_END, moveHandler);
+                       _map.addEventListener(MapEvent.RESIZE, resizeHandler);
                }
        
                /** @param params Currently includes "url" and "scheme"
                }
        
                /** @param params Currently includes "url" and "scheme"
@@ -63,7 +75,7 @@ package net.systemeD.halcyon {
                }
 
                private function createSprites():void {
                }
 
                private function createSprites():void {
-                       for (var i:uint=map.MINSCALE; i<=map.MAXSCALE; i++) {
+                       for (var i:uint=_map.MINSCALE; i<=_map.MAXSCALE; i++) {
                                this.addChild(new Sprite());
                        }
                }
                                this.addChild(new Sprite());
                        }
                }
@@ -96,34 +108,34 @@ package net.systemeD.halcyon {
 
                /** Set zoom scale (no update triggerd). */
                public function changeScale(scale:uint):void {
 
                /** Set zoom scale (no update triggerd). */
                public function changeScale(scale:uint):void {
-                       for (var i:uint=map.MINSCALE; i<=map.MAXSCALE; i++) {
-                               this.getChildAt(i-map.MINSCALE).visible=(scale==i);
+                       for (var i:uint=_map.MINSCALE; i<=_map.MAXSCALE; i++) {
+                               this.getChildAt(i-_map.MINSCALE).visible=(scale==i);
                        }
                        }
-                       x=map.lon2coord(map.centre_lon+offset_lon)-map.lon2coord(map.centre_lon);
-                       y=map.lat2coord(map.centre_lat+offset_lat)-map.lat2coord(map.centre_lat);
+                       x=_map.lon2coord(_map.centre_lon+offset_lon)-_map.lon2coord(_map.centre_lon);
+                       y=_map.lat2coord(_map.centre_lat+offset_lat)-_map.lat2coord(_map.centre_lat);
                }
                        
                /** Update bounds of tile area, and request new tiles if needed.  */
                
                public function update():void {
                        if (!baseurl) { return; }
                }
                        
                /** Update bounds of tile area, and request new tiles if needed.  */
                
                public function update():void {
                        if (!baseurl) { return; }
-                       tile_l=lon2tile(map.edge_l-offset_lon);
-                       tile_r=lon2tile(map.edge_r-offset_lon);
-                       tile_t=lat2tile(map.edge_t-offset_lat);
-                       tile_b=lat2tile(map.edge_b-offset_lat);
+                       tile_l=lon2tile(_map.edge_l-offset_lon);
+                       tile_r=lon2tile(_map.edge_r-offset_lon);
+                       tile_t=lat2tile(_map.edge_t-offset_lat);
+                       tile_b=lat2tile(_map.edge_b-offset_lat);
                        for (var tx:int=tile_l; tx<=tile_r; tx++) {
                                for (var ty:int=tile_t; ty<=tile_b; ty++) {
                        for (var tx:int=tile_l; tx<=tile_r; tx++) {
                                for (var ty:int=tile_t; ty<=tile_b; ty++) {
-                                       if (!tiles[map.scale+','+tx+','+ty]) { 
+                                       if (!tiles[_map.scale+','+tx+','+ty]) { 
                                                var loader:Loader = new Loader();
                                                var loader:Loader = new Loader();
-                                               tiles[map.scale+','+tx+','+ty]=loader;
+                                               tiles[_map.scale+','+tx+','+ty]=loader;
                                                loader.contentLoaderInfo.addEventListener(Event.INIT, doImgInit, false, 0, true);
                                                loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, missingTileError, false, 0, true);
                                                loader.contentLoaderInfo.addEventListener(Event.INIT, doImgInit, false, 0, true);
                                                loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, missingTileError, false, 0, true);
-                                               loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, function(e:HTTPStatusEvent):void { tileLoadStatus(e,map.scale,tx,ty); }, false, 0, true);
-                                               loader.load(new URLRequest(tileURL(tx,ty,map.scale)), 
+                                               loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, function(e:HTTPStatusEvent):void { tileLoadStatus(e,_map.scale,tx,ty); }, false, 0, true);
+                                               loader.load(new URLRequest(tileURL(tx,ty,_map.scale)), 
                                                            new LoaderContext(true));
                                                            new LoaderContext(true));
-                                               Sprite(this.getChildAt(map.scale-map.MINSCALE)).addChild(loader);
-                                               loader.x=map.lon2coord(tile2lon(tx));
-                                               loader.y=map.lat2coord(tile2lat(ty));
+                                               Sprite(this.getChildAt(_map.scale-_map.MINSCALE)).addChild(loader);
+                                               loader.x=_map.lon2coord(tile2lon(tx));
+                                               loader.y=_map.lat2coord(tile2lat(ty));
                                                if (sharpening) { loader.filters=[sharpenFilter]; }
                                        }
                                }
                                                if (sharpening) { loader.filters=[sharpenFilter]; }
                                        }
                                }
@@ -151,7 +163,7 @@ package net.systemeD.halcyon {
                        for (var tile:String in tiles) {
                                if (tiles[tile] is Sprite) {
                                        var coords:Array=tile.split(','); var tz:uint=coords[0]; var tx:uint=coords[1]; var ty:uint=coords[1];
                        for (var tile:String in tiles) {
                                if (tiles[tile] is Sprite) {
                                        var coords:Array=tile.split(','); var tz:uint=coords[0]; var tx:uint=coords[1]; var ty:uint=coords[1];
-                                       if (tz!=map.scale || tx<tile_l || tx>tile_r || ty<tile_t || ty<tile_b) {
+                                       if (tz!=_map.scale || tx<tile_l || tx>tile_r || ty<tile_t || ty<tile_b) {
                                                if (tiles[tile].parent) tiles[tile].parent.removeChild(tiles[tile]);
                                                delete tiles[tile];
                                                loadcount--;
                                                if (tiles[tile].parent) tiles[tile].parent.removeChild(tiles[tile]);
                                                delete tiles[tile];
                                                loadcount--;
@@ -181,11 +193,11 @@ package net.systemeD.halcyon {
 
                                default:
                                        if (baseurl.indexOf('{x}')>-1) {
 
                                default:
                                        if (baseurl.indexOf('{x}')>-1) {
-                                               t=baseurl.replace('{zoom}',map.scale).replace('{x}',tx).replace('{y}',ty).replace('{-y}',tmsy);
+                                               t=baseurl.replace('{zoom}',_map.scale).replace('{x}',tx).replace('{y}',ty).replace('{-y}',tmsy);
                                        } else if (baseurl.indexOf('$x')>-1) {
                                        } else if (baseurl.indexOf('$x')>-1) {
-                                               t=baseurl.replace('$z',map.scale).replace('$x',tx).replace('$y',ty).replace('$-y',tmsy);
+                                               t=baseurl.replace('$z',_map.scale).replace('$x',tx).replace('$y',ty).replace('$-y',tmsy);
                                        } else {
                                        } else {
-                                               t=baseurl.replace('!',map.scale).replace('!',tx).replace('!',ty);
+                                               t=baseurl.replace('!',_map.scale).replace('!',tx).replace('!',ty);
                                        }
                                        // also, someone should invent yet another variable substitution scheme
                                        break;
                                        }
                                        // also, someone should invent yet another variable substitution scheme
                                        break;
@@ -211,8 +223,8 @@ package net.systemeD.halcyon {
                public function nudgeHandler(event:MapEvent):void {
                        if (!baseurl) { return; }
                        this.x+=event.params.x; this.y+=event.params.y;
                public function nudgeHandler(event:MapEvent):void {
                        if (!baseurl) { return; }
                        this.x+=event.params.x; this.y+=event.params.y;
-                       offset_lat=map.centre_lat-map.coord2lat(map.lat2coord(map.centre_lat)-this.y);
-                       offset_lon=map.centre_lon-map.coord2lon(map.lon2coord(map.centre_lon)-this.x);
+                       offset_lat=_map.centre_lat-_map.coord2lat(_map.lat2coord(_map.centre_lat)-this.y);
+                       offset_lon=_map.centre_lon-_map.coord2lon(_map.lon2coord(_map.centre_lon)-this.x);
                        update();
                }
 
                        update();
                }
 
@@ -221,18 +233,143 @@ package net.systemeD.halcyon {
                // Co-ordinate conversion functions
 
                private function lon2tile(lon:Number):int {
                // Co-ordinate conversion functions
 
                private function lon2tile(lon:Number):int {
-                       return (Math.floor((lon+180)/360*Math.pow(2,map.scale)));
+                       return (Math.floor((lon+180)/360*Math.pow(2,_map.scale)));
                }
                private function lat2tile(lat:Number):int { 
                }
                private function lat2tile(lat:Number):int { 
-                       return (Math.floor((1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,map.scale)));
+                       return (Math.floor((1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,_map.scale)));
                }
                private function tile2lon(t:int):Number {
                }
                private function tile2lon(t:int):Number {
-                       return (t/Math.pow(2,map.scale)*360-180);
+                       return (t/Math.pow(2,_map.scale)*360-180);
                }
                private function tile2lat(t:int):Number { 
                }
                private function tile2lat(t:int):Number { 
-                       var n:Number=Math.PI-2*Math.PI*t/Math.pow(2,map.scale);
+                       var n:Number=Math.PI-2*Math.PI*t/Math.pow(2,_map.scale);
                        return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
                }
 
                        return (180/Math.PI*Math.atan(0.5*(Math.exp(n)-Math.exp(-n))));
                }
 
+               // ------------------------------------------------------------------
+               // Attribution/terms management
+               // (moved from Imagery.as)
+
+               private var _selected:Object={};
+               public function get selected():Object { return _selected; }
+
+               public function setAttribution():void {
+                       var tf:TextField=TextField(_overlay.getChildAt(0));
+                       tf.text='';
+                       if (!_selected.attribution) return;
+                       var attr:Array=[];
+                       if (_selected.attribution.providers) {
+                               // Bing attribution scheme
+                               for (var provider:String in _selected.attribution.providers) {
+                                       for each (var bounds:Array in _selected.attribution.providers[provider]) {
+                                               if (_map.scale>=bounds[0] && _map.scale<=bounds[1] &&
+                                                 ((_map.edge_l>bounds[3] && _map.edge_l<bounds[5]) ||
+                                                  (_map.edge_r>bounds[3] && _map.edge_r<bounds[5]) ||
+                                          (_map.edge_l<bounds[3] && _map.edge_r>bounds[5])) &&
+                                                 ((_map.edge_b>bounds[2] && _map.edge_b<bounds[4]) ||
+                                                  (_map.edge_t>bounds[2] && _map.edge_t<bounds[4]) ||
+                                                  (_map.edge_b<bounds[2] && _map.edge_t>bounds[4]))) {
+                                                       attr.push(provider);
+                                               }
+                                       }
+                               }
+                       }
+                       if (attr.length==0) return;
+                       tf.text="Background "+attr.join(", ");
+                       positionAttribution();
+                       dispatchEvent(new MapEvent(MapEvent.BUMP, { y: tf.textHeight }));       // don't let the toolbox obscure it
+               }
+               public function positionAttribution():void {
+                       if (!_selected.attribution) return;
+                       var tf:TextField=TextField(_overlay.getChildAt(0));
+                       tf.x=_map.mapwidth  - 5 - tf.textWidth;
+                       tf.y=_map.mapheight - 5 - tf.textHeight;
+               }
+
+               public function setLogo():void {
+                       while (_overlay.numChildren>2) { _overlay.removeChildAt(2); }
+                       if (!_selected.logoData) return;
+                       var logo:Sprite=new Sprite();
+                       logo.addChild(new Bitmap(_selected.logoData));
+                       if (_selected.attribution.url) { logo.buttonMode=true; logo.addEventListener(MouseEvent.CLICK, launchLogoLink, false, 0, true); }
+                       _overlay.addChild(logo);
+                       positionLogo();
+               }
+               public function positionLogo():void {
+                       if (_overlay.numChildren<3) return;
+                       _overlay.getChildAt(2).x=5;
+                       _overlay.getChildAt(2).y=_map.mapheight - 5 - _selected.logoHeight - (_selected.terms_url ? 10 : 0);
+               }
+               private function launchLogoLink(e:Event):void {
+                       if (!_selected.attribution.url) return;
+                       navigateToURL(new URLRequest(_selected.attribution.url), '_blank');
+               }
+               public function setTerms():void {
+                       var terms:TextField=TextField(_overlay.getChildAt(1));
+                       if (!_selected.attribution) { terms.text=''; return; }
+                       if (_selected.attribution && _selected.attribution.text) { terms.text=_selected.attribution.text; }
+                       else { terms.text="Background terms of use"; }
+                       positionTerms();
+                       terms.addEventListener(MouseEvent.CLICK, launchTermsLink, false, 0, true);
+               }
+               private function positionTerms():void {
+                       _overlay.getChildAt(1).x=5;
+                       _overlay.getChildAt(1).y=_map.mapheight - 15;
+               }
+               private function launchTermsLink(e:Event):void {
+                       if (!_selected.attribution.url) return;
+                       navigateToURL(new URLRequest(_selected.attribution.url), '_blank');
+               }
+
+               public function resizeHandler(event:MapEvent):void {
+                       positionLogo();
+                       positionTerms();
+                       positionAttribution();
+               }
+               private function moveHandler(event:MapEvent):void {
+                       setAttribution();
+                       // strictly speaking we should review the collection on every move, but slow
+                       // dispatchEvent(new Event("collection_changed"));
+               }
+
+               // Create overlay sprite
+               public static function overlaySprite():Sprite {
+                       var overlay:Sprite=new Sprite();
+                       var attribution:TextField=new TextField();
+                       attribution.width=220; attribution.height=300;
+                       attribution.multiline=true;
+                       attribution.wordWrap=true;
+                       attribution.selectable=false;
+                       attribution.defaultTextFormat=new TextFormat("_sans", 9, 0, false, false, false);
+                       overlay.addChild(attribution);
+                       var terms:TextField=new TextField();
+                       terms.width=200; terms.height=15;
+                       terms.selectable=false;
+                       terms.defaultTextFormat=new TextFormat("_sans", 9, 0, false, false, true);
+                       overlay.addChild(terms);
+                       return overlay;
+               }
+
+               // ------------------------------------------------------------------
+               // Choose a new background
+               // (moved from setBackground in Imagery.as)
+               
+               public function setBackgroundFromImagery(bg:Object,remember:Boolean):void {
+                       // set background
+                       _selected=bg;
+//                     dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, bg));
+                       _map.tileset.init(bg, bg!='');
+                       // update attribution and logo
+                       _overlay.visible=bg.hasOwnProperty('attribution');
+                       setLogo(); setAttribution(); setTerms();
+                       // save as SharedObject for next time
+                       if (remember) {
+                               var obj:SharedObject = SharedObject.getLocal("user_state","/");
+                               obj.setProperty('background_url' ,String(bg.url));
+                               obj.setProperty('background_name',String(bg.name));
+                               try { obj.flush(); } catch (e:Error) {}
+                       }
+               }
+
        }
 }
        }
 }
index 6ca5c85..2b2739f 100644 (file)
 
     <s:List width="100%" height="100%" id="background"
             labelField="name"
 
     <s:List width="100%" height="100%" id="background"
             labelField="name"
-            change="FlexGlobals.topLevelApplication.bgButton.close(); Imagery.instance().setBackground(background.selectedItem);"
-            dataProvider="{Imagery.instance().getAvailableImagery()}"
-            selectedItem="{Imagery.instance().selected}">
+            change="FlexGlobals.topLevelApplication.bgButton.close(); application.theMap.tileset.setBackgroundFromImagery(background.selectedItem,true);"
+            dataProvider="{Imagery.instance().getAvailableImagery(application.theMap)}"
+            selectedItem="{application.theMap.tileset.selected}">
       <s:layout>
       <s:layout>
-        <s:VerticalLayout requestedRowCount="{Imagery.instance().getAvailableImagery().length}" gap="0" horizontalAlign="contentJustify"/>
+        <s:VerticalLayout requestedRowCount="{Imagery.instance().getAvailableImagery(application.theMap).length}" gap="0" horizontalAlign="contentJustify"/>
       </s:layout>
     </s:List>
 
       </s:layout>
     </s:List>
 
           change="setSharpen(sharpen.selected)" />
     </s:HGroup>
 
           change="setSharpen(sharpen.selected)" />
     </s:HGroup>
 
-    <s:HGroup>
+    <s:HGroup width="100%" horizontalAlign="center">
+      <s:CheckBox label="Show floating window" id="showFloatingMap" selected="{application.floatingMap.visible}" 
+                 change="application.floatingMap.setFloatingMapVisible(showFloatingMap.selected);FlexGlobals.topLevelApplication.bgButton.close();" />
+    </s:HGroup>
+
+    <s:HGroup horizontalAlign="center">
       <s:Button id="editLabel" label="Edit..." click="FlexGlobals.topLevelApplication.bgButton.close(); new BackgroundDialog().init('Background imagery',background,Imagery.instance());" />
       <s:Button label="Vector file..." click="FlexGlobals.topLevelApplication.bgButton.close(); new VectorSourceDialog().init();" />
     </s:HGroup>
       <s:Button id="editLabel" label="Edit..." click="FlexGlobals.topLevelApplication.bgButton.close(); new BackgroundDialog().init('Background imagery',background,Imagery.instance());" />
       <s:Button label="Vector file..." click="FlexGlobals.topLevelApplication.bgButton.close(); new VectorSourceDialog().init();" />
     </s:HGroup>
index ed3709c..2eb9790 100644 (file)
@@ -3,13 +3,13 @@ package net.systemeD.potlatch2.collections {
        import flash.events.*;
        import flash.display.*;
        import flash.net.*;
        import flash.events.*;
        import flash.display.*;
        import flash.net.*;
-       import flash.text.TextField;
        import net.systemeD.halcyon.FileBank;
        import net.systemeD.halcyon.Map;
        import net.systemeD.halcyon.MapEvent;
        import net.systemeD.potlatch2.FunctionKeyManager;
        import mx.collections.ArrayCollection;
     import com.adobe.serialization.json.JSON;
        import net.systemeD.halcyon.FileBank;
        import net.systemeD.halcyon.Map;
        import net.systemeD.halcyon.MapEvent;
        import net.systemeD.potlatch2.FunctionKeyManager;
        import mx.collections.ArrayCollection;
     import com.adobe.serialization.json.JSON;
+       import mx.core.FlexGlobals;
 
        /*
                There's lots of further tidying we can do:
 
        /*
                There's lots of further tidying we can do:
@@ -27,15 +27,9 @@ package net.systemeD.potlatch2.collections {
                public var collection:Array=[];
                private var _selected:Object={};
 
                public var collection:Array=[];
                private var _selected:Object={};
 
-               private var _map:Map;
-               private var _overlay:Sprite;
-
                /* Load catalogue file */
 
                /* Load catalogue file */
 
-               public function init(map:Map, overlay:Sprite):void {
-                       _map = map;
-                       _overlay = overlay;
-
+               public function init():void {
                        // load imagery file
                        var request:URLRequest = new URLRequest(INDEX_URL);
                        var loader:URLLoader = new URLLoader();
                        // load imagery file
                        var request:URLRequest = new URLRequest(INDEX_URL);
                        var loader:URLLoader = new URLLoader();
@@ -43,10 +37,6 @@ package net.systemeD.potlatch2.collections {
                        loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
                        loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
                        loader.load(request);
                        loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
                        loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
                        loader.load(request);
-
-                       // create map listeners
-                       map.addEventListener(MapEvent.MOVE_END, moveHandler);
-                       map.addEventListener(MapEvent.RESIZE, resizeHandler);
                }
 
                private function onImageryIndexLoad(event:Event):void {
                }
 
                private function onImageryIndexLoad(event:Event):void {
@@ -87,7 +77,7 @@ package net.systemeD.potlatch2.collections {
                                                bg.logoData   = fb.getAsBitmapData(name);
                                                bg.logoWidth  = fb.getWidth(name);
                                                bg.logoHeight = fb.getHeight(name);
                                                bg.logoData   = fb.getAsBitmapData(name);
                                                bg.logoWidth  = fb.getWidth(name);
                                                bg.logoHeight = fb.getHeight(name);
-                                               setLogo();
+                                               dispatchEvent(new Event("refreshAttribution"));
                                                });
                                }
                                if (bg.attribution && bg.attribution.data_url) {
                                                });
                                }
                                if (bg.attribution && bg.attribution.data_url) {
@@ -100,11 +90,8 @@ package net.systemeD.potlatch2.collections {
                                }
                        });
                        if (saved.name && !_selected) { collection.push(saved); _selected=saved; }
                                }
                        });
                        if (saved.name && !_selected) { collection.push(saved); _selected=saved; }
-                       setBackground(_selected);
-
-                       // Tell the function key manager that we'd like to receive function key calls
-                       FunctionKeyManager.instance().registerListener('Background imagery',
-                               function(o:String):void { setBackground(findBackgroundWithName(o)); });
+                       if (_selected) dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, _selected));
+                       dispatchEvent(new Event("imageryLoaded"));
                        dispatchEvent(new Event("collection_changed"));
                }
                
                        dispatchEvent(new Event("collection_changed"));
                }
                
@@ -131,112 +118,18 @@ package net.systemeD.potlatch2.collections {
             }
                        default xml namespace = new Namespace("");
                        bg.attribution.providers=providers;
             }
                        default xml namespace = new Namespace("");
                        bg.attribution.providers=providers;
-                       setAttribution();
+                       dispatchEvent(new Event("refreshAttribution"));
                }
 
                }
 
-               public function setBackground(bg:Object):void {
-                       // set background
-                       _selected=bg;
-                       dispatchEvent(new CollectionEvent(CollectionEvent.SELECT, bg));
-                       // update attribution and logo
-                       _overlay.visible=bg.hasOwnProperty('attribution');
-                       setLogo(); setAttribution(); setTerms();
-                       // save as SharedObject for next time
-                       var obj:SharedObject = SharedObject.getLocal("user_state","/");
-                       obj.setProperty('background_url' ,String(bg.url));
-                       obj.setProperty('background_name',String(bg.name));
-                       try { obj.flush(); } catch (e:Error) {}
-               }
-               
                public function get selected():Object { return _selected; }
                
                public function get selected():Object { return _selected; }
                
-               private function findBackgroundWithName(name:String):Object {
+               public function findBackgroundWithName(name:String):Object {
                        for each (var bg:Object in collection) {
                                if (bg.name==name) { return bg; }
                        }
                        return { url:'' };
                }
 
                        for each (var bg:Object in collection) {
                                if (bg.name==name) { return bg; }
                        }
                        return { url:'' };
                }
 
-               private function moveHandler(event:MapEvent):void {
-                       setAttribution();
-                       dispatchEvent(new Event("collection_changed"));
-               }
-
-               /* --------------------
-                  Attribution and logo */
-
-               private function setAttribution():void {
-                       var tf:TextField=TextField(_overlay.getChildAt(0));
-                       tf.text='';
-                       if (!_selected.attribution) return;
-                       var attr:Array=[];
-                       if (_selected.attribution.providers) {
-                               // Bing attribution scheme
-                               for (var provider:String in _selected.attribution.providers) {
-                                       for each (var bounds:Array in _selected.attribution.providers[provider]) {
-                                               if (_map.scale>=bounds[0] && _map.scale<=bounds[1] &&
-                                                 ((_map.edge_l>bounds[3] && _map.edge_l<bounds[5]) ||
-                                                  (_map.edge_r>bounds[3] && _map.edge_r<bounds[5]) ||
-                                          (_map.edge_l<bounds[3] && _map.edge_r>bounds[5])) &&
-                                                 ((_map.edge_b>bounds[2] && _map.edge_b<bounds[4]) ||
-                                                  (_map.edge_t>bounds[2] && _map.edge_t<bounds[4]) ||
-                                                  (_map.edge_b<bounds[2] && _map.edge_t>bounds[4]))) {
-                                                       attr.push(provider);
-                                               }
-                                       }
-                               }
-                       }
-                       if (attr.length==0) return;
-                       tf.text="Background "+attr.join(", ");
-                       positionAttribution();
-                       dispatchEvent(new MapEvent(MapEvent.BUMP, { y: tf.textHeight }));       // don't let the toolbox obscure it
-               }
-               private function positionAttribution():void {
-                       var tf:TextField=TextField(_overlay.getChildAt(0));
-                       tf.x=_map.mapwidth  - 5 - tf.textWidth;
-                       tf.y=_map.mapheight - 5 - tf.textHeight;
-               }
-
-               private function setLogo():void {
-                       while (_overlay.numChildren>2) { _overlay.removeChildAt(2); }
-                       if (!_selected.logoData) return;
-                       var logo:Sprite=new Sprite();
-                       logo.addChild(new Bitmap(_selected.logoData));
-                       if (_selected.attribution.url) { logo.buttonMode=true; logo.addEventListener(MouseEvent.CLICK, launchLogoLink, false, 0, true); }
-                       _overlay.addChild(logo);
-                       positionLogo();
-               }
-               private function positionLogo():void {
-                       _overlay.getChildAt(2).x=5;
-                       _overlay.getChildAt(2).y=_map.mapheight - 5 - _selected.logoHeight - (_selected.terms_url ? 10 : 0);
-               }
-               private function launchLogoLink(e:Event):void {
-                       if (!_selected.attribution.url) return;
-                       navigateToURL(new URLRequest(_selected.attribution.url), '_blank');
-               }
-               private function setTerms():void {
-                       var terms:TextField=TextField(_overlay.getChildAt(1));
-                       if (!_selected.attribution) { terms.text=''; return; }
-                       if (_selected.attribution && _selected.attribution.text) { terms.text=_selected.attribution.text; }
-                       else { terms.text="Background terms of use"; }
-                       positionTerms();
-                       terms.addEventListener(MouseEvent.CLICK, launchTermsLink, false, 0, true);
-               }
-               private function positionTerms():void {
-                       _overlay.getChildAt(1).x=5;
-                       _overlay.getChildAt(1).y=_map.mapheight - 15;
-               }
-               private function launchTermsLink(e:Event):void {
-                       if (!_selected.attribution.url) return;
-                       navigateToURL(new URLRequest(_selected.attribution.url), '_blank');
-               }
-
-               private function resizeHandler(event:MapEvent):void {
-                       if (_selected.logoData) positionLogo();
-                       if (_selected.terms_url) positionTerms();
-                       if (_selected.attribution) positionAttribution();
-               }
-
         [Bindable(event="collection_changed")]
         public function getCollection():ArrayCollection {
             return new ArrayCollection(collection);
         [Bindable(event="collection_changed")]
         public function getCollection():ArrayCollection {
             return new ArrayCollection(collection);
@@ -246,24 +139,24 @@ package net.systemeD.potlatch2.collections {
                   Imagery index parser */
 
                [Bindable(event="collection_changed")]
                   Imagery index parser */
 
                [Bindable(event="collection_changed")]
-               public function getAvailableImagery():ArrayCollection {
+               public function getAvailableImagery(map:Map):ArrayCollection {
                        var available:Array=[];
                        for each (var bg:Object in collection) {
                                if (bg.extent && bg.extent.polygon) {
                                        // check if in boundary polygon
                                        var included:Boolean=false;
                                        for each (var poly:Array in bg.extent.polygon) {
                        var available:Array=[];
                        for each (var bg:Object in collection) {
                                if (bg.extent && bg.extent.polygon) {
                                        // check if in boundary polygon
                                        var included:Boolean=false;
                                        for each (var poly:Array in bg.extent.polygon) {
-                                               if (pointInPolygon(_map.centre_lon, _map.centre_lat, poly)) { included=true; }
+                                               if (pointInPolygon(map.centre_lon, map.centre_lat, poly)) { included=true; }
                                        }
                                        if (included) { available.push(bg); }
                                } else if (bg.extent && bg.extent.bbox && bg.extent.bbox.min_lon) {
                                        // if there's a bbox, check the current viewport intersects it
                                        }
                                        if (included) { available.push(bg); }
                                } else if (bg.extent && bg.extent.bbox && bg.extent.bbox.min_lon) {
                                        // if there's a bbox, check the current viewport intersects it
-                                       if (((_map.edge_l>bg.extent.bbox.min_lon && _map.edge_l<bg.extent.bbox.max_lon) ||
-                                            (_map.edge_r>bg.extent.bbox.min_lon && _map.edge_r<bg.extent.bbox.max_lon) ||
-                                            (_map.edge_l<bg.extent.bbox.min_lon && _map.edge_r>bg.extent.bbox.max_lon)) &&
-                                           ((_map.edge_b>bg.extent.bbox.min_lat && _map.edge_b<bg.extent.bbox.max_lat) ||
-                                            (_map.edge_t>bg.extent.bbox.min_lat && _map.edge_t<bg.extent.bbox.max_lat) ||
-                                            (_map.edge_b<bg.extent.bbox.min_lat && _map.edge_t>bg.extent.bbox.max_lat))) {
+                                       if (((map.edge_l>bg.extent.bbox.min_lon && map.edge_l<bg.extent.bbox.max_lon) ||
+                                            (map.edge_r>bg.extent.bbox.min_lon && map.edge_r<bg.extent.bbox.max_lon) ||
+                                            (map.edge_l<bg.extent.bbox.min_lon && map.edge_r>bg.extent.bbox.max_lon)) &&
+                                           ((map.edge_b>bg.extent.bbox.min_lat && map.edge_b<bg.extent.bbox.max_lat) ||
+                                            (map.edge_t>bg.extent.bbox.min_lat && map.edge_t<bg.extent.bbox.max_lat) ||
+                                            (map.edge_b<bg.extent.bbox.min_lat && map.edge_t>bg.extent.bbox.max_lat))) {
                                                available.push(bg);
                                        }
                                } else if (!bg.type || bg.type!='wms') {
                                                available.push(bg);
                                        }
                                } else if (!bg.type || bg.type!='wms') {
index fa73da2..eebb743 100644 (file)
@@ -291,11 +291,12 @@ package net.systemeD.potlatch2.controller {
                /** Create an action to add "source=*" tag to current entity based on background imagery. This is a convenient shorthand for users. */
                protected function setSourceTag():void {
                        if (selectCount!=1) { return; }
                /** Create an action to add "source=*" tag to current entity based on background imagery. This is a convenient shorthand for users. */
                protected function setSourceTag():void {
                        if (selectCount!=1) { return; }
-                       if (!Imagery.instance().selected) { return; }
-                       var sourceTag:String = Imagery.instance().selected.sourcetag || Imagery.instance().selected.id || Imagery.instance().selected.name;
+                       var bg:Object=controller.map.tileset.selected;
+                       if (!bg) { return; }
+                       var sourceTag:String = bg.sourcetag || bg.id || bg.name;
                        if (sourceTag=='None') { return; }
                        if ("sourcekey" in Imagery.instance().selected) {
                        if (sourceTag=='None') { return; }
                        if ("sourcekey" in Imagery.instance().selected) {
-                           firstSelected.setTag(Imagery.instance().selected.sourcekey, sourceTag, MainUndoStack.getGlobalStack().addAction);
+                           firstSelected.setTag(bg.sourcekey, sourceTag, MainUndoStack.getGlobalStack().addAction);
                        } else {
                            firstSelected.setTag('source', sourceTag, MainUndoStack.getGlobalStack().addAction);
                        }
                        } else {
                            firstSelected.setTag('source', sourceTag, MainUndoStack.getGlobalStack().addAction);
                        }
index 5fbe9cb..36dac00 100644 (file)
         public var theController:EditController;
                public var trackLoader:TrackLoader;
                public var toolbox:Toolbox;
         public var theController:EditController;
                public var trackLoader:TrackLoader;
                public var toolbox:Toolbox;
+               public var floatingMap:FloatingMap;
         public var bugLoader:BugLoader;
         public var bikeShopLoader:BikeShopLoader;
 
         public var bugLoader:BugLoader;
         public var bikeShopLoader:BikeShopLoader;
 
                        for (k in SharedObject.getLocal('user_state',"/").data) params[k]=SharedObject.getLocal('user_state',"/").data[k];
 
                        // Create map
                        for (k in SharedObject.getLocal('user_state',"/").data) params[k]=SharedObject.getLocal('user_state',"/").data[k];
 
                        // Create map
-                       theMap=new Map();
+                       var overlay:Sprite=TileSet.overlaySprite();
+                       theMap=new Map(overlay);
                        theMap.backdrop=b;
             theMap.updateSize(w,h);
                        theMap.addEventListener(MapEvent.SCALE, scaleHandler);
                        _root.addChild(theMap);
                        theMap.backdrop=b;
             theMap.updateSize(w,h);
                        theMap.addEventListener(MapEvent.SCALE, scaleHandler);
                        _root.addChild(theMap);
+                       _root.addChild(overlay);
 
                        // Initialise stylesheets
                        Stylesheets.instance().init();
 
                        // Initialise stylesheets
                        Stylesheets.instance().init();
                        //           until the user has decided where to start editing (e.g. when the first GPX loads)
                        theMap.init(params['lat'], params['lon'], params['zoom']);
 
                        //           until the user has decided where to start editing (e.g. when the first GPX loads)
                        theMap.init(params['lat'], params['lon'], params['zoom']);
 
-                       // add attribution/logo sprite
-                       var overlay:Sprite=new Sprite();
-                       var attribution:TextField=new TextField();
-                       attribution.width=220; attribution.height=300;
-                       attribution.multiline=true;
-                       attribution.wordWrap=true;
-                       attribution.selectable=false;
-                       attribution.defaultTextFormat=new TextFormat("_sans", 9, 0, false, false, false);
-                       overlay.addChild(attribution);
-                       var terms:TextField=new TextField();
-                       terms.width=200; terms.height=15;
-                       terms.selectable=false;
-                       terms.defaultTextFormat=new TextFormat("_sans", 9, 0, false, false, true);
-                       overlay.addChild(terms);
-                       _root.addChild(overlay);
-
                        // mouse-up handler attached to stage, so the user can release outside the map
                        stage.addEventListener(MouseEvent.MOUSE_UP, theMap.mouseUpHandler);
                        Globals.vars.map_area.addEventListener(MouseEvent.MOUSE_MOVE, theMap.mouseMoveHandler);
                        // mouse-up handler attached to stage, so the user can release outside the map
                        stage.addEventListener(MouseEvent.MOUSE_UP, theMap.mouseUpHandler);
                        Globals.vars.map_area.addEventListener(MouseEvent.MOUSE_MOVE, theMap.mouseMoveHandler);
                        theMap.tileset.setDimming(params['background_dim']    ==null ? true  : params['background_dim']);
                        theMap.tileset.setSharpen(params['background_sharpen']==null ? false : params['background_sharpen']);
                        var imagery:Imagery = Imagery.instance();
                        theMap.tileset.setDimming(params['background_dim']    ==null ? true  : params['background_dim']);
                        theMap.tileset.setSharpen(params['background_sharpen']==null ? false : params['background_sharpen']);
                        var imagery:Imagery = Imagery.instance();
-                       imagery.init(theMap, overlay);
+                       imagery.init();
+                       theMap.tileset.init(imagery.selected, imagery.selected != '');
                        imagery.addEventListener(MapEvent.BUMP, bumpHandler);
                        imagery.addEventListener(CollectionEvent.SELECT,
                        imagery.addEventListener(MapEvent.BUMP, bumpHandler);
                        imagery.addEventListener(CollectionEvent.SELECT,
-                               function(e:CollectionEvent):void { theMap.tileset.init(e.data, e.data!=''); }
+                               function(e:CollectionEvent):void { 
+                                       theMap.tileset.setBackgroundFromImagery(e.data,false);
+                               }
                        );
                        );
-                       theMap.tileset.init(imagery.selected, imagery.selected != '');
+                       imagery.addEventListener('imageryLoaded',function(e:Event):void {
+                               // Tell the function key manager that we'd like to receive function key calls
+                               FunctionKeyManager.instance().registerListener('Background imagery',
+                                       function(o:String):void { theMap.tileset.setBackgroundFromImagery(imagery.findBackgroundWithName(o),true); });
+                               dispatchEvent(new Event("collection_changed"));
+                       });
+                       imagery.addEventListener('refreshAttribution',function(e:Event):void {
+                               theMap.tileset.setLogo(); theMap.tileset.setAttribution(); theMap.tileset.setTerms(); 
+                       });
                        
                        // keyboard event attached to stage
                        stage.addEventListener(KeyboardEvent.KEY_UP, theMap.keyUpHandler);
                        
                        // keyboard event attached to stage
                        stage.addEventListener(KeyboardEvent.KEY_UP, theMap.keyUpHandler);
                        theController.addEventListener(AttentionEvent.ATTENTION, onAttention);
                        theController.addEventListener(AttentionEvent.ALERT, onAlert);
                        theController.addEventListener(EditController.CHANGED_STATE, onStateChanged);
                        theController.addEventListener(AttentionEvent.ATTENTION, onAttention);
                        theController.addEventListener(AttentionEvent.ALERT, onAlert);
                        theController.addEventListener(EditController.CHANGED_STATE, onStateChanged);
-            
+
+                       // add floating map
+                       floatingMap=FloatingMap(PopUpManager.createPopUp(this,FloatingMap,false));
+                       floatingMap.visible=false;
+                       floatingMap.init(theController);
+                       floatingMap.x=stage.stageWidth-410;
+                       floatingMap.y=36;
+
             // set the access token from saved cookie
             var tokenObject:SharedObject = SharedObject.getLocal("access_token","/");
             conn.setAccessToken(tokenObject.data["oauth_token"], tokenObject.data["oauth_token_secret"]);
             // set the access token from saved cookie
             var tokenObject:SharedObject = SharedObject.getLocal("access_token","/");
             conn.setAccessToken(tokenObject.data["oauth_token"], tokenObject.data["oauth_token_secret"]);