[fusion-commits] r1693 - trunk/lib/OpenLayers

svn_fusion at osgeo.org svn_fusion at osgeo.org
Thu Nov 27 16:17:45 EST 2008


Author: madair
Date: 2008-11-27 16:17:45 -0500 (Thu, 27 Nov 2008)
New Revision: 1693

Modified:
   trunk/lib/OpenLayers/OpenLayers.js
Log:
re #143: update of OL with extra units (and the Google layer type)

Modified: trunk/lib/OpenLayers/OpenLayers.js
===================================================================
--- trunk/lib/OpenLayers/OpenLayers.js	2008-11-27 15:41:43 UTC (rev 1692)
+++ trunk/lib/OpenLayers/OpenLayers.js	2008-11-27 21:17:45 UTC (rev 1693)
@@ -192,6 +192,7 @@
             "OpenLayers/Tween.js",
             "Rico/Corner.js",
             "Rico/Color.js",
+            "Gears/gears_init.js",
             "OpenLayers/Ajax.js",
             "OpenLayers/Request.js",
             "OpenLayers/Request/XMLHttpRequest.js",
@@ -1336,6 +1337,10 @@
  * Constant: INCHES_PER_UNIT
  * {Object} Constant inches per unit -- borrowed from MapServer mapscale.c
  * derivation of nautical miles from http://en.wikipedia.org/wiki/Nautical_mile
+ * Includes the full set of units supported by CS-MAP (http://trac.osgeo.org/csmap/)
+ * and PROJ.4 (http://trac.osgeo.org/proj/)
+ * The hardcoded table is maintain in a CS-MAP source code module named CSdataU.c
+ * The hardcoded table of PROJ.4 units are in pj_units.c.
  */
 OpenLayers.INCHES_PER_UNIT = { 
     'inches': 1.0,
@@ -1349,8 +1354,84 @@
 OpenLayers.INCHES_PER_UNIT["in"]= OpenLayers.INCHES_PER_UNIT.inches;
 OpenLayers.INCHES_PER_UNIT["degrees"] = OpenLayers.INCHES_PER_UNIT.dd;
 OpenLayers.INCHES_PER_UNIT["nmi"] = 1852 * OpenLayers.INCHES_PER_UNIT.m;
-OpenLayers.INCHES_PER_UNIT["mm"] = OpenLayers.INCHES_PER_UNIT.m / 1000.0;
 
+//CS-MAP units
+OpenLayers.METERS_PER_INCH = 0.02540005080010160020;
+OpenLayers.INCHES_PER_UNIT["Inch"] = OpenLayers.INCHES_PER_UNIT.inches;
+OpenLayers.INCHES_PER_UNIT["Meter"] = 1.0/OpenLayers.METERS_PER_INCH;   //EPSG:9001
+OpenLayers.INCHES_PER_UNIT["Foot"] = 0.30480060960121920243/OpenLayers.METERS_PER_INCH;   //EPSG:9003
+OpenLayers.INCHES_PER_UNIT["IFoot"] = 0.30480000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9002
+OpenLayers.INCHES_PER_UNIT["ClarkeFoot"] = 0.3047972651151/OpenLayers.METERS_PER_INCH;   //EPSG:9005
+OpenLayers.INCHES_PER_UNIT["SearsFoot"] = 0.30479947153867624624/OpenLayers.METERS_PER_INCH;   //EPSG:9041
+OpenLayers.INCHES_PER_UNIT["GoldCoastFoot"] = 0.30479971018150881758/OpenLayers.METERS_PER_INCH;   //EPSG:9094
+OpenLayers.INCHES_PER_UNIT["IInch"] = 0.02540000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["MicroInch"] = 0.00002540000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Mil"] = 0.00000002540000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Centimeter"] = 0.01000000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Kilometer"] = 1000.00000000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9036
+OpenLayers.INCHES_PER_UNIT["Yard"] = 0.91440182880365760731/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["SearsYard"] = 0.914398414616029/OpenLayers.METERS_PER_INCH;   //EPSG:9040
+OpenLayers.INCHES_PER_UNIT["IndianYard"] = 0.91439853074444079983/OpenLayers.METERS_PER_INCH;   //EPSG:9084
+OpenLayers.INCHES_PER_UNIT["IndianYd37"] = 0.91439523/OpenLayers.METERS_PER_INCH;   //EPSG:9085
+OpenLayers.INCHES_PER_UNIT["IndianYd62"] = 0.9143988/OpenLayers.METERS_PER_INCH;   //EPSG:9086
+OpenLayers.INCHES_PER_UNIT["IndianYd75"] = 0.9143985/OpenLayers.METERS_PER_INCH;   //EPSG:9087
+OpenLayers.INCHES_PER_UNIT["IndianFoot"] = 0.30479951/OpenLayers.METERS_PER_INCH;   //EPSG:9080
+OpenLayers.INCHES_PER_UNIT["IndianFt37"] = 0.30479841/OpenLayers.METERS_PER_INCH;   //EPSG:9081
+OpenLayers.INCHES_PER_UNIT["IndianFt62"] = 0.3047996/OpenLayers.METERS_PER_INCH;   //EPSG:9082
+OpenLayers.INCHES_PER_UNIT["IndianFt75"] = 0.3047995/OpenLayers.METERS_PER_INCH;   //EPSG:9083
+OpenLayers.INCHES_PER_UNIT["Mile"] = 1609.34721869443738887477/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["IYard"] = 0.91440000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9096
+OpenLayers.INCHES_PER_UNIT["IMile"] = 1609.34400000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9093
+OpenLayers.INCHES_PER_UNIT["NautM"] = 1852.00000000000000000000/OpenLayers.METERS_PER_INCH;   //EPSG:9030
+OpenLayers.INCHES_PER_UNIT["Lat-66"] = 110943.316488932731/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Lat-83"] = 110946.25736872234125/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Decimeter"] = 0.10000000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Millimeter"] = 0.00100000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Dekameter"] = 10.00000000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Decameter"] = 10.00000000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Hectometer"] = 100.00000000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["GermanMeter"] = 1.0000135965/OpenLayers.METERS_PER_INCH;   //EPSG:9031
+OpenLayers.INCHES_PER_UNIT["CaGrid"] = 0.999738/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["ClarkeChain"] = 20.1166194976/OpenLayers.METERS_PER_INCH;   //EPSG:9038          20.11669506"
+OpenLayers.INCHES_PER_UNIT["GunterChain"] = 20.11684023368047/OpenLayers.METERS_PER_INCH;   //EPSG:9033
+OpenLayers.INCHES_PER_UNIT["BenoitChain"] = 20.116782494375872/OpenLayers.METERS_PER_INCH;   //EPSG:9062
+OpenLayers.INCHES_PER_UNIT["SearsChain"] = 20.11676512155/OpenLayers.METERS_PER_INCH;   //EPSG:9042
+OpenLayers.INCHES_PER_UNIT["ClarkeLink"] = 0.201166194976/OpenLayers.METERS_PER_INCH;   //EPSG:9039
+OpenLayers.INCHES_PER_UNIT["GunterLink"] = 0.2011684023368047/OpenLayers.METERS_PER_INCH;   //EPSG:9034
+OpenLayers.INCHES_PER_UNIT["BenoitLink"] = 0.20116782494375872/OpenLayers.METERS_PER_INCH;   //EPSG:9063
+OpenLayers.INCHES_PER_UNIT["SearsLink"] = 0.2011676512155/OpenLayers.METERS_PER_INCH;   //EPSG:9043
+OpenLayers.INCHES_PER_UNIT["Rod"] = 5.02921005842012/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["IntnlChain"] = 20.1168/OpenLayers.METERS_PER_INCH;   //EPSG:9097
+OpenLayers.INCHES_PER_UNIT["IntnlLink"] = 0.201168/OpenLayers.METERS_PER_INCH;   //EPSG:9098
+OpenLayers.INCHES_PER_UNIT["Perch"] = 5.02921005842012/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Pole"] = 5.02921005842012/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Furlong"] = 201.1684023368046/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Rood"] = 3.778266898/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["CapeFoot"] = 0.3047972615/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Brealey"] = 375.00000000000000000000/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["ModAmFt"] = 0.304812252984505969011938/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["Fathom"] = 1.8288/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["NautM-UK"] = 1853.184/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["50kilometers"] = 50000.0/OpenLayers.METERS_PER_INCH;
+OpenLayers.INCHES_PER_UNIT["150kilometers"] = 150000.0/OpenLayers.METERS_PER_INCH;
+//unit abbreviations supported by PROJ.4
+OpenLayers.INCHES_PER_UNIT["mm"] = OpenLayers.INCHES_PER_UNIT["Meter"] / 1000.0;
+OpenLayers.INCHES_PER_UNIT["cm"] = OpenLayers.INCHES_PER_UNIT["Meter"] / 100.0;
+OpenLayers.INCHES_PER_UNIT["dm"] = OpenLayers.INCHES_PER_UNIT["Meter"] * 100.0;
+OpenLayers.INCHES_PER_UNIT["km"] = OpenLayers.INCHES_PER_UNIT["Meter"] * 1000.0;
+OpenLayers.INCHES_PER_UNIT["kmi"] = OpenLayers.INCHES_PER_UNIT["nmi"];    //International Nautical Mile
+OpenLayers.INCHES_PER_UNIT["fath"] = OpenLayers.INCHES_PER_UNIT["Fathom"]; //International Fathom
+OpenLayers.INCHES_PER_UNIT["ch"] = OpenLayers.INCHES_PER_UNIT["IntnlChain"];  //International Chain
+OpenLayers.INCHES_PER_UNIT["link"] = OpenLayers.INCHES_PER_UNIT["IntnlLink"]; //International Link
+OpenLayers.INCHES_PER_UNIT["us-in"] = OpenLayers.INCHES_PER_UNIT["inches"]; //U.S. Surveyor's Inch
+OpenLayers.INCHES_PER_UNIT["us-ft"] = OpenLayers.INCHES_PER_UNIT["Foot"];	//U.S. Surveyor's Foot
+OpenLayers.INCHES_PER_UNIT["us-yd"] = OpenLayers.INCHES_PER_UNIT["Yard"];	//U.S. Surveyor's Yard
+OpenLayers.INCHES_PER_UNIT["us-ch"] = OpenLayers.INCHES_PER_UNIT["GunterChain"]; //U.S. Surveyor's Chain
+OpenLayers.INCHES_PER_UNIT["us-mi"] = OpenLayers.INCHES_PER_UNIT["Mile"];   //U.S. Surveyor's Statute Mile
+OpenLayers.INCHES_PER_UNIT["ind-yd"] = OpenLayers.INCHES_PER_UNIT["IndianYd37"];  //Indian Yard
+OpenLayers.INCHES_PER_UNIT["ind-ft"] = OpenLayers.INCHES_PER_UNIT["IndianFt37"];  //Indian Foot
+OpenLayers.INCHES_PER_UNIT["ind-ch"] = 20.11669506/OpenLayers.METERS_PER_INCH;  //Indian Chain
+
 /** 
  * Constant: DOTS_PER_INCH
  * {Integer} 72 (A sensible default)
@@ -2864,14 +2945,7 @@
      * Property: top
      * {Number} Maximum vertical coordinate.
      */
