Project

General

Profile

1
/*
2
Author:       Cameron Shorter cameronAtshorter.net
3
License:      LGPL as per: http://www.gnu.org/copyleft/lesser.html
4

    
5
$Id: MapPaneOL.js 3935 2008-03-25 13:58:02Z ahocevar $
6
*/
7

    
8
// Ensure this object's dependancies are loaded.
9
loadCss("openlayers/style.css");
10
mapbuilder.loadScript(baseDir+"/util/openlayers/OpenLayers.js");
11
mapbuilder.loadScript(baseDir+"/util/Util.js");
12
mapbuilder.loadScript(baseDir+"/widget/WidgetBase.js");
13
mapbuilder.loadScript(baseDir+"/tool/Extent.js");
14
/**
15
 * Widget to render a map from an OGC context document.  The layers are
16
 * rendered using http://openlayers.org .
17
 * @constructor
18
 * @base WidgetBase
19
 * @param widgetNode  The widget's XML object node from the configuration document.
20
 * @param model       The model object that this widget belongs to.
21
 */
22
function MapPaneOL(widgetNode, model) {
23
  WidgetBase.apply(this,new Array(widgetNode, model));
24

    
25
  OpenLayers.ImgPath = config.skinDir + '/images/openlayers/';
26
  OpenLayers.ProxyHost = config.proxyUrl+"/?url=";
27
  
28

    
29
  // replacement for deprecated MapContainerBase
30
  this.containerNodeId = this.htmlTagId;
31
  model.containerModel = this.model;
32

    
33
  //Make sure the Extent is attached to the context and initialized
34
  if(!this.model.extent){
35
    this.model.extent = new Extent (this.model);
36
    this.model.addFirstListener( "loadModel", this.model.extent.firstInit, this.model.extent );
37
  }
38

    
39
  /**
40
   * For tiled wms layers: Overlap of map tiles in pixels. Useful for
41
   * preventing rendering artefacts at tile edges. Recommended values:
42
   * 0-15, default is 0 (no gutter at all).
43
   */
44
  this.tileGutter = this.getProperty("mb:tileGutter", 0);
45
  
46
  /**
47
   * For tiled wms layers: how many rows of tiles should be preloaded
48
   * outside the visible map? Large values mean slow loading, small
49
   * ones mean longer delays when panning. Recommended values: 1-3,
50
   * default is 2.
51
   */
52
  this.tileBuffer = parseInt(this.getProperty("mb:tileBuffer", 2));
53
  
54
   /**
55
    * For WMS layers: should they be regarded as normal WMS layers, 
56
    * with a single tile for the entire boundingbox or as a tiled
57
    * WMS layer
58
   */
59
  this.singleTile = Mapbuilder.parseBoolean(this.getProperty("mb:singleTile", true));
60
  
61
  /**
62
   * For tiled wms layers: how many pixels should the size of one tile
63
   * be? Default is 256.
64
   */
65
  this.tileSize = parseInt(this.getProperty("mb:tileSize", 256));
66
  
67
  /**
68
   * For WMS on top of Google Maps you need to reproject the WMS image. This will stretch
69
   * the WMS images to fit the odd sized google tiles. Default is false
70
   */
71
  this.imageReproject = Mapbuilder.parseBoolean(
72
      this.getProperty("mb:imageReproject", false));
73
  
74
  /**
75
   * for untiled wms layers: how many times should the map image be
76
   * larger than the visible map. Large values mean slow loading, small
77
   * ones mean many reloads when panning. Recommended values: 1-3,
78
   * default is 2.
79
   */
80
  this.imageBuffer = parseInt(this.getProperty("mb:imageBuffer", 2));
81
  
82
  /**
83
   * Should layers also be rendered outside the map extent? Default is false.
84
   */
85
  this.displayOutsideMaxExtent = Mapbuilder.parseBoolean(
86
      this.getProperty("mb:displayOutsideMaxExtent", false));
87
  
88
  /**
89
   * Number of layers that are currently being loaded
90
   */
91
  this.loadingLayers = 0;
92

    
93
  /**
94
   * Called after a feature has been added to a WFS.  This function triggers
95
   * the WMS basemaps to be redrawn.  A timestamp param is added to the URL
96
   * to ensure the basemap image is not cached.
97
   * This function is triggered by the refreshWmsLayers event. If this event
98
   * is fired with a <layerId> as param, only that layer will be refreshed.
99
   * @param objRef reference to this widget
100
   */
101
  this.refreshWmsLayers = function(objRef) {
102
    var layerId = objRef.model.getParam("refreshWmsLayers");
103
    var uniqueId = (new Date()).getTime();
104
    var layers = layerId ?
105
        [objRef.getLayer(objRef, layerId)] :
106
        objRef.model.map.layers;
107
    for (var i in layers) {
108
      if (layers[i].CLASS_NAME.indexOf('OpenLayers.Layer.WMS') == 0) {
109
        layers[i].mergeNewParams({uniqueId: uniqueId});
110
      }
111
    }
112
  }
113
  this.model.addListener("refreshWmsLayers",this.refreshWmsLayers,this);
114

    
115
  this.model.addListener("refresh",this.paint, this);
116
  this.model.addFirstListener("newModel", this.clear, this);
117
  this.model.addListener("hidden",this.hidden, this);
118
  this.model.addListener("addLayer",this.addLayer, this);
119
  this.model.addListener("deleteLayer",this.deleteLayer, this);
120
  this.model.addListener("moveLayerUp",this.moveLayerUp, this);
121
  this.model.addListener("moveLayerDown",this.moveLayerDown, this);
122
  this.model.addListener("opacity",this.setOpacity,this);
123
  this.model.addListener("bbox", this.zoomToBbox, this);
124
  //this.model.addListener( "zoomOut", this.zoomOut, this );
125
  //this.model.addListener( "zoomIn", this.zoomIn, this );
126
  // this.model.addListener( "zoomToMaxExtent", this.zoomToMaxExtent, this );
127
 //this.model.addFirstListener("loadModel",this.paint,this);
128

    
129
}
130

    
131
/**
132
 * Render the widget.
133
 * @param objRef Pointer to widget object.
134
 */
