Creating ohif:commands package

This commit is contained in:
Bruno Alves de Faria 2017-04-24 17:07:47 -03:00 committed by Erik Ziegler
parent 2f81c0e2e7
commit dbbcbe6e67
6 changed files with 151 additions and 48 deletions

View File

@ -0,0 +1,60 @@
import { ReactiveDict } from 'meteor/reactive-dict';
import { Tracker } from 'meteor/tracker';
import { OHIF } from 'meteor/ohif:core';
export class CommandsManager {
constructor() {
this.contexts = {};
Tracker.autorun(() => {
const currentContextName = OHIF.context.get();
OHIF.log.info(currentContextName);
// TODO: initialize hotkeys context
});
}
getContext(contextName) {
const context = this.contexts[contextName];
if (!context) {
OHIF.log.warn(`No context found with name "${contextName}"`);
}
return context;
}
getCurrentContext(contextName) {
return this.getContext(OHIF.context.get());
}
createContext(contextName) {
if (this.contexts[contextName]) {
return this.unsetCommands(contextName);
}
this.contexts[contextName] = new ReactiveDict();
}
setCommands(contextName, definitions) {
if (typeof definitions !== 'object') return;
const context = this.getContext(contextName);
if (!context) return;
this.unsetCommands(contextName);
Object.keys(definitions).forEach(key => context.set(key, definitions[key]));
}
registerCommand(contextName, key, definition) {
if (typeof definition !== 'object') return;
const context = this.getContext(contextName);
if (!context) return;
context.set(key, definition);
}
unsetCommands(contextName) {
const context = this.getContext(contextName);
if (!context) return;
context.clear();
}
}

View File

@ -0,0 +1,15 @@
import { ReactiveVar } from 'meteor/reactive-var';
import { OHIF } from 'meteor/ohif:core';
import { CommandsManager } from 'meteor/ohif:commands/client/classes/CommandsManager';
// Create context namespace using a ReactiveVar
const context = new ReactiveVar(null);
// Create commands namespace using a CommandsManager class instance
const commands = new CommandsManager(context);
// Append context namespace to OHIF namespace
OHIF.context = context;
// Export relevant objects
export { context, commands };

View File

@ -0,0 +1,22 @@
Package.describe({
name: 'ohif:commands',
summary: 'OHIF commands management',
version: '0.0.1'
});
Package.onUse(function(api) {
api.versionsFrom('1.4');
// Meteor packages
api.use([
'ecmascript',
'reactive-var',
'reactive-dict'
]);
// OHIF dependencies
api.use('ohif:core');
// Main module definition
api.mainModule('main.js', 'client');
});

View File