-    top: null,
-    
-    /**
-     * Property: centerLonLat
-     * {<OpenLayers.LonLat>} A cached center location.  This should not be
-     *     accessed directly.  Use <getCenterLonLat> instead.
-     */
-    centerLonLat: null,
+    top: null,    
 
     /**
      * Constructor: OpenLayers.Bounds
@@ -3048,12 +3122,8 @@
      * {<OpenLayers.LonLat>} The center of the bounds in map space.
      */
     getCenterLonLat:function() {
-        if(!this.centerLonLat) {
-            this.centerLonLat = new OpenLayers.LonLat(
-                (this.left + this.right) / 2, (this.bottom + this.top) / 2
-            );
-        }
-        return this.centerLonLat;
+        return new OpenLayers.LonLat( (this.left + this.right) / 2,
+                                      (this.bottom + this.top) / 2);
     },
 
     /**
@@ -3094,7 +3164,7 @@
         var bottom = (this.bottom - origy) * ratio + origy;
         var right = (this.right - origx) * ratio + origx;
         var top = (this.top - origy) * ratio + origy;
-        
+
         return new OpenLayers.Bounds(left, bottom, right, top);
     },
 
@@ -3130,7 +3200,6 @@
     extend:function(object) {
         var bounds = null;
         if (object) {
-            // clear cached center location
             switch(object.CLASS_NAME) {
                 case "OpenLayers.LonLat":    
                     bounds = new OpenLayers.Bounds(object.lon, object.lat,
@@ -3147,7 +3216,6 @@
             }
     
             if (bounds) {
-                this.centerLonLat = null;
                 if ( (this.left == null) || (bounds.left < this.left)) {
                     this.left = bounds.left;
                 }
@@ -3338,8 +3406,6 @@
      * {<OpenLayers.Bounds>} Itself, for use in chaining operations.
      */
     transform: function(source, dest) {
-        // clear cached center location
-        this.centerLonLat = null;
         var ll = OpenLayers.Projection.transform(
             {'x': this.left, 'y': this.bottom}, source, dest);
         var lr = OpenLayers.Projection.transform(
@@ -4579,23 +4645,7 @@
     display: function(display) {
         this.imageDiv.style.display = (display) ? "" : "none"; 
     },
-    
 
-    /**
-     * APIMethod: isDrawn
-     * 
-     * Returns:
-     * {Boolean} Whether or not the icon is drawn.
-     */
-    isDrawn: function() {
-        // nodeType 11 for ie, whose nodes *always* have a parentNode
-        // (of type document fragment)
-        var isDrawn = (this.imageDiv && this.imageDiv.parentNode && 
-                       (this.imageDiv.parentNode.nodeType != 11));    
-
-        return isDrawn;   
-    },
-
     CLASS_NAME: "OpenLayers.Icon"
 });
 /* ======================================================================
@@ -5996,10 +6046,7 @@
     /**
      * APIMethod: issue
      * Create a new XMLHttpRequest object, open it, set any headers, bind
-     *     a callback to done state, and send any data.  It is recommended that
-     *     you use one <GET>, <POST>, <PUT>, <DELETE>, <OPTIONS>, or <HEAD>.
-     *     This method is only documented to provide detail on the configuration
-     *     options available to all request methods.
+     *     a callback to done state, and send any data.
      *
      * Parameters:
      * config - {Object} Object containing properties for configuring the
@@ -6019,20 +6066,12 @@
      *     <OpenLayers.ProxyHost>.
      * params - {Object} Any key:value pairs to be appended to the
      *     url as a query string.  Assumes url doesn't already include a query
-     *     string or hash.  Typically, this is only appropriate for <GET>
-     *     requests where the query string will be appended to the url.
-     *     Parameter values that are arrays will be
+     *     string or hash.  Parameter values that are arrays will be
      *     concatenated with a comma (note that this goes against form-encoding)
      *     as is done with <OpenLayers.Util.getParameterString>.
      * headers - {Object} Object with header:value pairs to be set on
      *     the request.
-     * data - {String | Document} Optional data to send with the request.
-     *     Typically, this is only used with <POST> and <PUT> requests.
-     *     Make sure to provide the appropriate "Content-Type" header for your
-     *     data.  For <POST> and <PUT> requests, the content type defaults to
-     *     "application-xml".  If your data is a different content type, or
-     *     if you are using a different HTTP method, set the "Content-Type"
-     *     header to match your data type.
+     * data - {Object} Any data to send with the request.
      * callback - {Function} Function to call when request is done.
      *     To determine if the request failed, check request.status (200
      *     indicates success).
@@ -8989,7 +9028,7 @@
 };
 
 /** 
- * APIFunction: loadURL
+ * Function: loadURL
  * Background load a document.  For more flexibility in using XMLHttpRequest,
  *     see the <OpenLayers.Request> methods.
  *
@@ -12270,17 +12309,6 @@
     },
 
     /**
-     * APIMethod: isDrawn
-     * 
-     * Returns:
-     * {Boolean} Whether or not the marker is drawn.
-     */
-    isDrawn: function() {
-        var isDrawn = (this.icon && this.icon.isDrawn());
-        return isDrawn;   
-    },
-
-    /**
      * Method: onScreen
      *
      * Returns:
@@ -14177,7 +14205,7 @@
         if (this.checkModifiers(evt) && 
             this.control.handleRightClicks && 
             OpenLayers.Event.isRightClick(evt)) {
-          propagate = this.rightclick(evt);
+          propogate = this.rightclick(evt);
         }
 
         return propagate;
@@ -16909,6 +16937,745 @@
     CLASS_NAME: "OpenLayers.Handler.Box"
 });
 /* ======================================================================
+    OpenLayers/Layer/EventPane.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
+ * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Util.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.EventPane
+ * Base class for 3rd party layers.  Create a new event pane layer with the
+ * <OpenLayers.Layer.EventPane> constructor.
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer>
+ */
+OpenLayers.Layer.EventPane = OpenLayers.Class(OpenLayers.Layer, {
+    
+    /**
+     * APIProperty: smoothDragPan
+     * {Boolean} smoothDragPan determines whether non-public/internal API
+     *     methods are used for better performance while dragging EventPane 
+     *     layers. When not in sphericalMercator mode, the smoother dragging 
+     *     doesn't actually move north/south directly with the number of 
+     *     pixels moved, resulting in a slight offset when you drag your mouse 
+     *     north south with this option on. If this visual disparity bothers 
+     *     you, you should turn this option off, or use spherical mercator. 
+     *     Default is on.
+     */
+    smoothDragPan: true,
+
+    /**
+     * Property: isBaseLayer
+     * {Boolean} EventPaned layers are always base layers, by necessity.
+     */ 
+    isBaseLayer: true,
+
+    /**
+     * APIProperty: isFixed
+     * {Boolean} EventPaned layers are fixed by default.
+     */ 
+    isFixed: true,
+
+    /**
+     * Property: pane
+     * {DOMElement} A reference to the element that controls the events.
+     */
+    pane: null,
+
+
+    /**
+     * Property: mapObject
+     * {Object} This is the object which will be used to load the 3rd party library
+     * in the case of the google layer, this will be of type GMap, 
+     * in the case of the ve layer, this will be of type VEMap
+     */ 
+    mapObject: null,
+
+
+    /**
+     * Constructor: OpenLayers.Layer.EventPane
+     * Create a new event pane layer
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.prototype.initialize.apply(this, arguments);
+        if (this.pane == null) {
+            this.pane = OpenLayers.Util.createDiv(this.div.id + "_EventPane");
+        }
+    },
+    
+    /**
+     * APIMethod: destroy
+     * Deconstruct this layer.
+     */
+    destroy: function() {
+        this.mapObject = null;
+        OpenLayers.Layer.prototype.destroy.apply(this, arguments); 
+    },
+
+    
+    /**
+     * Method: setMap
+     * Set the map property for the layer. This is done through an accessor
+     * so that subclasses can override this and take special action once 
+     * they have their map variable set. 
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.prototype.setMap.apply(this, arguments);
+        
+        this.pane.style.zIndex = parseInt(this.div.style.zIndex) + 1;
+        this.pane.style.display = this.div.style.display;
+        this.pane.style.width="100%";
+        this.pane.style.height="100%";
+        if (OpenLayers.Util.getBrowserName() == "msie") {
+            this.pane.style.background = 
+                "url(" + OpenLayers.Util.getImagesLocation() + "blank.gif)";
+        }
+
+        if (this.isFixed) {
+            this.map.viewPortDiv.appendChild(this.pane);
+        } else {
+            this.map.layerContainerDiv.appendChild(this.pane);
+        }
+
+        // once our layer has been added to the map, we can load it
+        this.loadMapObject();
+    
+        // if map didn't load, display warning
+        if (this.mapObject == null) {
+            this.loadWarningMessage();
+        }
+    },
+
+    /**
+     * APIMethod: removeMap
+     * On being removed from the map, we'll like to remove the invisible 'pane'
+     *     div that we added to it on creation. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    removeMap: function(map) {
+        if (this.pane && this.pane.parentNode) {
+            this.pane.parentNode.removeChild(this.pane);
+            this.pane = null;
+        }
+        OpenLayers.Layer.prototype.removeMap.apply(this, arguments);
+    },
+  
+    /**
+     * Method: loadWarningMessage
+     * If we can't load the map lib, then display an error message to the 
+     *     user and tell them where to go for help.
+     * 
+     *     This function sets up the layout for the warning message. Each 3rd
+     *     party layer must implement its own getWarningHTML() function to 
+     *     provide the actual warning message.
+     */
+    loadWarningMessage:function() {
+
+        this.div.style.backgroundColor = "darkblue";
+
+        var viewSize = this.map.getSize();
+        
+        var msgW = Math.min(viewSize.w, 300);
+        var msgH = Math.min(viewSize.h, 200);
+        var size = new OpenLayers.Size(msgW, msgH);
+
+        var centerPx = new OpenLayers.Pixel(viewSize.w/2, viewSize.h/2);
+
+        var topLeft = centerPx.add(-size.w/2, -size.h/2);            
+
+        var div = OpenLayers.Util.createDiv(this.name + "_warning", 
+                                            topLeft, 
+                                            size,
+                                            null,
+                                            null,
+                                            null,
+                                            "auto");
+
+        div.style.padding = "7px";
+        div.style.backgroundColor = "yellow";
+
+        div.innerHTML = this.getWarningHTML();
+        this.div.appendChild(div);
+    },
+  
+    /** 
+     * Method: getWarningHTML
+     * To be implemented by subclasses.
+     * 
+     * Returns:
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        //should be implemented by subclasses
+        return "";
+    },
+  
+    /**
+     * Method: display
+     * Set the display on the pane
+     *
+     * Parameters:
+     * display - {Boolean}
+     */
+    display: function(display) {
+        OpenLayers.Layer.prototype.display.apply(this, arguments);
+        this.pane.style.display = this.div.style.display;
+    },
+  
+    /**
+     * Method: setZIndex
+     * Set the z-index order for the pane.
+     * 
+     * Parameters:
+     * zIndex - {int}
+     */
+    setZIndex: function (zIndex) {
+        OpenLayers.Layer.prototype.setZIndex.apply(this, arguments);
+        this.pane.style.zIndex = parseInt(this.div.style.zIndex) + 1;
+    },
+
+    /**
+     * Method: moveTo
+     * Handle calls to move the layer.
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * zoomChanged - {Boolean}
+     * dragging - {Boolean}
+     */
+    moveTo:function(bounds, zoomChanged, dragging) {
+        OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
+
+        if (this.mapObject != null) {
+
+            var newCenter = this.map.getCenter();
+            var newZoom = this.map.getZoom();
+
+            if (newCenter != null) {
+
+                var moOldCenter = this.getMapObjectCenter();
+                var oldCenter = this.getOLLonLatFromMapObjectLonLat(moOldCenter);
+
+                var moOldZoom = this.getMapObjectZoom();
+                var oldZoom= this.getOLZoomFromMapObjectZoom(moOldZoom);
+
+                if ( !(newCenter.equals(oldCenter)) || 
+                     !(newZoom == oldZoom) ) {
+
+                    if (dragging && this.dragPanMapObject && 
+                        this.smoothDragPan) {
+                        var oldPx = this.map.getViewPortPxFromLonLat(oldCenter);
+                        var newPx = this.map.getViewPortPxFromLonLat(newCenter);
+                        this.dragPanMapObject(newPx.x-oldPx.x, oldPx.y-newPx.y);
+                    } else {
+                        var center = this.getMapObjectLonLatFromOLLonLat(newCenter);
+                        var zoom = this.getMapObjectZoomFromOLZoom(newZoom);
+                        this.setMapObjectCenter(center, zoom, dragging);
+                    }
+                }
+            }
+        }
+    },
+
+
+  /********************************************************/
+  /*                                                      */
+  /*                 Baselayer Functions                  */
+  /*                                                      */
+  /********************************************************/
+
+    /**
+     * Method: getLonLatFromViewPortPx
+     * Get a map location from a pixel location
+     * 
+     * Parameters:
+     * viewPortPx - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     *  {<OpenLayers.LonLat>} An OpenLayers.LonLat which is the passed-in view
+     *  port OpenLayers.Pixel, translated into lon/lat by map lib
+     *  If the map lib is not loaded or not centered, returns null
+     */
+    getLonLatFromViewPortPx: function (viewPortPx) {
+        var lonlat = null;
+        if ( (this.mapObject != null) && 
+             (this.getMapObjectCenter() != null) ) {
+            var moPixel = this.getMapObjectPixelFromOLPixel(viewPortPx);
+            var moLonLat = this.getMapObjectLonLatFromMapObjectPixel(moPixel);
+            lonlat = this.getOLLonLatFromMapObjectLonLat(moLonLat);
+        }
+        return lonlat;
+    },
+
+ 
+    /**
+     * Method: getViewPortPxFromLonLat
+     * Get a pixel location from a map location
+     *
+     * Parameters:
+     * lonlat - {<OpenLayers.LonLat>}
+     *
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel which is the passed-in
+     * OpenLayers.LonLat, translated into view port pixels by map lib
+     * If map lib is not loaded or not centered, returns null
+     */
+    getViewPortPxFromLonLat: function (lonlat) {
+        var viewPortPx = null;
+        if ( (this.mapObject != null) && 
+             (this.getMapObjectCenter() != null) ) {
+
+            var moLonLat = this.getMapObjectLonLatFromOLLonLat(lonlat);
+            var moPixel = this.getMapObjectPixelFromMapObjectLonLat(moLonLat);
+        
+            viewPortPx = this.getOLPixelFromMapObjectPixel(moPixel);
+        }
+        return viewPortPx;
+    },
+
+  /********************************************************/
+  /*                                                      */
+  /*               Translation Functions                  */
+  /*                                                      */
+  /*   The following functions translate Map Object and   */
+  /*            OL formats for Pixel, LonLat              */
+  /*                                                      */
+  /********************************************************/
+
+  //
+  // TRANSLATION: MapObject LatLng <-> OpenLayers.LonLat
+  //
+
+    /**
+     * Method: getOLLonLatFromMapObjectLonLat
+     * Get an OL style map location from a 3rd party style map location
+     *
+     * Parameters
+     * moLonLat - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} An OpenLayers.LonLat, translated from the passed in 
+     *          MapObject LonLat
+     *          Returns null if null value is passed in
+     */
+    getOLLonLatFromMapObjectLonLat: function(moLonLat) {
+        var olLonLat = null;
+        if (moLonLat != null) {
+            var lon = this.getLongitudeFromMapObjectLonLat(moLonLat);
+            var lat = this.getLatitudeFromMapObjectLonLat(moLonLat);
+            olLonLat = new OpenLayers.LonLat(lon, lat);
+        }
+        return olLonLat;
+    },
+
+    /**
+     * Method: getMapObjectLonLatFromOLLonLat
+     * Get a 3rd party map location from an OL map location.
+     *
+     * Parameters:
+     * olLonLat - {<OpenLayers.LonLat>}
+     * 
+     * Returns:
+     * {Object} A MapObject LonLat, translated from the passed in 
+     *          OpenLayers.LonLat
+     *          Returns null if null value is passed in
+     */
+    getMapObjectLonLatFromOLLonLat: function(olLonLat) {
+        var moLatLng = null;
+        if (olLonLat != null) {
+            moLatLng = this.getMapObjectLonLatFromLonLat(olLonLat.lon,
+                                                         olLonLat.lat);
+        }
+        return moLatLng;
+    },
+
+
+  //
+  // TRANSLATION: MapObject Pixel <-> OpenLayers.Pixel
+  //
+
+    /**
+     * Method: getOLPixelFromMapObjectPixel
+     * Get an OL pixel location from a 3rd party pixel location.
+     *
+     * Parameters:
+     * moPixel - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Pixel>} An OpenLayers.Pixel, translated from the passed in 
+     *          MapObject Pixel
+     *          Returns null if null value is passed in
+     */
+    getOLPixelFromMapObjectPixel: function(moPixel) {
+        var olPixel = null;
+        if (moPixel != null) {
+            var x = this.getXFromMapObjectPixel(moPixel);
+            var y = this.getYFromMapObjectPixel(moPixel);
+            olPixel = new OpenLayers.Pixel(x, y);
+        }
+        return olPixel;
+    },
+
+    /**
+     * Method: getMapObjectPixelFromOLPixel
+     * Get a 3rd party pixel location from an OL pixel location
+     *
+     * Parameters:
+     * olPixel - {<OpenLayers.Pixel>}
+     * 
+     * Returns:
+     * {Object} A MapObject Pixel, translated from the passed in 
+     *          OpenLayers.Pixel
+     *          Returns null if null value is passed in
+     */
+    getMapObjectPixelFromOLPixel: function(olPixel) {
+        var moPixel = null;
+        if (olPixel != null) {
+            moPixel = this.getMapObjectPixelFromXY(olPixel.x, olPixel.y);
+        }
+        return moPixel;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.EventPane"
+});
+/* ======================================================================
+    OpenLayers/Layer/FixedZoomLevels.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
+ * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+/**
+ * @requires OpenLayers/Layer.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.FixedZoomLevels
+ *   Some Layers will already have established zoom levels (like google 
+ *    or ve). Instead of trying to determine them and populate a resolutions[]
+ *    Array with those values, we will hijack the resolution functionality
+ *    here.
+ * 
+ *   When you subclass FixedZoomLevels: 
+ * 
+ *   The initResolutions() call gets nullified, meaning no resolutions[] array 
+ *    is set up. Which would be a big problem getResolution() in Layer, since 
+ *    it merely takes map.zoom and indexes into resolutions[]... but....
+ * 
+ *   The getResolution() call is also overridden. Instead of using the 
+ *    resolutions[] array, we simply calculate the current resolution based
+ *    on the current extent and the current map size. But how will we be able
+ *    to calculate the current extent without knowing the resolution...?
+ *  
+ *   The getExtent() function is also overridden. Instead of calculating extent
+ *    based on the center point and the current resolution, we instead 
+ *    calculate the extent by getting the lonlats at the top-left and 
+ *    bottom-right by using the getLonLatFromViewPortPx() translation function,
+ *    taken from the pixel locations (0,0) and the size of the map. But how 
+ *    will we be able to do lonlat-px translation without resolution....?
+ * 
+ *   The getZoomForResolution() method is overridden. Instead of indexing into
+ *    the resolutions[] array, we call OpenLayers.Layer.getExent(), passing in
+ *    the desired resolution. With this extent, we then call getZoomForExtent() 
+ * 
+ * 
+ *   Whenever you implement a layer using OpenLayers.Layer.FixedZoomLevels, 
+ *    it is your responsibility to provide the following three functions:
+ * 
+ *   - getLonLatFromViewPortPx
+ *   - getViewPortPxFromLonLat
+ *   - getZoomForExtent
+ * 
+ *  ...those three functions should generally be provided by any reasonable 
+ *  API that you might be working from.
+ *
+ */
+OpenLayers.Layer.FixedZoomLevels = OpenLayers.Class({
+      
+  /********************************************************/
+  /*                                                      */
+  /*                 Baselayer Functions                  */
+  /*                                                      */
+  /*    The following functions must all be implemented   */
+  /*                  by all base layers                  */
+  /*                                                      */
+  /********************************************************/
+    
+    /**
+     * Constructor: OpenLayers.Layer.FixedZoomLevels
+     * Create a new fixed zoom levels layer.
+     */
+    initialize: function() {
+        //this class is only just to add the following functions... 
+        // nothing to actually do here... but it is probably a good
+        // idea to have layers that use these functions call this 
+        // inititalize() anyways, in case at some point we decide we 
+        // do want to put some functionality or state in here. 
+    },
+    
+    /**
+     * Method: initResolutions
+     * Populate the resolutions array
+     */
+    initResolutions: function() {
+
+        var props = new Array('minZoomLevel', 'maxZoomLevel', 'numZoomLevels');
+          
+        for(var i=0, len=props.length; i<len; i++) {
+            var property = props[i];
+            this[property] = (this.options[property] != null)  
+                                     ? this.options[property] 
+                                     : this.map[property];
+        }
+
+        if ( (this.minZoomLevel == null) ||
+             (this.minZoomLevel < this.MIN_ZOOM_LEVEL) ){
+            this.minZoomLevel = this.MIN_ZOOM_LEVEL;
+        }        
+
+        //
+        // At this point, we know what the minimum desired zoom level is, and
+        //  we must calculate the total number of zoom levels. 
+        //  
+        //  Because we allow for the setting of either the 'numZoomLevels'
+        //   or the 'maxZoomLevel' properties... on either the layer or the  
+        //   map, we have to define some rules to see which we take into
+        //   account first in this calculation. 
+        //
+        // The following is the precedence list for these properties:
+        // 
+        // (1) numZoomLevels set on layer
+        // (2) maxZoomLevel set on layer
+        // (3) numZoomLevels set on map
+        // (4) maxZoomLevel set on map*
+        // (5) none of the above*
+        //
+        // *Note that options (4) and (5) are only possible if the user 
+        //  _explicitly_ sets the 'numZoomLevels' property on the map to 
+        //  null, since it is set by default to 16. 
+        //
+
+        //
+        // Note to future: In 3.0, I think we should remove the default 
+        // value of 16 for map.numZoomLevels. Rather, I think that value 
+        // should be set as a default on the Layer.WMS class. If someone
+        // creates a 3rd party layer and does not specify any 'minZoomLevel', 
+        // 'maxZoomLevel', or 'numZoomLevels', and has not explicitly 
+        // specified any of those on the map object either.. then I think
+        // it is fair to say that s/he wants all the zoom levels available.
+        // 
+        // By making map.numZoomLevels *null* by default, that will be the 
+        // case. As it is, I don't feel comfortable changing that right now
+        // as it would be a glaring API change and actually would probably
+        // break many peoples' codes. 
+        //
+
+        //the number of zoom levels we'd like to have.
+        var desiredZoomLevels;
+
+        //this is the maximum number of zoom levels the layer will allow, 
+        // given the specified starting minimum zoom level.
+        var limitZoomLevels = this.MAX_ZOOM_LEVEL - this.minZoomLevel + 1;
+
+        if ( ((this.options.numZoomLevels == null) && 
+              (this.options.maxZoomLevel != null)) // (2)
+              ||
+             ((this.numZoomLevels == null) &&
+              (this.maxZoomLevel != null)) // (4)
+           ) {
+            //calculate based on specified maxZoomLevel (on layer or map)
+            desiredZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1;
+        } else {
+            //calculate based on specified numZoomLevels (on layer or map)
+            // this covers cases (1) and (3)
+            desiredZoomLevels = this.numZoomLevels;
+        }
+
+        if (desiredZoomLevels != null) {
+            //Now that we know what we would *like* the number of zoom levels
+            // to be, based on layer or map options, we have to make sure that
+            // it does not conflict with the actual limit, as specified by 
+            // the constants on the layer itself (and calculated into the
+            // 'limitZoomLevels' variable). 
+            this.numZoomLevels = Math.min(desiredZoomLevels, limitZoomLevels);
+        } else {
+            // case (5) -- neither 'numZoomLevels' not 'maxZoomLevel' was 
+            // set on either the layer or the map. So we just use the 
+            // maximum limit as calculated by the layer's constants.
+            this.numZoomLevels = limitZoomLevels;
+        }
+
+        //now that the 'numZoomLevels' is appropriately, safely set, 
+        // we go back and re-calculate the 'maxZoomLevel'.
+        this.maxZoomLevel = this.minZoomLevel + this.numZoomLevels - 1;
+
+        if (this.RESOLUTIONS != null) {
+            var resolutionsIndex = 0;
+            this.resolutions = [];
+            for(var i= this.minZoomLevel; i <= this.maxZoomLevel; i++) {
+                this.resolutions[resolutionsIndex++] = this.RESOLUTIONS[i];            
+            }
+            this.maxResolution = this.resolutions[0];
+            this.minResolution = this.resolutions[this.resolutions.length - 1];
+        }       
+    },
+    
+    /**
+     * APIMethod: getResolution
+     * Get the current map resolution
+     * 
+     * Returns:
+     * {Float} Map units per Pixel
+     */
+    getResolution: function() {
+
+        if (this.resolutions != null) {
+            return OpenLayers.Layer.prototype.getResolution.apply(this, arguments);
+        } else {
+            var resolution = null;
+            
+            var viewSize = this.map.getSize();
+            var extent = this.getExtent();
+            
+            if ((viewSize != null) && (extent != null)) {
+                resolution = Math.max( extent.getWidth()  / viewSize.w,
+                                       extent.getHeight() / viewSize.h );
+            }
+            return resolution;
+        }
+     },
+
+    /**
+     * APIMethod: getExtent
+     * Calculates using px-> lonlat translation functions on tl and br 
+     *     corners of viewport
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat 
+     *                       bounds of the current viewPort.
+     */
+    getExtent: function () {
+        var extent = null;
+        
+        
+        var size = this.map.getSize();
+        
+        var tlPx = new OpenLayers.Pixel(0,0);
+        var tlLL = this.getLonLatFromViewPortPx(tlPx);
+
+        var brPx = new OpenLayers.Pixel(size.w, size.h);
+        var brLL = this.getLonLatFromViewPortPx(brPx);
+        
+        if ((tlLL != null) && (brLL != null)) {
+            extent = new OpenLayers.Bounds(tlLL.lon, 
+                                       brLL.lat, 
+                                       brLL.lon, 
+                                       tlLL.lat);
+        }
+
+        return extent;
+    },
+
+    /**
+     * Method: getZoomForResolution
+     * Get the zoom level for a given resolution
+     *
+     * Parameters:
+     * resolution - {Float}
+     *
+     * Returns:
+     * {Integer} A suitable zoom level for the specified resolution.
+     *           If no baselayer is set, returns null.
+     */
+    getZoomForResolution: function(resolution) {
+      
+        if (this.resolutions != null) {
+            return OpenLayers.Layer.prototype.getZoomForResolution.apply(this, arguments);
+        } else {
+            var extent = OpenLayers.Layer.prototype.getExtent.apply(this, []);
+            return this.getZoomForExtent(extent);
+        }
+    },
+
+
+
+    
+    /********************************************************/
+    /*                                                      */
+    /*             Translation Functions                    */
+    /*                                                      */
+    /*    The following functions translate GMaps and OL    */ 
+    /*     formats for Pixel, LonLat, Bounds, and Zoom      */
+    /*                                                      */
+    /********************************************************/
+    
+    
+    //
+    // TRANSLATION: MapObject Zoom <-> OpenLayers Zoom
+    //
+  
+    /**
+     * Method: getOLZoomFromMapObjectZoom
+     * Get the OL zoom index from the map object zoom level
+     *
+     * Parameters:
+     * moZoom - {Integer}
+     * 
+     * Returns:
+     * {Integer} An OpenLayers Zoom level, translated from the passed in zoom
+     *           Returns null if null value is passed in
+     */
+    getOLZoomFromMapObjectZoom: function(moZoom) {
+        var zoom = null;
+        if (moZoom != null) {
+            zoom = moZoom - this.minZoomLevel;
+        }
+        return zoom;
+    },
+    
+    /**
+     * Method: getMapObjectZoomFromOLZoom
+     * Get the map object zoom level from the OL zoom level
+     *
+     * Parameters:
+     * olZoom - {Integer}
+     * 
+     * Returns:
+     * {Integer} A MapObject level, translated from the passed in olZoom
+     *           Returns null if null value is passed in
+     */
+    getMapObjectZoomFromOLZoom: function(olZoom) {
+        var zoom = null; 
+        if (olZoom != null) {
+            zoom = olZoom + this.minZoomLevel;
+        }
+        return zoom;
+    },
+
+    CLASS_NAME: "FixedZoomLevels.js"
+});
+
+/* ======================================================================
     OpenLayers/Layer/HTTPRequest.js
    ====================================================================== */
 
@@ -17283,6 +18050,7 @@
             if ((marker.icon != null) && (marker.icon.imageDiv != null) &&
                 (marker.icon.imageDiv.parentNode == this.div) ) {
                 this.div.removeChild(marker.icon.imageDiv);    
+                marker.drawn = false;
             }
         }
     },
