/*---------------- FILE HEADER --------------------------------------- This file is part of Geoide. Copyright (C) 2005-2006 by: IDgis B.V. http://www.idgis.nl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Herman Assink IDgis bv P.O. Box 15 7450 AA Holten The Netherlands E-Mail: herman.assink@idgis.nl * @version 1.4.0 * @author IDgis team * ------------------------------------------------------------------------*/ import nl.idgis.giclient.util.ArrayTools; import nl.idgis.giclient.filterencoding.ComplexFilter; import nl.idgis.giclient.filterencoding.OperationDefines; import nl.idgis.giclient.filterencoding.SpatialOperation; import nl.idgis.giclient.geoma.Envelope; import nl.idgis.giclient.geoma.Geometry; import nl.idgis.giclient.geoma.GMLFactory; import nl.idgis.giclient.geoma.NullGeometry; import nl.idgis.giclient.gis.Column; import nl.idgis.giclient.gis.Feature; import nl.idgis.giclient.gis.LayerEventDispatcher; import nl.idgis.giclient.gis.LayerSession; import nl.idgis.giclient.io.XMLResponse; import nl.idgis.giclient.io.XMLResponseListener; import nl.idgis.giclient.io.XMLServer; import nl.idgis.giclient.util.XMLTools; import nl.idgis.giclient.webserviceconnector.wfsconnector.WFSConnector; import nl.idgis.giclient.webserviceconnector.wfsconnector.FeatureType; import nl.idgis.giclient.gis.AnimationLayer; import nl.idgis.giclient.util.SynchListener; import nl.idgis.giclient.synch.SynchSocket; import nl.idgis.giclient.event.StateEventDispatcher; import nl.idgis.giclient.event.StateEventListener; import nl.idgis.giclient.event.StateEvent; import nl.idgis.giclient.event.ChangeEvent; import nl.idgis.giclient.webserviceconnector.MapConnector; import nl.idgis.giclient.webserviceconnector.giconnector.GIConnector; import nl.idgis.giclient.framework.FrameWork; import nl.idgis.giclient.Ruler; import nl.idgis.giclient.gis.CentreScale; class nl.idgis.giclient.gis.Layer { static function getFeatureIDs(features:Array):Array { var featureIDs:Array = new Array(); for (var i:Number = 0; i < features.length; i++) { featureIDs.push(Feature(features[i]).getID()); } return featureIDs; } private var available:Boolean = true; private var name:String = ""; private var title:String = ""; private var metaUrl:String = ""; private var visible:Boolean = true; private var expanded:Boolean = true; private var currentScale:Number = -1; private var superLayer:Layer = null; private var editable:Boolean = false; private var scales:Array = null; private var extentZoom:Boolean; private var attrInfoFeatureIDs:Array = null; private var selectedAttrInfoFeatureIDs:Array = null; private var layers:Array = null; private var noLegendLayer:Boolean = false; private var srs:String = ""; private var extentZoomable:Boolean = false; private var extentZoomableCalculated:Boolean = false; var layerEventDispatcher:LayerEventDispatcher = null; var stateEventDispatcher:StateEventDispatcher = null; function Layer(name:String, title:String, visible:Boolean, expanded:Boolean, scales:Array, superLayer:Layer, editable:Boolean, extentZoom:Boolean) { this.name = name; this.title = title; this.visible = visible; this.expanded = expanded; this.superLayer = superLayer; this.editable = editable; this.scales = scales; this.extentZoom = extentZoom; attrInfoFeatureIDs = new Array(); selectedAttrInfoFeatureIDs = new Array(); layerEventDispatcher = new LayerEventDispatcher(); stateEventDispatcher = new StateEventDispatcher(); } function getLongName():String { if(superLayer != null) return superLayer.getLongName() + ":" + name; else return name; } function getName():String { return name; } function getTitle():String { return title; } function setVisible(visible:Boolean):Void { if (this.visible != visible) { this.visible = visible; layerEventDispatcher.changeLayerVisible(this); } } function isVisible():Boolean { //trace(this.getLongName() + ": " + visible); return visible; } function isEditable():Boolean { return editable; } function isSelectable():Boolean { return false; } function isExtentZoomable():Boolean { if(!extentZoomableCalculated) { extentZoomable = calcIsExtentZoomable(); extentZoomableCalculated = true; } return extentZoomable; } private function calcIsExtentZoomable():Boolean { // Zooming to an empty group layer is not possible if(getMapConnector() == null && (layers == null || layers.length == 0)) { return false; } var envelope:Envelope = this.getEnvelope(); var centreScale:CentreScale = envelope.toCentreScale(Stage.width, Stage.height, Ruler(_root["frameWork"]["ruler"]).getGIS().getCoordPixFactor()); var envelopeScale = centreScale.getScale(); var zoomable:Boolean = envelopeScale < this.getMaxScale(); if(zoomable) { if(getMapConnector() != null) { return true; } else { // A group layer is only 'extent zoomable' if at least one of its sublayers is. for(var i:Number = 0; i < layers.length; i++) { if(Layer(layers[i]).isExtentZoomable()) { return true; } } return false; } } return false; } function areSuperLayersVisible():Boolean { var currentSuperLayer:Layer = superLayer; while (currentSuperLayer != null) { if (!currentSuperLayer.isVisible()) { return false; } currentSuperLayer = currentSuperLayer.getSuperLayer(); } return true; } function setExpanded(expanded:Boolean):Void { if (this.expanded != expanded) { this.expanded = expanded; this.fireChangeLayerExpanded(); } } private function fireChangeLayerExpanded() { layerEventDispatcher.changeLayerExpanded(); } function isExpanded():Boolean { var superExpanded:Boolean = true; if (this.getSuperLayer() != null) { superExpanded = this.getSuperLayer().isExpanded(); } if (!superExpanded) { return false; } else { return expanded; } } function getScales():Array { return scales; } function getMinScale():Number { var layerScales:Array = getScales(); if(layerScales.length == 0 && layers.length != 0) { var minScale:Number = Number.MAX_VALUE; for(var i:Number = 0; i < layers.length; i++) { var currentMinScale:Number = layers[i].getMinScale(); if(currentMinScale < minScale) minScale = currentMinScale; } return minScale; } return layerScales[0]; } function getMaxScale():Number { var layerScales:Array = getScales(); if(layerScales.length == 0 && layers.length != 0) { var maxScale:Number = 0; for(var i:Number = 0; i < layers.length; i++) { var currentMaxScale:Number = layers[i].getMaxScale(); if(currentMaxScale > maxScale) maxScale = currentMaxScale; } return maxScale; } return layerScales[layerScales.length - 1]; } function setCurrentScale(currentScale:Number):Void { var layerScales:Array = getScales(); var previousScale = this.currentScale; var forLoopDidIt:Boolean = false; for (var i:Number = layerScales.length - 1; i >= 0; i--) { if (currentScale >= layerScales[i]) { this.currentScale = layerScales[i]; forLoopDidIt = true; } } if (!forLoopDidIt) { this.currentScale = 0; } if (this.currentScale != previousScale) { stateEventDispatcher.dispatchEvent(new ChangeEvent(this, "Layer", "currentScale", previousScale)); } } function getCurrentScale():Number { return currentScale; } function getSuperLayer():Layer { return superLayer; } function getSuperLayers():Array { var superLayer:Layer = this.superLayer; var superLayers:Array = new Array(); while (superLayer != null) { superLayers.push(superLayer); superLayer = superLayer.getSuperLayer(); } return superLayers; } function setLayers(layers:Array) { this.layers = layers; } function getLayers():Array { return layers; } function getAllLayers():Array { var allLayers:Array = new Array(this); for (var i:Number = 0; i < layers.length; i++) { allLayers = allLayers.concat(Layer(layers[i]).getAllLayers()); } return allLayers; } function setNoLegendLayer(noLegendLayer:Boolean):Void { this.noLegendLayer = noLegendLayer; } function getNoLegendLayer():Boolean { return noLegendLayer; } function refresh():Void { layerEventDispatcher.refresh(this); } function setSelectedAttrInfoFeatureIDs(featureIDs:Array):Void { var toBeAddedFeatureIDs:Array = ArrayTools.getLeftOver(featureIDs, attrInfoFeatureIDs); var broadCastEvent:Boolean = false; if (toBeAddedFeatureIDs.length > 0) { attrInfoFeatureIDs = ArrayTools.concat(attrInfoFeatureIDs, toBeAddedFeatureIDs); broadCastEvent = true; } if (!ArrayTools.equals(featureIDs, selectedAttrInfoFeatureIDs)) { selectedAttrInfoFeatureIDs = featureIDs; broadCastEvent = true; } if (broadCastEvent) { layerEventDispatcher.selectAttrInfoFeatures(this); } } function getSelectedAttrInfoFeatureIDs():Array { return selectedAttrInfoFeatureIDs; } function getAttrInfoFeatureIDs():Array { return attrInfoFeatureIDs; } function clearAttrInfoFeaturesIDs():Void { attrInfoFeatureIDs = new Array(); selectedAttrInfoFeatureIDs = new Array(); // really changed? layerEventDispatcher.selectAttrInfoFeatures(this); } function loadFeatureEnvelopes(features:Array, synchListener:SynchListener):Void { (Feature(features[0])).loadEnvelope(synchListener); } function onFeatureSetEnvelope(feature:Feature, synchListener:SynchListener):Void { synchListener.onSynch(this, "ENVELOPES"); } function getLevel():Number { var currentLayer:Layer = this; var i:Number = 0; for (i = 0; currentLayer.getSuperLayer() != null; i++) { currentLayer = currentLayer.getSuperLayer(); } return i; } function moveLayerBackward(layer:Layer, end:Boolean):Void { var i:Number = 0; while (layers[i] != layer) { i++; } if (i < layers.length - 1) { if (end) { layers.splice(i, 1); layers.push(layer); } else { layers[i] = layers[i + 1]; layers[i + 1] = layer; } } } function moveLayerFrontward(layer:Layer, end:Boolean):Void { var i:Number = 0; while (layers[i] != layer) { i++; } if ((layers.length > 1) && (i > 0)) { if (end) { layers.splice(i, 1); layers.unshift(layer); } else { layers[i] = layers[i - 1]; layers[i - 1] = layer; } } } function moveLayerTo(fromLayer:Layer, toLayer:Layer):Void { //only exchanges now if ((fromLayer.getSuperLayer() == this) && (toLayer.getSuperLayer() == this)) { if (fromLayer != toLayer) { var layerFromIndex:Number = 9999; // nonexistent for (var i = 0; i < layers.length; i++) { if (layers[i] == fromLayer) { layerFromIndex = i; } } var layerToIndex:Number = 9999; //nonexistent for (var i = 0; i < layers.length; i++) { if (layers[i] == toLayer) { layerToIndex = i; } } if ((layerFromIndex == 9999) || (layerToIndex == 9999)) { //state("Given layer does not exist.", true); return; } layers[layerToIndex] = fromLayer; layers[layerFromIndex] = toLayer; } else { //returnvalue } } else { //returnvalue } } function getTimeRangeEnd():Date { if (layers != null) { var maxEndTime:Date = new Date(Number.MIN_VALUE); for (var i = 0; i < layers.length; i++ ) { var layer:Layer = Layer(layers[i]); var timeRangeEnd:Date = layer.getTimeRangeEnd(); if (timeRangeEnd != null && layer.isVisible() && layer.areSuperLayersVisible()) { if (timeRangeEnd > maxEndTime) { maxEndTime = timeRangeEnd; } } } return maxEndTime; } return null; } function getTimeRangeStart():Date { if (layers != null) { var minStartTime:Date = new Date(Number.MAX_VALUE); for (var i = 0; i < layers.length; i++ ) { var layer:Layer = Layer(layers[i]); var timeRangeStart:Date = layer.getTimeRangeStart(); if (timeRangeStart != null && layer.isVisible() && layer.areSuperLayersVisible()) { if (timeRangeStart < minStartTime) { minStartTime = timeRangeStart; } } } return minStartTime; } return null; } function addEventListener(stateEventListener:StateEventListener, sourceClassName:String, actionType:Number, propertyName:String):Void { if (sourceClassName + "_" + actionType + "_" + propertyName != "Layer_" + StateEvent.CHANGE + "_currentScale") { // EXCEPTION return; } stateEventDispatcher.addEventListener(stateEventListener, sourceClassName, actionType, propertyName); } function removeEventListener(stateEventListener:StateEventListener, sourceClassName:String, actionType:Number, propertyName:String):Void { if (sourceClassName + "_" + actionType + "_" + propertyName != "Layer_" + StateEvent.CHANGE + "_currentScale") { // EXCEPTION return; } stateEventDispatcher.removeEventListener(stateEventListener, sourceClassName, actionType, propertyName); } function getMapConnector():MapConnector { return null; } function getType():String { return ""; } function isAvailable():Boolean { return available; } function setAvailable(available:Boolean) { this.available = available; } function getEnvelope():Envelope { var subEnvelope:Envelope = Layer(layers[0]).getEnvelope(); var minX:Number = subEnvelope.getMinX(); var maxX:Number = subEnvelope.getMaxX(); var minY:Number = subEnvelope.getMinY(); var maxY:Number = subEnvelope.getMaxY(); for(var i:Number = 1; i < layers.length; i++) { var currentLayer:Layer = Layer(layers[i]); var currentEnvelope:Envelope = currentLayer.getEnvelope(); if(currentEnvelope.getMinX() < minX) { minX = currentEnvelope.getMinX(); } if(currentEnvelope.getMinY() < minY) { minY = currentEnvelope.getMinY(); } if(currentEnvelope.getMaxX() > maxX) { maxX = currentEnvelope.getMaxX(); } if(currentEnvelope.getMaxY() > maxY) { maxY = currentEnvelope.getMaxY(); } } return new Envelope(subEnvelope.getSRS(), minX, minY, maxX, maxY); } function setSRS(srs:String):Void { this.srs = srs; var mapConnector:MapConnector = this.getMapConnector(); if(mapConnector != null) setAvailable(mapConnector.isSRSSupported(this, srs)); if(layers != null) { for(var i:Number = 0; i < layers.length; i++) Layer(layers[i]).setSRS(srs); } } function getSRS() : String { return srs; } function getMetaUrl():String { return metaUrl; } function setMetaUrl(url:String):Void { metaUrl = url; } }