UNPKG

@metacell/geppetto-meta-ui

Version:

React components from geppetto-meta to create neuroscience applications and visualize data.

991 lines (964 loc) 39.6 kB
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } import React, { Component } from 'react'; import { PropTypes } from 'prop-types'; import * as THREE from 'three-legacy'; import DicomViewerUtils from './DicomViewerUtils'; import { offset } from '../utilities'; import { boundingBoxHelperFactory, VolumeLoader, StackModel } from 'ami.js'; var HelpersBoundingBox = boundingBoxHelperFactory(THREE); import { faDownload } from '@fortawesome/free-solid-svg-icons'; import CustomToolbar from '../common/CustomToolbar'; import { createZipFromRemoteFiles } from './util'; import Loader from "../loader/Loader"; var classes = { dicomViewer: "dicom-viewer", renderer: "dicom-viewer-renderer", toolbar: "dicom-viewer-toolbar", toolbarBox: "dicom-viewer-toolbar-box", button: "dicom-viewer-button" }; var _DicomViewer = /*#__PURE__*/function (_Component) { function _DicomViewer(props) { var _this2; _classCallCheck(this, _DicomViewer); _this2 = _callSuper(this, _DicomViewer, [props]); // 3d renderer _defineProperty(_this2, "animationOn", true); _defineProperty(_this2, "animationSkipRate", 3); _this2.r0 = { domClass: 'r0', domElement: null, renderer: null, color: 0x212121, targetID: 0, camera: null, controls: null, scene: null, light: null, parent: _this2 }; // 2d axial renderer _this2.r1 = { domClass: 'r1', domElement: null, renderer: null, color: 0x121212, sliceOrientation: 'axial', sliceColor: 0xff1744, targetID: 1, camera: null, controls: null, scene: null, light: null, stackHelper: null, localizerHelper: null, localizerScene: null, widgets: [], parent: _this2 }; // 2d sagittal renderer _this2.r2 = { domClass: 'r2', domElement: null, renderer: null, color: 0x121212, sliceOrientation: 'sagittal', sliceColor: 0xffea00, targetID: 2, camera: null, controls: null, scene: null, light: null, stackHelper: null, localizerHelper: null, localizerScene: null, widgets: [], parent: _this2 }; // 2d coronal renderer _this2.r3 = { domClass: 'r3', domElement: null, renderer: null, color: 0x121212, sliceOrientation: 'coronal', sliceColor: 0x76ff03, targetID: 3, camera: null, controls: null, scene: null, light: null, stackHelper: null, localizerHelper: null, localizerScene: null, widgets: [], parent: _this2 }; _this2.state = { ready: false }; _this2.containerRef = /*#__PURE__*/React.createRef(); _this2.onRender = _this2.props.onRender; _this2.drag = false; _this2.animationSkipRate = _this2.props.animationSkipRate || 3; _this2.startAnimation = _this2.startAnimation.bind(_this2); _this2.stopAnimation = _this2.stopAnimation.bind(_this2); _this2.centerOn = _this2.centerOn.bind(_this2); return _this2; } _inherits(_DicomViewer, _Component); return _createClass(_DicomViewer, [{ key: "extractFilesPath", value: function extractFilesPath(data) { if (!data) { return undefined; } if (!data.getMetaType) { return data; } if (data.getMetaType() === 'Instance') { var value = data.getVariable().getInitialValues()[0].value; switch (value.format) { case 'NIFTI': return value.data; case 'DCM': break; // todo: what do we do here? } } return undefined; } }, { key: "loadModel", value: function loadModel(modelData) { var data = this.extractFilesPath(modelData); if (!data) { return; } this.ready = false; var _this = this; var animationCount = 0; /** * Init the view */ function init() { /** * Called on each animation frame */ function animate() { if (_this.ready && _this.animationOn && animationCount++ % _this.animationSkipRate === 0) { // we are ready when both meshes have been loaded var _this$props = _this.props, mode = _this$props.mode, orientation = _this$props.orientation; var shouldRenderPlane = function shouldRenderPlane(plane) { return mode === 'quad_view' || orientation === plane; }; var shouldRender3D = shouldRenderPlane('3d'); var planesSetup = { 'r1': 'sagittal', 'r2': 'axial', 'r3': 'coronal' }; if (shouldRender3D) { // render _this.r0.controls.update(); _this.r0.light.position.copy(_this.r0.camera.position); _this.r0.renderer.render(_this.r0.scene, _this.r0.camera); _this.r0.scene.background = new THREE.Color("#353535"); } for (var _i = 0, _Object$entries = Object.entries(planesSetup); _i < _Object$entries.length; _i++) { var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), planeName = _Object$entries$_i[0], planeOrientation = _Object$entries$_i[1]; if (!shouldRenderPlane(planeOrientation)) { continue; } var plane = _this[planeName]; var camera = plane.camera; var renderer = plane.renderer; plane.controls.update(); // clear renderer renderer.clear(); plane.renderer.render(plane.scene, camera); plane.scene.background = new THREE.Color("#353535"); // localizer renderer.clearDepth(); renderer.render(plane.localizerScene, camera); // Widgets var _iterator = _createForOfIteratorHelper(plane.widgets), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var widget = _step.value; widget.update(); } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } } if (_this.onRender) { _this.onRender([_this.r0, _this.r1, _this.r2, _this.r3]); } } // request new frame requestAnimationFrame(animate); } // renderers DicomViewerUtils.initRenderer3D(_this.r0, _this.containerRef.current); DicomViewerUtils.initRenderer2D(_this.r1, _this.containerRef.current); DicomViewerUtils.initRenderer2D(_this.r2, _this.containerRef.current); DicomViewerUtils.initRenderer2D(_this.r3, _this.containerRef.current); // start rendering loop animate(); } // init threeJS init(); /* * load sequence for each file * instantiate the loader * it loads and parses the dicom image */ var loader = new VolumeLoader(); loader.load(this.extractFilesPath(data)).then(function () { var applySegmentationLUT = _this.props.applySegmentationLUT; var series = loader.data[0].mergeSeries(loader.data)[0]; loader.free(); loader = null; // get first stack from series var stack = series.stack[0]; stack.prepare(); // center 3d camera/control on the stack var centerLPS = stack.worldCenter(); _this.r0.camera.lookAt(centerLPS.x, centerLPS.y, centerLPS.z); _this.r0.camera.updateProjectionMatrix(); _this.r0.controls.target.set(centerLPS.x, centerLPS.y, centerLPS.z); // bounding box var boxHelper = new HelpersBoundingBox(stack); _this.r0.scene.add(boxHelper); // Init the 2D planes stack helpers DicomViewerUtils.initHelpersStack(_this.r1, stack); DicomViewerUtils.initHelpersStack(_this.r2, stack); DicomViewerUtils.initHelpersStack(_this.r3, stack); // Init the 2D planes segmentation LUT if necessary if (applySegmentationLUT) { DicomViewerUtils.initSegmentationLUT(_this.r1, stack, _this.r1.stackHelper); DicomViewerUtils.initSegmentationLUT(_this.r2, stack, _this.r2.stackHelper); DicomViewerUtils.initSegmentationLUT(_this.r3, stack, _this.r3.stackHelper); } var planesSetup = { 'r1': ['r2', 'r3'], // red slice 'r2': ['r1', 'r3'], // yellow slice 'r3': ['r1', 'r2'] // green slice }; // Initialize 2D planes localizer (cross on 2D planes) for (var _i2 = 0, _Object$entries2 = Object.entries(planesSetup); _i2 < _Object$entries2.length; _i2++) { var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2), planeName = _Object$entries2$_i[0], linkedPlaneNames = _Object$entries2$_i[1]; var plane = _this[planeName]; // Add each 2D plane to the 3D scene _this.r0.scene.add(plane.scene); /* * Init the localizer * create new mesh with Localizer shaders */ var planeEquation = plane.stackHelper.slice.cartesianEquation(); /* * create new mesh with Localizer shaders * compute the dependent stack helper */ var linkedPlanes = linkedPlaneNames.map(function (name) { var linkedStackHelper = _this[name].stackHelper; return { plane: linkedStackHelper.slice.cartesianEquation(), color: new THREE.Color(linkedStackHelper.borderColor) }; }); DicomViewerUtils.initHelpersLocalizer(plane, stack, planeEquation, linkedPlanes); } _this.configureEvents(); _this.updateLayout(_this.props.mode); _this.ready = true; _this.setState({ ready: true }); _this.props.onLoaded(); })["catch"](function (error) { window.console.log('oops... something went wrong...'); window.console.log(error); }); } }, { key: "updateLayout", value: function updateLayout(mode) { if (mode === 'single_view') { this.setSingleLayout(this.props.orientation); } else { this.setQuadLayout(); } } }, { key: "centerOn", value: function centerOn(plane, point) { if (!plane.stackHelper) { return; } var stackHelper = plane.stackHelper; var ijk = StackModel.worldToData(stackHelper.stack, point); this.r1.stackHelper.index = ijk.getComponent((this.r1.stackHelper.orientation + 2) % 3); this.r2.stackHelper.index = ijk.getComponent((this.r2.stackHelper.orientation + 2) % 3); this.r3.stackHelper.index = ijk.getComponent((this.r3.stackHelper.orientation + 2) % 3); DicomViewerUtils.updateLocalizer(this.r2, [this.r1.localizerHelper, this.r3.localizerHelper]); DicomViewerUtils.updateLocalizer(this.r1, [this.r2.localizerHelper, this.r3.localizerHelper]); DicomViewerUtils.updateLocalizer(this.r3, [this.r1.localizerHelper, this.r2.localizerHelper]); } }, { key: "clickedOnPoint", value: function clickedOnPoint(event, callback) { var canvas = event.srcElement.parentElement; var id = event.target.id; var mouse = { x: (event.clientX - offset(canvas).left) / canvas.clientWidth * 2 - 1, y: -((event.clientY - offset(canvas).top) / canvas.clientHeight) * 2 + 1 }; var plane = this["r".concat(id)]; if (!plane) { return; } var camera = plane.camera; // const stackHelper = plane.stackHelper; var scene = plane.scene; var raycaster = new THREE.Raycaster(); raycaster.setFromCamera(mouse, camera); var intersects = raycaster.intersectObjects(scene.children, true); if (intersects.length > 0) { callback(plane, intersects[0].point, event); } } }, { key: "configureEvents", value: function configureEvents() { var _this3 = this; var _this = this; function goToPoint(event) { _this.clickedOnPoint(event, _this.centerOn); } function pointClickedOn(event) { _this.clickedOnPoint(event, _this.props.pointClickedOn); } function goToSingleView(event) { var id = event.target.id; var orientation = null; switch (id) { case '0': orientation = '3d'; break; case '1': orientation = 'sagittal'; break; case '2': orientation = 'axial'; break; case '3': orientation = 'coronal'; break; } if (orientation != null) { _this.setState({ mode: 'single_view', orientation: orientation }); } } /* * function toggleMode (event) { * if (_this.props.mode === 'single_view') { * _this.changeMode(); * } else { * goToSingleView(event); * } * } */ function onScroll(event) { var view = event.target.domElement.dataset.view; var stackHelper = null; switch (view) { case 'r1': stackHelper = _this.r1.stackHelper; break; case 'r2': stackHelper = _this.r2.stackHelper; break; case 'r3': stackHelper = _this.r3.stackHelper; break; } if (event.delta > 0) { if (stackHelper.index >= stackHelper.orientationMaxIndex - 1) { return false; } stackHelper.index += 1; } else { if (stackHelper.index <= 0) { return false; } stackHelper.index -= 1; } DicomViewerUtils.updateLocalizer(_this.r2, [_this.r1.localizerHelper, _this.r3.localizerHelper]); DicomViewerUtils.updateLocalizer(_this.r1, [_this.r2.localizerHelper, _this.r3.localizerHelper]); DicomViewerUtils.updateLocalizer(_this.r3, [_this.r1.localizerHelper, _this.r2.localizerHelper]); return true; } function performEventAction(action, event) { // Check if it is a already defined action or a external one if (action === 'goToPoint' || action === 'goToSingleView' || action === 'toggleMode' || action === 'pointClickedOn') { eval(action + '(event)'); } else { action(event, this); } } function eventHandling(event) { if (_this.drag) { return; } if (event.type === 'mouseup' && event.which === 3 && _this.props.onRightClick) { performEventAction(_this.props.onRightClick, event); } var isClick = event.type === 'click'; if (isClick && (event.ctrlKey || event.metaKey) && _this.props.onCtrlClick) { performEventAction(_this.props.onCtrlClick, event); } else if (isClick && event.shiftKey && _this.props.onShiftClick) { performEventAction(_this.props.onShiftClick, event); } else if (isClick && _this.props.onClick) { performEventAction(_this.props.onClick, event); } else if (event.type === 'dblclick' && _this.props.onDoubleClick) { performEventAction(_this.props.onDoubleClick, event); } } // event listeners ondoubleclick _this.r0.domElement.addEventListener('dblclick', eventHandling); _this.r1.domElement.addEventListener('dblclick', eventHandling); _this.r2.domElement.addEventListener('dblclick', eventHandling); _this.r3.domElement.addEventListener('dblclick', eventHandling); // event listeners onclick this.r0.domElement.addEventListener('click', eventHandling); this.r1.domElement.addEventListener('click', eventHandling); this.r2.domElement.addEventListener('click', eventHandling); this.r3.domElement.addEventListener('click', eventHandling); this.r0.domElement.addEventListener('mouseup', eventHandling); this.r1.domElement.addEventListener('mouseup', eventHandling); this.r2.domElement.addEventListener('mouseup', eventHandling); this.r3.domElement.addEventListener('mouseup', eventHandling); // event listeners on scrol this.r1.controls.addEventListener('OnScroll', onScroll); this.r2.controls.addEventListener('OnScroll', onScroll); this.r3.controls.addEventListener('OnScroll', onScroll); // event listener on mouse down/up/move to detect drag on all views for (var _i3 = 0, _arr = ['r0', 'r1', 'r2', 'r3']; _i3 < _arr.length; _i3++) { var subref = _arr[_i3]; this[subref].domElement.addEventListener('mousedown', function () { _this3.drag = false; return false; }); this[subref].domElement.addEventListener('mousemove', function () { _this3.drag = true; }); this[subref].domElement.addEventListener('mouseout', function () { _this3.drag = false; }); } } }, { key: "setQuadLayout", value: function setQuadLayout() { // update 3D DicomViewerUtils.windowResize3D(this.r0); // update 2d DicomViewerUtils.windowResize2D(this.r1); DicomViewerUtils.windowResize2D(this.r2); DicomViewerUtils.windowResize2D(this.r3); } }, { key: "setSingleLayout", value: function setSingleLayout(orientation) { switch (orientation) { case '3d': DicomViewerUtils.windowResize3D(this.r0); break; case 'sagittal': DicomViewerUtils.windowResize2D(this.r1); break; case 'axial': DicomViewerUtils.windowResize2D(this.r2); break; case 'coronal': DicomViewerUtils.windowResize2D(this.r3); break; } } }, { key: "componentWillUnmount", value: function componentWillUnmount() { DicomViewerUtils.dispose(this.r0); DicomViewerUtils.dispose(this.r1); DicomViewerUtils.dispose(this.r2); DicomViewerUtils.dispose(this.r3); } }, { key: "componentDidMount", value: function componentDidMount() { this.loadModel(this.props.data); } }, { key: "componentDidUpdate", value: function componentDidUpdate(prevProps, prevState) { if (this.props.mode !== prevProps.mode || this.props.orientation !== prevProps.orientation || this.props.update > 1 && this.props.update !== prevProps.update || prevState.ready !== this.state.ready && !prevState.ready) { try { this.updateLayout(this.props.mode); } catch (e) { // not ready yet } } } }, { key: "shouldComponentUpdate", value: function shouldComponentUpdate(nextProps, nextState) { this.animationOn = true; return nextProps.data !== this.props.data || nextProps.update !== this.props.update || nextProps.fullScreen !== this.props.fullScreen || nextProps.mode !== this.props.mode || nextProps.orientation !== this.props.orientation || nextState.ready !== this.state.ready && nextState.ready; } }, { key: "stopAnimation", value: function stopAnimation() { this.animationOn = false; } }, { key: "startAnimation", value: function startAnimation() { this.animationOn = true; } }, { key: "download", value: function download() { createZipFromRemoteFiles(this.props.data, !Array.isArray(this.props.data) ? this.props.data : "data.zip"); } }, { key: "getCustomButtons", value: function getCustomButtons() { var customButtons = []; var toolbarButtons = this.props.toolbarButtons; var addButtons = function addButtons(buttons) { if (!buttons) { return; } customButtons.push.apply(customButtons, _toConsumableArray(buttons.map(function (b) { return _objectSpread(_objectSpread({}, b), {}, { id: b.tooltip }); }))); }; if (this.props.mode == 'single_view') { addButtons(toolbarButtons === null || toolbarButtons === void 0 ? void 0 : toolbarButtons.single_view); } else { addButtons(toolbarButtons === null || toolbarButtons === void 0 ? void 0 : toolbarButtons.quad_view); } if (this.props.showDownloadButton) { customButtons.push({ icon: faDownload, id: 'Download', tooltip: 'Download', action: this.download }); } if (this.props.fullScreen) { addButtons(toolbarButtons === null || toolbarButtons === void 0 ? void 0 : toolbarButtons.fullScreen); } else { addButtons(toolbarButtons === null || toolbarButtons === void 0 ? void 0 : toolbarButtons.minimized); } return customButtons; } }, { key: "hasCustomButtons", value: function hasCustomButtons() { var buttons = this.props.toolbarButtons; return (buttons === null || buttons === void 0 ? void 0 : buttons.single_view) || (buttons === null || buttons === void 0 ? void 0 : buttons.quad_view) || (buttons === null || buttons === void 0 ? void 0 : buttons.fullScreen) || (buttons === null || buttons === void 0 ? void 0 : buttons.minimized) || this.props.showDownloadButton; } }, { key: "render", value: function render() { var _this$props2 = this.props, toolbarOptions = _this$props2.toolbarOptions, loaderOptions = _this$props2.loaderOptions, mode = _this$props2.mode, orientation = _this$props2.orientation, id = _this$props2.id, fullScreen = _this$props2.fullScreen; var customButtons = this.getCustomButtons(); var containerStyle = fullScreen ? { position: 'fixed', top: '0', left: '0', zIndex: '9999', background: '#121212', height: '100%', width: '100%' } : { height: '100%', width: '100%' }; var displayView = function displayView(o) { return mode === 'single_view' && orientation === o; }; var display3DView = displayView('3d'); var doNotDisplay = function doNotDisplay(o) { return mode === 'single_view' && orientation !== o; }; var showLoader = loaderOptions && loaderOptions.showLoader; var loader = loaderOptions && loaderOptions.instance ? /*#__PURE__*/React.createElement(loaderOptions.instance, loaderOptions.props) : /*#__PURE__*/React.createElement(Loader, { fullscreen: fullScreen, handleClose: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.handleClose, messages: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.messages, messagesInterval: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.messagesInterval, elapsed: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.elapsed, backgroundStyle: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.backgroundStyle }); var toolbar = toolbarOptions && toolbarOptions.instance ? /*#__PURE__*/React.createElement(toolbarOptions.instance, _extends({ buttons: customButtons }, toolbarOptions.props)) : /*#__PURE__*/React.createElement(CustomToolbar, { buttons: customButtons, containerStyles: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.containerStyles, toolBarClassName: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.toolBarClassName, innerDivStyles: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.innerDivStyles, buttonStyles: toolbarOptions === null || toolbarOptions === void 0 ? void 0 : toolbarOptions.buttonStyles }); return /*#__PURE__*/React.createElement("div", { ref: this.containerRef, key: "".concat(id, "_component"), id: "".concat(id, "_component"), style: containerStyle, onMouseLeave: this.stopAnimation, className: "container-dicom-viewer" }, !this.state.ready && showLoader && loader, this.hasCustomButtons() && toolbar, /*#__PURE__*/React.createElement("div", { className: classes.dicomViewer, style: { height: '90%', width: '100%', display: 'flex', flexWrap: 'wrap', backgroundColor: '#353535' } }, /*#__PURE__*/React.createElement("div", { id: "r0", className: classes.renderer + ' r0', "data-view": "r0", style: { display: doNotDisplay('3d') ? 'none' : '', width: display3DView ? '100%' : '50%', height: display3DView ? '100%' : '50%', backgroundColor: '#000', "float": 'left' }, onMouseEnter: this.startAnimation }), /*#__PURE__*/React.createElement("div", { id: "r1", className: classes.renderer + ' r1', "data-view": "r1", style: { display: doNotDisplay('sagittal') ? 'none' : '', width: displayView('sagittal') ? '100%' : '50%', height: displayView('sagittal') ? '100%' : '50%', backgroundColor: '#000', "float": 'left' }, onMouseEnter: this.startAnimation }), /*#__PURE__*/React.createElement("div", { id: "r2", className: classes.renderer + ' r2', "data-view": "r2", style: { display: doNotDisplay('axial') ? 'none' : '', width: displayView('axial') ? '100%' : '50%', height: displayView('axial') ? '100%' : '50%', backgroundColor: '#000', "float": 'left' }, onMouseEnter: this.startAnimation }), /*#__PURE__*/React.createElement("div", { id: "r3", className: classes.renderer + ' r3', "data-view": "r3", style: { display: doNotDisplay('coronal') ? 'none' : '', width: displayView('coronal') ? '100%' : '50%', height: displayView('coronal') ? '100%' : '50%', backgroundColor: '#000', "float": 'left' }, onMouseEnter: this.startAnimation }), /*#__PURE__*/React.createElement("div", { className: "segmentationLUT-r1", style: { visibility: "hidden" } }), /*#__PURE__*/React.createElement("div", { className: "segmentationLUT-r2", style: { visibility: "hidden" } }), /*#__PURE__*/React.createElement("div", { className: "segmentationLUT-r3", style: { visibility: "hidden" } }))); } }]); }(Component); var DicomViewer = function DicomViewer(props) { return /*#__PURE__*/React.createElement(_DicomViewer, props); }; DicomViewer.defaultProps = { onLoaded: function onLoaded() {}, mode: 'quad_view', orientation: '3d', onClick: 'goToPoint', onCtrlClick: 'goToPoint', onShiftClick: 'goToPoint', onDoubleClick: 'goToPoint', onRightClick: undefined, showDownloadButton: false, toolbarOptions: null, loaderOptions: { showLoader: true } }; DicomViewer.propTypes = { /** * Component identifier */ id: PropTypes.string.isRequired, /** * Path/URL to file (f.e. "/path/to/my/file.gz") */ data: PropTypes.string.isRequired, /** * View mode: 'single_view' or 'quad_view' */ mode: PropTypes.oneOf(['single_view', 'quad_view']), /** * Display the dicom viewer in full screen */ fullScreen: PropTypes.bool, /** * Orientation view: '3d', 'coronal', 'axial' or 'sagittal' */ orientation: PropTypes.oneOf(['3d', 'coronal', 'axial', 'sagittal']), /** * Action to perform on click: 'goToPoint', or custom action */ onClick: PropTypes.oneOfType([PropTypes.oneOf(['goToPoint']), PropTypes.func]), /** * Action to performe on Ctrl click: 'goToPoint' or custom action */ onCtrlClick: PropTypes.oneOfType([PropTypes.oneOf(['goToPoint']), PropTypes.func]), /** * Action to performe on Shift click: 'goToPoint' or custom action */ onShiftClick: PropTypes.oneOfType([PropTypes.oneOf(['goToPoint']), PropTypes.func]), /** * Action to performe on right click: 'goToPoint' or custom action */ onRightClick: PropTypes.oneOfType([PropTypes.oneOf(['goToPoint']), PropTypes.func]), /** * Action to performe on double click: 'goToPoint' or custom action */ onDoubleClick: PropTypes.oneOfType([PropTypes.oneOf(['goToPoint']), PropTypes.func]), /** * Enables segmentation LUT */ applySegmentationLUT: PropTypes.bool, /** * Bool that defines the showing or not of the download button */ showDownloadButton: PropTypes.bool, /** * Callback function to be called after load is complete */ onLoaded: PropTypes.func, /** * Options to customize the toolbar */ toolbarOptions: PropTypes.shape({ /** * Reference to toolbar component */ instance: PropTypes.elementType, /** * Custom toolbar props */ props: PropTypes.shape({}), /** * Styles to be applied to the toolbar container */ containerStyles: PropTypes.shape({}), /** * Styles to be applied to the toolbar */ toolBarClassName: PropTypes.shape({}), /** * Styles to be applied to the inner div */ innerDivStyles: PropTypes.shape({}), /** * Styles to be applied to the buttons */ buttonStyles: PropTypes.shape({}) }), /** * Options to customize the loader */ loaderOptions: PropTypes.shape({ /** * Reference to toolbar component */ instance: PropTypes.elementType, /** * Custom loader props */ props: PropTypes.shape({}), /** * Bool to control the use of the loader */ showLoader: PropTypes.bool, /** * Function to handle the close of the Loader */ handleClose: PropTypes.func, /** * Array of Custom messages to display */ messages: PropTypes.array, /** * Number of milliseconds between custom messages */ messagesInterval: PropTypes.number, /** * Number of the progress value to show in linear determinate (in percentage) */ elapsed: PropTypes.number, /** * Style to be applied to the Loader background */ backgroundStyle: PropTypes.shape({ /** * Loader's background color. Defaults to rgba(255,142,0,0.1) */ backgroundColor: PropTypes.string }) }), /** * Buttons and action to add depending in the view mode/full screen */ toolbarButtons: PropTypes.shape({ /** * Buttons to display if the view is minimized */ minimized: PropTypes.arrayOf(PropTypes.shape({ /** * The button icon */ icon: PropTypes.string, /** * The tooltip of the button */ tooltip: PropTypes.string, /** * A callback that will be called when the button is clicked */ action: PropTypes.func })), /** * Buttons to display if the view is full screen */ fullScreen: PropTypes.arrayOf(PropTypes.shape({ /** * The button icon */ icon: PropTypes.string, /** * The tooltip of the button */ tooltip: PropTypes.string, /** * A callback that will be called when the button is clicked */ action: PropTypes.func })), /** * Buttons to display if the view is in single view mode */ single_view: PropTypes.arrayOf(PropTypes.shape({ /** * The button icon */ icon: PropTypes.string, /** * The tooltip of the button */ tooltip: PropTypes.string, /** * A callback that will be called when the button is clicked */ action: PropTypes.func })), /** * Buttons to display if the view in quad view mode */ quad_view: PropTypes.arrayOf(PropTypes.shape({ /** * The button icon */ icon: PropTypes.string, /** * The tooltip of the button */ tooltip: PropTypes.string, /** * A callback that will be called when the button is clicked */ action: PropTypes.func })) }) }; export default DicomViewer;