@@ -17313,11 +18081,10 @@
         if (px == null) {
             marker.display(false);
         } else {
-            if (!marker.isDrawn()) {
-                var markerImg = marker.draw(px);
+            var markerImg = marker.draw(px);
+            if (!marker.drawn) {
                 this.div.appendChild(markerImg);
-            } else if(marker.icon) {
-                marker.icon.moveTo(px);
+                marker.drawn = true;
             }
         }
     },
@@ -17346,6 +18113,169 @@
     CLASS_NAME: "OpenLayers.Layer.Markers"
 });
 /* ======================================================================
+    OpenLayers/Layer/SphericalMercator.js
+   ====================================================================== */
+
+/**
+ * @requires OpenLayers/Layer.js
+ * @requires OpenLayers/Projection.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.SphericalMercator
+ * A mixin for layers that wraps up the pieces neccesary to have a coordinate
+ *     conversion for working with commercial APIs which use a spherical
+ *     mercator projection.  Using this layer as a base layer, additional
+ *     layers can be used as overlays if they are in the same projection.
+ *
+ * A layer is given properties of this object by setting the sphericalMercator
+ *     property to true.
+ *
+ * More projection information:
+ *  - http://spatialreference.org/ref/user/google-projection/
+ *
+ * Proj4 Text:
+ *     +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0
+ *     +k=1.0 +units=m +nadgrids=@null +no_defs
+ *
+ * WKT:
+ *     900913=PROJCS["WGS84 / Simple Mercator", GEOGCS["WGS 84",
+ *     DATUM["WGS_1984", SPHEROID["WGS_1984", 6378137.0, 298.257223563]], 
+ *     PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], 
+ *     AXIS["Longitude", EAST], AXIS["Latitude", NORTH]],
+ *     PROJECTION["Mercator_1SP_Google"], 
+ *     PARAMETER["latitude_of_origin", 0.0], PARAMETER["central_meridian", 0.0], 
+ *     PARAMETER["scale_factor", 1.0], PARAMETER["false_easting", 0.0], 
+ *     PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["x", EAST],
+ *     AXIS["y", NORTH], AUTHORITY["EPSG","900913"]]
+ */
+OpenLayers.Layer.SphericalMercator = {
+
+    /**
+     * Method: getExtent
+     * Get the map's extent.
+     *
+     * Returns:
+     * {<OpenLayers.Bounds>} The map extent.
+     */
+    getExtent: function() {
+        var extent = null;
+        if (this.sphericalMercator) {
+            extent = this.map.calculateBounds();
+        } else {
+            extent = OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);
+        }
+        return extent;
+    },
+
+    /** 
+     * Method: initMercatorParameters 
+     * Set up the mercator parameters on the layer: resolutions,
+     *     projection, units.
+     */
+    initMercatorParameters: function() {
+        // set up properties for Mercator - assume EPSG:900913
+        this.RESOLUTIONS = [];
+        var maxResolution = 156543.0339;
+        for(var zoom=0; zoom<=this.MAX_ZOOM_LEVEL; ++zoom) {
+            this.RESOLUTIONS[zoom] = maxResolution / Math.pow(2, zoom);
+        }
+        this.units = "m";
+        this.projection = "EPSG:900913";
+    },
+
+    /**
+     * APIMethod: forwardMercator
+     * Given a lon,lat in EPSG:4326, return a point in Spherical Mercator.
+     *
+     * Parameters:
+     * lon - {float} 
+     * lat - {float}
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} The coordinates transformed to Mercator.
+     */
+    forwardMercator: function(lon, lat) {
+        var x = lon * 20037508.34 / 180;
+        var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
+
+        y = y * 20037508.34 / 180;
+        
+        return new OpenLayers.LonLat(x, y);
+    },
+
+    /**
+     * APIMethod: inverseMercator
+     * Given a x,y in Spherical Mercator, return a point in EPSG:4326.
+     *
+     * Parameters:
+     * x - {float} A map x in Spherical Mercator.
+     * y - {float} A map y in Spherical Mercator.
+     * 
+     * Returns:
+     * {<OpenLayers.LonLat>} The coordinates transformed to EPSG:4326.
+     */
+    inverseMercator: function(x, y) {
+
+        var lon = (x / 20037508.34) * 180;
+        var lat = (y / 20037508.34) * 180;
+
+        lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
+        
+        return new OpenLayers.LonLat(lon, lat);
+    },
+
+    /**
+     * Method: projectForward 
+     * Given an object with x and y properties in EPSG:4326, modify the x,y
+     * properties on the object to be the Spherical Mercator projected
+     * coordinates.
+     *
+     * Parameters:
+     * point - {Object} An object with x and y properties. 
+     * 
+     * Returns:
+     * {Object} The point, with the x and y properties transformed to spherical
+     * mercator.
+     */
+    projectForward: function(point) {
+        var lonlat = OpenLayers.Layer.SphericalMercator.forwardMercator(point.x, point.y);
+        point.x = lonlat.lon;
+        point.y = lonlat.lat;
+        return point;
+    },
+    
+    /**
+     * Method: projectInverse
+     * Given an object with x and y properties in Spherical Mercator, modify
+     * the x,y properties on the object to be the unprojected coordinates.
+     *
+     * Parameters:
+     * point - {Object} An object with x and y properties. 
+     * 
+     * Returns:
+     * {Object} The point, with the x and y properties transformed from
+     * spherical mercator to unprojected coordinates..
+     */
+    projectInverse: function(point) {
+        var lonlat = OpenLayers.Layer.SphericalMercator.inverseMercator(point.x, point.y);
+        point.x = lonlat.lon;
+        point.y = lonlat.lat;
+        return point;
+    }
+
+};
+
+/**
+ * Note: Two transforms declared
+ * Transforms from EPSG:4326 to EPSG:900913 and from EPSG:900913 to EPSG:4326
+ *     are set by this class.
+ */
+OpenLayers.Projection.addTransform("EPSG:4326", "EPSG:900913",
+    OpenLayers.Layer.SphericalMercator.projectForward);
+OpenLayers.Projection.addTransform("EPSG:900913", "EPSG:4326",
+    OpenLayers.Layer.SphericalMercator.projectInverse);
+/* ======================================================================
     OpenLayers/Control/DrawFeature.js
    ====================================================================== */
 
