Allow Alt/option key to disable geometry check and nope cursor

(re: #4646)
This commit is contained in:
Bryan Housel
2018-01-08 15:47:29 -05:00
parent 58eaca2aa0
commit ea9643e08b
3 changed files with 120 additions and 12 deletions

View File

@@ -34,8 +34,8 @@
}
/* `.target-nope` objects are explicitly forbidden to join to */
.node.target.target-nope,
.way.target.target-nope {
.surface:not(.nope-disabled) .node.target.target-nope,
.surface:not(.nope-disabled) .way.target.target-nope {
cursor: not-allowed;
}

View File

@@ -1,5 +1,12 @@
import { t } from '../util/locale';
import {
event as d3_event,
select as d3_select
} from 'd3-selection';
import { d3keybinding as d3_keybinding } from '../lib/d3.keybinding.js';
import {
actionAddMidpoint,
actionMoveNode,
@@ -34,11 +41,40 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {
_tempEdits++;
function keydown() {
if (d3_event.keyCode === d3_keybinding.modifierCodes.alt) {
if (context.surface().classed('nope')) {
context.surface()
.classed('nope-suppressed', true);
}
context.surface()
.classed('nope', false)
.classed('nope-disabled', true);
}
}
function keyup() {
if (d3_event.keyCode === d3_keybinding.modifierCodes.alt) {
if (context.surface().classed('nope-suppressed')) {
context.surface()
.classed('nope', true);
}
context.surface()
.classed('nope-suppressed', false)
.classed('nope-disabled', false);
}
}
// related code
// - `mode/drag_node.js` `doMode()`
// - `behavior/draw.js` `click()`
// - `behavior/draw_way.js` `move()`
function move(datum) {
context.surface().classed('nope-disabled', d3_event.altKey);
var nodeLoc = datum && datum.properties && datum.properties.entity && datum.properties.entity.loc;
var nodeGroups = datum && datum.properties && datum.properties.nodes;
var loc = context.map().mouseCoordinates();
@@ -68,9 +104,18 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {
// If so, class the surface with a nope cursor.
// `skipLast` - include closing segment in the check, see #4655
function checkGeometry(skipLast) {
var doBlock = isInvalidGeometry(end, context.graph(), skipLast);
context.surface()
.classed('nope', doBlock);
var nopeDisabled = context.surface().classed('nope-disabled');
var isInvalid = isInvalidGeometry(end, context.graph(), skipLast);
if (nopeDisabled) {
context.surface()
.classed('nope', false)
.classed('nope-suppressed', isInvalid);
} else {
context.surface()
.classed('nope', isInvalid)
.classed('nope-suppressed', false);
}
}
@@ -122,6 +167,10 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {
.on('cancel', drawWay.cancel)
.on('finish', drawWay.finish);
d3_select(window)
.on('keydown.drawWay', keydown)
.on('keyup.drawWay', keyup);
context.map()
.dblclickEnable(false)
.on('drawn.draw', setActiveElements);
@@ -153,6 +202,15 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {
.selectAll('.active')
.classed('active', false);
surface
.classed('nope', false)
.classed('nope-suppressed', false)
.classed('nope-disabled', false);
d3_select(window)
.on('keydown.hover', null)
.on('keyup.hover', null);
context.history()
.on('undone.draw', null);
};
@@ -274,7 +332,9 @@ export function behaviorDrawWay(context, wayId, index, mode, startGraph) {
}, 1000);
context.surface()
.classed('nope', false);
.classed('nope', false)
.classed('nope-disabled', false)
.classed('nope-suppressed', false);
context.enter(modeBrowse(context));
};

View File

@@ -5,6 +5,8 @@ import {
select as d3_select
} from 'd3-selection';
import { d3keybinding as d3_keybinding } from '../lib/d3.keybinding.js';
import { t } from '../util/locale';
import {
@@ -83,6 +85,32 @@ export function modeDragNode(context) {
}
function keydown() {
if (d3_event.keyCode === d3_keybinding.modifierCodes.alt) {
if (context.surface().classed('nope')) {
context.surface()
.classed('nope-suppressed', true);
}
context.surface()
.classed('nope', false)
.classed('nope-disabled', true);
}
}
function keyup() {
if (d3_event.keyCode === d3_keybinding.modifierCodes.alt) {
if (context.surface().classed('nope-suppressed')) {
context.surface()
.classed('nope', true);
}
context.surface()
.classed('nope-suppressed', false)
.classed('nope-disabled', false);
}
}
function start(entity) {
_wasMidpoint = entity.type === 'midpoint';
var hasHidden = context.features().hasHiddenConnections(entity, context.graph());
@@ -173,15 +201,23 @@ export function modeDragNode(context) {
// check if this movement causes the geometry to break
var doBlock = invalidGeometry(entity, context.graph());
context.surface()
.classed('nope', doBlock);
var nopeDisabled = context.surface().classed('nope-disabled');
var isInvalid = isInvalidGeometry(entity, context.graph());
if (nopeDisabled) {
context.surface()
.classed('nope', false)
.classed('nope-suppressed', isInvalid);
} else {
context.surface()
.classed('nope', isInvalid)
.classed('nope-suppressed', false);
}
_lastLoc = loc;
}
function invalidGeometry(entity, graph) {
function isInvalidGeometry(entity, graph) {
var parents = graph.parentWays(entity);
var i, j, k;
@@ -223,7 +259,7 @@ export function modeDragNode(context) {
// If we still haven't tested this node's parent way for self-intersections.
// (because it's not a member of a multipolygon), test it now.
if (activeIndex !== null && parent.isClosed()) {
if (activeIndex === null && parent.isClosed()) {
nodes = parent.nodes.map(function(nodeID) { return graph.entity(nodeID); });
if (nodes.length && geoHasSelfIntersections(nodes, entity.id)) {
return true;
@@ -238,8 +274,10 @@ export function modeDragNode(context) {
function move(entity) {
if (_isCancelled) return;
d3_event.sourceEvent.stopPropagation();
context.surface().classed('nope-disabled', d3_event.sourceEvent.altKey);
_lastLoc = context.projection.invert(d3_event.point);
doMove(entity);
@@ -337,6 +375,10 @@ export function modeDragNode(context) {
context.install(hover);
context.install(edit);
d3_select(window)
.on('keydown.drawWay', keydown)
.on('keyup.drawWay', keyup);
context.history()
.on('undone.drag-node', cancel);
};
@@ -347,6 +389,10 @@ export function modeDragNode(context) {
context.uninstall(hover);
context.uninstall(edit);
d3_select(window)
.on('keydown.hover', null)
.on('keyup.hover', null);
context.history()
.on('undone.drag-node', null);
@@ -357,6 +403,8 @@ export function modeDragNode(context) {
context.surface()
.classed('nope', false)
.classed('nope-suppressed', false)
.classed('nope-disabled', false)
.selectAll('.active')
.classed('active', false);