Move ohif:hotkeys into ohif:core
This commit is contained in:
1 parent
1abd0e6f9d
commit
184c959037
10 files changed
+14
-1
No files matched your search
@@ -0,0 +1,6 @@
|
||||
<template name="hotkeysConfirmReplacementPopover">
|
||||
{{#popoverForm (extend this confirmLabel='Yes' cancelLabel='No' confirmClass='btn-danger')}}
|
||||
<p><b>{{this.conflictedFunctionName}}</b> is already using the <b>{{this.hotkeyCombination}}</b> shortcut.</p>
|
||||
<p>Do you want to use the shortcut for the <b>{{this.newFunctionName}}</b> function instead?</p>
|
||||
{{/popoverForm}}
|
||||
</template>
|
||||
@@ -0,0 +1,21 @@
|
||||
<template name="hotkeysForm">
|
||||
{{#form (extend this api=instance.api class='form-themed')}}
|
||||
<div class="form-content">
|
||||
{{#let lists=getHotkeyInputInformationLists}}
|
||||
<div class="row">
|
||||
<div class="col-lg-6 hotkeys-left">
|
||||
{{>hotkeysFormTable inputs=lists.left}}
|
||||
</div>
|
||||
<div class="col-lg-6 hotkeys-right">
|
||||
{{>hotkeysFormTable inputs=lists.right}}
|
||||
</div>
|
||||
</div>
|
||||
{{/let}}
|
||||
</div>
|
||||
<div class="form-buttons clearfix">
|
||||
{{#button class='btn btn-danger pull-left' action='resetDefaults'}}Reset to Defaults{{/button}}
|
||||
{{#button class='btn btn-primary pull-right' action='save'}}Save{{/button}}
|
||||
{{#button class='btn btn-secondary pull-right m-r-1' tagAttributes=(extend '' data-dismiss='modal')}}Close{{/button}}
|
||||
</div>
|
||||
{{/form}}
|
||||
</template>
|
||||
@@ -0,0 +1,237 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { $ } from 'meteor/jquery';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.hotkeysForm.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
const { contextName } = instance.data;
|
||||
|
||||
instance.api = {
|
||||
save() {
|
||||
const form = instance.$('form').first().data('component');
|
||||
const definitions = form.value();
|
||||
const promise = OHIF.hotkeys.store(contextName, definitions);
|
||||
promise.then(() => {
|
||||
const successMessage = 'The keyboard shortcut preferences were successfully saved.';
|
||||
OHIF.ui.notifications.success({ text: successMessage });
|
||||
OHIF.hotkeys.load(contextName).then(defs => instance.hotkeysDefinitions.set(defs));
|
||||
});
|
||||
return promise;
|
||||
},
|
||||
|
||||
resetDefaults() {
|
||||
const dialogOptions = {
|
||||
class: 'themed',
|
||||
title: 'Reset Keyboard Shortcuts',
|
||||
message: 'Are you sure you want to reset all the shortcuts to their defaults?'
|
||||
};
|
||||
|
||||
return OHIF.ui.showDialog('dialogConfirm', dialogOptions).then(() => {
|
||||
const resetDefaults = OHIF.hotkeys.resetDefaults(contextName);
|
||||
resetDefaults.then(() => {
|
||||
OHIF.hotkeys.load(contextName).then(defs => instance.hotkeysDefinitions.set(defs));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const rg = (start, end) => _.range(start, end + 1);
|
||||
instance.allowedKeys = _.union(
|
||||
[8, 13, 27, 32, 46], // BACKSPACE, ENTER, ESCAPE, SPACE, DELETE
|
||||
[12, 106, 107, 109, 110, 111], // Numpad keys
|
||||
rg(219, 221), // [\]
|
||||
rg(186, 191), // ;=,-./
|
||||
rg(112, 130), // F1-F19
|
||||
rg(33, 40), // arrow keys, home/end, pg dn/up
|
||||
rg(48, 57), // 0-9
|
||||
rg(65, 90) // A-Z
|
||||
);
|
||||
|
||||
instance.updateInputText = (event, displayPressedKey=false) => {
|
||||
const $target = $(event.currentTarget);
|
||||
const keysPressedArray = instance.getKeysPressedArray(event);
|
||||
|
||||
if (displayPressedKey) {
|
||||
const specialKeyName = jQuery.hotkeys.specialKeys[event.which];
|
||||
const keyName = specialKeyName || String.fromCharCode(event.keyCode) || event.key;
|
||||
keysPressedArray.push(keyName.toUpperCase());
|
||||
}
|
||||
|
||||
$target.val(keysPressedArray.join('+'));
|
||||
};
|
||||
|
||||
instance.getKeysPressedArray = event => {
|
||||
const keysPressedArray = [];
|
||||
|
||||
if (event.ctrlKey && !event.altKey) {
|
||||
keysPressedArray.push('CTRL');
|
||||
}
|
||||
|
||||
if (event.shiftKey && !event.altKey) {
|
||||
keysPressedArray.push('SHIFT');
|
||||
}
|
||||
|
||||
if (event.altKey && !event.ctrlKey) {
|
||||
keysPressedArray.push('ALT');
|
||||
}
|
||||
|
||||
return keysPressedArray;
|
||||
};
|
||||
|
||||
instance.getConflictingCommand = (currentCommand, currentCombination) => {
|
||||
const form = instance.$('form').first().data('component');
|
||||
const hotkeys = form.value();
|
||||
|
||||
let conflict = '';
|
||||
_.each(hotkeys, (combination, command) => {
|
||||
if (combination && combination === currentCombination && command !== currentCommand) {
|
||||
conflict = command;
|
||||
}
|
||||
});
|
||||
|
||||
return conflict;
|
||||
};
|
||||
|
||||
instance.disallowedCombinations = {
|
||||
'': [],
|
||||
ALT: ['SPACE'],
|
||||
SHIFT: [],
|
||||
CTRL: ['F4', 'F5', 'F11', 'W', 'R', 'T', 'O', 'P', 'A', 'D', 'F', 'G', 'H', 'J', 'L', 'Z', 'X', 'C', 'V', 'B', 'N', 'PAGEDOWN', 'PAGEUP'],
|
||||
'CTRL+SHIFT': ['Q', 'W', 'R', 'T', 'P', 'A', 'H', 'V', 'B', 'N']
|
||||
};
|
||||
|
||||
const hotkeysContext = OHIF.hotkeys.getContext(contextName) || {};
|
||||
instance.hotkeysDefinitions = new ReactiveVar(hotkeysContext.definitions);
|
||||
OHIF.hotkeys.load(contextName).then(defs => instance.hotkeysDefinitions.set(defs));
|
||||
});
|
||||
|
||||
Template.hotkeysForm.events({
|
||||
'keydown .hotkey'(event, instance) {
|
||||
// Prevent ESC key from propagating and closing the modal
|
||||
if (event.keyCode === 27) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
if (instance.allowedKeys.indexOf(event.keyCode) > -1) {
|
||||
instance.updateInputText(event, true);
|
||||
$(event.currentTarget).trigger('hotkeyChange');
|
||||
} else {
|
||||
instance.updateInputText(event);
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
'hotkeyChange .hotkey'(event, instance, data={}) {
|
||||
const $target = $(event.currentTarget);
|
||||
const combination = $target.val();
|
||||
const keys = combination.split('+');
|
||||
const lastKey = keys.pop();
|
||||
const modifierCombination = keys.join('+');
|
||||
const isModifier = ['CTRL', 'ALT', 'SHIFT'].indexOf(lastKey) > -1;
|
||||
|
||||
const formItem = $target.data('component');
|
||||
const conflictedCommand = instance.getConflictingCommand(this.key, combination);
|
||||
if (isModifier) {
|
||||
// Clean the input if left with only a modifier key or browser specific command
|
||||
formItem.error(`It's not possible to define only modifier keys (CTRL, ALT and SHIFT) as a shortcut`);
|
||||
$target.val('').focus();
|
||||
} else if (instance.disallowedCombinations[modifierCombination].indexOf(lastKey) > -1) {
|
||||
// Clean the input and show error if combination is not allowed
|
||||
formItem.error(`The "${combination}" shortcut combination is not allowed`);
|
||||
$target.val('').focus();
|
||||
} else if (conflictedCommand) {
|
||||
if (data.blurTrigger) return;
|
||||
|
||||
// Remove the error message
|
||||
formItem.error(false);
|
||||
formItem.toggleTooltip(false);
|
||||
|
||||
const placement = $target.closest('.hotkeys-left').length ? 'right' : 'left';
|
||||
const commandsContext = OHIF.commands.getContext(instance.data.contextName);
|
||||
const popoverData = {
|
||||
conflictedFunctionName: commandsContext[conflictedCommand].name,
|
||||
newFunctionName: commandsContext[this.key].name,
|
||||
hotkeyCombination: combination,
|
||||
};
|
||||
|
||||
const popoverOptions = {
|
||||
event,
|
||||
placement
|
||||
};
|
||||
|
||||
const conflictedFormItem = instance.$('form').first().data('component').item(conflictedCommand);
|
||||
formItem.state('error', true);
|
||||
conflictedFormItem.state('error', true);
|
||||
|
||||
const cleanup = () => {
|
||||
instance.popoverVisible = false;
|
||||
formItem.state('error', false);
|
||||
conflictedFormItem.state('error', false);
|
||||
};
|
||||
|
||||
const popoverTemplate = 'hotkeysConfirmReplacementPopover';
|
||||
instance.popoverVisible = true;
|
||||
OHIF.ui.showPopover(popoverTemplate, popoverData, popoverOptions).then(() => {
|
||||
cleanup();
|
||||
formItem.value(combination);
|
||||
conflictedFormItem.value('');
|
||||
$target.blur();
|
||||
}).catch(() => {
|
||||
cleanup();
|
||||
$target.val('').focus();
|
||||
});
|
||||
} else {
|
||||
// Remove the error message and blur the component if everything is fine
|
||||
formItem.error(false);
|
||||
if (!data.blurTrigger) {
|
||||
$target.blur();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'blur .hotkey'(event, instance, data={}) {
|
||||
$(event.currentTarget).trigger('hotkeyChange', { blurTrigger: true });
|
||||
},
|
||||
|
||||
'keyup .hotkey'(event, instance) {
|
||||
if (!instance.popoverVisible) {
|
||||
instance.updateInputText(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.hotkeysForm.helpers({
|
||||
getHotkeyInputInformationLists() {
|
||||
OHIF.hotkeys.changeObserver.depend();
|
||||
|
||||
const instance = Template.instance();
|
||||
const { contextName } = instance.data;
|
||||
|
||||
const hotkeyDefinitions = instance.hotkeysDefinitions.get();
|
||||
const commandsContext = OHIF.commands.getContext(contextName);
|
||||
if (!hotkeyDefinitions || !commandsContext) return {};
|
||||
|
||||
const commands = Object.keys(OHIF.hotkeys.defaults[contextName] || {});
|
||||
const list = [];
|
||||
commands.forEach(commandName => {
|
||||
const commandDefinitions = commandsContext[commandName];
|
||||
if (!commandDefinitions) return;
|
||||
list.push({
|
||||
key: commandName,
|
||||
label: commandDefinitions.name,
|
||||
value: hotkeyDefinitions[commandName] || ''
|
||||
});
|
||||
});
|
||||
|
||||
const left = list.splice(0, Math.ceil(list.length / 2));
|
||||
const right = list;
|
||||
|
||||
return {
|
||||
left,
|
||||
right
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
<template name="hotkeysFormTable">
|
||||
<table class="full-width">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-right p-r-1">Function</th>
|
||||
<th class="text-center">Shortcut</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each input in this.inputs}}
|
||||
<tr>
|
||||
<td class="text-right p-r-1">{{getLabel input}}</td>
|
||||
<td width="200">{{>inputText (extend class='hotkey text-center' key=input.key value=input.value)}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.hotkeysFormTable.helpers({
|
||||
getLabel(input) {
|
||||
let result = input.label;
|
||||
if (input.key.indexOf('WLPreset') === 0) {
|
||||
const presetIndex = parseInt(input.key.replace('WLPreset', ''));
|
||||
const preset = OHIF.viewer.wlPresets[presetIndex];
|
||||
if (preset.id) {
|
||||
result += ` (${preset.id})`;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
import './confirmReplacementPopover.html';
|
||||
|
||||
import './form.html';
|
||||
import './form.js';
|
||||
|
||||
import './formTable.html';
|
||||
import './formTable.js';
|
||||
Reference in new issue
Block a user