~mortenoh/+junk/dhis2-detailed-import-export

« back to all changes in this revision

Viewing changes to gis/dhis-gis-geostat/mfbase/openlayers/lib/OpenLayers/Style.js

  • Committer: larshelge at gmail
  • Date: 2009-03-03 16:46:36 UTC
  • Revision ID: larshelge@gmail.com-20090303164636-2sjlrquo7ib1gf7r
Initial check-in

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
 
2
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 
3
  * full text of the license. */
 
4
 
 
5
 
 
6
/**
 
7
 * @requires OpenLayers/Util.js
 
8
 * @requires OpenLayers/Feature/Vector.js
 
9
 */
 
10
 
 
11
/**
 
12
 * Class: OpenLayers.Style
 
13
 * This class represents a UserStyle obtained
 
14
 *     from a SLD, containing styling rules.
 
15
 */
 
16
OpenLayers.Style = OpenLayers.Class({
 
17
 
 
18
    /**
 
19
     * APIProperty: name
 
20
     * {String}
 
21
     */
 
22
    name: null,
 
23
    
 
24
    /**
 
25
     * Property: title
 
26
     * {String} Title of this style (set if included in SLD)
 
27
     */
 
28
    title: null,
 
29
    
 
30
    /**
 
31
     * Property: description
 
32
     * {String} Description of this style (set if abstract is included in SLD)
 
33
     */
 
34
    description: null,
 
35
 
 
36
    /**
 
37
     * APIProperty: layerName
 
38
     * {<String>} name of the layer that this style belongs to, usually
 
39
     * according to the NamedLayer attribute of an SLD document.
 
40
     */
 
41
    layerName: null,
 
42
    
 
43
    /**
 
44
     * APIProperty: isDefault
 
45
     * {Boolean}
 
46
     */
 
47
    isDefault: false,
 
48
     
 
49
    /** 
 
50
     * Property: rules 
 
51
     * {Array(<OpenLayers.Rule>)}
 
52
     */
 
53
    rules: null,
 
54
    
 
55
    /**
 
56
     * Property: context
 
57
     * {Object} An optional object with properties that symbolizers' property
 
58
     * values should be evaluated against. If no context is specified,
 
59
     * feature.attributes will be used
 
60
     */
 
61
    context: null,
 
62
 
 
63
    /**
 
64
     * Property: defaultStyle
 
65
     * {Object} hash of style properties to use as default for merging
 
66
     * rule-based style symbolizers onto. If no rules are defined,
 
67
     * createSymbolizer will return this style.
 
68
     */
 
69
    defaultStyle: null,
 
70
    
 
71
    /**
 
72
     * Property: propertyStyles
 
73
     * {Hash of Boolean} cache of style properties that need to be parsed for
 
74
     * propertyNames. Property names are keys, values won't be used.
 
75
     */
 
76
    propertyStyles: null,
 
77
    
 
78
 
 
79
    /** 
 
80
     * Constructor: OpenLayers.Style
 
81
     * Creates a UserStyle.
 
82
     *
 
83
     * Parameters:
 
84
     * style        - {Object} Optional hash of style properties that will be
 
85
     *                used as default style for this style object. This style
 
86
     *                applies if no rules are specified. Symbolizers defined in
 
87
     *                rules will extend this default style.
 
88
     * options      - {Object} An optional object with properties to set on the
 
89
     *                userStyle
 
90
     * 
 
91
     * Return:
 
92
     * {<OpenLayers.Style>}
 
93
     */
 
94
    initialize: function(style, options) {
 
95
        this.rules = [];
 
96
 
 
97
        // use the default style from OpenLayers.Feature.Vector if no style
 
98
        // was given in the constructor
 
99
        this.setDefaultStyle(style || 
 
100
                OpenLayers.Feature.Vector.style["default"]);
 
101
        
 
102
        OpenLayers.Util.extend(this, options);
 
103
    },
 
104
 
 
105
    /** 
 
106
     * APIMethod: destroy
 
107
     * nullify references to prevent circular references and memory leaks
 
108
     */
 
109
    destroy: function() {
 
110
        for (var i=0, len=this.rules.length; i<len; i++) {
 
111
            this.rules[i].destroy();
 
112
            this.rules[i] = null;
 
113
        }
 
114
        this.rules = null;
 
115
        this.defaultStyle = null;
 
116
    },
 
117
    
 
118
    /**
 
119
     * Method: createSymbolizer
 
120
     * creates a style by applying all feature-dependent rules to the base
 
121
     * style.
 
122
     * 
 
123
     * Parameters:
 
124
     * feature - {<OpenLayers.Feature>} feature to evaluate rules for
 
125
     * 
 
126
     * Returns:
 
127
     * {Object} symbolizer hash
 
128
     */
 
129
    createSymbolizer: function(feature) {
 
130
        var style = this.createLiterals(
 
131
            OpenLayers.Util.extend({}, this.defaultStyle), feature);
 
132
        
 
133
        var rules = this.rules;
 
134
 
 
135
        var rule, context;
 
136
        var elseRules = [];
 
137
        var appliedRules = false;
 
138
        for(var i=0, len=rules.length; i<len; i++) {
 
139
            rule = rules[i];
 
140
            // does the rule apply?
 
141
            var applies = rule.evaluate(feature);
 
142
            
 
143
            if(applies) {
 
144
                if(rule instanceof OpenLayers.Rule && rule.elseFilter) {
 
145
                    elseRules.push(rule);
 
146
                } else {
 
147
                    appliedRules = true;
 
148
                    this.applySymbolizer(rule, style, feature);
 
149
                }
 
150
            }
 
151
        }
 
152
        
 
153
        // if no other rules apply, apply the rules with else filters
 
154
        if(appliedRules == false && elseRules.length > 0) {
 
155
            appliedRules = true;
 
156
            for(var i=0, len=elseRules.length; i<len; i++) {
 
157
                this.applySymbolizer(elseRules[i], style, feature);
 
158
            }
 
159
        }
 
160
 
 
161
        // don't display if there were rules but none applied
 
162
        if(rules.length > 0 && appliedRules == false) {
 
163
            style.display = "none";
 
164
        } else {
 
165
            style.display = "";
 
166
        }
 
167
        
 
168
        return style;
 
169
    },
 
170
    
 
171
    /**
 
172
     * Method: applySymbolizer
 
173
     *
 
174
     * Parameters:
 
175
     * rule - {OpenLayers.Rule}
 
176
     * style - {Object}
 
177
     * feature - {<OpenLayer.Feature.Vector>}
 
178
     *
 
179
     * Returns:
 
180
     * {Object} A style with new symbolizer applied.
 
181
     */
 
182
    applySymbolizer: function(rule, style, feature) {
 
183
        var symbolizerPrefix = feature.geometry ?
 
184
                this.getSymbolizerPrefix(feature.geometry) :
 
185
                OpenLayers.Style.SYMBOLIZER_PREFIXES[0];
 
186
 
 
187
        var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;
 
188
 
 
189
        // merge the style with the current style
 
190
        return this.createLiterals(
 
191
                OpenLayers.Util.extend(style, symbolizer), feature);
 
192
    },
 
193
    
 
194
    /**
 
195
     * Method: createLiterals
 
196
     * creates literals for all style properties that have an entry in
 
197
     * <this.propertyStyles>.
 
198
     * 
 
199
     * Parameters:
 
200
     * style   - {Object} style to create literals for. Will be modified
 
201
     *           inline.
 
202
     * feature - {Object}
 
203
     * 
 
204
     * Returns:
 
205
     * {Object} the modified style
 
206
     */
 
207
    createLiterals: function(style, feature) {
 
208
        var context = this.context || feature.attributes || feature.data;
 
209
        
 
210
        for (var i in this.propertyStyles) {
 
211
            style[i] = OpenLayers.Style.createLiteral(style[i], context, feature);
 
212
        }
 
213
        return style;
 
214
    },
 
215
    
 
216
    /**
 
217
     * Method: findPropertyStyles
 
218
     * Looks into all rules for this style and the defaultStyle to collect
 
219
     * all the style hash property names containing ${...} strings that have
 
220
     * to be replaced using the createLiteral method before returning them.
 
221
     * 
 
222
     * Returns:
 
223
     * {Object} hash of property names that need createLiteral parsing. The
 
224
     * name of the property is the key, and the value is true;
 
225
     */
 
226
    findPropertyStyles: function() {
 
227
        var propertyStyles = {};
 
228
 
 
229
        // check the default style
 
230
        var style = this.defaultStyle;
 
231
        this.addPropertyStyles(propertyStyles, style);
 
232
 
 
233
        // walk through all rules to check for properties in their symbolizer
 
234
        var rules = this.rules;
 
235
        var symbolizer, value;
 
236
        for (var i=0, len=rules.length; i<len; i++) {
 
237
            var symbolizer = rules[i].symbolizer;
 
238
            for (var key in symbolizer) {
 
239
                value = symbolizer[key];
 
240
                if (typeof value == "object") {
 
241
                    // symbolizer key is "Point", "Line" or "Polygon"
 
242
                    this.addPropertyStyles(propertyStyles, value);
 
243
                } else {
 
244
                    // symbolizer is a hash of style properties
 
245
                    this.addPropertyStyles(propertyStyles, symbolizer);
 
246
                    break;
 
247
                }
 
248
            }
 
249
        }
 
250
        return propertyStyles;
 
251
    },
 
252
    
 
253
    /**
 
254
     * Method: addPropertyStyles
 
255
     * 
 
256
     * Parameters:
 
257
     * propertyStyles - {Object} hash to add new property styles to. Will be
 
258
     *                  modified inline
 
259
     * symbolizer     - {Object} search this symbolizer for property styles
 
260
     * 
 
261
     * Returns:
 
262
     * {Object} propertyStyles hash
 
263
     */
 
264
    addPropertyStyles: function(propertyStyles, symbolizer) {
 
265
        var property;
 
266
        for (var key in symbolizer) {
 
267
            property = symbolizer[key];
 
268
            if (typeof property == "string" &&
 
269
                    property.match(/\$\{\w+\}/)) {
 
270
                propertyStyles[key] = true;
 
271
            }
 
272
        }
 
273
        return propertyStyles;
 
274
    },
 
275
    
 
276
    /**
 
277
     * APIMethod: addRules
 
278
     * Adds rules to this style.
 
279
     * 
 
280
     * Parameters:
 
281
     * rules - {Array(<OpenLayers.Rule>)}
 
282
     */
 
283
    addRules: function(rules) {
 
284
        this.rules = this.rules.concat(rules);
 
285
        this.propertyStyles = this.findPropertyStyles();
 
286
    },
 
287
    
 
288
    /**
 
289
     * APIMethod: setDefaultStyle
 
290
     * Sets the default style for this style object.
 
291
     * 
 
292
     * Parameters:
 
293
     * style - {Object} Hash of style properties
 
294
     */
 
295
    setDefaultStyle: function(style) {
 
296
        this.defaultStyle = style; 
 
297
        this.propertyStyles = this.findPropertyStyles();
 
298
    },
 
299
        
 
300
    /**
 
301
     * Method: getSymbolizerPrefix
 
302
     * Returns the correct symbolizer prefix according to the
 
303
     * geometry type of the passed geometry
 
304
     * 
 
305
     * Parameters:
 
306
     * geometry {<OpenLayers.Geometry>}
 
307
     * 
 
308
     * Returns:
 
309
     * {String} key of the according symbolizer
 
310
     */
 
311
    getSymbolizerPrefix: function(geometry) {
 
312
        var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES;
 
313
        for (var i=0, len=prefixes.length; i<len; i++) {
 
314
            if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) {
 
315
                return prefixes[i];
 
316
            }
 
317
        }
 
318
    },
 
319
    
 
320
    CLASS_NAME: "OpenLayers.Style"
 
321
});
 