@@ -17876,6 +18806,555 @@
     CLASS_NAME: "OpenLayers.Format.WKT" 
 });     
 /* ======================================================================
+    OpenLayers/Layer/Google.js
+   ====================================================================== */
+
+/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
+ * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. */
+
+
+/**
+ * @requires OpenLayers/Layer/SphericalMercator.js
+ * @requires OpenLayers/Layer/EventPane.js
+ * @requires OpenLayers/Layer/FixedZoomLevels.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Google
+ * 
+ * Inherits from:
+ *  - <OpenLayers.Layer.SphericalMercator>
+ *  - <OpenLayers.Layer.EventPane>
+ *  - <OpenLayers.Layer.FixedZoomLevels>
+ */
+OpenLayers.Layer.Google = OpenLayers.Class(
+    OpenLayers.Layer.EventPane, 
+    OpenLayers.Layer.FixedZoomLevels, {
+    
+    /** 
+     * Constant: MIN_ZOOM_LEVEL
+     * {Integer} 0 
+     */
+    MIN_ZOOM_LEVEL: 0,
+    
+    /** 
+     * Constant: MAX_ZOOM_LEVEL
+     * {Integer} 19
+     */
+    MAX_ZOOM_LEVEL: 19,
+
+    /** 
+     * Constant: RESOLUTIONS
+     * {Array(Float)} Hardcode these resolutions so that they are more closely
+     *                tied with the standard wms projection
+     */
+    RESOLUTIONS: [
+        1.40625, 
+        0.703125, 
+        0.3515625, 
+        0.17578125, 
+        0.087890625, 
+        0.0439453125,
+        0.02197265625, 
+        0.010986328125, 
+        0.0054931640625, 
+        0.00274658203125,
+        0.001373291015625, 
+        0.0006866455078125, 
+        0.00034332275390625,
+        0.000171661376953125, 
+        0.0000858306884765625, 
+        0.00004291534423828125,
+        0.00002145767211914062, 
+        0.00001072883605957031,
+        0.00000536441802978515, 
+        0.00000268220901489257
+    ],
+
+    /**
+     * APIProperty: type
+     * {GMapType}
+     */
+    type: null,
+
+    /**
+     * APIProperty: sphericalMercator
+     * {Boolean} Should the map act as a mercator-projected map? This will
+     *     cause all interactions with the map to be in the actual map 
+     *     projection, which allows support for vector drawing, overlaying 
+     *     other maps, etc. 
+     */
+    sphericalMercator: false, 
+    
+    /**
+     * Property: dragObject
+     * {GDraggableObject} Since 2.93, Google has exposed the ability to get
+     *     the maps GDraggableObject. We can now use this for smooth panning
+     */
+    dragObject: null, 
+
+    /** 
+     * Constructor: OpenLayers.Layer.Google
+     * 
+     * Parameters:
+     * name - {String} A name for the layer.
+     * options - {Object} An optional object whose properties will be set
+     *     on the layer.
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
+        OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, 
+                                                                    arguments);
+        this.addContainerPxFunction();
+        if (this.sphericalMercator) {
+            OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator);
+            this.initMercatorParameters();
+        }    
+    },
+    
+    /** 
+     * Method: loadMapObject
+     * Load the GMap and register appropriate event listeners. If we can't 
+     *     load GMap2, then display a warning message.
+     */
+    loadMapObject:function() {
+        
+        //has gmaps library has been loaded?
+        try {
+            // create GMap, hide nav controls
+            this.mapObject = new GMap2( this.div );
+            
+            //since v 2.93 getDragObject is now available.
+            if(typeof this.mapObject.getDragObject == "function") {
+                this.dragObject = this.mapObject.getDragObject();
+            } else {
+                this.dragPanMapObject = null;
+            }
+
+
+            // move the ToS and branding stuff up to the pane
+            // thanks a *mil* Erik for thinking of this
+            var poweredBy = this.div.lastChild;
+            this.div.removeChild(poweredBy);
+            this.pane.appendChild(poweredBy);
+            poweredBy.className = "olLayerGooglePoweredBy gmnoprint";
+            poweredBy.style.left = "";
+            poweredBy.style.bottom = "";
+
+            var termsOfUse = this.div.lastChild;
+            this.div.removeChild(termsOfUse);
+            this.pane.appendChild(termsOfUse);
+            termsOfUse.className = "olLayerGoogleCopyright";
+            termsOfUse.style.right = "";
+            termsOfUse.style.bottom = "";
+
+        } catch (e) {
+            OpenLayers.Console.error(e);
+        }
+               
+    },
+
+    /** 
+     * APIMethod: setMap
+     * Overridden from EventPane because if a map type has been specified, 
+     *     we need to attach a listener for the first moveend -- this is how 
+     *     we will know that the map has been centered. Only once the map has 
+     *     been centered is it safe to change the gmap object's map type. 
+     * 
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.EventPane.prototype.setMap.apply(this, arguments);
+
+        if (this.type != null) {
+            this.map.events.register("moveend", this, this.setMapType);
+        }
+    },
+    
+    /** 
+     * Method: setMapType
+     * The map has been centered, and a map type was specified, so we 
+     *     set the map type on the gmap object, then unregister the listener
+     *     so that we dont keep doing this every time the map moves.
+     */
+    setMapType: function() {
+        if (this.mapObject.getCenter() != null) {
+            
+            // Support for custom map types.
+            if (OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),
+                                        this.type) == -1) {
+                this.mapObject.addMapType(this.type);
+            }    
+
+            this.mapObject.setMapType(this.type);
+            this.map.events.unregister("moveend", this, this.setMapType);
+        }
+    },
+
+    /**
+     * APIMethod: onMapResize
+     * 
+     * Parameters:
+     * evt - {Event}
+     */
+    onMapResize: function() {
+        if(this.visibility) {
+            this.mapObject.checkResize();  
+        } else {
+            this.windowResized = true;
+        }
+    },
+    
+    /**
+     * Method: display
+     * Hide or show the layer
+     *
+     * Parameters:
+     * display - {Boolean}
+     */
+    display: function(display) {
+        OpenLayers.Layer.EventPane.prototype.display.apply(this, arguments);
+        if(this.div.style.display == "block" && this.windowResized) {
+            this.mapObject.checkResize();
+            this.windowResized = false;
+        }
+    },
+
+    /**
+     * APIMethod: getZoomForExtent
+     * 
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *  
+     * Returns:
+     * {Integer} Corresponding zoom level for a specified Bounds. 
+     *           If mapObject is not loaded or not centered, returns null
+     *
+    getZoomForExtent: function (bounds) {
+        var zoom = null;
+        if (this.mapObject != null) {
+            var moBounds = this.getMapObjectBoundsFromOLBounds(bounds);
+            var moZoom = this.getMapObjectZoomFromMapObjectBounds(moBounds);
+
+            //make sure zoom is within bounds    
+            var moZoom = Math.min(Math.max(moZoom, this.minZoomLevel), 
+                                 this.maxZoomLevel);
+
+            zoom = this.getOLZoomFromMapObjectZoom(moZoom);
+        }
+        return zoom;
+    },
+    
+    */
+    
+  //
+  // TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds
+  //
+
+    /**
+     * APIMethod: getOLBoundsFromMapObjectBounds
+     * 
+     * Parameters:
+     * moBounds - {Object}
+     * 
+     * Returns:
+     * {<OpenLayers.Bounds>} An <OpenLayers.Bounds>, translated from the 
+     *                       passed-in MapObject Bounds.
+     *                       Returns null if null value is passed in.
+     */
+    getOLBoundsFromMapObjectBounds: function(moBounds) {
+        var olBounds = null;
+        if (moBounds != null) {
+            var sw = moBounds.getSouthWest();
+            var ne = moBounds.getNorthEast();
+            if (this.sphericalMercator) {
+                sw = this.forwardMercator(sw.lng(), sw.lat());
+                ne = this.forwardMercator(ne.lng(), ne.lat());
+            } else {
+                sw = new OpenLayers.LonLat(sw.lng(), sw.lat()); 
+                ne = new OpenLayers.LonLat(ne.lng(), ne.lat()); 
+            }    
+            olBounds = new OpenLayers.Bounds(sw.lon, 
+                                             sw.lat, 
+                                             ne.lon, 
+                                             ne.lat );
+        }
+        return olBounds;
+    },
+
+    /**
+     * APIMethod: getMapObjectBoundsFromOLBounds
+     * 
+     * Parameters:
+     * olBounds - {<OpenLayers.Bounds>}
+     * 
+     * Returns:
+     * {Object} A MapObject Bounds, translated from olBounds
+     *          Returns null if null value is passed in
+     */
+    getMapObjectBoundsFromOLBounds: function(olBounds) {
+        var moBounds = null;
+        if (olBounds != null) {
+            var sw = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.bottom, olBounds.left) : 
+              new OpenLayers.LonLat(olBounds.bottom, olBounds.left);
+            var ne = this.sphericalMercator ? 
+              this.inverseMercator(olBounds.top, olBounds.right) : 
+              new OpenLayers.LonLat(olBounds.top, olBounds.right);
+            moBounds = new GLatLngBounds(new GLatLng(sw.lat, sw.lon),
+                                         new GLatLng(ne.lat, ne.lon));
+        }
+        return moBounds;
+    },
+
+    /** 
+     * Method: addContainerPxFunction
+     * Hack-on function because GMAPS does not give it to us
+     * 
+     * Parameters: 
+     * gLatLng - {GLatLng}
+     * 
+     * Returns:
+     * {GPoint} A GPoint specifying gLatLng translated into "Container" coords
+     */
+    addContainerPxFunction: function() {
+        if ( (typeof GMap2 != "undefined") && 
+             !GMap2.prototype.fromLatLngToContainerPixel) {
+          
+            GMap2.prototype.fromLatLngToContainerPixel = function(gLatLng) {
+          
+                // first we translate into "DivPixel"
+                var gPoint = this.fromLatLngToDivPixel(gLatLng);
+      
+                // locate the sliding "Div" div
+                var div = this.getContainer().firstChild.firstChild;
+  
+                // adjust by the offset of "Div" and voila!
+                gPoint.x += div.offsetLeft;
+                gPoint.y += div.offsetTop;
+    
+                return gPoint;
+            };
+        }
+    },
+
+    /** 
+     * APIMethod: getWarningHTML
+     * 
+     * Returns: 
+     * {String} String with information on why layer is broken, how to get
+     *          it working.
+     */
+    getWarningHTML:function() {
+        return OpenLayers.i18n("googleWarning");
+    },
+
+
+    /************************************
+     *                                  *
+     *   MapObject Interface Controls   *
+     *                                  *
+     ************************************/
+
+
+  // Get&Set Center, Zoom
+
+    /** 
+     * APIMethod: setMapObjectCenter
+     * Set the mapObject to the specified center and zoom
+     * 
+     * Parameters:
+     * center - {Object} MapObject LonLat format
+     * zoom - {int} MapObject zoom format
+     */
+    setMapObjectCenter: function(center, zoom) {
+        this.mapObject.setCenter(center, zoom); 
+    },
+   
+    /**
+     * APIMethod: dragPanMapObject
+     * 
+     * Parameters:
+     * dX - {Integer}
+     * dY - {Integer}
+     */
+    dragPanMapObject: function(dX, dY) {
+        this.dragObject.moveBy(new GSize(-dX, dY));
+    },
+
+    /**
+     * APIMethod: getMapObjectCenter
+     * 
+     * Returns: 
+     * {Object} The mapObject's current center in Map Object format
+     */
+    getMapObjectCenter: function() {
+        return this.mapObject.getCenter();
+    },
+
+    /** 
+     * APIMethod: getMapObjectZoom
+     * 
+     * Returns:
+     * {Integer} The mapObject's current zoom, in Map Object format
+     */
+    getMapObjectZoom: function() {
+        return this.mapObject.getZoom();
+    },
+
+
+  // LonLat - Pixel Translation
+  
+    /**
+     * APIMethod: getMapObjectLonLatFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Object} MapObject LonLat translated from MapObject Pixel
+     */
+    getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
+        return this.mapObject.fromContainerPixelToLatLng(moPixel);
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Object} MapObject Pixel transtlated from MapObject LonLat
+     */
+    getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
+        return this.mapObject.fromLatLngToContainerPixel(moLonLat);
+    },
+
+  
+  // Bounds
+  
+    /** 
+     * APIMethod: getMapObjectZoomFromMapObjectBounds
+     * 
+     * Parameters:
+     * moBounds - {Object} MapObject Bounds format
+     * 
+     * Returns:
+     * {Object} MapObject Zoom for specified MapObject Bounds
+     */
+    getMapObjectZoomFromMapObjectBounds: function(moBounds) {
+        return this.mapObject.getBoundsZoomLevel(moBounds);
+    },
+
+    /************************************
+     *                                  *
+     *       MapObject Primitives       *
+     *                                  *
+     ************************************/
+
+
+  // LonLat
+    
+    /**
+     * APIMethod: getLongitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Longitude of the given MapObject LonLat
+     */
+    getLongitudeFromMapObjectLonLat: function(moLonLat) {
+        return this.sphericalMercator ? 
+          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lon :
+          moLonLat.lng();  
+    },
+
+    /**
+     * APIMethod: getLatitudeFromMapObjectLonLat
+     * 
+     * Parameters:
+     * moLonLat - {Object} MapObject LonLat format
+     * 
+     * Returns:
+     * {Float} Latitude of the given MapObject LonLat
+     */
+    getLatitudeFromMapObjectLonLat: function(moLonLat) {
+        var lat = this.sphericalMercator ? 
+          this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lat :
+          moLonLat.lat(); 
+        return lat;  
+    },
+    
+    /**
+     * APIMethod: getMapObjectLonLatFromLonLat
+     * 
+     * Parameters:
+     * lon - {Float}
+     * lat - {Float}
+     * 
+     * Returns:
+     * {Object} MapObject LonLat built from lon and lat params
+     */
+    getMapObjectLonLatFromLonLat: function(lon, lat) {
+        var gLatLng;
+        if(this.sphericalMercator) {
+            var lonlat = this.inverseMercator(lon, lat);
+            gLatLng = new GLatLng(lonlat.lat, lonlat.lon);
+        } else {
+            gLatLng = new GLatLng(lat, lon);
+        }
+        return gLatLng;
+    },
+
+  // Pixel
+    
+    /**
+     * APIMethod: getXFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} X value of the MapObject Pixel
+     */
+    getXFromMapObjectPixel: function(moPixel) {
+        return moPixel.x;
+    },
+
+    /**
+     * APIMethod: getYFromMapObjectPixel
+     * 
+     * Parameters:
+     * moPixel - {Object} MapObject Pixel format
+     * 
+     * Returns:
+     * {Integer} Y value of the MapObject Pixel
+     */
+    getYFromMapObjectPixel: function(moPixel) {
+        return moPixel.y;
+    },
+
+    /**
+     * APIMethod: getMapObjectPixelFromXY
+     * 
+     * Parameters:
+     * x - {Integer}
+     * y - {Integer}
+     * 
+     * Returns:
+     * {Object} MapObject Pixel from x and y parameters
+     */
+    getMapObjectPixelFromXY: function(x, y) {
+        return new GPoint(x, y);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Google"
+});
+/* ======================================================================
     OpenLayers/Layer/Grid.js
    ====================================================================== */
 
