Move interaction event handlers to class methods
This commit is contained in:
@@ -16,7 +16,7 @@ import {always, primaryAction, altKeyOnly, singleClick} from '../events/conditio
|
||||
import {boundingExtent, buffer, createOrUpdateFromCoordinate} from '../extent.js';
|
||||
import GeometryType from '../geom/GeometryType.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import PointerInteraction, {handleEvent as handlePointerEvent} from '../interaction/Pointer.js';
|
||||
import PointerInteraction from '../interaction/Pointer.js';
|
||||
import VectorLayer from '../layer/Vector.js';
|
||||
import VectorSource from '../source/Vector.js';
|
||||
import VectorEventType from '../source/VectorEventType.js';
|
||||
@@ -157,12 +157,7 @@ class Modify extends PointerInteraction {
|
||||
*/
|
||||
constructor(options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleEvent: handleEvent,
|
||||
handleUpEvent: handleUpEvent
|
||||
});
|
||||
super(/** @type {import("./Pointer.js").Options} */ (options));
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -170,7 +165,6 @@ class Modify extends PointerInteraction {
|
||||
*/
|
||||
this.condition_ = options.condition ? options.condition : primaryAction;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Browser event.
|
||||
@@ -667,6 +661,211 @@ class Modify extends PointerInteraction {
|
||||
return vertexFeature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may modify the geometry.
|
||||
* @override
|
||||
*/
|
||||
handleEvent(mapBrowserEvent) {
|
||||
if (!(mapBrowserEvent instanceof MapBrowserPointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
this.lastPointerEvent_ = mapBrowserEvent;
|
||||
|
||||
let handled;
|
||||
if (!mapBrowserEvent.map.getView().getInteracting() &&
|
||||
mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE &&
|
||||
!this.handlingDownUpSequence) {
|
||||
this.handlePointerMove_(mapBrowserEvent);
|
||||
}
|
||||
if (this.vertexFeature_ && this.deleteCondition_(mapBrowserEvent)) {
|
||||
if (mapBrowserEvent.type != MapBrowserEventType.SINGLECLICK || !this.ignoreNextSingleClick_) {
|
||||
handled = this.removePoint();
|
||||
} else {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.SINGLECLICK) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
}
|
||||
|
||||
return super.handleEvent(mapBrowserEvent) && !handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(evt) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
this.willModifyFeatures_(evt);
|
||||
|
||||
const vertex = evt.coordinate;
|
||||
for (let i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
|
||||
const dragSegment = this.dragSegments_[i];
|
||||
const segmentData = dragSegment[0];
|
||||
const depth = segmentData.depth;
|
||||
const geometry = segmentData.geometry;
|
||||
let coordinates;
|
||||
const segment = segmentData.segment;
|
||||
const index = dragSegment[1];
|
||||
|
||||
while (vertex.length < geometry.getStride()) {
|
||||
vertex.push(segment[index][vertex.length]);
|
||||
}
|
||||
|
||||
switch (geometry.getType()) {
|
||||
case GeometryType.POINT:
|
||||
coordinates = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POINT:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index] = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.CIRCLE:
|
||||
segment[0] = segment[1] = vertex;
|
||||
if (segmentData.index === CIRCLE_CENTER_INDEX) {
|
||||
this.changingFeature_ = true;
|
||||
geometry.setCenter(vertex);
|
||||
this.changingFeature_ = false;
|
||||
} else { // We're dragging the circle's circumference:
|
||||
this.changingFeature_ = true;
|
||||
geometry.setRadius(coordinateDistance(geometry.getCenter(), vertex));
|
||||
this.changingFeature_ = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
|
||||
if (coordinates) {
|
||||
this.setGeometryCoordinates_(geometry, coordinates);
|
||||
}
|
||||
}
|
||||
this.createOrUpdateVertexFeature_(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(evt) {
|
||||
if (!this.condition_(evt)) {
|
||||
return false;
|
||||
}
|
||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
||||
const pixelCoordinate = evt.map.getCoordinateFromPixel(evt.pixel);
|
||||
this.dragSegments_.length = 0;
|
||||
this.modified_ = false;
|
||||
const vertexFeature = this.vertexFeature_;
|
||||
if (vertexFeature) {
|
||||
const insertVertices = [];
|
||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
||||
const vertex = geometry.getCoordinates();
|
||||
const vertexExtent = boundingExtent([vertex]);
|
||||
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
|
||||
const componentSegments = {};
|
||||
segmentDataMatches.sort(compareIndexes);
|
||||
for (let i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
|
||||
const segmentDataMatch = segmentDataMatches[i];
|
||||
const segment = segmentDataMatch.segment;
|
||||
let uid = String(getUid(segmentDataMatch.feature));
|
||||
const depth = segmentDataMatch.depth;
|
||||
if (depth) {
|
||||
uid += '-' + depth.join('-'); // separate feature components
|
||||
}
|
||||
if (!componentSegments[uid]) {
|
||||
componentSegments[uid] = new Array(2);
|
||||
}
|
||||
if (segmentDataMatch.geometry.getType() === GeometryType.CIRCLE &&
|
||||
segmentDataMatch.index === CIRCLE_CIRCUMFERENCE_INDEX) {
|
||||
|
||||
const closestVertex = closestOnSegmentData(pixelCoordinate, segmentDataMatch);
|
||||
if (coordinatesEqual(closestVertex, vertex) && !componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
}
|
||||
} else if (coordinatesEqual(segment[0], vertex) &&
|
||||
!componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
} else if (coordinatesEqual(segment[1], vertex) &&
|
||||
!componentSegments[uid][1]) {
|
||||
|
||||
// prevent dragging closed linestrings by the connecting node
|
||||
if ((segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.LINE_STRING ||
|
||||
segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.MULTI_LINE_STRING) &&
|
||||
componentSegments[uid][0] &&
|
||||
componentSegments[uid][0].index === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.dragSegments_.push([segmentDataMatch, 1]);
|
||||
componentSegments[uid][1] = segmentDataMatch;
|
||||
} else if (this.insertVertexCondition_(evt) && getUid(segment) in this.vertexSegments_ &&
|
||||
(!componentSegments[uid][0] && !componentSegments[uid][1])) {
|
||||
insertVertices.push([segmentDataMatch, vertex]);
|
||||
}
|
||||
}
|
||||
if (insertVertices.length) {
|
||||
this.willModifyFeatures_(evt);
|
||||
}
|
||||
for (let j = insertVertices.length - 1; j >= 0; --j) {
|
||||
this.insertVertex_.apply(this, insertVertices[j]);
|
||||
}
|
||||
}
|
||||
return !!this.vertexFeature_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(evt) {
|
||||
for (let i = this.dragSegments_.length - 1; i >= 0; --i) {
|
||||
const segmentData = this.dragSegments_[i][0];
|
||||
const geometry = segmentData.geometry;
|
||||
if (geometry.getType() === GeometryType.CIRCLE) {
|
||||
// Update a circle object in the R* bush:
|
||||
const coordinates = geometry.getCenter();
|
||||
const centerSegmentData = segmentData.featureSegments[0];
|
||||
const circumferenceSegmentData = segmentData.featureSegments[1];
|
||||
centerSegmentData.segment[0] = centerSegmentData.segment[1] = coordinates;
|
||||
circumferenceSegmentData.segment[0] = circumferenceSegmentData.segment[1] = coordinates;
|
||||
this.rBush_.update(createOrUpdateFromCoordinate(coordinates), centerSegmentData);
|
||||
this.rBush_.update(geometry.getExtent(), circumferenceSegmentData);
|
||||
} else {
|
||||
this.rBush_.update(boundingExtent(segmentData.segment), segmentData);
|
||||
}
|
||||
}
|
||||
if (this.modified_) {
|
||||
this.dispatchEvent(new ModifyEvent(ModifyEventType.MODIFYEND, this.features_, evt));
|
||||
this.modified_ = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserEvent.js").default} evt Event.
|
||||
* @private
|
||||
@@ -985,223 +1184,6 @@ function compareIndexes(a, b) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} evt Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleDownEvent(evt) {
|
||||
if (!this.condition_(evt)) {
|
||||
return false;
|
||||
}
|
||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
||||
const pixelCoordinate = evt.map.getCoordinateFromPixel(evt.pixel);
|
||||
this.dragSegments_.length = 0;
|
||||
this.modified_ = false;
|
||||
const vertexFeature = this.vertexFeature_;
|
||||
if (vertexFeature) {
|
||||
const insertVertices = [];
|
||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
||||
const vertex = geometry.getCoordinates();
|
||||
const vertexExtent = boundingExtent([vertex]);
|
||||
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
|
||||
const componentSegments = {};
|
||||
segmentDataMatches.sort(compareIndexes);
|
||||
for (let i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
|
||||
const segmentDataMatch = segmentDataMatches[i];
|
||||
const segment = segmentDataMatch.segment;
|
||||
let uid = String(getUid(segmentDataMatch.feature));
|
||||
const depth = segmentDataMatch.depth;
|
||||
if (depth) {
|
||||
uid += '-' + depth.join('-'); // separate feature components
|
||||
}
|
||||
if (!componentSegments[uid]) {
|
||||
componentSegments[uid] = new Array(2);
|
||||
}
|
||||
if (segmentDataMatch.geometry.getType() === GeometryType.CIRCLE &&
|
||||
segmentDataMatch.index === CIRCLE_CIRCUMFERENCE_INDEX) {
|
||||
|
||||
const closestVertex = closestOnSegmentData(pixelCoordinate, segmentDataMatch);
|
||||
if (coordinatesEqual(closestVertex, vertex) && !componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
}
|
||||
} else if (coordinatesEqual(segment[0], vertex) &&
|
||||
!componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
} else if (coordinatesEqual(segment[1], vertex) &&
|
||||
!componentSegments[uid][1]) {
|
||||
|
||||
// prevent dragging closed linestrings by the connecting node
|
||||
if ((segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.LINE_STRING ||
|
||||
segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.MULTI_LINE_STRING) &&
|
||||
componentSegments[uid][0] &&
|
||||
componentSegments[uid][0].index === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.dragSegments_.push([segmentDataMatch, 1]);
|
||||
componentSegments[uid][1] = segmentDataMatch;
|
||||
} else if (this.insertVertexCondition_(evt) && getUid(segment) in this.vertexSegments_ &&
|
||||
(!componentSegments[uid][0] && !componentSegments[uid][1])) {
|
||||
insertVertices.push([segmentDataMatch, vertex]);
|
||||
}
|
||||
}
|
||||
if (insertVertices.length) {
|
||||
this.willModifyFeatures_(evt);
|
||||
}
|
||||
for (let j = insertVertices.length - 1; j >= 0; --j) {
|
||||
this.insertVertex_.apply(this, insertVertices[j]);
|
||||
}
|
||||
}
|
||||
return !!this.vertexFeature_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} evt Event.
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleDragEvent(evt) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
this.willModifyFeatures_(evt);
|
||||
|
||||
const vertex = evt.coordinate;
|
||||
for (let i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
|
||||
const dragSegment = this.dragSegments_[i];
|
||||
const segmentData = dragSegment[0];
|
||||
const depth = segmentData.depth;
|
||||
const geometry = segmentData.geometry;
|
||||
let coordinates;
|
||||
const segment = segmentData.segment;
|
||||
const index = dragSegment[1];
|
||||
|
||||
while (vertex.length < geometry.getStride()) {
|
||||
vertex.push(segment[index][vertex.length]);
|
||||
}
|
||||
|
||||
switch (geometry.getType()) {
|
||||
case GeometryType.POINT:
|
||||
coordinates = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POINT:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index] = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.CIRCLE:
|
||||
segment[0] = segment[1] = vertex;
|
||||
if (segmentData.index === CIRCLE_CENTER_INDEX) {
|
||||
this.changingFeature_ = true;
|
||||
geometry.setCenter(vertex);
|
||||
this.changingFeature_ = false;
|
||||
} else { // We're dragging the circle's circumference:
|
||||
this.changingFeature_ = true;
|
||||
geometry.setRadius(coordinateDistance(geometry.getCenter(), vertex));
|
||||
this.changingFeature_ = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
|
||||
if (coordinates) {
|
||||
this.setGeometryCoordinates_(geometry, coordinates);
|
||||
}
|
||||
}
|
||||
this.createOrUpdateVertexFeature_(vertex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} evt Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleUpEvent(evt) {
|
||||
for (let i = this.dragSegments_.length - 1; i >= 0; --i) {
|
||||
const segmentData = this.dragSegments_[i][0];
|
||||
const geometry = segmentData.geometry;
|
||||
if (geometry.getType() === GeometryType.CIRCLE) {
|
||||
// Update a circle object in the R* bush:
|
||||
const coordinates = geometry.getCenter();
|
||||
const centerSegmentData = segmentData.featureSegments[0];
|
||||
const circumferenceSegmentData = segmentData.featureSegments[1];
|
||||
centerSegmentData.segment[0] = centerSegmentData.segment[1] = coordinates;
|
||||
circumferenceSegmentData.segment[0] = circumferenceSegmentData.segment[1] = coordinates;
|
||||
this.rBush_.update(createOrUpdateFromCoordinate(coordinates), centerSegmentData);
|
||||
this.rBush_.update(geometry.getExtent(), circumferenceSegmentData);
|
||||
} else {
|
||||
this.rBush_.update(boundingExtent(segmentData.segment), segmentData);
|
||||
}
|
||||
}
|
||||
if (this.modified_) {
|
||||
this.dispatchEvent(new ModifyEvent(ModifyEventType.MODIFYEND, this.features_, evt));
|
||||
this.modified_ = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may modify the
|
||||
* geometry.
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} `false` to stop event propagation.
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleEvent(mapBrowserEvent) {
|
||||
if (!(mapBrowserEvent instanceof MapBrowserPointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
this.lastPointerEvent_ = mapBrowserEvent;
|
||||
|
||||
let handled;
|
||||
if (!mapBrowserEvent.map.getView().getInteracting() &&
|
||||
mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE &&
|
||||
!this.handlingDownUpSequence) {
|
||||
this.handlePointerMove_(mapBrowserEvent);
|
||||
}
|
||||
if (this.vertexFeature_ && this.deleteCondition_(mapBrowserEvent)) {
|
||||
if (mapBrowserEvent.type != MapBrowserEventType.SINGLECLICK || !this.ignoreNextSingleClick_) {
|
||||
handled = this.removePoint();
|
||||
} else {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.SINGLECLICK) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
}
|
||||
|
||||
return handlePointerEvent.call(this, mapBrowserEvent) && !handled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance from a point to a line segment.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user