diff --git a/Packages/ohif-cornerstone/package.js b/Packages/ohif-cornerstone/package.js index 8b5a44323..0404f35aa 100644 --- a/Packages/ohif-cornerstone/package.js +++ b/Packages/ohif-cornerstone/package.js @@ -6,11 +6,11 @@ Package.describe({ Npm.depends({ hammerjs: '2.0.8', - 'cornerstone-core': '2.2.7', - 'cornerstone-tools': '3.0.0-b.1421', - 'cornerstone-math': '0.1.6', - 'dicom-parser': '1.8.0', - 'cornerstone-wado-image-loader': '2.1.4', + 'cornerstone-core': '2.2.8', + 'cornerstone-tools': '3.0.0-b.1471', + 'cornerstone-math': '0.1.7', + 'dicom-parser': '1.8.3', + 'cornerstone-wado-image-loader': '2.2.3', 'dcmjs': '0.2.1' }); diff --git a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/CornerstoneViewport.js b/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/CornerstoneViewport.js deleted file mode 100644 index 27fe94c61..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/CornerstoneViewport.js +++ /dev/null @@ -1,751 +0,0 @@ -import { - Component, -} from 'react'; -import React from 'react'; -import PropTypes from 'prop-types'; -import { OHIF } from 'meteor/ohif:core'; -import debounce from 'lodash.debounce'; -// import * as cornerstone from 'cornerstone-core'; -// import * as cornerstoneTools from 'cornerstone-tools'; - -import { - cornerstone, - cornerstoneTools, -} from 'meteor/ohif:cornerstone'; -import './CornerstoneViewport.styl'; -// import './lib/initCornerstone.js'; -import ImageScrollbar from '../ImageScrollbar/ImageScrollbar.js'; -import ViewportOverlay from '../ViewportOverlay/ViewportOverlay.js'; -import ToolContextMenu from '../ToolContextMenu/ToolContextMenu.js'; -import LoadingIndicator from '../LoadingIndicator/LoadingIndicator.js'; -import ViewportOrientationMarkers from '../ViewportOrientationMarkers/ViewportOrientationMarkers.js'; -import { - StackManager, -} from '../../../lib/StackManager'; -import './CornerstoneViewport.styl'; - -const EVENT_RESIZE = 'resize'; -const loadIndicatorDelay = 45; -const { - loadHandlerManager, -} = cornerstoneTools; - -function setToolsPassive(tools) { - tools.forEach((tool) => { - cornerstoneTools.setToolPassive(tool); - }); -} - -function initializeTools(tools) { - Array.from(tools).forEach((tool) => { - const apiTool = cornerstoneTools[`${tool.name}Tool`]; - if (apiTool) { - cornerstoneTools.addTool(apiTool, tool.configuration); - } else { - throw new Error(`Tool not found: ${tool.name}Tool`); - } - }); -} - -function getCornerstoneStack(viewportData) { - const { - displaySetInstanceUid, - studyInstanceUid, - } = viewportData; - - // Create shortcut to displaySet - const study = OHIF.viewer.Studies.findBy({ - studyInstanceUid, - }); - - const displaySet = study.displaySets.find((set) => { - return set.displaySetInstanceUid === displaySetInstanceUid; - }); - - // Get stack from Stack Manager - const stack = StackManager.findOrCreateStack(study, displaySet); - stack.currentImageIdIndex = 0; - - return stack; -} - - -const scrollToIndex = cornerstoneTools.import('util/scrollToIndex'); - -class CornerstoneViewport extends Component { - constructor(props) { - super(props); - - const stack = getCornerstoneStack(this.props.viewportData); - - // TODO: Allow viewport as a prop - this.state = { - stack, - displaySetInstanceUid: this.props.viewportData.displaySetInstanceUid, - imageId: stack.imageIds[0], - viewportHeight: '100%', - isLoading: false, // true, - imageScrollbarValue: 0, - numImagesLoaded: 0, - }; - - this.displayScrollbar = stack.imageIds.length > 1; - this.state.viewport = cornerstone.getDefaultViewport(null, undefined); - - this.onImageRendered = this.onImageRendered.bind(this); - this.onNewImage = this.onNewImage.bind(this); - this.onWindowResize = this.onWindowResize.bind(this); - this.onImageLoaded = this.onImageLoaded.bind(this); - this.onStackScroll = this.onStackScroll.bind(this); - this.startLoadingHandler = this.startLoadingHandler.bind(this); - this.doneLoadingHandler = this.doneLoadingHandler.bind(this); - this.onMouseClick = this.onMouseClick.bind(this); - this.onTouchPress = this.onTouchPress.bind(this); - this.onTouchStart = this.onTouchStart.bind(this); - this.onMeasurementAddedOrRemoved = this.onMeasurementAddedOrRemoved.bind( - this, - ); - - this.setViewportActive = this.setViewportActive.bind(this); - - this.onCloseToolContextMenu = this.onCloseToolContextMenu.bind(this); - this.imageSliderOnInputCallback = this.imageSliderOnInputCallback.bind( - this, - ); - - this.loadHandlerTimeout = 25; - // loadHandlerManager.setStartLoadHandler(this.startLoadingHandler); - // loadHandlerManager.setEndLoadHandler(this.doneLoadingHandler); - - this.debouncedResize = debounce(() => { - try { - cornerstone.getEnabledElement(this.element); - } catch (error) { - console.error(error); - return; - } - - cornerstone.resize(this.element, true); - - this.setState({ - viewportHeight: `${this.element.clientHeight - 20}px`, - }); - }, 300); - - this.slideTimeoutTime = 25; - this.slideTimeout = null; - } - - static defaultProps = { - activeTool: 'Wwwc', - } - - render() { - const isLoading = this.state.isLoading || this.state.numImagesLoaded / this.state.stack.imageIds.length < 0.1; - - return (
-
{ - this.element = input; - } - } - > - { - isLoading ? : '' - } -
{ - this.displayScrollbar && ( - ) - } { - /* this.state.bidirectionalAddLabelShow && ( - - )*/ - }
- ); - } - -bidirectionalToolLabellingCallback = ( - measurementData, - eventData, - doneCallback, - options = {}, -) => { - const labellingDoneCallback = () => { - this.hideExtraButtons(); - return doneCallback(); - }; - - this.bidirectional = { - measurementData, - eventData, - labellingDoneCallback, - skipButton: options.skipButton, - editDescription: options.editDescription, - }; - - this.setState({ - bidirectionalAddLabelShow: true, - }); -}; - -onContextMenu(event) { - // Preventing the default behaviour for right-click is essential to - // allow right-click tools to work. - event.preventDefault(); -} - -onWindowResize() { - this.debouncedResize(); -} - -onImageRendered() { - const viewport = cornerstone.getViewport(this.element); - - this.setState({ - viewport, - }); -} - -onNewImage() { - const image = cornerstone.getImage(this.element); - - this.setState({ - imageId: image.imageId, - }); -} - -componentDidMount() { - const element = this.element; - - // Enable the DOM Element for use with Cornerstone - cornerstone.enable(element); - - cornerstone.events.addEventListener( - cornerstone.EVENTS.IMAGE_LOADED, - this.onImageLoaded, - ); - - // Load the first image in the stack - cornerstone.loadAndCacheImage(this.state.imageId).then((image) => { - try { - cornerstone.getEnabledElement(element); - } catch (error) { - // Handle cases where the user ends the session before the image is displayed. - console.error(error); - return; - } - - // Set Soft Tissue preset for all images by default - const viewport = cornerstone.getDefaultViewportForImage(element, image); - viewport.voi = { - windowWidth: 400, - windowCenter: 40, - }; - - // Display the first image - cornerstone.displayImage(element, image, viewport); - - // Clear any previous tool state - cornerstoneTools.clearToolState(this.element, 'stack'); - - // Disable stack prefetch in case there are still queued requests - cornerstoneTools.stackPrefetch.disable(this.element); - - // Add the stack tool state to the enabled element - const stack = this.state.stack; - cornerstoneTools.addStackStateManager(element, ['stack']); - cornerstoneTools.addToolState(element, 'stack', stack); - cornerstoneTools.stackPrefetch.enable(this.element); - - const tools = [{ - name: 'Bidirectional', - configuration: { - getMeasurementLocationCallback: this - .bidirectionalToolLabellingCallback, - shadow: true, - drawHandlesOnHover: true, - }, - }, - { - name: 'Wwwc', - }, - { - name: 'Zoom', - configuration: { - minScale: 0.3, - maxScale: 25, - preventZoomOutsideImage: true, - }, - }, - { - name: 'Pan', - }, - { - name: 'StackScroll', - }, - { - name: 'PanMultiTouch', - }, - { - name: 'ZoomTouchPinch', - }, - { - name: 'StackScrollMouseWheel', - }, - { - name: 'StackScrollMultiTouch', - }, - ]; - - initializeTools(tools); - - this.setActiveTool(this.props.activeTool); - - /* For touch devices, by default we activate: - - Pinch to zoom - - Two-finger Pan - - Three (or more) finger Stack Scroll - */ - cornerstoneTools.setToolActive('PanMultiTouch', { - mouseButtonMask: 0, - isTouchActive: true, - }); - cornerstoneTools.setToolActive('ZoomTouchPinch', { - mouseButtonMask: 0, - isTouchActive: true, - }); - - cornerstoneTools.setToolActive('StackScrollMultiTouch', { - mouseButtonMask: 0, - isTouchActive: true, - }); - - cornerstoneTools.stackPrefetch.setConfiguration({ - maxImagesToPrefetch: Infinity, - preserveExistingPool: false, - maxSimultaneousRequests: 6, - }); - - /* For mouse devices, by default we turn on: - - Stack scrolling by mouse wheel - - Stack scrolling by keyboard up / down arrow keys - - Pan with middle click - - Zoom with right click - */ - - cornerstoneTools.setToolActive('StackScrollMouseWheel', { - mouseButtonMask: 0, - isTouchActive: true, - }); - - element.addEventListener( - cornerstone.EVENTS.IMAGE_RENDERED, - this.onImageRendered, - ); - - element.addEventListener(cornerstone.EVENTS.NEW_IMAGE, this.onNewImage); - - element.addEventListener( - cornerstoneTools.EVENTS.STACK_SCROLL, - this.onStackScroll, - ); - - element.addEventListener( - cornerstoneTools.EVENTS.MEASUREMENT_ADDED, - this.onMeasurementAddedOrRemoved, - ); - - element.addEventListener( - cornerstoneTools.EVENTS.MEASUREMENT_REMOVED, - this.onMeasurementAddedOrRemoved, - ); - - element.addEventListener( - cornerstoneTools.EVENTS.MOUSE_CLICK, - this.onMouseClick, - ); - - element.addEventListener( - cornerstoneTools.EVENTS.TOUCH_PRESS, - this.onTouchPress, - ); - - element.addEventListener( - cornerstoneTools.EVENTS.TOUCH_START, - this.onTouchStart, - ); - - window.addEventListener(EVENT_RESIZE, this.onWindowResize); - - this.setState({ - viewportHeight: `${this.element.clientHeight - 20}px`, - }); - }); -} - -componentWillUnmount() { - const element = this.element; - element.removeEventListener( - cornerstone.EVENTS.IMAGE_RENDERED, - this.onImageRendered, - ); - - element.removeEventListener(cornerstone.EVENTS.NEW_IMAGE, this.onNewImage); - - element.removeEventListener( - cornerstoneTools.EVENTS.STACK_SCROLL, - this.onStackScroll, - ); - - element.removeEventListener( - cornerstoneTools.EVENTS.MEASUREMENT_ADDED, - this.onMeasurementAddedOrRemoved, - ); - - element.removeEventListener( - cornerstoneTools.EVENTS.MEASUREMENT_REMOVED, - this.onMeasurementAddedOrRemoved, - ); - - element.removeEventListener( - cornerstoneTools.EVENTS.MOUSE_CLICK, - this.onMouseClick, - ); - - element.removeEventListener( - cornerstoneTools.EVENTS.TOUCH_PRESS, - this.onTouchPress, - ); - - element.removeEventListener( - cornerstoneTools.EVENTS.TOUCH_START, - this.onTouchStart, - ); - - window.removeEventListener(EVENT_RESIZE, this.onWindowResize); - - cornerstone.disable(element); - - cornerstone.events.removeEventListener( - cornerstone.EVENTS.IMAGE_LOADED, - this.onImageLoaded, - ); -} - -componentDidUpdate(prevProps) { - // TODO: Add a real object shallow comparison here? - if ( - this.state.displaySetInstanceUid !== this.props.viewportData.displaySetInstanceUid - ) { - const { - displaySetInstanceUid, - studyInstanceUid, - currentImageIdIndex, - } = this.props.viewportData; - - // Create shortcut to displaySet - const study = OHIF.viewer.Studies.findBy({ - studyInstanceUid, - }); - - const displaySet = study.displaySets.find((set) => { - return set.displaySetInstanceUid === displaySetInstanceUid; - }); - - // Get stack from Stack Manager - const stack = StackManager.findOrCreateStack(study, displaySet); - const stackData = cornerstoneTools.getToolState(this.element, 'stack'); - let currentStack = stackData && stackData.data[0]; - - if (!currentStack) { - currentStack = { - currentImageIdIndex, - imageIds: stack.imageIds, - }; - - cornerstoneTools.addStackStateManager(this.element, ['stack']); - cornerstoneTools.addToolState(this.element, 'stack', currentStack); - } else { - // TODO: we should make something like setToolState by an ID - currentStack.currentImageIdIndex = currentImageIdIndex; - currentStack.imageIds = stack.imageIds; - } - - const imageId = currentStack.imageIds[currentImageIdIndex]; - - this.setState({ - displaySetInstanceUid, - studyInstanceUid, - stack, - imageId, - }); - - cornerstoneTools.stackPrefetch.disable(this.element); - cornerstone.loadAndCacheImage(imageId).then((image) => { - try { - cornerstone.getEnabledElement(this.element); - } catch (error) { - // Handle cases where the user ends the session before the image is displayed. - console.error(error); - return; - } - - const viewport = cornerstone.getDefaultViewportForImage(this.element, image); - - // Workaround for Cornerstone issue #304 - viewport.displayedArea.brhc = { - x: image.width, - y: image.height, - }; - - cornerstone.displayImage(this.element, image, viewport); - - cornerstoneTools.stackPrefetch.enable(this.element); - }); - } - - if (this.props.activeTool !== prevProps.activeTool) { - this.setActiveTool(this.props.activeTool); - - // TODO: Why do we need to do this in v3? - cornerstoneTools.setToolActive('StackScrollMouseWheel', { - mouseButtonMask: 0, - isTouchActive: true, - }); - } - - // TODO: Check this, causes infinite loop - // this.debouncedResize(); -} - -setActiveTool = (activeTool) => { - const leftMouseTools = ['Bidirectional', 'Wwwc', 'StackScroll']; - - setToolsPassive(leftMouseTools); - - // pan is the default tool for middle mouse button - const isPanToolActive = activeTool === 'Pan'; - const panOptions = { - mouseButtonMask: isPanToolActive ? [1, 4] : [4], - isTouchActive: isPanToolActive, - }; - cornerstoneTools.setToolActive('Pan', panOptions); - - // zoom is the default tool for right mouse button - const isZoomToolActive = activeTool === 'Zoom'; - const zoomOptions = { - mouseButtonMask: isZoomToolActive ? [1, 2] : [2], - isTouchActive: isZoomToolActive, - }; - cornerstoneTools.setToolActive('Zoom', zoomOptions); - - cornerstoneTools.setToolActive(activeTool, { - mouseButtonMask: 1, - isTouchActive: true, - }); -}; - -onStackScroll(event) { - this.setViewportActive(); - - const element = event.currentTarget; - const stackData = cornerstoneTools.getToolState(element, 'stack'); - const stack = stackData.data[0]; - - this.hideExtraButtons(); - - this.setState({ - stack, - imageScrollbarValue: stack.currentImageIdIndex, - }); -} - -onImageLoaded() { - this.setState({ - numImagesLoaded: this.state.numImagesLoaded + 1, - }); -} - -startLoadingHandler() { - // console.log('startLoadingHandler'); - clearTimeout(this.loadHandlerTimeout); - this.loadHandlerTimeout = setTimeout(() => { - this.setState({ - isLoading: true, - }); - }, loadIndicatorDelay); -} - -doneLoadingHandler() { - clearTimeout(this.loadHandlerTimeout); - this.setState({ - isLoading: false, - }); -} - -onMeasurementAddedOrRemoved() { - console.log('onMeasurementAddedOrRemoved'); - /* const { toolType, measurementData } = event.detail; - - // TODO: Pass in as prop? - const toolsOfInterest = ['Bidirectional']; - - this.hideExtraButtons(); - - if (toolsOfInterest.includes(toolType)) { - const image = cornerstone.getImage(this.element); - const viewport = cornerstone.getViewport(this.element); - - const type = { - cornerstonetoolsmeasurementadded: 'added', - cornerstonetoolsmeasurementremoved: 'removed' - }; - const action = type[event.type]; - - if (action === 'added') { - measurementData._id = guid(); - measurementData.viewport = cloneDeep(viewport); - } - - this.props.measurementsAddedOrRemoved( - action, - image.imageId, - toolType, - measurementData - ); - }*/ -} - -setViewportActive() { - const { - viewportIndex, - } = this.props.viewportData; - const activeViewportIndex = window.store.getState().viewports.activeViewport; - if (viewportIndex !== activeViewportIndex) { - window.store.dispatch({ - type: 'SET_VIEWPORT_ACTIVE', - viewportIndex, - }); - } -} - -onMouseClick(event) { - this.setViewportActive(); - - if (event.detail.event.which === 3) { - this.setState({ - toolContextMenuData: { - eventData: event.detail, - isTouchEvent: false, - }, - }); - } -} - -onTouchPress(event) { - this.setViewportActive(); - - this.setState({ - toolContextMenuData: { - eventData: event.detail, - isTouchEvent: true, - }, - }); -} - -onTouchStart() { - this.setViewportActive(); -} - -onCloseToolContextMenu() { - this.setState({ - toolContextMenuData: null, - }); -} - -imageSliderOnInputCallback(value) { - this.setViewportActive(); - - this.setState({ - imageScrollbarValue: value, - }); - - // Note that we throttle requests to prevent the - // user's ultrafast scrolling from firing requests too quickly. - // clearTimeout(this.slideTimeout); - // this.slideTimeout = setTimeout(() => { - scrollToIndex(this.element, value); - // }, this.slideTimeoutTime); -} - -hideExtraButtons = () => { - if (this.state.bidirectionalAddLabelShow === true) { - this.setState({ - bidirectionalAddLabelShow: false, - }); - } - this.setState({ - toolContextMenuData: null, - }); -}; -} - -CornerstoneViewport.propTypes = { - measurementsAddedOrRemoved: PropTypes.func, - measurementsChanged: PropTypes.func, - activeTool: PropTypes.string, - viewportData: PropTypes.object.isRequired, -}; - -export default CornerstoneViewport; diff --git a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/CornerstoneViewport.styl b/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/CornerstoneViewport.styl deleted file mode 100644 index d42dd76cf..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/CornerstoneViewport.styl +++ /dev/null @@ -1,42 +0,0 @@ -@import "{ohif:design}/app" - -.CornerstoneViewport - width: 100% - height: 100% - -.viewport-element - width: 100% - height: 100% - position: relative; - background-color: black - - // Prevent the blue outline in Chrome when a viewport is selected - outline: 0 !important - - // Prevents the entire page from getting larger - // when the magnify tool is near the sides/corners of the page - overflow: hidden - -.viewportInstructions - display: block - font-size: 13px - theme('color', '$textSecondaryColor') - line-height: 18px - pointer-events: none // Necessary for drag/drop through to cornerstone element below - text-align: center - position: absolute - top: 0 - bottom: 0 - right: 0 - left: 0 - margin: auto - height: 20px - -/* These are some good CSS settings for a circular magnifying glass - Try removing the border-radius to make a square magnifying glass */ -.magnifyTool - border: 4px white solid - box-shadow: 2px 2px 10px #1e1e1e - border-radius: 50% - display: none - cursor: none diff --git a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/imageViewerViewport.html b/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/imageViewerViewport.html deleted file mode 100644 index 410a36fd4..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/imageViewerViewport.html +++ /dev/null @@ -1,13 +0,0 @@ - diff --git a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/imageViewerViewport.js b/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/imageViewerViewport.js deleted file mode 100644 index 49933421e..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/CornerstoneViewport/imageViewerViewport.js +++ /dev/null @@ -1,697 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { Template } from 'meteor/templating'; -import { Tracker } from 'meteor/tracker'; -import { Session } from 'meteor/session'; -import { $ } from 'meteor/jquery'; -// OHIF Modules -import { OHIF } from 'meteor/ohif:core'; -import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone'; -// Local Modules -import { StackManager } from '../../../lib/StackManager'; -import { setActiveViewport } from '../../../lib/setActiveViewport'; -import { imageViewerViewportData } from '../../../lib/imageViewerViewportData'; -import { updateCrosshairsSynchronizer } from '../../../lib/updateCrosshairsSynchronizer'; -import { toolManager } from '../../../lib/toolManager'; -import { updateOrientationMarkers } from '../../../lib/updateOrientationMarkers'; -import { getInstanceClassDefaultViewport } from '../../../lib/instanceClassSpecificViewport'; -import { OHIFError } from '../../../lib/classes/OHIFError'; - -const allCornerstoneEvents = ['click', 'cornerstonetoolsmousedown', 'cornerstonetoolsmousedownactivate', - 'cornerstonetoolsmouseclick', 'cornerstonetoolsmousedrag', 'cornerstonetoolsmouseup', - 'cornerstonetoolsmousewheel', 'cornerstonetoolsdoubletap', 'cornerstonetoolstouchpress', - 'cornerstonetoolsmultitouchstart', 'cornerstonetoolsmultitouchstartactive', 'cornerstonetoolsmultitouchdrag']; - -const PLUGIN_CORNERSTONE = 'cornerstone'; - -// Create a way to add hooks to be executed every time a cornerstone element is enabled -OHIF.viewer.cornerstoneElementHooks = []; - -/** - * This function loads a study series into a viewport element. - * - * @param data {object} Object containing the study, series, and viewport element to be used - */ -const loadDisplaySetIntoViewport = (data, templateData) => { - const wlPresets = OHIF.viewerbase.wlPresets; - - OHIF.log.info('imageViewerViewport loadDisplaySetIntoViewport'); - - // Make sure we have all the data required to render the series - if (!data.study || !data.displaySet || !data.element) { - OHIF.log.warn('loadDisplaySetIntoViewport: No Study, Display Set, or Element provided'); - return; - } - - // Get the current element and it's index in the list of all viewports - // The viewport index is often used to store information about a viewport element - const element = data.element; - const viewportIndex = templateData.viewportIndex; - - const layoutManager = OHIF.viewerbase.layoutManager; - layoutManager.viewportData = layoutManager.viewportData || {}; - layoutManager.viewportData[viewportIndex] = layoutManager.viewportData[viewportIndex] || {}; - layoutManager.viewportData[viewportIndex].viewportIndex = viewportIndex; - - // Stop here if no data was defined for the viewer - if (!OHIF.viewer.data) return; - - // This data will be saved so that the viewport can be reloaded to the same state later - OHIF.viewer.data.loadedSeriesData[viewportIndex] = {}; - - // Create shortcut to displaySet - const displaySet = data.displaySet; - - // Get stack from Stack Manager - let stack = StackManager.findOrCreateStack(data.study, displaySet); - - // If is a clip, updates the global FPS for cine dialog - if (stack.isClip && stack.frameRate > 0) { - // Sets the global variable - OHIF.viewer.cine.framesPerSecond = parseFloat(stack.frameRate); - // Update the cine dialog FPS - Session.set('UpdateCINE', Math.random()); - } - - // Shortcut for array with image IDs - const imageIds = stack.imageIds; - - // Define the current image stack using the newly created image IDs - stack = { - currentImageIdIndex: data.currentImageIdIndex > 0 && data.currentImageIdIndex < imageIds.length ? data.currentImageIdIndex : 0, - imageIds: imageIds, - displaySetInstanceUid: data.displaySetInstanceUid - }; - - // Get the current image ID for the stack that will be rendered - const imageId = imageIds[stack.currentImageIdIndex]; - - // Save the current image ID inside the template data so it can be - // retrieved from the template helpers - templateData.imageId = imageId; - - // Save the current image ID inside the ViewportLoading object. - // - // The ViewportLoading object relates the viewport elements with whichever - // image is currently being loaded into them. This is useful so that we can - // place progress (download %) for each image inside the proper viewports. - window.ViewportLoading[viewportIndex] = imageId; - - // Enable Cornerstone for the viewport element - const options = { - renderer: OHIF.cornerstone.renderer - }; - cornerstone.enable(element, options); - - // Call every defined hook - OHIF.viewer.cornerstoneElementHooks.forEach(hook => { - if (typeof hook === 'function') { - hook(element); - } - }); - - // Get the handler functions that will run when loading has finished or thrown - // an error. These are used to show/hide loading / error text boxes on each viewport. - const endLoadingHandler = cornerstoneTools.loadHandlerManager.getEndLoadHandler(); - const errorLoadingHandler = cornerstoneTools.loadHandlerManager.getErrorLoadingHandler(); - - // Get the current viewport settings - const viewport = cornerstone.getViewport(element); - - const { studyInstanceUid, seriesInstanceUid, displaySetInstanceUid, currentImageIdIndex } = data; - - // Store the current series data inside the Layout Manager - layoutManager.viewportData[viewportIndex] = { - imageId, - studyInstanceUid, - seriesInstanceUid, - displaySetInstanceUid, - currentImageIdIndex, - viewport: viewport || data.viewport, - viewportIndex, - plugin: PLUGIN_CORNERSTONE - }; - - // Handle the case where the imageId isn't loaded correctly and the - // imagePromise returns undefined - // To test, uncomment the next line - // data.imageId = 'AfileThatDoesntWork'; // For testing only! - - let imagePromise; - try { - imagePromise = cornerstone.loadAndCacheImage(imageId); - } catch (error) { - OHIF.log.info(error); - if (!imagePromise) { - errorLoadingHandler(element, imageId, error); - return; - } - } - - // Additional tasks for metadata provider. If using your own - // metadata provider, this may not be necessary. - // updateMetadata is important, though, to update image metadata that - // for any reason was missing some information such as rows, columns, - // sliceThickness, etc (See MetadataProvider class from ohif-cornerstone package) - const metadataProvider = OHIF.viewer.metadataProvider; - const isUpdateMetadataDefined = metadataProvider && typeof metadataProvider.updateMetadata === 'function'; - - // loadAndCacheImage configurable callbacks - const callbacks = imageViewerViewportData.callbacks; - - // Check if it has before loadAndCacheImage callback - if (typeof callbacks.before === 'function') { - OHIF.log.info('imageViewerViewport before loadAndCacheImage callback'); - callbacks.before(imagePromise, templateData); - } - - // Start loading the image. - imagePromise.then(image => { - let enabledElement; - try { - enabledElement = cornerstone.getEnabledElement(element); - } - catch (error) { - OHIF.log.warn('Viewport destroyed before loaded image could be displayed'); - return; - } - - // Caches element's jQuery object - const $element = $(element); - - // Update the enabled element with the image and viewport data - // This is not usually necessary, but we need them stored in case - // a sopClassUid-specific viewport setting is present. - enabledElement.image = image; - enabledElement.viewport = cornerstone.getDefaultViewport(enabledElement.canvas, image); - - if (isUpdateMetadataDefined) { - // Update the metaData for missing fields - metadataProvider.updateMetadata(image); - } - - // Check if there are default viewport settings for this sopClassUid - if (!displaySet.images || !displaySet.images.length) { - return; - } - - const instance = displaySet.images[0]; - const instanceClassViewport = getInstanceClassDefaultViewport(instance, enabledElement, image.imageId); - - // If there are sopClassUid-specific viewport settings, apply them - if (instanceClassViewport) { - cornerstone.displayImage(element, image, instanceClassViewport); - - // Mark that this element should not be fit to the window in the resize listeners - // TODO: Find another way to do this? - enabledElement.fitToWindow = false; - - // Resize the canvas to fit the current viewport element size. - cornerstone.resize(element, false); - } else if (data.viewport) { - // If there is a saved object containing Cornerstone viewport data - // (e.g. scale, invert, window settings) in the input data, apply it now. - cornerstone.displayImage(element, image, data.viewport); - - // Resize the canvas to fit the current viewport element size. Fit the displayed - // image to the canvas dimensions. - cornerstone.resize(element, true); - } else { - // If no saved viewport settings or modality-specific settings exists, - // display the loaded image in the viewport element with no loaded viewport - // settings. - cornerstone.displayImage(element, image); - - // Resize the canvas to fit the current viewport element size. Fit the displayed - // image to the canvas dimensions. - cornerstone.resize(element, true); - } - - // Set/store W/L preset data to Default on first display - wlPresets.updateElementWLPresetData(element); - - // Remove the data for this viewport from the ViewportLoading object - // This will stop the loading percentage complete from being displayed. - delete window.ViewportLoading[viewportIndex]; - - // Call the handler function that represents the end of the image loading phase - // (e.g. hide the progress text box) - endLoadingHandler(element, image); - - // Remove the 'empty' class from the viewport to hide any instruction text - element.classList.remove('empty'); - - // Hide the viewport instructions (i.e. 'Drag a stack here') and show - // the viewport overlay data. - $element.siblings('.viewportInstructions').hide(); - $element.siblings('.imageViewerViewportOverlay').show(); - - // Add stack state managers for the stack tool, CINE tool, and reference lines - cornerstoneTools.addStackStateManager(element, ['stack', 'playClip', 'referenceLines']); - - // Enable orientation markers, if applicable - updateOrientationMarkers(element); - - // Clear any old stack data - cornerstoneTools.clearToolState(element, 'stack'); - cornerstoneTools.addToolState(element, 'stack', stack); - - // Set the default CINE settings - const multiframeMetadata = instance.getDataProperty('multiframeMetadata'); - - let fps; - if (multiframeMetadata && multiframeMetadata.averageFrameRate > 0) { - fps = multiframeMetadata.averageFrameRate; - } else { - fps = OHIF.viewer.cine.framesPerSecond; - } - - const cineToolData = { - loop: OHIF.viewer.cine.loop, - framesPerSecond: fps - }; - - cornerstoneTools.addToolState(element, 'playClip', cineToolData); - - // Autoplay datasets that have framerates set - if (multiframeMetadata && multiframeMetadata.isMultiframeImage && multiframeMetadata.averageFrameRate > 0) { - cornerstoneTools.playClip(element); - } - - // Instantiate the tools - toolManager.instantiateTools(element); - - // Use the tool manager to enable the currently active tool for this - // newly rendered element - toolManager.setActiveTool(); - - // Define a function to run whenever the Cornerstone viewport is rendered - // (e.g. following a change of window or zoom) - const onImageRendered = (event) => { - const eventData = event.detail; - const { viewport, element } = eventData; - - // Attention: Adding OHIF.log.info in this function may decrease the performance - // since this callback function is called multiple times (eg: when a tool is - // enabled/disabled -> cornerstone[toolName].tool.enable) - - if (!layoutManager.viewportData[viewportIndex]) { - OHIF.log.warn(`onImageRendered: LayoutManager has no viewport data for this viewport index?: ${viewportIndex}`); - } - - // Use Session to trigger reactive updates in the viewportOverlay helper functions - // This lets the viewport overlay always display correct window / zoom values - Session.set('CornerstoneImageRendered' + viewportIndex, Math.random()); - - // Save the current viewport into the OHIF.viewer.data global variable - layoutManager.viewportData[viewportIndex].viewport = viewport; - OHIF.viewer.data.loadedSeriesData[viewportIndex].viewport = viewport; - - // Update the W/L Preset data, if necessary - wlPresets.updateElementWLPresetData(element); - - // Check if it has onImageRendered loadAndCacheImage callback - if (typeof callbacks.onImageRendered === 'function') { - callbacks.onImageRendered(event, eventData, viewportIndex, templateData); - } - }; - - // Attach the onImageRendered callback to the CornerstoneImageRendered event - element.removeEventListener('cornerstoneimagerendered', onImageRendered); - element.addEventListener('cornerstoneimagerendered', onImageRendered); - - // Set a random value for the Session variable in order to trigger an overlay update - Session.set('CornerstoneImageRendered' + viewportIndex, Math.random()); - - // Define a function to run whenever the Cornerstone viewport changes images - // (e.g. during scrolling) - const onNewImage = (event) => { - const eventData = event.detail; - - // Attention: Adding OHIF.log.info in this function may decrease the performance - // since this callback function is called multiple times (eg: when a tool is - // enabled/disabled -> cornerstone[toolName].tool.enable) - - if (isUpdateMetadataDefined) { - // Update the metaData for missing fields - metadataProvider.updateMetadata(eventData.enabledElement.image); - } - - // Update the templateData with the new imageId - // This allows the template helpers to update reactively - templateData.imageId = eventData.enabledElement.image.imageId; - Session.set('CornerstoneNewImage' + viewportIndex, Math.random()); - layoutManager.viewportData[viewportIndex].imageId = eventData.enabledElement.image.imageId; - - // Get the element and stack data - const element = event.target; - const toolData = cornerstoneTools.getToolState(element, 'stack'); - if (!toolData || !toolData.data || !toolData.data.length) { - return; - } - - // Update orientation markers in case new slices don't have the same orientation - // as the first slice - updateOrientationMarkers(element); - - // If this viewport is displaying a stack of images, save the current image - // index in the stack to the global OHIF.viewer.data object. - const stack = cornerstoneTools.getToolState(element, 'stack'); - if (stack && stack.data.length && stack.data[0].imageIds.length > 1) { - const imageIdIndex = stack.data[0].imageIds.indexOf(templateData.imageId); - layoutManager.viewportData[viewportIndex].currentImageIdIndex = imageIdIndex; - OHIF.viewer.data.loadedSeriesData[viewportIndex].currentImageIdIndex = imageIdIndex; - } - - const wlPresetData = cornerstone.getElementData(element, 'wlPreset'); - const wlPresetDataName = wlPresetData && wlPresetData.name; - wlPresets.applyWLPreset(wlPresetDataName, element); - - // Check if it has onNewImage loadAndCacheImage callback - if (typeof callbacks.onNewImage === 'function') { - callbacks.onNewImage(event, eventData, viewportIndex, templateData); - } - }; - - // Attach the onNewImage callback to the CornerstoneNewImage event - element.removeEventListener('cornerstonenewimage', onNewImage); - element.addEventListener('cornerstonenewimage', onNewImage); - - // Set a random value for the Session variable in order to trigger an overlay update - Session.set('CornerstoneNewImage' + viewportIndex, Math.random()); - - const onStackScroll = () => { - // Attention: Adding OHIF.log.info in this function may decrease the performance - // since this callback function is called multiple times (eg: when a tool is - // enabled/disabled -> cornerstone[toolName].tool.enable) - - // Update the imageSlider value - Session.set('CornerstoneNewImage' + viewportIndex, Math.random()); - }; - - element.removeEventListener('cornerstonestackscroll', onStackScroll); - if (stack.imageIds.length > 1) { - element.addEventListener('cornerstonestackscroll', onStackScroll); - } - - // Define a function to trigger an event whenever a new viewport is being used - // This is used to update the value of the "active viewport", when the user interacts - // with a new viewport element - const sendActivationTrigger = (event) => { - const eventData = event && event.detail; - // Attention: Adding OHIF.log.info in this function decrease the performance - // since this callback function is called multiple times (eg: when a tool is - // enabled/disabled -> cornerstone[toolName].tool.enable) - - // Reset the focus, even if we don't need to re-enable reference lines or prefetching - const element = (eventData && eventData.element) || (event && event.currentTarget); - if (!element) return; - const $element = $(element); - - // Stop here if we don't have eventData set - if (!eventData) return; - - // Check if the current active viewport in the Meteor Session - // Is the same as the viewport in which the activation event was fired. - // If it was, no changes are necessary, so stop here. - const activeViewportIndex = window.store.getState().viewports.activeViewport; - if (viewportIndex === activeViewportIndex) return; - - $element.focus(); - - OHIF.log.info('imageViewerViewport sendActivationTrigger'); - - // Otherwise, trigger an 'OHIFActivateViewport' event to be handled by the Template event - // handler - eventData.viewportIndex = viewportIndex; - const customEvent = $.Event('OHIFActivateViewport', eventData); - - // Need to overwrite the type set in the original event - customEvent.type = 'OHIFActivateViewport'; - $element.trigger(customEvent, eventData); - }; - - // Handle mouseenter event to send viewport activation trigger only if there is no focused dropdown - const onMouseEnter = () => { - if ($(':focus').closest('.dropdown').length) return; - - sendActivationTrigger(); - }; - - // Attach the sendActivationTrigger function to all of the Cornerstone interaction events - allCornerstoneEvents.forEach(eventType => { - element.removeEventListener(eventType, sendActivationTrigger); - element.addEventListener(eventType, sendActivationTrigger); - }); - $element.off('mouseenter', onMouseEnter); - $element.on('mouseenter', onMouseEnter); - - OHIF.viewer.data.loadedSeriesData = layoutManager.viewportData; - - // Check if image plane (orientation / location) data is present for the current image - const imagePlane = cornerstone.metaData.get('imagePlane', image.imageId); - if (imagePlane && imagePlane.frameOfReferenceUID) { - // If it is, add this element to the global synchronizer... - OHIF.viewer.updateImageSynchronizer.add(element); - - if (OHIF.viewer.refLinesEnabled) { - // ... and if reference lines are globally enabled, let cornerstoneTools know. - cornerstoneTools.setToolEnabledForElement(element, 'referenceLines', { - synchronizationContext: OHIF.viewer.updateImageSynchronizer - }); - } - - // If the crosshairs tool is active, update the synchronizer - // that is used for its synchronized viewport updating. - // This is necessary if this new image shares a frame of reference - // with currently displayed images - const activeTool = toolManager.getActiveTool(); - if (activeTool === 'crosshairs') { - updateCrosshairsSynchronizer(imagePlane.frameOfReferenceUID); - } - } - - // Set the active viewport based on the Session variable - // This is done to ensure that the active element has the current - // focus, so that keyboard events are triggered. - if (viewportIndex === window.store.getState().viewports.activeViewport) { - const viewportContainer = $element.parents('.viewportContainer'); - - setActiveViewport(viewportContainer); - } - - // Run any renderedCallback that exists in the data context - if (data.renderedCallback && typeof data.renderedCallback === 'function') { - data.renderedCallback(element); - } - - // Check if it has after loadAndCacheImage callback - if (typeof callbacks.after === 'function') { - OHIF.log.info('imageViewerViewport after callback'); - callbacks.after(image, templateData, element); - } - }, error => { - // If something goes wrong while loading the image, fire the error handler. - errorLoadingHandler(element, imageId, error); - }); -}; - -/** - * This function sets the display set for the study and calls LoadDisplaySetIntoViewport function - * - * @param data includes study data - * @param displaySetInstanceUid Display set information which is loaded in Template - * @param templateData currentData of Template - * - */ -const setDisplaySet = (data, displaySetInstanceUid, templateData) => { - const study = data.study; - - if (!study) { - throw new OHIFError('Study does not exist'); - } - - let displaySets = study.displaySets; - if (!displaySets.length) { - displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(study); - study.displaySets = displaySets; - study.setDisplaySets(displaySets); - - study.forEachDisplaySet(displaySet => { - OHIF.viewerbase.stackManager.makeAndAddStack(study, displaySet); - }); - } - - if (!displaySets) { - throw new OHIFError('Study has no display sets'); - } - - displaySets.every(displaySet => { - if (displaySet.displaySetInstanceUid === displaySetInstanceUid) { - data.displaySet = displaySet; - return false; - } - - return true; - }); - - // If we didn't find anything, stop here - if (!data.displaySet) { - data.displaySet = displaySets[0]; - // throw new OHIFError('Display set not found in specified study!'); - } - - // Otherwise, load pass the data object into loadSeriesIntoViewport - loadDisplaySetIntoViewport(data, templateData); -}; - -Meteor.startup(() => { - window.ViewportLoading = window.ViewportLoading || {}; - toolManager.configureLoadProcess(); -}); - -Template.imageViewerViewport.onRendered(function() { - const templateData = Template.currentData(); - OHIF.log.info('imageViewerViewport onRendered'); - - // When the imageViewerViewport template is rendered - const element = this.find('.imageViewerViewport'); - this.element = element; - this.$element = $(element); - - // Display the loading indicator for this element - this.$element.siblings('.imageViewerLoadingIndicator').css('display', 'block'); - - // Get the current active viewport index, if this viewport has the same index, - // add the CSS 'active' class to highlight this viewport. - const activeViewport = window.store.getState().viewports.activeViewport; - - // Focus the viewport if it's the active one - if (templateData.viewportIndex === activeViewport) { - this.$element.focus(); - } - - let { currentImageIdIndex } = templateData; - const { viewport, studyInstanceUid, seriesInstanceUid, renderedCallback, displaySetInstanceUid } = templateData; - - if (!currentImageIdIndex) { - currentImageIdIndex = 0; - } - - // Calls extendData function to provide flexibility between systems - imageViewerViewportData.extendData(templateData); - - // Create a data object to pass to the series loading function (loadSeriesIntoViewport) - const data = { - element, - viewport, - currentImageIdIndex, - displaySetInstanceUid, - studyInstanceUid, - seriesInstanceUid, - renderedCallback, - activeViewport - }; - - // If no displaySetInstanceUid was supplied, display the drag/drop - // instructions and then stop here since we don't know what to display in the viewport. - if (!displaySetInstanceUid) { - element.classList.add('empty'); - this.$element.siblings('.imageViewerLoadingIndicator').css('display', 'none'); - this.$element.siblings('.viewportInstructions').show(); - return; - } - - // @TypeSafeStudies - const study = OHIF.viewer.Studies.findBy({ studyInstanceUid }); - - data.study = study; - setDisplaySet(data, displaySetInstanceUid, templateData); - - // Double click event handlers to handle viewport enlargement - function doubleClickHandler (event) { - const $element = $(this); - const { layoutManager } = OHIF.viewerbase; - const $viewports = $('.imageViewerViewport'); - - $element.trigger('ohif.viewer.viewport.toggleEnlargement'); - - // Get the double clicked viewport index - const viewportIndex = $viewports.index(event.currentTarget); - - // Stop here if there's only one viewport - if (!layoutManager.isZoomed && $viewports.length <= 1) return; - - // Enlarge the double clicked viewport - layoutManager.toggleEnlargement(viewportIndex); - - // Wait for DOM re-rendering and update the active viewport - Tracker.afterFlush(() => { - let viewportIndexToZoom; - // Check if the viewer is zoomed - if (layoutManager.isZoomed) { - // Set the active viewport as the only one visible - viewportIndexToZoom = 0; - } else { - // Set the active viewport as the previous zoomed viewport - viewportIndexToZoom = layoutManager.zoomedViewportIndex || 0; - } - // Set zoomed viewport as active... - const viewportContainer = $('.viewportContainer').get(viewportIndexToZoom); - setActiveViewport(viewportContainer); - }); - } - - const doubleClickEvents = ['cornerstonetoolsmousedoubleclick', 'cornerstonetoolsdoubletap']; - doubleClickEvents.forEach(eventType => { - element.removeEventListener(eventType, doubleClickHandler); - element.addEventListener(eventType, doubleClickHandler); - }); -}); - -Template.imageViewerViewport.onDestroyed(function() { - OHIF.log.info('imageViewerViewport onDestroyed'); - - // When a viewport element is being destroyed - const element = this.find('.imageViewerViewport'); - const $element = $(element); - if (!element || $element.hasClass('empty') || !$element.find('canvas').length) { - return; - } - - // Remove all tools for the destroyed element - toolManager.removeToolsForElement(element); - - OHIF.viewer.updateImageSynchronizer.remove(element); - - // Clear the stack prefetch data - cornerstoneTools.clearToolState(element, 'stackPrefetch'); - - // Try to stop any currently playing clips - // Otherwise the interval will continuously throw errors - try { - const enabledElement = cornerstone.getEnabledElement(element); - if (enabledElement) { - cornerstoneTools.stopClip(element); - } - } catch (error) { - OHIF.log.warn(error); - } - - // Trigger custom Destroy Viewport event - // for compatibility with other systems - $element.trigger('OHIFDestroyedViewport'); - - // Disable the viewport element with Cornerstone - // This also triggers the removal of the element from all available - // synchronizers, such as the one used for reference lines. - cornerstone.disable(element); -}); - -Template.imageViewerViewport.events({ - 'OHIFActivateViewport .imageViewerViewport'(event) { - OHIF.log.info('imageViewerViewport OHIFActivateViewport'); - - const viewportContainer = $(event.currentTarget).parents('.viewportContainer').get(0); - setActiveViewport(viewportContainer); - } -}); diff --git a/Packages/ohif-viewerbase/client/components/viewer/GridLayout/GridLayout.js b/Packages/ohif-viewerbase/client/components/viewer/GridLayout/GridLayout.js index 93e3700c1..755bc173e 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/GridLayout/GridLayout.js +++ b/Packages/ohif-viewerbase/client/components/viewer/GridLayout/GridLayout.js @@ -2,13 +2,37 @@ import { Component } from 'react'; import React from 'react'; import PropTypes from 'prop-types'; import { OHIF } from 'meteor/ohif:core'; -import CornerstoneViewport from '../CornerstoneViewport/CornerstoneViewport.js'; +import CornerstoneViewport from 'react-cornerstone-viewport'; import './GridLayout.styl'; +import StackManager from '../../../lib/StackManager.js'; +import { cornerstone, cornerstoneTools } from 'meteor/ohif:cornerstone'; const TOP_CLASS = 'top'; const BOTTOM_CLASS = 'bottom'; const MIDDLE_CLASS = 'middle'; +function getCornerstoneStack(viewportData) { + const { + displaySetInstanceUid, + studyInstanceUid, + } = viewportData; + + // Create shortcut to displaySet + const study = OHIF.viewer.Studies.findBy({ + studyInstanceUid, + }); + + const displaySet = study.displaySets.find((set) => { + return set.displaySetInstanceUid === displaySetInstanceUid; + }); + + // Get stack from Stack Manager + const stack = StackManager.findOrCreateStack(study, displaySet); + stack.currentImageIdIndex = 0; + + return stack; +} + class GridLayout extends Component { constructor(props) { super(props); @@ -76,7 +100,7 @@ class GridLayout extends Component { const viewports = viewportData.map((data, index) => { const className = `viewportContainer ${this.getClass(index)} ${this.getActiveClass(index)}`; - + // TODO[react]: Not sure why I needed to do this. Looks like // empty viewports aren't provided with a viewportIndex normally? data.viewportIndex = index; @@ -86,16 +110,26 @@ class GridLayout extends Component { width: `${width}%`, }; - const cornerstoneViewport = (data) => ( - - ); + const cornerstoneViewport = (data) => { + const stack = getCornerstoneStack(data) + const viewportData = { + stack, + ...data + }; + + return (); + }; const pluginViewport = (data) => (
); - let contents; + let contents; if (!data.studyInstanceUid || !data.displaySetInstanceUid) { contents = (
diff --git a/Packages/ohif-viewerbase/client/components/viewer/ImageScrollbar/ImageScrollbar.js b/Packages/ohif-viewerbase/client/components/viewer/ImageScrollbar/ImageScrollbar.js deleted file mode 100644 index a7a74dab0..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ImageScrollbar/ImageScrollbar.js +++ /dev/null @@ -1,68 +0,0 @@ -import { Component } from 'react'; -import React from 'react'; -import PropTypes from 'prop-types'; -import './ImageScrollbar.styl'; - -class ImageScrollbar extends Component { - constructor(props) { - super(props); - - this.onChange = this.onChange.bind(this); - this.onKeyDown = this.onKeyDown.bind(this); - } - - render() { - this.style = { - width: `${this.props.height}` - }; - - return ( -
-
- -
-
- ); - } - - onChange(event) { - const intValue = parseInt(event.target.value, 10); - this.props.onInputCallback(intValue); - } - - onKeyDown(event) { - // We don't allow direct keyboard up/down input on the - // image sliders since the natural direction is reversed (0 is at the top) - - // Store the KeyCodes in an object for readability - const keys = { - DOWN: 40, - UP: 38 - }; - - if (event.which === keys.DOWN) { - OHIF.commands.run('scrollDown'); - event.preventDefault(); - } else if (event.which === keys.UP) { - OHIF.commands.run('scrollUp'); - event.preventDefault(); - } - } -} - -ImageScrollbar.propTypes = { - value: PropTypes.number.isRequired, - onInputCallback: PropTypes.func.isRequired -}; - -export default ImageScrollbar; diff --git a/Packages/ohif-viewerbase/client/components/viewer/ImageScrollbar/ImageScrollbar.styl b/Packages/ohif-viewerbase/client/components/viewer/ImageScrollbar/ImageScrollbar.styl deleted file mode 100644 index 460cff602..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ImageScrollbar/ImageScrollbar.styl +++ /dev/null @@ -1,123 +0,0 @@ -@import "{ohif:design}/app" - -$imageSliderBorderRadius = 57px -$imageSliderTrackColor = rgba(0,0,0,0) -$imageSliderBorder = none - -// Note that these are backwards due to the magic needed to make a cross-browser vertical slider -$imageSliderWidth = 12px -$imageSliderHeight = 39px - -.scroll - height: 100% - padding: 5px - position: absolute - right: 0 - top: 0 - - .scroll-holder - height: calc(100% - 20px) - margin-top: 5px - position: relative - width: 12px - - .imageSlider - height: $imageSliderWidth - left: 12px - padding: 0 - position: absolute - top: 0 - - vendorize(transform, rotate(90deg)) - vendorize(transform-origin, top left) - - -webkit-appearance: none - background-color: $imageSliderTrackColor - - // Remove focus highlights on range input - &:focus - outline: none - vendorize(box-shadow, none) - - // Remove focus border in Firefox - &::-moz-focus-outer - border: none - - // --- Style the range track --- // - &::-webkit-slider-runnable-track - background-color: $imageSliderTrackColor - border: none - cursor: pointer - height: 5px - z-index: 6 - - &::-moz-range-track - background-color: $imageSliderTrackColor - border: none - cursor: pointer - height: 2px - z-index: 6 - - &::-ms-track - animate: 0.2s - background: transparent - border: none - border-width: 15px 0 - color: $imageSliderTrackColor - cursor: pointer - height: $imageSliderWidth - width: 100% - - // Hide any fill IE tries to add - &::-ms-fill-lower - background: $imageSliderTrackColor - - &::-ms-fill-upper - background: $imageSliderTrackColor - - // --- Style the range thumb --- // - &::-webkit-slider-thumb - -webkit-appearance: none !important - theme('background-color', '$imageSliderColor') - border: $imageSliderBorder - border-radius: $imageSliderBorderRadius - cursor: -webkit-grab - height: $imageSliderWidth - margin-top: -4px - width: $imageSliderHeight - - &:active - theme('background-color', '$activeColor') - cursor: -webkit-grabbing - - &::-moz-range-thumb - theme('background-color', '$imageSliderColor') - border: $imageSliderBorder - border-radius: $imageSliderBorderRadius - cursor: -moz-grab - height: $imageSliderWidth - width: $imageSliderHeight - z-index: 7 - - &:active - theme('background-color', '$activeColor') - cursor: -moz-grabbing - - &::-ms-thumb - theme('background-color', '$imageSliderColor') - border: $imageSliderBorder - border-radius: $imageSliderBorderRadius - cursor: ns-resize - height: $imageSliderWidth - width: $imageSliderHeight - - &:active - theme('background-color', '$activeColor') - - &::-ms-tooltip - display: none - -// Set left position in IE, border-width attribute breaks left position of imageSlider -@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) - .imageSlider - left: 50px diff --git a/Packages/ohif-viewerbase/client/components/viewer/LoadingIndicator/LoadingIndicator.js b/Packages/ohif-viewerbase/client/components/viewer/LoadingIndicator/LoadingIndicator.js deleted file mode 100644 index 97b27d768..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/LoadingIndicator/LoadingIndicator.js +++ /dev/null @@ -1,110 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { $ } from 'meteor/jquery'; -import { OHIF } from 'meteor/ohif:core'; - -import { Component } from 'react'; -import React from 'react'; -import PropTypes from 'prop-types'; -import './LoadingIndicator.styl'; - -Meteor.startup(() => { - // This checking is necessary because cornerstoneTools may not have some tools available. - // Example: when an app defines its own cornerstone's lib versions, so it - // uses only ohif-viewerbase and not ohif-cornerstone and those libs are added later. - if (cornerstoneTools.loadHandlerManager) { - cornerstoneTools.loadHandlerManager.setStartLoadHandler(startLoadingHandler); - cornerstoneTools.loadHandlerManager.setEndLoadHandler(doneLoadingHandler); - cornerstoneTools.loadHandlerManager.setErrorLoadingHandler(errorLoadingHandler); - } -}); - -let loadHandlerTimeout; - -const startLoadingHandler = element => { - clearTimeout(loadHandlerTimeout); - loadHandlerTimeout = setTimeout(() => { - console.log('startLoading'); - const elem = $(element); - elem.siblings('.imageViewerErrorLoadingIndicator').css('display', 'none'); - elem.find('canvas').not('.magnifyTool').addClass('faded'); - elem.siblings('.imageViewerLoadingIndicator').css('display', 'block'); - }, OHIF.viewer.loadIndicatorDelay); -}; - -const doneLoadingHandler = element => { - clearTimeout(loadHandlerTimeout); - const elem = $(element); - elem.siblings('.imageViewerErrorLoadingIndicator').css('display', 'none'); - elem.find('canvas').not('.magnifyTool').removeClass('faded'); - elem.siblings('.imageViewerLoadingIndicator').css('display', 'none'); -}; - -const errorLoadingHandler = (element, imageId, error, source) => { - clearTimeout(loadHandlerTimeout); - const elem = $(element); - - // Could probably chain all of these, but this is more readable - elem.find('canvas').not('.magnifyTool').removeClass('faded'); - elem.siblings('.imageViewerLoadingIndicator').css('display', 'none'); - - // Don't display errors from the stackPrefetch tool - if (source === 'stackPrefetch') { - return; - } - - const errorLoadingIndicator = elem.siblings('.imageViewerErrorLoadingIndicator'); - errorLoadingIndicator.css('display', 'block'); - - // This is just used to expand upon some error messages that are sent - // when things fail. An example is a network error throwing the error - // which is only described as "network". - const errorDetails = { - network: 'A network error has occurred' - // We need to expand this further when we see more obscure error messages - }; - - if (errorDetails.hasOwnProperty(error)) { - error = errorDetails[error]; - } - - errorLoadingIndicator.find('.description').text(`An error has occurred while loading image: ${imageId}`); - if (error) { - errorLoadingIndicator.find('.details').text(`Details: ${error}`); - } -}; - -class LoadingIndicator extends Component { - constructor(props) { - super(props); - } - - render() { - // TODO[react]: Pass this in as a prop reactively - //const percentComplete = Session.get('CornerstoneLoadProgress' + this.viewportIndex); - let percComplete; - if (this.props.percentComplete && this.props.percentComplete !== 100) { - percComplete = `${this.props.percentComplete}%`; - } - - return (<> -
-
-

Loading... {percComplete}

-
-
-
-
-

Error Loading Image

-

An error has occurred.

-

-
-
- ); - } -} - -LoadingIndicator.propTypes = { - percentComplete: PropTypes.number -}; - -export default LoadingIndicator; diff --git a/Packages/ohif-viewerbase/client/components/viewer/LoadingIndicator/LoadingIndicator.styl b/Packages/ohif-viewerbase/client/components/viewer/LoadingIndicator/LoadingIndicator.styl deleted file mode 100644 index 190d139c1..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/LoadingIndicator/LoadingIndicator.styl +++ /dev/null @@ -1,39 +0,0 @@ -@import "{ohif:design}/app" - -.imageViewerLoadingIndicator - theme('color', '$textSecondaryColor') - -.faded - opacity: 0.5 - -.imageViewerErrorLoadingIndicator - theme('color', '$uiYellow') - - p, h4 - padding: 4px 0 - text-align: center - word-wrap: break-word - - p - font-size: 11pt - -.loadingIndicator - background-color: rgba(0,0,0,0.75) - display: none - font-size: 18px - height: 100% - overflow: hidden - pointer-events: none // Necessary for click-through to cornerstone element below - position: absolute - top: 0 - width: 100% - z-index: 1 - - .indicatorContents - font-size: 30px - font-weight: 300 - position: absolute - text-align: center - top: 50% - transform(translateY(-50%)) - width: 100% diff --git a/Packages/ohif-viewerbase/client/components/viewer/ViewportOrientationMarkers/ViewportOrientationMarkers.js b/Packages/ohif-viewerbase/client/components/viewer/ViewportOrientationMarkers/ViewportOrientationMarkers.js deleted file mode 100644 index f4ca06ef3..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ViewportOrientationMarkers/ViewportOrientationMarkers.js +++ /dev/null @@ -1,87 +0,0 @@ -import { Component } from 'react'; -import React from 'react'; -import PropTypes from 'prop-types'; -import './ViewportOrientationMarkers.styl'; - -/** - * Computes the orientation labels on a Cornerstone-enabled Viewport element - * when the viewport settings change (e.g. when a horizontal flip or a rotation occurs) - * - * @param imageId The Cornerstone ImageId - * @param viewport The current viewport - */ -export function getOrientationMarkers(imageId, viewport) { - const imagePlane = cornerstone.metaData.get('imagePlane', imageId); - if (!imagePlane || !imagePlane.rowCosines || !imagePlane.columnCosines) { - return; - } - - const rowString = cornerstoneTools.orientation.getOrientationString(imagePlane.rowCosines); - const columnString = cornerstoneTools.orientation.getOrientationString(imagePlane.columnCosines); - const oppositeRowString = cornerstoneTools.orientation.invertOrientationString(rowString); - const oppositeColumnString = cornerstoneTools.orientation.invertOrientationString(columnString); - - const markers = { - top: oppositeColumnString, - left: oppositeRowString - }; - - // If any vertical or horizontal flips are applied, change the orientation strings ahead of - // the rotation applications - if (viewport.vflip) { - markers.top = cornerstoneTools.orientation.invertOrientationString(markers.top); - } - - if (viewport.hflip) { - markers.left = cornerstoneTools.orientation.invertOrientationString(markers.left); - } - - // Swap the labels accordingly if the viewport has been rotated - // This could be done in a more complex way for intermediate rotation values (e.g. 45 degrees) - if (viewport.rotation === 90 || viewport.rotation === -270) { - return { - top: markers.left, - left: cornerstoneTools.orientation.invertOrientationString(markers.top) - }; - } else if (viewport.rotation === -90 || viewport.rotation === 270) { - return { - top: cornerstoneTools.orientation.invertOrientationString(markers.left), - left: markers.top - }; - } else if (viewport.rotation === 180 || viewport.rotation === -180) { - return { - top: cornerstoneTools.orientation.invertOrientationString(markers.top), - left: cornerstoneTools.orientation.invertOrientationString(markers.left) - }; - } - - return markers; -} - -class ViewportOrientationMarkers extends Component { - render() { - const { imageId, viewport } = this.props; - const markers = getOrientationMarkers(imageId, viewport); - if (!markers) { - return ''; - } - - return ( -
-
- {markers.top} -
-
- {markers.left} -
-
- ); - } -}; - -ViewportOrientationMarkers.propTypes = { - imageId: PropTypes.string.isRequired, - viewport: PropTypes.object.isRequired -}; - -export default ViewportOrientationMarkers; diff --git a/Packages/ohif-viewerbase/client/components/viewer/ViewportOrientationMarkers/ViewportOrientationMarkers.styl b/Packages/ohif-viewerbase/client/components/viewer/ViewportOrientationMarkers/ViewportOrientationMarkers.styl deleted file mode 100644 index cf6dc5a2d..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ViewportOrientationMarkers/ViewportOrientationMarkers.styl +++ /dev/null @@ -1,17 +0,0 @@ -.ViewportOrientationMarkers - pointer-events: none // Necessary for click-through to cornerstone element below - - font-size: 15px - color: rgb(204, 204, 204) - line-height: 18px - - .orientation-marker - position: absolute - - .top-mid - top: 5px - left: 50% - - .left-mid - top: 47% - left: 5px diff --git a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/ViewportOverlay.js b/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/ViewportOverlay.js deleted file mode 100644 index 34c7c9a68..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/ViewportOverlay.js +++ /dev/null @@ -1,139 +0,0 @@ -import { Component } from 'react'; -import React from 'react'; -import PropTypes from 'prop-types'; -import './ViewportOverlay.styl'; -import { viewportOverlayUtils } from '../../../lib/viewportOverlayUtils'; -import { helpers } from '../../../lib/helpers/index.js'; -const { formatPN, formatDA, formatNumberPrecision, formatTM, isValidNumber} = helpers; - -function getCompression(imageId) { - const instance = cornerstone.metaData.get('instance', imageId); - if (!instance) { - return ''; - } - - if (instance.lossyImageCompression === '01' && - instance.lossyImageCompressionRatio !== '') { - const compressionMethod = instance.lossyImageCompressionMethod || 'Lossy: '; - const compressionRatio = formatNumberPrecision(instance.lossyImageCompressionRatio, 2); - return compressionMethod + compressionRatio + ' : 1'; - } - - return 'Lossless / Uncompressed'; -} - -function getImageDimensions(imageId) { - const instance = cornerstone.metaData.get('instance', imageId) - if (!instance) { - return ''; - } - - return `${instance.columns} x ${instance.rows}`; -} - -class ViewportOverlay extends Component { - render() { - const zoom = this.props.viewport.scale * 100; - const imageId = this.props.imageId; - - const patientMetadata = cornerstone.metaData.get('patient', imageId); - const studyMetadata = cornerstone.metaData.get('study', imageId); - const seriesMetadata = cornerstone.metaData.get('series', imageId); - const instanceMetadata = cornerstone.metaData.get('instance', imageId); - - const patientName = patientMetadata.name; - const patientId = patientMetadata.id;; - const { studyDate, studyTime, studyDescription } = studyMetadata; - const { seriesNumber, seriesDescription } = seriesMetadata; - const { instanceNumber, frameTime, thickness, spacingBetweenSlices, sliceLocation } = instanceMetadata; - const frameRate = formatNumberPrecision(1000 / frameTime, 1); - const compression = getCompression(imageId); - const windowWidth = this.props.viewport.voi.windowWidth || 0; - const windowCenter = this.props.viewport.voi.windowCenter || 0; - const wwwc = `W: ${windowWidth.toFixed(0)} L: ${windowCenter.toFixed(0)}`; - const imageIndex = this.props.stack.imageIds.indexOf(this.props.imageId) + 1; - const numImages = this.props.stack.imageIds.length; - const imageDimensions = getImageDimensions(imageId); - - const normal = (<> -
-
{formatPN(patientName)}
-
{patientId}
-
-
-
{studyDescription}
-
{formatDA(studyDate)} {formatTM(studyTime)}
-
-
-
Zoom: {formatNumberPrecision(zoom,0)}%
-
{compression}
-
{wwwc}
-
-
-
{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}
-
{numImages > 1 ? `Img: ${instanceNumber} ${imageIndex}/${numImages}` : ''}
-
{frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''} -
{imageDimensions}
-
- {isValidNumber(sliceLocation) ? `Loc: ${formatNumberPrecision(sliceLocation, 2)} mm` : ''} - {thickness ? `Thick: ${formatNumberPrecision(thickness, 2)} mm` : ''} - {spacingBetweenSlices ? `Spacing: ${formatNumberPrecision(spacingBetweenSlices, 2)} mm` : ''} -
-
{seriesDescription}
-
-
- ); - - const rightOnly = (<> -
-
{formatPN(patientName)}
-
{patientId}
-
{studyDescription}
-
{formatDA(studyDate)} {formatTM(studyTime)}
-
-
-
{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}
-
{numImages > 1 ? `Img: ${instanceNumber} ${imageIndex}/${numImages}` : ''}
-
{frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}
-
{imageDimensions}
-
{seriesDescription}
-
Zoom: ${formatNumberPrecision(zoom, 0)}%
-
{compression}
-
{wwwc}
-
- ); - - const leftOnly = (<> -
-
{formatPN(patientName)}
-
{patientId}
-
{studyDescription}
-
{formatDA(studyDate)} {formatTM(studyTime)}
-
-
-
{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}
-
{numImages > 1 ? `Img: ${instanceNumber} ${imageIndex}/${numImages}` : ''}
-
{frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}
-
{imageDimensions}
-
{seriesDescription}
-
Zoom: ${formatNumberPrecision(zoom, 0)}%
-
{compression}
-
{wwwc}
-
- ); - - return ( -
- {normal} -
- ); - } -} - -ViewportOverlay.propTypes = { - viewport: PropTypes.object.isRequired, - imageId: PropTypes.string.isRequired, - stack: PropTypes.object.isRequired -}; - -export default ViewportOverlay; diff --git a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/ViewportOverlay.styl b/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/ViewportOverlay.styl deleted file mode 100644 index eb87fa6ee..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/ViewportOverlay.styl +++ /dev/null @@ -1,52 +0,0 @@ -@import "{ohif:design}/app" - -$viewportTagPadding = 20px - -.imageViewerViewport.empty ~ .ViewportOverlay - display: none - -.ViewportOverlay - theme('color', '$textSecondaryColor') - - .overlay-element - position: absolute - font-weight: 400 - text-shadow: 1px 1px black - pointer-events: none - - .top-left - top: $viewportTagPadding - left: $viewportTagPadding - - .top-center - top: $viewportTagPadding - padding-top: $viewportTagPadding - width: 100% - text-align: center - - .top-right - top: $viewportTagPadding - right: $viewportTagPadding - text-align: right - - .bottom-left - bottom: $viewportTagPadding - left: $viewportTagPadding - - .bottom-right - bottom: $viewportTagPadding - right: $viewportTagPadding - text-align: right - - &.controlsVisible - .topright, .bottomright - right: "calc(%s + 19px)" % $viewportTagPadding - - svg - theme('color', '$defaultColor') - theme('fill', '$defaultColor') - theme('stroke', '$defaultColor') - background-color: transparent - margin: 2px - width: 18px - height: 18px diff --git a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/viewportOverlay-blz.js b/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/viewportOverlay-blz.js deleted file mode 100644 index f80cfe136..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/viewportOverlay-blz.js +++ /dev/null @@ -1,245 +0,0 @@ -import { Template } from 'meteor/templating'; -import { Session } from 'meteor/session'; -import { _ } from 'meteor/underscore'; -import { OHIF } from 'meteor/ohif:core'; -import { cornerstone } from 'meteor/ohif:cornerstone'; -import { viewportOverlayUtils } from '../../../lib/viewportOverlayUtils'; -import { getElementIfNotEmpty } from '../../../lib/getElementIfNotEmpty'; -import { getStackDataIfNotEmpty } from '../../../lib/getStackDataIfNotEmpty'; - -Template.viewportOverlay.onCreated(() => { - const instance = Template.instance(); - - instance.getImageIndex = () => { - const stack = getStackDataIfNotEmpty(instance.data.viewportIndex); - if (!stack || stack.currentImageIdIndex === undefined) return; - - return stack.currentImageIdIndex; - }; -}); - -Template.viewportOverlay.helpers({ - wwwc() { - Session.get('CornerstoneImageRendered' + this.viewportIndex); - - const element = getElementIfNotEmpty(this.viewportIndex); - if (!element) { - return ''; - } - - const viewport = cornerstone.getViewport(element); - if (!viewport) { - return ''; - } - - return 'W ' + viewport.voi.windowWidth.toFixed(0) + ' L ' + viewport.voi.windowCenter.toFixed(0); - }, - - zoom() { - Session.get('CornerstoneImageRendered' + this.viewportIndex); - - const element = getElementIfNotEmpty(this.viewportIndex); - if (!element) { - return; - } - - const viewport = cornerstone.getViewport(element); - if (!viewport) { - return; - } - - return (viewport.scale * 100.0); - }, - - imageDimensions() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - const image = viewportOverlayUtils.getImage(this.viewportIndex); - if (!image) { - return ''; - } - - return image.width + ' x ' + image.height; - }, - - patientName() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getPatient.call(this, 'name'); - }, - - patientId() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getPatient.call(this, 'id'); - }, - - patientBirthDate() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getPatient.call(this, 'birthDate'); - }, - - patientSex() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getPatient.call(this, 'sex'); - }, - - studyDate() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getStudy.call(this, 'studyDate'); - }, - - studyTime() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getStudy.call(this, 'studyTime'); - }, - - studyDescription() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getStudy.call(this, 'studyDescription'); - }, - - seriesDescription() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getSeries.call(this, 'seriesDescription'); - }, - - frameRate() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - const frameTime = viewportOverlayUtils.getInstance.call(this, 'frameTime'); - if (!frameTime) { - return; - } - - const frameRate = 1000 / frameTime; - return frameRate.toFixed(1); - }, - - seriesNumber() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getSeries.call(this, 'seriesNumber'); - }, - - instanceNumber() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getInstance.call(this, 'instanceNumber'); - }, - - thickness() { - // Displays Slice Thickness (0018,0050) - - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getInstance.call(this, 'sliceThickness'); - }, - - location() { - // Displays Slice Location (0020,1041), if present. - // - Otherwise, displays Table Position (0018,9327) - // - TODO: Otherwise, displays a value derived from Image Position (Patient) (0020,0032) - - Session.get('CornerstoneNewImage' + this.viewportIndex); - const sliceLocation = viewportOverlayUtils.getInstance.call(this, 'sliceLocation'); - if (sliceLocation !== '') { - return sliceLocation; - } - - const tablePosition = viewportOverlayUtils.getInstance.call(this, 'tablePosition'); - if (tablePosition !== '') { - return tablePosition; - } - - return viewportOverlayUtils.getInstance.call(this, 'imagePositionPatient'); - }, - - spacingBetweenSlices() { - // Displays Spacing Between Slices (0018,0088), if present. - - // TODO: Otherwise, displays a value derived from successive values - // of Image Position (Patient) (0020,0032) perpendicular to - // the Image Orientation (Patient) (0020,0037) - - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getInstance.call(this, 'spacingBetweenSlices'); - }, - - compression() { - // Displays whether or not lossy compression has been applied: - // - // - Checks Lossy Image Compression (0028,2110) - // - If so, displays the value of Lossy Image Compression Ratio (0028,2112) - // and Lossy Image Compression Method (0028,2114) - - Session.get('CornerstoneNewImage' + this.viewportIndex); - - if (!this.imageId) { - return false; - } - - const instance = cornerstone.metaData.get('instance', this.imageId); - if (!instance) { - return ''; - } - - if (instance.lossyImageCompression === '01' && - instance.lossyImageCompressionRatio !== '') { - const compressionMethod = instance.lossyImageCompressionMethod || 'Lossy: '; - const compressionRatio = parseFloat(instance.lossyImageCompressionRatio).toFixed(2); - return compressionMethod + compressionRatio + ' : 1'; - } - - return 'Lossless / Uncompressed'; - }, - - tagDisplayLeftOnly() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getTagDisplay.call(this, 'side') === 'L'; - }, - - tagDisplayRightOnly() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getTagDisplay.call(this, 'side') === 'R'; - }, - - tagDisplaySpecified() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getTagDisplay.call(this, 'side'); - }, - - imageNumber() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - return viewportOverlayUtils.getInstance.call(this, 'number'); - }, - - imageIndex() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - const imageIndex = Template.instance().getImageIndex(); - return _.isUndefined(imageIndex) ? 0 : imageIndex + 1; - }, - - numImages() { - Session.get('CornerstoneNewImage' + this.viewportIndex); - - const stack = getStackDataIfNotEmpty(this.viewportIndex); - if (!stack || !stack.imageIds) { - return; - } - - return stack.imageIds.length; - }, -}); diff --git a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/viewportOverlay.html b/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/viewportOverlay.html deleted file mode 100644 index 67e7c5377..000000000 --- a/Packages/ohif-viewerbase/client/components/viewer/ViewportOverlay/viewportOverlay.html +++ /dev/null @@ -1,73 +0,0 @@ - diff --git a/Packages/ohif-viewerbase/client/components/viewer/index.js b/Packages/ohif-viewerbase/client/components/viewer/index.js index 8b2211e01..2fb47d21a 100644 --- a/Packages/ohif-viewerbase/client/components/viewer/index.js +++ b/Packages/ohif-viewerbase/client/components/viewer/index.js @@ -1,20 +1,11 @@ import ViewerMain from './ViewerMain/ViewerMain.js'; import GridLayout from './GridLayout/GridLayout.js'; -import LoadingIndicator from './LoadingIndicator/LoadingIndicator.js'; -import CornerstoneViewport from './CornerstoneViewport/CornerstoneViewport.js'; -import ImageScrollbar from './ImageScrollbar/ImageScrollbar.js'; import ToolContextMenu from './ToolContextMenu/ToolContextMenu.js'; -import ViewportOverlay from './ViewportOverlay/ViewportOverlay.js'; -import ViewportOrientationMarkers from './ViewportOrientationMarkers/ViewportOrientationMarkers.js'; const viewer = { ViewerMain, GridLayout, - LoadingIndicator, - CornerstoneViewport, - ImageScrollbar, ToolContextMenu, - ViewportOverlay, }; export default viewer; diff --git a/Packages/ohif-viewerbase/client/lib/StackManager.js b/Packages/ohif-viewerbase/client/lib/StackManager.js index 21b0245cb..a40e7475b 100644 --- a/Packages/ohif-viewerbase/client/lib/StackManager.js +++ b/Packages/ohif-viewerbase/client/lib/StackManager.js @@ -146,3 +146,4 @@ const StackManager = { }; export { StackManager }; +export default StackManager; diff --git a/Packages/ohif-viewerbase/package.js b/Packages/ohif-viewerbase/package.js index b70e5c3cd..7bb47ffda 100644 --- a/Packages/ohif-viewerbase/package.js +++ b/Packages/ohif-viewerbase/package.js @@ -4,6 +4,16 @@ Package.describe({ version: '0.0.1' }); +Npm.depends({ + 'react-cornerstone-viewport': 'git://github.com:cornerstonejs/react-cornerstone-viewport.git', + hammerjs: '2.0.8', + 'cornerstone-core': '2.2.8', + 'cornerstone-tools': '3.0.0-b.1471', + 'cornerstone-math': '0.1.7', + 'dicom-parser': '1.8.3', + 'cornerstone-wado-image-loader': '2.2.3', +}); + Package.onUse(function(api) { api.versionsFrom('1.7'); diff --git a/package-lock.json b/package-lock.json index 5688b2b54..851cb319a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,445 +1,5 @@ { "name": "ohif-viewers-meta", "version": "0.0.1", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "bcrypt": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-2.0.1.tgz", - "integrity": "sha512-DwB7WgJPdskbR+9Y3OTJtwRq09Lmm7Na6b+4ewvXjkD0nfNRi1OozxljHm5ETlDCBq9DTy04lQz+rj+T2ztIJg==", - "requires": { - "nan": "2.10.0", - "node-pre-gyp": "0.9.1" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "bundled": true - } - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.9.1", - "bundled": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true - }, - "rc": { - "version": "1.2.6", - "bundled": true, - "requires": { - "deep-extend": "~0.4.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true - } - } - }, - "readable-stream": { - "version": "2.3.5", - "bundled": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true - }, - "sax": { - "version": "1.2.4", - "bundled": true - }, - "semver": { - "version": "5.5.0", - "bundled": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.0.3", - "bundled": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.0.2", - "bundled": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - } - } - }, - "gitbook-plugin-edit-link": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/gitbook-plugin-edit-link/-/gitbook-plugin-edit-link-2.0.2.tgz", - "integrity": "sha1-2PzZJ+ztgeemYqctWdtgnq/X5y8=" - }, - "gitbook-plugin-github": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/gitbook-plugin-github/-/gitbook-plugin-github-3.0.0.tgz", - "integrity": "sha1-Z0V9+YpX6o75slGLiDQNs3ClMXs=" - }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" - } - } + "lockfileVersion": 1 }