@@ -18296,12 +19775,12 @@
                 tileoffsetlon += tilelon;       
                 tileoffsetx += this.tileSize.w;
             } while ((tileoffsetlon <= bounds.right + tilelon * this.buffer)
-                     || colidx < minCols);
+                     || colidx < minCols)  
              
             tileoffsetlat -= tilelat;
             tileoffsety += this.tileSize.h;
         } while((tileoffsetlat >= bounds.bottom - tilelat * this.buffer)
-                || rowidx < minRows);
+                || rowidx < minRows)
         
         //shave off exceess rows and colums
         this.removeExcessTiles(rowidx, colidx);
@@ -19039,17 +20518,6 @@
      * {Boolean} Whether or not to handle right clicks. Default is false.
      */
     handleRightClicks: false,
-
-    /**
-     * APIProperty: zoomBoxKeyMask
-     * {Integer} <OpenLayers.Handler> key code of the key, which has to be
-     *    pressed, while drawing the zoom box with the mouse on the screen. 
-     *    You should probably set handleRightClicks to true if you use this
-     *    with MOD_CTRL, to disable the context menu for machines which use
-     *    CTRL-Click as a right click.
-     * Default: <OpenLayers.Handler.MOD_SHIFT
-     */
-    zoomBoxKeyMask: OpenLayers.Handler.MOD_SHIFT,
     
     /**
      * Constructor: OpenLayers.Control.Navigation
@@ -19133,7 +20601,7 @@
             OpenLayers.Util.extend({map: this.map}, this.dragPanOptions)
         );
         this.zoomBox = new OpenLayers.Control.ZoomBox(
-                    {map: this.map, keyMask: this.zoomBoxKeyMask});
+                    {map: this.map, keyMask: OpenLayers.Handler.MOD_SHIFT});
         this.dragPan.draw();
         this.zoomBox.draw();
         this.handlers.wheel = new OpenLayers.Handler.MouseWheel(
@@ -21529,7 +22997,9 @@
                 this.preFeatureInsert(feature);
             }
 
-            this.drawFeature(feature);
+            if (this.drawn) {
+                this.drawFeature(feature);
+            }
             
             if (notify) {
                 this.events.triggerEvent("featureadded", {
@@ -21648,12 +23118,6 @@
      * style - {Object} Symbolizer hash or {String} renderIntent
      */
     drawFeature: function(feature, style) {
-        // don't try to draw the feature with the renderer if the layer is not 
-        // drawn itself
-        if (!this.drawn) {
-            return
-        }
-        
         if (typeof style != "object") {
             var renderIntent = typeof style == "string" ?
                 style : feature.renderIntent;



More information about the fusion-commits mailing list