135
MapPaneOL.prototype.paint = function(objRef, refresh) {
136
  
137
  // Create an OpenLayers map
138

    
139
  //Test if context exist
140
  if(objRef.model.doc.selectSingleNode("//wmc:OWSContext"))
141
    objRef.context="OWS";
142
  else if(objRef.model.doc.selectSingleNode("//wmc:ViewContext"))
143
    objRef.context="View";
144
  else
145
    alert(mbGetMessage("noContextDefined"));
146

    
147
  var proj=objRef.model.proj;
148

    
149
  //maxExtent
150
  var maxExtent=null;
151
  maxExtent=objRef.getProperty("mb:maxExtent");
152
  maxExtent=(maxExtent)?maxExtent.split(" "):null;
153
  // If the maxExtentis not specified in the config
154
  // calculate it from the BBox  in the Context.
155
  if(!maxExtent){
156
    maxExtent=objRef.model.getBoundingBox();
157
  }
158
  maxExtent=(maxExtent)?new OpenLayers.Bounds(maxExtent[0],maxExtent[1],maxExtent[2],maxExtent[3]):null;
159
  if(maxExtent==null)alert(mbGetMessage("noBboxInContext"));
160

    
161
  //maxResolution
162
  var maxResolution=null;
163
  maxResolution=objRef.getProperty("mb:maxResolution");
164
  maxResolution=(maxResolution) ? parseFloat(maxResolution) : "auto";
165

    
166
  //minResolution
167
  var minResolution=null;
168
  minResolution=objRef.getProperty("mb:minResolution");
169
  minResolution=(minResolution) ? parseFloat(minResolution) : undefined;
170
  
171
  //transitionEffect
172
  objRef.transitionEffect = objRef.getProperty("mb:transitionEffect", undefined);
173
  
174
  //units
175
  var units = proj.getUnits() == 'meters' ? 'm' : proj.getUnits();
176
  
177
  //resolutions
178
  //TBD: if resolutions is both set here and for the baselayer and they are different weird things may happen
179
  //     this needs to be solved
180
  var resolutions=objRef.getProperty("mb:resolutions");
181
  resolutions = resolutions ? resolutions.split(",") : null;
182
  if (resolutions) {
183
    for (var r=0; r<resolutions.length; r++) {
184
      resolutions[r] = parseFloat(resolutions[r]);
185
    }
186
  }
187

    
188
  //fixed scales - overrides resolutions
189
  var scales = objRef.getProperty("mb:scales");
190
  if(scales){
191
    scales = scales.split(",");
192
    resolutions = new Array();
193
    for (var s=0; s<scales.length; s++) {
194
      resolutions.push(OpenLayers.Util.getResolutionFromScale(scales[s], units));
195
    }
196
  }
197
  if(resolutions){
198
    objRef.model.extent.setZoomLevels(true,resolutions);
199
  }
200
  else objRef.model.extent.setZoomLevels(false);
201

    
202
  //get the output DIV and set it to context-size
203
  var node = document.getElementById(objRef.containerNodeId);
204
  var fixedSize = Mapbuilder.parseBoolean(objRef.getProperty("mb:fixedSize", false));
205
  if(fixedSize){
206
    node.style.width = objRef.model.getWindowWidth()+"px";
207
    node.style.height = objRef.model.getWindowHeight()+"px";
208
  }
209
  
210
  //default map options
211
  var mapOptions = {
212
        controls:[],
213
        projection: proj,
214
        units: units,
215
        fractionalZoom: true,
216
        maxExtent: maxExtent,
217
        maxResolution: maxResolution,
218
        minResolution: minResolution,
219
        resolutions: resolutions,
220
        theme: null, // we have the theme loaded by Mapbuilder
221
        destroy: function(destroy){
222
                   if (destroy != true) {
223
                     this.mbMapPane.model.setParam("newModel", true);
224
                   } else {
225
                     this.mbMapPane = null;
226
                     this.mbCursor = null;
227
                     OpenLayers.Map.prototype.destroy.apply(this, arguments);
228
                     this.layerContainerDiv = null;
229
                     this.baseLayer = null;
230
                   }}
231
      };
232

    
233
  if (!objRef.model.map) {
234
    objRef.model.map = new OpenLayers.Map(node, mapOptions);
235

    
236
    // Increase hight of Control layers to allow for lots of layers.
237
    objRef.model.map.Z_INDEX_BASE.Control=10000;
238
    var baseLayer = null;
239
    
240
    //If we have an OWSContext and we have a BaseLayer we need to use this layer
241
    //for more information have a look at http://docs.codehaus.org/display/MAP/Using+Google-layers
242
    if(objRef.context=="OWS"&&objRef.model.getBaseLayer()){
243
      var baseLayerNode = objRef.model.getBaseLayer();
244
     
245
      //overrule the SRS in the Context with the one from the BaseLayer
246
      var baseSrs = baseLayerNode.selectSingleNode("ows:TileSet/ows:SRS");
247
      if(baseSrs) objRef.model.setSRS(getNodeValue(baseSrs));
248
      //overrule the units in the Context with the updated SRS units
249
      units = proj.getUnits() == 'meters' ? 'm' : proj.getUnits();
250
      //overrule the boundingbox in the Context with the maxExtent from the BaseLayer
251
      var maxExtentNode = baseLayerNode.selectSingleNode("ows:TileSet/ows:BoundingBox");
252
      if(maxExtentNode) maxExtent = new OpenLayers.Bounds(maxExtentNode.selectSingleNode('@minx').nodeValue,maxExtentNode.selectSingleNode('@miny').nodeValue,maxExtentNode.selectSingleNode('@maxx').nodeValue,maxExtentNode.selectSingleNode('@maxy').nodeValue);
253
      //overrule resolutions in the Context with the one from BaseLayer
254
      //@TODO: check if the firstChild is really needed
255
      var resolutions =baseLayerNode.selectSingleNode("ows:TileSet/ows:Resolutions");
256
      resolutions = resolutions ? getNodeValue(resolutions).split(",") : null;
257
      if (resolutions) {
258
        for (var r=0; r<resolutions.length; r++) {
259
           resolutions[r] = parseFloat(resolutions[r]);
260
        }
261
      }
262
      //overrule tileSize in the Context with the one from the BaseLayer
263
      //right now we only support square tiles which are defined by their width:		  
264
      var tileSize =baseLayerNode.selectSingleNode("ows:TileSet/ows:Width");
265
      if(tileSize) objRef.tileSize = parseInt(tileSize.nodeValue);
266
      //check if there's a format defined for the BaseLayer
267
      var format = baseLayerNode.selectSingleNode("ows:TileSet/ows:Format");
268
      if(format) format = format.nodeValue;
269
      
270
      //Initialising the baseLayer
271
      // Test service of the baseLayer
272
      var service=baseLayerNode.selectSingleNode("wmc:Server/@service");
273
      service=(service)?service.nodeValue:"";
274
      // Test title of the baseLayer
275
      var title=Mapbuilder.getProperty(baseLayerNode, "wmc:Title", "");
276
      // Get the name of the baseLayer
277
      var baseLayerName = Mapbuilder.getProperty(baseLayerNode, "wmc:Name", "");
278
      // get the layer-type of the BaseLayer (this allows specifying if is is a arial,road or hybrid map)
279
      var baseLayerType = Mapbuilder.getProperty(baseLayerNode, "ows:TileSet/ows:Layers", "hybrid");
280
      // it might be that the baseLayer is a WMS so we need to fetch the url
281
      var href=Mapbuilder.getProperty(baseLayerNode, "wmc:Server/wmc:OnlineResource/@xlink:href", "");
282
      
283
      var baseLayerOptions = {
284
              units: units,
285
              projection: proj,
286
              maxExtent: maxExtent,
287
             
288
              alpha: false,            //option for png transparency with ie6
289
              isBaseLayer: true,
290
              displayOutsideMaxExtent: objRef.displayOutsideMaxExtent,
291
              ratio: 1
292
              
293
         };
294
         
295
      switch(service){
296
        // WMS Layer (Untiled)
297
        case "OGC":
298
        case "WMS":
299
        case "wms":
300
        case "OGC:WMS":
301
          
302
          baseLayerOptions.ratio = objRef.imageBuffer;
303
    
304
          var params = new Array();
305

    
306
         
307
         baseLayer= new OpenLayers.Layer.WMS(title,href,{
308
              layers: baseLayerName,
309
              format: format
310
              },
311
            baseLayerOptions
312
          );
313
        break;
314
    
315
        // WMS-C Layer (Tiled)
316
        case "WMS-C":
317
        case "OGC:WMS-C":
318
          baseLayerOptions.gutter = objRef.tileGutter;
319
          baseLayerOptions.buffer = objRef.tileBuffer;
320
          baseLayerOptions.tileSize = new OpenLayers.Size(objRef.tileSize, objRef.tileSize);
321
          
322
          baseLayer= new OpenLayers.Layer.WMS(title,href,{
323
              layers: baseLayerName,
324
              format: format
325
            },
326
            baseLayerOptions
327
          );
328
          objRef.model.map.fractionalZoom = false;
329
        break;
330
    
331
        case "GMAP":
332
        case "Google":       
333
          if(maxExtent) baseLayerOptions.maxExtent=maxExtent;
334
          //check if we have spherical projection
335
          var sphericalMercator = (objRef.model.getSRS()=='EPSG:900913')?true:false;
336
          //check if we have a layertype
337
          switch(baseLayerType){
338
            case "aerial":
339
            case "satellite":            
340
              baseLayerType=G_SATELLITE_MAP;
341
            break;
342
            case "road":
343
            case "normal":            
344
              baseLayerType=G_NORMAL_MAP;
345
            break;
346
            default:
347
              baseLayerType=G_HYBRID_MAP;
348
          }
349
          baseLayer = new OpenLayers.Layer.Google( baseLayerName , {type: baseLayerType, minZoomLevel: 0, maxZoomLevel:19, sphericalMercator: sphericalMercator, maxResolution: 156543.0339 }, baseLayerOptions );
350
          objRef.model.map.numZoomLevels = 20;
351
          objRef.model.map.fractionalZoom = false;
352
        break;
353
    
354
        case "YMAP":
355
        case "Yahoo":
356
          //Yahoo-layer doesn't support layerTypes
357
          if(maxExtent) baseLayerOptions.maxExtent=maxExtent;
358
          //check if we have spherical projection
359
          var sphericalMercator = (objRef.model.getSRS()=='EPSG:900913')?true:false;          
360
          baseLayer = new OpenLayers.Layer.Yahoo(  baseLayerName , { maxZoomLevel:21, sphericalMercator: sphericalMercator }, baseLayerOptions );
361
          objRef.model.map.fractionalZoom = false;
362
        break;
363
    
364
        case "VE":
365
        case "Microsoft":
366
          if(maxExtent) baseLayerOptions.maxExtent=maxExtent;
367
          //check if we have spherical projection
368
          var sphericalMercator = (objRef.model.getSRS()=='EPSG:900913')?true:false;
369
          //check if we have a layertype
370
          switch(baseLayerType){
371
            case "aerial":
372
            case "satellite":
373
              baseLayerType=VEMapStyle.Aerial;
374
            break;
375
            case "road":
376
            case "normal":
377
              baseLayerType=VEMapStyle.Road;
378
            break;
379
            default:
380
              baseLayerType=VEMapStyle.Hybrid;
381
          }
382
          baseLayer = new OpenLayers.Layer.VirtualEarth( baseLayerName,{minZoomLevel: 0, maxZoomLevel: 21,type: baseLayerType});
383
          objRef.model.map.fractionalZoom = false;
384
        break;
385
    
386
        case "MultiMap":
387
           if(maxExtent) baseLayerOptions.maxExtent=maxExtent;
388
           //check if we have spherical projection
389
          var sphericalMercator = (objRef.model.getSRS()=='EPSG:900913')?true:false;          
390
          baseLayer = new OpenLayers.Layer.MultiMap( baseLayerName , { maxZoomLevel:21, sphericalMercator: sphericalMercator }, baseLayerOptions );
391
          objRef.model.map.fractionalZoom = false;
392
        break;
393
        default:
394
          alert(mbGetMessage("layerTypeNotSupported", service));
395
        }
396
    }
397
    //Otherwise we will just use a bogus WMS layer as BaseLayer
398
    else {
399
      var baseLayerOptions = {
400
              units: units,
401
              projection: proj.srsCode,
402
              maxExtent: maxExtent,
403
              maxResolution: maxResolution,  //"auto" if not defined in the context
404
              minResolution: minResolution,
405
              resolutions: resolutions,
406
              alpha: false,            //option for png transparency with ie6
407
              isBaseLayer: true,
408
              displayOutsideMaxExtent: objRef.displayOutsideMaxExtent,
409
              ratio: 1,
410
              singleTile: true,
411
              transitionEffect: objRef.transitionEffect,
412
              visibility: false,
413
              moveTo: function(){return true}
414
         };
415
      baseLayer = new OpenLayers.Layer.WMS("baselayer",
416
              config.skinDir+"/images/openlayers/blank.gif", null, baseLayerOptions);
417
      
418
    }
419
    objRef.model.map.addLayer(baseLayer); 
420
  }
421
  else {
422
    objRef.deleteAllLayers(objRef);
423
  }
424
    
425
  var layers = objRef.model.getAllLayers();
426
  if (!objRef.oLlayers){
427
    objRef.oLlayers = {};
428
  }
429

    
430
  for (var i=0;i<=layers.length-1;i++){
431
    objRef.addLayer(objRef,layers[i]);
432
  }
433
  var bbox=objRef.model.getBoundingBox();
434

    
435
  // set objRef as attribute of the OL map, so we have a reference
436
  // to MapPaneOL available when handling OpenLayers events.
437
  objRef.model.map.mbMapPane = objRef;
438

    
439
  // register OpenLayers event to keep the context updated
440
  objRef.model.map.events.register('moveend', objRef.model.map, objRef.updateContext);
441
  // register OpenLayers event to do updates onmouseup
442
  objRef.model.map.events.register('mouseup', objRef.model.map, objRef.updateMouse);
443
  
444
  objRef.model.callListeners("bbox");
445
  
446
}
447

    
448
/**
449
 * remove OpenLayers events and layers
450
 * @param objRef reference to this widget
451
 */
