in packages/ketcher-react/src/script/ui/state/hotkeys.ts [99:216]
function keyHandle(dispatch, getState, hotKeys, event) {
const state = getState();
if (state.modal || selectIsAbbreviationLookupOpen(state)) return;
const { editor } = state;
const { render } = editor;
const actionState = state.actionState;
const actionTool = actionState.activeTool;
const key = keyNorm(event);
let group: any = null;
const hoveredItem = getHoveredItem(render.ctab);
if (key && key.length === 1 && !hoveredItem) {
const currentlyPressedKeys = selectAbbreviationLookupValue(state);
const isShortcutKey = shortcutKeys.includes(key?.toLowerCase());
const isTheSameKey = key === currentlyPressedKeys;
const isAbbreviationLookupShown =
(!isTheSameKey || !isShortcutKey) && currentlyPressedKeys;
if (isAbbreviationLookupShown) {
dispatch(showAbbreviationLookup(event.key));
clearTimeout(abbreviationLookupTimeoutId);
abbreviationLookupTimeoutId = undefined;
const resetAction = SettingsManager.getSettings().selectionTool;
dispatch(onAction(resetAction));
event.preventDefault();
return;
} else {
abbreviationLookupTimeoutId = window.setTimeout(() => {
dispatch(closeAbbreviationLookup());
abbreviationLookupTimeoutId = undefined;
}, ABBREVIATION_LOOKUP_TYPING_TIMEOUT);
dispatch(initAbbreviationLookup(event.key));
}
}
if (key && key.length === 1 && key.match('/')) {
const hotkeyDialogTypes = {
atoms: actions['atom-props'].action,
bonds: actions['bond-props'].action,
};
if (!hoveredItem) {
return;
}
const dialogType = Object.keys(hoveredItem)[0];
if (Object.hasOwn(hotkeyDialogTypes, dialogType)) {
handleHotkeyOverItem({
hoveredItem,
newAction: hotkeyDialogTypes[dialogType],
editor,
dispatch,
});
}
event.preventDefault();
} else if (editor.rotateController.isRotating && key === 'Escape') {
editor.rotateController.revert();
} else if ((group = keyNorm.lookup(hotKeys, event)) !== undefined) {
const index = checkGroupOnTool(group, actionTool); // index currentTool in group || -1
const groupLength = group !== null ? group.length : 1;
const newIndex = (index + 1) % groupLength;
const actName = group[newIndex];
if (actionState[actName] && actionState[actName].disabled === true) {
event.preventDefault();
return;
}
// Removing from what should be saved - structure, which was added to paste tool,
// but not yet rendered on canvas
removeNotRenderedStruct(actionTool, group, dispatch);
if (clipArea.actions.indexOf(actName) === -1) {
let newAction = ['zoom-in', 'zoom-out'].includes(actName)
? actions[actName].action()
: actions[actName].action;
const hoveredItem = getHoveredItem(render.ctab);
// check if atom is currently hovered over
// in this case we do not want to activate the corresponding tool
// and just insert the atom directly
if (
hoveredItem &&
newAction.tool !== 'select' &&
newAction.dialog !== 'templates'
) {
newAction = getCurrentAction(group[index]) || newAction;
handleHotkeyOverItem({
hoveredItem,
newAction,
editor,
dispatch,
});
} else {
if (newAction.tool === 'select') {
if (key === 'Escape') {
newAction = SettingsManager.getSettings().selectionTool;
} else if (index === -1) {
newAction = {};
}
}
dispatch(onAction(newAction));
}
event.preventDefault();
} else if (isIE) {
clipArea.exec(event);
}
} else if (isArrowKey(event.key)) {
moveSelectedItems(editor, event.key, event.shiftKey);
}
}