From 9153bc9fc7926706c31fe9870201805461487506 Mon Sep 17 00:00:00 2001 From: burnpiro Date: Tue, 28 Sep 2021 22:20:03 +0200 Subject: [PATCH] Run `setTool[mode]` function when list of tools provided as props has changed. Call executes on every update and updates the state of all provided tools. This allows to turn tools ON/OFF without initializing entire `CornerstoneViewport` component. Resolves #117 --- .../CornerstoneViewport.js | 84 +++++++++++++++---- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/src/CornerstoneViewport/CornerstoneViewport.js b/src/CornerstoneViewport/CornerstoneViewport.js index 7ac003a..7637262 100644 --- a/src/CornerstoneViewport/CornerstoneViewport.js +++ b/src/CornerstoneViewport/CornerstoneViewport.js @@ -264,6 +264,22 @@ class CornerstoneViewport extends Component { cornerstoneTools.stackPrefetch.enable(this.element); } + // ~~ TOOLS + + const { tools } = this.props; + const { tools: prevTools } = prevProps; + + // Could be done by checking one by one + // but then we have to make sure the order is the same + // this ways checks if anything in the tools definition has changed + // Current `hasToolsChanges` is almost always true because prevTools have `toolClass` property + // TODO create list of tools to update and use only them + const hasToolsChanges = JSON.stringify(tools) !== JSON.stringify(prevTools); + + if (hasToolsChanges) { + _updateExistingTools(tools, this.element); + } + // ~~ ACTIVE TOOL const { activeTool } = this.props; const { activeTool: prevActiveTool } = prevProps; @@ -821,13 +837,7 @@ function _trySetActiveTool(element, activeToolName) { */ function _addAndConfigureInitialToolsForElement(tools, element) { for (let i = 0; i < tools.length; i++) { - const tool = - typeof tools[i] === 'string' - ? { name: tools[i] } - : Object.assign({}, tools[i]); - const toolName = `${tool.name}Tool`; // Top level CornerstoneTools follow this pattern - - tool.toolClass = tool.toolClass || cornerstoneTools[toolName]; + const tool = _unifyToolStructure(tools[i]); if (!tool.toolClass) { console.warn(`Unable to add tool with name '${tool.name}'.`); @@ -840,16 +850,60 @@ function _addAndConfigureInitialToolsForElement(tools, element) { tool.props || {} ); - const hasInitialMode = - tool.mode && AVAILABLE_TOOL_MODES.includes(tool.mode); + _modifyToolsMode(tool, element); + } +} + +/** + * Iterate over the provided tools; Update tools + * + * @param {string[]|object[]} tools + * @param {HTMLElement} element + */ +function _updateExistingTools(tools, element) { + for (let i = 0; i < tools.length; i++) { + const tool = _unifyToolStructure(tools[i]); - if (hasInitialMode) { - // TODO: We may need to check `tool.props` and the tool class's prototype - // to determine the name it registered with cornerstone. `tool.name` is not - // reliable. - const setToolModeFn = TOOL_MODE_FUNCTIONS[tool.mode]; - setToolModeFn(element, tool.name, tool.modeOptions || {}); + if (!tool.toolClass) { + console.warn(`Unable to update tool with name '${tool.name}'.`); + continue; } + + _modifyToolsMode(tool, element); + } +} + +/** + * Parse provided tool to tool object + * + * @param {string|object} tool + * @returns {object} Valid cornerstone tool object + */ +function _unifyToolStructure(tool) { + const toolDef = + typeof tool === 'string' ? { name: tool } : Object.assign({}, tool); + const toolName = `${toolDef.name}Tool`; // Top level CornerstoneTools follow this pattern + + toolDef.toolClass = toolDef.toolClass || cornerstoneTools[toolName]; + + return toolDef; +} + +/** + * Checks and sets mode for defined tool + * + * @param {object} tool + * @param {HTMLElement} element + */ +function _modifyToolsMode(tool, element) { + const hasInitialMode = tool.mode && AVAILABLE_TOOL_MODES.includes(tool.mode); + + if (hasInitialMode) { + // TODO: We may need to check `tool.props` and the tool class's prototype + // to determine the name it registered with cornerstone. `tool.name` is not + // reliable. + const setToolModeFn = TOOL_MODE_FUNCTIONS[tool.mode]; + setToolModeFn(element, tool.name, tool.modeOptions || {}); } }