452
MapPaneOL.prototype.clear = function(objRef) {
453
  if (objRef.model.map) {
454
    OpenLayers.Event.stopObservingElement(window);
455
    objRef.model.map.destroy(true);
456
    objRef.model.map = null;
457
    objRef.oLlayers = {};
458
  }
459
}
460

    
461
/**
462
 * Event handler to keep the modelStatus updated when an OpenLayers layer
463
 * starts loading.
464
 * @param e OpenLayers event
465
 */
466
MapPaneOL.prototype.increaseLoadingLayers = function(e) {
467
  ++this.loadingLayers;
468
  var message = mbGetMessage((this.loadingLayers>1) ? "loadingLayers" : "loadingLayer",
469
    this.loadingLayers);
470
  this.model.setParam("modelStatus", message);
471
}
472

    
473
/**
474
 * Event handler to keep the modelStatus updated when an OpenLayers layer
475
 * finished loading.
476
 * @param e OpenLayers event
477
 */
478
MapPaneOL.prototype.decreaseLoadingLayers = function(e) {
479
  --this.loadingLayers;
480
  var message = this.loadingLayers > 0 ?
481
          mbGetMessage((this.loadingLayers>1) ? "loadingLayers" : "loadingLayer",
482
                  this.loadingLayers) :
483
          null;
484
  this.model.setParam("modelStatus", message);
485
}
486

    
487
/**
488
 * Event handler to keep the Mapbuilder context updated. It also
489
 * sets the map cursor to the previously stored value.
490
 * This is called by OpenLayers.
491
 * @param e OpenLayers event
492
 */
