/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for * full list of contributors). Published under the Clear BSD license. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the * full text of the license. */ /** * @requires OpenLayers/Util.js * @requires OpenLayers/Feature/Vector.js */ /** * Class: OpenLayers.Style * This class represents a UserStyle obtained * from a SLD, containing styling rules. */ OpenLayers.Style = OpenLayers.Class({ /** * Property: id * {String} A unique id for this session. */ id: null, /** * APIProperty: name * {String} */ name: null, /** * Property: title * {String} Title of this style (set if included in SLD) */ title: null, /** * Property: description * {String} Description of this style (set if abstract is included in SLD) */ description: null, /** * APIProperty: layerName * {} name of the layer that this style belongs to, usually * according to the NamedLayer attribute of an SLD document. */ layerName: null, /** * APIProperty: isDefault * {Boolean} */ isDefault: false, /** * Property: rules * {Array()} */ rules: null, /** * Property: context * {Object} An optional object with properties that symbolizers' property * values should be evaluated against. If no context is specified, * feature.attributes will be used */ context: null, /** * Property: defaultStyle * {Object} hash of style properties to use as default for merging * rule-based style symbolizers onto. If no rules are defined, * createSymbolizer will return this style. If is set to * true, the defaultStyle will only be taken into account if there are * rules defined. */ defaultStyle: null, /** * Property: defaultsPerSymbolizer * {Boolean} If set to true, the will extend the symbolizer * of every rule. Properties of the will also be used to set * missing symbolizer properties if the symbolizer has stroke, fill or * graphic set to true. Default is false. */ defaultsPerSymbolizer: false, /** * Property: propertyStyles * {Hash of Boolean} cache of style properties that need to be parsed for * propertyNames. Property names are keys, values won't be used. */ propertyStyles: null, /** * Constructor: OpenLayers.Style * Creates a UserStyle. * * Parameters: * style - {Object} Optional hash of style properties that will be * used as default style for this style object. This style * applies if no rules are specified. Symbolizers defined in * rules will extend this default style. * options - {Object} An optional object with properties to set on the * style. * * Valid options: * rules - {Array()} List of rules to be added to the * style. * * Return: * {} */ initialize: function(style, options) { OpenLayers.Util.extend(this, options); this.rules = []; if(options && options.rules) { this.addRules(options.rules); } // use the default style from OpenLayers.Feature.Vector if no style // was given in the constructor this.setDefaultStyle(style || OpenLayers.Feature.Vector.style["default"]); this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_"); }, /** * APIMethod: destroy * nullify references to prevent circular references and memory leaks */ destroy: function() { for (var i=0, len=this.rules.length; i} feature to evaluate rules for * * Returns: * {Object} symbolizer hash */ createSymbolizer: function(feature) { var style = this.defaultsPerSymbolizer ? {} : this.createLiterals( OpenLayers.Util.extend({}, this.defaultStyle), feature); var rules = this.rules; var rule, context; var elseRules = []; var appliedRules = false; for(var i=0, len=rules.length; i 0) { appliedRules = true; for(var i=0, len=elseRules.length; i 0 && appliedRules == false) { style.display = "none"; } return style; }, /** * Method: applySymbolizer * * Parameters: * rule - {OpenLayers.Rule} * style - {Object} * feature - {} * * Returns: * {Object} A style with new symbolizer applied. */ applySymbolizer: function(rule, style, feature) { var symbolizerPrefix = feature.geometry ? this.getSymbolizerPrefix(feature.geometry) : OpenLayers.Style.SYMBOLIZER_PREFIXES[0]; var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer; if(this.defaultsPerSymbolizer === true) { var defaults = this.defaultStyle; OpenLayers.Util.applyDefaults(symbolizer, { pointRadius: defaults.pointRadius }); if(symbolizer.stroke === true || symbolizer.graphic === true) { OpenLayers.Util.applyDefaults(symbolizer, { strokeWidth: defaults.strokeWidth, strokeColor: defaults.strokeColor, strokeOpacity: defaults.strokeOpacity, strokeDashstyle: defaults.strokeDashstyle, strokeLinecap: defaults.strokeLinecap }); } if(symbolizer.fill === true || symbolizer.graphic === true) { OpenLayers.Util.applyDefaults(symbolizer, { fillColor: defaults.fillColor, fillOpacity: defaults.fillOpacity }); } if(symbolizer.graphic === true) { OpenLayers.Util.applyDefaults(symbolizer, { pointRadius: this.defaultStyle.pointRadius, externalGraphic: this.defaultStyle.externalGraphic, graphicName: this.defaultStyle.graphicName, graphicOpacity: this.defaultStyle.graphicOpacity, graphicWidth: this.defaultStyle.graphicWidth, graphicHeight: this.defaultStyle.graphicHeight, graphicXOffset: this.defaultStyle.graphicXOffset, graphicYOffset: this.defaultStyle.graphicYOffset }); } } // merge the style with the current style return this.createLiterals( OpenLayers.Util.extend(style, symbolizer), feature); }, /** * Method: createLiterals * creates literals for all style properties that have an entry in * . * * Parameters: * style - {Object} style to create literals for. Will be modified * inline. * feature - {Object} * * Returns: * {Object} the modified style */ createLiterals: function(style, feature) { var context = OpenLayers.Util.extend({}, feature.attributes || feature.data); OpenLayers.Util.extend(context, this.context); for (var i in this.propertyStyles) { style[i] = OpenLayers.Style.createLiteral(style[i], context, feature, i); } return style; }, /** * Method: findPropertyStyles * Looks into all rules for this style and the defaultStyle to collect * all the style hash property names containing ${...} strings that have * to be replaced using the createLiteral method before returning them. * * Returns: * {Object} hash of property names that need createLiteral parsing. The * name of the property is the key, and the value is true; */ findPropertyStyles: function() { var propertyStyles = {}; // check the default style var style = this.defaultStyle; this.addPropertyStyles(propertyStyles, style); // walk through all rules to check for properties in their symbolizer var rules = this.rules; var symbolizer, value; for (var i=0, len=rules.length; i)} */ addRules: function(rules) { Array.prototype.push.apply(this.rules, rules); this.propertyStyles = this.findPropertyStyles(); }, /** * APIMethod: setDefaultStyle * Sets the default style for this style object. * * Parameters: * style - {Object} Hash of style properties */ setDefaultStyle: function(style) { this.defaultStyle = style; this.propertyStyles = this.findPropertyStyles(); }, /** * Method: getSymbolizerPrefix * Returns the correct symbolizer prefix according to the * geometry type of the passed geometry * * Parameters: * geometry {} * * Returns: * {String} key of the according symbolizer */ getSymbolizerPrefix: function(geometry) { var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES; for (var i=0, len=prefixes.length; i} Clone of this style. */ clone: function() { var options = OpenLayers.Util.extend({}, this); // clone rules if(this.rules) { options.rules = []; for(var i=0, len=this.rules.length; i} optional feature to pass to * for evaluating functions in the * context. * property - {String} optional, name of the property for which the literal is * being created for evaluating functions in the context. * * Returns: * {String} the parsed value. In the example of the value parameter above, the * result would be "foo valueOfBar", assuming that the passed feature has an * attribute named "bar" with the value "valueOfBar". */ OpenLayers.Style.createLiteral = function(value, context, feature, property) { if (typeof value == "string" && value.indexOf("${") != -1) { value = OpenLayers.String.format(value, context, [feature, property]); value = (isNaN(value) || !value) ? value : parseFloat(value); } return value; }; /** * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES * {Array} prefixes of the sld symbolizers. These are the * same as the main geometry types */ OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text', 'Raster'];