366 lines
11 KiB
JavaScript
366 lines
11 KiB
JavaScript
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 };
|