@ -2,7 +2,7 @@ import { ReactiveVar } from 'meteor/reactive-var';
import { HotkeysContext } from 'meteor/ohif:hotkeys/client/classes/HotkeysContext'; import { HotkeysContext } from 'meteor/ohif:hotkeys/client/classes/HotkeysContext';
export class HotkeysManager { export class HotkeysManager {
constructor() { constructor(retrieveFunction, storeFunction) {
this.contexts = {}; this.contexts = {};
this.currentContextName = null; this.currentContextName = null;
this.enabled = new ReactiveVar(true); this.enabled = new ReactiveVar(true);

View File

@ -1,18 +1,11 @@
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
import { HotkeysManager } from 'meteor/ohif:hotkeys/client/classes/HotkeysManager'; import { HotkeysManager } from 'meteor/ohif:hotkeys/client/classes/HotkeysManager';
/** // Create hotkeys namespace using a HotkeysManager class instance
* Create hotkeys namespace using a HotkeysManager class instance
*/
const hotkeys = new HotkeysManager(); const hotkeys = new HotkeysManager();
/** // Append hotkeys namespace to OHIF namespace
* Append hotkeys namespace to OHIF namespace
*/
OHIF.hotkeys = hotkeys; OHIF.hotkeys = hotkeys;
/** // Export relevant objects
* Export relevant objects
*/
export { hotkeys }; export { hotkeys };

View File

@ -132,6 +132,7 @@ export const toolManager = {
this.configureTools(); this.configureTools();
initialized = true; initialized = true;
}, },
configureTools() { configureTools() {
// Get Cornerstone Tools // Get Cornerstone Tools
const { panMultiTouch, textStyle, toolStyle, toolColors, const { panMultiTouch, textStyle, toolStyle, toolColors,
@ -171,29 +172,22 @@ export const toolManager = {
const ellipticalRoiConfig = ellipticalRoi.getConfiguration(); const ellipticalRoiConfig = ellipticalRoi.getConfiguration();
// Add shadow to length tool // Add shadow to length tool
length.setConfiguration({ length.setConfiguration(Object.assign({}, lengthConfig, shadowConfig, { drawHandlesOnHover: true }));
...lengthConfig,
...shadowConfig,
drawHandlesOnHover: true
});
// Add shadow to length tool // Add shadow to length tool
ellipticalRoi.setConfiguration({ ellipticalRoi.setConfiguration(Object.assign({}, ellipticalRoiConfig, shadowConfig));
...ellipticalRoiConfig,
...shadowConfig
});
// Set the configuration values for the Text Marker (Spine Labelling) tool // Set the configuration values for the Text Marker (Spine Labelling) tool
const startFrom = $('#startFrom'); const $startFrom = $('#startFrom');
const ascending = $('#ascending'); const $ascending = $('#ascending');
const textMarkerConfig = { const textMarkerConfig = {
markers: [ 'L5', 'L4', 'L3', 'L2', 'L1', // Lumbar spine markers: [ 'L5', 'L4', 'L3', 'L2', 'L1', // Lumbar spine
'T12', 'T11', 'T10', 'T9', 'T8', 'T7', // Thoracic spine 'T12', 'T11', 'T10', 'T9', 'T8', 'T7', // Thoracic spine
'T6', 'T5', 'T4', 'T3', 'T2', 'T1', 'T6', 'T5', 'T4', 'T3', 'T2', 'T1',
'C7', 'C6', 'C5', 'C4', 'C3', 'C2', 'C1', // Cervical spine 'C7', 'C6', 'C5', 'C4', 'C3', 'C2', 'C1', // Cervical spine
], ],
current: startFrom.val(), current: $startFrom.val(),
ascending: ascending.is(':checked'), ascending: $ascending.is(':checked'),
loop: true, loop: true,
changeTextCallback: textMarkerUtils.changeTextCallback, changeTextCallback: textMarkerUtils.changeTextCallback,
shadow: shadowConfig.shadow, shadow: shadowConfig.shadow,
@ -236,12 +230,13 @@ export const toolManager = {
// http://stackoverflow.com/questions/9907419/javascript-object-get-key-by-value // http://stackoverflow.com/questions/9907419/javascript-object-get-key-by-value
return Object.keys(object).filter(key => object[key] === value); return Object.keys(object).filter(key => object[key] === value);
}, },
configureLoadProcess() { configureLoadProcess() {
// Whenever the CornerstoneImageLoadProgress is fired, identify which viewports // Whenever the CornerstoneImageLoadProgress is fired, identify which viewports
// the "in-progress" image is to be displayed in. Then pass the percent complete // the "in-progress" image is to be displayed in. Then pass the percent complete
// via the Meteor Session to the other templates to be displayed in the relevant viewports. // via the Meteor Session to the other templates to be displayed in the relevant viewports.
$(cornerstone).on('CornerstoneImageLoadProgress', (e, eventData) => { $(cornerstone).on('CornerstoneImageLoadProgress', (e, eventData) => {
viewportIndices = this.getKeysByValue(window.ViewportLoading, eventData.imageId); const viewportIndices = this.getKeysByValue(window.ViewportLoading, eventData.imageId);
viewportIndices.forEach(viewportIndex => { viewportIndices.forEach(viewportIndex => {
Session.set('CornerstoneLoadProgress' + viewportIndex, eventData.percentComplete); Session.set('CornerstoneLoadProgress' + viewportIndex, eventData.percentComplete);
}); });
@ -250,24 +245,31 @@ export const toolManager = {
Session.set('CornerstoneThumbnailLoadProgress' + encodedId, eventData.percentComplete); Session.set('CornerstoneThumbnailLoadProgress' + encodedId, eventData.percentComplete);
}); });
}, },
setGestures(newGestures) { setGestures(newGestures) {
gestures = newGestures; gestures = newGestures;
}, },
getGestures() { getGestures() {
return gestures; return gestures;
}, },
addTool(name, base) { addTool(name, base) {
tools[name] = base; tools[name] = base;
}, },
getTools() { getTools() {
return tools; return tools;
}, },
setToolDefaultStates(states) { setToolDefaultStates(states) {
toolDefaultStates = states; toolDefaultStates = states;
}, },
getToolDefaultStates() { getToolDefaultStates() {
return toolDefaultStates; return toolDefaultStates;
}, },
setActiveToolForElement(tool, element) { setActiveToolForElement(tool, element) {
const canvases = $(element).find('canvas'); const canvases = $(element).find('canvas');
if (element.classList.contains('empty') || !canvases.length) { if (element.classList.contains('empty') || !canvases.length) {
@ -276,22 +278,19 @@ export const toolManager = {
// First, deactivate the current active tool // First, deactivate the current active tool
tools[activeTool].mouse.deactivate(element, 1); tools[activeTool].mouse.deactivate(element, 1);
 
if (tools[activeTool].touch) { if (tools[activeTool].touch) {
tools[activeTool].touch.deactivate(element); tools[activeTool].touch.deactivate(element);
} }
// Enable tools based on their default states // Enable tools based on their default states
Object.keys(toolDefaultStates).forEach( action => { Object.keys(toolDefaultStates).forEach(action => {
const relevantTools = toolDefaultStates[action]; const relevantTools = toolDefaultStates[action];
if (!relevantTools || !relevantTools.length || action === 'disabledToolButtons') { if (!relevantTools || !relevantTools.length || action === 'disabledToolButtons') return;
return; relevantTools.forEach(toolType => {
}
relevantTools.forEach( toolType => {
// the currently active tool has already been deactivated and can be skipped // the currently active tool has already been deactivated and can be skipped
if (action === 'deactivate' && toolType === activeTool) { if (action === 'deactivate' && toolType === activeTool) return;
return;
}
tools[toolType].mouse[action]( tools[toolType].mouse[action](
element, element,
(action === 'activate' || action === 'deactivate' ? 1 : void 0) (action === 'activate' || action === 'deactivate' ? 1 : void 0)
@ -334,7 +333,7 @@ export const toolManager = {
// scroll is the default tool for middle mouse wheel for stacks // scroll is the default tool for middle mouse wheel for stacks
cornerstoneTools.stackScrollWheel.activate(element); cornerstoneTools.stackScrollWheel.activate(element);
if (gestures['stackScrollMultiTouch'].enabled === true) { if (gestures.stackScrollMultiTouch.enabled === true) {
cornerstoneTools.stackScrollMultiTouch.activate(element); // Three finger scroll cornerstoneTools.stackScrollMultiTouch.activate(element); // Three finger scroll
} }
@ -385,37 +384,41 @@ export const toolManager = {
tools[tool].touch.activate(element); tools[tool].touch.activate(element);
} }
if (gestures['zoomTouchPinch'].enabled === true) { if (gestures.zoomTouchPinch.enabled === true) {
cornerstoneTools.zoomTouchPinch.activate(element); // Two finger pinch cornerstoneTools.zoomTouchPinch.activate(element); // Two finger pinch
} }
if (gestures['panMultiTouch'].enabled === true) { if (gestures.panMultiTouch.enabled === true) {
cornerstoneTools.panMultiTouch.activate(element); // Two or >= Two finger pan cornerstoneTools.panMultiTouch.activate(element); // Two or >= Two finger pan
} }
if (gestures['doubleTapZoom'].enabled === true) { if (gestures.doubleTapZoom.enabled === true) {
cornerstoneTools.doubleTapZoom.activate(element); cornerstoneTools.doubleTapZoom.activate(element);
} }
}, },
setActiveTool(tool, elements) { setActiveTool(tool, elements) {
if (!initialized) { if (!initialized) {
toolManager.init(); toolManager.init();
} }
// Prevent changing if tool is already active
if (tool === toolManager.getActiveTool()) return;
/** /**
* TODO: Add textMarkerDialogs template to OHIF's * TODO: Add textMarkerDialogs template to OHIF's
*/ */
const dialog = document.getElementById('textMarkerOptionsDialog'); const dialog = document.getElementById('textMarkerOptionsDialog');
if(dialog) { if (dialog) {
if (tool === 'spine' && activeTool !== 'spine' && dialog.getAttribute('open') !== 'open') { if (tool === 'spine' && activeTool !== 'spine' && dialog.getAttribute('open') !== 'open') {
dialog.show(); dialog.show();
} else if(activeTool !== 'spine' && dialog.getAttribute("open") === "open") { } else if (activeTool !== 'spine' && dialog.getAttribute('open') === 'open') {
dialog.close(); dialog.close();
} }
} }
/** /**
* TODO: Use Session variables to activate a button and use Helpers like in toolbarSectionButton.js from OHIFs. * TODO: Use Session variables to activate a button and use Helpers like in toolbarSectionButton.js from OHIFs.
*/ */
// Set the div to active for the tool // Set the div to active for the tool
$('.imageViewerButton').removeClass('active'); $('.imageViewerButton').removeClass('active');
@ -428,19 +431,24 @@ export const toolManager = {
tool = defaultTool; tool = defaultTool;
} }
let $elements;
if (!elements || !elements.length) { if (!elements || !elements.length) {
elements = $('.imageViewerViewport'); $elements = $('.imageViewerViewport');
} else {
$elements = $(elements);
} }
// Otherwise, set the active tool for all viewport elements // Otherwise, set the active tool for all viewport elements
$(elements).each((index, element) => { $elements.each((index, element) => {
toolManager.setActiveToolForElement(tool, element); toolManager.setActiveToolForElement(tool, element);
}); });
activeTool = tool; activeTool = tool;
// Store the active tool in the session in order to enable reactivity // Store the active tool in the session in order to enable reactivity
Session.set('ToolManagerActiveTool', tool); Session.set('ToolManagerActiveTool', tool);
}, },
getActiveTool() { getActiveTool() {
if (!initialized) { if (!initialized) {
toolManager.init(); toolManager.init();
@ -453,30 +461,35 @@ export const toolManager = {
return activeTool; return activeTool;
}, },
setDefaultTool(tool) { setDefaultTool(tool) {
defaultTool = tool; defaultTool = tool;
}, },
getDefaultTool() { getDefaultTool() {
return defaultTool; return defaultTool;
}, },
setConfigureTools(configureTools) { setConfigureTools(configureTools) {
if(typeof configureTools === 'function') { if (typeof configureTools === 'function') {
this.configureTools = configureTools; this.configureTools = configureTools;
} }
}, },
activateCommandButton(button) { activateCommandButton(button) {
const activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || []; const activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || [];
if(activeCommandButtons.indexOf(button) === -1) { if (activeCommandButtons.indexOf(button) === -1) {
activeCommandButtons.push(button); activeCommandButtons.push(button);
Session.set('ToolManagerActiveCommandButtons', activeCommandButtons); Session.set('ToolManagerActiveCommandButtons', activeCommandButtons);
} }
}, },
deactivateCommandButton(button) { deactivateCommandButton(button) {
const activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || []; const activeCommandButtons = Session.get('ToolManagerActiveCommandButtons') || [];
const index = activeCommandButtons.indexOf(button); const index = activeCommandButtons.indexOf(button);
if(index !== -1) { if (index !== -1) {
activeCommandButtons.splice(index, 1); activeCommandButtons.splice(index, 1);
Session.set('ToolManagerActiveCommandButtons', activeCommandButtons); Session.set('ToolManagerActiveCommandButtons', activeCommandButtons);
} }