{{#form (extend this class='form-themed' api=instance.api)}}
- {{>inputText label='W/L Preset 1' key='WLPreset1'}}
+
+
+
+ | Preset |
+ Name |
+ Window Level (WL) |
+ Window Width (WW) |
+
+
+
+ {{#each presetInputInformation in getPresetsInputInformationList}}
+ {{#group base='baseTr' key=(concat @index)}}
+ {{sum @index 1}} |
+ {{>inputText key='id' value=presetInputInformation.id}} |
+ {{>inputText key='wc' value=(filterNaN presetInputInformation.wc) dataType='Number'}} |
+ {{>inputText key='ww' value=(filterNaN presetInputInformation.ww) dataType='Number'}} |
+ {{/group}}
+ {{/each}}
+
+
{{#button class='btn btn-primary pull-right' action='save'}}Save{{/button}}
diff --git a/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.js b/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.js
index a3b05db13..4e74c78c6 100644
--- a/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.js
+++ b/Packages/ohif-viewerbase/client/components/viewer/windowLevelPresets/form.js
@@ -1,14 +1,16 @@
import { Template } from 'meteor/templating';
+import { _ } from 'meteor/underscore';
import { OHIF } from 'meteor/ohif:core';
Template.windowLevelPresetsForm.onCreated(() => {
const instance = Template.instance();
+ const { wlPresets } = OHIF.viewerbase;
instance.api = {
save() {
const form = instance.$('form').first().data('component');
const definitions = form.value();
- // TODO: return save method with promise
+ wlPresets.store(definitions);
},
resetDefaults() {
@@ -17,9 +19,14 @@ Template.windowLevelPresetsForm.onCreated(() => {
message: 'Are you sure you want to reset all the window level presets to their defaults?'
};
- return OHIF.ui.showDialog('dialogConfirm', dialogOptions).then(() => {
- // TODO: return reset method with promise
- });
+ return OHIF.ui.showDialog('dialogConfirm', dialogOptions).then(() => wlPresets.resetDefaults());
}
};
});
+
+Template.windowLevelPresetsForm.helpers({
+ getPresetsInputInformationList() {
+ OHIF.viewerbase.wlPresets.changeObserver.depend();
+ return _.toArray(OHIF.viewer.wlPresets);
+ }
+});
diff --git a/Packages/ohif-viewerbase/client/lib/WLPresets.js b/Packages/ohif-viewerbase/client/lib/WLPresets.js
index 57436c04f..8ec741766 100644
--- a/Packages/ohif-viewerbase/client/lib/WLPresets.js
+++ b/Packages/ohif-viewerbase/client/lib/WLPresets.js
@@ -1,141 +1,213 @@
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';
-
+import { Tracker } from 'meteor/tracker';
+import { _ } from 'meteor/underscore';
import { OHIF } from 'meteor/ohif:core';
import { viewportUtils } from './viewportUtils';
const WL_PRESET_CUSTOM = 'Custom';
const WL_PRESET_DEFAULT = 'Default';
+const WL_STORAGE_KEY = `WindowLevelPresetsDefinitions`;
+
+OHIF.viewer.defaultWLPresets = {
+ 0: {
+ id: 'SoftTissue',
+ wc: 40,
+ ww: 400
+ },
+ 1: {
+ id: 'Lung',
+ wc: -600,
+ ww: 1500
+ },
+ 2: {
+ id: 'Liver',
+ wc: 90,
+ ww: 150
+ },
+ 3: {
+ id: 'Bone',
+ wc: 480,
+ ww: 2500
+ },
+ 4: {
+ id: 'Brain',
+ wc: 40,
+ ww: 80
+ },
+ 5: {},
+ 6: {},
+ 7: {},
+ 8: {},
+ 9: {}
+};
+
+class WindowLevelPresetsManager {
+ constructor() {
+ this.defaults = {};
+ this.retrieveFunction = null;
+ this.storeFunction = null;
+ this.changeObserver = new Tracker.Dependency();
+ }
+
+ updateElementWLPresetData(element) {
+ const wlPresetData = cornerstone.getElementData(element, 'wlPreset');
+ const enabledElement = cornerstone.getEnabledElement(element);
+ const { viewport, image } = enabledElement;
+ const { windowCenter, windowWidth } = viewport.voi;
+ let preset, presetName;
+
+ if (windowWidth === image.windowWidth && windowCenter === image.windowCenter) {
+ presetName = WL_PRESET_DEFAULT;
+ } else {
+ const WLPresets = OHIF.viewer.wlPresets;
+ for (let index in WLPresets) {
+ const currentPreset = WLPresets[index];
+ if (windowCenter === currentPreset.wc && windowWidth === currentPreset.ww) {
+ preset = currentPreset;
+ presetName = preset.id;
+ break;
+ }
+ }
+ }
+
+ wlPresetData.name = presetName || WL_PRESET_CUSTOM;
+ wlPresetData.ww = windowWidth;
+ wlPresetData.wc = windowCenter;
+
+ if (wlPresetData.name === WL_PRESET_CUSTOM) {
+ const custom = wlPresetData.custom || (wlPresetData.custom = Object.create(null));
+ custom.ww = windowWidth;
+ custom.wc = windowCenter;
+ }
+ }
+
+ /**
+ * Set specified W/L preset on given element on fallback to default W/L preset if the specified preset is not valid.
+ * @param {String} presetName The desired W/L preset to be applied
+ * @param {DOMElement} element An enabled viewport DOM Element.
+ */
+ applyWLPreset(presetName, element) {
+ const wlPresets = OHIF.viewer.wlPresets;
+ const wlPresetData = cornerstone.getElementData(element, 'wlPreset');
+ const viewport = cornerstone.getViewport(element);
+
+ const preset = wlPresets[presetName] || _.findWhere(wlPresets, { id: presetName });
+ if (presetName === WL_PRESET_CUSTOM && wlPresetData.custom) {
+ viewport.voi.windowWidth = wlPresetData.custom.ww;
+ viewport.voi.windowCenter = wlPresetData.custom.wc;
+ } else if (preset && !_.isEmpty(preset) && preset.id) {
+ presetName = preset.id;
+ viewport.voi.windowWidth = preset.ww;
+ viewport.voi.windowCenter = preset.wc;
+ } else {
+ const enabledElement = cornerstone.getEnabledElement(element);
+ viewport.voi.windowWidth = enabledElement.image.windowWidth;
+ viewport.voi.windowCenter = enabledElement.image.windowCenter;
+ presetName = WL_PRESET_DEFAULT;
+ }
+
+ wlPresetData.name = presetName;
+ wlPresetData.ww = viewport.voi.windowWidth;
+ wlPresetData.wc = viewport.voi.windowCenter;
+
+ // Update the viewport
+ cornerstone.setViewport(element, viewport);
+
+ OHIF.log.info('WLPresets::Applying WL Preset: ' + presetName);
+
+ // Notify other components about W/L Preset changes
+ Session.set('OHIFWlPresetApplied', presetName);
+ }
+
+ store(wlPresets) {
+ return new Promise((resolve, reject) => {
+ if (this.storeFunction) {
+ this.storeFunction(wlPresets).then(resolve).catch(reject);
+ } else if (Meteor.userId()) {
+ OHIF.user.setData(WL_STORAGE_KEY, wlPresets).then(resolve).catch(reject);
+ } else {
+ Session.setPersistent(WL_STORAGE_KEY, wlPresets);
+ resolve();
+ }
+ }).then(() => this.setOHIFWLPresets(wlPresets));
+ }
+
+ retrieve() {
+ return new Promise((resolve, reject) => {
+ if (this.retrieveFunction) {
+ this.retrieveFunction().then(resolve).catch(reject);
+ } else if (Meteor.userId()) {
+ try {
+ resolve(OHIF.user.getData(WL_STORAGE_KEY));
+ } catch(error) {
+ reject(error);
+ }
+ } else {
+ resolve(Session.get(WL_STORAGE_KEY));
+ }
+ });
+ }
+
+ load() {
+ return new Promise((resolve, reject) => {
+ this.retrieve().then(wlPresets => {
+ if (wlPresets) {
+ this.setOHIFWLPresets(wlPresets);
+ } else {
+ this.loadDefauls();
+ }
+ }).catch(this.loadDefauls);
+ });
+ }
+
+ applyWLPresetToActiveElement(presetName) {
+ const element = viewportUtils.getActiveViewportElement();
+ if (!element) {
+ return;
+ }
+
+ this.applyWLPreset(presetName, element);
+ }
+
+ /**
+ * Overrides OHIF's wlPresets
+ * @param {Object} wlPresets Object with wlPresets mapping
+ */
+ setOHIFWLPresets(wlPresets) {
+ const hasOwn = Object.prototype.hasOwnProperty;
+ const presetMap = Object.create(null); // Objects without prototype have much faster lookup times
+ for (let index in wlPresets) {
+ if (hasOwn.call(wlPresets, index)) {
+ presetMap[index] = wlPresets[index];
+ }
+ }
+
+ OHIF.viewer.wlPresets = presetMap;
+ this.changeObserver.changed();
+ }
+
+ loadDefauls() {
+ this.setOHIFWLPresets(OHIF.viewer.defaultWLPresets);
+ }
+
+ resetDefaults() {
+ return this.store(OHIF.viewer.defaultWLPresets);
+ }
+}
// TODO: add this to a namespace definition
Meteor.startup(function() {
- OHIF.viewer.defaultWLPresets = {
- SoftTissue: {
- wc: 40,
- ww: 400
- },
- Lung: {
- wc: -600,
- ww: 1500
- },
- Liver: {
- wc: 90,
- ww: 150
- },
- Bone: {
- wc: 480,
- ww: 2500
- },
- Brain: {
- wc: 40,
- ww: 80
- }
- };
- setOHIFWLPresets(OHIF.viewer.defaultWLPresets);
});
-function updateElementWLPresetData(element) {
- const wlPresetData = cornerstone.getElementData(element, 'wlPreset');
- const enabledElement = cornerstone.getEnabledElement(element);
- const { viewport, image } = enabledElement;
- const { windowCenter, windowWidth } = viewport.voi;
- let presetName;
-
- if (windowWidth === image.windowWidth && windowCenter === image.windowCenter) {
- presetName = WL_PRESET_DEFAULT;
- } else {
- const WLPresets = OHIF.viewer.wlPresets;
- for (let name in WLPresets) {
- const preset = WLPresets[name];
- if (windowCenter === preset.wc && windowWidth === preset.ww) {
- presetName = name;
- break;
- }
- }
- }
-
- wlPresetData.name = presetName || WL_PRESET_CUSTOM;
- wlPresetData.ww = windowWidth;
- wlPresetData.wc = windowCenter;
-
- if (wlPresetData.name === WL_PRESET_CUSTOM) {
- const custom = wlPresetData.custom || (wlPresetData.custom = Object.create(null));
- custom.ww = windowWidth;
- custom.wc = windowCenter;
- }
-}
-
-/**
- * Set specified W/L preset on given element on fallback to default W/L preset if the specified preset is not valid.
- * @param {String} presetName The desired W/L preset to be applied
- * @param {DOMElement} element An enabled viewport DOM Element.
- */
-function applyWLPreset(presetName, element) {
- const wlPresets = OHIF.viewer.wlPresets;
- const wlPresetData = cornerstone.getElementData(element, 'wlPreset');
- const viewport = cornerstone.getViewport(element);
-
- if (presetName === WL_PRESET_CUSTOM && wlPresetData.custom) {
- viewport.voi.windowWidth = wlPresetData.custom.ww;
- viewport.voi.windowCenter = wlPresetData.custom.wc;
- } else if (presetName in wlPresets) {
- const preset = wlPresets[presetName];
- viewport.voi.windowWidth = preset.ww;
- viewport.voi.windowCenter = preset.wc;
- } else {
- const enabledElement = cornerstone.getEnabledElement(element);
- viewport.voi.windowWidth = enabledElement.image.windowWidth;
- viewport.voi.windowCenter = enabledElement.image.windowCenter;
- presetName = WL_PRESET_DEFAULT;
- }
-
- wlPresetData.name = presetName;
- wlPresetData.ww = viewport.voi.windowWidth;
- wlPresetData.wc = viewport.voi.windowCenter;
-
- // Update the viewport
- cornerstone.setViewport(element, viewport);
-
- OHIF.log.info('WLPresets::Applying WL Preset: ' + presetName);
-
- // Notify other components about W/L Preset changes
- Session.set('OHIFWlPresetApplied', presetName);
-}
-
-function applyWLPresetToActiveElement(presetName) {
- const element = viewportUtils.getActiveViewportElement();
- if (!element) {
- return;
- }
-
- applyWLPreset(presetName, element);
-}
-
-/**
- * Overrides OHIF's wlPresets
- * @param {Object} wlPresets Object with wlPresets mapping
- */
-function setOHIFWLPresets(wlPresets) {
- const hasOwn = Object.prototype.hasOwnProperty;
- const presetMap = Object.create(null); // Objects without prototype have much faster lookup times
- for (let name in wlPresets) {
- if (hasOwn.call(wlPresets, name)) {
- presetMap[name] = wlPresets[name];
- }
- }
- OHIF.viewer.wlPresets = presetMap;
-}
-
/**
* Export functions inside WLPresets namespace.
*/
+const WLPresets = new WindowLevelPresetsManager();
-const WLPresets = {
- applyWLPreset,
- applyWLPresetToActiveElement,
- setOHIFWLPresets,
- updateElementWLPresetData
-};
+Meteor.startup(() => {
+ WLPresets.load();
+});
export { WLPresets };
diff --git a/Packages/ohif-viewerbase/client/lib/hotkeyUtils.js b/Packages/ohif-viewerbase/client/lib/hotkeyUtils.js
index 4302fb8a9..be9f20860 100644
--- a/Packages/ohif-viewerbase/client/lib/hotkeyUtils.js
+++ b/Packages/ohif-viewerbase/client/lib/hotkeyUtils.js
@@ -65,11 +65,16 @@ Meteor.startup(function() {
toggleCineDialog: '',
// Preset hotkeys
- WLPresetSoftTissue: '1',
- WLPresetLung: '2',
- WLPresetLiver: '3',
- WLPresetBone: '4',
- WLPresetBrain: '5'
+ WLPreset0: '1',
+ WLPreset1: '2',
+ WLPreset2: '3',
+ WLPreset3: '4',
+ WLPreset4: '5',
+ WLPreset5: '6',
+ WLPreset6: '7',
+ WLPreset7: '8',
+ WLPreset8: '9',
+ WLPreset9: '0'
};
// For now
@@ -140,23 +145,15 @@ Meteor.startup(function() {
clearTools: 'Clear Tools'
});
- // Functions to register the preset switching commands
- const registerWLPresetCommands = map => _.each(map, (commandName, presetName) => {
- OHIF.commands.register(contextName, presetName, {
- name: commandName,
- action: WLPresets.applyWLPresetToActiveElement,
- params: presetName.replace('WLPreset', '')
- });
- });
-
// Register the preset switching commands
- registerWLPresetCommands({
- 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'
- });
+ const applyPreset = presetName => WLPresets.applyWLPresetToActiveElement(presetName);
+ for (let i = 0; i < 10; i++) {
+ OHIF.commands.register(contextName, `WLPreset${i}`, {
+ name: `W/L Preset ${i + 1}`,
+ action: applyPreset,
+ params: i
+ });
+ }
// Register viewport navigation commands
OHIF.commands.set(contextName, {