Skip to content

Commit

Permalink
feat(init.js): Allow app to configure internal modules other than glo…
Browse files Browse the repository at this point in the history
…balConfig via init. (#1094)
  • Loading branch information
JamesAPetts authored Oct 3, 2019
1 parent 40488e2 commit fc4e1ff
Show file tree
Hide file tree
Showing 19 changed files with 127 additions and 48 deletions.
21 changes: 20 additions & 1 deletion docs/latest/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
cornerstoneTools.init();
```

The `cornerstoneTools.init();` call accepts a configuration object if you would like to deviate from default behaviors:
The `cornerstoneTools.init();` call accepts a configuration object if you would like to deviate from default behaviors of `cornerstoneTool`'s `globalConfiguration`:

```js
cornerstoneTools.init({
Expand Down Expand Up @@ -108,6 +108,25 @@ cornerstoneTools.init({
});
```

If you wish to change modules other than the `globalConfiguration` module, you may pass an array of named module configuration like so:

```js
cornerstoneTools.init([
{
moduleName: 'globalConfiguration',
configuration: {
showSVGCursors: true,
},
},
{
moduleName: 'segmentation',
configuration: {
outlineWidth: 2,
},
},
]);
```

You can go further and configure textStyle, toolStyle, toolColors, etc:

```js
Expand Down
15 changes: 14 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,20 @@
<script src="netlify-example/imageLoader.js"></script>

<script>
cornerstoneTools.init({ showSVGCursors: true });
cornerstoneTools.init([
{
moduleName: 'globalConfiguration',
configuration: {
showSVGCursors: true
}
},
{
moduleName: 'segmentation',
configuration: {
outlineWidth: 2
}
}
]);
const imageIds = ['example://1', 'example://2', 'example://3'];
const stack = {
currentImageIdIndex: 0,
Expand Down
36 changes: 18 additions & 18 deletions netlify-example/brush/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ <h2>

// Segmentation Module API //

const { configuration, getters, setters } = cornerstoneTools.getModule(
const segmentationModule = cornerstoneTools.getModule(
'segmentation'
);

Expand All @@ -447,11 +447,11 @@ <h2>
function brushApiCall(opperation) {
switch (opperation) {
case 'next-segment':
setters.incrementActiveSegmentIndex(element);
segmentationModule.setters.incrementActiveSegmentIndex(element);
cornerstone.updateImage(element);
break;
case 'previous-segment':
setters.decrementActiveSegmentIndex(element);
segmentationModule.setters.decrementActiveSegmentIndex(element);
cornerstone.updateImage(element);
break;
case 'switch-labelmap':
Expand All @@ -461,7 +461,7 @@ <h2>
activeLabelmapIndex = 0;
}

setters.activeLabelmapIndex(element, activeLabelmapIndex);
segmentationModule.setters.activeLabelmapIndex(element, activeLabelmapIndex);

const label = document.getElementById('active-label-map-label');
label.innerHTML = 'Active Labelmap: ' + activeLabelmapIndex;
Expand All @@ -471,7 +471,7 @@ <h2>
break;

case 'toggle-segment-1':
const visible = setters.toggleSegmentVisibility(element, 1);
const visible = segmentationModule.setters.toggleSegmentVisibility(element, 1);

console.log(visible);

Expand All @@ -483,7 +483,7 @@ <h2>
cornerstone.updateImage(element);
break;
case 'calculate-segment-1-stats':
getters.labelmapStats(element, 1).then(result => {
segmentationModule.getters.labelmapStats(element, 1).then(result => {
const statsLabel = document.getElementById(
'calculate-segment-1-stats-label'
);
Expand Down Expand Up @@ -516,23 +516,23 @@ <h2>
const outlineDisplay = document.getElementById('display-outline');

outlineDisplay.addEventListener('input', event => {
configuration.renderOutline = event.target.checked;
segmentationModule.configuration.renderOutline = event.target.checked;
cornerstone.updateImage(element);
});

// Display Fill
const fillDisplay = document.getElementById('display-fill');

fillDisplay.addEventListener('input', event => {
configuration.renderFill = event.target.checked;
segmentationModule.configuration.renderFill = event.target.checked;
cornerstone.updateImage(element);
});

// Display Inactive
const inactiveDisplay = document.getElementById('display-inactive');

inactiveDisplay.addEventListener('input', event => {
configuration.shouldRenderInactiveLabelmaps = event.target.checked;
segmentationModule.configuration.shouldRenderInactiveLabelmaps = event.target.checked;
cornerstone.updateImage(element);
});

Expand All @@ -544,33 +544,33 @@ <h2>
alphaSlider.addEventListener('input', event => {
const normalisedAlpha = event.target.value / 255.0;

configuration.fillAlpha = normalisedAlpha;
segmentationModule.configuration.fillAlpha = normalisedAlpha;
cornerstone.updateImage(element);
});

// Active Outline
const outlineAlphaSlider = document.getElementById('outline-alpha');

outlineAlphaSlider.defaultValue = Math.floor(
configuration.outlineAlpha * 255
segmentationModule.configuration.outlineAlpha * 255
);
outlineAlphaSlider.addEventListener('input', event => {
const normalisedAlpha = event.target.value / 255.0;

configuration.outlineAlpha = normalisedAlpha;
segmentationModule.configuration.outlineAlpha = normalisedAlpha;
cornerstone.updateImage(element);
});

// Inactive Fill
const inactiveAlphaSlider = document.getElementById('fill-alpha-inactive');

inactiveAlphaSlider.defaultValue = Math.floor(
configuration.fillAlphaInactive * 255
segmentationModule.configuration.fillAlphaInactive * 255
);
inactiveAlphaSlider.addEventListener('input', event => {
const normalisedAlpha = event.target.value / 255.0;

configuration.fillAlphaInactive = normalisedAlpha;
segmentationModule.configuration.fillAlphaInactive = normalisedAlpha;
cornerstone.updateImage(element);
});

Expand All @@ -580,12 +580,12 @@ <h2>
);

inactiveOutlineAlphaSlider.defaultValue = Math.floor(
configuration.outlineAlphaInactive * 255
segmentationModule.configuration.outlineAlphaInactive * 255
);
inactiveOutlineAlphaSlider.addEventListener('input', event => {
const normalisedAlpha = event.target.value / 255.0;

configuration.outlineAlphaInactive = normalisedAlpha;
segmentationModule.configuration.outlineAlphaInactive = normalisedAlpha;
cornerstone.updateImage(element);
});

Expand Down Expand Up @@ -637,11 +637,11 @@ <h2>

Mousetrap.bind(['command+z', 'ctrl+z'], function () {
console.log('UNDO');
setters.undo(element)
segmentationModule.setters.undo(element)
});
Mousetrap.bind(['command+y', 'ctrl+y'], function () {
console.log('REDO');
setters.redo(element)
segmentationModule.setters.redo(element)
});
</script>

Expand Down
3 changes: 2 additions & 1 deletion src/eventDispatchers/imageRenderedEventDispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import onImageRenderedBrushEventHandler from '../eventListeners/onImageRenderedB
import external from './../externalModules.js';

const segmentationModule = getModule('segmentation');
const segmentationConfiguration = segmentationModule.configuration;

const onImageRendered = function(evt) {
const eventData = evt.detail;
Expand All @@ -22,6 +21,8 @@ const onImageRendered = function(evt) {
// Must be using stacks in order to use segmentation tools.
const stackToolState = getToolState(element, 'stack');

const segmentationConfiguration = segmentationModule.configuration;

if (
stackToolState &&
(segmentationConfiguration.renderFill ||
Expand Down
6 changes: 5 additions & 1 deletion src/eventListeners/internals/renderSegmentation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getModule } from '../../store/index.js';
import renderSegmentationFill from './renderSegmentationFill';
import renderSegmentationOutline from './renderSegmentationOutline';

const { configuration } = getModule('segmentation');
const segmentationModule = getModule('segmentation');

/**
* Renders the segmentation based on the brush configuration and
Expand Down Expand Up @@ -50,6 +50,8 @@ export default function renderSegmentation(
* @returns {boolean} True if the segmentation should be filled.
*/
function shouldRenderFill(isActiveLabelMap) {
const { configuration } = segmentationModule;

return (
configuration.renderFill &&
((isActiveLabelMap && configuration.fillAlpha !== 0) ||
Expand All @@ -65,6 +67,8 @@ function shouldRenderFill(isActiveLabelMap) {
* @returns {boolean} True if the segmentation should be outlined.
*/
function shouldRenderOutline(isActiveLabelMap) {
const { configuration } = segmentationModule;

return (
configuration.renderOutline &&
((isActiveLabelMap && configuration.outlineAlpha !== 0) ||
Expand Down
4 changes: 3 additions & 1 deletion src/eventListeners/internals/renderSegmentationFill.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from '../../drawing/index.js';
import external from '../../externalModules';

const { state, configuration } = getModule('segmentation');
const segmentationModule = getModule('segmentation');

export default function renderSegmentationFill(
evt,
Expand All @@ -31,6 +31,7 @@ export default function renderSegmentationFill(
* @returns {HTMLCanvasElement}
*/
export function getLabelmapCanvas(evt, labelmap3D, labelmap2D) {
const { state } = segmentationModule;
const eventData = evt.detail;
const { image } = eventData;
const cols = image.width;
Expand Down Expand Up @@ -77,6 +78,7 @@ export function getLabelmapCanvas(evt, labelmap3D, labelmap2D) {
* @returns {null}
*/
export function renderFill(evt, labelmapCanvas, isActiveLabelMap) {
const { configuration } = segmentationModule;
const eventData = evt.detail;
const context = getNewContext(eventData.canvasContext.canvas);

Expand Down
4 changes: 3 additions & 1 deletion src/eventListeners/internals/renderSegmentationOutline.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import external from '../../externalModules.js';
import { getNewContext, draw, drawLines } from '../../drawing/index.js';
import { disableLogger } from '../../index.js';

const { state, configuration } = getModule('segmentation');
const segmentationModule = getModule('segmentation');

export default function renderSegmentationOutline(
evt,
Expand All @@ -12,6 +12,7 @@ export default function renderSegmentationOutline(
labelmapIndex,
isActiveLabelMap
) {
const { configuration } = segmentationModule;
const outline = getOutline(
evt,
labelmap3D,
Expand All @@ -37,6 +38,7 @@ export function renderOutline(
colorLUTIndex,
isActiveLabelMap = true
) {
const { configuration, state } = segmentationModule;
const eventData = evt.detail;
const { element, canvasContext } = eventData;

Expand Down
3 changes: 2 additions & 1 deletion src/eventListeners/onImageRenderedBrushEventHandler.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getModule } from '../store/index.js';
import renderSegmentation from './internals/renderSegmentation.js';

const { configuration, getters } = getModule('segmentation');
const segmentationModule = getModule('segmentation');

/**
* Finds which segmentations need to be rendered based on the configuration and
Expand All @@ -13,6 +13,7 @@ const { configuration, getters } = getModule('segmentation');
export default function(evt) {
const eventData = evt.detail;
const element = eventData.element;
const { configuration, getters } = segmentationModule;

const {
activeLabelmapIndex,
Expand Down
33 changes: 25 additions & 8 deletions src/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,38 @@ import windowResizeHandler from './eventListeners/windowResizeHandler.js';
* @method
* @name init
*
* @param {Object} [configuration = {}] The global configuration to apply.
* @param {Object|Object[]} [defaultConfiguration = {}] The configuration to apply. Assumed globalConfiguration
* only one value, otherwise moduleName, configuration entires in an array.
* @returns {Object} A configured CornerstoneTools instance with top level API members.
*/
export default function(configuration = {}) {
export default function(defaultConfiguration = {}) {
_addCornerstoneEventListeners();
_initModules();

// Apply global configuration
const globalConfigurationModule = getModule('globalConfiguration');

globalConfigurationModule.configuration = Object.assign(
{},
globalConfigurationModule.configuration,
configuration
);
if (Array.isArray(defaultConfiguration)) {
defaultConfiguration.forEach(configurationEntry => {
const { moduleName, configuration } = configurationEntry;

const module = getModule(moduleName);

if (module) {
module.configuration = Object.assign(
{},
module.configuration,
configuration
);
}
});
} else {
// defaultConfiguration is an object, default to assigning it to globalConfiguration.
globalConfigurationModule.configuration = Object.assign(
{},
globalConfigurationModule.configuration,
defaultConfiguration
);
}

if (globalConfigurationModule.configuration.autoResizeViewports) {
windowResizeHandler.enable();
Expand Down
3 changes: 3 additions & 0 deletions src/store/modules/cursorModule.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import external from '../../externalModules';

const configuration = {
iconSize: 16,
viewBox: {
Expand Down Expand Up @@ -25,6 +27,7 @@ const getters = {
};

export default {
configuration,
getters,
setters,
};
5 changes: 4 additions & 1 deletion src/store/modules/segmentationModule/activeSegmentIndex.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import getElement from './getElement';
import { getToolState } from '../../../stateManagement/toolState.js';
import state from './state';
import configuration from './configuration';
import { getModule } from '../../index.js';

/**
* Returns the `activeSegmentIndex` for the active `Labelmap3D` for the `BrushStackState` displayed on the element.
Expand Down Expand Up @@ -68,6 +68,8 @@ function setActiveSegmentIndex(elementOrEnabledElementUID, segmentIndex) {
const activeLabelmapIndex = brushStackState.activeLabelmapIndex;
const labelmap3D = brushStackState.labelmaps3D[activeLabelmapIndex];

const { configuration } = getModule('segmentation');

if (segmentIndex <= 0) {
segmentIndex = 1;
} else if (segmentIndex > configuration.segmentsPerLabelmap) {
Expand Down Expand Up @@ -119,6 +121,7 @@ function decrementActiveSegmentIndex(elementOrEnabledElementUID) {
* @returns {null}
*/
function _changeActiveSegmentIndex(element, increaseOrDecrease = 'increase') {
const { configuration } = getModule('segmentation');
const stackState = getToolState(element, 'stack');
const stackData = stackState.data[0];
const firstImageId = stackData.imageIds[0];
Expand Down
Loading

0 comments on commit fc4e1ff

Please sign in to comment.