1 /** 2 * @fileOverview 3 * Copyright (c) 2013 Regione Autonoma della Sardegna 4 * Published under the GPL license.<br> 5 * See <a href="https://sardegnageoportale.it/webgis/license.txt">https://sardegnageoportale.it/webgis/license.txt</a> 6 * for the full text of the license. 7 * @version 0.1 8 */ 9 10 /** 11 * @require plugins/LayerTree.js 12 * @require GeoExt/plugins/TreeNodeComponent.js 13 * @require GeoExt/widgets/WMSLegend.js 14 * @require GeoExt/widgets/VectorLegend.js 15 */ 16 17 /** 18 * @namespace framework.plugins 19 */ 20 Ext.namespace("framework.plugins"); 21 22 /** @example 23 * If you want to change the vendor-specific legend_options parameter that 24 * is sent to the WMS for GetLegendGraphic you can use ``baseAttrs`` on the 25 * ``loader`` config: 26 * 27 * .. code-block:: javascript 28 * 29 * var layerManager = new gxp.plugins.LayerManager({ 30 * loader: { 31 * baseAttrs: { 32 * baseParams: { 33 * legend_options: "fontAntiAliasing:true;fontSize:11;fontName:Arial;fontColor:#FFFFFF" 34 * } 35 * } 36 * } 37 * }); 38 * 39 */ 40 41 /** 42 * Plugin for adding a tree of layers with their legend to a 'gxp.Viewer'. 43 * Also provides a context menu on layer nodes. 44 * @name_ LayerManager 45 * @class Plugin for adding a tree of layers with their legend 46 * @constructor 47 * @extends <a target="_blank" href="http://gxp.opengeo.org/master/doc/lib/plugins/LayerTree.html">gxp.plugins.LayerTree</a> 48 */ 49 framework.plugins.LayerManager = Ext.extend(gxp.plugins.LayerTree, 50 /** 51 * @lends framework.plugins.LayerManager.prototype 52 */ 53 { 54 /** 55 * gxp_layermanager plugin type. 56 * @public 57 * @type String 58 */ 59 ptype: "framework_layermanager", 60 61 /** 62 * Text for baselayer node of layer tree (i18n). 63 * @public 64 * @type String 65 */ 66 baseNodeText: "Base Maps", 67 68 /** 69 * 'Object' The groups to show in the layer tree. Keys are group names, 70 * and values are either group titles or an object with 'title' and 71 * ``exclusive`` properties. 'exclusive' means that nodes will have 72 * radio buttons instead of checkboxes, so only one layer of the group can 73 * be active at a time. Optional, the default is 74 * 75 * .. code-block:: javascript 76 * 77 * groups: { 78 * "default": "Overlays", // title can be overridden with overlayNodeText 79 * "background": { 80 * title: "Base Maps", // can be overridden with baseNodeText 81 * exclusive: true 82 * } 83 * } 84 */ 85 86 /** 87 * output configuration 88 * @private 89 */ 90 createOutputConfig: function() { 91 this.tree = this.createPreOutputConfig(this, arguments); 92 var self = this; 93 this.target.layer_group = this.groups; 94 self.target.addEvents('nodeselectionchange'); 95 self.tree.selModel.on({ 96 selectionchange: function(obj, node, last) { 97 self.target.fireEvent('nodeselectionchange',obj.tree.root, node, last); 98 } 99 }); 100 Ext.applyIf(this.tree, Ext.apply({ 101 cls: "gxp-layermanager-tree", 102 lines: false, 103 useArrows: false, 104 plugins: [{ 105 ptype: "gx_treenodecomponent" 106 }] 107 }, this.treeConfig)); 108 return this.tree; 109 }, 110 111 /** 112 * layer node configuration 113 * @private 114 */ 115 configureLayerNode: function(loader, attr) { 116 framework.plugins.LayerManager.superclass.configureLayerNode.apply(this, arguments); 117 var legendXType; 118 // add a WMS legend to each node created 119 if (OpenLayers.Layer.WMS && attr.layer instanceof OpenLayers.Layer.WMS) { 120 legendXType = "gx_wmslegend"; 121 } else if (OpenLayers.Layer.Vector && attr.layer instanceof OpenLayers.Layer.Vector) { 122 legendXType = "gx_vectorlegend"; 123 } 124 if (legendXType) { 125 var baseParams; 126 var clsParam; //hide legend in layers inactive on default 127 if (loader && loader.baseAttrs && loader.baseAttrs.baseParams) { 128 baseParams = loader.baseAttrs.baseParams; 129 } 130 131 //hide legend in layers inactive on default 132 if (this.target.mapPanel.layers.getByLayer(attr.layer).data.layer.options.visibility && 133 this.target.mapPanel.layers.getByLayer(attr.layer).data.layer.minScale >= this.target.mapPanel.layers.getByLayer(attr.layer).data.layer.scales[this.target.mapPanel.zoom]) 134 clsParam = "legend"; 135 else 136 clsParam = "legend x-hide-display"; 137 138 Ext.apply(attr, { 139 component: { 140 xtype: legendXType, 141 // TODO these baseParams were only tested with GeoServer, 142 // so maybe they should be configurable - and they are 143 // only relevant for gx_wmslegend. 144 hidden: !attr.layer.getVisibility(), 145 baseParams: Ext.apply({ 146 transparent: true 147 // format: "image/png", //da disattivare per ArcGIS online... forzato per i layer gruppi di GeoServer 148 // legend_options: "fontAntiAliasing:true;fontSize:11;fontName:Arial;forceLabels:on;" 149 }, baseParams), 150 layerRecord: this.target.mapPanel.layers.getByLayer(attr.layer), 151 showTitle: false, 152 // custom class for css positioning 153 // see tree-legend.html 154 cls: clsParam 155 } 156 }); 157 158 } 159 }, 160 161 /** 162 * @private 163 * @returns: 'Object' Configuration object for an Ext.tree.TreePanel 164 */ 165 createPreOutputConfig: function() { 166 var treeRoot = new Ext.tree.TreeNode({ 167 text: this.rootNodeText, 168 expanded: true, 169 isTarget: false, 170 allowDrop: true 171 }); 172 173 var baseAttrs; 174 if (this.initialConfig.loader && this.initialConfig.loader.baseAttrs) { 175 baseAttrs = this.initialConfig.loader.baseAttrs; 176 } 177 178 var defaultGroup = this.defaultGroup, 179 plugin = this, 180 groupConfig, 181 exclusive; 182 for (var group in this.groups) { 183 groupConfig = typeof this.groups[group] == "string" ? 184 {title: this.groups[group]} : this.groups[group]; 185 exclusive = groupConfig.exclusive; 186 var newNode = this.createNode(plugin,group,groupConfig,defaultGroup,exclusive,baseAttrs); 187 newNode.addVisibilityEventHandlers(); 188 treeRoot.appendChild(newNode); 189 } 190 191 return { 192 xtype: "treepanel", 193 root: treeRoot, 194 rootVisible: false, 195 shortTitle: this.shortTitle, 196 border: false, 197 enableDD: true, 198 selModel: new Ext.tree.DefaultSelectionModel({ 199 listeners: { 200 beforeselect: this.handleBeforeSelect, 201 scope: this 202 } 203 }), 204 listeners: { 205 contextmenu: this.handleTreeContextMenu, 206 beforemovenode: this.handleBeforeMoveNode, 207 scope: this 208 }, 209 contextMenu: new Ext.menu.Menu({ 210 items: [] 211 }) 212 }; 213 }, 214 215 /** create group node 216 * @public 217 * @param {plugin} 'framework.plugins.LayerManager' object self 218 * @param {group} 'String' group name 219 * @param {groupConfig} 'object' group object 220 * @param {defaultGroup} 'String' default group name 221 * @param {exclusive} 'boolean' exclusive content (one layer on for time) 222 * @param {baseAttrs} 'object' configuration attrubutes 223 * @returns {framework.plugins.RASGroupNode} group node 224 */ 225 createNode: function(plugin,group,groupConfig,defaultGroup,exclusive,baseAttrs){ 226 return new framework.plugins.RASGroupNode(Ext.apply({ 227 text: groupConfig.title, 228 iconCls: "gxp-folder", 229 expanded: true, 230 groupKey: group, 231 group: group == defaultGroup ? undefined : group, 232 loader: new GeoExt.tree.LayerLoader({ 233 baseAttrs: exclusive ? 234 Ext.apply({checkedGroup: Ext.isString(exclusive) ? exclusive : group}, baseAttrs) : 235 baseAttrs, 236 store: this.target.mapPanel.layers, 237 filter: (function(group) { 238 return function(record) { 239 return (record.get("group") || defaultGroup) == group && 240 record.getLayer().displayInLayerSwitcher == true; 241 }; 242 })(group), 243 createNode: function(attr) { 244 plugin.configureLayerNode(this, attr); 245 return GeoExt.tree.LayerLoader.prototype.createNode.apply(this, arguments); 246 } 247 }), 248 singleClickExpand: true, 249 allowDrag: true, 250 listeners: { 251 append: function(tree, node) { 252 node.expand(); 253 }, 254 move: function( tree, obj, oldParent, newParent, newIndex ){ 255 var groups = self.group_layer; 256 var value,key; 257 //test 258 // var keysInit = []; 259 // for(var k in groups){ 260 // keysInit.push(k); 261 // } 262 263 for(var child=0;child<oldParent.childNodes.length;child++){ 264 key = oldParent.childNodes[child].attributes.groupKey; 265 value = groups[key]; 266 delete groups[key]; 267 groups[key] = value; 268 } 269 //test 270 // var keys = []; 271 // for(var k in groups){ 272 // keys.push(k); 273 // } 274 275 /** Order layer on map by tree position 276 * @private 277 * @param {node} node with layer to order 278 * @param {parent} father node 279 * @param {index} index node inside parent 280 */ 281 orderLayer = function(node, parent, index) { 282 this._reordering = true; 283 // remove the record and re-insert it at the correct index 284 this.store = obj.loader.store; 285 var record = this.store.getByLayer(node.layer); 286 if(parent instanceof GeoExt.tree.LayerContainer) { 287 parent.loader._reordering = true; 288 this.store.remove(record); 289 var newRecordIndex; 290 if(index > 0) { 291 // find index by neighboring node in the same container 292 var searchIndex = (index === 0) ? index + 1 : index - 1; 293 newRecordIndex = this.store.findBy(function(r) { 294 return parent.childNodes[searchIndex].layer === r.getLayer(); 295 }); 296 index === 0 && newRecordIndex++; 297 } else { 298 // find index by last node of a container above 299 var prev = parent; 300 do { 301 prev = prev.previousSibling; 302 } while (prev && !(prev instanceof GeoExt.tree.LayerContainer && prev.lastChild)); 303 if(prev) { 304 newRecordIndex = this.store.findBy(function(r) { 305 return prev.lastChild.layer === r.getLayer(); 306 }); 307 } else { 308 // find indext by first node of a container below 309 var next = parent; 310 do { 311 next = next.nextSibling; 312 } while (next && !(next instanceof GeoExt.tree.LayerContainer && next.firstChild)); 313 if(next) { 314 newRecordIndex = this.store.findBy(function(r) { 315 return next.firstChild.layer === r.getLayer(); 316 }); 317 } 318 newRecordIndex++; 319 } 320 } 321 if(newRecordIndex !== undefined) { 322 this.store.insert(newRecordIndex, [record]); 323 window.setTimeout(function() { 324 parent.reload(); 325 //oldParent.reload(); 326 }); 327 } else { 328 this.store.insert(oldRecordIndex, [record]); 329 } 330 delete parent.loader._reordering; 331 } 332 delete this._reordering; 333 } 334 //reorder layers on map 335 for(var i=0;i<obj.childNodes.length;i++){ 336 orderLayer(obj.childNodes[i], obj, i); 337 } 338 } 339 } 340 }, groupConfig)); 341 }, 342 343 /** Add a group with given group/group name 344 * @public 345 * @param {group} group object or group name 346 */ 347 addGroup: function(group){ 348 var plugin = this; 349 var groupConfig = typeof group == "string" ? {title: group, checked:false} : group; 350 for(var group_ in this.groups) { 351 objGroup = typeof this.groups[group_] == "string" ? {title: this.groups[group_]} : this.groups[group_]; 352 if(objGroup.title === groupConfig.title){ 353 alert('Gruppo giĆ esistente!'); 354 return; 355 } 356 } 357 var keyGroup = groupConfig.title.replace(/\s/g, "_"); 358 this.groups[keyGroup] = groupConfig; 359 //riordina posizioni groups 360 for(var group_ in this.groups) { 361 objGroup = typeof this.groups[group_] == "string" ? {title: this.groups[group_]} : this.groups[group_]; 362 if(objGroup.title !== groupConfig.title){ 363 var obj = this.groups[group_]; 364 delete this.groups[group_]; 365 this.groups[group_] = obj; 366 } 367 } 368 var exclusive = groupConfig.exclusive; 369 var baseAttrs; 370 if (this.initialConfig.loader && this.initialConfig.loader.baseAttrs) { 371 baseAttrs = this.initialConfig.loader.baseAttrs; 372 } 373 var firstChild = this.tree.root.item(0); 374 var newNode = this.createNode(plugin,keyGroup,groupConfig,this.defaultGroup,exclusive,baseAttrs); 375 newNode.addVisibilityEventHandlers(); 376 this.tree.root.insertBefore(newNode,firstChild); 377 378 }, 379 380 /** private: method[handleBeforeMoveNode] 381 */ 382 handleBeforeMoveNode: function(tree, node, oldParent, newParent, i) { 383 // change the group when moving to a new container 384 if(oldParent !== newParent) { 385 var store = newParent.loader.store; 386 var index = store.findBy(function(r) { 387 return r.getLayer() === node.layer; 388 }); 389 var record = store.getAt(index); 390 record.set("group", newParent.attributes.group); 391 } 392 393 //CONTROLLO LAYER TMS "NON DISPONIBILE 394 Ext.each(this.target.mapPanel.map.layers, function(l){ 395 if (l.layerNT && l.visibility == true) { 396 l.layerNT.display(false); 397 } 398 }); 399 } 400 }); 401 402 Ext.preg(framework.plugins.LayerManager.prototype.ptype, framework.plugins.LayerManager); 403