diff --git a/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts b/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts index fa3c6d47c..ad5898ee9 100644 --- a/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts +++ b/extensions/cornerstone-dicom-seg/src/utils/hydrationUtils.ts @@ -180,7 +180,8 @@ function getUpdatedViewportsForSegmentation({ }); } }); - return updatedViewports; + + return updatedViewports.filter(v => v.viewportOptions?.viewportType !== 'volume3d'); } export { diff --git a/extensions/cornerstone/src/commandsModule.ts b/extensions/cornerstone/src/commandsModule.ts index b63aee091..1a7401340 100644 --- a/extensions/cornerstone/src/commandsModule.ts +++ b/extensions/cornerstone/src/commandsModule.ts @@ -311,6 +311,10 @@ function commandsModule({ return; } + if (!toolGroup.hasTool(toolName)) { + return; + } + const activeToolName = toolGroup.getActivePrimaryMouseButtonTool(); if (activeToolName) { diff --git a/extensions/cornerstone/src/getToolbarModule.tsx b/extensions/cornerstone/src/getToolbarModule.tsx index 7c1209836..e6cbbe41b 100644 --- a/extensions/cornerstone/src/getToolbarModule.tsx +++ b/extensions/cornerstone/src/getToolbarModule.tsx @@ -166,6 +166,19 @@ export default function getToolbarModule({ commandsManager, servicesManager }) { }; }, }, + { + name: 'evaluate.not3D', + evaluate: ({ viewportId, button }) => { + const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId); + + if (viewport?.type === 'volume3d') { + return { + disabled: true, + className: '!text-common-bright ohif-disabled', + }; + } + }, + }, { name: 'evaluate.viewportProperties.toggle', evaluate: ({ viewportId, button }) => { diff --git a/extensions/cornerstone/src/hps/fourUp.ts b/extensions/cornerstone/src/hps/fourUp.ts index 776d7a298..ac7435fb8 100644 --- a/extensions/cornerstone/src/hps/fourUp.ts +++ b/extensions/cornerstone/src/hps/fourUp.ts @@ -1,7 +1,9 @@ export const fourUp = { id: 'fourUp', locked: true, - name: 'fourUp', + name: '3D four up', + icon: 'layout-advanced-3d-four-up', + isPreset: true, createdDate: '2023-03-15T10:29:44.894Z', modifiedDate: '2023-03-15T10:29:44.894Z', availableTo: {}, diff --git a/extensions/cornerstone/src/hps/main3D.ts b/extensions/cornerstone/src/hps/main3D.ts index a7b837991..e59437cb3 100644 --- a/extensions/cornerstone/src/hps/main3D.ts +++ b/extensions/cornerstone/src/hps/main3D.ts @@ -1,7 +1,9 @@ export const main3D = { id: 'main3D', locked: true, - name: 'main3D', + name: '3D main', + icon: 'layout-advanced-3d-main', + isPreset: true, createdDate: '2023-03-15T10:29:44.894Z', modifiedDate: '2023-03-15T10:29:44.894Z', availableTo: {}, diff --git a/extensions/cornerstone/src/hps/mpr.ts b/extensions/cornerstone/src/hps/mpr.ts index c9a9eea82..5927af785 100644 --- a/extensions/cornerstone/src/hps/mpr.ts +++ b/extensions/cornerstone/src/hps/mpr.ts @@ -2,8 +2,10 @@ import { Types } from '@ohif/core'; export const mpr: Types.HangingProtocol.Protocol = { id: 'mpr', - name: 'Multi-Planar Reconstruction', + name: 'MPR', locked: true, + icon: 'layout-advanced-mpr', + isPreset: true, createdDate: '2021-02-23', modifiedDate: '2023-08-15', availableTo: {}, diff --git a/extensions/cornerstone/src/hps/only3D.ts b/extensions/cornerstone/src/hps/only3D.ts index d319d1ee4..53c32cf61 100644 --- a/extensions/cornerstone/src/hps/only3D.ts +++ b/extensions/cornerstone/src/hps/only3D.ts @@ -1,7 +1,9 @@ export const only3D = { id: 'only3D', locked: true, - name: 'only3D', + name: '3D only', + icon: 'layout-advanced-3d-only', + isPreset: true, createdDate: '2023-03-15T10:29:44.894Z', modifiedDate: '2023-03-15T10:29:44.894Z', availableTo: {}, diff --git a/extensions/cornerstone/src/hps/primary3D.ts b/extensions/cornerstone/src/hps/primary3D.ts index 126553248..8d92943ae 100644 --- a/extensions/cornerstone/src/hps/primary3D.ts +++ b/extensions/cornerstone/src/hps/primary3D.ts @@ -1,7 +1,9 @@ export const primary3D = { id: 'primary3D', locked: true, - name: 'primary3D', + name: '3D primary', + icon: 'layout-advanced-3d-primary', + isPreset: true, createdDate: '2023-03-15T10:29:44.894Z', modifiedDate: '2023-03-15T10:29:44.894Z', availableTo: {}, diff --git a/extensions/cornerstone/src/hps/primaryAxial.ts b/extensions/cornerstone/src/hps/primaryAxial.ts index 2126920b3..f42b919fa 100644 --- a/extensions/cornerstone/src/hps/primaryAxial.ts +++ b/extensions/cornerstone/src/hps/primaryAxial.ts @@ -1,7 +1,9 @@ export const primaryAxial = { id: 'primaryAxial', locked: true, - name: 'primaryAxial', + name: 'Axial Primary', + icon: 'layout-advanced-axial-primary', + isPreset: true, createdDate: '2023-03-15T10:29:44.894Z', modifiedDate: '2023-03-15T10:29:44.894Z', availableTo: {}, diff --git a/extensions/default/src/Toolbar/LegacyLayoutSelector.tsx b/extensions/default/src/Toolbar/LegacyLayoutSelector.tsx new file mode 100644 index 000000000..341f6686e --- /dev/null +++ b/extensions/default/src/Toolbar/LegacyLayoutSelector.tsx @@ -0,0 +1,88 @@ +import React, { useEffect, useState, useCallback } from 'react'; +import PropTypes from 'prop-types'; +import { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui'; +import { ServicesManager } from '@ohif/core'; + +function LegacyLayoutSelectorWithServices({ servicesManager, ...props }) { + const { toolbarService } = servicesManager.services; + + const onSelection = useCallback( + props => { + toolbarService.recordInteraction({ + interactionType: 'action', + commands: [ + { + commandName: 'setViewportGridLayout', + commandOptions: { ...props }, + context: 'DEFAULT', + }, + ], + }); + }, + [toolbarService] + ); + + return ( + + ); +} + +function LayoutSelector({ rows, columns, className, onSelection, ...rest }) { + const [isOpen, setIsOpen] = useState(false); + + const closeOnOutsideClick = () => { + if (isOpen) { + setIsOpen(false); + } + }; + + useEffect(() => { + window.addEventListener('click', closeOnOutsideClick); + return () => { + window.removeEventListener('click', closeOnOutsideClick); + }; + }, [isOpen]); + + const onInteractionHandler = () => setIsOpen(!isOpen); + const DropdownContent = isOpen ? OHIFLayoutSelector : null; + + return ( + + ) + } + isActive={isOpen} + type="toggle" + /> + ); +} + +LayoutSelector.propTypes = { + rows: PropTypes.number, + columns: PropTypes.number, + onLayoutChange: PropTypes.func, + servicesManager: PropTypes.instanceOf(ServicesManager), +}; + +LayoutSelector.defaultProps = { + rows: 3, + columns: 3, + onLayoutChange: () => {}, +}; + +export default LegacyLayoutSelectorWithServices; diff --git a/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx b/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx index 27202ed0a..8428472dd 100644 --- a/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx +++ b/extensions/default/src/Toolbar/ToolbarLayoutSelector.tsx @@ -1,37 +1,127 @@ import React, { useEffect, useState, useCallback } from 'react'; import PropTypes from 'prop-types'; -import { LayoutSelector as OHIFLayoutSelector, ToolbarButton } from '@ohif/ui'; +import { LayoutSelector as OHIFLayoutSelector, ToolbarButton, LayoutPreset } from '@ohif/ui'; import { ServicesManager } from '@ohif/core'; -function ToolbarLayoutSelectorWithServices({ servicesManager, commands, ...props }) { - const { toolbarService, viewportGridService } = servicesManager.services; +const defaultCommonPresets = [ + { + icon: 'layout-common-1x1', + commandOptions: { + numRows: 1, + numCols: 1, + }, + }, + { + icon: 'layout-common-1x2', + commandOptions: { + numRows: 1, + numCols: 2, + }, + }, + { + icon: 'layout-common-2x2', + commandOptions: { + numRows: 2, + numCols: 2, + }, + }, + { + icon: 'layout-common-2x3', + commandOptions: { + numRows: 2, + numCols: 3, + }, + }, +]; - const onInteraction = useCallback( - args => { - const viewportId = viewportGridService.getActiveViewportId(); - const refreshProps = { - viewportId, - }; - - if (props.onLayoutChange) { - props.onLayoutChange(args); +const generateAdvancedPresets = hangingProtocolService => { + const hangingProtocols = Array.from(hangingProtocolService.protocols.values()); + return hangingProtocols + .map(hp => { + if (!hp.isPreset) { + return null; } - toolbarService.recordInteraction({ commands }, { ...args, refreshProps }); + return { + icon: hp.icon, + title: hp.name, + commandOptions: { + protocolId: hp.id, + }, + }; + }) + .filter(preset => preset !== null); +}; + +function ToolbarLayoutSelectorWithServices({ servicesManager, ...props }) { + const { toolbarService } = servicesManager.services; + + const [isDisabled, setIsDisabled] = useState(false); + + const handleMouseEnter = () => { + setIsDisabled(false); + }; + + const onSelection = useCallback( + props => { + toolbarService.recordInteraction({ + interactionType: 'action', + commands: [ + { + commandName: 'setViewportGridLayout', + commandOptions: { ...props }, + }, + ], + }); + setIsDisabled(true); + }, + [toolbarService] + ); + const onSelectionPreset = useCallback( + props => { + toolbarService.recordInteraction({ + interactionType: 'action', + commands: [ + { + commandName: 'setHangingProtocol', + commandOptions: { ...props }, + }, + ], + }); + setIsDisabled(true); }, [toolbarService] ); return ( - +
+ +
); } -function LayoutSelector({ rows, columns, className, onInteraction, ...rest }) { +function LayoutSelector({ + rows, + columns, + className, + onSelection, + onSelectionPreset, + servicesManager, + tooltipDisabled, + ...rest +}) { const [isOpen, setIsOpen] = useState(false); + const { customizationService, hangingProtocolService } = servicesManager.services; + const commonPresets = customizationService.get('commonPresets') || defaultCommonPresets; + const advancedPresets = + customizationService.get('advancedPresets') || generateAdvancedPresets(hangingProtocolService); + const closeOnOutsideClick = () => { if (isOpen) { setIsOpen(false); @@ -45,24 +135,68 @@ function LayoutSelector({ rows, columns, className, onInteraction, ...rest }) { }; }, [isOpen]); - const onInteractionHandler = () => setIsOpen(!isOpen); + const onInteractionHandler = () => { + setIsOpen(!isOpen); + }; const DropdownContent = isOpen ? OHIFLayoutSelector : null; return ( +
+
+
Common
+ +
+ {commonPresets.map((preset, index) => ( + + ))} +
+ +
+ +
Advanced
+ +
+ {advancedPresets.map((preset, index) => ( + + ))} +
+
+ +
+
Custom
+ +

+ Hover to select

rows and columns

Click to apply +

+
+
) } isActive={isOpen} @@ -79,8 +213,8 @@ LayoutSelector.propTypes = { }; LayoutSelector.defaultProps = { + columns: 4, rows: 3, - columns: 3, onLayoutChange: () => {}, }; diff --git a/modes/basic-dev-mode/src/toolbarButtons.js b/modes/basic-dev-mode/src/toolbarButtons.js index 638e73b72..e11c15a25 100644 --- a/modes/basic-dev-mode/src/toolbarButtons.js +++ b/modes/basic-dev-mode/src/toolbarButtons.js @@ -148,7 +148,7 @@ const toolbarButtons: Button[] = [ uiType: 'ohif.layoutSelector', props: { rows: 3, - columns: 3, + columns: 4, evaluate: 'evaluate.action', commands: [ { diff --git a/modes/basic-test-mode/src/initToolGroups.ts b/modes/basic-test-mode/src/initToolGroups.ts index 3187e12e3..97caed87a 100644 --- a/modes/basic-test-mode/src/initToolGroups.ts +++ b/modes/basic-test-mode/src/initToolGroups.ts @@ -193,10 +193,38 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { toolGroupService.createToolGroupAndAddTools('mpr', tools); } +function initVolume3DToolGroup(extensionManager, toolGroupService) { + const utilityModule = extensionManager.getModuleEntry( + '@ohif/extension-cornerstone.utilityModule.tools' + ); + + const { toolNames, Enums } = utilityModule.exports; + + const tools = { + active: [ + { + toolName: toolNames.TrackballRotateTool, + bindings: [{ mouseButton: Enums.MouseBindings.Primary }], + }, + { + toolName: toolNames.Zoom, + bindings: [{ mouseButton: Enums.MouseBindings.Secondary }], + }, + { + toolName: toolNames.Pan, + bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }], + }, + ], + }; + + toolGroupService.createToolGroupAndAddTools('volume3d', tools); +} + function initToolGroups(extensionManager, toolGroupService, commandsManager) { initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, 'default'); initSRToolGroup(extensionManager, toolGroupService, commandsManager); initMPRToolGroup(extensionManager, toolGroupService, commandsManager); + initVolume3DToolGroup(extensionManager, toolGroupService); } export default initToolGroups; diff --git a/modes/basic-test-mode/src/toolbarButtons.ts b/modes/basic-test-mode/src/toolbarButtons.ts index 34b300e22..2e1517676 100644 --- a/modes/basic-test-mode/src/toolbarButtons.ts +++ b/modes/basic-test-mode/src/toolbarButtons.ts @@ -155,6 +155,41 @@ const toolbarButtons: Button[] = [ evaluate: 'evaluate.cornerstoneTool', }, }, + { + id: 'MPR', + uiType: 'ohif.radioGroup', + props: { + icon: 'icon-mpr', + label: 'MPR', + commands: [ + { + commandName: 'toggleHangingProtocol', + commandOptions: { + protocolId: 'mpr', + }, + }, + ], + evaluate: 'evaluate.mpr', + }, + }, + { + id: 'TrackBallRotate', + type: 'ohif.radioGroup', + props: { + type: 'tool', + icon: 'tool-3d-rotate', + label: '3D Rotate', + commands: [ + { + commandName: 'setToolActive', + commandOptions: { + toolName: 'TrackBallRotate', + }, + context: 'CORNERSTONE', + }, + ], + }, + }, { id: 'Capture', uiType: 'ohif.radioGroup', @@ -174,30 +209,9 @@ const toolbarButtons: Button[] = [ uiType: 'ohif.layoutSelector', props: { rows: 3, - columns: 3, + columns: 4, evaluate: 'evaluate.action', - commands: [ - { - commandName: 'setViewportGridLayout', - }, - ], - }, - }, - { - id: 'MPR', - uiType: 'ohif.radioGroup', - props: { - icon: 'icon-mpr', - label: 'MPR', - commands: [ - { - commandName: 'toggleHangingProtocol', - commandOptions: { - protocolId: 'mpr', - }, - }, - ], - evaluate: 'evaluate.mpr', + commands: 'setViewportGridLayout', }, }, { diff --git a/modes/longitudinal/src/index.js b/modes/longitudinal/src/index.js index 87fe93251..a04a7d301 100644 --- a/modes/longitudinal/src/index.js +++ b/modes/longitudinal/src/index.js @@ -83,11 +83,11 @@ function modeFactory({ modeConfiguration }) { toolbarService.createButtonSection('primary', [ 'MeasurementTools', 'Zoom', - 'WindowLevel', 'Pan', + 'TrackballRotate', + 'WindowLevel', 'Capture', 'Layout', - 'MPR', 'Crosshairs', 'MoreTools', ]); diff --git a/modes/longitudinal/src/moreTools.ts b/modes/longitudinal/src/moreTools.ts index 2f3d5c247..8b0e0c9e0 100644 --- a/modes/longitudinal/src/moreTools.ts +++ b/modes/longitudinal/src/moreTools.ts @@ -54,7 +54,7 @@ const moreTools = [ label: 'Flip Horizontal', tooltip: 'Flip Horizontally', commands: 'flipViewportHorizontal', - evaluate: 'evaluate.viewportProperties.toggle', + evaluate: ['evaluate.viewportProperties.toggle', 'evaluate.not3D'], }), createButton({ id: 'ImageSliceSync', @@ -73,7 +73,7 @@ const moreTools = [ commandOptions: { toggledState: true }, }, }, - evaluate: 'evaluate.cornerstone.synchronizer', + evaluate: ['evaluate.cornerstone.synchronizer', 'evaluate.not3D'], }), createButton({ id: 'ReferenceLines', @@ -137,7 +137,7 @@ const moreTools = [ label: 'Cine', tooltip: 'Cine', commands: 'toggleCine', - evaluate: 'evaluate.cine', + evaluate: ['evaluate.cine', 'evaluate.not3D'], }), createButton({ id: 'Angle', diff --git a/modes/longitudinal/src/toolbarButtons.ts b/modes/longitudinal/src/toolbarButtons.ts index 34b300e22..76217b29f 100644 --- a/modes/longitudinal/src/toolbarButtons.ts +++ b/modes/longitudinal/src/toolbarButtons.ts @@ -1,9 +1,6 @@ // TODO: torn, can either bake this here; or have to create a whole new button type // Only ways that you can pass in a custom React component for render :l -import { - // ListMenu, - WindowLevelMenuItem, -} from '@ohif/ui'; +import { WindowLevelMenuItem } from '@ohif/ui'; import { defaults, ToolbarService } from '@ohif/core'; import type { Button } from '@ohif/core/types'; @@ -36,7 +33,7 @@ function _createWwwcPreset(preset, title, subtitle) { export const setToolActiveToolbar = { commandName: 'setToolActiveToolbar', commandOptions: { - toolGroupIds: ['default', 'mpr', 'SRToolGroup'], + toolGroupIds: ['default', 'mpr', 'SRToolGroup', 'volume3d'], }, }; @@ -155,6 +152,17 @@ const toolbarButtons: Button[] = [ evaluate: 'evaluate.cornerstoneTool', }, }, + { + id: 'TrackballRotate', + uiType: 'ohif.radioGroup', + props: { + type: 'tool', + icon: 'tool-3d-rotate', + label: '3D Rotate', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }, + }, { id: 'Capture', uiType: 'ohif.radioGroup', @@ -174,7 +182,7 @@ const toolbarButtons: Button[] = [ uiType: 'ohif.layoutSelector', props: { rows: 3, - columns: 3, + columns: 4, evaluate: 'evaluate.action', commands: [ { @@ -183,23 +191,6 @@ const toolbarButtons: Button[] = [ ], }, }, - { - id: 'MPR', - uiType: 'ohif.radioGroup', - props: { - icon: 'icon-mpr', - label: 'MPR', - commands: [ - { - commandName: 'toggleHangingProtocol', - commandOptions: { - protocolId: 'mpr', - }, - }, - ], - evaluate: 'evaluate.mpr', - }, - }, { id: 'Crosshairs', uiType: 'ohif.radioGroup', diff --git a/modes/segmentation/package.json b/modes/segmentation/package.json index b4c4a277e..98d772ad0 100644 --- a/modes/segmentation/package.json +++ b/modes/segmentation/package.json @@ -35,7 +35,14 @@ "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" }, "peerDependencies": { - "@ohif/core": "3.8.0-beta.64" + "@ohif/core": "3.8.0-beta.64", + "@ohif/extension-cornerstone": "3.8.0-beta.64", + "@ohif/extension-cornerstone-dicom-rt": "3.8.0-beta.64", + "@ohif/extension-cornerstone-dicom-seg": "3.8.0-beta.64", + "@ohif/extension-cornerstone-dicom-sr": "3.8.0-beta.64", + "@ohif/extension-default": "3.8.0-beta.64", + "@ohif/extension-dicom-pdf": "3.8.0-beta.64", + "@ohif/extension-dicom-video": "3.8.0-beta.64" }, "dependencies": { "@babel/runtime": "^7.20.13", diff --git a/modes/segmentation/src/index.tsx b/modes/segmentation/src/index.tsx index e4db1b9e9..85a55a830 100644 --- a/modes/segmentation/src/index.tsx +++ b/modes/segmentation/src/index.tsx @@ -4,6 +4,9 @@ import toolbarButtons from './toolbarButtons'; import segmentationButtons from './segmentationButtons'; import initToolGroups from './initToolGroups'; +const DEFAULT_TOOL_GROUP_ID = 'default'; +const VOLUME3D_TOOL_GROUP_ID = 'volume3d'; + const ohif = { layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack', @@ -62,12 +65,13 @@ function modeFactory({ modeConfiguration }) { toolbarService.addButtons(segmentationButtons); toolbarService.createButtonSection('primary', [ + 'WindowLevel', 'Pan', + 'Zoom', + 'TrackballRotate', 'Capture', 'Layout', - 'MPR', 'Crosshairs', - 'Zoom', 'MoreTools', ]); toolbarService.createButtonSection('segmentationToolbox', ['BrushTools', 'Shapes']); @@ -105,9 +109,13 @@ function modeFactory({ modeConfiguration }) { // that is not supported by the mode const modalitiesArray = modalities.split('\\'); return { - valid: modalitiesArray.length === 1 ? !['SM', 'US', 'MG', 'OT', 'DOC', 'CR'].includes(modalitiesArray[0]) : true, - description: 'The mode does not support studies that ONLY include the following modalities: SM, US, MG, OT, DOC, CR', - } + valid: + modalitiesArray.length === 1 + ? !['SM', 'US', 'MG', 'OT', 'DOC', 'CR'].includes(modalitiesArray[0]) + : true, + description: + 'The mode does not support studies that ONLY include the following modalities: SM, US, MG, OT, DOC, CR', + }; }, /** * Mode Routes are used to define the mode's behavior. A list of Mode Route diff --git a/modes/segmentation/src/initToolGroups.ts b/modes/segmentation/src/initToolGroups.ts index 31895daf0..026cecdbf 100644 --- a/modes/segmentation/src/initToolGroups.ts +++ b/modes/segmentation/src/initToolGroups.ts @@ -81,6 +81,7 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { toolName: utilityModule.exports.toolNames.Crosshairs, configuration: { viewportIndicators: false, + disableOnPassive: true, autoPan: { enabled: false, panSize: 10, @@ -92,9 +93,37 @@ function initMPRToolGroup(extensionManager, toolGroupService, commandsManager) { toolGroupService.createToolGroupAndAddTools('mpr', tools); } +function initVolume3DToolGroup(extensionManager, toolGroupService) { + const utilityModule = extensionManager.getModuleEntry( + '@ohif/extension-cornerstone.utilityModule.tools' + ); + + const { toolNames, Enums } = utilityModule.exports; + + const tools = { + active: [ + { + toolName: toolNames.TrackballRotateTool, + bindings: [{ mouseButton: Enums.MouseBindings.Primary }], + }, + { + toolName: toolNames.Zoom, + bindings: [{ mouseButton: Enums.MouseBindings.Secondary }], + }, + { + toolName: toolNames.Pan, + bindings: [{ mouseButton: Enums.MouseBindings.Auxiliary }], + }, + ], + }; + + toolGroupService.createToolGroupAndAddTools('volume3d', tools); +} + function initToolGroups(extensionManager, toolGroupService, commandsManager) { initDefaultToolGroup(extensionManager, toolGroupService, commandsManager, 'default'); initMPRToolGroup(extensionManager, toolGroupService, commandsManager); + initVolume3DToolGroup(extensionManager, toolGroupService); } export default initToolGroups; diff --git a/modes/segmentation/src/toolbarButtons.ts b/modes/segmentation/src/toolbarButtons.ts index bbff5e2d6..4d2dacd06 100644 --- a/modes/segmentation/src/toolbarButtons.ts +++ b/modes/segmentation/src/toolbarButtons.ts @@ -1,8 +1,16 @@ -import { defaults, ToolbarService } from '@ohif/core'; import type { Button } from '@ohif/core/types'; +import { defaults, ToolbarService, ViewportGridService } from '@ohif/core'; import { WindowLevelMenuItem } from '@ohif/ui'; const { windowLevelPresets } = defaults; +const { createButton } = ToolbarService; + +const ReferenceLinesListeners: RunCommand = [ + { + commandName: 'setSourceViewportForReferenceLinesTool', + context: 'CORNERSTONE', + }, +]; function _createWwwcPreset(preset, title, subtitle) { return { @@ -21,16 +29,12 @@ function _createWwwcPreset(preset, title, subtitle) { }; } -function _createSetToolActiveCommands(toolName, toolGroupIds = ['default', 'mpr', 'SRToolGroup']) { - return toolGroupIds.map(toolGroupId => ({ - commandName: 'setToolActive', - commandOptions: { - toolGroupId, - toolName, - }, - context: 'CORNERSTONE', - })); -} +export const setToolActiveToolbar = { + commandName: 'setToolActiveToolbar', + commandOptions: { + toolGroupIds: ['default', 'mpr', 'SRToolGroup'], + }, +}; const toolbarButtons: Button[] = [ { @@ -39,7 +43,7 @@ const toolbarButtons: Button[] = [ props: { icon: 'tool-zoom', label: 'Zoom', - commands: _createSetToolActiveCommands('Zoom'), + commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }, }, @@ -48,12 +52,12 @@ const toolbarButtons: Button[] = [ uiType: 'ohif.splitButton', props: { groupId: 'WindowLevel', - primary: ToolbarService.createButton({ + primary: createButton({ id: 'WindowLevel', icon: 'tool-window-level', label: 'Window Level', tooltip: 'Window Level', - commands: _createSetToolActiveCommands('WindowLevel'), + commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }), secondary: { @@ -76,7 +80,18 @@ const toolbarButtons: Button[] = [ props: { icon: 'tool-move', label: 'Pan', - commands: _createSetToolActiveCommands('Pan'), + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }, + }, + { + id: 'TrackballRotate', + uiType: 'ohif.radioGroup', + props: { + type: 'tool', + icon: 'tool-3d-rotate', + label: '3D Rotate', + commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }, }, @@ -86,12 +101,7 @@ const toolbarButtons: Button[] = [ props: { icon: 'tool-capture', label: 'Capture', - commands: [ - { - commandName: 'showDownloadViewportModal', - context: 'CORNERSTONE', - }, - ], + commands: 'showDownloadViewportModal', evaluate: 'evaluate.action', }, }, @@ -100,31 +110,9 @@ const toolbarButtons: Button[] = [ uiType: 'ohif.layoutSelector', props: { rows: 3, - columns: 3, + columns: 4, evaluate: 'evaluate.action', - commands: [ - { - commandName: 'setViewportGridLayout', - }, - ], - }, - }, - { - id: 'MPR', - uiType: 'ohif.radioGroup', - props: { - icon: 'icon-mpr', - label: 'MPR', - commands: [ - { - commandName: 'toggleHangingProtocol', - commandOptions: { - protocolId: 'mpr', - }, - context: 'DEFAULT', - }, - ], - evaluate: 'evaluate.mpr', + commands: 'setViewportGridLayout', }, }, { @@ -133,7 +121,12 @@ const toolbarButtons: Button[] = [ props: { icon: 'tool-crosshair', label: 'Crosshairs', - commands: _createSetToolActiveCommands('Crosshairs', ['mpr']), + commands: { + commandName: 'setToolActiveToolbar', + commandOptions: { + toolGroupIds: ['mpr'], + }, + }, evaluate: 'evaluate.cornerstoneTool', }, }, @@ -143,104 +136,146 @@ const toolbarButtons: Button[] = [ props: { groupId: 'MoreTools', evaluate: 'evaluate.group.promoteToPrimaryIfCornerstoneToolNotActiveInTheList', - primary: ToolbarService.createButton({ + primary: createButton({ id: 'Reset', icon: 'tool-reset', - label: 'Reset View', - tooltip: 'Reset', - commands: [ - { - commandName: 'resetViewport', - context: 'CORNERSTONE', - }, - ], + tooltip: 'Reset View', + label: 'Reset', + commands: 'resetViewport', evaluate: 'evaluate.action', }), secondary: { icon: 'chevron-down', + label: '', tooltip: 'More Tools', }, items: [ - ToolbarService.createButton({ - id: 'RotateRight', + createButton({ + id: 'Reset', + icon: 'tool-reset', + label: 'Reset View', + tooltip: 'Reset View', + commands: 'resetViewport', + evaluate: 'evaluate.action', + }), + createButton({ + id: 'rotate-right', icon: 'tool-rotate-right', label: 'Rotate Right', tooltip: 'Rotate +90', - commands: [ - { - commandName: 'rotateViewportCW', - context: 'CORNERSTONE', - }, - ], + commands: 'rotateViewportCW', evaluate: 'evaluate.action', }), - ToolbarService.createButton({ - id: 'FlipHorizontal', + createButton({ + id: 'flipHorizontal', icon: 'tool-flip-horizontal', - label: 'Flip Horizontally', - tooltip: 'Flip Horizontal', - commands: [ - { - commandName: 'flipViewportHorizontal', - context: 'CORNERSTONE', - }, - ], - evaluate: 'evaluate.action', + label: 'Flip Horizontal', + tooltip: 'Flip Horizontally', + commands: 'flipViewportHorizontal', + evaluate: ['evaluate.viewportProperties.toggle', 'evaluate.not3D'], }), - ToolbarService.createButton({ + createButton({ + id: 'ReferenceLines', + icon: 'tool-referenceLines', + label: 'Reference Lines', + tooltip: 'Show Reference Lines', + commands: { + commandName: 'setToolEnabled', + commandOptions: { + toolName: 'ReferenceLines', + toggle: true, // Toggle the tool on/off upon click + }, + }, + listeners: { + [ViewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED]: ReferenceLinesListeners, + [ViewportGridService.EVENTS.VIEWPORTS_READY]: ReferenceLinesListeners, + }, + evaluate: 'evaluate.cornerstoneTool.toggle', + }), + createButton({ + id: 'ImageOverlay', + icon: 'toggle-dicom-overlay', + label: 'Image Overlay', + tooltip: 'Toggle Image Overlay', + commands: { + commandName: 'setToolEnabled', + commandOptions: { + toolName: 'ImageOverlayViewer', + toggle: true, // Toggle the tool on/off upon click + }, + }, + evaluate: 'evaluate.cornerstoneTool.toggle', + }), + createButton({ id: 'StackScroll', icon: 'tool-stack-scroll', label: 'Stack Scroll', tooltip: 'Stack Scroll', - commands: _createSetToolActiveCommands('StackScroll'), + commands: setToolActiveToolbar, evaluate: 'evaluate.cornerstoneTool', }), - ToolbarService.createButton({ - id: 'Magnify', - icon: 'tool-magnify', - label: 'Magnify', - tooltip: 'Magnify', - commands: _createSetToolActiveCommands('Magnify'), - evaluate: 'evaluate.cornerstoneTool', - }), - ToolbarService.createButton({ - id: 'Invert', + createButton({ + id: 'invert', icon: 'tool-invert', label: 'Invert', tooltip: 'Invert Colors', - commands: [ - { - commandName: 'invertViewport', - context: 'CORNERSTONE', - }, - ], - evaluate: 'evaluate.action', + commands: 'invertViewport', + evaluate: 'evaluate.viewportProperties.toggle', }), - ToolbarService.createButton({ + createButton({ + id: 'Probe', + icon: 'tool-probe', + label: 'Probe', + tooltip: 'Probe', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), + createButton({ id: 'Cine', icon: 'tool-cine', label: 'Cine', tooltip: 'Cine', - commands: [ - { - commandName: 'toggleCine', - context: 'CORNERSTONE', - }, - ], - evaluate: 'evaluate.action', + commands: 'toggleCine', + evaluate: ['evaluate.cine', 'evaluate.not3D'], }), - ToolbarService.createButton({ - id: 'DicomTagBrowser', + createButton({ + id: 'Angle', + icon: 'tool-angle', + label: 'Angle', + tooltip: 'Angle', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), + createButton({ + id: 'Magnify', + icon: 'tool-magnify', + label: 'Magnify', + tooltip: 'Magnify', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), + createButton({ + id: 'RectangleROI', + icon: 'tool-rectangle', + label: 'Rectangle', + tooltip: 'Rectangle', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), + createButton({ + id: 'CalibrationLine', + icon: 'tool-calibration', + label: 'Calibration', + tooltip: 'Calibration Line', + commands: setToolActiveToolbar, + evaluate: 'evaluate.cornerstoneTool', + }), + createButton({ + id: 'TagBrowser', icon: 'list-bullets', label: 'Dicom Tag Browser', tooltip: 'Dicom Tag Browser', - commands: [ - { - commandName: 'openDICOMTagViewer', - context: 'DEFAULT', - }, - ], - evaluate: 'evaluate.action', + commands: 'openDICOMTagViewer', }), ], }, diff --git a/modes/tmtv/src/toolbarButtons.js b/modes/tmtv/src/toolbarButtons.js index 35d3f3383..5beaac21f 100644 --- a/modes/tmtv/src/toolbarButtons.js +++ b/modes/tmtv/src/toolbarButtons.js @@ -100,22 +100,6 @@ const toolbarButtons = [ evaluate: 'evaluate.cornerstoneTool', }, }, - { - id: 'MPR', - uiType: 'ohif.radioGroup', - props: { - icon: 'icon-mpr', - label: 'MPR', - commands: [ - { - commandName: 'toggleHangingProtocol', - commandOptions: { protocolId: 'mpr' }, - context: 'DEFAULT', - }, - ], - evaluate: 'evaluate.mpr', - }, - }, // Window Level + Presets { id: 'WindowLevel', diff --git a/platform/app/cypress/support/aliases.js b/platform/app/cypress/support/aliases.js index 1bda29b36..5b28709ca 100644 --- a/platform/app/cypress/support/aliases.js +++ b/platform/app/cypress/support/aliases.js @@ -12,7 +12,6 @@ export function initCornerstoneToolsAliases() { cy.get('[data-cy="MoreTools-split-button-secondary"]').as('moreBtnSecondary'); cy.get('[data-cy="Layout"]').as('layoutBtn'); cy.get('.cornerstone-viewport-element').as('viewport'); - cy.get('[data-cy="MPR"]').as('mprBtn'); } //Creating aliases for Common page elements diff --git a/platform/cli/templates/mode/src/index.tsx b/platform/cli/templates/mode/src/index.tsx index 7ff747bbe..5efbe0a2a 100644 --- a/platform/cli/templates/mode/src/index.tsx +++ b/platform/cli/templates/mode/src/index.tsx @@ -56,7 +56,6 @@ function modeFactory({ modeConfiguration }) { 'Pan', 'Capture', 'Layout', - 'MPR', 'Crosshairs', 'MoreTools', ]); diff --git a/platform/core/src/services/ToolBarService/ToolbarService.ts b/platform/core/src/services/ToolBarService/ToolbarService.ts index eff3912ab..6fce58d2b 100644 --- a/platform/core/src/services/ToolBarService/ToolbarService.ts +++ b/platform/core/src/services/ToolBarService/ToolbarService.ts @@ -420,6 +420,34 @@ export default class ToolbarService extends PubSubService { return; } + if (Array.isArray(evaluate)) { + const evaluators = evaluate.map(evaluatorName => { + const evaluateFunction = this._evaluateFunction[evaluatorName]; + + if (!evaluateFunction) { + throw new Error( + `Evaluate function not found for name: ${evaluatorName}, you can register an evaluate function with the getToolbarModule in your extensions` + ); + } + + return evaluateFunction; + }); + + props.evaluate = args => { + const results = evaluators.map(evaluator => evaluator(args)); + const mergedResult = results.reduce((acc, result) => { + return { + ...acc, + ...result, + }; + }, {}); + + return mergedResult; + }; + + return; + } + if (typeof evaluate === 'string') { const evaluateFunction = this._evaluateFunction[evaluate]; @@ -429,7 +457,7 @@ export default class ToolbarService extends PubSubService { } throw new Error( - `Evaluate function not found for name: ${evaluate}, you can register an evaluate function with the getToolbarModule in your extensions` + `Evaluate function not found for name: ${evaluate}, you can register an evaluate function with the getToolbarModule in your extensions` ); } @@ -443,7 +471,7 @@ export default class ToolbarService extends PubSubService { } throw new Error( - `Evaluate function not found for name: ${name}, you can register an evaluate function with the getToolbarModule in your extensions` + `Evaluate function not found for name: ${name}, you can register an evaluate function with the getToolbarModule in your extensions` ); } }; diff --git a/platform/core/src/services/ToolBarService/types.ts b/platform/core/src/services/ToolBarService/types.ts index 9b53e5e3a..1318e90f3 100644 --- a/platform/core/src/services/ToolBarService/types.ts +++ b/platform/core/src/services/ToolBarService/types.ts @@ -1,6 +1,6 @@ import type { RunCommand } from '../../types/Command'; -export type EvaluatePublic = string | EvaluateFunction; +export type EvaluatePublic = string | EvaluateFunction | string[]; export type EvaluateFunction = (props: Record) => { disabled: boolean; diff --git a/platform/core/src/types/HangingProtocol.ts b/platform/core/src/types/HangingProtocol.ts index 0e23b1d2e..0c0efa512 100644 --- a/platform/core/src/types/HangingProtocol.ts +++ b/platform/core/src/types/HangingProtocol.ts @@ -304,6 +304,16 @@ export type Protocol = { */ minSeriesLoaded: number; }; + + /* + * The icon to use for this protocol. This is used to display the protocol + * in the advanced layout selector. + */ + + icon?: string; + + /** Indicates if the protocol is a preset or not. Useful for setting presets for the layout selector */ + isPreset?: true; }; /** Used to dynamically generate protocols. diff --git a/platform/docs/docs/migration-guide.md b/platform/docs/docs/migration-guide.md index 9ca0cf8a2..9f93828a5 100644 --- a/platform/docs/docs/migration-guide.md +++ b/platform/docs/docs/migration-guide.md @@ -657,7 +657,6 @@ onModeEnter: ({ servicesManager, extensionManager, commandsManager }) => { 'Pan', 'Capture', 'Layout', - 'MPR', 'Crosshairs', 'MoreTools', ]); diff --git a/platform/docs/docs/platform/extensions/modules/toolbar.md b/platform/docs/docs/platform/extensions/modules/toolbar.md index 1af8549c7..a735b2daf 100644 --- a/platform/docs/docs/platform/extensions/modules/toolbar.md +++ b/platform/docs/docs/platform/extensions/modules/toolbar.md @@ -184,7 +184,6 @@ function modeFactory({ modeConfiguration }) { 'Pan', 'Capture', 'Layout', - 'MPR', 'Crosshairs', 'MoreTools', ]); diff --git a/platform/docs/docs/platform/services/data/ToolbarService.md b/platform/docs/docs/platform/services/data/ToolbarService.md index 5a0a15964..3eb03ffd2 100644 --- a/platform/docs/docs/platform/services/data/ToolbarService.md +++ b/platform/docs/docs/platform/services/data/ToolbarService.md @@ -243,7 +243,6 @@ toolbarService.createButtonSection('primary', [ 'Pan', 'Capture', 'Layout', - 'MPR', 'Crosshairs', 'MoreTools', ]); diff --git a/platform/ui/src/assets/icons/layout-advanced-3d-four-up.svg b/platform/ui/src/assets/icons/layout-advanced-3d-four-up.svg new file mode 100644 index 000000000..f9f445ee1 --- /dev/null +++ b/platform/ui/src/assets/icons/layout-advanced-3d-four-up.svg @@ -0,0 +1,13 @@ + + + layout-advanced-3d-four-up + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-advanced-3d-main.svg b/platform/ui/src/assets/icons/layout-advanced-3d-main.svg new file mode 100644 index 000000000..15b5d31cc --- /dev/null +++ b/platform/ui/src/assets/icons/layout-advanced-3d-main.svg @@ -0,0 +1,12 @@ + + + layout-advanced-3d-main + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-advanced-3d-only.svg b/platform/ui/src/assets/icons/layout-advanced-3d-only.svg new file mode 100644 index 000000000..8ee7a7431 --- /dev/null +++ b/platform/ui/src/assets/icons/layout-advanced-3d-only.svg @@ -0,0 +1,9 @@ + + + layout-advanced-3d-only + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-advanced-3d-primary.svg b/platform/ui/src/assets/icons/layout-advanced-3d-primary.svg new file mode 100644 index 000000000..e77ecc9d6 --- /dev/null +++ b/platform/ui/src/assets/icons/layout-advanced-3d-primary.svg @@ -0,0 +1,12 @@ + + + layout-advanced-3d-primary + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-advanced-axial-primary.svg b/platform/ui/src/assets/icons/layout-advanced-axial-primary.svg new file mode 100644 index 000000000..79a34077a --- /dev/null +++ b/platform/ui/src/assets/icons/layout-advanced-axial-primary.svg @@ -0,0 +1,11 @@ + + + layout-advanced-axial-primary + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-advanced-mpr.svg b/platform/ui/src/assets/icons/layout-advanced-mpr.svg new file mode 100644 index 000000000..d23b2fbf4 --- /dev/null +++ b/platform/ui/src/assets/icons/layout-advanced-mpr.svg @@ -0,0 +1,11 @@ + + + layout-advanced-mpr + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-common-1x1.svg b/platform/ui/src/assets/icons/layout-common-1x1.svg new file mode 100644 index 000000000..537c7a86c --- /dev/null +++ b/platform/ui/src/assets/icons/layout-common-1x1.svg @@ -0,0 +1,9 @@ + + + layout-common-1x1 + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-common-1x2.svg b/platform/ui/src/assets/icons/layout-common-1x2.svg new file mode 100644 index 000000000..db5aca362 --- /dev/null +++ b/platform/ui/src/assets/icons/layout-common-1x2.svg @@ -0,0 +1,10 @@ + + + layout-common-1x2 + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-common-2x2.svg b/platform/ui/src/assets/icons/layout-common-2x2.svg new file mode 100644 index 000000000..8dfe00701 --- /dev/null +++ b/platform/ui/src/assets/icons/layout-common-2x2.svg @@ -0,0 +1,11 @@ + + + layout-common-2x2 + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/layout-common-2x3.svg b/platform/ui/src/assets/icons/layout-common-2x3.svg new file mode 100644 index 000000000..3cb298eec --- /dev/null +++ b/platform/ui/src/assets/icons/layout-common-2x3.svg @@ -0,0 +1,12 @@ + + + layout-common-2x3 + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/tool-3d-rotate.svg b/platform/ui/src/assets/icons/tool-3d-rotate.svg new file mode 100644 index 000000000..20d190cad --- /dev/null +++ b/platform/ui/src/assets/icons/tool-3d-rotate.svg @@ -0,0 +1,20 @@ + + + tool-3d-rotate + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/ui/src/assets/icons/tool-layout.svg b/platform/ui/src/assets/icons/tool-layout.svg index f225033dd..7e8bf1494 100644 --- a/platform/ui/src/assets/icons/tool-layout.svg +++ b/platform/ui/src/assets/icons/tool-layout.svg @@ -1,6 +1,21 @@ - - - - + + + tool-layout + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/platform/ui/src/components/Icon/getIcon.js b/platform/ui/src/components/Icon/getIcon.js index 47336987c..4940fb771 100644 --- a/platform/ui/src/components/Icon/getIcon.js +++ b/platform/ui/src/components/Icon/getIcon.js @@ -145,6 +145,20 @@ import oldTrash from './../../assets/icons/old-trash.svg'; import oldPlay from './../../assets/icons/old-play.svg'; import oldStop from './../../assets/icons/old-stop.svg'; +/** LAYOUT */ + +import layoutAdvanced3DFourUp from './../../assets/icons/layout-advanced-3d-four-up.svg'; +import layoutAdvanced3DMain from './../../assets/icons/layout-advanced-3d-main.svg'; +import layoutAdvanced3DOnly from './../../assets/icons/layout-advanced-3d-only.svg'; +import layoutAdvanced3DPrimary from './../../assets/icons/layout-advanced-3d-primary.svg'; +import layoutAdvancedAxialPrimary from './../../assets/icons/layout-advanced-axial-primary.svg'; +import layoutAdvancedMPR from './../../assets/icons/layout-advanced-mpr.svg'; +import layoutCommon1x1 from './../../assets/icons/layout-common-1x1.svg'; +import layoutCommon1x2 from './../../assets/icons/layout-common-1x2.svg'; +import layoutCommon2x2 from './../../assets/icons/layout-common-2x2.svg'; +import layoutCommon2x3 from './../../assets/icons/layout-common-2x3.svg'; +import iconToolRotate from './../../assets/icons/tool-3d-rotate.svg'; + /** New investigational use */ import investigationalUse from './../../assets/icons/illustration-investigational-use.svg'; @@ -256,6 +270,7 @@ const ICONS = { 'tool-freehand-line': toolFreehand, 'tool-freehand-polygon': toolFreehandPolygon, 'tool-polygon': toolPolygon, + 'tool-3d-rotate': iconToolRotate, 'edit-patient': editPatient, 'icon-mpr': iconMPR, 'icon-next-inactive': iconNextInactive, @@ -295,6 +310,18 @@ const ICONS = { 'old-play': oldPlay, 'old-stop': oldStop, + /** LAYOUT */ + 'layout-advanced-3d-four-up': layoutAdvanced3DFourUp, + 'layout-advanced-3d-main': layoutAdvanced3DMain, + 'layout-advanced-3d-only': layoutAdvanced3DOnly, + 'layout-advanced-3d-primary': layoutAdvanced3DPrimary, + 'layout-advanced-axial-primary': layoutAdvancedAxialPrimary, + 'layout-advanced-mpr': layoutAdvancedMPR, + 'layout-common-1x1': layoutCommon1x1, + 'layout-common-1x2': layoutCommon1x2, + 'layout-common-2x2': layoutCommon2x2, + 'layout-common-2x3': layoutCommon2x3, + /** New investigational use */ 'illustration-investigational-use': investigationalUse, }; diff --git a/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx b/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx new file mode 100644 index 000000000..79ba6be15 --- /dev/null +++ b/platform/ui/src/components/LayoutPreset/LayoutPreset.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Icon from '../Icon/Icon'; + +function LayoutPreset({ onSelection, title, icon, commandOptions, classNames }) { + return ( +
{ + onSelection(commandOptions); + }} + > + + {title &&
{title}
} +
+ ); +} + +LayoutPreset.defaultProps = { + onSelection: () => {}, +}; + +LayoutPreset.propTypes = { + onSelection: PropTypes.func.isRequired, + title: PropTypes.string, + icon: PropTypes.string.isRequired, + commandOptions: PropTypes.object.isRequired, + classNames: PropTypes.string, +}; + +export default LayoutPreset; diff --git a/platform/ui/src/components/LayoutPreset/index.js b/platform/ui/src/components/LayoutPreset/index.js new file mode 100644 index 000000000..c7d10c306 --- /dev/null +++ b/platform/ui/src/components/LayoutPreset/index.js @@ -0,0 +1,2 @@ +import LayoutPreset from './LayoutPreset'; +export default LayoutPreset; diff --git a/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx b/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx index be90880d6..2271069ed 100644 --- a/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx +++ b/platform/ui/src/components/LayoutSelector/LayoutSelector.tsx @@ -21,7 +21,6 @@ function LayoutSelector({ onSelection, rows, columns }) { gridTemplateRows: gridSize.repeat(rows), backgroundColor: '#090c29', // primary-dark }} - className="p-2" > {Array.apply(null, Array(rows * columns)) .map(function (_, i) { @@ -30,12 +29,8 @@ function LayoutSelector({ onSelection, rows, columns }) { .map(index => (
{ const x = index % columns; const y = Math.floor(index / columns); @@ -55,7 +50,7 @@ function LayoutSelector({ onSelection, rows, columns }) { LayoutSelector.defaultProps = { onSelection: () => {}, - columns: 3, + columns: 4, rows: 3, }; diff --git a/platform/ui/src/components/ToolbarButton/ToolbarButton.tsx b/platform/ui/src/components/ToolbarButton/ToolbarButton.tsx index 9665a8573..804f2df34 100644 --- a/platform/ui/src/components/ToolbarButton/ToolbarButton.tsx +++ b/platform/ui/src/components/ToolbarButton/ToolbarButton.tsx @@ -16,6 +16,7 @@ const ToolbarButton = ({ className, size, toolTipClassName, + disableToolTip = false, ...rest // }) => { @@ -37,6 +38,7 @@ const ToolbarButton = ({ content={shouldShowDropdown ? dropdownContent : label} tight={shouldShowDropdown} className={toolTipClassNameToUse} + isDisabled={disableToolTip} >