<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright 2009 James Richards
  Licensed under the Creative Commons Attribution 3.0 United States License:
    http://creativecommons.org/licenses/by/3.0/legalcode
-->
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:gm="com.google.maps.*"
    backgroundGradientColors="[0xFFFFFF, 0xAAAAAA]"
    height="100%" width="100%"  viewSourceURL="srcview/index.html">
    <gm:Map id="map"
        width="100%" 
        height="100%" 
        key="(Your API Key Here)"
        mapevent_mapready="map_mapReady(event)" />

    <mx:Script>
        <![CDATA[
            import com.adobe.serialization.json.JSON;

            import com.google.maps.LatLng;    
            import com.google.maps.LatLngBounds;
            import com.google.maps.Map;    
            import com.google.maps.MapMoveEvent;
            import com.google.maps.MapType;
            
            import com.google.maps.controls.OverviewMapControl;
            import com.google.maps.controls.ScaleControl;
            import com.google.maps.controls.ZoomControl;
            import com.google.maps.controls.PositionControl;
            import com.google.maps.controls.MapTypeControl;

            import com.google.maps.overlays.Polygon;
            import com.google.maps.overlays.PolygonOptions;
            
            import com.google.maps.styles.FillStyle;
            import com.google.maps.styles.StrokeStyle;
            
            import mx.controls.Alert;
            import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.http.HTTPService;
            
            // Parcels URL and parameters
            private var parcelsUrl:String = "http://sampleserver1.arcgisonline.com/" +
                "ArcGIS/rest/services/Portland/ESRI_LandBase_WebMercator/MapServer/1/query";
            private var wgs84wkid:String = "4236";
            private var toolTipField:String = "RNO";
            
            // Parcels map service
            private var parcelsService:HTTPService = new HTTPService();
            
            // Parcels symbols
            private var transparentFill:FillStyle;
            private var greyStroke:StrokeStyle;
            private var whiteStroke:StrokeStyle;
            
            private function map_mapReady(event:Event):void { 
                // Setup parcel symbols
                transparentFill = new FillStyle({ 
                    alpha: 0.0 });
                greyStroke = new StrokeStyle({
                    alpha: 1.0,
                    thickness: 1.5,
                    color: 0x333333 });
                whiteStroke = new StrokeStyle({
                    alpha: 1.0,
                    thickness: 1.5,
                    color: 0xffffff });
                
                // Add map controls
                var mtc:MapTypeControl = new MapTypeControl();
                map.addControl(mtc);
                var pc:PositionControl = new PositionControl();
                map.addControl(pc);
                var zc:ZoomControl = new ZoomControl();
                map.addControl(zc);
                var sc:ScaleControl = new ScaleControl();
                map.addControl(sc);
                var omc:OverviewMapControl = new OverviewMapControl();
                map.addControl(omc);
                
                // Add event listeners
                map.addEventListener(MapMoveEvent.MOVE_END, map_moveEnd);

                // Initialize map            
                map.setCenter(new LatLng(45.520211, -122.65553), 17, 
                    MapType.NORMAL_MAP_TYPE);
            }
            
            private function map_moveEnd(event:MapMoveEvent):void {
                // Get zoom level
                var zoom:Number = map.getZoom();
                trace("map_moveEnd - Zoom level: " + zoom.toString());
                
                // Only draw parcels if zoomed in far enough
                if (zoom < 17) {
                    // This just clears the overlays if we're not zoomed in far enough.
                    // This would be a problem if there are other overlays besides parcels.
                    // We'll deal with that in a future post.
                    map.clearOverlays();
                    return;
                }
                
                // Get current extent
                var bnds:LatLngBounds = map.getLatLngBounds();
                
                // An ESRI envelope is configured as xmin, ymin, xmax, ymax
                var envelope:String = bnds.getWest().toString() + "," +
                                      bnds.getSouth().toString() + "," +
                                      bnds.getEast().toString() + "," +
                                      bnds.getNorth().toString();
                trace("map_moveEnd - Envelope: " + envelope);
                
                // Cancel http service in case a request was sent 
                // that hasn't come back yet
                parcelsService.cancel();
                
                // Setup http service and add listeners
                parcelsService.url = parcelsUrl;
                parcelsService.addEventListener(ResultEvent.RESULT, onParcelResult);
                parcelsService.addEventListener(FaultEvent.FAULT, onHttpFault);
                
                // Setup parameters to pass to the service
                var params:Object = new Object();
                params.geometry = envelope;
                params.geometryType = "esriGeometryEnvelope";
                params.inSR = wgs84wkid;
                params.spatialRel = "esriSpatialRelIntersects";
                params.returnGeometry = "true";
                params.outSR = wgs84wkid;
                params.outFields = toolTipField;
                params.f = "json";
                
                // Send the request
                parcelsService.send(params);
            }
            
            private function onParcelResult(event:ResultEvent):void {
                //trace(event.result as String);
                
                // Use ascorelib JSON serializer to decode returned object
                var obj:Object = JSON.decode(event.result as String);
                if (obj.error != null) {
                    Alert.show('An error occured on the server. The response message returned was:\n\n' + 
                        event.result, 'Server Error');
                    return;
                }
                
                // Simply clear all the polygons from the map.
                // This would be a problem if there are other overlays.
                // We'll deal with that in a future post.
                map.clearOverlays();
                
                // Get the features array from the returned JSON
                var features:Array = obj.features as Array;
                
                // This code breaks multipolygons into a separate polygon for each
                // ring. Not ideal, but necessary at this zoom level because the only
                // way to create multi ringed polygons in GMaps Flash API (as of v 1.9c)
                // is with the Polyline Encoding Algorithm - and this algorithm rounds
                // to 5 decimal places - thus creating choppy looking polygons. 
                // We'll discuss this further in a future post.
                for each (var feature:Object in features) {
                    for each (var ring:Array in feature.geometry.rings) {
                        var points:Array = new Array();
                        for each (var point:Array in ring) {
                            points.push(new LatLng(point[1], point[0]));
                        }
                        
                        var polyOpts:PolygonOptions = new PolygonOptions();
                        polyOpts.fillStyle = transparentFill;
                        polyOpts.strokeStyle = 
                            (map.getCurrentMapType() == MapType.NORMAL_MAP_TYPE ? 
                            greyStroke : whiteStroke);
                        polyOpts.tooltip = feature.attributes[toolTipField];
    
                        var poly:Polygon = new Polygon(points, polyOpts);
                        map.addOverlay(poly);
                    }
                }                
             }
         
            private function onHttpFault(event:FaultEvent):void {
                Alert.show(event.toString(), "HttpFault");
            }
        ]]>
    </mx:Script>
</mx:Application>