mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-12 16:52:50 +00:00
enable keybindings for unavailable operations -> show info message
this should make it easier to discover what a given keypress was supposed to do (e.g. which operation it triggered) closes #9896
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { t } from '../core';
|
||||
|
||||
/* Creates a keybinding behavior for an operation */
|
||||
export function behaviorOperation(context) {
|
||||
var _operation;
|
||||
@@ -7,19 +9,26 @@ export function behaviorOperation(context) {
|
||||
// prevent operations during low zoom selection
|
||||
if (!context.map().withinEditableZoom()) return;
|
||||
|
||||
if (_operation.availableForKeypress && !_operation.availableForKeypress()) return;
|
||||
// ignore (temporarily) disabled operation keyboard shortcuts,
|
||||
// e.g. Ctrl+C while text is selected
|
||||
if (_operation.availableForKeypress?.() === false) return;
|
||||
|
||||
d3_event.preventDefault();
|
||||
|
||||
var disabled = _operation.disabled();
|
||||
|
||||
if (disabled) {
|
||||
if (!_operation.available()) {
|
||||
context.ui().flash
|
||||
.duration(4000)
|
||||
.iconName('#iD-operation-' + _operation.id)
|
||||
.iconClass('operation disabled')
|
||||
.label(t.append('operations._unavailable', {
|
||||
operation: t(`operations.${_operation.id}.title`) || _operation.id
|
||||
}))();
|
||||
} else if (_operation.disabled()) {
|
||||
context.ui().flash
|
||||
.duration(4000)
|
||||
.iconName('#iD-operation-' + _operation.id)
|
||||
.iconClass('operation disabled')
|
||||
.label(_operation.tooltip())();
|
||||
|
||||
} else {
|
||||
context.ui().flash
|
||||
.duration(2000)
|
||||
@@ -35,14 +44,19 @@ export function behaviorOperation(context) {
|
||||
|
||||
function behavior() {
|
||||
if (_operation && _operation.available()) {
|
||||
context.keybinding()
|
||||
.on(_operation.keys, keypress);
|
||||
behavior.on();
|
||||
}
|
||||
|
||||
return behavior;
|
||||
}
|
||||
|
||||
|
||||
behavior.on = function() {
|
||||
context.keybinding()
|
||||
.on(_operation.keys, keypress);
|
||||
};
|
||||
|
||||
|
||||
behavior.off = function() {
|
||||
context.keybinding()
|
||||
.off(_operation.keys);
|
||||
|
||||
@@ -192,7 +192,6 @@ export function modeSelect(context, selectedIDs) {
|
||||
};
|
||||
|
||||
function loadOperations() {
|
||||
|
||||
_operations.forEach(function(operation) {
|
||||
if (operation.behavior) {
|
||||
context.uninstall(operation.behavior);
|
||||
@@ -200,29 +199,39 @@ export function modeSelect(context, selectedIDs) {
|
||||
});
|
||||
|
||||
_operations = Object.values(Operations)
|
||||
.map(function(o) { return o(context, selectedIDs); })
|
||||
.filter(function(o) { return o.id !== 'delete' && o.id !== 'downgrade' && o.id !== 'copy'; })
|
||||
.map(o => o(context, selectedIDs))
|
||||
.filter(o => o.id !== 'delete' && o.id !== 'downgrade' && o.id !== 'copy')
|
||||
.concat([
|
||||
// group copy/downgrade/delete operation together at the end of the list
|
||||
Operations.operationCopy(context, selectedIDs),
|
||||
Operations.operationDowngrade(context, selectedIDs),
|
||||
Operations.operationDelete(context, selectedIDs)
|
||||
]).filter(function(operation) {
|
||||
return operation.available();
|
||||
]);
|
||||
|
||||
_operations
|
||||
.filter(operation => operation.available())
|
||||
.forEach(operation => {
|
||||
if (operation.behavior) {
|
||||
context.install(operation.behavior);
|
||||
}
|
||||
});
|
||||
|
||||
_operations.forEach(function(operation) {
|
||||
if (operation.behavior) {
|
||||
context.install(operation.behavior);
|
||||
}
|
||||
});
|
||||
// unavailable operations: still install keybindings
|
||||
// to show information message about the unavailability of the operation
|
||||
_operations
|
||||
.filter(operation => !operation.available())
|
||||
.forEach(operation => {
|
||||
if (operation.behavior) {
|
||||
operation.behavior.on();
|
||||
}
|
||||
});
|
||||
|
||||
// remove any displayed menu
|
||||
context.ui().closeEditMenu();
|
||||
}
|
||||
|
||||
mode.operations = function() {
|
||||
return _operations;
|
||||
return _operations.filter(operation => operation.available());
|
||||
};
|
||||
|
||||
|
||||
@@ -638,7 +647,7 @@ export function modeSelect(context, selectedIDs) {
|
||||
|
||||
_focusedVertexIds = null;
|
||||
|
||||
_operations.forEach(function(operation) {
|
||||
_operations.forEach(operation => {
|
||||
if (operation.behavior) {
|
||||
context.uninstall(operation.behavior);
|
||||
}
|
||||
|
||||
@@ -104,9 +104,9 @@ export function operationCopy(context, selectedIDs) {
|
||||
|
||||
|
||||
operation.availableForKeypress = function() {
|
||||
var selection = window.getSelection && window.getSelection();
|
||||
const selection = window.getSelection?.();
|
||||
// if the user has text selected then let them copy that, not the selected feature
|
||||
return !selection || !selection.toString();
|
||||
return !selection?.toString();
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ export function utilKeybinding(namespace) {
|
||||
function testBindings(d3_event, isCapturing) {
|
||||
var didMatch = false;
|
||||
var bindings = Object.keys(_keybindings).map(function(id) { return _keybindings[id]; });
|
||||
var i, binding;
|
||||
|
||||
// Most key shortcuts will accept either lower or uppercase ('h' or 'H'),
|
||||
// so we don't strictly match on the shift key, but we prioritize
|
||||
@@ -20,8 +19,7 @@ export function utilKeybinding(namespace) {
|
||||
// (This lets us differentiate between '←'/'⇧←' or '⌘Z'/'⌘⇧Z')
|
||||
|
||||
// priority match shifted keybindings first
|
||||
for (i = 0; i < bindings.length; i++) {
|
||||
binding = bindings[i];
|
||||
for (const binding of bindings) {
|
||||
if (!binding.event.modifiers.shiftKey) continue; // no shift
|
||||
if (!!binding.capture !== isCapturing) continue;
|
||||
if (matches(d3_event, binding, true)) {
|
||||
@@ -36,8 +34,7 @@ export function utilKeybinding(namespace) {
|
||||
if (didMatch) return;
|
||||
|
||||
// then unshifted keybindings
|
||||
for (i = 0; i < bindings.length; i++) {
|
||||
binding = bindings[i];
|
||||
for (const binding of bindings) {
|
||||
if (binding.event.modifiers.shiftKey) continue; // shift
|
||||
if (!!binding.capture !== isCapturing) continue;
|
||||
if (matches(d3_event, binding, false)) {
|
||||
|
||||
Reference in New Issue
Block a user