Project

General

Profile

1
/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
2
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the full
3
 * text of the license. */
4

    
5
/**
6
 * @class
7
 */
8
OpenLayers.Layer = Class.create();
9
OpenLayers.Layer.prototype = {
10

    
11
    /** @type String */
12
    id: null,
13

    
14
    /** @type String */
15
    name: null,
16

    
17
    /** @type DOMElement */
18
    div: null,
19

    
20
    /** This variable is set when the layer is added to the map, via the 
21
     *  accessor function setMap()
22
     * 
23
     * @type OpenLayers.Map */
24
    map: null,
25
    
26
    /** Whether or not the layer is a base layer. This should be set 
27
     *   individually by all subclasses. 
28
     *   Default is false
29
     * 
30
     * @type Boolean
31
     */
32
    isBaseLayer: false,
33
 
34
    /** asserts whether or not the layer's images have an alpha channel 
35
     * 
36
     * @type boolean */
37
    alpha: false,
38

    
39
  // OPTIONS
40

    
41
    /** @type Array */
42
    options: null,
43

    
44
    /** @type String */
45
    projection: null,    
46
        
47
    /** @type OpenLayers.Bounds */
48
    maxExtent: null,
49
    
50
    /** @type float */
51
    maxResolution: null,
52

    
53
    /** @type int */
54
    numZoomLevels: null,
55
   
56
    /** @type float */
57
    minScale: null,
58
    
59
    /** @type float */
60
    maxScale: null,
61
    
62
    /** @type String */
63
    units: null,
64
    
65
    /**
66
     * @constructor
67
     * 
68
     * @param {String} name
69
     * @param {Object} options Hashtable of extra options to tag onto the layer
70
     */
71
    initialize: function(name, options) {
72
        if (arguments.length > 0) {
73

    
74
            //store a copy of the custom options for later cloning
75
            this.options = Object.extend(new Object(), options);
76
            
77
            //add options to layer
78
            Object.extend(this, this.options);
79

    
80
            this.name = name;
81
            
82
            //generate unique id based on name
83
            this.id = OpenLayers.Util.createUniqueID("Layer_");
84
            
85
            if (this.div == null) {
86
                this.div = OpenLayers.Util.createDiv();
87
                this.div.style.width = "100%";
88
                this.div.style.height = "100%";
89
            }
90
        }
91
    },
92
    
93
    /**
94
     * Destroy is a destructor: this is to alleviate cyclic references which
95
     * the Javascript garbage cleaner can not take care of on its own.
96
     */
97
    destroy: function() {
98
        if (this.map != null) {
99
            this.map.removeLayer(this);
100
        }
101
        this.map = null;
102
        this.name = null;
103
        this.div = null;
104
        this.options = null;
105
    },
106
    
107
   /**
108
    * @returns An exact clone of this OpenLayers.Layer
109
    * @type OpenLayers.Layer
110
    */
111
    clone: function (obj) {
112
        
113
        if (obj == null) {
114
            obj = new OpenLayers.Layer(this.name, this.options);
115
        } 
116
        
117
        // catch any randomly tagged-on properties
118
        OpenLayers.Util.applyDefaults(obj, this);
119
        
120
        // a cloned layer should never have its map property set
121
        //  because it has not been added to a map yet. 
122
        obj.map = null;
123
        
124
        return obj;
125
    },
126
    
127
    /** 
128
     * @param {String} newName
129
     */
130
    setName: function(newName) {
131
        this.name = newName;
132
        if (this.map != null)
133
            this.map.events.triggerEvent("changelayer");
134
    },    
135
    
136
   /**
137
    * @param {Object} newOptions
138
    */
139
    addOptions: function (newOptions) {
140
        
141
        // update our copy for clone
142
        Object.extend(this.options, newOptions);
143

    
144
        // add new options to this
145
        Object.extend(this, this.options);
146
    },
147
    
148
    /**
149
     * 
150
     */
151
    onMapResize: function() {
152
        //this function can be implemented by subclasses  
153
    },
154

    
155
    /**
156
     * @param {OpenLayers.Bounds} bound
157
     * @param {Boolean} zoomChanged tells when zoom has changed, as layers 
158
     *                   have to do some init work in that case.
159
     * @param {Boolean} minor
160
     */
161
    moveTo:function(bounds, zoomChanged, minor) {
162
        //this function can be implemented by subclasses.
163
    },
164

    
165
    /** Set the map property for the layer. This is done through an accessor
166
     *   so that subclasses can override this and take special action once 
167
     *   they have their map variable set. 
168
     * 
169
     *  Here we take care to bring over any of the necessary default properties
170
     *   from the map. 
171
     * 
172
     * @param {OpenLayers.Map} map
173
     */
174
    setMap: function(map) {
175
        this.map = map;
176
        
177
        var properties = new Array(
178
          'projection', 'units',
179
          'scales', 'resolutions',
180
          'maxScale', 'minScale', 
181
          'maxResolution', 'minResolution', 
182
          'minExtent', 'maxExtent',
183
          'numZoomLevels'
184
        );
185
        if (this.map.maxZoomLevel && !this.numZoomLevels) {
186
            this.numZoomLevels = this.map.maxZoomLevel + 1;
187
        }
188
        for(var i=0; i < properties.length; i++) {
189
            if (this[properties[i]] == null) {
190
                this[properties[i]] = this.map[properties[i]];
191
            }    
192
        }
193
    },
194
  
195
    /**
196
    * @returns Whether or not the layer is visible
197
    * @type Boolean
198
    */
199
    getVisibility: function() {
200
        return (this.div.style.display != "none");
201
    },
202

    
203
    /** 
204
     * @param {Boolean} visible
205
     * @param {Boolean} noEvent
206
     */
207
    setVisibility: function(visible, noEvent) {
208
        if (visible != this.getVisibility()) {
209
            this.div.style.display = (visible) ? "block" : "none";
210
            if ((visible) && (this.map != null)) {
211
                var extent = this.map.getExtent();
212
                if (extent != null) {
213
                    this.moveTo(this.map.getExtent());
214
                }
215
            }
216
            if ((this.map != null) && 
217
                ((noEvent == null) || (noEvent == false))) {
218
                this.map.events.triggerEvent("changelayer");
219
            }
220
        }
221
    },
222
    
223
    
224
  /********************************************************/
225
  /*                                                      */
226
  /*                 Layer Options                        */
227
  /*                                                      */
228
  /*    Accessor functions to Layer Options parameters    */
229
  /*                                                      */
230
  /********************************************************/
231
    
232
    /** 
233
     * @param {Boolean} isBaseLayer 
234
     */
235
    setIsBaseLayer: function(isBaseLayer) {
236
        this.isBaseLayer = isBaseLayer;
237
        if (this.map != null) {
238
            this.map.events.triggerEvent("changelayer");
239
        }
240
    },
241
    
242
    /**
243
     * @type String
244
     */
245
    getProjection: function() {
246
        return this.projection;
247
    },    
248
    
249
    /**
250
     * @type OpenLayers.Bounds
251
     */
252
    getMaxExtent: function() {
253
        return this.maxExtent;
254
    }, 
255

    
256
    /** 
257
     * @type float
258
     */
259
    getMaxResolution: function() {
260
        return this.maxResolution;
261
    },
262
    
263
    /**
264
     * @returns The total number of zoom levels this layer can reach
265
     * @type int
266
     */
267
    getNumZoomLevels: function() {
268
        return this.numZoomLevels;
269
    },
270

    
271
  /********************************************************/
272
  /*                                                      */
273
  /*                 Baselayer Functions                  */
274
  /*                                                      */
275
  /*    The following functions must all be implemented   */
276
  /*                  by all base layers                  */
277
  /*                                                      */
278
  /********************************************************/
279
    
280
    /** 
281
     * @returns Degrees per Pixel
282
     * @type float
283
     */
284
    getResolution: function() {
285
        var viewSize = this.map.getSize();
286
        var extent = this.getExtent();
287
        return Math.max( extent.getWidth()  / viewSize.w,
288
                         extent.getHeight() / viewSize.h );
289
    },
290
    
291
    /** Calculates using px-> lonlat translation functions on tl and br 
292
     *   corners of viewport
293
     * 
294
     * @returns A Bounds object which represents the lon/lat bounds of the 
295
     *          current viewPort.
296
     * @type OpenLayers.Bounds
297
     */
298
    getExtent: function () {
299
        var extent = null;
300
        
301
        
302
        var size = this.map.getSize();
303
        
304
        var tlPx = new OpenLayers.Pixel(0,0);
305
        var tlLL = this.getLonLatFromViewPortPx(tlPx);
306

    
307
        var brPx = new OpenLayers.Pixel(size.w, size.h);
308
        var brLL = this.getLonLatFromViewPortPx(brPx);
309
        
310
        if ((tlLL != null) && (brLL != null)) {
311
            extent = new OpenLayers.Bounds(tlLL.lon, 
312
                                       brLL.lat, 
313
                                       brLL.lon, 
314
                                       tlLL.lat);
315
        }
316

    
317
        return extent;
318
    },
319

    
320
    
321
    /**
322
    * @param {OpenLayers.Pixel} viewPortPx
323
    *
324
    * @returns An OpenLayers.LonLat which is the passed-in view port
325
    *          OpenLayers.Pixel, translated into lon/lat by the layer
326
    * @type OpenLayers.LonLat
327
    */
328
    getLonLatFromViewPortPx: function (viewPortPx) {
329
        var size = this.map.getSize();
330
        var center = this.map.getCenter();
331
        var res  = this.map.getResolution();
332
    
333
        var delta_x = viewPortPx.x - (size.w / 2);
334
        var delta_y = viewPortPx.y - (size.h / 2);
335
        
336
        return new OpenLayers.LonLat(center.lon + delta_x * res ,
337
                                     center.lat - delta_y * res); 
338
    },
339

    
340
    /**
341
    * @param {OpenLayers.LonLat} lonlat
342
    *
343
    * @returns An OpenLayers.Pixel which is the passed-in OpenLayers.LonLat, 
344
    *          translated into view port pixels
345
    * @type OpenLayers.Pixel
346
    */
347
    getViewPortPxFromLonLat: function (lonlat) {
348
        var resolution = this.map.getResolution();
349
        var extent = this.map.getExtent();
350
        return new OpenLayers.Pixel(
351
                       Math.round(1/resolution * (lonlat.lon - extent.left)),
352
                       Math.round(1/resolution * (extent.top - lonlat.lat))
353
                       );    
354
    },
355
    
356
    /**
357
    * @param {OpenLayers.Bounds} bounds
358
    *
359
    * @return {int}
360
    */
361
    getZoomForExtent: function (bounds) {
362
        // this should be implemented by subclasses
363
    },
364

    
365

    
366

    
367
    /** @final @type String */
368
    CLASS_NAME: "OpenLayers.Layer"
369
};
(7-7/13)