Convert feature copying functionality from a standalone behavior to an operation and add to edit menu (re: #2508)

Show flash feedback message when copying features with keyboard shortcut
Disallow copying of untagged vertices
This commit is contained in:
Quincy Morgan
2020-05-13 15:42:28 -04:00
parent e0a23723da
commit 0278e700a0
7 changed files with 96 additions and 53 deletions
+8
View File
@@ -80,6 +80,14 @@ en:
annotation: Changed the role of a relation member.
change_tags:
annotation: Changed tags.
copy:
title: Copy
description:
single: Make this feature pasteable.
multiple: Make these features pasteable.
annotation:
single: Copied a feature.
multiple: "Copied {n} features."
circularize:
title: Circularize
description:
+11
View File
@@ -103,6 +103,17 @@
"change_tags": {
"annotation": "Changed tags."
},
"copy": {
"title": "Copy",
"description": {
"single": "Make this feature pasteable.",
"multiple": "Make these features pasteable."
},
"annotation": {
"single": "Copied a feature.",
"multiple": "Copied {n} features."
}
},
"circularize": {
"title": "Circularize",
"description": {
-1
View File
@@ -1,6 +1,5 @@
export { behaviorAddWay } from './add_way';
export { behaviorBreathe } from './breathe';
export { behaviorCopy } from './copy';
export { behaviorDrag } from './drag';
export { behaviorDrawWay } from './draw_way';
export { behaviorDraw } from './draw';
-2
View File
@@ -6,7 +6,6 @@ import { actionAddMidpoint } from '../actions/add_midpoint';
import { actionDeleteRelation } from '../actions/delete_relation';
import { behaviorBreathe } from '../behavior/breathe';
import { behaviorCopy } from '../behavior/copy';
import { behaviorHover } from '../behavior/hover';
import { behaviorLasso } from '../behavior/lasso';
import { behaviorPaste } from '../behavior/paste';
@@ -38,7 +37,6 @@ export function modeSelect(context, selectedIDs) {
var keybinding = utilKeybinding('select');
var breatheBehavior = behaviorBreathe(context);
var behaviors = [
behaviorCopy(context),
behaviorPaste(context),
breatheBehavior,
behaviorHover(context),
@@ -1,10 +1,57 @@
import { event as d3_event } from 'd3-selection';
import { t } from '../core/localizer';
import { behaviorOperation } from '../behavior/operation';
import { uiCmd } from '../ui/cmd';
import { utilArrayGroupBy } from '../util';
export function operationCopy(selectedIDs, context) {
function getFilteredIdsToCopy() {
return selectedIDs.filter(function(selectedID) {
var entity = context.graph().hasEntity(selectedID);
// don't copy untagged vertices separately from ways
return entity.hasInterestingTags() || entity.geometry(context.graph()) !== 'vertex';
});
}
var operation = function() {
if (!getSelectionText()) {
d3_event.preventDefault();
}
var graph = context.graph();
var selected = groupEntities(getFilteredIdsToCopy(), graph);
var canCopy = [];
var skip = {};
var entity;
var i;
for (i = 0; i < selected.relation.length; i++) {
entity = selected.relation[i];
if (!skip[entity.id] && entity.isComplete(graph)) {
canCopy.push(entity.id);
skip = getDescendants(entity.id, graph, skip);
}
}
for (i = 0; i < selected.way.length; i++) {
entity = selected.way[i];
if (!skip[entity.id]) {
canCopy.push(entity.id);
skip = getDescendants(entity.id, graph, skip);
}
}
for (i = 0; i < selected.node.length; i++) {
entity = selected.node[i];
if (!skip[entity.id]) {
canCopy.push(entity.id);
}
}
context.copyIDs(canCopy);
};
export function behaviorCopy(context) {
function groupEntities(ids, graph) {
var entities = ids.map(function (id) { return graph.entity(id); });
@@ -45,55 +92,34 @@ export function behaviorCopy(context) {
}
function doCopy() {
// prevent copy during low zoom selection
if (!context.map().withinEditableZoom()) return;
if (!getSelectionText()) {
d3_event.preventDefault();
}
var graph = context.graph();
var selected = groupEntities(context.selectedIDs(), graph);
var canCopy = [];
var skip = {};
var entity;
var i;
for (i = 0; i < selected.relation.length; i++) {
entity = selected.relation[i];
if (!skip[entity.id] && entity.isComplete(graph)) {
canCopy.push(entity.id);
skip = getDescendants(entity.id, graph, skip);
}
}
for (i = 0; i < selected.way.length; i++) {
entity = selected.way[i];
if (!skip[entity.id]) {
canCopy.push(entity.id);
skip = getDescendants(entity.id, graph, skip);
}
}
for (i = 0; i < selected.node.length; i++) {
entity = selected.node[i];
if (!skip[entity.id]) {
canCopy.push(entity.id);
}
}
context.copyIDs(canCopy);
}
function behavior() {
context.keybinding().on(uiCmd('⌘C'), doCopy);
return behavior;
}
behavior.off = function() {
context.keybinding().off(uiCmd('⌘C'));
operation.available = function() {
return getFilteredIdsToCopy().length > 0;
};
return behavior;
operation.disabled = function() {
return false;
};
operation.tooltip = function() {
return selectedIDs.length === 1 ?
t('operations.copy.description.single') :
t('operations.copy.description.multiple');
};
operation.annotation = function() {
return selectedIDs.length === 1 ?
t('operations.copy.annotation.single') :
t('operations.copy.annotation.multiple', { n: selectedIDs.length });
};
operation.id = 'copy';
operation.keys = [uiCmd('⌘C')];
operation.title = t('operations.copy.title');
operation.behavior = behaviorOperation(context).which(operation);
return operation;
}
+1
View File
@@ -1,5 +1,6 @@
export { operationCircularize } from './circularize';
export { operationContinue } from './continue';
export { operationCopy } from './copy';
export { operationDelete } from './delete';
export { operationDisconnect } from './disconnect';
export { operationDowngrade } from './downgrade';
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="20" height="20" viewBox="0 0 20 20">
<path d="M16,7 C16.552,7 17,7.448 17,8 L17,16 C17,16.552 16.552,17 16,17 L8,17 C7.448,17 7,16.552 7,16 L7,8 C7,7.448 7.448,7 8,7 L16,7 z M15,9 L9,9 L9,15 L15,15 L15,9 z" fill="inherit"/>
<path d="M16,7 C16.552,7 17,7.448 17,8 L17,16 C17,16.552 16.552,17 16,17 L8,17 C7.448,17 7,16.552 7,16 L7,8 C7,7.448 7.448,7 8,7 L16,7 z M15,9 L9,9 L9,15 L15,15 L15,9 z" fill="currentColor"/>
<path d="M11,1 C11.552,1 12,1.448 12,2 L12,6 L10,6 L10,3 L4,3 L4,9 L6,9 L6,11 L3,11 C2.448,11 2,10.552 2,10 L2,2 C2,1.448 2.448,1 3,1 L11,1 z" fill="inherit"/>
</svg>

Before

Width:  |  Height:  |  Size: 653 B

After

Width:  |  Height:  |  Size: 658 B