diff --git a/modules/modes/select.js b/modules/modes/select.js index f84f64331..f81da0dd7 100644 --- a/modules/modes/select.js +++ b/modules/modes/select.js @@ -28,9 +28,6 @@ import { } from '../util'; -var _relatedParent; - - export function modeSelect(context, selectedIDs) { var mode = { id: 'select', @@ -48,6 +45,10 @@ export function modeSelect(context, selectedIDs) { var _newFeature = false; var _follow = false; + // `_focusedParentWayId` is used when we visit a vertex with multiple + // parents, and we want to remember which parent line we started on. + var _focusedParentWayId; + function singular() { if (selectedIDs && selectedIDs.length === 1) { @@ -86,14 +87,14 @@ export function modeSelect(context, selectedIDs) { // find the parent ways for nextVertex, previousVertex, and selectParent - function multipleParents(onlyCommonParents) { + function parentWaysIdsOfSelection(onlyCommonParents) { var graph = context.graph(); var parents = []; for (var i = 0; i < selectedIDs.length; i++) { var entity = context.hasEntity(selectedIDs[i]); if (!entity || entity.geometry(graph) !== 'vertex') { - return []; // selection includes some not vertices + return []; // selection includes some non-vertices } var currParents = graph.parentWays(entity).map(function(w) { return w.id; }); @@ -112,26 +113,23 @@ export function modeSelect(context, selectedIDs) { } - function singularParent() { - var parents = multipleParents(true); - if (!parents || parents.length === 0) { - _relatedParent = null; - return null; + function checkFocusedParent() { + if (_focusedParentWayId) { + var parents = parentWaysIdsOfSelection(true); + if (parents.indexOf(_focusedParentWayId) === -1) _focusedParentWayId = null; + } + } + + + function parentWayIdForVertexNavigation() { + var parentIds = parentWaysIdsOfSelection(true); + + if (_focusedParentWayId && parentIds.indexOf(_focusedParentWayId) !== -1) { + // prefer the previously seen parent + return _focusedParentWayId; } - // relatedParent is used when we visit a vertex with multiple - // parents, and we want to remember which parent line we started on. - - if (parents.length === 1) { - _relatedParent = parents[0]; // remember this parent for later - return _relatedParent; - } - - if (parents.indexOf(_relatedParent) !== -1) { - return _relatedParent; // prefer the previously seen parent - } - - return parents[0]; + return parentIds.length ? parentIds[0] : null; } @@ -244,7 +242,7 @@ export function modeSelect(context, selectedIDs) { .on(utilKeybinding.plusKeys.map((key) => uiCmd('⇧⌥' + key)), scaleSelection(Math.pow(1.05, 5))) .on(utilKeybinding.minusKeys.map((key) => uiCmd('⇧' + key)), scaleSelection(1/1.05)) .on(utilKeybinding.minusKeys.map((key) => uiCmd('⇧⌥' + key)), scaleSelection(1/Math.pow(1.05, 5))) - .on(['\\', 'pause'], nextParent) + .on(['\\', 'pause'], focusNextParent) .on(uiCmd('⌘↑'), selectParent) .on('⎋', esc, true); @@ -427,9 +425,10 @@ export function modeSelect(context, selectedIDs) { surface.selectAll('.related') .classed('related', false); - singularParent(); - if (_relatedParent) { - surface.selectAll(utilEntitySelector([_relatedParent])) + // reload `_focusedParentWayId` based on the current selection + checkFocusedParent(); + if (_focusedParentWayId) { + surface.selectAll(utilEntitySelector([_focusedParentWayId])) .classed('related', true); } @@ -456,18 +455,20 @@ export function modeSelect(context, selectedIDs) { function firstVertex(d3_event) { d3_event.preventDefault(); var entity = singular(); - var parent = singularParent(); + var parentId = parentWayIdForVertexNavigation(); var way; if (entity && entity.type === 'way') { way = entity; - } else if (parent) { - way = context.entity(parent); + } else if (parentId) { + way = context.entity(parentId); } + _focusedParentWayId = way && way.id; if (way) { context.enter( - modeSelect(context, [way.first()]).follow(true) + mode.selectedIDs([way.first()]) + .follow(true) ); } } @@ -476,18 +477,20 @@ export function modeSelect(context, selectedIDs) { function lastVertex(d3_event) { d3_event.preventDefault(); var entity = singular(); - var parent = singularParent(); + var parentId = parentWayIdForVertexNavigation(); var way; if (entity && entity.type === 'way') { way = entity; - } else if (parent) { - way = context.entity(parent); + } else if (parentId) { + way = context.entity(parentId); } + _focusedParentWayId = way && way.id; if (way) { context.enter( - modeSelect(context, [way.last()]).follow(true) + mode.selectedIDs([way.last()]) + .follow(true) ); } } @@ -495,10 +498,11 @@ export function modeSelect(context, selectedIDs) { function previousVertex(d3_event) { d3_event.preventDefault(); - var parent = singularParent(); - if (!parent) return; + var parentId = parentWayIdForVertexNavigation(); + _focusedParentWayId = parentId; + if (!parentId) return; - var way = context.entity(parent); + var way = context.entity(parentId); var length = way.nodes.length; var curr = way.nodes.indexOf(selectedIDs[0]); var index = -1; @@ -511,7 +515,8 @@ export function modeSelect(context, selectedIDs) { if (index !== -1) { context.enter( - modeSelect(context, [way.nodes[index]]).follow(true) + mode.selectedIDs([way.nodes[index]]) + .follow(true) ); } } @@ -519,10 +524,11 @@ export function modeSelect(context, selectedIDs) { function nextVertex(d3_event) { d3_event.preventDefault(); - var parent = singularParent(); - if (!parent) return; + var parentId = parentWayIdForVertexNavigation(); + _focusedParentWayId = parentId; + if (!parentId) return; - var way = context.entity(parent); + var way = context.entity(parentId); var length = way.nodes.length; var curr = way.nodes.indexOf(selectedIDs[0]); var index = -1; @@ -535,37 +541,38 @@ export function modeSelect(context, selectedIDs) { if (index !== -1) { context.enter( - modeSelect(context, [way.nodes[index]]).follow(true) + mode.selectedIDs([way.nodes[index]]) + .follow(true) ); } } - function nextParent(d3_event) { + function focusNextParent(d3_event) { d3_event.preventDefault(); - var parents = multipleParents(true); + var parents = parentWaysIdsOfSelection(true); if (!parents || parents.length < 2) return; - var index = parents.indexOf(_relatedParent); + var index = parents.indexOf(_focusedParentWayId); if (index < 0 || index > parents.length - 2) { - _relatedParent = parents[0]; + _focusedParentWayId = parents[0]; } else { - _relatedParent = parents[index + 1]; + _focusedParentWayId = parents[index + 1]; } var surface = context.surface(); surface.selectAll('.related') .classed('related', false); - if (_relatedParent) { - surface.selectAll(utilEntitySelector([_relatedParent])) + if (_focusedParentWayId) { + surface.selectAll(utilEntitySelector([_focusedParentWayId])) .classed('related', true); } } function selectParent(d3_event) { d3_event.preventDefault(); - var parents = _relatedParent ? [_relatedParent] : multipleParents(false); + var parents = _focusedParentWayId ? [_focusedParentWayId] : parentWaysIdsOfSelection(false); if (!parents || parents.length === 0) return; context.enter( @@ -577,6 +584,7 @@ export function modeSelect(context, selectedIDs) { mode.exit = function() { + // we could enter the mode multiple times but it's only new the first time _newFeature = false; _operations.forEach(function(operation) {