493
MapPaneOL.prototype.updateContext = function(e) {
494
  // get objRef from the event originator object (e.object),
495
  // where it was stored as mbPane property by paint().
496
  var objRef = e.object.mbMapPane;
497

    
498
  var bboxOL = objRef.model.map.getExtent().toBBOX().split(',');
499
  var ul = new Array(bboxOL[0],bboxOL[3]);
500
  var lr = new Array(bboxOL[2],bboxOL[1]);
501

    
502
  if(objRef.model.getWindowWidth()!=e.element.offsetWidth)
503
    objRef.model.setWindowWidth(e.element.offsetWidth);
504
  if(objRef.model.getWindowHeight()!=e.element.offsetHeight)
505
    objRef.model.setWindowHeight(e.element.offsetHeight);	
506

    
507
  var currentAoi = objRef.model.getParam('aoi');
508
  var newAoi = new Array(ul, lr);
509
  if (!currentAoi || currentAoi.toString() != newAoi.toString()) {
510
    objRef.model.setBoundingBox( new Array(ul[0], lr[1], lr[0], ul[1]) );
511
    objRef.model.extent.setSize(objRef.model.map.getResolution());
512
    objRef.model.setParam("aoi", newAoi);
513
  }
514
}
515

    
516
/**
517
 * Restore the map cursor stored by buttons. This has to be done
518
 * in an OpenLayers mouseup event, because the mouseup event
519
 * in OpenLayers resets the cursor to default.
520
 * @param e OpenLayers event
521
 */
