OpenLayers OpenLayers

Changeset 6240

Show
Ignore:
Timestamp:
02/12/08 18:05:47 (7 months ago)
Author:
ahocevar
Message:

"users should be able to customize the select style per feature": Created a StyleMap class which stores all styles that are needed for a layer. Controls that need to render features differently can now just give a render intent (e.g. "default", "select" or "temporary") to the layer's drawFeature method, instead of having extra style informations like Control.SelectFeature.selectStyle. Existing application that set layer.style or feature.style are still supported, but both of these style properties are now null by default. r=crschmidt,elemoine,tschaub (closes #1120)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/openlayers/examples/georss-flickr.html

    r6145 r6240  
    3232            style = new OpenLayers.Style({externalGraphic: "${thumbnail}"}); 
    3333             
     34            // make the thumbnails larger when we select them 
     35            selectStyle = new OpenLayers.Style({pointRadius: 35}); 
     36             
    3437            // create a rule with a point symbolizer that will make the thumbnail 
    3538            // larger if the title of the rss item conatins "powder" 
     
    4851            style.addRules([rule, elseRule]); 
    4952             
    50             markerLayer = new OpenLayers.Layer.Vector("", {style: style}); 
     53            markerLayer = new OpenLayers.Layer.Vector("", {styleMap: new OpenLayers.StyleMap({ 
     54                "default": style, 
     55                "select": selectStyle})}); 
    5156            map.addLayer(markerLayer); 
    5257             
    5358            // control that will show a popup when clicking on a thumbnail 
    5459            var popupControl = new OpenLayers.Control.SelectFeature(markerLayer, { 
    55               selectStyle: style, 
    5660              onSelect: function(feature) { 
    5761                  var pos = feature.geometry; 
  • trunk/openlayers/examples/openmnnd.html

    r6145 r6240  
    2929            map.addLayer(wms); 
    3030 
    31             wfs = new OpenLayers.Layer.WFS("Minnesota Streams (WFS)", wfs_url, {'typename':'streams'}, {ratio:1.25, minZoomLevel:4}); 
     31            wfs = new OpenLayers.Layer.WFS("Minnesota Streams (WFS)", wfs_url, {'typename':'streams'}, {ratio:1.25, minZoomLevel:4, style: OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default'])}); 
    3232 
    3333            // preFeatureInsert can be used to set style before the feature is drawn 
     
    5858 
    5959            rstyle = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']); 
    60             OpenLayers.Util.extend(rstyle, {'strokeColor': 'white', strokeWIdth: "4"}); 
     60            OpenLayers.Util.extend(rstyle, {'strokeColor': 'white', strokeWidth: "4"}); 
    6161            rwfs = new OpenLayers.Layer.WFS("Minnesota Roads (WFS)", wfs_url, {'typename':'roads'}, 
    6262              {ratio:1.25, minZoomLevel:7, extractAttributes: true, style:rstyle}); 
  • trunk/openlayers/examples/osm-layer.html

    r6145 r6240  
    4848        } 
    4949        function style_osm_feature(feature) { 
    50             feature.style.fill = "black"
     50            feature.style = OpenLayers.Util.extend({'fill':'black'}, OpenLayers.Feature.Vector.style['default'])
    5151            if (feature.attributes.highway == "motorway") { 
    5252                feature.style.strokeColor = "blue"; 
  • trunk/openlayers/examples/sld.html

    r6145 r6240  
    3333            styles = sld[1]; 
    3434             
    35             waterStyle = styles["WaterBodies"]; 
     35            // for the hover style, we do not want to use the SLD default as 
     36            // base style 
     37            styles["WaterBodies"]["Hover Styler"].defaultStyle = OpenLayers.Util.extend({}, 
     38                OpenLayers.Feature.Vector.style["select"]); 
    3639             
    3740            gmlLayers = [ 
     
    3942                    new OpenLayers.Layer.GML("StateBoundaries", 
    4043                            "tasmania/TasmaniaStateBoundaries.xml", { 
    41                             style: waterStyle["default"]}), 
     44                            styleMap: new OpenLayers.StyleMap(styles["WaterBodies"])}), 
    4245                    new OpenLayers.Layer.GML("Roads", 
    4346                            "tasmania/TasmaniaRoads.xml", { 
    44                             style: waterStyle["default"]}), 
     47                            styleMap: new OpenLayers.StyleMap(styles["Roads"])}), 
    4548                    new OpenLayers.Layer.GML("WaterBodies", 
    4649                            "tasmania/TasmaniaWaterBodies.xml", { 
    47                             style: waterStyle["default"]}), 
     50                            styleMap: new OpenLayers.StyleMap(styles["WaterBodies"])}), 
    4851                    new OpenLayers.Layer.GML("Cities", 
    4952                            "tasmania/TasmaniaCities.xml", { 
    50                             style: waterStyle["default"]})]; 
     53                            styleMap: new OpenLayers.StyleMap(styles["Cities"])})]; 
    5154  
    52             // add the first layer with the style passed to the constructor 
    53             map.addLayer(gmlLayers[0]); 
    54             // add the other layers after setting the style using the 
    55             // setStyle() method, which will pick the correct default style 
    56             // from the styles hash we got back from 
    57             // OpenLayers.Format.SLD.read() 
    58             for (var i=1; i<gmlLayers.length; i++) { 
    59                 gmlLayers[i].style = styles[gmlLayers[i].name]["default"]; 
    60                       map.addLayer(gmlLayers[i]); 
    61                 gmlLayers[i].redraw(); 
     55            for (var i=0; i<gmlLayers.length; i++) { 
     56                map.addLayer(gmlLayers[i]); 
    6257            } 
    6358             
    64             // SLD can also be used for the SelectFeature control 
    65             waterStyle["Hover Styler"].defaultStyle = 
    66                     OpenLayers.Feature.Vector.style["select"]; 
    6759            hover = new OpenLayers.Control.SelectFeature(gmlLayers[2], { 
    68                     selectStyle: waterStyle["Hover Styler"]
    69                     hover: true 
     60                    hover: true
     61                    renderIntent: "Hover Styler" 
    7062                }); 
    7163            map.addControl(hover); 
     
    7567        // set a new style when the radio button changes 
    7668        function setStyle(styleName) { 
     69            gmlLayers[2].styleMap.styles["default"] = styles["WaterBodies"][styleName]; 
    7770            // change the style of the features of the WaterBodies layer 
    78             var features = gmlLayers[2].features; 
    79             for (var i=0; i<features.length; i++) { 
    80                 features[i].style = waterStyle[styleName]; 
    81             } 
    8271            gmlLayers[2].redraw(); 
    8372        } 
  • trunk/openlayers/examples/wfs-scribble.html

    r6145 r6240  
    3636            df.featureAdded = function(feature) { 
    3737              feature.state = OpenLayers.State.INSERT; 
    38               feature.style['strokeColor'] = "#ff0000"
     38              feature.style = OpenLayers.Util.extend({'strokeColor': '#ff0000'}, OpenLayers.Feature.Vector.style['default'])
    3939              feature.layer.drawFeature(feature); 
    4040            } 
  • trunk/openlayers/lib/OpenLayers.js

    r6200 r6240  
    178178            "OpenLayers/Layer/GML.js", 
    179179            "OpenLayers/Style.js", 
     180            "OpenLayers/StyleMap.js", 
    180181            "OpenLayers/Rule.js", 
    181182            "OpenLayers/Rule/FeatureId.js", 
  • trunk/openlayers/lib/OpenLayers/Control/ModifyFeature.js

    r6149 r6240  
    168168        this.vertices = []; 
    169169        this.virtualVertices = []; 
    170         this.styleVirtual = OpenLayers.Util.extend({}, this.layer.style); 
     170        this.styleVirtual = OpenLayers.Util.extend({}, 
     171            this.layer.style || this.layer.styleMap.createSymbolizer()); 
    171172        this.styleVirtual.fillOpacity = 0.3; 
    172173        this.styleVirtual.strokeOpacity = 0.3; 
     
    410411                this.virtualVertices = []; 
    411412            } 
    412             this.layer.drawFeature(this.feature, this.selectControl.selectStyle); 
     413            this.layer.drawFeature(this.feature, this.selectControl.renderIntent); 
    413414        } 
    414415        // keep the vertex on top so it gets the mouseout after dragging 
     
    497498                vertex.geometry.parent.removeComponent(vertex.geometry); 
    498499                this.layer.drawFeature(this.feature, 
    499                                        this.selectControl.selectStyle); 
     500                                       this.selectControl.renderIntent); 
    500501                this.resetVertices(); 
    501502                this.onModification(this.feature); 
  • trunk/openlayers/lib/OpenLayers/Control/SelectFeature.js

    r6149 r6240  
    9696     * {Object} Hash of styles 
    9797     */ 
    98     selectStyle: OpenLayers.Feature.Vector.style['select'], 
     98    selectStyle: null, 
     99     
     100    /** 
     101     * Property: renderIntent 
     102     * {String} key used to retrieve the select style from the layer's 
     103     * style map. 
     104     */ 
     105    renderIntent: "select", 
    99106 
    100107    /** 
     
    248255     */ 
    249256    select: function(feature) { 
    250         // Store feature style for restoration later 
    251         if(feature.originalStyle != feature.style) { 
    252             feature.originalStyle = feature.style; 
    253         } 
    254257        this.layer.selectedFeatures.push(feature); 
    255258 
    256         var selectStyle = this.selectStyle; 
    257  
    258         if (feature.style.CLASS_NAME == "OpenLayers.Style") { 
    259             feature.style = feature.style.createStyle(feature); 
    260         } else { 
    261             feature.style = OpenLayers.Util.extend({}, feature.style); 
    262         } 
    263         if (selectStyle.CLASS_NAME == "OpenLayers.Style") { 
    264             selectStyle = selectStyle.createStyle(feature); 
    265         } 
    266         OpenLayers.Util.extend(feature.style, selectStyle); 
    267  
    268         this.layer.drawFeature(feature); 
     259        var selectStyle = this.selectStyle || this.renderIntent; 
     260         
     261        this.layer.drawFeature(feature, selectStyle); 
    269262        this.layer.events.triggerEvent("featureselected", {feature: feature}); 
    270263        this.onSelect(feature); 
     
    281274    unselect: function(feature) { 
    282275        // Store feature style for restoration later 
    283         if(feature.originalStyle != null) { 
    284             feature.style = feature.originalStyle; 
    285         } 
    286         this.layer.drawFeature(feature); 
     276        this.layer.drawFeature(feature, "default"); 
    287277        OpenLayers.Util.removeItem(this.layer.selectedFeatures, feature); 
    288278        this.layer.events.triggerEvent("featureunselected", {feature: feature}); 
  • trunk/openlayers/lib/OpenLayers/Feature/Vector.js

    r5909 r6240  
    6060    style: null, 
    6161     
     62    /** 
     63     * Property: renderIntent 
     64     * {String} rendering intent currently being used 
     65     */ 
     66    renderIntent: "default", 
     67 
    6268    /**  
    6369     * Constructor: OpenLayers.Feature.Vector 
  • trunk/openlayers/lib/OpenLayers/Format/SLD.js

    r6200 r6240  
    196196     * Parameters: 
    197197     * xmlNode - {<DOMElement>} 
    198      * name - {String} The name of the returned rule. 
    199198     *  
    200199     * Returns: 
     
    568567     * attributeName  - {String} name of the attribute to match 
    569568     * attributeValue - {String} optional value of the attribute 
    570      * 
    571      * Returns: 
    572      * {DOMElement} 
    573569     */ 
    574570    getNodeWithAttribute: function(xmlNodeList, attributeName, attributeValue) { 
  • trunk/openlayers/lib/OpenLayers/Layer/Vector.js

    r6173 r6240  
    9999     */ 
    100100    style: null, 
     101     
     102    /** 
     103     * Property: styleMap 
     104     * {<OpenLayers.StyleMap>} 
     105     */ 
     106    styleMap: null, 
    101107 
    102108    /** 
     
    148154        ); 
    149155 
    150         var defaultStyle = OpenLayers.Feature.Vector.style['default']; 
    151         this.style = OpenLayers.Util.extend({}, defaultStyle); 
    152  
    153156        OpenLayers.Layer.prototype.initialize.apply(this, arguments); 
    154157 
     
    163166            this.displayError(); 
    164167        }  
     168 
     169        if (!this.styleMap) { 
     170            this.styleMap = new OpenLayers.StyleMap(); 
     171        } 
    165172 
    166173        this.features = []; 
     
    313320            feature.layer = this; 
    314321 
    315             if (!feature.style) { 
     322            if (!feature.style && this.style) { 
    316323                feature.style = OpenLayers.Util.extend({}, this.style); 
    317324            } 
     
    404411     * Parameters:  
    405412     * feature - {<OpenLayers.Feature.Vector>}  
    406      * style - {Object}  
     413     * style - {Object} Symbolizer hash or {String} renderIntent 
    407414     */ 
    408415    drawFeature: function(feature, style) { 
    409         if(style == null) { 
    410             if(feature.style) { 
    411                 style = feature.style; 
    412             } else { 
    413                 style = this.style; 
    414             } 
    415         } 
    416  
    417         if (style && style.CLASS_NAME &&  
    418             style.CLASS_NAME == "OpenLayers.Style") { 
    419             style = style.createStyle(feature); 
    420         }     
     416        if (typeof style != "object") { 
     417            var renderIntent = typeof style == "string" ? 
     418                style : feature.renderIntent; 
     419            style = feature.style || this.style; 
     420            if (!style) { 
     421                style = this.styleMap.createSymbolizer(feature, renderIntent); 
     422            } 
     423        } 
    421424         
    422425        this.renderer.drawFeature(feature, style); 
  • trunk/openlayers/lib/OpenLayers/Style.js

    r6200 r6240  
    4444     * Property: defaultStyle 
    4545     * {Object} hash of style properties to use as default for merging 
    46      * rule-based style symbolizers onto. If no rules are defined, createStyle 
    47      * will return this style. 
     46     * rule-based style symbolizers onto. If no rules are defined, 
     47     * createSymbolizer will return this style. 
    4848     */ 
    4949    defaultStyle: null, 
     
    9797     
    9898    /** 
    99      * APIMethod: createStyle 
     99     * Method: createSymbolizer 
    100100     * creates a style by applying all feature-dependent rules to the base 
    101101     * style. 
     
    103103     * Parameters: 
    104104     * feature - {<OpenLayers.Feature>} feature to evaluate rules for 
    105      * baseStyle - {Object} hash of styles feature styles to extend 
    106      *  
    107      * Returns: 
    108      * {<OpenLayers.Feature.Vector.style>} hash of feature styles 
    109      */ 
    110     createStyle: function(feature) { 
     105     *  
     106     * Returns: 
     107     * {Object} symbolizer hash 
     108     */ 
     109    createSymbolizer: function(feature) { 
    111110        var style = OpenLayers.Util.extend({}, this.defaultStyle); 
    112111         
  • trunk/openlayers/tests/Control/test_ModifyFeature.html

    r6149 r6240  
    77        t.plan(3); 
    88        var layer = { 
     9            styleMap: {createSymbolizer: function(){}}, 
    910            events: { 
    1011                on: function() {} 
     
    7879         
    7980        var control = new OpenLayers.Control.ModifyFeature({ 
    80             style: null
     81            styleMap: {createSymbolizer: function(){}}
    8182            events: { 
    8283                on: function() {} 
  • trunk/openlayers/tests/Control/test_SelectFeature.html

    r6149 r6240  
    3434     
    3535    function test_Control_SelectFeature_select(t) { 
    36         t.plan(7); 
     36        t.plan(2); 
    3737        var map = new OpenLayers.Map("map"); 
    3838        var layer = new OpenLayers.Layer.Vector(); 
     
    4141        var feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0,0)); 
    4242        layer.addFeatures(feature); 
    43         layer.drawFeature = function() { } 
     43        layer.drawFeature = function(feature, style) { 
     44            layer.styleMap.createSymbolizer(feature, style); 
     45        } 
    4446        control.select(feature); 
    45         t.eq(feature.style.strokeColor, OpenLayers.Feature.Vector.style['select'].strokeColor, "feature style is set to select style"); 
     47        t.eq(feature.renderIntent, "select", "render intent is set to select"); 
    4648        control.unselect(feature); 
    47         t.eq(feature.style.strokeColor, OpenLayers.Feature.Vector.style['default'].strokeColor, "feature style is set back to old style"); 
    48          
    49         // Don't ever overwrite my feature style with undefined properties from the selectStyle 
    50         feature.style = {externalGraphic: "foo.png", pointRadius: 39}; 
    51         control.selectStyle.pointRadius = undefined; 
    52         control.select(feature); 
    53         t.eq(feature.style.pointRadius, 39, "undefined style property inherited from original feature style"); 
    54         control.unselect(feature); 
    55          
    56         // Ok, that one went well. But I'm sure you cannot handle OL.Style. 
    57         feature.style = new OpenLayers.Style({externalGraphic: "foo.png", pointRadius: 39}); 
    58         control.select(feature); 
    59         t.eq(feature.style.pointRadius, 39, "undefined style property inherited from original feature style object"); 
    60         control.unselect(feature); 
    61          
    62         // Wow, but using OL.Style as selectStyle will break you. 
    63         control.selectStyle = new OpenLayers.Style({strokeColor: "green"}); 
    64         control.select(feature); 
    65         t.eq(feature.style.strokeColor, "green", "style correct if both feature.style and selectStyle are OL.Style"); 
    66         control.unselect(feature); 
    67          
    68         // Not bad, not bad. And what if I set feature.style back to a style hash? 
    69         feature.style = layer.style; 
    70         control.select(feature); 
    71         t.eq(feature.style.strokeColor, "green", "style still correct with only selectStyle being OL.Style"); 
    72         control.unselect(feature); 
    73         t.eq(feature.style.strokeColor, OpenLayers.Feature.Vector.style["default"].strokeColor, "style set back to original correctly"); 
     49        t.eq(feature.renderIntent, "default", "render intent is set back to default"); 
    7450    } 
    7551     
  • trunk/openlayers/tests/Layer/test_Vector.html

    r5476 r6240  
    6868        t.ok(layer.features.length == 0, 
    6969             "OpenLayers.Layer.Vector.removeFeatures(layer.features) removes all feature from the features array"); 
    70     } 
    71      
    72     function test_Layer_Vector_addStyle (t) { 
    73         t.plan(2);     
    74         var layer = new OpenLayers.Layer.Vector(name); 
    75         var map = new OpenLayers.Map('map'); 
    76         map.addLayer(layer); 
    77         var g = new OpenLayers.Geometry.Point(0, 0); 
    78         var f = new OpenLayers.Feature.Vector(g); 
    79         t.eq( f.style,  null, "Feature style is null by default."); 
    80         layer.addFeatures(f); 
    81         t.ok( f.style != null, "Feature style is set by layer."); 
    8270    } 
    8371     
     
    10795             "calls layer.renderer.drawFeature() with feature.geometry"); 
    10896         
    109         feature.style = 'exists'
     97        feature.style = {foo: "bar"}
    11098        layer.drawFeature(feature); 
    11199        t.eq(feature.style, s, 
     
    113101         
    114102        feature.style = null; 
    115         layer.style = 'exists'
     103        layer.style = {foo: "bar"}
    116104        layer.drawFeature(feature); 
    117         t.eq(layer.style, s
     105        t.eq(layer.style.foo, s.foo
    118106             "given null feature style, uses layer style"); 
    119107 
    120         feature.style = 'exists'
    121         layer.style = 'exists'
    122         var customStyle = 'custom'
     108        feature.style = {foo1: "bar1"}
     109        layer.style = {foo2: "bar2"}
     110        var customStyle = {foo: "bar"}
    123111        layer.drawFeature(feature, customStyle); 
    124         t.eq(customStyle, s
     112        t.eq(customStyle.foo, s.foo
    125113             "given a custom style, renders with that"); 
    126114         
  • trunk/openlayers/tests/list-tests.html

    r6177 r6240  
    4343    <li>Feature/test_Vector.html</li> 
    4444    <li>test_Style.html</li> 
     45    <li>test_StyleMap.html</li> 
    4546    <li>test_Rule.html</li> 
    4647    <li>Rule/test_Comparison.html</li> 
  • trunk/openlayers/tests/test_Style.html

    r6131 r6240  
    1212             "new OpenLayers.Style returns object" );  
    1313        t.eq(style.foo, "bar", "constructor sets options correctly");  
    14         t.eq(typeof style.createStyle, "function", "style has a createStyle function");  
     14        t.eq(typeof style.createSymbolizer, "function", "style has a createSymbolizer function");  
    1515    } 
    1616     
     
    4646        var feature = new OpenLayers.Feature.Vector( 
    4747                new OpenLayers.Geometry.Point(3,5), 
    48                 {"foo": "bar"}, 
    49                 style); 
     48                {"foo": "bar"}); 
    5049 
    5150        feature.fid = "1"; 
    5251        // for this fid, the above rule should apply 
     52         
     53        layer.styleMap = new OpenLayers.StyleMap(style); 
    5354                 
    5455        layer.addFeatures([feature]); 
     
    5960 
    6061        // at this scale, the feature should be green 
    61         var createdStyle = style.createStyle(feature); 
     62        var createdStyle = style.createSymbolizer(feature); 
    6263        t.eq(createdStyle.externalGraphic, "barbar.png", "Calculated property style correctly."); 
    6364        t.eq(createdStyle.display, "", "Feature is visible at scale "+map.getScale()); 
     
    6667        map.setCenter(new OpenLayers.LonLat(3,5), 9); 
    6768        // at this scale, the feature should be red 
    68         createdStyle = style.createStyle(feature); 
     69        createdStyle = style.createSymbolizer(feature); 
    6970        t.eq(createdStyle.display, "", "Feature is visible at scale "+map.getScale()); 
    7071        t.eq(createdStyle.fillColor, "yellow", "Point symbolizer from rule applied correctly."); 
     
    7273        map.setCenter(new OpenLayers.LonLat(3,5), 8); 
    7374        // at this scale, the feature should be yellow 
    74         createdStyle = style.createStyle(feature); 
     75        createdStyle = style.createSymbolizer(feature); 
    7576        t.eq(createdStyle.display, "", "Feature is visible at scale "+map.getScale()); 
    7677        t.eq(createdStyle.fillColor, "red", "Point symbolizer from rule applied correctly."); 
     
    7879        map.setCenter(new OpenLayers.LonLat(3,5), 7); 
    7980        // at this scale, the feature should be invisible 
    80         createdStyle = style.createStyle(feature); 
     81        createdStyle = style.createSymbolizer(feature); 
    8182        t.eq(createdStyle.display, "none", "Feature is invisible at scale "+map.getScale()); 
    8283        t.eq(createdStyle.fillColor, baseStyle.fillColor, "Point symbolizer from base style applied correctly."); 
     
    8586        // now the rule should not apply 
    8687         
    87         createdStyle = style.createStyle(feature); 
     88        createdStyle = style.createSymbolizer(feature); 
    8889        t.eq(createdStyle.fillColor, baseStyle.fillColor, "Correct style for rule that does not apply to fid=\"2\"."); 
    8990    } 
    9091     
    91     function test_Style_createStyle(t) { 
     92    function test_Style_createSymbolizer(t) { 
    9293        t.plan(2); 
    9394        var style = new OpenLayers.Style(); 
     
    105106            t.eq(r.id, rule.id, "(plain) applySymbolizer called with correct rule"); 
    106107        } 
    107         style.createStyle(new OpenLayers.Feature.Vector()); 
     108        style.createSymbolizer(new OpenLayers.Feature.Vector()); 
    108109 
    109110        rule.evaluate = function() {return false;}; 
     
    111112            t.eq(r.id, elseRule.id, "(else) applySymbolizer called with correct rule"); 
    112113        } 
    113         style.createStyle(new OpenLayers.Feature.Vector()); 
     114        style.createSymbolizer(new OpenLayers.Feature.Vector()); 
    114115    } 
    115116     
     
    127128        var style = new OpenLayers.Style(); 
    128129        style.addRules([rule]); 
    129         var styleHash = style.createStyle(new OpenLayers.Feature.Vector()); 
     130        var styleHash = style.createSymbolizer(new OpenLayers.Feature.Vector()); 
    130131        t.eq(styleHash.externalGraphic, "bar.png", "correctly evaluated rule against a custom context"); 
    131132    }