/src/com/google/maps/extras/arcgislink/ArcGISTileLayer.as
ActionScript | 217 lines | 143 code | 31 blank | 43 comment | 20 complexity | dc3eb8c983c1bc8069f0f199f9950bbe MD5 | raw file
1/* 2 * ArcGIS for Google Maps Flash API 3 * 4 * License http://www.apache.org/licenses/LICENSE-2.0 5 */ 6 /** 7 * @author nianwei at gmail dot com 8 */ 9 10package com.google.maps.extras.arcgislink { 11 import com.google.maps.*; 12 import com.google.maps.interfaces.*; 13 14 import flash.display.DisplayObject; 15 import flash.display.Loader; 16 import flash.events.*; 17 import flash.geom.Point; 18 import flash.net.URLRequest; 19 import com.google.maps.extras.arcgislink.*; 20 import com.google.maps.extras.arcgislink.*; 21 /** 22 * Used for cached map service 23 */ 24 //There some unique challenges in AS3 compare to JS in implementing this class : 25 // --can not call super in a callback function, must be inside the constructor context 26 //--copyright et once passed in constructor the overriden functions such as getCopyrightCollection etc does not seem to be used. 27 public class ArcGISTileLayer extends TileLayerBase implements IEventDispatcher { 28 29 private var baseUrl_:String; 30 private var mapService_:MapService; 31 private var urlTemplate_:String; 32 private var numOfHosts_:int; 33 internal var projection_:ArcGISTileConfig; // need access from MapType 34 private var fullBounds_:* /*Envelope*/ ; 35 private var initialBounds_:* /*Envelope*/ ; 36 37 public function ArcGISTileLayer(service:*, opt_layerOpts:ArcGISTileLayerOptions=undefined) { 38 dispatcher_=new EventDispatcher(this); 39 opt_layerOpts=opt_layerOpts || new ArcGISTileLayerOptions({}); 40 this.mapService_=(service is MapService) ? service as MapService : new MapService(service as String); 41 if (opt_layerOpts.name) { 42 this.mapService_.name=opt_layerOpts.name; 43 } 44 this.alpha_=isNaN(opt_layerOpts.alpha) ? Alpha.OPAQUE : opt_layerOpts.alpha; 45 46 //In the format of mt[number].domain.com 47 if (opt_layerOpts.hosts) { 48 var pro:String=ArcGISUtil.extractString(this.mapService_.url, '', '://'); 49 var host:String=ArcGISUtil.extractString(this.mapService_.url, '://', '/'); 50 var path:String=ArcGISUtil.extractString(this.mapService_.url, pro + '://' + host, ''); 51 this.urlTemplate_=pro + '://' + opt_layerOpts.hosts + path; 52 this.numOfHosts_=parseInt(ArcGISUtil.extractString(opt_layerOpts.hosts, '[', ']'), 10); 53 } 54 var copy:ICopyrightCollection=opt_layerOpts.copyrights; 55 if (!copy) { 56 copy=new CopyrightCollection('pre'); 57 copy.addCopyright(new Copyright('1', new LatLngBounds(new LatLng(-90, -180), new LatLng(90, 180)), 0, '')); 58 } 59 this.copy_=copy; 60 this.minZoom_=opt_layerOpts.minResolution || 0; 61 this.maxZoom_=opt_layerOpts.maxResolution || 20; 62 63 if (this.mapService_.hasLoaded()) { 64 this.init_(opt_layerOpts); 65 } else { 66 var me:ArcGISTileLayer=this; 67 this.mapService_.addEventListener(ServiceEvent.LOAD, function():void { 68 me.init_(opt_layerOpts); 69 me.dispatchEvent(new ServiceEvent(ServiceEvent.LOAD)); 70 }); 71 } 72 super(this.copy_, this.minZoom_, this.maxZoom_, this.alpha_); 73 if (this.mapService_.hasLoaded()) { 74 dispatchEvent(new ServiceEvent(ServiceEvent.LOAD)); 75 } 76 } 77 78 /** 79 * Initialize the tile layer from a loaded map service 80 * @param {ArcGISMapService} mapService 81 * @param {Object} opt_layerOpts 82 */ 83 private function init_(opt_layerOpts:*):void { 84 this.projection_=new ArcGISTileConfig(this.mapService_.tileInfo, this.mapService_.fullExtent); 85 var copy:CopyrightCollection=opt_layerOpts.copyrights; 86 if (!copy) { 87 copy=new CopyrightCollection(''); 88 copy.addCopyright(new Copyright('1', ArcGISUtil.fromEnvelopeToLatLngBounds(this.mapService_.fullExtent), this.projection_.zoomOffset_, this.mapService_.copyrightText)); 89 } 90 this.copy_=copy; 91 this.minZoom_=opt_layerOpts.minResolution || this.projection_.minResolution(); 92 this.maxZoom_=opt_layerOpts.maxResolution || this.projection_.maxResolution(); 93 // It seems unlike in JS, AS3's super can be called only in one place in constructor, 94 // as a workaround all get methods are overriden. 95 // TileLayerBase.call(this, copy, minZoom, maxZoom, opt_layerOpts); 96 // super(copy, minZoom, maxZoom, opt_layerOpts.alpha); 97 } 98 99 100 /** 101 * Creates and loads a tile (x, y) at the given zoom level. 102 * @param tilePos Tile coordinates. 103 * @param zoom Tile zoom. 104 * @return Display object representing the tile. 105 */ 106 public override function loadTile(tile:Point, zoom:Number):DisplayObject { 107 var url:String; //.minResolution() 108 var z:Number=zoom - (this.projection_ ? this.projection_.zoomOffset_ : this.getMinResolution()); //.minResolution()); 109 if (!isNaN(tile.x) && !isNaN(tile.y) && z >= 0) { 110 var u:String=this.mapService_.url; 111 if (this.urlTemplate_) { 112 u=this.urlTemplate_.replace('[' + this.numOfHosts_ + ']', '' + ((tile.y + tile.x) % this.numOfHosts_)); 113 } 114 url=u + '/tile/' + z + '/' + tile.y + '/' + tile.x; 115 116 } 117 var loader:Loader=new Loader(); 118 if (url!=null){ 119 loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); 120 loader.load(new URLRequest(url)); 121 } 122 return loader; 123 } 124 125 private function ioErrorHandler(event:IOErrorEvent):void { 126 trace("ioErrorHandler: " + event); 127 } 128 129 /** 130 * Gain access to the underline {@link ArcGISMapService} 131 * @return {MapSerive} 132 */ 133 public function getMapService():MapService { 134 return this.mapService_; 135 } 136 137 /** 138 * Get full bounds of the to the underline {@link ArcGISMapService} 139 * @return {GLatLngBounds} 140 */ 141 public function getFullBounds():LatLngBounds { 142 this.fullBounds_=this.fullBounds_ || ArcGISUtil.fromEnvelopeToLatLngBounds(this.mapService_.fullExtent); 143 return this.fullBounds_; 144 } 145 146 public function getInitialBounds():LatLngBounds { 147 this.initialBounds_=this.initialBounds_ || ArcGISUtil.fromEnvelopeToLatLngBounds(this.mapService_.initialExtent); 148 return this.initialBounds_; 149 } 150 151 /** 152 * Returns the {@link ArcGISProjection}, a subclass of <code>GProjection</code> 153 * used by this ArcGISTileLayer. 154 * @return {ArcGISProjection} 155 */ 156 public function getProjection():ArcGISTileConfig { 157 return this.projection_ || ArcGISTileConfig.GOOGLE_MAPS; 158 } 159 160 public function hasLoaded():Boolean { 161 return this.mapService_.hasLoaded(); 162 } 163 164 public function getName():String { 165 return this.mapService_.name; 166 } 167 private var dispatcher_:EventDispatcher; 168 169 public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void { 170 171 dispatcher_.addEventListener(type, listener, useCapture, priority); 172 } 173 174 public function dispatchEvent(evt:Event):Boolean { 175 return dispatcher_.dispatchEvent(evt); 176 } 177 178 public function hasEventListener(type:String):Boolean { 179 return dispatcher_.hasEventListener(type); 180 } 181 182 public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void { 183 dispatcher_.removeEventListener(type, listener, useCapture); 184 } 185 186 public function willTrigger(type:String):Boolean { 187 return dispatcher_.willTrigger(type); 188 } 189 190 191 private var copy_:ICopyrightCollection; 192 193 public override function getCopyrightCollection():ICopyrightCollection { 194 return this.copy_ ? this.copy_ : super.getCopyrightCollection(); 195 } 196 private var maxZoom_:Number; 197 198 public override function getMaxResolution():Number { 199 return this.maxZoom_ ? this.maxZoom_ : super.getMaxResolution(); 200 } 201 private var minZoom_:Number; 202 203 public override function getMinResolution():Number { 204 return this.minZoom_ ? this.minZoom_ : super.getMinResolution(); 205 } 206 private var alpha_:Number; 207 208 public override function getAlpha():Number { 209 return this.alpha_ ? this.alpha_ : super.getAlpha(); 210 } 211 212 public function setAlpha(alpha:Number):void { 213 this.alpha_=alpha; 214 } 215 216 } 217}