522
MapPaneOL.prototype.updateMouse = function(e) {
523
  // get objRef from the event originator object (e.object),
524
  // where it was stored as mbPane property by paint().
525
  var objRef = e.object.mbMapPane;
526

    
527
  // update map pane cursor
528
  if (objRef.model.map.mbCursor) {
529
    objRef.model.map.div.style.cursor = objRef.model.map.mbCursor;
530
  }
531
}
532

    
533
/**
534
 * Zoom to the current Bounding Box.
535
 * @param objRef reference to this widget
536
 */
537
MapPaneOL.prototype.zoomToBbox = function(objRef) {
538
  if (objRef.model.map) {
539
    var bbox = objRef.model.getBoundingBox();
540
    var displayBbox = [];
541
    var extent = objRef.model.map.getExtent();
542
    if (extent) {
543
      displayBbox = extent.toBBOX();
544
    }
545
    // only perform zoom operation if not already at bbox
546
    if (bbox.toString() != displayBbox.toString()) {
547
      objRef.model.map.zoomToExtent(new OpenLayers.Bounds(bbox[0],bbox[1],bbox[2],bbox[3]));
548
    }
549
  }
550
}
551

    
552
/**
553
 * Hide/unhide a layer. Called by Context when the hidden attribute changes.
554
 * @param objRef Pointer to widget object.
555
 * @param layerId Id of the layer to hide/unhide.
556
 */
557
MapPaneOL.prototype.hidden = function(objRef, layerId) {
558
  var vis=objRef.model.getHidden(layerId);
559
  if(vis=="1"){ var hidden=false; }
560
  else {var hidden=true; }
561
  var  tmpLayer=objRef.getLayer(objRef,layerId)
562
  if(tmpLayer)tmpLayer.setVisibility(hidden);
563
}
564

    
565
/**
566
  * Returns OL layer node from LayerMgr
567
  * @param layerId The layer Id (or layerName)
568
  */
569
MapPaneOL.prototype.getLayer = function(objRef,layerId) {
570

    
571
  // If layer cannot be found then layerId might actually be layerName
572
  // We then try to fetch the @id of the layer from the model
573
  if (!objRef.oLlayers[layerId]) {
574
    layerId = objRef.model.getLayerIdByName(layerId) || layerId;
575
  }
576

    
577
  if(objRef.oLlayers[layerId] && objRef.oLlayers[layerId].id) {
578
    return objRef.model.map.getLayer(objRef.oLlayers[layerId].id);
579
  } else {
580
    return false;
581
  }
582
}
583

    
584

    
585
//####################################################
586
/**
587
 * Removes a layer from the output
588
/**
589
 * Removes a layer from the output
590
 * @param objRef Pointer to this object.
591
 * @param layerId the WMS name for the layer to be removed
592
 */
593
MapPaneOL.prototype.deleteLayer = function(objRef, layerId) {
594
  if(objRef.oLlayers[layerId])objRef.model.map.removeLayer(objRef.oLlayers[layerId]);
595
}
596
/**
597
 * Removes all layers from the output
598
 * @param objRef Pointer to this object.
599
 * @param objRef Pointer to this object.
600
 */
601
MapPaneOL.prototype.deleteAllLayers = function(objRef) {
602
  for (var i in objRef.oLlayers) {
603
    var layer = objRef.oLlayers[i];
604
    layer.destroy();
605
  }
606
  objRef.oLlayers = {};
607
}
608

    
609
//#############################################TDO
610
/**
611
 * Moves a layer up in the stack of map layers
612
 * @param objRef Pointer to this object.
613
 * @param layerId the WMS name for the layer to be removed
614
 */
615
MapPaneOL.prototype.moveLayerUp = function(objRef, layerId) {
616
  var map=objRef.model.map;
617
  map.raiseLayer(map.getLayer(objRef.oLlayers[layerId].id), 1);
618
}
619

    
620
/**
621
 * Moves a layer up in the stack of map layers
622
 * @param objRef Pointer to this object.
623
 * @param layerId the WMS name for the layer to be removed
624
 */
