Ticket #18: patch-18-r371-D1.diff

File patch-18-r371-D1.diff, 48.7 kB (added by elemoine, 1 year ago)
  • geoext/build/apidoc_config/Menu.txt

    old new  
    5050 
    5151   File: FeatureReader  (GeoExt/data/FeatureReader.js) 
    5252   File: FeatureRecord  (GeoExt/data/FeatureRecord.js) 
    53    File: FeatureStoreMediator  (GeoExt/data/FeatureStoreMediator.js) 
     53   File: FeatureStoreMixin   (GeoExt/data/FeatureStore.js) 
    5454   File: LayerReader  (GeoExt/data/LayerReader.js) 
    5555   File: LayerRecord  (GeoExt/data/LayerRecord.js) 
    56    File: LayerStoreMediator  (GeoExt/data/LayerStoreMediator.js) 
    5756   File: LayerStoreMixin  (GeoExt/data/LayerStore.js) 
    5857   File: ProtocolProxy  (GeoExt/data/ProtocolProxy.js) 
    5958   }  # Group: Data 
  • geoext/tests/lib/GeoExt/data/FeatureStoreMediator.html

    old new  
    1 <!DOCTYPE html> 
    2 <html debug="true"> 
    3   <head> 
    4     <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script> 
    5     <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script> 
    6  
    7     <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script> 
    8     <script type="text/javascript" src="../../../../lib/GeoExt.js"></script> 
    9  
    10     <script type="text/javascript"> 
    11         function test_constructor(t) { 
    12             t.plan(1); 
    13             // setup 
    14             var mediator, store; 
    15             store = new Ext.data.Store({ 
    16                 reader: new GeoExt.data.FeatureReader( 
    17                     {}, [{name: "name", type: "string"}] 
    18                 ) 
    19             }); 
    20             // 1 test 
    21             mediator = new GeoExt.data.FeatureStoreMediator({ 
    22                 store: store 
    23             }); 
    24             t.ok(mediator.store == store, 
    25                  "ctor correctly sets store"); 
    26         } 
    27         function test_addFeatures(t) { 
    28             t.plan(4); 
    29             // setup 
    30             var mediator, store, features, flip, filter; 
    31             store = new Ext.data.Store({ 
    32                 reader: new GeoExt.data.FeatureReader( 
    33                     {}, [{name: "name", type: "string"}] 
    34                 ) 
    35             }); 
    36             mediator = new GeoExt.data.FeatureStoreMediator({ 
    37                 store: store 
    38             }); 
    39             function createFeatures() { 
    40                 return [ 
    41                     new OpenLayers.Feature.Vector(null, { 
    42                         name: "foo" 
    43                     }), 
    44                     new OpenLayers.Feature.Vector() 
    45                 ]; 
    46             } 
    47             // 2 tests 
    48             features = createFeatures(); 
    49             mediator.addFeatures(features); 
    50             t.eq(store.getCount(), 2, 
    51                  "addFeatures adds correct number of features"); 
    52             var record = store.getById(features[0].id); 
    53             t.ok(record.get('feature') == features[0], 
    54                  'addFeatures correctly adds features'); 
    55             // 1 test 
    56             features = createFeatures(); 
    57             mediator.addFeatures(features, {append: false}); 
    58             t.eq(store.getCount(), 2, 
    59                  "addFeatures adds correct number of features"); 
    60             // 1 test 
    61             flip = false; 
    62             filter = function() { flip = !flip; return flip; }; 
    63             features = createFeatures(); 
    64             mediator.addFeatures(features,  
    65                 {append: false, filter: filter}); 
    66             t.eq(store.getCount(), 1, 
    67                  "addFeatures adds correct number of features " + 
    68                  "with filter passed"); 
    69         } 
    70         // there's a bug in Ext where Ext dereferences an undefined 
    71         // value, the bug triggers with a grouping store and group 
    72         // field when store.loadData is called with only one arg 
    73         // or with false as the second arg. addFeatures works 
    74         // around that bug, so that test_addFeatures_ExtBug passes 
    75         // 
    76         // prefix the function name with test_ if you want to 
    77         // actually run the test 
    78         /* 
    79         function ExtBug(t) { 
    80             t.plan(1); 
    81             // setup 
    82             var store, a; 
    83             store = new Ext.data.GroupingStore({ 
    84                 reader: new Ext.data.ArrayReader({id: 0}, [ 
    85                     {name: "name", mapping: 1}, 
    86                     {name: "occupation", mapping: 2} 
    87                 ]), 
    88                 groupField: "name" 
    89             }); 
    90             a = [[1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist']]; 
    91             store.loadData(a, false); // same effect with store.loadData(a) 
    92             // 1 test 
    93             t.eq(store.getCount(), 2, 
    94                  "correct number of records loaded"); 
    95         } 
    96         */ 
    97         function test_addFeatures_ExtBug(t) { 
    98             t.plan(2); 
    99             // setup 
    100             var mediator, store, features, flip, filter; 
    101             store = new Ext.data.GroupingStore({ 
    102                 reader: new GeoExt.data.FeatureReader( 
    103                     {}, [{name: "name", type: "string"}] 
    104                 ), 
    105                 groupField: "name" 
    106             }); 
    107             mediator = new GeoExt.data.FeatureStoreMediator({ 
    108                 store: store 
    109             }); 
    110             function createFeatures() { 
    111                 return [ 
    112                     new OpenLayers.Feature.Vector(null, { 
    113                         name: "foo" 
    114                     }), 
    115                     new OpenLayers.Feature.Vector() 
    116                 ]; 
    117             } 
    118             // 2 tests 
    119             features = createFeatures(); 
    120             // {append: false} makes Ext panic without the workaround 
    121             // in FeatureStoreMediator.js, see test_ExtBug for making 
    122             // Ext panic without MapFish involves 
    123             mediator.addFeatures(features, {append: false}); 
    124             t.eq(store.getCount(), 2, 
    125                  "addFeatures adds correct number of features"); 
    126             var record = store.getById(features[0].id); 
    127             t.ok(record.get('feature') == features[0], 
    128                  'addFeatures correctly adds features'); 
    129         } 
    130         function test_removeFeatures(t) { 
    131             t.plan(1); 
    132             // setup 
    133             var mediator, store, features; 
    134             store = new Ext.data.Store({ 
    135                 reader: new GeoExt.data.FeatureReader( 
    136                     {}, [{name: "name", type: "string"}] 
    137                 ) 
    138             }); 
    139             mediator = new GeoExt.data.FeatureStoreMediator({ 
    140                 store: store 
    141             }); 
    142             function createFeatures() { 
    143                 return [ 
    144                     new OpenLayers.Feature.Vector(null, { 
    145                         name: "foo" 
    146                     }), 
    147                     new OpenLayers.Feature.Vector() 
    148                 ]; 
    149             } 
    150             // 1 test 
    151             features = createFeatures(); 
    152             mediator.addFeatures(features); 
    153             mediator.removeFeatures(features); 
    154             t.eq(store.getCount(), 0, 
    155                  'removesFeatures correctly removes features'); 
    156         } 
    157     </script> 
    158   <body> 
    159     <div id="map"></div> 
    160   </body> 
    161 </html> 
  • geoext/tests/lib/GeoExt/data/LayerStoreMediator.html

    old new  
    1 <!DOCTYPE html> 
    2 <html debug="true"> 
    3   <head> 
    4     <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script> 
    5     <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script> 
    6  
    7     <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script> 
    8     <script type="text/javascript" src="../../../../lib/GeoExt.js"></script> 
    9  
    10     <script type="text/javascript"> 
    11         function test_constructor(t) { 
    12             t.plan(3); 
    13             // setup 
    14             var mediator, store, layer; 
    15             store = new Ext.data.Store({ 
    16                 reader: new GeoExt.data.FeatureReader( 
    17                     {}, [{name: "name", type: "string"}] 
    18                 ) 
    19             }); 
    20             layer = new OpenLayers.Layer.Vector(); 
    21             // 3 tests 
    22             mediator = new GeoExt.data.LayerStoreMediator({ 
    23                 store: store, 
    24                 layer: layer, 
    25                 activate: function() { 
    26                     t.ok(true, "ctor calls activate"); 
    27                 } 
    28             }); 
    29             t.ok(mediator.layer == layer, 
    30                  "ctor correctly sets layer"); 
    31             t.ok(mediator.featureStoreMediator instanceof 
    32                      GeoExt.data.FeatureStoreMediator, 
    33                  "ctor correctly creates feature store mediator"); 
    34         } 
    35         function test_events(t) { 
    36             t.plan(3); 
    37             // setup 
    38             var mediator, store, layer, eventType; 
    39             store = new Ext.data.Store({ 
    40                 reader: new GeoExt.data.FeatureReader( 
    41                     {}, [{name: "name", type: "string"}] 
    42                 ) 
    43             }); 
    44             layer = new OpenLayers.Layer.Vector(); 
    45             mediator = new GeoExt.data.LayerStoreMediator({ 
    46                 store: store, 
    47                 layer: layer, 
    48                 update: function() { 
    49                     t.ok(true, "update called on " + eventType); 
    50                 } 
    51             }); 
    52             // 1 test 
    53             eventType = "featuresadded"; 
    54             layer.events.triggerEvent(eventType); 
    55             // 1 test 
    56             eventType = "featuresremoved"; 
    57             layer.events.triggerEvent(eventType); 
    58             // 1 test 
    59             eventType = "featuremodified"; 
    60             layer.events.triggerEvent(eventType); 
    61         } 
    62         function test_update(t) { 
    63             t.plan(2); 
    64             // setup 
    65             var mediator, store, layer; 
    66             store = new Ext.data.Store({ 
    67                 reader: new GeoExt.data.FeatureReader( 
    68                     {}, [{name: "name", type: "string"}] 
    69                 ) 
    70             }); 
    71             layer = new OpenLayers.Layer.Vector(); 
    72             mediator = new GeoExt.data.LayerStoreMediator({ 
    73                 store: store, 
    74                 layer: layer 
    75             }); 
    76             function createFeatures() { 
    77                 return [ 
    78                     new OpenLayers.Feature.Vector(null, {name: "foo"}), 
    79                     new OpenLayers.Feature.Vector(null, {name: "bar"}) 
    80                 ]; 
    81             } 
    82             // 1 test 
    83             layer.features = createFeatures(); 
    84             layer.events.triggerEvent("featuresadded"); 
    85             t.eq(store.getCount(), 2, 
    86                  "featuresadded event caused insertion of 2 records");  
    87             // 1 test 
    88             layer.features = createFeatures(); 
    89             layer.events.triggerEvent("featuresadded"); 
    90             t.eq(store.getCount(), 2, 
    91                  "featuresadded event caused insertion of 2 records");  
    92         } 
    93     </script> 
    94   <body> 
    95     <div id="map"></div> 
    96   </body> 
    97 </html> 
  • geoext/tests/lib/GeoExt/data/FeatureStore.html

    old new  
     1<!DOCTYPE html>  
     2<html debug="true"> 
     3  <head>  
     4    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script> 
     5    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script> 
     6    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script> 
     7    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script> 
     8 
     9    <script type="text/javascript">  
     10        function test_constructor(t) {  
     11            t.plan(3);  
     12 
     13            var store, reader, layer; 
     14 
     15            store = new GeoExt.data.FeatureStore();  
     16            t.ok(store.reader instanceof GeoExt.data.FeatureReader, 
     17                 "ctor creates a feature reader if none is provided"); 
     18 
     19            reader = new Ext.data.ArrayReader(); 
     20            store = new GeoExt.data.FeatureStore({reader: reader}); 
     21            t.ok(store.reader == reader, 
     22                 "ctor sets the passed reader in the instance"); 
     23 
     24            layer = new OpenLayers.Layer.Vector("Foo Layer"); 
     25            store = new GeoExt.data.FeatureStore({layer: layer}); 
     26            t.ok(store.layer == layer, 
     27                 "ctor sets the passed layer in the instance"); 
     28        }  
     29 
     30        function test_load_clear(t) { 
     31            t.plan(5); 
     32             
     33            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     34            var store = new GeoExt.data.FeatureStore({ 
     35                layer: layer 
     36            }); 
     37 
     38            // loadData 
     39            store.loadData([ 
     40                new OpenLayers.Feature.Vector(), 
     41                new OpenLayers.Feature.Vector() 
     42            ]); 
     43            t.eq(layer.features.length, 2, "loading two records in the store with 'loadData' adds two features to the layer"); 
     44            t.eq(store.getCount(), 2, 'loading two records in the store with "loadData" does not create duplicate records in store');  
     45 
     46            // loadData with recordFilter 
     47            store.recordFilter = function(record) { return false; }; 
     48            store.loadData([ 
     49                new OpenLayers.Feature.Vector(), 
     50                new OpenLayers.Feature.Vector() 
     51            ]); 
     52            t.eq(layer.features.length, 0, 
     53                 "loading two records in the store with 'loadData' adds no feature to the layer if recordFilter returns false"); 
     54 
     55            // removeAll 
     56            store.removeAll(); 
     57            t.eq(store.getCount(), 0, '"removeAll" on store removes all records from the store');  
     58            t.eq(layer.features.length, 0, '"removeAll" on store removes features from layer');  
     59        } 
     60         
     61        function test_bind_unbind(t) { 
     62            t.plan(28); 
     63             
     64            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     65            var store = new GeoExt.data.FeatureStore(); 
     66            var features = [new OpenLayers.Feature.Vector("Foo feature"), 
     67                          new OpenLayers.Feature.Vector("Bar feature")]; 
     68            var records = [ 
     69                new GeoExt.data.FeatureRecord({ 
     70                    feature: new OpenLayers.Feature.Vector("Foo record")}), 
     71                new GeoExt.data.FeatureRecord({ 
     72                    feature: new OpenLayers.Feature.Vector("Bar record")}) 
     73            ]; 
     74 
     75            var reinit_test_data = function () { 
     76                // unbind store 
     77                store.unbind(); 
     78 
     79                // remove all existing records and features 
     80                store.removeAll(); 
     81                layer.removeFeatures(layer.features); 
     82                t.eq(layer.features.length, 0, "there is no more features in the layer"); 
     83                t.eq(store.getCount(), 0, "there is no more records in the store"); 
     84 
     85                // add testing data to store and layer 
     86                store.add(records); 
     87                layer.addFeatures(features); 
     88                t.eq(layer.features.length, 2, "initial features are loaded in the layer"); 
     89                t.eq(store.getCount(), 2, "initial records are loaded in the store"); 
     90            }; 
     91             
     92            // test store to layer synchronization 
     93            reinit_test_data(); 
     94            store.bind(layer, {initDir: GeoExt.data.FeatureStore.STORE_TO_LAYER}); 
     95            t.eq(layer.features.length, 4, "initial records are synchronized to layer"); 
     96            t.eq(store.getCount(), 2, "initial features are not synchronized to store"); 
     97            layer.removeFeatures([features[0]]); 
     98            t.eq(layer.features.length, 3, "removing feature not present in store has been well removed"); 
     99            t.eq(store.getCount(), 2, "nothing to remove in store when removing feature not present in store"); 
     100 
     101            // test layer to store synchronization 
     102            reinit_test_data(); 
     103            store.bind(layer, {initDir: GeoExt.data.FeatureStore.LAYER_TO_STORE}); 
     104            t.eq(layer.features.length, 2, "initial records are not synchronized to layer"); 
     105            t.eq(store.getCount(), 4, "initial features are synchronized to store"); 
     106            store.remove(records[0]); 
     107            t.eq(store.getCount(), 3, "removing record not present in layer has been well removed"); 
     108            t.eq(layer.features.length, 2, "nothing to remove in layer when removing record not present in layer"); 
     109 
     110            // test both synchronization 
     111            reinit_test_data(); 
     112            store.bind(layer, {initDir: GeoExt.data.FeatureStore.LAYER_TO_STORE | 
     113                                      GeoExt.data.FeatureStore.STORE_TO_LAYER}); 
     114            t.eq(layer.features.length, 4, "initial records are synchronized to layer"); 
     115            t.eq(store.getCount(), 4, "initial features are synchronized to store"); 
     116 
     117            // test no synchronization 
     118            reinit_test_data(); 
     119            store.bind(layer, {initDir: 0}); 
     120            t.eq(layer.features.length, 2, "initial records are not synchronized to layer"); 
     121            t.eq(store.getCount(), 2, "initial features are not synchronized to store"); 
     122        } 
     123 
     124        function test_add_remove(t) { 
     125             
     126            t.plan(5); 
     127             
     128            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     129            var store = new GeoExt.data.FeatureStore({ 
     130                layer: layer 
     131            }); 
     132            var record = new GeoExt.data.FeatureRecord({ 
     133                feature: new OpenLayers.Feature.Vector() 
     134            }); 
     135 
     136            // add 
     137            store.add([record]); 
     138            t.eq(store.getCount(), 1, 'Adding a record to store with "add" does not create duplicate record in store');  
     139            t.eq(layer.features.length, 1, 'Adding a record to store with "add" does create corresponding feature in layer');  
     140 
     141            // remove 
     142            store.remove(record); 
     143            t.eq(store.getCount(), 0, 'remove on store with "remove" removes the record from the store');  
     144            t.eq(layer.features.length, 0, 'remove on store with "remove" removes the corresponding feature from layer');  
     145 
     146            // add with recordFilter 
     147            store.recordFilter = function(record) { return false; }; 
     148            store.add([record]); 
     149            t.eq(layer.features.length, 0, 
     150                 'Adding a record with "add" does not add feature to layer if recordFilter returns false'); 
     151        } 
     152         
     153        function test_addFeatures_removeFeatures(t) { 
     154             
     155            t.plan(5); 
     156             
     157            var features = [  
     158                new OpenLayers.Feature.Vector(),  
     159                new OpenLayers.Feature.Vector()  
     160            ];  
     161            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     162            var store = new GeoExt.data.FeatureStore({ 
     163                layer: layer 
     164            }); 
     165 
     166            // test layer addFeatures 
     167            layer.addFeatures(features); 
     168            t.eq(layer.features.length, 2, 'Adding features to layer with "addFeatures" does not create duplicate features on the layer'); 
     169            t.eq(store.getCount(), 2, 'Adding features to layer with "addFeatures" does create corresponding records in the store'); 
     170 
     171            // test layer removeFeatures 
     172            layer.removeFeatures(layer.features); 
     173            t.eq(store.getCount(), 0, '"removeFeatures" on layer removes records from the store');  
     174            t.eq(layer.features.length, 0, '"removeFeatures" on layer removes features from layer'); 
     175 
     176            // test layer addFeatures with featureFilter 
     177            store.featureFilter = function(feature) { return false; }; 
     178            layer.addFeatures(features); 
     179            t.eq(store.getCount(), 0, 
     180                 'Adding features to layer with "addFeatures" does not insert records in the store if featureFilter returns false'); 
     181        } 
     182 
     183        function test_featuremodified_update(t) { 
     184            t.plan(6); 
     185 
     186            /* 
     187             * Set up 
     188             */ 
     189            var feature, id, layer, store, recordType, record; 
     190 
     191            feature = new OpenLayers.Feature.Vector(null, { 
     192                foo: "foo", 
     193                bar: "bar" 
     194            }); 
     195 
     196            id = feature.id; 
     197 
     198            recordType = GeoExt.data.FeatureRecord.create([ 
     199                {name: "foo"}, {name: "bar"} 
     200            ]); 
     201 
     202            layer = new OpenLayers.Layer.Vector("vector"); 
     203 
     204            store = new GeoExt.data.FeatureStore({ 
     205                layer: layer, 
     206                recordType: recordType, 
     207                data: [feature] 
     208            }); 
     209 
     210            t.eq(store.getById(id).get("foo"), "foo", 
     211                 "record gets correct initial value for property \"foo\""); 
     212 
     213            t.eq(store.getById(id).get("bar"), "bar", 
     214                 "record gets correct initial value for property \"bar\""); 
     215 
     216            /* 
     217             * Test 
     218             */ 
     219             
     220            // featuremodified 
     221            feature.attributes.foo = "foo2"; 
     222            feature.attributes.bar = "bar2"; 
     223            layer.events.triggerEvent("featuremodified", {feature: feature}); 
     224 
     225            t.eq(store.getById(id).get("foo"), "foo2", 
     226                 "featuremodified event causes update of record property \"foo\""); 
     227 
     228            t.eq(store.getById(id).get("bar"), "bar2", 
     229                 "featuremodified event causes update of record property \"bar\""); 
     230 
     231            // update 
     232            record = store.getById(id); 
     233            record.set("foo", "foo3"); 
     234            record.set("bar", "bar3"); 
     235 
     236            t.eq(layer.getFeatureById(id).attributes.foo, "foo3", 
     237                 "update event causes update of feature property \"foo\""); 
     238 
     239            t.eq(layer.getFeatureById(id).attributes.bar, "bar3", 
     240                 "update event causes update of feature property \"bar\""); 
     241 
     242         } 
     243    </script>  
     244  
     245  <body>  
     246    <div id="map"></div>  
     247  </body>  
     248</html>  
     249 
  • geoext/tests/list-tests.html

    old new  
    11<ul id="testlist"> 
    22  <li>lib/GeoExt/data/FeatureRecord.html</li> 
    33  <li>lib/GeoExt/data/FeatureReader.html</li> 
    4   <li>lib/GeoExt/data/FeatureStoreMediator.html</li> 
     4  <li>lib/GeoExt/data/FeatureStore.html</li> 
    55  <li>lib/GeoExt/data/LayerRecord.html</li> 
    66  <li>lib/GeoExt/data/LayerReader.html</li> 
    77  <li>lib/GeoExt/data/LayerStore.html</li> 
    8   <li>lib/GeoExt/data/LayerStoreMediator.html</li> 
    98  <li>lib/GeoExt/data/ProtocolProxy.html</li> 
    109  <li>lib/GeoExt/widgets/MapPanel.html</li> 
    1110  <li>lib/GeoExt/widgets/Popup.html</li> 
  • geoext/lib/GeoExt.js

    old new  
    6060        var jsfiles = new Array( 
    6161            "GeoExt/data/FeatureRecord.js", 
    6262            "GeoExt/data/FeatureReader.js", 
    63             "GeoExt/data/FeatureStoreMediator.js", 
     63            "GeoExt/data/FeatureStore.js", 
    6464            "GeoExt/data/LayerRecord.js", 
    6565            "GeoExt/data/LayerReader.js", 
    6666            "GeoExt/data/LayerStore.js", 
    67             "GeoExt/data/LayerStoreMediator.js", 
    6867            "GeoExt/data/ProtocolProxy.js", 
    6968            "GeoExt/widgets/MapPanel.js", 
    7069            "GeoExt/widgets/Popup.js" 
  • geoext/lib/GeoExt/data/FeatureStore.js

    old new  
     1/* Copyright (C) 2008-2009 The Open Source Geospatial Foundation ¹ 
     2 * Published under the BSD license. 
     3 * See http://geoext.org/svn/geoext/core/trunk/license.txt for the full text 
     4 * of the license. 
     5 *  
     6 * ¹ pending approval */ 
     7 
     8/** 
     9 * @include GeoExt/data/FeatureReader.js 
     10 */ 
     11 
     12Ext.namespace("GeoExt.data"); 
     13 
     14/** 
     15 * Class: GeoExt.data.FeatureStoreMixin 
     16 * A store that synchronizes a features array of an {OpenLayers.Layer.Vector} with a 
     17 * feature store holding {<GeoExt.data.FeatureRecord>} entries. 
     18 *  
     19 * This class can not be instantiated directly. Instead, it is meant to extend 
     20 * {Ext.data.Store} or a subclass of it: 
     21 * (start code) 
     22 * var store = new (Ext.extend(Ext.data.Store, GeoExt.data.FeatureStoreMixin))({ 
     23 *     layer: myLayer, 
     24 *     features: myFeatures 
     25 * }); 
     26 * (end) 
     27 *  
     28 * For convenience, a {<GeoExt.data.FeatureStore>} class is available as a 
     29 * shortcut to the Ext.extend sequence in the above code snippet. The above 
     30 * is equivalent to: 
     31 * (start code) 
     32 * var store = new GeoExt.data.FeatureStore({ 
     33 *     layer: myLayer, 
     34 *     features: myFeatures 
     35 * }); 
     36 * (end) 
     37 */ 
     38GeoExt.data.FeatureStoreMixin = { 
     39    /** 
     40     * APIProperty: layer 
     41     * {OpenLayers.Layer.Vector} Layer that this store will be in sync with. 
     42     */ 
     43    layer: null, 
     44 
     45    /** 
     46     * Property: reader 
     47     * {<GeoExt.data.FeatureReader>} The reader used to get 
     48     *     <GeoExt.data.FeatureRecord> objects from {OpenLayers.Feature.Vector} 
     49     *     objects. 
     50     */ 
     51    reader: null, 
     52 
     53    /** 
     54     * APIProperty: featureFilter 
     55     * {Function} This function is called before a feature record is added to 
     56     *     the store, it receives the feature from which a feature record is 
     57     *     to be created, if it returns false then no record is added. 
     58     */ 
     59    featureFilter: function(feature) {}, 
     60     
     61    /** 
     62     * APIProperty: recordFilter 
     63     * {Function} This function is called before a feature is added to the 
     64     *     layer, it receives the feature record associated with the feature 
     65     *     to be added, if it returns false then no feature is added. 
     66     */ 
     67    recordFilter: function(record) {}, 
     68 
     69    /** 
     70     * Constructor: GeoExt.data.FeatureStoreMixin 
     71     *  
     72     * Parameters: 
     73     * config - {Object} 
     74     *  
     75     * Valid config options: 
     76     * layer - {OpenLayers.Layer.Vector} layer to sync the feature store with. 
     77     * features - {Array(OpenLayers.Feature.Vector)} Features that will be added to the 
     78     *     feature store (and the layer, because we are already syncing). 
     79     * recordType - {<GeoExt.data.FeatureRecord>} If provided, a custom feature 
     80     *     record type with additional fields will be used. Default fields for 
     81     *     every feature record are {OpenLayers.Feature.Vector} feature and {String} title. 
     82     * initDir - {Number} Bitfields specifying the direction to use for the 
     83     *     initial sync between the layer and the store, if set to 0 then no 
     84     *     initial sync is done. Defaults to 
     85     *     <GeoExt.data.FeatureStore.LAYER_TO_STORE>|<GeoExt.data.FeatureStore.STORE_TO_LAYER>. 
     86     */ 
     87    constructor: function(config) { 
     88        config = config || {}; 
     89        config.reader = config.reader || 
     90                        new GeoExt.data.FeatureReader({}, config.recordType); 
     91        var layer = config.layer; 
     92        delete config.layer; 
     93        // 'features' option - is an alias 'data' option 
     94        if (config.features) { 
     95            config.data = config.features; 
     96        } 
     97        delete config.features; 
     98        // "initDir" option 
     99        var options = {initDir: config.initDir}; 
     100        delete config.initDir; 
     101        arguments.callee.superclass.constructor.call(this, config); 
     102        if(layer) { 
     103            this.bind(layer, options); 
     104        } 
     105    }, 
     106 
     107    /** 
     108     * APIMethod: bind 
     109     * Bind this store to a layer instance, once bound the store 
     110     * is synchronized with the layer and vice-versa. 
     111     *  
     112     * Parameters: 
     113     * layer - {OpenLayers.Layer.Vector} The layer instance. 
     114     * options - {Object} 
     115     * 
     116     * Valid config options: 
     117     * initDir - {Number} Bitfields specifying the direction to use for the 
     118     *     initial sync between the layer and the store, if set to 0 then no 
     119     *     initial sync is done. Defaults to 
     120     *     <GeoExt.data.FeatureStore.LAYER_TO_STORE>|<GeoExt.data.FeatureStore.STORE_TO_LAYER>. 
     121     */ 
     122    bind: function(layer, options) { 
     123        if(this.layer) { 
     124            // already bound 
     125            return; 
     126        } 
     127        this.layer = layer; 
     128        options = options || {}; 
     129 
     130        var initDir = options.initDir; 
     131        if(options.initDir == undefined) { 
     132            initDir = GeoExt.data.FeatureStore.LAYER_TO_STORE | 
     133                      GeoExt.data.FeatureStore.STORE_TO_LAYER; 
     134        } 
     135 
     136        // create a snapshot of the layer's features 
     137        var features = layer.features.slice(0); 
     138 
     139        if(initDir & GeoExt.data.FeatureStore.STORE_TO_LAYER) { 
     140            var records = this.getRange(); 
     141            for(var i=records.length - 1; i>=0; i--) { 
     142                this.layer.addFeatures([records[i].get("feature")]); 
     143            } 
     144        } 
     145 
     146        if(initDir & GeoExt.data.FeatureStore.LAYER_TO_STORE) { 
     147            this.loadData(features, true /* append */); 
     148        } 
     149 
     150        layer.events.on({ 
     151            "featuresadded": this.onFeaturesAdded, 
     152            "featuresremoved": this.onFeaturesRemoved, 
     153            "featuremodified": this.onFeatureModified, 
     154            scope: this 
     155        }); 
     156        this.on({ 
     157            "load": this.onLoad, 
     158            "clear": this.onClear, 
     159            "add": this.onAdd, 
     160            "remove": this.onRemove, 
     161            "update": this.onUpdate, 
     162            scope: this 
     163        }); 
     164    }, 
     165 
     166    /** 
     167     * APIMethod: unbind 
     168     * Unbind this store from the layer it is currently bound. 
     169     */ 
     170    unbind: function() { 
     171        if(this.layer) { 
     172            this.layer.events.un({ 
     173                "featuresadded": this.onFeaturesAdded, 
     174                "featuresremoved": this.onFeaturesRemoved, 
     175                "featuremodified": this.onFeatureModified, 
     176                scope: this 
     177            }); 
     178            this.un("load", this.onLoad, this); 
     179            this.un("clear", this.onClear, this); 
     180            this.un("add", this.onAdd, this); 
     181            this.un("remove", this.onRemove, this); 
     182            this.un("update", this.onUpdate, this); 
     183 
     184            this.layer = null; 
     185        } 
     186    }, 
     187    
     188    
     189    /** 
     190     * Method: onFeaturesAdded 
     191     * Handler for layer featuresadded event 
     192     *  
     193     * Parameters: 
     194     * evt - {Object} 
     195     */ 
     196    onFeaturesAdded: function(evt) { 
     197        if(!this._adding) { 
     198            var i, len, feature, features = evt.features, toAdd = []; 
     199            for(var i=0, len=features.length; i<len; i++) { 
     200                feature = features[i]; 
     201                if(this.featureFilter(feature) !== false) { 
     202                    toAdd.push(feature); 
     203                } 
     204            } 
     205            // add feature records to the store, when called with 
     206            // append true loadData triggers an "add" event and 
     207            // then a "load" event 
     208            this._adding = true; 
     209            this.loadData(toAdd, true /* append */); 
     210            delete this._adding; 
     211        } 
     212    }, 
     213     
     214    /** 
     215     * Method: onFeaturesRemoved 
     216     * Handler for layer featuresremoved event 
     217     *  
     218     * Parameters: 
     219     * evt - {Object} 
     220     */ 
     221    onFeaturesRemoved: function(evt){ 
     222        if(!this._removing) { 
     223            var features = evt.features, feature, record, i; 
     224            for(i=features.length - 1; i>=0; i--) { 
     225                feature = features[i]; 
     226                record = this.getById(feature.id); 
     227                if(record !== undefined) { 
     228                    this._removing = true; 
     229                    this.remove(record); 
     230                    delete this._removing; 
     231                } 
     232            } 
     233        } 
     234    }, 
     235 
     236    /** 
     237     * Method: onFeatureModified 
     238     * Handler for layer featuremodified event 
     239     * 
     240     * Parameters: 
     241     * evt - {Object} 
     242     */ 
     243    onFeatureModified: function(evt) { 
     244        if(!this._updating) { 
     245            var feature = evt.feature; 
     246            var record = this.getById(feature.id); 
     247            if(record !== undefined) { 
     248                record.beginEdit(); 
     249                attributes = feature.attributes; 
     250                if(attributes) { 
     251                    var fields = this.recordType.prototype.fields; 
     252                    for(var i=0, len=fields.length; i<len; i++) { 
     253                        var field = fields.items[i]; 
     254                        var v = attributes[field.mapping || field.name] || 
     255                                field.defaultValue; 
     256                        v = field.convert(v); 
     257                        record.set(field.name, v); 
     258                    } 
     259                } 
     260                // the calls to set below won't trigger "update" 
     261                // events because we called beginEdit to start a 
     262                // "transaction", "update" will be triggered by 
     263                // endEdit 
     264                record.set("state", feature.state); 
     265                record.set("fid", feature.fid); 
     266                record.set("feature", feature); 
     267                this._updating = true; 
     268                record.endEdit(); 
     269                delete this._updating; 
     270            } 
     271        } 
     272    }, 
     273    
     274    /** 
     275     * Method: onLoad 
     276     * Handler for store load event 
     277     *  
     278     * Parameters: 
     279     * store - {Ext.data.Store} 
     280     * records - {Array(Ext.data.Record)} 
     281     * options - {Object} 
     282     */ 
     283    onLoad: function(store, records, options) { 
     284        // if options.add is true an "add" event was already 
     285        // triggered, and onAdd already did the work of  
     286        // adding the features to the layer. 
     287        if(!options || options.add !== true) { 
     288            this._removing = true; 
     289            this.layer.removeFeatures(this.layer.features); 
     290            delete this._removing; 
     291            var i, len, record, features = []; 
     292            for(i=0, len=records.length; i<len; i++) { 
     293                record = records[i]; 
     294                if(this.recordFilter(record) !== false) { 
     295                    features.push(record.get("feature")); 
     296                } 
     297            } 
     298            if(features.length > 0) { 
     299                this._adding = true; 
     300                this.layer.addFeatures(features); 
     301                delete this._adding; 
     302            } 
     303        } 
     304    }, 
     305     
     306    /** 
     307     * Method: onClear 
     308     * Handler for store clear event 
     309     *  
     310     * Parameters: 
     311     * store - {Ext.data.Store} 
     312     */ 
     313    onClear: function(store) { 
     314        this._removing = true; 
     315        this.layer.removeFeatures(this.layer.features); 
     316        delete this._removing; 
     317    }, 
     318     
     319    /** 
     320     * Method: onAdd 
     321     * Handler for store add event 
     322     *  
     323     * Parameters: 
     324     * store - {Ext.data.Store} 
     325     * records - {Array(Ext.data.Record)} 
     326     * index - {Number} 
     327     */ 
     328    onAdd: function(store, records, index) { 
     329        if(!this._adding) { 
     330            var i, len, record, features = []; 
     331            for(i=0, len=records.length; i<len; i++) { 
     332                record = records[i]; 
     333                if(this.recordFilter(record) !== false) { 
     334                    features.push(record.get("feature")); 
     335                } 
     336            } 
     337            if(features.length > 0) { 
     338                this._adding = true; 
     339                this.layer.addFeatures(features); 
     340                delete this._adding; 
     341            } 
     342        } 
     343    }, 
     344     
     345    /** 
     346     * Method: onRemove 
     347     * Handler for store remove event 
     348     *  
     349     * Parameters: 
     350     * store - {Ext.data.Store} 
     351     * records - {Array(Ext.data.Record)} 
     352     * index - {Number} 
     353     */ 
     354    onRemove: function(store, record, index){ 
     355        if(!this._removing) { 
     356            var feature = record.get("feature"); 
     357            if (this.layer.getFeatureById(feature.id) != null) { 
     358                this._removing = true; 
     359                this.layer.removeFeatures([record.get("feature")]); 
     360                delete this._removing; 
     361            } 
     362        } 
     363    }, 
     364 
     365    /** 
     366     * Method: onUpdate 
     367     * Handler for store update event 
     368     * 
     369     * Parameters: 
     370     * store - {Ext.data.Store} 
     371     * record - (Ext.data.Record)} 
     372     * operation - {String} 
     373     */ 
     374    onUpdate: function(store, record, operation) { 
     375        if(!this._updating) { 
     376            var feature = record.get("feature"); 
     377            if(record.fields) { 
     378                var cont = this.layer.events.triggerEvent( 
     379                    "beforefeaturemodified", {feature: feature} 
     380                ); 
     381                if(cont !== false) { 
     382                    record.fields.each( 
     383                        function(field) { 
     384                            feature.attributes[field.mapping || field.name] = 
     385                                record.get(field.name); 
     386                        } 
     387                    ); 
     388                    this._updating = true; 
     389                    this.layer.events.triggerEvent( 
     390                        "featuremodified", {feature: feature} 
     391                    ); 
     392                    delete this._updating; 
     393                    if (this.layer.getFeatureById(feature.id) != null) { 
     394                        this.layer.drawFeature(feature); 
     395                    } 
     396                } 
     397            } 
     398        } 
     399    } 
     400}; 
     401 
     402/** 
     403 * Class: GeoExt.data.FeatureStore 
     404 * Default implementation of an {Ext.data.Store} extended with 
     405 * {<GeoExt.data.FeatureStoreMixin>} 
     406 *  
     407 * Inherits from: 
     408 * - {Ext.data.Store} 
     409 * - {<GeoExt.data.FeatureStoreMixin>} 
     410 */ 
     411/** 
     412 * Constructor: GeoExt.data.FeatureStore 
     413 *  
     414 * Parameters: 
     415 * config - {Object} See {<GeoExt.data.FeatureStoreMixin>} and  
     416 * http://extjs.com/deploy/dev/docs/?class=Ext.data.Store for valid config 
     417 *     options.  
     418 */ 
     419GeoExt.data.FeatureStore = Ext.extend( 
     420    Ext.data.Store, 
     421    GeoExt.data.FeatureStoreMixin 
     422); 
     423 
     424/** 
     425 * Constant: GeoExt.data.FeatureStore.LAYER_TO_STORE 
     426 * {Integer} Constant used to make the store be automatically updated 
     427 * when changes occur in the layer. 
     428 */ 
     429GeoExt.data.FeatureStore.LAYER_TO_STORE = 1; 
     430 
     431/** 
     432 * Constant: GeoExt.data.FeatureStore.STORE_TO_LAYER 
     433 * {Integer} Constant used to make the layer be automatically updated 
     434 * when changes occur in the store. 
     435 */ 
     436GeoExt.data.FeatureStore.STORE_TO_LAYER = 2; 
  • geoext/lib/GeoExt/data/FeatureStoreMediator.js

    old new  
    1 /* 
    2  * Copyright (C) 2008 Eric Lemoine, Camptocamp France SAS 
    3  * 
    4  * This file is part of GeoExt 
    5  * 
    6  * GeoExt is free software: you can redistribute it and/or modify 
    7  * it under the terms of the GNU General Public License as published by 
    8  * the Free Software Foundation, either version 3 of the License, or 
    9  * (at your option) any later version. 
    10  * 
    11  * GeoExt is distributed in the hope that it will be useful, 
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    14  * GNU General Public License for more details. 
    15  * 
    16  * You should have received a copy of the GNU General Public License 
    17  * along with GeoExt.  If not, see <http://www.gnu.org/licenses/>. 
    18  */ 
    19  
    20 /** 
    21  * @requires GeoExt/data/FeatureReader.js 
    22  */ 
    23  
    24 Ext.namespace('GeoExt', 'GeoExt.data'); 
    25  
    26 /** 
    27  * Class: GeoExt.data.FeatureStoreMediator 
    28  * This class is to be used when one wants to insert features in a store. 
    29  * 
    30  * Usage example: 
    31  * (start code) 
    32  * var store = new Ext.data.Store({ 
    33  *     reader: new GeoExt.data.FeatureReader( 
    34  *         {}, [{name: "name", type: "string"}] 
    35  *     ) 
    36  * }); 
    37  * var mediator = new GeoExt.data.FeatureStoreMediator({ 
    38  *     store: store, 
    39  *     append: false, 
    40  *     filter: function(feature) { 
    41  *         return feature.state != OpenLayers.State.UNKNOWN; 
    42  *     } 
    43  * }); 
    44  * (end) 
    45  */ 
    46  
    47 /** 
    48  * Constructor: GeoExt.data.FeatureStoreMediator 
    49  * Create an instance of GeoExt.data.FeatureStoreMediator 
    50  * 
    51  * Parameters: 
    52  * config - {Object} A config object used to set the feature 
    53  *     store mediator's properties, see below for the list 
    54  *     of supported properties. 
    55  * 
    56  * Returns: 
    57  * {<GeoExt.data.FeatureStoreMediator>} 
    58  */ 
    59 GeoExt.data.FeatureStoreMediator = function(config){ 
    60     Ext.apply(this, config); 
    61     if (!this.store) { 
    62         OpenLayers.Console.error( 
    63             "store is missing in the config"); 
    64     } 
    65     if (!(this.store.reader instanceof GeoExt.data.FeatureReader)) { 
    66         OpenLayers.Console.error( 
    67             "store does not use a FeatureReader"); 
    68     } 
    69 }; 
    70  
    71 GeoExt.data.FeatureStoreMediator.prototype = { 
    72     /** 
    73      * APIProperty: store 
    74      * {Ext.data.Store} An Ext data store 
    75      */ 
    76     store: null, 
    77  
    78     /** 
    79      * APIProperty: append 
    80      * {Boolean} False if the store must be cleared before adding new 
    81      * features into it, false otherwise; defaults to true. 
    82      */ 
    83     append: true, 
    84  
    85     /** 
    86      * APIProperty: filter 
    87      * {Function} a filter function called for each feature to be 
    88      * inserted, the feature is passed as an argument to the function, 
    89      * if it returns true the feature is inserted into the store, 
    90      * otherwise the feature is not inserted. 
    91      */ 
    92     filter: null, 
    93  
    94     /** 
    95      * APIMethod: addFeatures 
    96      *      Add features to the store. 
    97      *  
    98      * Parameters: 
    99      * features - {<OpenLayers.Feature.Vector>} or 
    100      *     {Array{<OpenLayers.Feature.Vector>}} A feature or an 
    101      *     array of features to add to the store. 
    102      * config - a config object which can include the properties 
    103      *     "append" and "filter", if set these properties will 
    104      *     override that set in the object. 
    105      */ 
    106     addFeatures: function(features, config) { 
    107         if (!Ext.isArray(features)) { 
    108             features = [features]; 
    109         } 
    110         config = OpenLayers.Util.applyDefaults(config, 
    111             {append: this.append, filter: this.filter}); 
    112         var toAdd = features; 
    113         if (config.filter) { 
    114             toAdd = []; 
    115             var feature; 
    116             for (var i = 0, len = features.length; i < len; i++) { 
    117                 feature = features[i]; 
    118                 if (config.filter(feature)) { 
    119                     toAdd.push(feature); 
    120                 } 
    121             } 
    122         } 
    123         // because of a bug in Ext if config.append is false we clean 
    124         // the store ourself and always pass true to loadData, there 
    125         // are cases where passing false to loadData results in Ext 
    126         // trying to dereference an undefined value, see the unit 
    127         // tests test_ExtBug and text_addFeatures_ExtBug for  
    128         // concrete examples 
    129         if (!config.append) { 
    130             this.store.removeAll(); 
    131         } 
    132         this.store.loadData(toAdd, true); 
    133     }, 
    134  
    135     /** 
    136      * APIMethod: removeFeatures 
    137      *      Remove features from the store. 
    138      * 
    139      * Parameters: 
    140      * features - {<OpenLayers.Feature.Vector>} or 
    141      *      {Array{<OpenLayers.Feature.Vector>}} A feature or an 
    142      *      array of features to remove from the store. If null 
    143      *      all the features in the store are removed. 
    144      */ 
    145     removeFeatures: function(features) { 
    146         if (!features) { 
    147             this.store.removeAll(); 
    148         } else { 
    149             if (!Ext.isArray(features)) { 
    150                 features = [features]; 
    151             } 
    152             for (var i = 0, len = features.length; i < len; i++) { 
    153                 var feature = features[i]; 
    154                 var r = this.store.getById(feature.id); 
    155                 if (r !== undefined) { 
    156                     this.store.remove(r); 
    157                 } 
    158             } 
    159         } 
    160     } 
    161 }; 
  • geoext/lib/GeoExt/data/LayerStoreMediator.js

    old new  
    1 /* 
    2  * Copyright (C) 2008 Eric Lemoine, Camptocamp France SAS 
    3  * 
    4  * This file is part of GeoExt 
    5  * 
    6  * GeoExt is free software: you can redistribute it and/or modify 
    7  * it under the terms of the GNU General Public License as published by 
    8  * the Free Software Foundation, either version 3 of the License, or 
    9  * (at your option) any later version. 
    10  * 
    11  * GeoExt is distributed in the hope that it will be useful, 
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    14  * GNU General Public License for more details. 
    15  * 
    16  * You should have received a copy of the GNU General Public License 
    17  * along with GeoExt.  If not, see <http://www.gnu.org/licenses/>. 
    18  */ 
    19  
    20 /** 
    21  * @requires GeoExt/data/FeatureStoreMediator.js 
    22  */ 
    23  
    24 Ext.namespace('GeoExt', 'GeoExt.data'); 
    25  
    26 /** 
    27  * Class: GeoExt.data.LayerStoreMediator 
    28  * 
    29  * This class is to be used when one wants to insert, remove, and 
    30  * update features in a grid as a result of features being inserted, 
    31  * removed, modified in a vector layer. 
    32  * 
    33  * Usage example: 
    34  * (start code) 
    35  * var layer = new OpenLayers.Layer.Vector("vector"); 
    36  * var store = new Ext.data.Store({ 
    37  *     reader: new GeoExt.data.FeatureReader( 
    38  *         {}, [{name: "name", type: "string"}] 
    39  *     ) 
    40  * }); 
    41  * var mediator = new GeoExt.data.LayerStoreMediator({ 
    42  *     store: store, 
    43  *     filter: function(feature) { 
    44  *         return feature.state != OpenLayers.State.UNKNOWN; 
    45  *     } 
    46  * }); 
    47  * (end) 
    48  */ 
    49  
    50 /** 
    51  * Constructor: GeoExt.data.LayerStoreMediator 
    52  * Create an instance of GeoExt.data.LayerStoreMediator. 
    53  * 
    54  * Parameters: 
    55  * config - {Object} A config object used to set the layer 
    56  *     store mediator's properties (see below for the list 
    57  *     of supported properties), and configure it with the 
    58  *     Ext store; see the usage example above. 
    59  * 
    60  * Returns: 
    61  * {<GeoExt.data.LayerStoreMediator>} 
    62  */ 
    63 GeoExt.data.LayerStoreMediator = function(config) { 
    64     var store = config.store; 
    65     // no need to place the store in the instance 
    66     delete config.store; 
    67     Ext.apply(this, config); 
    68     if (!this.layer) { 
    69         OpenLayers.Console.error( 
    70             "layer is missing in config"); 
    71     } 
    72     this.featureStoreMediator = new GeoExt.data.FeatureStoreMediator({ 
    73         store: store 
    74     }); 
    75     if (this.autoActivate) { 
    76         this.activate(); 
    77     } 
    78 }; 
    79  
    80 GeoExt.data.LayerStoreMediator.prototype = { 
    81     /** 
    82      * APIProperty: layer 
    83      * {<OpenLayers.Layer.Vector>} The vector layer. 
    84      */ 
    85     layer: null, 
    86  
    87     /** 
    88      * APIProperty: filter 
    89      * {Function} a filter function called for each feature to be 
    90      * inserted, the feature is passed as an argument to the function, 
    91      * if it returns true the feature is inserted into the store, 
    92      * otherwise the feature is not inserted. 
    93      */ 
    94     filter: null, 
    95  
    96     /** 
    97      * APIProperty: autoActivate 
    98      * {Boolean} True if the mediator must be activated as part of 
    99      * its creation, false otherwise; if false then the mediator must 
    100      * be explicitely activate using the activate method; defaults 
    101      * to true. 
    102      */ 
    103     autoActivate: true, 
    104  
    105     /** 
    106      * Property: active 
    107      * {Boolean} 
    108      */ 
    109     active: false, 
    110  
    111     /** 
    112      * Property: featureStoreMediator 
    113      * {<GeoExt.data.featureStoreMediator>} An internal 
    114      * feature store mediator for manually adding features to the 
    115      * Ext store. 
    116      */ 
    117     featureStoreMediator: null, 
    118  
    119     /** 
    120      * APIMethod: activate 
    121      * Activate the mediator. 
    122      * 
    123      * Returns: 
    124      * {Boolean} - False if the mediator was already active, true 
    125      * otherwise. 
    126      */ 
    127     activate: function() { 
    128         if (!this.active) { 
    129             this.layer.events.on({ 
    130                 featuresadded: this.update, 
    131                 featuresremoved: this.update, 
    132                 featuremodified: this.update, 
    133                 scope: this 
    134             }); 
    135             this.active = true; 
    136             return true; 
    137         } 
    138         return false; 
    139     }, 
    140  
    141     /** 
    142      * APIMethod: deactivate 
    143      * Deactivate the mediator. 
    144      * 
    145      * Returns: 
    146      * {Boolean} - False if the mediator was already deactive, true 
    147      * otherwise. 
    148      */ 
    149     deactivate: function() { 
    150         if (this.active) { 
    151             this.layer.events.un({ 
    152                 featuresadded: this.update, 
    153                 featuresremoved: this.update, 
    154                 featuremodified: this.update, 
    155                 scope: this 
    156             }); 
    157             return true; 
    158         } 
    159         return false; 
    160     }, 
    161  
    162     /** 
    163      * Method: update 
    164      *      Called when features are added, removed or modified. This 
    165      *      function empties the store, loops over the features in 
    166      *      the layer, and for each feature calls the user-defined 
    167      *      filter function, if the return value of the filter function 
    168      *      evaluates to true the feature is added to the store. 
    169      */ 
    170     update: function() { 
    171         this.featureStoreMediator.addFeatures( 
    172             this.layer.features, 
    173             {append: false, filter: this.filter}); 
    174     } 
    175 };