Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor internal events API #1266

Merged
merged 6 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,9 @@ export default function(ctx) {
currentModeRender(geojson, push) {
return currentMode.render(geojson, push);
},
fire(name, event) {
if (events[name]) {
events[name](event);
}
fire(eventName, eventData) {
if (!ctx.map) return;
ctx.map.fire(eventName, eventData);
},
addEventListeners() {
ctx.map.on('mousemove', events.mousemove);
Expand Down
2 changes: 1 addition & 1 deletion src/modes/direct_select.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const DirectSelect = {};
// INTERNAL FUCNTIONS

DirectSelect.fireUpdate = function() {
this.map.fire(Constants.events.UPDATE, {
this.fire(Constants.events.UPDATE, {
action: Constants.updateActions.CHANGE_COORDINATES,
features: this.getSelected().map(f => f.toGeoJSON())
});
Expand Down
2 changes: 1 addition & 1 deletion src/modes/draw_line_string.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ DrawLineString.onStop = function(state) {
//remove last added coordinate
state.line.removeCoordinate(`${state.currentVertexPosition}`);
if (state.line.isValid()) {
this.map.fire(Constants.events.CREATE, {
this.fire(Constants.events.CREATE, {
features: [state.line.toGeoJSON()]
});
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/modes/draw_point.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ DrawPoint.stopDrawingAndRemove = function(state) {
DrawPoint.onTap = DrawPoint.onClick = function(state, e) {
this.updateUIClasses({ mouse: Constants.cursors.MOVE });
state.point.updateCoordinate('', e.lngLat.lng, e.lngLat.lat);
this.map.fire(Constants.events.CREATE, {
this.fire(Constants.events.CREATE, {
features: [state.point.toGeoJSON()]
});
this.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [state.point.id] });
Expand Down
2 changes: 1 addition & 1 deletion src/modes/draw_polygon.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ DrawPolygon.onStop = function(state) {
//remove last added coordinate
state.polygon.removeCoordinate(`0.${state.currentVertexPosition}`);
if (state.polygon.isValid()) {
this.map.fire(Constants.events.CREATE, {
this.fire(Constants.events.CREATE, {
features: [state.polygon.toGeoJSON()]
});
} else {
Expand Down
10 changes: 10 additions & 0 deletions src/modes/mode_interface_accessors.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,16 @@ ModeInterface.prototype.changeMode = function(mode, opts = {}, eventOpts = {}) {
return this._ctx.events.changeMode(mode, opts, eventOpts);
};

/**
* Fire a map event
* @name this.fire
* @param {String} eventName - the event name.
* @param {Object} eventData - the event data object.
*/
ModeInterface.prototype.fire = function(eventName, eventData) {
return this._ctx.events.fire(eventName, eventData);
};

/**
* Update the state of draw map classes
* @name this.updateUIClasses
Expand Down
6 changes: 3 additions & 3 deletions src/modes/simple_select.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ SimpleSelect.onSetup = function(opts) {
};

SimpleSelect.fireUpdate = function() {
this.map.fire(Constants.events.UPDATE, {
this.fire(Constants.events.UPDATE, {
action: Constants.updateActions.MOVE,
features: this.getSelected().map(f => f.toGeoJSON())
});
Expand Down Expand Up @@ -347,7 +347,7 @@ SimpleSelect.onCombineFeatures = function() {
this.deleteFeature(this.getSelectedIds(), { silent: true });
this.setSelected([multiFeature.id]);

this.map.fire(Constants.events.COMBINE_FEATURES, {
this.fire(Constants.events.COMBINE_FEATURES, {
createdFeatures: [multiFeature.toGeoJSON()],
deletedFeatures: featuresCombined
});
Expand Down Expand Up @@ -378,7 +378,7 @@ SimpleSelect.onUncombineFeatures = function() {
}

if (createdFeatures.length > 1) {
this.map.fire(Constants.events.UNCOMBINE_FEATURES, {
this.fire(Constants.events.UNCOMBINE_FEATURES, {
createdFeatures,
deletedFeatures: featuresUncombined
});
Expand Down
26 changes: 0 additions & 26 deletions src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,33 +52,7 @@ export default function render() {
features: store.sources.hot
});

if (store._emitSelectionChange) {
store.ctx.map.fire(Constants.events.SELECTION_CHANGE, {
features: store.getSelected().map(feature => feature.toGeoJSON()),
points: store.getSelectedCoordinates().map(coordinate => ({
type: Constants.geojsonTypes.FEATURE,
properties: {},
geometry: {
type: Constants.geojsonTypes.POINT,
coordinates: coordinate.coordinates
}
}))
});
store._emitSelectionChange = false;
}

if (store._deletedFeaturesToEmit.length) {
const geojsonToEmit = store._deletedFeaturesToEmit.map(feature => feature.toGeoJSON());

store._deletedFeaturesToEmit = [];

store.ctx.map.fire(Constants.events.DELETE, {
features: geojsonToEmit
});
}

cleanup();
store.ctx.map.fire(Constants.events.RENDER, {});

function cleanup() {
store.isDirty = false;
Expand Down
39 changes: 32 additions & 7 deletions src/store.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import toDenseArray from './lib/to_dense_array.js';
import StringSet from './lib/string_set.js';
import render from './render.js';
import {interactions} from './constants.js';
import * as Constants from './constants.js';

export default function Store(ctx) {
this._features = {};
this._featureIds = new StringSet();
this._selectedFeatureIds = new StringSet();
this._selectedCoordinates = [];
this._changedFeatureIds = new StringSet();
this._deletedFeaturesToEmit = [];
this._emitSelectionChange = false;
this._mapInitialConfig = {};
this.ctx = ctx;
Expand All @@ -25,13 +24,33 @@ export default function Store(ctx) {
renderRequest = requestAnimationFrame(() => {
renderRequest = null;
render.call(this);

// Fire deduplicated selection change event
if (this._emitSelectionChange) {
this.ctx.events.fire(Constants.events.SELECTION_CHANGE, {
features: this.getSelected().map(feature => feature.toGeoJSON()),
points: this.getSelectedCoordinates().map(coordinate => ({
type: Constants.geojsonTypes.FEATURE,
properties: {},
geometry: {
type: Constants.geojsonTypes.POINT,
coordinates: coordinate.coordinates
}
}))
});

this._emitSelectionChange = false;
}

// Fire render event
this.ctx.events.fire(Constants.events.RENDER, {});
});
}
};

this.isDirty = false;
}


/**
* Delays all rendering until the returned function is invoked
* @return {Function} renderBatch
Expand Down Expand Up @@ -119,18 +138,24 @@ Store.prototype.add = function(feature) {
* @return {Store} this
*/
Store.prototype.delete = function(featureIds, options = {}) {
const deletedFeaturesToEmit = [];
toDenseArray(featureIds).forEach((id) => {
if (!this._featureIds.has(id)) return;
this._featureIds.delete(id);
this._selectedFeatureIds.delete(id);
if (!options.silent) {
if (this._deletedFeaturesToEmit.indexOf(this._features[id]) === -1) {
this._deletedFeaturesToEmit.push(this._features[id]);
if (deletedFeaturesToEmit.indexOf(this._features[id]) === -1) {
deletedFeaturesToEmit.push(this._features[id].toGeoJSON());
}
}
delete this._features[id];
this.isDirty = true;
});

if (deletedFeaturesToEmit.length) {
this.ctx.events.fire(Constants.events.DELETE, {features: deletedFeaturesToEmit});
}

refreshSelectedCoordinates(this, options);
return this;
};
Expand Down Expand Up @@ -256,7 +281,7 @@ Store.prototype.getSelectedIds = function() {
* @return {Array<Object>} Selected features.
*/
Store.prototype.getSelected = function() {
return this._selectedFeatureIds.values().map(id => this.get(id));
return this.getSelectedIds().map(id => this.get(id));
};

/**
Expand Down Expand Up @@ -305,7 +330,7 @@ function refreshSelectedCoordinates(store, options) {
* Stores the initial config for a map, so that we can set it again after we're done.
*/
Store.prototype.storeMapConfig = function() {
interactions.forEach((interaction) => {
Constants.interactions.forEach((interaction) => {
const interactionSet = this.ctx.map[interaction];
if (interactionSet) {
this._mapInitialConfig[interaction] = this.ctx.map[interaction].isEnabled();
Expand Down
19 changes: 13 additions & 6 deletions test/store.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {spy} from 'sinon';

import Store from '../src/store.js';
import createFeature from './utils/create_feature.js';
import getPublicMemberKeys from './utils/get_public_member_keys.js';
import createMap from './utils/create_map.js';

function createStore() {
const map = createMap();
const ctx = { map };
const ctx = {
map: createMap(),
events: {
fire: spy()
}
};

return new Store(ctx);
}

Expand Down Expand Up @@ -211,16 +218,16 @@ test('Store#setSelected', () => {
const line = createFeature('line');
const polygon = createFeature('polygon');

store.setSelected(point.id);
store.setSelected(point.id, {silent: true});
assert.deepEqual(store.getSelectedIds(), [point.id]);

store.setSelected([line.id, polygon.id]);
store.setSelected([line.id, polygon.id], {silent: true});
assert.deepEqual(store.getSelectedIds(), [line.id, polygon.id]);

store.setSelected(line.id);
store.setSelected(line.id, {silent: true});
assert.deepEqual(store.getSelectedIds(), [line.id]);

store.setSelected();
store.setSelected(undefined, {silent: true});
assert.deepEqual(store.getSelectedIds(), []);
});

Expand Down
1 change: 1 addition & 0 deletions test/utils/create_mock_draw_mode_context.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function createMockDrawModeContext() {
}
},
events: {
fire: spy(),
changeMode: spy(),
actionable: spy()
},
Expand Down