625
MapPaneOL.prototype.moveLayerDown = function(objRef, layerId) {
626
  objRef.model.map.raiseLayer(objRef.getLayer(objRef,layerId), -1);
627
}
628
//###############################################
629
/**
630
   * Called when the context's opacity attribute changes.
631
/**
632
   * Called when the context's opacity attribute changes.
633
   * @param objRef This object.
634
   * @param layerId  The id of the layer that was toggled.
635
   */
636
MapPaneOL.prototype.setOpacity=function(objRef, layerId){
637
  var _opacity="1";
638
  _opacity=objRef.model.getOpacity(layerId);
639
  objRef.getLayer(objRef,layerId).setOpacity(_opacity);
640
}
641
/**
642
 * Adds a layer into the output
643
   * @param objRef This object.
644
   * @param layerNode  The node of the layer
645
 */
646
MapPaneOL.prototype.addLayer = function(objRef, layerNode) {
647
  // OpenLayers doesn't contain information about projection, so if the
648
  // baseLayer projection is not standard lat/long, it needs to know
649
  // maxExtent and maxResolution to calculate the zoomLevels.
650
  var layer = layerNode;
651

    
652
  // Test service of the layer
653
  var service=layer.selectSingleNode("wmc:Server/@service");service=(service)?service.nodeValue:"";
654

    
655
  // Test title of the layer
656
  var title=Mapbuilder.getProperty(layer, "wmc:Title", "");
657

    
658
  // Get the name of the layer
659
  layerName = Mapbuilder.getProperty(layer, "wmc:Name", "");
660

    
661
  // Get the layerId. Fallback to layerName if non-existent
662
  var layerId;
663
  if (layer.selectSingleNode("@id") && layer.selectSingleNode("@id").nodeValue) {
664
    layerId = layer.selectSingleNode("@id").nodeValue;
665
  } else {
666
    layerId = layerName;
667
  }
668

    
669
  if (objRef.context=="OWS"){
670
    var href=Mapbuilder.getProperty(layer, "wmc:Server/wmc:OnlineResource/@xlink:href", "");
671
  }
672
  else {
673
     if(_SARISSA_IS_SAFARI){
674
     var nodehref=layer.selectSingleNode("wmc:Server/wmc:OnlineResource");
675
     var href=nodehref.attributes[1].nodeValue;
676
     }
677
   else{
678
     if(_SARISSA_IS_OPERA){
679
       var href=layer.selectSingleNode("wmc:Server/wmc:OnlineResource").getAttributeNS ("http://www.w3.org/1999/xlink","href");// for opera
680
     }else{
681
       var href=layer.selectSingleNode("wmc:Server/wmc:OnlineResource").getAttribute("xlink:href");
682
     }
683
    }
684
  }
685

    
686
  // Test format of the layer
687
  var format=layer.selectSingleNode("wmc:FormatList/wmc:Format[@current='1']");
688
  if (!format) {
689
    format = layer.selectSingleNode("wmc:FormatList/wmc:Format");
690
  }
691
  format = format ? getNodeValue(format) : "image/gif";
692

    
693
  // Test visibility of the layer
694
  var vis=layer.selectSingleNode("@hidden");
695
  if (vis) {
696
    if(vis.nodeValue=="1")
697
      vis=false;
698
    else
699
      vis=true;
700
  }
701
  // Test if layer is queryable
702
  var query=layer.selectSingleNode("@queryable");
703
  if (query){
704
    if(query.nodeValue=="1")
705
      query=true;
706
    else
707
      query=false;
708
  }
709

    
710
  // Test if opacity is specified
711
  var opacity=layer.selectSingleNode("@opacity");
712
  if (opacity)
713
    opacity=opacity.nodeValue;
714
  else
715
    opacity=false;
716
  
717
  // Get current style node of the layer
718
  var currentStyle = layer.selectSingleNode('wmc:StyleList/wmc:Style[@current=1]');
719

    
720
  // will be true for IE6, false for later versions of IE
721
  objRef.IE6 = false /*@cc_on || @_jscript_version < 5.7 @*/;
722
  
723
  //default option value for a layer
724
  var layerOptions = {
725
          visibility: vis,
726
          projection: objRef.model.map.baseLayer.projection,
727
          queryable: query,
728
          maxExtent: objRef.model.map.baseLayer.maxExtent,
729
          maxResolution: objRef.model.map.baseLayer.maxResolution,  //"auto" if not defined in the context
730
          minResolution: objRef.model.map.baseLayer.minResolution,  //"auto" if not defined in the context
731
          alpha: format.indexOf("png") != -1 ? objRef.IE6 : false,         //option for png transparency with ie6
732
          isBaseLayer: false,
733
          displayOutsideMaxExtent: objRef.displayOutsideMaxExtent
734
     };
735
     
736
  switch(service){
737
    // WMS Layer (Untiled)
738
    case "OGC":
739
    case "WMS":
740
    case "wms":
741
    case "OGC:WMS":
742
      if(!objRef.model.map.baseLayer){
743
        layerOptions.isBaseLayer=true;
744
      }
745
      else {
746
        //TBD what if we have layers with different projections in the context?
747
        layerOptions.reproject=objRef.imageReproject;
748
        layerOptions.isBaseLayer=false;
749
      }
750

    
751
      layerOptions.ratio = objRef.imageBuffer;
752
      layerOptions.singleTile = objRef.singleTile;
753
      if (objRef.singleTile == true) {
754
        layerOptions.transitionEffect = objRef.transitionEffect;
755
      }
756

    
757
      var params = new Array();
758
      params = sld2UrlParam(currentStyle);
759
      if (objRef.model.timestampList && objRef.model.timestampList.getAttribute("layerId") == layerId) { 
760
        var ts = objRef.model.timestampList.childNodes[0];
761

    
762
        objRef.oLlayers[layerId]= new OpenLayers.Layer.WMS(title,href,{
763
            layers: layerName,
764
            // "TRUE" in upper case else the context doc boston.xml
765
            // (i.c. the IONIC WMS/WFS) doesn't work.
766
            // Note that this is in line with the WMS standard (OGC 01-068r2),
767
            // section 6.4.1 Parameter Ordering and Case:
768
            // "Parameter names shall not be case sensitive,
769
            //  but parameter values shall be case sensitive."
770
            transparent: format.indexOf("jpeg") == -1 ? "TRUE" : "FALSE",
771
            "TIME": getNodeValue(ts),	          
772
            format: format,
773
            sld:params.sld,
774
            sld_body:params.sld_body,
775
            styles:params.styles
776
          },
777
          layerOptions
778
        );      
779
        // Turn on timestamp listenet
780
          this.model.addListener("timestamp",this.timestampListener,this);	      
781
      }
782
      else {
783
        objRef.oLlayers[layerId]= new OpenLayers.Layer.WMS(title,href,{
784
            layers: layerName,
785
            // "TRUE" in upper case else the context doc boston.xml
786
            // (i.c. the IONIC WMS/WFS) doesn't work.
787
            // Note that this is in line with the WMS standard (OGC 01-068r2),
788
            // section 6.4.1 Parameter Ordering and Case:
789
            // "Parameter names shall not be case sensitive,
790
            //  but parameter values shall be case sensitive."
791
            transparent: format.indexOf("jpeg") == -1 ? "TRUE" : "FALSE",
792
            format: format,
793
            sld:params.sld,
794
            sld_body:params.sld_body,
795
            styles:params.styles
796
          },
797
          layerOptions
798
        );
799
      }
800
    break;
801

    
802
    // WMS-C Layer (Tiled)
803
    case "WMS-C":
804
    case "OGC:WMS-C":
805
      if(!objRef.model.map.baseLayer){
806
        layerOptions.isBaseLayer=true;
807
      }
808
      else {
809
        //TBD what if we have layers with different projections in the context?
810
        layerOptions.reproject=objRef.imageReproject;
811
        layerOptions.isBaseLayer=false;
812
      }
813

    
814
      layerOptions.gutter = objRef.tileGutter;
815
      layerOptions.buffer = objRef.tileBuffer;
816
      layerOptions.tileSize = new OpenLayers.Size(objRef.tileSize, objRef.tileSize);
817
      
818
      var params = new Array();
819
      params = sld2UrlParam(currentStyle);
820
      objRef.oLlayers[layerId]= new OpenLayers.Layer.WMS(title,href,{
821
          layers: layerName,
822
          transparent: format.indexOf("jpeg") == -1 ? "TRUE" : "FALSE",
823
          format: format,
824
          sld:params.sld,
825
          sld_body:params.sld_body,
826
          styles:params.styles
827
        },
828
        layerOptions
829
      );
830
      objRef.model.map.fractionalZoom = false;
831
    break;
832

    
833
    // WFS Layer
834
    case "WFS":
835
    case "wfs":
836
    case "OGC:WFS":
837
      style = sld2OlStyle(currentStyle);
838
      if(style){
839
        layerOptions.styleMap=new OpenLayers.StyleMap(style);
840
      }
841
      else{
842
        layerOptions.style=objRef.getWebSafeStyle(objRef, 2*i+1);
843
      }
844
      layerOptions.featureClass=OpenLayers.Feature.WFS;
845

    
846
      objRef.oLlayers[layerId]= new OpenLayers.Layer.WFS(
847
        title,
848
        href,{
849
          typename: layerId,
850
          maxfeatures: 1000},
851
          layerOptions
852
        );
853
    break;
854

    
855
    // GML Layer
856
    case "gml":
857
    case "OGC:GML":
858
      style = sld2OlStyle(currentStyle);
859
      if(style){
860
        layerOptions.styleMap=new OpenLayers.StyleMap(style);
861
      }
862
      else{
863
        layerOptions.style=objRef.getWebSafeStyle(objRef, 2*i+1);
864
      }
865
      objRef.oLlayers[layerId] = new OpenLayers.Layer.GML(title,href,layerOptions);
866

    
867
    break;
868

    
869
     // KML Layer
870
    case "KML":
871
    case "kml":
872
      objRef.oLlayers[layerId]= new OpenLayers.Layer.GML(
873
        title,
874
        href,{
875
          format: OpenLayers.Format.KML
876
          }
877
        );
878
    break;
879
    
880
  // Currently the following layertypes are only supported in a OwsContext doc as a BaseLayer
881
  // for more information see http://docs.codehaus.org/display/MAP/Using+Google-layers
882
   /* case "GMAP":
883
    case "Google":
884
      //the empty baseLayer has to be destroyed when you want to use google
885
      objRef.model.map.baseLayer.destroy();
886
      layerOptions.maxExtent=new OpenLayers.Bounds("-20037508", "-20037508", "20037508", "20037508.34");
887
       objRef.oLlayers[layerId] = new OpenLayers.Layer.Google( "Google Satellite" , {type: G_HYBRID_MAP, maxZoomLevel:18, sphericalMercator: true }, layerOptions );
888
    break;
889

    
890
    case "YMAP":
891
    case "Yahoo":
892
      // <script src="http://api.maps.yahoo.com/ajaxymap?v=3.0&appid=euzuro-openlayers"></script>
893
      layerOptions.isBaseLayer=true;
894
      objRef.oLlayers[layerId] = new OpenLayers.Layer.Yahoo( "Yahoo");
895
    break;
896

    
897
    case "VE":
898
    case "Microsoft":
899
      //<script src='http://dev.virtualearth.net/mapcontrol/v3/mapcontrol.js'></script>
900
      layerOptions.isBaseLayer=true;
901
      objRef.oLlayers[layerId] = new OpenLayers.Layer.VirtualEarth( "VE",{minZoomLevel: 0, maxZoomLevel: 18,type: VEMapStyle.Hybrid});
902
    break;
903

    
904
    case "MultiMap":
905
      //<script type="text/javascript" src="http://clients.multimap.com/API/maps/1.1/metacarta_04"></script>
906
      layerOptions.isBaseLayer=true;
907
      objRef.oLlayers[layerId] = new OpenLayers.Layer.MultiMap( "MultiMap");
908
    break;*/
909
    default:
910
      alert(mbGetMessage("layerTypeNotSupported", service));
911
  }
912
  if(opacity && objRef.oLlayers[layerId]){
913
    objRef.oLlayers[layerId].setOpacity(opacity);
914
  }
915
  
916
  objRef.oLlayers[layerId].events.register('loadstart', objRef, objRef.increaseLoadingLayers);
917
  objRef.oLlayers[layerId].events.register('loadend', objRef, objRef.decreaseLoadingLayers);
918
  
919
  // Here the OL layer gets added to the OL map
920
  objRef.model.map.addLayer(objRef.oLlayers[layerId]);
921
}
922

    
923
/**
924
 * gets an OpenLayers vector style with web safe colors.
925
 * @param objRef reference to this object
926
 * @param colorNumber number of a color from which to generate websafe color
927
 * @return {OpenLayers.Style} style for OpenLayers vector rendering
928
 */
