OpenLayers OpenLayers

root/trunk/openlayers/tests/Control/ModifyFeature.html

Revision 8382, 21.2 kB (checked in by tschaub, 2 months ago)

Draw and modify controls now set feature state. No longer do we need to check feature state in app code in cases where features are created or modified with these controls. r=elemoine,ahocevar (closes #1833)

  • Property svn:eol-style set to native
Line 
1 <html>
2 <head>
3     <script src="../../lib/OpenLayers.js"></script>
4     <script type="text/javascript">
5    
6     function test_initialize(t) {
7         t.plan(3);
8         var layer = {
9             styleMap: {createSymbolizer: function(){}},
10             events: {
11                 on: function() {},
12                 un: function() {}
13             }
14         };
15         var options = {
16             geometryTypes: "bar"
17         };
18         var control = new OpenLayers.Control.ModifyFeature(layer, options);
19        
20         t.ok(control.layer == layer,
21              "constructor sets layer correctly");
22         t.eq(control.selectControl.geometryTypes, "bar",
23              "constructor sets options correctly on feature handler");
24         t.eq(control.mode, OpenLayers.Control.ModifyFeature.RESHAPE,
25              "constructor initializes modification mode correctly");
26         control.destroy();
27     }
28
29     function test_destroy(t) {
30         t.plan(2);
31         var map = new OpenLayers.Map("map");
32         var layer = new OpenLayers.Layer.Vector();
33         map.addLayer(layer);
34         var control = new OpenLayers.Control.ModifyFeature(layer);
35         control.selectControl.destroy = function() {
36             t.ok(true,
37                  "control.destroy calls destroy on select control");
38         }
39         control.dragControl.destroy = function() {
40             t.ok(true,
41                  "control.destroy calls destroy on feature handler");
42         }
43         control.destroy();
44         map.destroy();
45     }
46    
47     function test_activate(t) {
48         t.plan(2);
49         var map = new OpenLayers.Map("map");
50         var layer = new OpenLayers.Layer.Vector();
51         map.addLayer(layer);
52         var control = new OpenLayers.Control.ModifyFeature(layer);
53         map.addControl(control);
54         t.ok(!control.selectControl.active,
55              "select control is not active prior to activating control");
56         control.activate();
57         t.ok(control.selectControl.active,
58              "select control is active after activating control");
59
60         map.destroy();
61     }
62
63     function test_initDeleteCodes(t) {
64         t.plan(3);
65         var layer = new OpenLayers.Layer.Vector();
66         var control = new OpenLayers.Control.ModifyFeature(layer, {'deleteCodes': 46});
67         t.eq(control.deleteCodes[0], 46, "Delete code properly turned into an array.");
68         var control = new OpenLayers.Control.ModifyFeature(layer);
69         t.eq(control.deleteCodes[0], 46, "Default deleteCodes include delete");
70         t.eq(control.deleteCodes[1], 68, "Default deleteCodes include 'd'");
71        
72         control.destroy();
73         layer.destroy();
74     }
75    
76     function test_handleKeypress(t) {
77         t.plan(11);
78
79         /**
80          * There are two things that we want to test here
81          * 1) test that control.deleteCodes are respected
82          * 3) test that a vertex is properly deleted
83          *
84          * In the future, feature deletion may be added to the control.
85          */
86        
87         var layer = new OpenLayers.Layer.Vector();
88         var control = new OpenLayers.Control.ModifyFeature(layer);
89         var delKey = 46;
90         var dKey = 100;
91         control.deleteCodes = [delKey, dKey];
92        
93         // test that a polygon vertex is deleted for all delete codes
94         var point = new OpenLayers.Feature.Vector(
95             new OpenLayers.Geometry.Point()
96         );
97         var poly = new OpenLayers.Feature.Vector(
98             new OpenLayers.Geometry.Polygon()
99         );
100        
101         // mock up vertex deletion
102         control.dragControl.feature = point;
103         control.feature = poly;
104         control.vertices = [point];
105         point.geometry.parent = {
106             removeComponent: function(geometry) {
107                 t.eq(geometry.id, point.geometry.id,
108                      "vertex deletion: removeComponent called on parent with proper geometry");
109             }
110         };
111         layer.events.on({"featuremodified": function(event) {
112             t.eq(event.feature.id, poly.id, "vertex deletion: featuremodifed triggered");
113         }});
114         layer.drawFeature = function(feature) {
115             t.eq(feature.id, poly.id,
116                  "vertex deletion: drawFeature called with the proper feature");
117         };
118         control.resetVertices = function() {
119             t.ok(true, "vertex deletion: resetVertices called");
120         };
121         control.onModification = function(feature) {
122             t.eq(feature.id, poly.id,
123                  "vertex deletion: onModification called with the proper feature");
124         };
125         // run the above four tests twice
126         control.handleKeypress({keyCode:delKey});
127         control.handleKeypress({keyCode:dKey});
128         t.eq(control.feature.state, OpenLayers.State.UPDATE, "feature state set to update");
129
130         // now make sure nothing happens if the vertex is mid-drag
131         control.dragControl.handlers.drag.dragging = true;
132         control.handleKeypress({keyCode:delKey});
133
134         //  clean up
135         control.destroy();
136         layer.destroy();
137     }   
138        
139
140     function test_onUnSelect(t) {
141         t.plan(6);
142         var layer = new OpenLayers.Layer.Vector();
143         var control = new OpenLayers.Control.ModifyFeature(layer);
144         var fakeFeature = {'id':'myid'};
145         control.vertices = 'a';
146         control.virtualVertices = 'b';
147         control.features = true;
148         layer.events.on({"afterfeaturemodified": function(event) {
149             t.eq(event.feature, fakeFeature, "afterfeaturemodified triggered");
150         }});
151         control.dragControl.deactivate = function() { t.ok(true, "Deactivate called on drag control"); }
152         control.onModificationEnd = function (feature) { t.eq(feature.id, fakeFeature.id, "onModificationEnd got feature.") }
153         layer.removeFeatures = function(verts) {
154             t.ok(verts == 'a', "Normal verts removed correctly");
155         }
156         layer.destroyFeatures = function(verts) {
157             t.ok(verts == 'b', "Virtual verts destroyed correctly");
158         }
159         control.unselectFeature(fakeFeature);
160         t.eq(control.feature, null, "feature is set to null");
161        
162         layer.destroyFeatures = function() {};       
163         control.destroy();
164         layer.destroy();
165     }
166    
167     function test_stop_modification(t) {
168         t.plan(1);
169         var map = new OpenLayers.Map('map');
170         var layer = new OpenLayers.Layer.Vector("Vectors!", {isBaseLayer: true});
171         var feature = new OpenLayers.Feature.Vector(
172             new OpenLayers.Geometry.Point(0, 0)
173         );
174         layer.addFeatures([feature]);
175         map.addLayer(layer);
176         map.setCenter(new OpenLayers.LonLat(0, 0));
177
178
179         // If a feature is to be modified, control.selectFeature gets called.
180         // We want this test to fail if selectFeature gets called.
181         var modified = false;
182         var _ = OpenLayers.Control.ModifyFeature.prototype.selectFeature;
183         OpenLayers.Control.ModifyFeature.prototype.selectFeature = function() {
184             modified = true;
185         }
186
187         var control = new OpenLayers.Control.ModifyFeature(layer);
188         map.addControl(control);
189         control.activate();
190
191         // register a listener that will stop feature modification
192         layer.events.on({"beforefeaturemodified": function() {return false}});
193
194         // we can initiate feature modification by selecting a feature with
195         // the control's select feature control
196         control.selectControl.select(feature);
197        
198         if(modified) {
199             t.fail("selectFeature called, prepping feature for modification");
200         } else {
201             t.ok(true, "the beforefeaturemodified listener stopped feature modification");
202         }
203        
204         OpenLayers.Control.ModifyFeature.prototype.selectFeature = _;
205     }
206
207     function test_selectFeature(t) {
208         t.plan(12);
209         var map = new OpenLayers.Map('map');
210         var layer = new OpenLayers.Layer.Vector("Vectors!", {isBaseLayer: true});
211         map.addLayer(layer);
212         map.setCenter(new OpenLayers.LonLat(0, 0));
213         var control = new OpenLayers.Control.ModifyFeature(layer);
214         control.vertices = [];
215         control.virtualVertices = [];
216         var callback = function(obj) {
217             t.ok(obj.feature == fakeFeature, "beforefeaturemodified triggered");
218         };
219         layer.events.on({"beforefeaturemodified": callback});
220         control.dragControl.activate = function() { t.ok(true, "drag Control activated"); }
221         control.onModificationStart = function(feature)  { t.eq(feature.id, fakeFeature.id, "On Modification Start called with correct feature."); }
222        
223         // Start of testing
224        
225         control.collectVertices = function() { t.fail("Collect vertices called when geom is a point"); }
226         var fakeFeature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0, 0));
227        
228         // Points don't call collectVertices
229         control.selectFeature(fakeFeature);
230        
231         control.collectVertices = function() {
232           t.ok(true, "collectVertices called");
233           this.vertices = 'a';
234           this.virtualVertices = 'd';
235           layer.addFeatures(this.vertices);
236           layer.addFeatures(this.virtualVertices);
237         }
238        
239         layer.addFeatures = function(features) {
240             t.ok(features == 'a' || features == 'd', "features passed correctly");
241         }
242        
243         fakeFeature.geometry = new OpenLayers.Geometry.Polygon([
244             new OpenLayers.Geometry.LinearRing([
245                 new OpenLayers.Geometry.Point(0, 0),
246                 new OpenLayers.Geometry.Point(1, 1)
247             ])
248         ]);
249        
250         // OnSelect calls collectVertices and passes features to layer
251         control.selectFeature(fakeFeature);
252        
253         control.vertices = ['a'];
254         control.virtualVertices = ['b'];
255        
256         layer.addFeatures = function(features) {}
257        
258         layer.removeFeatures = function(features) {
259             t.eq(features.length, 1, "Correct feature length passed in");
260         }   
261
262         // Features are removed whenever they exist
263         control.selectFeature(fakeFeature);
264        
265         control.destroy();
266
267         // layer.destroy() will call removeFeatures with an empty array, make
268         // removeFeatures reference an empty function to prevent the above
269         // test to fail
270         layer.removeFeatures = function(features) {};
271         layer.destroy();
272     } 
273
274     function test_resetVertices(t) {
275         t.plan(18);
276         var layer = new OpenLayers.Layer.Vector();
277         var control = new OpenLayers.Control.ModifyFeature(layer);
278         var point = new OpenLayers.Geometry.Point(5,6);
279         var point2 = new OpenLayers.Geometry.Point(7,8);
280         var point3 = new OpenLayers.Geometry.Point(9,10);
281        
282         control.feature = new OpenLayers.Feature.Vector(point);
283         control.resetVertices();
284         t.eq(control.vertices.length, 0, "Correct vertices length");
285         t.eq(control.virtualVertices.length, 0, "Correct virtual vertices length.");
286
287         var multiPoint = new OpenLayers.Geometry.MultiPoint([point, point2]);
288         control.feature = new OpenLayers.Feature.Vector(multiPoint);
289         control.resetVertices();
290         t.eq(control.vertices.length, 2, "Correct vertices length with multipoint");
291         t.eq(control.virtualVertices.length, 0, "Correct virtual vertices length (multipoint).");
292
293         var line = new OpenLayers.Geometry.LineString([point, point2]);
294         control.feature = new OpenLayers.Feature.Vector(line);
295         control.resetVertices();
296         t.eq(control.vertices.length, 2, "Correct vertices length with line");
297         t.eq(control.virtualVertices.length, 1, "Correct virtual vertices length (linestring).");
298        
299         var polygon = new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([point, point2, point3])]);
300         control.feature = new OpenLayers.Feature.Vector(polygon);
301         control.resetVertices();
302         t.eq(control.vertices.length, 3, "Correct vertices length with polygon");
303         t.eq(control.virtualVertices.length, 3, "Correct virtual vertices length (polygon).");
304
305         control.mode = OpenLayers.Control.ModifyFeature.DRAG;
306         control.resetVertices();
307         t.ok(control.dragHandle != null, "Drag handle is set");
308         t.eq(control.vertices.length, 0, "Correct vertices length with polygon (DRAG)");
309
310         control.mode = OpenLayers.Control.ModifyFeature.ROTATE;
311         control.resetVertices();
312         t.ok(control.radiusHandle != null, "Radius handle is set");
313         t.eq(control.vertices.length, 0, "Correct vertices length with polygon (ROTATE)");
314
315         control.mode = OpenLayers.Control.ModifyFeature.RESIZE;
316         control.resetVertices();
317         t.ok(control.radiusHandle != null, "Radius handle is set");
318         t.eq(control.vertices.length, 0, "Correct vertices length with polygon (RESIZE)");
319
320         control.mode = OpenLayers.Control.ModifyFeature.RESHAPE | OpenLayers.Control.ModifyFeature.RESIZE;
321         control.resetVertices();
322         t.ok(control.radiusHandle != null, "Radius handle is set");
323         t.eq(control.vertices.length, 3, "Correct vertices length with polygon (RESHAPE | RESIZE)");
324         t.eq(control.virtualVertices.length, 3, "Correct virtual vertices length (RESHAPE | RESIZE)");
325        
326         control.dragControl.feature = new OpenLayers.Feature.Vector(polygon);
327         control.dragControl.map = {};
328         control.dragControl.map.div = {};
329         control.dragControl.map.div.style = {};
330         control.dragControl.map.div.cursor = "foo";
331         control.dragControl.handlers.drag.deactivate = function() {
332             this.active = false;
333         }
334         control.resetVertices();
335         t.ok(!control.dragControl.handlers.drag.active, "resetVertices deactivates drag handler");
336         control.dragControl.map = null;
337        
338         control.destroy();
339         layer.destroy();
340     }   
341        
342     function test_onDrag(t) {
343         t.plan(1);
344         t.ok(true, "onDrag not tested yet.");
345     }
346    
347     function test_dragComplete(t) {
348         t.plan(8);
349         var layer = new OpenLayers.Layer.Vector();
350         var control = new OpenLayers.Control.ModifyFeature(layer);
351        
352         var fakeFeature = {
353          'geometry': { 'id':'myGeom'},
354          'id': 'fakeFeature'
355         };
356         layer.addFeatures = function (verts) {
357             t.ok(verts == 'virtual' || verts == 'normal', verts + " verts correct");
358         }
359         layer.removeFeatures = function (verts) {
360             t.ok(verts == 'previous virtual' || verts == 'previous normal', verts + " verts correct");
361         }
362         layer.events.on({"featuremodified": function(event) {
363             t.eq(event.feature, fakeFeature, "featuremodified triggered");
364         }});
365         control.onModification = function(feat) {
366             t.eq(feat.id, fakeFeature.id, "onModification gets correct feat");
367         }
368         control.collectVertices = function() {
369             t.ok(true, "collectVertices called");
370             this.vertices = 'normal';
371             this.virtualVertices = 'virtual';
372             layer.addFeatures(this.vertices);
373             layer.addFeatures(this.virtualVertices);
374         }
375         control.feature = fakeFeature;
376         control.vertices = 'previous normal';
377         control.virtualVertices = 'previous virtual';
378         control.dragComplete();
379         t.eq(fakeFeature.state, OpenLayers.State.UPDATE, "feature state set to UPDATE");
380        
381         control.destroy();
382
383         // layer.destroy() will call removeFeatures with an empty array, make
384         // removeFeatures reference an empty function to prevent the above
385         // test to fail
386         layer.removeFeatures = function(verts) {};
387         layer.destroy();
388     }
389    
390     function test_deactivate(t) {
391         t.plan(2);
392         var map = new OpenLayers.Map("map");
393         var layer = new OpenLayers.Layer.Vector();
394         map.addLayer(layer);
395         var control = new OpenLayers.Control.ModifyFeature(layer);
396         map.addControl(control);
397        
398         control.selectControl.deactivate = function() {
399             t.ok(true,
400                  "control.deactivate calls deactivate on select control");
401         }
402         control.dragControl.deactivate = function() {
403             t.ok(true,
404                  "control.deactivate calls deactivate on drag control");
405         }
406         control.active = true;
407         control.deactivate();
408        
409         map.destroy();
410     }
411
412     function test_onModificationStart(t) {
413         t.plan(1);
414         var map = new OpenLayers.Map("map");
415         var layer = new OpenLayers.Layer.Vector();
416         map.addLayer(layer);
417         var control = new OpenLayers.Control.ModifyFeature(layer);
418         map.addControl(control);
419         control.activate();
420        
421         // make sure onModificationStart is called on feature selection
422         var testFeature = new OpenLayers.Feature.Vector(
423             new OpenLayers.Geometry.Point(Math.random(), Math.random())
424         );
425         control.onModificationStart = function(feature) {
426             t.eq(feature.id, testFeature.id,
427                  "onModificationStart called with the right feature");
428         };
429         control.selectFeature(testFeature);
430        
431         map.destroy();
432     }
433    
434     function test_onModification(t) {
435         t.plan(3);
436         var map = new OpenLayers.Map("map");
437         var layer = new OpenLayers.Layer.Vector();
438         map.addLayer(layer);
439         var control = new OpenLayers.Control.ModifyFeature(layer);
440         map.addControl(control);
441         control.activate();
442        
443         // make sure onModification is called on drag complete
444         var point = new OpenLayers.Feature.Vector(
445             new OpenLayers.Geometry.Point(Math.random(), Math.random())
446         );
447         control.feature = point;
448         control.onModification = function(feature) {
449             t.eq(feature.id, point.id,
450                 "onModification called with the right feature on drag complete");
451         };
452         control.dragComplete();
453        
454         // make sure onModification is called on vertex deletion
455         var poly = new OpenLayers.Feature.Vector(
456             new OpenLayers.Geometry.Polygon()
457         );
458         var oldDraw = layer.drawFeature;
459         layer.drawFeature = function() {
460             return;
461         };
462         control.feature = poly;
463         control.vertices = [point];
464         layer.events.on({"featuremodified": function(event) {
465             t.eq(event.feature.id, poly.id, "featuremodified triggered");
466         }});
467         control.onModification = function(feature) {
468             t.eq(feature.id, poly.id,
469                 "onModification called with the right feature on vertex delete");
470         };
471         point.geometry.parent = poly.geometry;
472         control.dragControl.feature = point;
473         control.handleKeypress