322
 
 
323
 
 
324
/**
 
325
 * Function: createLiteral
 
326
 * converts a style value holding a combination of PropertyName and Literal
 
327
 * into a Literal, taking the property values from the passed features.
 
328
 * 
 
329
 * Parameters:
 
330
 * value - {String} value to parse. If this string contains a construct like
 
331
 *         "foo ${bar}", then "foo " will be taken as literal, and "${bar}"
 
332
 *         will be replaced by the value of the "bar" attribute of the passed
 
333
 *         feature.
 
334
 * context - {Object} context to take attribute values from
 
335
 * feature - {OpenLayers.Feature.Vector} The feature that will be passed
 
336
 *     to <OpenLayers.String.format> for evaluating functions in the context.
 
337
 * 
 
338
 * Returns:
 
339
 * {String} the parsed value. In the example of the value parameter above, the
 
340
 * result would be "foo valueOfBar", assuming that the passed feature has an
 
341
 * attribute named "bar" with the value "valueOfBar".
 
342
 */
 
343
OpenLayers.Style.createLiteral = function(value, context, feature) {
 
344
    if (typeof value == "string" && value.indexOf("${") != -1) {
 
345
        value = OpenLayers.String.format(value, context, [feature]);
 
346
        value = (isNaN(value) || !value) ? value : parseFloat(value);
 
347
    }
 
348
    return value;
 
349
};
 
350
    
 
351
/**
 
352
 * Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES
 
353
 * {Array} prefixes of the sld symbolizers. These are the
 
354
 * same as the main geometry types
 
355
 */
 
356
OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text'];