mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-14 21:28:11 +02:00
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:
@@ -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:
|
||||
|
||||
Vendored
+11
@@ -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,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';
|
||||
|
||||
@@ -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,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,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 |
Reference in New Issue
Block a user