import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { withTranslation } from 'react-i18next'; import { MODULE_TYPES } from '@ohif/core'; import { ExpandableToolMenu, RoundedButtonGroup, ToolbarButton, withModal, withDialog, } from '@ohif/ui'; import './ToolbarRow.css'; import { commandsManager, extensionManager } from './../App.js'; import ConnectedCineDialog from './ConnectedCineDialog'; import ConnectedLayoutButton from './ConnectedLayoutButton'; import { withAppContext } from '../context/AppContext'; class ToolbarRow extends Component { // TODO: Simplify these? isOpen can be computed if we say "any" value for selected, // closed if selected is null/undefined static propTypes = { isLeftSidePanelOpen: PropTypes.bool.isRequired, isRightSidePanelOpen: PropTypes.bool.isRequired, selectedLeftSidePanel: PropTypes.string.isRequired, selectedRightSidePanel: PropTypes.string.isRequired, handleSidePanelChange: PropTypes.func.isRequired, activeContexts: PropTypes.arrayOf(PropTypes.string).isRequired, studies: PropTypes.array, t: PropTypes.func.isRequired, // NOTE: withDialog, withModal HOCs dialog: PropTypes.any, modal: PropTypes.any, }; static defaultProps = { studies: [], }; constructor(props) { super(props); const toolbarButtonDefinitions = _getVisibleToolbarButtons.call(this); // TODO: // If it's a tool that can be active... Mark it as active? // - Tools that are on/off? // - Tools that can be bound to multiple buttons? // Normal ToolbarButtons... // Just how high do we need to hoist this state? // Why ToolbarRow instead of just Toolbar? Do we have any others? this.state = { toolbarButtons: toolbarButtonDefinitions, activeButtons: [], }; this.seriesPerStudyCount = []; this._handleBuiltIn = _handleBuiltIn.bind(this); this.updateButtonGroups(); } updateButtonGroups() { const panelModules = extensionManager.modules[MODULE_TYPES.PANEL]; this.buttonGroups = { left: [], right: [], }; // ~ FIND MENU OPTIONS panelModules.forEach(panelExtension => { const panelModule = panelExtension.module; const defaultContexts = Array.from(panelModule.defaultContext); panelModule.menuOptions.forEach(menuOption => { const contexts = Array.from(menuOption.context || defaultContexts); const hasActiveContext = this.props.activeContexts.some(actx => contexts.includes(actx) ); // It's a bit beefy to pass studies; probably only need to be reactive on `studyInstanceUIDs` and activeViewport? // Note: This does not cleanly handle `studies` prop updating with panel open const isDisabled = typeof menuOption.isDisabled === 'function' && menuOption.isDisabled(this.props.studies); if (hasActiveContext && !isDisabled) { const menuOptionEntry = { value: menuOption.target, icon: menuOption.icon, bottomLabel: menuOption.label, }; const from = menuOption.from || 'right'; this.buttonGroups[from].push(menuOptionEntry); } }); }); // TODO: This should come from extensions, instead of being baked in this.buttonGroups.left.unshift({ value: 'studies', icon: 'th-large', bottomLabel: this.props.t('Series'), }); } componentDidUpdate(prevProps) { const activeContextsChanged = prevProps.activeContexts !== this.props.activeContexts; const prevStudies = prevProps.studies; const studies = this.props.studies; const seriesPerStudyCount = this.seriesPerStudyCount; let studiesUpdated = false; if (prevStudies.length !== studies.length) { studiesUpdated = true; } else { for (let i = 0; i < studies.length; i++) { if (studies[i].series.length !== seriesPerStudyCount[i]) { seriesPerStudyCount[i] = studies[i].series.length; studiesUpdated = true; break; } } } if (studiesUpdated) { this.updateButtonGroups(); } if (activeContextsChanged) { this.setState( { toolbarButtons: _getVisibleToolbarButtons.call(this), }, this.closeCineDialogIfNotApplicable ); } } closeCineDialogIfNotApplicable = () => { const { dialog } = this.props; let { dialogId, activeButtons, toolbarButtons } = this.state; if (dialogId) { const cineButtonPresent = toolbarButtons.find( button => button.options && button.options.behavior === 'CINE' ); if (!cineButtonPresent) { dialog.dismiss({ id: dialogId }); activeButtons = activeButtons.filter( button => button.options && button.options.behavior !== 'CINE' ); this.setState({ dialogId: null, activeButtons }); } } }; render() { const buttonComponents = _getButtonComponents.call( this, this.state.toolbarButtons, this.state.activeButtons ); const onPress = (side, value) => { this.props.handleSidePanelChange(side, value); }; const onPressLeft = onPress.bind(this, 'left'); const onPressRight = onPress.bind(this, 'right'); return ( <>