add support for provider attribution and logo, as required by Bing. Add an entry...
authorRichard Fairhurst <richard@systemed.net>
Tue, 30 Nov 2010 00:48:21 +0000 (00:48 +0000)
committerRichard Fairhurst <richard@systemed.net>
Tue, 30 Nov 2010 00:48:21 +0000 (00:48 +0000)
  <set>
<name>Bing</name>
<url>http://ecn.t0.tiles.virtualearth.net/tiles/a$quadkey.jpeg?g=587&mkt=en-gb&n=z</url>
<scheme>microsoft</scheme>
<sourcetag>Bing</sourcetag>
<attribution_url>http://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/0,0?zl=1&mapVersion=v1&key=Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU&include=ImageryProviders&output=xml</attribution_url>
<logo>bing_maps.png</logo>
<logo_url>http://www.bing.com/maps</logo_url>
</set>

net/systemeD/halcyon/Map.as
net/systemeD/potlatch2/collections/Imagery.as
potlatch2.mxml
resources/bing_maps.png [new file with mode: 0644]

index 103caba..e168ec3 100644 (file)
@@ -172,7 +172,7 @@ package net.systemeD.halcyon {
                private function setCentre():void {
                        centre_lat=coord2lat(-y+mapheight/2);
                        centre_lon=coord2lon(-x+mapwidth/2);
-                       this.dispatchEvent(new MapEvent(MapEvent.MOVE, {lat:centre_lat, lon:centre_lon, scale:scale}));
+                       this.dispatchEvent(new MapEvent(MapEvent.MOVE, {lat:centre_lat, lon:centre_lon, scale:scale, minlon:edge_l, maxlon:edge_r, minlat:edge_b, maxlat:edge_t}));
                }
                
                public function nudgeBackground(x:Number,y:Number):void {
index 1c5e302..4cc2f9e 100644 (file)
@@ -2,9 +2,12 @@ package net.systemeD.potlatch2.collections {
 
        import flash.events.EventDispatcher;
        import flash.events.Event;
+       import flash.display.*;
        import flash.net.*;
+       import flash.text.TextField;
        import net.systemeD.halcyon.DebugURLRequest;
        import net.systemeD.halcyon.Map;
+       import net.systemeD.halcyon.MapEvent;
        import net.systemeD.potlatch2.FunctionKeyManager;
        import net.systemeD.potlatch2.Yahoo;
        import mx.collections.ArrayCollection;
@@ -23,25 +26,35 @@ package net.systemeD.potlatch2.collections {
 
                public var collection:Array=[];
                public var selected:Object={};
+
                private var _yahooDefault:Boolean=false;
                private var _map:Map;
+               private var _overlay:Sprite;
                private var _yahoo:Yahoo;
 
                /* Load catalogue file */
 
-               public function init(map:Map,yahoo:Yahoo,yahooDefault:Boolean):void {
+               public function init(map:Map, overlay:Sprite, yahoo:Yahoo, yahooDefault:Boolean):void {
                        _map = map;
+                       _overlay = overlay;
                        _yahoo = yahoo;
                        _yahooDefault = yahooDefault;
+
+                       // load imagery file
                var request:DebugURLRequest = new DebugURLRequest("imagery.xml");
                var loader:URLLoader = new URLLoader();
                loader.addEventListener(Event.COMPLETE, onImageryLoad);
                loader.load(request.request);
+
+                       // 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);
                        var saved:Object;
+                       var bg:Object;
                        if (SharedObject.getLocal("user_state").data['background_url']) {
                                saved={ name: SharedObject.getLocal("user_state").data['background_name'],
                                                url:  SharedObject.getLocal("user_state").data['background_url' ] };
@@ -52,6 +65,7 @@ package net.systemeD.potlatch2.collections {
                        var isSet:Boolean=false;
             var backgroundSet:Boolean = false;
 
+                       // Read all values from XML file
             collection=new Array(
                                { name: "None", url: "" },
                                { name: "Yahoo", url: "yahoo", sourcetag: "Yahoo" } );
@@ -65,31 +79,99 @@ package net.systemeD.potlatch2.collections {
                                    (obj.name==saved.name && obj.name!='Custom')) { isSet=true; }
                        }
 
+                       // Add user's previous preference (from SharedObject) if we didn't find it in the XML file
             if (!isSet && saved.name && saved.url && saved.url!='' && saved.url!='yahoo') {
                 collection.push(saved);
                 isSet=true;
             }
 
-                       for each (var bg:Object in collection) {
+                       // Automatically select the user's previous preference
+                       for each (bg in collection) {
                                if (bg.name==saved.name || bg.url==saved.url) {
                                        setBackground(bg);
                     backgroundSet = true;
                                }
                        }
 
-            // For most contributors it's useful to set the background to yahoo by default, I reckon, but lets make it a config
+            // Otherwise, set Yahoo as default (if this was passed in as an option from the embedding page)
             if (!backgroundSet && _yahooDefault) {
                 setBackground(collection[1]);
             }
+
+                       // Get any attribution and logo details
+                       for each (bg in collection) {
+                               if (bg.logo) {
+                                       // load the logo
+                                       var loader:Loader = new Loader();
+                                       var thisbg1:Object = bg;                        // scope it for the closure
+                                       loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void { onLogoLoad(e,thisbg1); });
+                                       loader.load(new URLRequest(bg.logo));
+                               }
+                               if (bg.attribution_url) {
+                                       // load the attribution
+                                       trace("requesting "+bg.attribution_url);
+                               var urlloader:URLLoader = new URLLoader();
+                                       var thisbg2:Object = bg;                        // scope it for the closure
+                                       urlloader.addEventListener(Event.COMPLETE, function(e:Event):void { onAttributionLoad(e,thisbg2); });
+                               urlloader.load(new URLRequest(bg.attribution_url));
+                               }
+                       }
+
+                       // 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)); });
                        dispatchEvent(new Event("collection_changed"));
                }
                
+               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 {
+                       trace ("onAttributionLoad");
+                       // if we ever need to cope with non-Microsoft attribution, then this should look at bg.scheme
+                       // someone who actually likes XML can replace the following with the 'proper' way of doing it
+                       var xmlnsPattern:RegExp = new RegExp("xmlns[^\"]*\"[^\"]*\"", "gi");
+                       var xsiPattern:RegExp = new RegExp("xsi[^\"]*\"[^\"]*\"", "gi");
+                       var s:String=e.target.data;
+                       var xml:XML = new XML(s.replace(xmlnsPattern, "").replace(xsiPattern, ""));
+                       var attribution:Object = {};
+                       for each (var ResourceSets:XML in xml.child("ResourceSets")) {
+                               for each (var ResourceSet:XML in ResourceSets.child("ResourceSet")) {
+                                       for each (var Resources:XML in ResourceSet.child("Resources")) {
+                                               for each (var ImageryMetadata:XML in Resources.child("ImageryMetadata")) {
+                                                       for each (var ImageryProvider:XML in ImageryMetadata.child("ImageryProvider")) {
+                                                               var areas:Array=[];
+                                                               for each (var CoverageArea:XML in ImageryProvider.child("CoverageArea")) {
+                                                                       areas.push([CoverageArea.ZoomMin,
+                                                                                   CoverageArea.ZoomMax,
+                                                                                   CoverageArea.BoundingBox.SouthLatitude,
+                                                                                   CoverageArea.BoundingBox.WestLongitude,
+                                                                                   CoverageArea.BoundingBox.NorthLatitude,
+                                                                                   CoverageArea.BoundingBox.EastLongitude]);
+                                                               }
+                                                               attribution[ImageryProvider.Attribution]=areas;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       bg.attribution=attribution;
+                       setAttribution();
+               }
+
                public function setBackground(bg:Object):void {
+                       // set background
+                       selected=bg;
                        if (bg.url=='yahoo') { _map.setBackground({url:''}); _yahoo.show(); }
                                        else { _map.setBackground(bg      ); _yahoo.hide(); }
-                       selected=bg;
+                       // update attribution and logo
+                       _overlay.visible=bg.attribution || bg.logo;
+                       setLogo(); setAttribution();
+                       // 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));
@@ -103,6 +185,39 @@ package net.systemeD.potlatch2.collections {
                        return { url:'' };
                }
 
+               private function moveHandler(event:MapEvent):void {
+                       setAttribution();
+               }
+               private function setAttribution():void {
+                       if (!selected.attribution) return;
+                       var attr:Array=[];
+                       for (var provider:String in selected.attribution) {
+                               for each (var bounds:Array in selected.attribution[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);
+                                       }
+                               }
+                       }
+                       TextField(_overlay.getChildAt(0)).text="Background "+attr.join(", ");
+               }
+               private function resizeHandler(event:MapEvent):void {
+                       if (!selected.logoData) return;
+                       _overlay.getChildAt(1).y=event.params.height-5-selected.logoHeight;
+               }
+               private function setLogo():void {
+                       if (!selected.logoData) return;
+                       while (_overlay.numChildren>1) { _overlay.removeChildAt(1); }
+                       var logo:Bitmap=new Bitmap(selected.logoData);
+                       logo.x=5; logo.y=_map.mapheight-5-selected.logoHeight;
+                       _overlay.addChild(logo);
+               }
+
                [Bindable(event="collection_changed")]
                public function getAvailableImagery():ArrayCollection {
                        var available:Array=[];
index 6775c01..72a6191 100644 (file)
                        _root.addChild(s);
                        theMap.mask=s;
 
+                       // add attribution/logo sprite
+                       var overlay:Sprite=new Sprite();
+                       var attribution:TextField=new TextField();
+                       attribution.width=200; attribution.height=300;
+                       attribution.multiline=true;
+                       attribution.wordWrap=true;
+                       attribution.selectable=false;
+                       attribution.defaultTextFormat=new TextFormat("_sans", 9, 0, false, false, false);
+                       attribution.x=5; attribution.y=5;
+                       overlay.addChild(attribution);
+                       _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);
                        Globals.vars.map_area.addEventListener(MouseEvent.MOUSE_DOWN, theMap.mouseDownHandler);
 
                        // initialise imagery and stylesheets
-                       Imagery.instance().init(theMap,yahoo,loaderInfo.parameters['yahoo_default'] == 'true');
+                       Imagery.instance().init(theMap, overlay, yahoo, loaderInfo.parameters['yahoo_default'] == 'true');
                        Stylesheets.instance().init(theMap);
 
                        // keyboard event attached to stage
diff --git a/resources/bing_maps.png b/resources/bing_maps.png
new file mode 100644 (file)
index 0000000..ae4367e
Binary files /dev/null and b/resources/bing_maps.png differ