Creating ohif:commands package
This commit is contained in:
parent
2f81c0e2e7
commit
dbbcbe6e67
60
Packages/ohif-commands/client/classes/CommandsManager.js
Normal file
60
Packages/ohif-commands/client/classes/CommandsManager.js
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Packages/ohif-commands/main.js
Normal file
15
Packages/ohif-commands/main.js
Normal 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 };
|
||||||
22
Packages/ohif-commands/package.js
Normal file
22
Packages/ohif-commands/package.js
Normal 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');
|
||||||
|
});
|
||||||
@ -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);
|
||||||
|
|||||||
@ -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 };
|
||||||
|
|||||||
@ -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 OHIF’s.
|
* TODO: Use Session variables to activate a button and use Helpers like in toolbarSectionButton.js from OHIF’s.
|
||||||
*/
|
*/
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user