UNPKG

webgme-dss

Version:

Design Studio for Dynamic Systems with Modelica as backend

249 lines (211 loc) 7.31 kB
import React, {Component} from 'react'; import PropTypes from 'prop-types'; import update from 'immutability-helper'; import IconButton from '@material-ui/core/IconButton'; import OpenInNew from '@material-ui/icons/OpenInNew'; import AddCircle from '@material-ui/icons/AddCircle'; import PortalWindow from '../gme/PortalWindow'; import Plotter from './Plotter'; import CheckboxList from '../gme/CheckboxList'; import colorHash from '../gme/utils/colorHash'; class PlotManager extends Component { static propTypes = { variables: PropTypes.arrayOf(PropTypes.string).isRequired, simRes: PropTypes.object.isRequired, }; state = { docked: true, latestWindowId: null, plotWindows: {}, }; componentWillReceiveProps(nextProps) { const {plotWindows, latestWindowId} = this.state; const windowIds = Object.keys(plotWindows); if (windowIds.length > 0) { // Filter invalid ones and add new ones. const newPlotVariables = nextProps.variables.filter(varName => !this.props.variables.includes(varName)); const updateDesc = {}; windowIds.forEach((windowId) => { let windowVariables = plotWindows[windowId].variables .filter(varName => nextProps.variables.includes(varName)); if (windowId === latestWindowId) { windowVariables = windowVariables.concat(newPlotVariables); } updateDesc[windowId] = { $set: { variables: windowVariables, }, }; }); this.setState({plotWindows: update(this.state.plotWindows, updateDesc)}); } } toggleDocked = () => { const {variables} = this.props; const {docked} = this.state; const newState = { docked: !docked, latestWindowId: null, plotWindows: {}, }; if (docked) { newState.plotWindows['1'] = { variables, }; newState.latestWindowId = '1'; } this.setState(newState); }; addPlotWindow = () => { const {plotWindows} = this.state; let id; for (let i = 1; i <= Object.keys(plotWindows).length + 1; i += 1) { if (!plotWindows[i]) { id = i.toString(); break; } } this.setState({ plotWindows: update(plotWindows, { [id]: { $set: {variables: []}, }, }), latestWindowId: id, }); } removePlotWindow = (id) => { const {plotWindows, latestWindowId} = this.state; const windowIds = Object.keys(plotWindows); if (windowIds.length === 1) { // Last window is removed - we are no longer undocked. this.toggleDocked(); return; } const newState = { plotWindows: update(plotWindows, { $unset: [id], }), }; if (id === latestWindowId) { newState.latestWindowId = windowIds.find(windowId => windowId !== id); } this.setState(newState); } plotVariableCheckChange = windowId => (varName, event, checked) => { const {plotWindows} = this.state; let varAddOrRemove; if (checked) { varAddOrRemove = { $push: [varName], }; } else { varAddOrRemove = { $splice: [[plotWindows[windowId].variables.indexOf(varName), 1]], }; } this.setState({ latestWindowId: windowId, plotWindows: update(plotWindows, { [windowId]: { variables: varAddOrRemove, }, }), }); } render() { const {variables, simRes} = this.props; const {docked, plotWindows} = this.state; // FIXME: Problem mutating there? It's only sorting though... variables.sort(); const toggleDockedBtn = ( <IconButton style={{ position: 'absolute', top: 0, right: 5, }} onClick={this.toggleDocked} > <OpenInNew style={{ transform: `rotate(${docked ? 0 : 180}deg)`, }} /> </IconButton> ); if (docked) { return ( <div> {toggleDockedBtn} <Plotter variables={variables} simRes={simRes}/> </div>); } const windowIds = Object.keys(plotWindows).sort(); const portals = windowIds.map(windowId => ( <PortalWindow key={windowId} onClose={() => this.removePlotWindow(windowId)} windowFeatures={{ height: 400, width: 800, }} > <title>{`Plot window ${windowId}`}</title> <h1>{`Plot window ${windowId}`}:</h1> <Plotter variables={plotWindows[windowId].variables} simRes={simRes}/> </PortalWindow> )); const selectors = windowIds.map((windowId) => { const checkBoxes = variables.map(varName => ({ id: varName, isChecked: plotWindows[windowId].variables.includes(varName), cbStyle: { color: colorHash(varName).rgb, height: 36, }, })); return ( <CheckboxList key={windowId} title={`Plot window ${windowId}:`} items={checkBoxes} onCheckedChange={this.plotVariableCheckChange(windowId)} /> ); }); const addWindowBtn = ( <IconButton style={{ position: 'absolute', top: 0, left: 0, }} onClick={this.addPlotWindow} > <AddCircle/> </IconButton> ); return ( <div style={{ height: 300, }} > {toggleDockedBtn} {addWindowBtn} <div style={{ display: 'inline-flex', paddingLeft: 50, paddingTop: 20, height: 'calc(100% - 20px)', width: 'calc(100% - 50px)', overflow: 'auto', }} > {selectors} </div> {portals} </div> ); } } export default PlotManager;