ohif-viewer/Packages/ohif-viewerbase/client/lib/hotkeyUtils.js
2017-01-30 12:17:16 -02:00

366 lines
11 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Meteor } from 'meteor/meteor';
import { $ } from 'meteor/jquery';
import { OHIF } from 'meteor/ohif:core';
import { toolManager } from './toolManager';
import { setActiveViewport } from './setActiveViewport';
import { switchToImageRelative } from './switchToImageRelative';
import { switchToImageByIndex } from './switchToImageByIndex';
import { viewportUtils } from './viewportUtils';
import { panelNavigation } from './panelNavigation';
import { WLPresets } from './WLPresets';
// TODO: add this to namespace definitions
Meteor.startup(function() {
if (!OHIF.viewer) {
OHIF.viewer = {};
}
OHIF.viewer.loadIndicatorDelay = 200;
OHIF.viewer.defaultTool = 'wwwc';
OHIF.viewer.refLinesEnabled = true;
OHIF.viewer.isPlaying = {};
OHIF.viewer.cine = {
framesPerSecond: 24,
loop: true
};
OHIF.viewer.defaultHotkeys = {
defaultTool: 'ESC',
angle: 'A',
stackScroll: 'S',
pan: 'P',
magnify: 'M',
scrollDown: 'DOWN',
scrollUp: 'UP',
nextDisplaySet: 'PAGEDOWN',
previousDisplaySet: 'PAGEUP',
nextPanel: 'RIGHT',
previousPanel: 'LEFT',
invert: 'I',
flipV: 'V',
flipH: 'H',
wwwc: 'W',
zoom: 'Z',
cinePlay: 'SPACE',
rotateR: 'R',
rotateL: 'L',
toggleOverlayTags: 'SHIFT',
WLPresetSoftTissue: ['NUMPAD1', '1'],
WLPresetLung: ['NUMPAD2', '2'],
WLPresetLiver: ['NUMPAD3', '3'],
WLPresetBone: ['NUMPAD4', '4'],
WLPresetBrain: ['NUMPAD5', '5']
};
// For now
OHIF.viewer.hotkeys = OHIF.viewer.defaultHotkeys;
OHIF.viewer.hotkeyFunctions = {
wwwc() {
toolManager.setActiveTool('wwwc');
},
zoom() {
toolManager.setActiveTool('zoom');
},
angle() {
toolManager.setActiveTool('angle');
},
dragProbe() {
toolManager.setActiveTool('dragProbe');
},
ellipticalRoi() {
toolManager.setActiveTool('ellipticalRoi');
},
magnify() {
toolManager.setActiveTool('magnify');
},
annotate() {
toolManager.setActiveTool('annotate');
},
stackScroll() {
toolManager.setActiveTool('stackScroll');
},
pan() {
toolManager.setActiveTool('pan');
},
length() {
toolManager.setActiveTool('length');
},
spine() {
toolManager.setActiveTool('spine');
},
wwwcRegion() {
toolManager.setActiveTool('wwwcRegion');
},
zoomIn() {
const button = document.getElementById('zoomIn');
flashButton(button);
viewportUtils.zoomIn();
},
zoomOut() {
const button = document.getElementById('zoomOut');
flashButton(button);
viewportUtils.zoomOut();
},
zoomToFit() {
const button = document.getElementById('zoomToFit');
flashButton(button);
viewportUtils.zoomToFit();
},
scrollDown() {
const container = $('.viewportContainer.active');
const button = container.find('#nextImage').get(0);
if (!container.find('.imageViewerViewport').hasClass('empty')) {
flashButton(button);
switchToImageRelative(1);
}
},
scrollFirstImage() {
const container = $('.viewportContainer.active');
if (!container.find('.imageViewerViewport').hasClass('empty')) {
switchToImageByIndex(0);
}
},
scrollLastImage() {
const container = $('.viewportContainer.active');
if (!container.find('.imageViewerViewport').hasClass('empty')) {
switchToImageByIndex(-1);
}
},
scrollUp() {
const container = $('.viewportContainer.active');
if (!container.find('.imageViewerViewport').hasClass('empty')) {
const button = container.find('#prevImage').get(0);
flashButton(button);
switchToImageRelative(-1);
}
},
previousDisplaySet() {
OHIF.viewerbase.layoutManager.moveDisplaySets(false);
},
nextDisplaySet() {
OHIF.viewerbase.layoutManager.moveDisplaySets(true);
},
nextPanel() {
panelNavigation.loadNextActivePanel();
},
previousPanel() {
panelNavigation.loadPreviousActivePanel();
},
invert() {
const button = document.getElementById('invert');
flashButton(button);
viewportUtils.invert();
},
flipV() {
const button = document.getElementById('flipV');
flashButton(button);
viewportUtils.flipV();
},
flipH() {
const button = document.getElementById('flipH');
flashButton(button);
viewportUtils.flipH();
},
rotateR() {
const button = document.getElementById('rotateR');
flashButton(button);
viewportUtils.rotateR();
},
rotateL() {
const button = document.getElementById('rotateL');
flashButton(button);
viewportUtils.rotateL();
},
cinePlay() {
viewportUtils.toggleCinePlay();
},
defaultTool() {
const tool = toolManager.getDefaultTool();
toolManager.setActiveTool(tool);
},
toggleOverlayTags() {
const dicomTags = $('.imageViewerViewportOverlay .dicomTag');
if (dicomTags.eq(0).css('display') === 'none') {
dicomTags.show();
} else {
dicomTags.hide();
}
},
resetStack() {
const button = document.getElementById('resetStack');
flashButton(button);
resetStack();
},
clearImageAnnotations() {
const button = document.getElementById('clearImageAnnotations');
flashButton(button);
clearImageAnnotations();
},
cineDialog () {
/**
* TODO: This won't work in OHIF's, since this element
* doesn't exist
*/
const button = document.getElementById('cine');
flashButton(button);
viewportUtils.toggleCineDialog();
button.classList.toggle('active');
}
};
OHIF.viewer.loadedSeriesData = {};
});
// Define a jQuery reverse function
$.fn.reverse = [].reverse;
/**
* Overrides OHIF's refLinesEnabled
* @param {Boolean} refLinesEnabled True to enable and False to disable
*/
function setOHIFRefLines(refLinesEnabled) {
OHIF.viewer.refLinesEnabled = refLinesEnabled;
}
/**
* Overrides OHIF's hotkeys
* @param {Object} hotkeys Object with hotkeys mapping
*/
function setOHIFHotkeys(hotkeys) {
OHIF.viewer.hotkeys = hotkeys;
}
/**
* Global function to merge different hotkeys configurations
* but avoiding conflicts between different keys with same action
* When this occurs, it will delete the action from OHIF's configuration
* So if you want to keep all OHIF's actions, use an unused-ohif-key
* Used for compatibility with others systems only
*
* @param hotkeysActions {object} Object with actions map
* @return {object}
*/
function mergeHotkeys(hotkeysActions) {
// Merge hotkeys, overriding OHIF's settings
let mergedHotkeys = {
...OHIF.viewer.defaultHotkeys,
...hotkeysActions
};
const defaultHotkeys = OHIF.viewer.defaultHotkeys;
const hotkeysKeys = Object.keys(hotkeysActions);
// Check for conflicts with same keys but different actions
Object.keys(defaultHotkeys).forEach(ohifAction => {
hotkeysKeys.forEach(definedAction => {
// Different action but same key:
// Remove action from merge if is not in "hotkeysActions"
// If it is, it's already merged so nothing to do
if(ohifAction !== definedAction && hotkeysActions[definedAction] === defaultHotkeys[ohifAction] && !hotkeysActions[ohifAction]) {
delete mergedHotkeys[ohifAction];
}
});
});
return mergedHotkeys;
}
/**
* Add an active class to a button for 100ms only
* to give the impressiont the button was pressed.
* This is for tools that don't keep the button "pressed"
* all the time the tool is active.
*
* @param button DOM Element for the button to be "flashed"
*/
function flashButton(button) {
if (!button) {
return;
}
button.classList.add('active');
setTimeout(() => {
button.classList.remove('active');
}, 100);
}
/**
* Binds a task to a hotkey keydown event
* @param {String} hotkey keyboard key
* @param {String} task task function name
*/
function bindHotkey(hotkey, task) {
var hotkeyFunctions = OHIF.viewer.hotkeyFunctions;
// Only bind defined, non-empty HotKeys
if (!hotkey || hotkey === '') {
return;
}
var fn;
if (task.indexOf('WLPreset') > -1) {
var presetName = task.replace('WLPreset', '');
fn = function() {
WLPresets.applyWLPresetToActiveElement(presetName);
};
} else {
fn = hotkeyFunctions[task];
// If the function doesn't exist in the
// hotkey function list, try the viewer-specific function list
if (!fn && OHIF.viewer && OHIF.viewer.functionList) {
fn = OHIF.viewer.functionList[task];
}
}
if (!fn) {
return;
}
var hotKeyForBinding = hotkey.toLowerCase();
$(document).bind('keydown', hotKeyForBinding, fn);
}
/**
* Binds all hotkeys keydown events to the tasks defined in
* OHIF.viewer.hotkeys or a given param
* @param {Object} hotkeys hotkey and task mapping (not required). If not given, uses OHIF.viewer.hotkeys
*/
function enableHotkeys(hotkeys) {
const viewerHotkeys = hotkeys || OHIF.viewer.hotkeys;
$(document).unbind('keydown');
Object.keys(viewerHotkeys).forEach(function(task) {
const taskHotkeys = viewerHotkeys[task];
if (!taskHotkeys || !taskHotkeys.length) {
return;
}
if (taskHotkeys instanceof Array) {
taskHotkeys.forEach(function(hotkey) {
bindHotkey(hotkey, task);
});
} else {
// taskHotkeys represents a single key
bindHotkey(taskHotkeys, task);
}
});
}
/**
* Export functions inside hotkeyUtils namespace.
*/
const hotkeyUtils = {
setOHIFRefLines, /* @TODO: find a better place for this... */
setOHIFHotkeys,
mergeHotkeys,
enableHotkeys
};
export { hotkeyUtils };