1 package net.systemeD.potlatch2.collections {
4 import flash.display.*;
6 import flash.text.TextField;
7 import net.systemeD.halcyon.DebugURLRequest;
8 import net.systemeD.halcyon.Map;
9 import net.systemeD.halcyon.MapEvent;
10 import net.systemeD.potlatch2.FunctionKeyManager;
11 import net.systemeD.potlatch2.Yahoo;
12 import mx.collections.ArrayCollection;
15 There's lots of further tidying we can do:
16 - remove all the horrid Yahoo stuff
17 - remove the backreferences to _map and send events instead
18 but this will do for now and help remove the clutter from potlatch2.mxml.
21 public class Imagery extends EventDispatcher {
23 private static const GLOBAL_INSTANCE:Imagery = new Imagery();
24 public static function instance():Imagery { return GLOBAL_INSTANCE; }
26 public var collection:Array=[];
27 public var selected:Object={};
29 private var _yahooDefault:Boolean=false;
31 private var _overlay:Sprite;
32 private var _yahoo:Yahoo;
34 /* Load catalogue file */
36 public function init(map:Map, overlay:Sprite, yahoo:Yahoo, yahooDefault:Boolean):void {
40 _yahooDefault = yahooDefault;
43 var request:DebugURLRequest = new DebugURLRequest("imagery.xml");
44 var loader:URLLoader = new URLLoader();
45 loader.addEventListener(Event.COMPLETE, onImageryLoad);
46 loader.load(request.request);
48 // create map listeners
49 map.addEventListener(MapEvent.MOVE, moveHandler);
50 map.addEventListener(MapEvent.RESIZE, resizeHandler);
53 private function onImageryLoad(event:Event):void {
54 var xml:XML = new XML(URLLoader(event.target).data);
57 if (SharedObject.getLocal("user_state").data['background_url']) {
58 saved={ name: SharedObject.getLocal("user_state").data['background_name'],
59 url: SharedObject.getLocal("user_state").data['background_url' ] };
64 var isSet:Boolean=false;
65 var backgroundSet:Boolean = false;
67 // Read all values from XML file
69 { name: "None", url: "" },
70 { name: "Yahoo", url: "yahoo", sourcetag: "Yahoo" } );
71 for each(var set:XML in xml.set) {
74 for each (a in set.@*) { obj[a.name().localName]=a.toString(); }
75 for each (a in set.* ) { obj[a.name() ]=a.toString(); }
77 if ((obj.url ==saved.url) ||
78 (obj.name==saved.name && obj.name!='Custom')) { isSet=true; }
81 // Add user's previous preference (from SharedObject) if we didn't find it in the XML file
82 if (!isSet && saved.name && saved.url && saved.url!='' && saved.url!='yahoo') {
83 collection.push(saved);
87 // Automatically select the user's previous preference
88 for each (bg in collection) {
89 if (bg.name==saved.name || bg.url==saved.url) {
95 // Otherwise, set Yahoo as default (if this was passed in as an option from the embedding page)
96 if (!backgroundSet && _yahooDefault) {
97 setBackground(collection[1]);
100 // Get any attribution and logo details
101 for each (bg in collection) {
104 var loader:Loader = new Loader();
105 var thisbg1:Object = bg; // scope it for the closure
106 loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(e:Event):void { onLogoLoad(e,thisbg1); });
107 loader.load(new URLRequest(bg.logo));
109 if (bg.attribution_url) {
110 // load the attribution
111 trace("requesting "+bg.attribution_url);
112 var urlloader:URLLoader = new URLLoader();
113 var thisbg2:Object = bg; // scope it for the closure
114 urlloader.addEventListener(Event.COMPLETE, function(e:Event):void { onAttributionLoad(e,thisbg2); });
115 urlloader.load(new URLRequest(bg.attribution_url));
119 // Tell the function key manager that we'd like to receive function key calls
120 FunctionKeyManager.instance().registerListener('Background imagery',
121 function(o:String):void { setBackground(findBackgroundWithName(o)); });
122 dispatchEvent(new Event("collection_changed"));
125 public function onLogoLoad(e:Event, bg:Object):void {
126 bg.logoData = Bitmap(LoaderInfo(e.target).content).bitmapData;
127 bg.logoWidth = e.target.loader.width;
128 bg.logoHeight= e.target.loader.height;
132 public function onAttributionLoad(e:Event,bg: Object):void {
133 trace ("onAttributionLoad");
134 // if we ever need to cope with non-Microsoft attribution, then this should look at bg.scheme
135 // someone who actually likes XML can replace the following with the 'proper' way of doing it
136 var xmlnsPattern:RegExp = new RegExp("xmlns[^\"]*\"[^\"]*\"", "gi");
137 var xsiPattern:RegExp = new RegExp("xsi[^\"]*\"[^\"]*\"", "gi");
138 var s:String=e.target.data;
139 var xml:XML = new XML(s.replace(xmlnsPattern, "").replace(xsiPattern, ""));
140 var attribution:Object = {};
141 for each (var ResourceSets:XML in xml.child("ResourceSets")) {
142 for each (var ResourceSet:XML in ResourceSets.child("ResourceSet")) {
143 for each (var Resources:XML in ResourceSet.child("Resources")) {
144 for each (var ImageryMetadata:XML in Resources.child("ImageryMetadata")) {
145 for each (var ImageryProvider:XML in ImageryMetadata.child("ImageryProvider")) {
147 for each (var CoverageArea:XML in ImageryProvider.child("CoverageArea")) {
148 areas.push([CoverageArea.ZoomMin,
149 CoverageArea.ZoomMax,
150 CoverageArea.BoundingBox.SouthLatitude,
151 CoverageArea.BoundingBox.WestLongitude,
152 CoverageArea.BoundingBox.NorthLatitude,
153 CoverageArea.BoundingBox.EastLongitude]);
155 attribution[ImageryProvider.Attribution]=areas;
161 bg.attribution=attribution;
165 public function setBackground(bg:Object):void {
168 if (bg.url=='yahoo') { _map.setBackground({url:''}); _yahoo.show(); }
169 else { _map.setBackground(bg ); _yahoo.hide(); }
170 // update attribution and logo
171 _overlay.visible=bg.attribution || bg.logo;
172 setLogo(); setAttribution();
173 // save as SharedObject for next time
174 var obj:SharedObject = SharedObject.getLocal("user_state");
175 obj.setProperty('background_url' ,String(bg.url));
176 obj.setProperty('background_name',String(bg.name));
180 private function findBackgroundWithName(name:String):Object {
181 for each (var bg:Object in collection) {
182 if (bg.name==name) { return bg; }
187 private function moveHandler(event:MapEvent):void {
190 private function setAttribution():void {
191 if (!selected.attribution) return;
193 for (var provider:String in selected.attribution) {
194 for each (var bounds:Array in selected.attribution[provider]) {
195 if (_map.scale>=bounds[0] && _map.scale<=bounds[1] &&
196 ((_map.edge_l>bounds[3] && _map.edge_l<bounds[5]) ||
197 (_map.edge_r>bounds[3] && _map.edge_r<bounds[5]) ||
198 (_map.edge_l<bounds[3] && _map.edge_r>bounds[5])) &&
199 ((_map.edge_b>bounds[2] && _map.edge_b<bounds[4]) ||
200 (_map.edge_t>bounds[2] && _map.edge_t<bounds[4]) ||
201 (_map.edge_b<bounds[2] && _map.edge_t>bounds[4]))) {
206 TextField(_overlay.getChildAt(0)).text="Background "+attr.join(", ");
208 private function resizeHandler(event:MapEvent):void {
209 if (!selected.logoData) return;
210 _overlay.getChildAt(1).y=event.params.height-5-selected.logoHeight;
212 private function setLogo():void {
213 if (!selected.logoData) return;
214 while (_overlay.numChildren>1) { _overlay.removeChildAt(1); }
215 var logo:Sprite=new Sprite();
216 logo.addChild(new Bitmap(selected.logoData));
217 logo.x=5; logo.y=_map.mapheight-5-selected.logoHeight;
218 if (selected.logo_url) { logo.buttonMode=true; logo.addEventListener(MouseEvent.CLICK, launchLogoLink, false, 0, true); }
219 _overlay.addChild(logo);
221 private function launchLogoLink(e:Event):void {
222 if (!selected.logo_url) return;
223 navigateToURL(new URLRequest(selected.logo_url), '_blank');
226 [Bindable(event="collection_changed")]
227 public function getAvailableImagery():ArrayCollection {
228 var available:Array=[];
229 for each (var bg:Object in collection) {
231 // if there's a bbox, check the current viewport intersects it
232 if (((_map.edge_l>bg.minlon && _map.edge_l<bg.maxlon) ||
233 (_map.edge_r>bg.minlon && _map.edge_r<bg.maxlon) ||
234 (_map.edge_l<bg.minlon && _map.edge_r>bg.maxlon)) &&
235 ((_map.edge_b>bg.minlat && _map.edge_b<bg.maxlat) ||
236 (_map.edge_t>bg.minlat && _map.edge_t<bg.maxlat) ||
237 (_map.edge_b<bg.minlat && _map.edge_t>bg.maxlat))) {
241 // if there's no bbox (i.e. global set), include it anyway
245 return new ArrayCollection(available);