diff --git a/data/core.yaml b/data/core.yaml index 86a7c9a04..22a88f5e7 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -104,20 +104,40 @@ en: orthogonalize: title: Square description: - vertex: Square this corner. - line: Square the corners of this line. - area: Square the corners of this area. + corner: + single: Square this corner. + multiple: Square these corners. + feature: + single: Square the corners of this feature. + multiple: Square the corners of these features. key: Q annotation: - vertex: Squared a single corner. - line: Squared the corners of a line. - area: Squared the corners of an area. - end_vertex: This can't be squared because it is an end node. - square_enough: This can't be made more square than it already is. - not_squarish: This can't be made square because it is not squarish. - too_large: This can't be made square because not enough of it is currently visible. - connected_to_hidden: This can't be made square because it is connected to a hidden feature. - not_downloaded: This can't be made square because parts of it have not yet been downloaded. + corner: + single: Squared a corner. + multiple: Squared several corners. + feature: + single: Squared the corners of a feature. + multiple: Squared the corners of several features. + multiple_blockers: + multiple: These can't be squared for multiple reasons. + end_vertex: + single: This can't be squared because it is an endpoint. + multiple: These can't be squared because they are endpoints. + square_enough: + single: This can't be made more square than it already is. + multiple: These can't be made more square than they already are. + not_squarish: + single: This can't be made square because it is not squarish. + multiple: These can't be made square because they are not squarish. + too_large: + single: This can't be made square because not enough of it is currently visible. + multiple: These can't be made square because not enought of them are currently visible. + connected_to_hidden: + single: This can't be made square because it is connected to a hidden feature. + multiple: These can't be made square because some are connected to hidden features. + not_downloaded: + single: This can't be made square because parts of it have not yet been downloaded. + multiple: These can't be made square because parts of them have not yet been downloaded. straighten: title: Straighten description: diff --git a/dist/locales/en.json b/dist/locales/en.json index b5777bcb8..47e6715b8 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -134,22 +134,53 @@ "orthogonalize": { "title": "Square", "description": { - "vertex": "Square this corner.", - "line": "Square the corners of this line.", - "area": "Square the corners of this area." + "corner": { + "single": "Square this corner.", + "multiple": "Square these corners." + }, + "feature": { + "single": "Square the corners of this feature.", + "multiple": "Square the corners of these features." + } }, "key": "Q", "annotation": { - "vertex": "Squared a single corner.", - "line": "Squared the corners of a line.", - "area": "Squared the corners of an area." + "corner": { + "single": "Squared a corner.", + "multiple": "Squared several corners." + }, + "feature": { + "single": "Squared the corners of a feature.", + "multiple": "Squared the corners of several features." + } }, - "end_vertex": "This can't be squared because it is an end node.", - "square_enough": "This can't be made more square than it already is.", - "not_squarish": "This can't be made square because it is not squarish.", - "too_large": "This can't be made square because not enough of it is currently visible.", - "connected_to_hidden": "This can't be made square because it is connected to a hidden feature.", - "not_downloaded": "This can't be made square because parts of it have not yet been downloaded." + "multiple_blockers": { + "multiple": "These can't be squared for multiple reasons." + }, + "end_vertex": { + "single": "This can't be squared because it is an endpoint.", + "multiple": "These can't be squared because they are endpoints." + }, + "square_enough": { + "single": "This can't be made more square than it already is.", + "multiple": "These can't be made more square than they already are." + }, + "not_squarish": { + "single": "This can't be made square because it is not squarish.", + "multiple": "These can't be made square because they are not squarish." + }, + "too_large": { + "single": "This can't be made square because not enough of it is currently visible.", + "multiple": "These can't be made square because not enought of them are currently visible." + }, + "connected_to_hidden": { + "single": "This can't be made square because it is connected to a hidden feature.", + "multiple": "These can't be made square because some are connected to hidden features." + }, + "not_downloaded": { + "single": "This can't be made square because parts of it have not yet been downloaded.", + "multiple": "These can't be made square because parts of them have not yet been downloaded." + } }, "straighten": { "title": "Straighten", diff --git a/modules/operations/orthogonalize.js b/modules/operations/orthogonalize.js index 369e5790f..fd79be8e0 100644 --- a/modules/operations/orthogonalize.js +++ b/modules/operations/orthogonalize.js @@ -5,33 +5,41 @@ import { utilGetAllNodes } from '../util'; export function operationOrthogonalize(selectedIDs, context) { - var _entityID; - var _entity; - var _geometry; - var action = chooseAction(); + var _extent; + var type; + var actions = selectedIDs.map(chooseAction).filter(Boolean); + var amount = actions.length === 1 ? 'single' : 'multiple'; var nodes = utilGetAllNodes(selectedIDs, context.graph()); var coords = nodes.map(function(n) { return n.loc; }); - function chooseAction() { - if (selectedIDs.length !== 1) return null; + function chooseAction(entityID) { - _entityID = selectedIDs[0]; - _entity = context.entity(_entityID); - _geometry = context.geometry(_entityID); + var entity = context.entity(entityID); + var geometry = context.geometry(entityID); + + if (!_extent) { + _extent = entity.extent(context.graph()); + } else { + _extent = _extent.extend(entity.extent(context.graph())); + } // square a line/area - if (_entity.type === 'way' && new Set(_entity.nodes).size > 2 ) { - return actionOrthogonalize(_entityID, context.projection); + if (entity.type === 'way' && new Set(entity.nodes).size > 2 ) { + if (type && type !== 'feature') return null; + type = 'feature'; + return actionOrthogonalize(entityID, context.projection); // square a single vertex - } else if (_geometry === 'vertex') { + } else if (geometry === 'vertex') { + if (type && type !== 'corner') return null; + type = 'corner'; var graph = context.graph(); - var parents = graph.parentWays(_entity); + var parents = graph.parentWays(entity); if (parents.length === 1) { var way = parents[0]; - if (way.nodes.indexOf(_entityID) !== -1) { - return actionOrthogonalize(way.id, context.projection, _entityID); + if (way.nodes.indexOf(entityID) !== -1) { + return actionOrthogonalize(way.id, context.projection, entityID); } } } @@ -41,9 +49,19 @@ export function operationOrthogonalize(selectedIDs, context) { var operation = function() { - if (!action) return; + if (!actions.length) return; - context.perform(action, operation.annotation()); + var combinedAction = function(graph, t) { + actions.forEach(function(action) { + if (!action.disabled(graph)) { + graph = action(graph, t); + } + }); + return graph; + }; + combinedAction.transitionable = true; + + context.perform(combinedAction, operation.annotation()); window.setTimeout(function() { context.validator().validate(); @@ -52,19 +70,33 @@ export function operationOrthogonalize(selectedIDs, context) { operation.available = function() { - return Boolean(action); + return actions.length && selectedIDs.length === actions.length; }; // don't cache this because the visible extent could change operation.disabled = function() { - if (!action) return ''; + if (!actions.length) return ''; + + var actionDisabled; + + var actionDisableds = {}; + + if (actions.every(function(action) { + var disabled = action.disabled(context.graph()); + if (disabled) actionDisableds[disabled] = true; + return disabled; + })) { + actionDisabled = actions[0].disabled(context.graph()); + } - var actionDisabled = action.disabled(context.graph()); if (actionDisabled) { + if (Object.keys(actionDisableds).length > 1) { + return 'multiple_blockers'; + } return actionDisabled; - } else if (_geometry !== 'vertex' && - _entity.extent(context.graph()).percentContainedIn(context.extent()) < 0.8) { + } else if (type !== 'corner' && + _extent.percentContainedIn(context.extent()) < 0.8) { return 'too_large'; } else if (someMissing()) { return 'not_downloaded'; @@ -93,13 +125,13 @@ export function operationOrthogonalize(selectedIDs, context) { operation.tooltip = function() { var disable = operation.disabled(); return disable ? - t('operations.orthogonalize.' + disable) : - t('operations.orthogonalize.description.' + _geometry); + t('operations.orthogonalize.' + disable + '.' + amount) : + t('operations.orthogonalize.description.' + type + '.' + amount); }; operation.annotation = function() { - return t('operations.orthogonalize.annotation.' + _geometry); + return t('operations.orthogonalize.annotation.' + type + '.' + amount); };