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

File patch-18-r371-C0.diff, 45.8 kB (added by elemoine, 1 year ago)
  • 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 
  • 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> 
  • 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> 
  • 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(4); 
     32             
     33            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     34            var store = new GeoExt.data.FeatureStore({ 
     35                layer: layer 
     36            }); 
     37 
     38            store.loadData([ 
     39                new OpenLayers.Feature.Vector(), 
     40                new OpenLayers.Feature.Vector() 
     41            ]); 
     42            t.eq(layer.features.length, 2, "loading two records in the store with 'loadData' adds two features to the layer"); 
     43            t.eq(store.getCount(), 2, 'loading two records in the store with "loadData" does not create duplicate records in store');  
     44 
     45            store.removeAll(); 
     46            t.eq(store.getCount(), 0, '"removeAll" on store removes all records from the store');  
     47            t.eq(layer.features.length, 0, '"removeAll" on store removes features from layer');  
     48        } 
     49         
     50        function test_bind_unbind(t) { 
     51            t.plan(28); 
     52             
     53            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     54            var store = new GeoExt.data.FeatureStore(); 
     55            var features = [new OpenLayers.Feature.Vector("Foo feature"), 
     56                          new OpenLayers.Feature.Vector("Bar feature")]; 
     57            var records = [ 
     58                new GeoExt.data.FeatureRecord({ 
     59                    feature: new OpenLayers.Feature.Vector("Foo record")}), 
     60                new GeoExt.data.FeatureRecord({ 
     61                    feature: new OpenLayers.Feature.Vector("Bar record")}) 
     62            ]; 
     63 
     64            var reinit_test_data = function () { 
     65                // unbind store 
     66                store.unbind(); 
     67 
     68                // remove all existing records and features 
     69                store.removeAll(); 
     70                layer.removeFeatures(layer.features); 
     71                t.eq(layer.features.length, 0, "there is no more features in the layer"); 
     72                t.eq(store.getCount(), 0, "there is no more records in the store"); 
     73 
     74                // add testing data to store and layer 
     75                store.add(records); 
     76                layer.addFeatures(features); 
     77                t.eq(layer.features.length, 2, "initial features are loaded in the layer"); 
     78                t.eq(store.getCount(), 2, "initial records are loaded in the store"); 
     79            }; 
     80             
     81            // test store to layer synchronization 
     82            reinit_test_data(); 
     83            store.bind(layer, {initDir: GeoExt.data.FeatureStore.STORE_TO_LAYER}); 
     84            t.eq(layer.features.length, 4, "initial records are synchronized to layer"); 
     85            t.eq(store.getCount(), 2, "initial features are not synchronized to store"); 
     86            layer.removeFeatures([features[0]]); 
     87            t.eq(layer.features.length, 3, "removing feature not present in store has been well removed"); 
     88            t.eq(store.getCount(), 2, "nothing to remove in store when removing feature not present in store"); 
     89 
     90            // test layer to store synchronization 
     91            reinit_test_data(); 
     92            store.bind(layer, {initDir: GeoExt.data.FeatureStore.LAYER_TO_STORE}); 
     93            t.eq(layer.features.length, 2, "initial records are not synchronized to layer"); 
     94            t.eq(store.getCount(), 4, "initial features are synchronized to store"); 
     95            store.remove(records[0]); 
     96            t.eq(store.getCount(), 3, "removing record not present in layer has been well removed"); 
     97            t.eq(layer.features.length, 2, "nothing to remove in layer when removing record not present in layer"); 
     98 
     99            // test both synchronization 
     100            reinit_test_data(); 
     101            store.bind(layer, {initDir: GeoExt.data.FeatureStore.LAYER_TO_STORE | 
     102                                      GeoExt.data.FeatureStore.STORE_TO_LAYER}); 
     103            t.eq(layer.features.length, 4, "initial records are synchronized to layer"); 
     104            t.eq(store.getCount(), 4, "initial features are synchronized to store"); 
     105 
     106            // test no synchronization 
     107            reinit_test_data(); 
     108            store.bind(layer, {initDir: 0}); 
     109            t.eq(layer.features.length, 2, "initial records are not synchronized to layer"); 
     110            t.eq(store.getCount(), 2, "initial features are not synchronized to store"); 
     111        } 
     112 
     113        function test_add_remove(t) { 
     114             
     115            t.plan(4); 
     116             
     117            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     118            var store = new GeoExt.data.FeatureStore({ 
     119                layer: layer 
     120            }); 
     121            var record = new GeoExt.data.FeatureRecord({ 
     122                feature: new OpenLayers.Feature.Vector() 
     123            }); 
     124 
     125            store.add([record]); 
     126            t.eq(store.getCount(), 1, 'Adding a record to store with "add" does not create duplicate record in store');  
     127            t.eq(layer.features.length, 1, 'Adding a record to store with "add" does create correspondant feature in layer');  
     128             
     129            store.remove(record); 
     130            t.eq(store.getCount(), 0, 'remove on store with "remove" removes the record from the store');  
     131            t.eq(layer.features.length, 0, 'remove on store with "remove" removes the correspondant feature from layer');  
     132        } 
     133         
     134        function test_addFeatures_removeFeatures(t) { 
     135             
     136            t.plan(4); 
     137             
     138            var features = [  
     139                new OpenLayers.Feature.Vector(),  
     140                new OpenLayers.Feature.Vector()  
     141            ];  
     142            var layer = new OpenLayers.Layer.Vector("Foo layer"); 
     143            var store = new GeoExt.data.FeatureStore({ 
     144                layer: layer 
     145            }); 
     146 
     147            // test layer addFeatures 
     148            layer.addFeatures(features); 
     149            t.eq(layer.features.length, 2, 'Adding features to layer with "addFeatures" does not create duplicate features on the layer'); 
     150            t.eq(store.getCount(), 2, 'Adding features to layer with "addFeatures" does create correspondant records in the store'); 
     151 
     152            // test layer removeFeatures 
     153            layer.removeFeatures(layer.features); 
     154            t.eq(store.getCount(), 0, '"removeFeatures" on layer removes records from the store');  
     155            t.eq(layer.features.length, 0, '"removeFeatures" on layer removes features from layer'); 
     156        } 
     157 
     158        function test_featuremodified_update(t) { 
     159            t.plan(6); 
     160 
     161            /* 
     162             * Set up 
     163             */ 
     164            var feature, id, layer, store, recordType, record; 
     165 
     166            feature = new OpenLayers.Feature.Vector(null, { 
     167                foo: "foo", 
     168                bar: "bar" 
     169            }); 
     170 
     171            id = feature.id; 
     172 
     173            recordType = GeoExt.data.FeatureRecord.create([ 
     174                {name: "foo"}, {name: "bar"} 
     175            ]); 
     176 
     177            layer = new OpenLayers.Layer.Vector("vector"); 
     178 
     179            store = new GeoExt.data.FeatureStore({ 
     180                layer: layer, 
     181                recordType: recordType, 
     182                data: [feature] 
     183            }); 
     184 
     185            t.eq(store.getById(id).get("foo"), "foo", 
     186                 "record gets correct initial value for property \"foo\""); 
     187 
     188            t.eq(store.getById(id).get("bar"), "bar", 
     189                 "record gets correct initial value for property \"bar\""); 
     190 
     191            /* 
     192             * Test 
     193             */ 
     194             
     195            // featuremodified 
     196            feature.attributes.foo = "foo2"; 
     197            feature.attributes.bar = "bar2"; 
     198            layer.events.triggerEvent("featuremodified", {feature: feature}); 
     199 
     200            t.eq(store.getById(id).get("foo"), "foo2", 
     201                 "featuremodified event causes update of record property \"foo\""); 
     202 
     203            t.eq(store.getById(id).get("bar"), "bar2", 
     204                 "featuremodified event causes update of record property \"bar\""); 
     205 
     206            // update 
     207            record = store.getById(id); 
     208            record.set("foo", "foo3"); 
     209            record.set("bar", "bar3"); 
     210 
     211            t.eq(layer.getFeatureById(id).attributes.foo, "foo3", 
     212                 "update event causes update of feature property \"foo\""); 
     213 
     214            t.eq(layer.getFeatureById(id).attributes.bar, "bar3", 
     215                 "update event causes update of feature property \"bar\""); 
     216 
     217         } 
     218    </script>  
     219  
     220  <body>  
     221    <div id="map"></div>  
     222  </body>  
     223</html>  
     224 
  • 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> 
  • 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" 
  • 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     * Constructor: GeoExt.data.FeatureStoreMixin 
     55     *  
     56     * Parameters: 
     57     * config - {Object} 
     58     *  
     59     * Valid config options: 
     60     * layer - {OpenLayers.Layer.Vector} layer to sync the feature store with. 
     61     * features - {Array(OpenLayers.Feature.Vector)} Features that will be added to the 
     62     *     feature store (and the layer, because we are already syncing). 
     63     * recordType - {<GeoExt.data.FeatureRecord>} If provided, a custom feature 
     64     *     record type with additional fields will be used. Default fields for 
     65     *     every feature record are {OpenLayers.Feature.Vector} feature and {String} title. 
     66     * initDir - {Number} Bitfields specifying the direction to use for the 
     67     *     initial sync between the layer and the store, if set to 0 then no 
     68     *     initial sync is done. Defaults to 
     69     *     <GeoExt.data.FeatureStore.LAYER_TO_STORE>|<GeoExt.data.FeatureStore.STORE_TO_LAYER>. 
     70     */ 
     71    constructor: function(config) { 
     72        config = config || {}; 
     73        config.reader = config.reader || 
     74                        new GeoExt.data.FeatureReader({}, config.recordType); 
     75        var layer = config.layer; 
     76        delete config.layer; 
     77        // 'features' option - is an alias 'data' option 
     78        if (config.features) { 
     79            config.data = config.features; 
     80        } 
     81        delete config.features; 
     82        // "initDir" option 
     83        var options = {initDir: config.initDir}; 
     84        delete config.initDir; 
     85        arguments.callee.superclass.constructor.call(this, config); 
     86        if(layer) { 
     87            this.bind(layer, options); 
     88        } 
     89    }, 
     90 
     91    /** 
     92     * APIMethod: bind 
     93     * Bind this store to a layer instance, once bound the store 
     94     * is synchronized with the layer and vice-versa. 
     95     *  
     96     * Parameters: 
     97     * layer - {OpenLayers.Layer.Vector} The layer instance. 
     98     * options - {Object} 
     99     * 
     100     * Valid config options: 
     101     * initDir - {Number} Bitfields specifying the direction to use for the 
     102     *     initial sync between the layer and the store, if set to 0 then no 
     103     *     initial sync is done. Defaults to 
     104     *     <GeoExt.data.FeatureStore.LAYER_TO_STORE>|<GeoExt.data.FeatureStore.STORE_TO_LAYER>. 
     105     */ 
     106    bind: function(layer, options) { 
     107        if(this.layer) { 
     108            // already bound 
     109            return; 
     110        } 
     111        this.layer = layer; 
     112        options = options || {}; 
     113 
     114        var initDir = options.initDir; 
     115        if(options.initDir == undefined) { 
     116            initDir = GeoExt.data.FeatureStore.LAYER_TO_STORE | 
     117                      GeoExt.data.FeatureStore.STORE_TO_LAYER; 
     118        } 
     119 
     120        // create a snapshot of the layer's features 
     121        var features = layer.features.slice(0); 
     122 
     123        if(initDir & GeoExt.data.FeatureStore.STORE_TO_LAYER) { 
     124            var records = this.getRange(); 
     125            for(var i=records.length - 1; i>=0; i--) { 
     126                this.layer.addFeatures([records[i].get("feature")]); 
     127            } 
     128        } 
     129        if(initDir & GeoExt.data.FeatureStore.LAYER_TO_STORE) { 
     130            this.loadData(features, true); 
     131        } 
     132 
     133        layer.events.on({ 
     134            "featuresadded": this.onFeaturesAdded, 
     135            "featuresremoved": this.onFeaturesRemoved, 
     136            "featuremodified": this.onFeatureModified, 
     137            scope: this 
     138        }); 
     139        this.on({ 
     140            "load": this.onLoad, 
     141            "clear": this.onClear, 
     142            "add": this.onAdd, 
     143            "remove": this.onRemove, 
     144            "update": this.onUpdate, 
     145            scope: this 
     146        }); 
     147    }, 
     148 
     149    /** 
     150     * APIMethod: unbind 
     151     * Unbind this store from the layer it is currently bound. 
     152     */ 
     153    unbind: function() { 
     154        if(this.layer) { 
     155            this.layer.events.un({ 
     156                "featuresadded": this.onFeaturesAdded, 
     157                "featuresremoved": this.onFeaturesRemoved, 
     158                "featuremodified": this.onFeatureModified, 
     159                scope: this 
     160            }); 
     161            this.un("load", this.onLoad, this); 
     162            this.un("clear", this.onClear, this); 
     163            this.un("add", this.onAdd, this); 
     164            this.un("remove", this.onRemove, this); 
     165            this.un("update", this.onUpdate, this); 
     166 
     167            this.layer = null; 
     168        } 
     169    }, 
     170    
     171    
     172    /** 
     173     * Method: onFeaturesAdded 
     174     * Handler for layer featuresadded event 
     175     *  
     176     * Parameters: 
     177     * evt - {Object} 
     178     */ 
     179    onFeaturesAdded: function(evt) { 
     180        if(!this._adding) { 
     181            this._adding = true; 
     182            var features = evt.features; 
     183            this.loadData(features, true); 
     184            delete this._adding; 
     185        } 
     186    }, 
     187     
     188    /** 
     189     * Method: onFeaturesRemoved 
     190     * Handler for layer featuresremoved event 
     191     *  
     192     * Parameters: 
     193     * evt - {Object} 
     194     */ 
     195    onFeaturesRemoved: function(evt){ 
     196        if(!this._removing) { 
     197            this._removing = true; 
     198            var features = evt.features, feature, record, i; 
     199            for(i=features.length - 1; i>=0; i--) { 
     200                feature = features[i]; 
     201                record = this.getById(feature.id); 
     202                if(record !== undefined) { 
     203                    this.remove(record); 
     204                } 
     205            } 
     206            delete this._removing; 
     207        } 
     208    }, 
     209 
     210    /** 
     211     * Method: onFeatureModified 
     212     * Handler for layer featuremodified event 
     213     * 
     214     * Parameters: 
     215     * evt - {Object} 
     216     */ 
     217    onFeatureModified: function(evt) { 
     218        if(!this._updating) { 
     219            this._updating = true; 
     220            var feature = evt.feature; 
     221            var record = this.getById(feature.id); 
     222            if(record !== undefined) { 
     223                record.beginEdit(); 
     224                attributes = feature.attributes; 
     225                if(attributes) { 
     226                    var fields = this.recordType.prototype.fields; 
     227                    for(var i=0, len=fields.length; i<len; i++) { 
     228                        var field = fields.items[i]; 
     229                        var v = attributes[field.mapping || field.name] || 
     230                                field.defaultValue; 
     231                        v = field.convert(v); 
     232                        record.set(field.name, v); 
     233                    } 
     234                } 
     235                record.set("state", feature.state); 
     236                record.set("fid", feature.fid); 
     237                record.set("feature", feature); 
     238                record.endEdit(); 
     239            } 
     240            delete this._updating; 
     241        } 
     242    }, 
     243    
     244    /** 
     245     * Method: onLoad 
     246     * Handler for store load event 
     247     *  
     248     * Parameters: 
     249     * store - {Ext.data.Store} 
     250     * records - {Array(Ext.data.Record)} 
     251     * options - {Object} 
     252     */ 
     253    onLoad: function(store, records, options) { 
     254        if (options && !options.add) { 
     255            this._removing = true; 
     256            this.layer.removeFeatures(this.layer.features); 
     257            delete this._removing; 
     258 
     259            // features has already been added to layer on "add" event 
     260            var len = records.length; 
     261            if (len > 0) { 
     262                var features = new Array(len); 
     263                for (var j = 0; j < len; j++) { 
     264                    features[j] = records[j].get("feature"); 
     265                } 
     266                this._adding = true; 
     267                this.layer.addFeatures(features); 
     268                delete this._adding; 
     269            } 
     270        } 
     271    }, 
     272     
     273    /** 
     274     * Method: onClear 
     275     * Handler for store clear event 
     276     *  
     277     * Parameters: 
     278     * store - {Ext.data.Store} 
     279     */ 
     280    onClear: function(store) { 
     281        this._removing = true; 
     282        this.layer.removeFeatures(this.layer.features); 
     283        delete this._removing; 
     284    }, 
     285     
     286    /** 
     287     * Method: onAdd 
     288     * Handler for store add event 
     289     *  
     290     * Parameters: 
     291     * store - {Ext.data.Store} 
     292     * records - {Array(Ext.data.Record)} 
     293     * index - {Number} 
     294     */ 
     295    onAdd: function(store, records, index) { 
     296        if(!this._adding) { 
     297            var len = records.length; 
     298            if (len > 0) { 
     299                var features = new Array(len); 
     300                for (var j = 0; j < len; j++) { 
     301                    features[j] = records[j].get("feature"); 
     302                } 
     303                this._adding = true; 
     304                this.layer.addFeatures(features); 
     305                delete this._adding; 
     306            } 
     307        } 
     308    }, 
     309     
     310    /** 
     311     * Method: onRemove 
     312     * Handler for store remove event 
     313     *  
     314     * Parameters: 
     315     * store - {Ext.data.Store} 
     316     * records - {Array(Ext.data.Record)} 
     317     * index - {Number} 
     318     */ 
     319    onRemove: function(store, record, index){ 
     320        if(!this._removing) { 
     321            var feature = record.get("feature"); 
     322            if (this.layer.getFeatureById(feature.id) != null) { 
     323                this._removing = true; 
     324                this.layer.removeFeatures([record.get("feature")]); 
     325                delete this._removing; 
     326            } 
     327        } 
     328    }, 
     329 
     330    /** 
     331     * Method: onUpdate 
     332     * Handler for store update event 
     333     * 
     334     * Parameters: 
     335     * store - {Ext.data.Store} 
     336     * record - (Ext.data.Record)} 
     337     * operation - {String} 
     338     */ 
     339    onUpdate: function(store, record, operation) { 
     340        if(!this._updating) { 
     341            var feature = record.get("feature"); 
     342            if(record.fields) { 
     343                var cont = this.layer.events.triggerEvent( 
     344                    "beforefeaturemodified", {feature: feature} 
     345                ); 
     346                if(cont !== false) { 
     347                    record.fields.each( 
     348                        function(field) { 
     349                            feature.attributes[field.mapping || field.name] = 
     350                                record.get(field.name); 
     351                        } 
     352                    ); 
     353                    this._updating = true; 
     354                    this.layer.events.triggerEvent( 
     355                        "featuremodified", {feature: feature} 
     356                    ); 
     357                    delete this._updating; 
     358                    if (this.layer.getFeatureById(feature.id) != null) { 
     359                        this.layer.drawFeature(feature); 
     360                    } 
     361                } 
     362            } 
     363        } 
     364    } 
     365}; 
     366 
     367/** 
     368 * Class: GeoExt.data.FeatureStore 
     369 * Default implementation of an {Ext.data.Store} extended with 
     370 * {<GeoExt.data.FeatureStoreMixin>} 
     371 *  
     372 * Inherits from: 
     373 * - {Ext.data.Store} 
     374 * - {<GeoExt.data.FeatureStoreMixin>} 
     375 */ 
     376/** 
     377 * Constructor: GeoExt.data.FeatureStore 
     378 *  
     379 * Parameters: 
     380 * config - {Object} See {<GeoExt.data.FeatureStoreMixin>} and  
     381 * http://extjs.com/deploy/dev/docs/?class=Ext.data.Store for valid config 
     382 *     options.  
     383 */ 
     384GeoExt.data.FeatureStore = Ext.extend( 
     385    Ext.data.Store, 
     386    GeoExt.data.FeatureStoreMixin 
     387); 
     388 
     389/** 
     390 * Constant: GeoExt.data.FeatureStore.LAYER_TO_STORE 
     391 * {Integer} Constant used to make the store be automatically updated 
     392 * when changes occur in the layer. 
     393 */ 
     394GeoExt.data.FeatureStore.LAYER_TO_STORE = 1; 
     395 
     396/** 
     397 * Constant: GeoExt.data.FeatureStore.STORE_TO_LAYER 
     398 * {Integer} Constant used to make the layer be automatically updated 
     399 * when changes occur in the store. 
     400 */ 
     401GeoExt.data.FeatureStore.STORE_TO_LAYER = 2; 
  • 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 }; 
  • 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 };