Files
iD/modules/behavior/select.js
2017-03-22 16:01:14 -04:00

152 lines
4.2 KiB
JavaScript

import * as d3 from 'd3';
import _ from 'lodash';
import { geoEuclideanDistance } from '../geo';
import { modeBrowse, modeSelect } from '../modes';
import { osmEntity } from '../osm';
export function behaviorSelect(context) {
var suppressMenu = true,
tolerance = 4,
p1 = null;
function keydown() {
if (d3.event && d3.event.shiftKey) {
context.surface()
.classed('behavior-multiselect', true);
}
}
function keyup() {
if (!d3.event || !d3.event.shiftKey) {
context.surface()
.classed('behavior-multiselect', false);
}
}
function point() {
return d3.mouse(context.container().node());
}
function contextmenu() {
if (!p1) p1 = point();
d3.event.preventDefault();
suppressMenu = false;
click();
}
function mousedown() {
if (!p1) p1 = point();
d3.select(window)
.on('mouseup.select', mouseup, true);
var isShowAlways = +context.storage('edit-menu-show-always') === 1;
suppressMenu = !isShowAlways;
}
function mouseup() {
click();
}
function click() {
d3.select(window)
.on('mouseup.select', null, true);
if (!p1) return;
var p2 = point(),
dist = geoEuclideanDistance(p1, p2);
p1 = null;
if (dist > tolerance) {
return;
}
var isMultiselect = d3.event.shiftKey || d3.select('#surface .lasso').node(),
isShowAlways = +context.storage('edit-menu-show-always') === 1,
datum = d3.event.target.__data__,
mode = context.mode();
if (datum && datum.type === 'midpoint') {
// do nothing..
} else if (!(datum instanceof osmEntity)) {
// clicked nothing..
if (!isMultiselect && mode.id !== 'browse') {
context.enter(modeBrowse(context));
}
} else {
// clicked an entity..
var selectedIDs = context.selectedIDs();
if (!isMultiselect) {
if (selectedIDs.length > 1 && (!suppressMenu && !isShowAlways)) {
// multiple things already selected, just show the menu...
mode.suppressMenu(false).reselect();
} else {
// select a single thing..
context.enter(modeSelect(context, [datum.id]).suppressMenu(suppressMenu));
}
} else {
if (selectedIDs.indexOf(datum.id) !== -1) {
// clicked entity is already in the selectedIDs list..
if (!suppressMenu && !isShowAlways) {
// don't deselect clicked entity, just show the menu.
mode.suppressMenu(false).reselect();
} else {
// deselect clicked entity, then reenter select mode or return to browse mode..
selectedIDs = _.without(selectedIDs, datum.id);
context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse(context));
}
} else {
// clicked entity is not in the selected list, add it..
selectedIDs = selectedIDs.concat([datum.id]);
context.enter(modeSelect(context, selectedIDs).suppressMenu(suppressMenu));
}
}
}
// reset for next time..
suppressMenu = true;
}
var behavior = function(selection) {
d3.select(window)
.on('keydown.select', keydown)
.on('keyup.select', keyup);
selection
.on('mousedown.select', mousedown)
.on('contextmenu.select', contextmenu);
keydown();
};
behavior.off = function(selection) {
d3.select(window)
.on('keydown.select', null)
.on('keyup.select', null)
.on('mouseup.select', null, true);
selection
.on('mousedown.select', null)
.on('contextmenu.select', null);
keyup();
};
return behavior;
}