929
MapPaneOL.prototype.getWebSafeStyle = function(objRef, colorNumber) {
930
  colors=new Array("00","33","66","99","CC","FF");
931
  colorNumber=(colorNumber)?colorNumber:0;
932
  colorNumber=(colorNumber<0)?0:colorNumber;
933
  colorNumber=(colorNumber>215)?215:colorNumber;
934
  i=parseInt(colorNumber/36);
935
  j=parseInt((colorNumber-i*36)/6);
936
  k=parseInt((colorNumber-i*36-j*6));
937
  var color="#"+colors[i]+colors[j]+colors[k];
938
  var defaultStyle = {
939
            fillColor: "#808080",
940
            fillOpacity: 1,
941
            strokeColor: "#000000",
942
            strokeOpacity: 1,
943
            strokeWidth: 1,
944
            pointRadius: 6};
945
  var style=OpenLayers.Util.extend(defaultStyle,OpenLayers.Feature.Vector.style["default"]);
946
  style.fillColor = color;
947
  style.strokeColor = color;
948
  style.map = objRef.model.map;
949
  return style;
950
}
951

    
952
/**
953
   * Called for refreshing one layer.
954
   * @param objRef This object.
955
   * @param layerId  The id of the layer that was toggled.
956
   */
957
MapPaneOL.prototype.refreshLayer = function(objRef, layerId , newParams){
958
  newParams['version'] = Math.random(); //necessary for see change in certain case
959
  objRef.getLayer(objRef,layerId).mergeNewParams(newParams);
960
}
961
  
