1/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for 2 * full list of contributors). Published under the 2-clause BSD license. 3 * See license.txt in the OpenLayers distribution or repository for the 4 * full text of the license. */ 5 6/** 7 * @requires OpenLayers/Control/DragFeature.js 8 * @requires OpenLayers/Control/SelectFeature.js 9 * @requires OpenLayers/Handler/Keyboard.js 10 */ 11 12/** 13 * Class: OpenLayers.Control.ModifyFeature 14 * Control to modify features. When activated, a click renders the vertices 15 * of a feature - these vertices can then be dragged. By default, the 16 * delete key will delete the vertex under the mouse. New features are 17 * added by dragging "virtual vertices" between vertices. Create a new 18 * control with the <OpenLayers.Control.ModifyFeature> constructor. 19 * 20 * Inherits From: 21 * - <OpenLayers.Control> 22 */ 23OpenLayers.Control.ModifyFeature = OpenLayers.Class(OpenLayers.Control, { 24 25 /** 26 * APIProperty: geometryTypes 27 * {Array(String)} To restrict modification to a limited set of geometry 28 * types, send a list of strings corresponding to the geometry class 29 * names. 30 */ 31 geometryTypes: null, 32 33 /** 34 * APIProperty: clickout 35 * {Boolean} Unselect features when clicking outside any feature. 36 * Default is true. 37 */ 38 clickout: true, 39 40 /** 41 * APIProperty: toggle 42 * {Boolean} Unselect a selected feature on click. 43 * Default is true. 44 */ 45 toggle: true, 46 47 /** 48 * APIProperty: standalone 49 * {Boolean} Set to true to create a control without SelectFeature 50 * capabilities. Default is false. If standalone is true, to modify 51 * a feature, call the <selectFeature> method with the target feature. 52 * Note that you must call the <unselectFeature> method to finish 53 * feature modification in standalone mode (before starting to modify 54 * another feature). 55 */ 56 standalone: false, 57 58 /** 59 * Property: layer 60 * {<OpenLayers.Layer.Vector>} 61 */ 62 layer: null, 63 64 /** 65 * Property: feature 66 * {<OpenLayers.Feature.Vector>} Feature currently available for modification. 67 */ 68 feature: null, 69 70 /** 71 * Property: vertices 72 * {Array(<OpenLayers.Feature.Vector>)} Verticies currently available 73 * for dragging. 74 */ 75 vertices: null, 76 77 /** 78 * Property: virtualVertices 79 * {Array(<OpenLayers.Feature.Vector>)} Virtual vertices in the middle 80 * of each edge. 81 */ 82 virtualVertices: null, 83 84 /** 85 * Property: selectControl 86 * {<OpenLayers.Control.SelectFeature>} 87 */ 88 selectControl: null, 89 90 /** 91 * Property: dragControl 92 * {<OpenLayers.Control.DragFeature>} 93 */ 94 dragControl: null, 95 96 /** 97 * Property: handlers 98 * {Object} 99 */ 100 handlers: null, 101 102 /** 103 * APIProperty: deleteCodes 104 * {Array(Integer)} Keycodes for deleting verticies. Set to null to disable 105 * vertex deltion by keypress. If non-null, keypresses with codes 106 * in this array will delete vertices under the mouse. Default 107 * is 46 and 68, the 'delete' and lowercase 'd' keys. 108 */ 109 deleteCodes: null, 110 111 /** 112 * APIProperty: virtualStyle 113 * {Object} A symbolizer to be used for virtual vertices. 114 */ 115 virtualStyle: null, 116 117 /** 118 * APIProperty: virtualStyle 119 * {Object} Style to be applied to the summits. 120 */ 121 PointStyle: null, 122 123 /** 124 * APIProperty: virtualStyle 125 * {Object} Cursor to be applied to the edit circles. 126 */ 127 pointCursor: 'move', 128 129 /** 130 * APIProperty: vertexRenderIntent 131 * {String} The renderIntent to use for vertices. If no <virtualStyle> is 132 * provided, this renderIntent will also be used for virtual vertices, with 133 * a fillOpacity and strokeOpacity of 0.3. Default is null, which means 134 * that the layer's default style will be used for vertices. 135 */ 136 vertexRenderIntent: null, 137 138 /** 139 * APIProperty: mode 140 * {Integer} Bitfields specifying the modification mode. Defaults to 141 * OpenLayers.Control.ModifyFeature.RESHAPE. To set the mode to a 142 * combination of options, use the | operator. For example, to allow 143 * the control to both resize and rotate features, use the following 144 * syntax 145 * (code) 146 * control.mode = OpenLayers.Control.ModifyFeature.RESIZE | 147 * OpenLayers.Control.ModifyFeature.ROTATE; 148 * (end) 149 */ 150 mode: null, 151 152 /** 153 * APIProperty: createVertices 154 * {Boolean} Create new vertices by dragging the virtual vertices 155 * in the middle of each edge. Default is true. 156 */ 157 createVertices: true, 158 159 /** 160 * Property: modified 161 * {Boolean} The currently selected feature has been modified. 162 */ 163 modified: false, 164 165 /** 166 * Property: radiusHandle 167 * {<OpenLayers.Feature.Vector>} A handle for rotating/resizing a feature. 168 */ 169 radiusHandle: null, 170 171 /** 172 * Property: dragHandle 173 * {<OpenLayers.Feature.Vector>} A handle for dragging a feature. 174 */ 175 dragHandle: null, 176 177 /** 178 * APIProperty: onModificationStart 179 * {Function} *Deprecated*. Register for "beforefeaturemodified" instead. 180 * The "beforefeaturemodified" event is triggered on the layer before 181 * any modification begins. 182 * 183 * Optional function to be called when a feature is selected 184 * to be modified. The function should expect to be called with a 185 * feature. This could be used for example to allow to lock the 186 * feature on server-side. 187 */ 188 onModificationStart: function() {}, 189 190 /** 191 * APIProperty: onModification 192 * {Function} *Deprecated*. Register for "featuremodified" instead. 193 * The "featuremodified" event is triggered on the layer with each 194 * feature modification. 195 * 196 * Optional function to be called when a feature has been 197 * modified. The function should expect to be called with a feature. 198 */ 199 onModification: function() {}, 200 201 /** 202 * APIProperty: onModificationEnd 203 * {Function} *Deprecated*. Register for "afterfeaturemodified" instead. 204 * The "afterfeaturemodified" event is triggered on the layer after 205 * a feature has been modified. 206 * 207 * Optional function to be called when a feature is finished 208 * being modified. The function should expect to be called with a 209 * feature. 210 */ 211 onModificationEnd: function() {}, 212 213 /** 214 * Constructor: OpenLayers.Control.ModifyFeature 215 * Create a new modify feature control. 216 * 217 * Parameters:
218 * layer - {<OpenLayers.Layer.Vector>} Layer that contains features that 219 * will be modified. 220 * options - {Object} Optional object whose properties will be set on the 221 * control. 222 */ 223 initialize: function(layer, options) { 224 options = options || {}; 225 this.layer = layer; 226 this.vertices = []; 227 this.virtualVertices = []; 228 this.virtualStyle = OpenLayers.Util.extend({}, 229 this.layer.style || 230 this.layer.styleMap.createSymbolizer(null, options.vertexRenderIntent) 231 ); 232 this.virtualStyle.cursor = this.pointCursor; // Curseur déplacement sur tous les ronds 233 this.PointStyle = OpenLayers.Util.extend({}, this.virtualStyle); // Style pour les sommets 234 this.virtualStyle.fillOpacity = 0.3; 235 this.virtualStyle.strokeOpacity = 0.3; 236 this.deleteCodes = [46, 68]; 237 this.mode = OpenLayers.Control.ModifyFeature.RESHAPE; 238 OpenLayers.Control.prototype.initialize.apply(this, [options]); 239 if(!(OpenLayers.Util.isArray(this.deleteCodes))) { 240 this.deleteCodes = [this.deleteCodes]; 241 } 242 var control = this; 243 244 // configure the select control 245 var selectOptions = { 246 geometryTypes: this.geometryTypes, 247 clickout: this.clickout, 248 toggle: this.toggle, 249 onBeforeSelect: this.beforeSelectFeature, 250 onSelect: this.selectFeature, 251 onUnselect: this.unselectFeature, 252 scope: this 253 }; 254 if(this.standalone === false) { 255 this.selectControl = new OpenLayers.Control.SelectFeature( 256 layer, selectOptions 257 ); 258 } 259 260 // configure the drag control 261 var dragOptions = { 262 geometryTypes: ["OpenLayers.Geometry.Point"], 263 onStart: function(feature, pixel) { 264 control.dragStart.apply(control, [feature, pixel]); 265 }, 266 onDrag: function(feature, pixel) { 267 control.dragVertex.apply(control, [feature, pixel]); 268 }, 269 onComplete: function(feature) { 270 control.dragComplete.apply(control, [feature]); 271 }, 272 featureCallbacks: { 273 over: function(feature) { 274 /** 275 * In normal mode, the feature handler is set up to allow 276 * dragging of all points. In standalone mode, we only 277 * want to allow dragging of sketch vertices and virtual 278 * vertices - or, in the case of a modifiable point, the 279 * point itself. 280 */ 281 if(control.standalone !== true || feature._sketch || 282 control.feature === feature) { 283 control.dragControl.overFeature.apply( 284 control.dragControl, [feature]); 285 } 286 } 287 } 288 }; 289 this.dragControl = new OpenLayers.Control.DragFeature( 290 layer, dragOptions 291 ); 292 293 // configure the keyboard handler 294 var keyboardOptions = { 295 keydown: this.handleKeypress 296 }; 297 this.handlers = { 298 keyboard: new OpenLayers.Handler.Keyboard(this, keyboardOptions) 299 }; 300 }, 301 302 /** 303 * APIMethod: destroy 304 * Take care of things that are not handled in superclass. 305 */ 306 destroy: function() { 307 this.layer = null; 308 this.standalone || this.selectControl.destroy(); 309 this.dragControl.destroy(); 310 OpenLayers.Control.prototype.destroy.apply(this, []); 311 }, 312 313 /** 314 * APIMethod: activate 315 * Activate the control. 316 * 317 * Returns: 318 * {Boolean} Successfully activated the control. 319 */ 320 activate: function() { 321 var r= ((this.standalone || this.selectControl.activate()) && 322 this.handlers.keyboard.activate() && 323 OpenLayers.Control.prototype.activate.apply(this, arguments)); 324 325 326 hoverControl.deactivate(); 327 selectControl.deactivate(); 328 329 return r; 330 331 332 333 }, 334 335 /** 336 * APIMethod: deactivate 337 * Deactivate the control. 338 * 339 * Returns: 340 * {Boolean} Successfully deactivated the control. 341 */ 342 deactivate: function() { 343 344 345 hoverControl.activate(); 346 selectControl.activate(); 347 348 349 var deactivated = false;
350 // the return from the controls is unimportant in this case 351 if(OpenLayers.Control.prototype.deactivate.apply(this, arguments)) { 352 this.layer.removeFeatures(this.vertices, {silent: true}); 353 this.layer.removeFeatures(this.virtualVertices, {silent: true}); 354 this.vertices = []; 355 this.dragControl.deactivate(); 356 var feature = this.feature; 357 var valid = feature && feature.geometry && feature.layer; 358 if(this.standalone === false) { 359 if(valid) { 360 this.selectControl.unselect.apply(this.selectControl, 361 [feature]); 362 } 363 this.selectControl.deactivate(); 364 } else { 365 if(valid) { 366 this.unselectFeature(feature); 367 } 368 } 369 this.handlers.keyboard.deactivate(); 370 deactivated = true; 371 } 372 return deactivated; 373 }, 374 375 /** 376 * Method: beforeSelectFeature 377 * Called before a feature is selected. 378 * 379 * Parameters:
380 * feature - {<OpenLayers.Feature.Vector>} The feature about to be selected. 381 */ 382 beforeSelectFeature: function(feature) { 383 return this.layer.events.triggerEvent( 384 "beforefeaturemodified", {feature: feature} 385 ); 386 }, 387 388 /** 389 * APIMethod: selectFeature 390 * Select a feature for modification in standalone mode. In non-standalone 391 * mode, this method is called when the select feature control selects a 392 * feature. Register a listener to the beforefeaturemodified event and 393 * return false to prevent feature modification. 394 * 395 * Parameters: 396 * feature - {<OpenLayers.Feature.Vector>} the selected feature. 397 */ 398 selectFeature: function(feature) { 399 if (!this.standalone || this.beforeSelectFeature(feature) !== false) { 400 this.feature = feature; 401 this.modified = false; 402 this.resetVertices(); 403 this.dragControl.activate(); 404 this.onModificationStart(this.feature); 405 } 406 // keep track of geometry modifications 407 var modified = feature.modified; 408 if (feature.geometry && !(modified && modified.geometry)) { 409 this._originalGeometry = feature.geometry.clone(); 410 } 411 }, 412 413 /** 414 * APIMethod: unselectFeature 415 * Called when the select feature control unselects a feature. 416 * 417 * Parameters:
418 * feature - {<OpenLayers.Feature.Vector>} The unselected feature. 419 */ 420 unselectFeature: function(feature) { 421 this.layer.removeFeatures(this.vertices, {silent: true}); 422 this.vertices = []; 423 this.layer.destroyFeatures(this.virtualVertices, {silent: true}); 424 this.virtualVertices = []; 425 if(this.dragHandle) { 426 this.layer.destroyFeatures([this.dragHandle], {silent: true}); 427 delete this.dragHandle; 428 } 429 if(this.radiusHandle) { 430 this.layer.destroyFeatures([this.radiusHandle], {silent: true}); 431 delete this.radiusHandle; 432 } 433 this.feature = null; 434 this.dragControl.deactivate(); 435 this.onModificationEnd(feature); 436 this.layer.events.triggerEvent("afterfeaturemodified", { 437 feature: feature, 438 modified: this.modified 439 }); 440 this.modified = false; 441 }, 442 443 /** 444 * Method: dragStart 445 * Called by the drag feature control with before a feature is dragged. 446 * This method is used to differentiate between points and vertices 447 * of higher order geometries. This respects the <geometryTypes> 448 * property and forces a select of points when the drag control is 449 * already active (and stops events from propagating to the select 450 * control). 451 * 452 * Parameters:
453 * feature - {<OpenLayers.Feature.Vector>} The point or vertex about to be 454 * dragged. 455 * pixel - {<OpenLayers.Pixel>} Pixel location of the mouse event. 456 */ 457 dragStart: function(feature, pixel) { 458 // only change behavior if the feature is not in the vertices array 459 if(feature != this.feature && !feature.geometry.parent && 460 feature != this.dragHandle && feature != this.radiusHandle) { 461 if(this.standalone === false && this.feature) { 462 // unselect the currently selected feature 463 this.selectControl.clickFeature.apply(this.selectControl, 464 [this.feature]); 465 } 466 // check any constraints on the geometry type 467 if(this.geometryTypes == null || 468 OpenLayers.Util.indexOf(this.geometryTypes, 469 feature.geometry.CLASS_NAME) != -1) { 470 // select the point 471 this.standalone || this.selectControl.clickFeature.apply( 472 this.selectControl, [feature]); 473 /** 474 * TBD: These lines improve workflow by letting the user 475 * immediately start dragging after the mouse down. 476 * However, it is very ugly to be messing with controls 477 * and their handlers in this way. I'd like a better 478 * solution if the workflow change is necessary. 479 */ 480 // prepare the point for dragging 481 this.dragControl.overFeature.apply(this.dragControl, 482 [feature]); 483 this.dragControl.lastPixel = pixel; 484 this.dragControl.handlers.drag.started = true; 485 this.dragControl.handlers.drag.start = pixel; 486 this.dragControl.handlers.drag.last = pixel; 487 } 488 } 489 }, 490 491 /** 492 * Method: dragVertex 493 * Called by the drag feature control with each drag move of a vertex. 494 * 495 * Parameters: 496 * vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged. 497 * pixel - {<OpenLayers.Pixel>} Pixel location of the mouse event. 498 */ 499 dragVertex: function(vertex, pixel) { 500 this.modified = true; 501 /** 502 * Five cases: 503 * 1) dragging a simple point 504 * 2) dragging a virtual vertex 505 * 3) dragging a drag handle 506 * 4) dragging a real vertex 507 * 5) dragging a radius handle 508 */ 509 if(this.feature.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { 510 // dragging a simple point 511 if(this.feature != vertex) { 512 this.feature = vertex; 513 } 514 this.layer.events.triggerEvent("vertexmodified", { 515 vertex: vertex.geometry, 516 feature: this.feature, 517 pixel: pixel 518 }); 519 } else { 520 if(vertex._index) { 521 // dragging a virtual vertex 522 vertex.geometry.parent.addComponent(vertex.geometry, 523 vertex._index); 524 // move from virtual to real vertex 525 delete vertex._index; 526 OpenLayers.Util.removeItem(this.virtualVertices, vertex); 527 this.vertices.push(vertex); 528 } else if(vertex == this.dragHandle) { 529 // dragging a drag handle 530 this.layer.removeFeatures(this.vertices, {silent: true}); 531 this.vertices = []; 532 if(this.radiusHandle) { 533 this.layer.destroyFeatures([this.radiusHandle], {silent: true}); 534 this.radiusHandle = null; 535 } 536 } else if(vertex !== this.radiusHandle) { 537 // dragging a real vertex 538 this.layer.events.triggerEvent("vertexmodified", { 539 vertex: vertex.geometry, 540 feature: this.feature, 541 pixel: pixel 542 }); 543 } 544 // dragging a radius handle - no special treatment 545 if(this.virtualVertices.length > 0) { 546 this.layer.destroyFeatures(this.virtualVertices, {silent: true}); 547 this.virtualVertices = []; 548 } 549 this.layer.drawFeature(this.feature, this.standalone ? undefined : 550 this.selectControl.renderIntent); 551 } 552 // keep the vertex on top so it gets the mouseout after dragging 553 // this should be removed in favor of an option to draw under or 554 // maintain node z-index 555 this.layer.drawFeature(vertex); 556 }, 557 558 /** 559 * Method: dragComplete 560 * Called by the drag feature control when the feature dragging is complete. 561 * 562 * Parameters: 563 * vertex - {<OpenLayers.Feature.Vector>} The vertex being dragged. 564 */ 565 dragComplete: function(vertex) { 566 this.resetVertices(); 567 this.setFeatureState(); 568 this.onModification(this.feature); 569 this.layer.events.triggerEvent("featuremodified", 570 {feature: this.feature}); 571 }, 572 573 /** 574 * Method: setFeatureState 575 * Called when the feature is modified. If the current state is not 576 * INSERT or DELETE, the state is set to UPDATE. 577 */ 578 setFeatureState: function() { 579 if(this.feature.state != OpenLayers.State.INSERT && 580 this.feature.state != OpenLayers.State.DELETE) { 581 this.feature.state = OpenLayers.State.UPDATE; 582 if (this.modified && this._originalGeometry) { 583 var feature = this.feature; 584 feature.modified = OpenLayers.Util.extend(feature.modified, {
585 geometry: this._originalGeometry 586 }); 587 delete this._originalGeometry; 588 } 589 } 590 }, 591 592 /** 593 * Method: resetVertices 594 */ 595 resetVertices: function() { 596 // if coming from a drag complete we're about to destroy the vertex 597 // that was just dragged. For that reason, the drag feature control 598 // will never detect a mouse-out on that vertex, meaning that the drag 599 // handler won't be deactivated. This can cause errors because the drag 600 // feature control still has a feature to drag but that feature is 601 // destroyed. To prevent this, we call outFeature on the drag feature 602 // control if the control actually has a feature to drag. 603 if(this.dragControl.feature) { 604 this.dragControl.outFeature(this.dragControl.feature); 605 } 606 if(this.vertices.length > 0) { 607 this.layer.removeFeatures(this.vertices, {silent: true}); 608 this.vertices = []; 609 } 610 if(this.virtualVertices.length > 0) { 611 this.layer.removeFeatures(this.virtualVertices, {silent: true}); 612 this.virtualVertices = []; 613 } 614 if(this.dragHandle) { 615 this.layer.destroyFeatures([this.dragHandle], {silent: true}); 616 this.dragHandle = null; 617 } 618 if(this.radiusHandle) { 619 this.layer.destroyFeatures([this.radiusHandle], {silent: true}); 620 this.radiusHandle = null; 621 } 622 if(this.feature && 623 this.feature.geometry.CLASS_NAME != "OpenLayers.Geometry.Point") { 624 if((this.mode & OpenLayers.Control.ModifyFeature.DRAG)) { 625 this.collectDragHandle(); 626 } 627 if((this.mode & (OpenLayers.Control.ModifyFeature.ROTATE | 628 OpenLayers.Control.ModifyFeature.RESIZE))) { 629 this.collectRadiusHandle(); 630 } 631 if(this.mode & OpenLayers.Control.ModifyFeature.RESHAPE){ 632 // Don't collect vertices when we're resizing 633 if (!(this.mode & OpenLayers.Control.ModifyFeature.RESIZE)){ 634 this.collectVertices(); 635 } 636 } 637 } 638 }, 639 640 /** 641 * Method: handleKeypress 642 * Called by the feature handler on keypress. This is used to delete 643 * vertices. If the <deleteCode> property is set, vertices will 644 * be deleted when a feature is selected for modification and 645 * the mouse is over a vertex. 646 * 647 * Parameters: 648 * evt - {Event} Keypress event. 649 */ 650 handleKeypress: function(evt) { 651 var code = evt.keyCode; 652 653 // check for delete key 654 if(this.feature && 655 OpenLayers.Util.indexOf(this.deleteCodes, code) != -1) { 656 var vertex = this.dragControl.feature; 657 if(vertex && 658 OpenLayers.Util.indexOf(this.vertices, vertex) != -1 && 659 !this.dragControl.handlers.drag.dragging && 660 vertex.geometry.parent) { 661 // remove the vertex 662 vertex.geometry.parent.removeComponent(vertex.geometry); 663 this.layer.events.triggerEvent("vertexremoved", { 664 vertex: vertex.geometry, 665 feature: this.feature, 666 pixel: evt.xy 667 }); 668 this.layer.drawFeature(this.feature, this.standalone ? 669 undefined : 670 this.selectControl.renderIntent); 671 this.modified = true; 672 this.resetVertices(); 673 this.setFeatureState(); 674 this.onModification(this.feature); 675 this.layer.events.triggerEvent("featuremodified", 676 {feature: this.feature}); 677 } 678 } 679 }, 680 681 /** 682 * Method: collectVertices 683 * Collect the vertices from the modifiable feature's geometry and push 684 * them on to the control's vertices array. 685 */ 686 collectVertices: function() { 687 this.vertices = []; 688 this.virtualVertices = []; 689 var control = this; 690 function collectComponentVertices(geometry) { 691 var i, vertex, component, len; 692 if(geometry.CLASS_NAME == "OpenLayers.Geometry.Point") { 693 vertex = new OpenLayers.Feature.Vector(geometry); 694 vertex._sketch = true; 695 vertex.renderIntent = control.vertexRenderIntent; 696 control.vertices.push(vertex); 697 } else { 698 var numVert = geometry.components.length; 699 if(geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") { 700 numVert -= 1; 701 } 702 for(i=0; i<numVert; ++i) { 703 component = geometry.components[i]; 704 if(component.CLASS_NAME == "OpenLayers.Geometry.Point") { 705 vertex = new OpenLayers.Feature.Vector(component, null, control.PointStyle); // Nouveau style des sommets 706 vertex._sketch = true; 707 vertex.renderIntent = control.vertexRenderIntent; 708 control.vertices.push(vertex); 709 } else { 710 collectComponentVertices(component); 711 } 712 } 713 714 // add virtual vertices in the middle of each edge 715 if (control.createVertices && geometry.CLASS_NAME != "OpenLayers.Geometry.MultiPoint") { 716 for(i=0, len=geometry.components.length; i<len-1; ++i) { 717 var prevVertex = geometry.components[i]; 718 var nextVertex = geometry.components[i + 1]; 719 if(prevVertex.CLASS_NAME == "OpenLayers.Geometry.Point" && 720 nextVertex.CLASS_NAME == "OpenLayers.Geometry.Point") { 721 var x = (prevVertex.x + nextVertex.x) / 2; 722 var y = (prevVertex.y + nextVertex.y) / 2; 723 var point = new OpenLayers.Feature.Vector( 724 new OpenLayers.Geometry.Point(x, y), 725 null, control.virtualStyle 726 ); 727 // set the virtual parent and intended index 728 point.geometry.parent = geometry; 729 point._index = i + 1; 730 point._sketch = true; 731 control.virtualVertices.push(point); 732 } 733 } 734 } 735 } 736 } 737 collectComponentVertices.call(this, this.feature.geometry); 738 this.layer.addFeatures(this.virtualVertices, {silent: true}); 739 this.layer.addFeatures(this.vertices, {silent: true}); 740 }, 741 742 /** 743 * Method: collectDragHandle 744 * Collect the drag handle for the selected geometry. 745 */ 746 collectDragHandle: function() { 747 var geometry = this.feature.geometry; 748 var center = geometry.getBounds().getCenterLonLat(); 749 var originGeometry = new OpenLayers.Geometry.Point( 750 center.lon, center.lat 751 ); 752 var origin = new OpenLayers.Feature.Vector(originGeometry); 753 originGeometry.move = function(x, y) { 754 OpenLayers.Geometry.Point.prototype.move.call(this, x, y); 755 geometry.move(x, y); 756 }; 757 origin._sketch = true; 758 this.dragHandle = origin; 759 this.dragHandle.renderIntent = this.vertexRenderIntent; 760 this.layer.addFeatures([this.dragHandle], {silent: true}); 761 }, 762 763 /** 764 * Method: collectRadiusHandle 765 * Collect the radius handle for the selected geometry. 766 */ 767 collectRadiusHandle: function() { 768 var geometry = this.feature.geometry; 769 var bounds = geometry.getBounds(); 770 var center = bounds.getCenterLonLat(); 771 var originGeometry = new OpenLayers.Geometry.Point( 772 center.lon, center.lat 773 ); 774 var radiusGeometry = new OpenLayers.Geometry.Point( 775 bounds.right, bounds.bottom 776 ); 777 var radius = new OpenLayers.Feature.Vector(radiusGeometry); 778 var resize = (this.mode & OpenLayers.Control.ModifyFeature.RESIZE); 779 var reshape = (this.mode & OpenLayers.Control.ModifyFeature.RESHAPE); 780 var rotate = (this.mode & OpenLayers.Control.ModifyFeature.ROTATE); 781 782 radiusGeometry.move = function(x, y) { 783 OpenLayers.Geometry.Point.prototype.move.call(this, x, y); 784 var dx1 = this.x - originGeometry.x; 785 var dy1 = this.y - originGeometry.y; 786 var dx0 = dx1 - x; 787 var dy0 = dy1 - y; 788 if(rotate) { 789 var a0 = Math.atan2(dy0, dx0); 790 var a1 = Math.atan2(dy1, dx1); 791 var angle = a1 - a0; 792 angle *= 180 / Math.PI; 793 geometry.rotate(angle, originGeometry); 794 } 795 if(resize) { 796 var scale, ratio; 797 // 'resize' together with 'reshape' implies that the aspect 798 // ratio of the geometry will not be preserved whilst resizing 799 if (reshape) { 800 scale = dy1 / dy0; 801 ratio = (dx1 / dx0) / scale; 802 } else { 803 var l0 = Math.sqrt((dx0 * dx0) + (dy0 * dy0)); 804 var l1 = Math.sqrt((dx1 * dx1) + (dy1 * dy1)); 805 scale = l1 / l0; 806 } 807 geometry.resize(scale, originGeometry, ratio); 808 } 809 }; 810 radius._sketch = true; 811 this.radiusHandle = radius; 812 this.radiusHandle.renderIntent = this.vertexRenderIntent; 813 this.layer.addFeatures([this.radiusHandle], {silent: true}); 814 }, 815 816 /** 817 * Method: setMap 818 * Set the map property for the control and all handlers. 819 * 820 * Parameters: 821 * map - {<OpenLayers.Map>} The control's map. 822 */ 823 setMap: function(map) {
824 this.standalone || this.selectControl.setMap(map); 825 this.dragControl.setMap(map); 826 OpenLayers.Control.prototype.setMap.apply(this, arguments); 827 }, 828 829 CLASS_NAME: "OpenLayers.Control.ModifyFeature" 830}); 831 832/** 833 * Constant: RESHAPE 834 * {Integer} Constant used to make the control work in reshape mode 835 */ 836OpenLayers.Control.ModifyFeature.RESHAPE = 1; 837/** 838 * Constant: RESIZE 839 * {Integer} Constant used to make the control work in resize mode 840 */ 841OpenLayers.Control.ModifyFeature.RESIZE = 2; 842/** 843 * Constant: ROTATE 844 * {Integer} Constant used to make the control work in rotate mode 845 */ 846OpenLayers.Control.ModifyFeature.ROTATE = 4; 847/** 848 * Constant: DRAG 849 * {Integer} Constant used to make the control work in drag mode 850 */ 851OpenLayers.Control.ModifyFeature.DRAG = 8;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.