Adding inputs to define hotkeys
This commit is contained in:
parent
bbb1cf0789
commit
20f274962b
@ -12,7 +12,10 @@ export class HotkeysContext {
|
||||
Object.keys(definitions).forEach(command => {
|
||||
const hotkey = definitions[command];
|
||||
this.unregister(command);
|
||||
this.register(command, hotkey);
|
||||
if (hotkey) {
|
||||
this.register(command, hotkey);
|
||||
}
|
||||
|
||||
this.definitions[command] = hotkey;
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template name="hotkeysDialog">
|
||||
{{#dialogSimple title='Keyboard Shortcuts'}}
|
||||
{{>hotkeysForm}}
|
||||
{{#dialogSimple (extend this dialogClass='dialog-hotkeys' title='Keyboard Shortcuts')}}
|
||||
{{>hotkeysForm this}}
|
||||
{{/dialogSimple}}
|
||||
</template>
|
||||
|
||||
3
Packages/ohif-hotkeys/client/components/dialog.styl
Normal file
3
Packages/ohif-hotkeys/client/components/dialog.styl
Normal file
@ -0,0 +1,3 @@
|
||||
.dialog-hotkeys .modal-body
|
||||
max-height: 80vh
|
||||
overflow-y: auto
|
||||
@ -1,5 +1,7 @@
|
||||
<template name="hotkeysForm">
|
||||
{{#form class='form-themed'}}
|
||||
{{>inputText class='hotkey' label='Window W/L'}}
|
||||
{{#form (extend this class='form-themed')}}
|
||||
{{#each hotkeyInputInformation in getHotkeyInputInformationList}}
|
||||
{{>inputText (extend hotkeyInputInformation class='hotkey')}}
|
||||
{{/each}}
|
||||
{{/form}}
|
||||
</template>
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { $ } from 'meteor/jquery';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.hotkeysForm.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
@ -38,6 +40,19 @@ Template.hotkeysForm.onCreated(() => {
|
||||
|
||||
return keysPressedArray;
|
||||
};
|
||||
|
||||
instance.disallowedCombinations = {
|
||||
'': [],
|
||||
ALT: ['SPACE'],
|
||||
SHIFT: [],
|
||||
CTRL: ['F4', 'F5', 'F11', 'W', 'R', 'T', 'O', 'P', 'A', 'S', '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']
|
||||
};
|
||||
});
|
||||
|
||||
// >>>> REMOVE ME
|
||||
Meteor.startup(() => {
|
||||
OHIF.ui.showDialog('hotkeysDialog', { contextName: 'viewer' });
|
||||
});
|
||||
|
||||
Template.hotkeysForm.events({
|
||||
@ -52,7 +67,47 @@ Template.hotkeysForm.events({
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
'blur .hotkey'(event, instance) {
|
||||
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;
|
||||
// Clean the input if left with only a modifier key or browser specific command
|
||||
if (isModifier) {
|
||||
$target.val('');
|
||||
} else if (instance.disallowedCombinations[modifierCombination].indexOf(lastKey) > -1) {
|
||||
$target.val('');
|
||||
// TODO: show warning
|
||||
$target.focus();
|
||||
}
|
||||
},
|
||||
|
||||
'keyup .hotkey'(event, instance) {
|
||||
instance.updateInputText(event);
|
||||
}
|
||||
});
|
||||
|
||||
Template.hotkeysForm.helpers({
|
||||
getHotkeyInputInformationList() {
|
||||
OHIF.context.dep.depend();
|
||||
const instance = Template.instance();
|
||||
const { contextName } = instance.data;
|
||||
const hotkeysInputInformation = [];
|
||||
const hotkeysContext = OHIF.hotkeys.getContext(contextName);
|
||||
const commandsContext = OHIF.commands.getContext(contextName);
|
||||
if (!hotkeysContext || !commandsContext) return hotkeysInputInformation;
|
||||
const hotkeyDefinitions = hotkeysContext.definitions;
|
||||
_.each(hotkeyDefinitions, (keyCombination, commandName) => {
|
||||
const commandDefinitions = commandsContext[commandName];
|
||||
if (!commandDefinitions) return;
|
||||
hotkeysInputInformation.push({
|
||||
key: commandName,
|
||||
label: commandDefinitions.name,
|
||||
value: keyCombination
|
||||
});
|
||||
});
|
||||
return hotkeysInputInformation;
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import './dialog.html';
|
||||
import './dialog.styl';
|
||||
|
||||
import './form.html';
|
||||
import './form.js';
|
||||
|
||||
@ -15,6 +15,7 @@ Package.onUse(function(api) {
|
||||
api.use([
|
||||
'ecmascript',
|
||||
'templating',
|
||||
'stylus',
|
||||
'reactive-var',
|
||||
'session',
|
||||
'iron:router',
|
||||
|
||||
@ -22,31 +22,54 @@ Meteor.startup(function() {
|
||||
};
|
||||
|
||||
OHIF.viewer.defaultHotkeys = {
|
||||
// Tool hotkeys
|
||||
defaultTool: 'ESC',
|
||||
zoom: 'Z',
|
||||
wwwc: 'W',
|
||||
pan: 'P',
|
||||
angle: 'A',
|
||||
stackScroll: 'S',
|
||||
pan: 'P',
|
||||
magnify: 'M',
|
||||
scrollDown: 'DOWN',
|
||||
scrollUp: 'UP',
|
||||
nextDisplaySet: 'PAGEDOWN',
|
||||
previousDisplaySet: 'PAGEUP',
|
||||
nextPanel: 'RIGHT',
|
||||
previousPanel: 'LEFT',
|
||||
invert: 'I',
|
||||
flipV: 'V',
|
||||
length: '',
|
||||
annotate: '',
|
||||
dragProbe: '',
|
||||
ellipticalRoi: '',
|
||||
rectangleRoi: '',
|
||||
spine: '',
|
||||
|
||||
// Viewport hotkeys
|
||||
flipH: 'H',
|
||||
wwwc: 'W',
|
||||
zoom: 'Z',
|
||||
toggleCinePlay: 'SPACE',
|
||||
flipV: 'V',
|
||||
rotateR: 'R',
|
||||
rotateL: 'L',
|
||||
invert: 'I',
|
||||
zoomIn: '',
|
||||
zoomOut: '',
|
||||
zoomToFit: '',
|
||||
resetViewport: '',
|
||||
clearTools: '',
|
||||
|
||||
// Viewport navigation hotkeys
|
||||
scrollDown: 'DOWN',
|
||||
scrollUp: 'UP',
|
||||
scrollLastImage: '',
|
||||
scrollFirstImage: '',
|
||||
previousDisplaySet: 'PAGEUP',
|
||||
nextDisplaySet: 'PAGEDOWN',
|
||||
nextPanel: 'RIGHT',
|
||||
previousPanel: 'LEFT',
|
||||
|
||||
// Miscellaneous hotkeys
|
||||
toggleOverlayTags: 'SHIFT',
|
||||
WLPresetSoftTissue: ['NUMPAD1', '1'],
|
||||
WLPresetLung: ['NUMPAD2', '2'],
|
||||
WLPresetLiver: ['NUMPAD3', '3'],
|
||||
WLPresetBone: ['NUMPAD4', '4'],
|
||||
WLPresetBrain: ['NUMPAD5', '5']
|
||||
toggleCinePlay: 'SPACE',
|
||||
toggleCineDialog: '',
|
||||
|
||||
// Preset hotkeys
|
||||
WLPresetSoftTissue: '1',
|
||||
WLPresetLung: '2',
|
||||
WLPresetLiver: '3',
|
||||
WLPresetBone: '4',
|
||||
WLPresetBrain: '5'
|
||||
};
|
||||
|
||||
// For now
|
||||
@ -71,21 +94,27 @@ Meteor.startup(function() {
|
||||
});
|
||||
});
|
||||
|
||||
// Register the default tool command
|
||||
OHIF.commands.register(contextName, 'defaultTool', {
|
||||
name: 'Default Tool',
|
||||
action: () => toolManager.setActiveTool(toolManager.getDefaultTool())
|
||||
});
|
||||
|
||||
// Register the tool switching commands
|
||||
registerToolCommands({
|
||||
wwwc: 'Levels',
|
||||
wwwc: 'Window W/L',
|
||||
zoom: 'Zoom',
|
||||
angle: 'Angle',
|
||||
dragProbe: 'Probe',
|
||||
ellipticalRoi: 'Ellipse',
|
||||
angle: 'Angle Measurement',
|
||||
dragProbe: 'Pixel Probe',
|
||||
ellipticalRoi: 'Elliptical Probe',
|
||||
rectangleRoi: 'Rectangle',
|
||||
magnify: 'Magnify',
|
||||
annotate: 'Annotate',
|
||||
stackScroll: 'Stack Scroll',
|
||||
stackScroll: 'Scroll Stack',
|
||||
pan: 'Pan',
|
||||
length: 'Length',
|
||||
spine: 'Spine',
|
||||
wwwcRegion: 'ROI Window'
|
||||
length: 'Length Measurement',
|
||||
spine: 'Spine Labels',
|
||||
wwwcRegion: 'W/L by Region'
|
||||
});
|
||||
|
||||
// Functions to register the viewport commands
|
||||
@ -99,16 +128,16 @@ Meteor.startup(function() {
|
||||
|
||||
// Register the viewport commands
|
||||
registerViewportCommands({
|
||||
zoomIn: 'Zoom in',
|
||||
zoomOut: 'Zoom out',
|
||||
zoomToFit: 'Zoom to fit',
|
||||
zoomIn: 'Zoom In',
|
||||
zoomOut: 'Zoom Out',
|
||||
zoomToFit: 'Zoom to Fit',
|
||||
invert: 'Invert',
|
||||
flipH: 'Flip horizontally',
|
||||
flipV: 'Flip vertically',
|
||||
rotateR: 'Rotate right',
|
||||
rotateL: 'Rotate left',
|
||||
flipH: 'Flip Horizontally',
|
||||
flipV: 'Flip Vertically',
|
||||
rotateR: 'Rotate Right',
|
||||
rotateL: 'Rotate Left',
|
||||
resetViewport: 'Reset',
|
||||
clearTools: 'Clear'
|
||||
clearTools: 'Clear Tools'
|
||||
});
|
||||
|
||||
// Functions to register the preset switching commands
|
||||
@ -122,75 +151,67 @@ Meteor.startup(function() {
|
||||
|
||||
// Register the preset switching commands
|
||||
registerWLPresetCommands({
|
||||
WLPresetSoftTissue: 'SoftTissue',
|
||||
WLPresetLung: 'Lung',
|
||||
WLPresetLiver: 'Liver',
|
||||
WLPresetBone: 'Bone',
|
||||
WLPresetBrain: 'Brain'
|
||||
WLPresetSoftTissue: 'W/L Preset: Soft Tissue',
|
||||
WLPresetLung: 'W/L Preset: Lung',
|
||||
WLPresetLiver: 'W/L Preset: Liver',
|
||||
WLPresetBone: 'W/L Preset: Bone',
|
||||
WLPresetBrain: 'W/L Preset: Brain'
|
||||
});
|
||||
|
||||
// Register scrolling commands
|
||||
OHIF.commands.set(contextName, {
|
||||
scrollDown: {
|
||||
name: 'Scroll down',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageRelative(1)
|
||||
},
|
||||
scrollUp: {
|
||||
name: 'Scroll up',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageRelative(-1)
|
||||
},
|
||||
scrollFirstImage: {
|
||||
name: 'Scroll to first image',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageByIndex(0)
|
||||
},
|
||||
scrollLastImage: {
|
||||
name: 'Scroll to last image',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageByIndex(-1)
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Register viewport navigation commands
|
||||
OHIF.commands.set(contextName, {
|
||||
scrollDown: {
|
||||
name: 'Scroll Down',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageRelative(1)
|
||||
},
|
||||
scrollUp: {
|
||||
name: 'Scroll Up',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageRelative(-1)
|
||||
},
|
||||
scrollFirstImage: {
|
||||
name: 'Scroll to First Image',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageByIndex(0)
|
||||
},
|
||||
scrollLastImage: {
|
||||
name: 'Scroll to Last Image',
|
||||
action: () => !isActiveViewportEmpty() && switchToImageByIndex(-1)
|
||||
},
|
||||
previousDisplaySet: {
|
||||
name: 'Previous display set',
|
||||
name: 'Previous Series',
|
||||
action: () => OHIF.viewerbase.layoutManager.moveDisplaySets(false),
|
||||
disabled: () => !OHIF.viewerbase.layoutManager.canMoveDisplaySets(false)
|
||||
},
|
||||
nextDisplaySet: {
|
||||
name: 'Next display set',
|
||||
name: 'Next Series',
|
||||
action: () => OHIF.viewerbase.layoutManager.moveDisplaySets(true),
|
||||
disabled: () => !OHIF.viewerbase.layoutManager.canMoveDisplaySets(true)
|
||||
},
|
||||
nextPanel: {
|
||||
name: 'Next panel',
|
||||
name: 'Next Panel',
|
||||
action: () => panelNavigation.loadNextActivePanel()
|
||||
},
|
||||
previousPanel: {
|
||||
name: 'Previous panel',
|
||||
name: 'Previous Panel',
|
||||
action: () => panelNavigation.loadPreviousActivePanel()
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Register miscellaneous commands
|
||||
OHIF.commands.set(contextName, {
|
||||
defaultTool: {
|
||||
name: 'Default tool',
|
||||
action: () => toolManager.setActiveTool(toolManager.getDefaultTool())
|
||||
},
|
||||
toggleOverlayTags: {
|
||||
name: 'Toggle overlay tags',
|
||||
name: 'Toggle Image Annotations',
|
||||
action() {
|
||||
const $dicomTags = $('.imageViewerViewportOverlay .dicomTag');
|
||||
$dicomTags.toggle($dicomTags.eq(0).css('display') === 'none');
|
||||
}
|
||||
},
|
||||
toggleCinePlay: {
|
||||
name: 'Play/Pause',
|
||||
name: 'Play/Pause Cine',
|
||||
action: viewportUtils.toggleCinePlay,
|
||||
disabled: OHIF.viewerbase.viewportUtils.hasMultipleFrames
|
||||
},
|
||||
toggleCineDialog: {
|
||||
name: 'CINE dialog',
|
||||
name: 'Show/Hide Cine Controls',
|
||||
action: viewportUtils.toggleCineDialog,
|
||||
disabled: OHIF.viewerbase.viewportUtils.hasMultipleFrames
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user