962
  /**
963
   * Called when the map timestamp is changed so set the layer visiblity.
964
   * @param objRef This object.
965
   * @param timestampIndex  The array index for the layer to be displayed. 
966
   */
967
MapPaneOL.prototype.timestampListener=function(objRef, timestampIndex){
968
  if (window.movieLoop.frameIsLoading == true) {
969
    return;
970
  }
971
  var layerId = objRef.model.timestampList.getAttribute("layerId");
972
  var ts = objRef.model.timestampList.childNodes[timestampIndex];
973

    
974
  if (layerId && ts) {				
975
    var curLayer = objRef.oLlayers[layerId]; //TBD: please check if this still works now we've moved to layerId
976
    if (!curLayer.grid) {
977
      return;
978
    }
979
    div = curLayer.grid[0][0].imgDiv;
980
    // Perform URL substitution via regexps
981
    var oldImageUrl = div.src || div.firstChild.src;
982
    var newImageUrl = oldImageUrl.replace(/TIME\=.*?\&/,'TIME=' + getNodeValue(ts) + '&');
983
    if (oldImageUrl == newImageUrl) {
984
      return;
985
    }
986

    
987
    function imageLoaded() {
988
      window.movieLoop.frameIsLoading = false;
989
      if(element.removeEventListener) { // Standard
990
        element.removeEventListener("load", imageLoaded, false);
991
      } else if(element.detachEvent) { // IE
992
        element.detachEvent('onload', imageLoaded);
993
      }
994
    }
995

    
996
    window.movieLoop.frameIsLoading = true;
997
    var element = div.nodeName.toUpperCase() == "IMG" ? div : div.firstChild;
998
    if(element.addEventListener) { // Standard
999
      element.addEventListener("load", imageLoaded, false);
1000
    } else if(element.attachEvent) { // IE
1001
      element.attachEvent('onload', imageLoaded);
1002
    }
1003
    if (objRef.IE6) {
1004
      OpenLayers.Util.modifyAlphaImageDiv(div,
1005
            null, null, null, newImageUrl);
1006
    } else {
1007
      element.src = newImageUrl;
1008
    }
1009
  }
1010
      
1011
}
(78-78/145)