react-floorplanner
Version:
react-floorplanner is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
193 lines (174 loc) • 5.71 kB
JSX
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import IconNewFile from 'react-icons/lib/fa/file-o';
import IconPointer from 'react-icons/lib/fa/mouse-pointer';
import Icon3DFirstPerson from 'react-icons/lib/md/directions-run';
import IconCatalog from 'react-icons/lib/fa/plus';
import IconUndo from 'react-icons/lib/md/undo';
import IconConfigure from 'react-icons/lib/md/settings';
import ToolbarButton from './toolbar-button';
import ToolbarSaveButton from './toolbar-save-button';
import ToolbarLoadButton from './toolbar-load-button';
import If from '../../utils/react-if';
import {
MODE_IDLE,
MODE_3D_VIEW,
MODE_3D_FIRST_PERSON,
MODE_VIEWING_CATALOG,
MODE_CONFIGURING_PROJECT
} from '../../constants';
import * as SharedStyle from '../../shared-style';
const Icon2D = () => <p style={{
fontSize: '19px',
textDecoration: 'none',
fontWeight: 'bold',
margin: '0px'
}}>2D</p>;
const Icon3D = () => <p style={{
fontSize: '19px',
textDecoration: 'none',
fontWeight: 'bold',
margin: '0px'
}}>3D</p>;
const ASIDE_STYLE = {
backgroundColor: SharedStyle.PRIMARY_COLOR.main,
padding: '10px'
};
const sortButtonsCb = (a, b) => {
if (a.index === undefined || a.index === null) {
a.index = Number.MAX_SAFE_INTEGER;
}
if (b.index === undefined || b.index === null) {
b.index = Number.MAX_SAFE_INTEGER;
}
return a.index - b.index;
};
const mapButtonsCb = (el, ind) => {
return (
<If
key={ind}
condition={el.condition}
style={{position: 'relative'}}
>
{el.dom}
</If>
);
};
export default class Toolbar extends Component {
constructor(props, context) {
super(props, context);
this.state = {};
}
shouldComponentUpdate(nextProps, nextState) {
return this.props.state.mode !== nextProps.state.mode ||
this.props.height !== nextProps.height ||
this.props.width !== nextProps.width;
}
render() {
let {
props: {state, width, height, toolbarButtons, allowProjectFileSupport},
context: {projectActions, viewer3DActions, translator}
} = this;
let mode = state.get('mode');
let sorter = [
{
index: 0, condition: allowProjectFileSupport, dom: <ToolbarButton
active={false}
tooltip={translator.t('New project')}
onClick={event => confirm(translator.t('Would you want to start a new Project?')) ? projectActions.newProject() : null}>
<IconNewFile/>
</ToolbarButton>
},
{
index: 1, condition: allowProjectFileSupport,
dom: <ToolbarSaveButton state={state}/>
},
{
index: 2, condition: allowProjectFileSupport,
dom: <ToolbarLoadButton state={state}/>
},
{
index: 3, condition: true,
dom: <ToolbarButton
active={[MODE_VIEWING_CATALOG].includes(mode)}
tooltip={translator.t('Open catalog')}
onClick={event => projectActions.openCatalog()}>
<IconCatalog/>
</ToolbarButton>
},
{
index: 4, condition: true, dom: <ToolbarButton
active={[MODE_3D_VIEW].includes(mode)}
tooltip={translator.t('3D View')}
onClick={event => viewer3DActions.selectTool3DView()}>
<Icon3D/>
</ToolbarButton>
},
{
index: 5, condition: true, dom: <ToolbarButton
active={[MODE_IDLE].includes(mode)}
tooltip={translator.t('2D View')}
onClick={event => projectActions.rollback()}>
{[MODE_3D_FIRST_PERSON, MODE_3D_VIEW].includes(mode) ? <Icon2D/> : <IconPointer/>}
</ToolbarButton>
},
{
index: 6, condition: true, dom: <ToolbarButton
active={[MODE_3D_FIRST_PERSON].includes(mode)}
tooltip={translator.t('3D First Person')}
onClick={event => viewer3DActions.selectTool3DFirstPerson()}>
<Icon3DFirstPerson/>
</ToolbarButton>
},
{
index: 7, condition: true, dom: <ToolbarButton
active={false}
tooltip={translator.t('Undo (CTRL-Z)')}
onClick={event => projectActions.undo()}>
<IconUndo/>
</ToolbarButton>
},
{
index: 8, condition: true, dom: <ToolbarButton
active={[MODE_CONFIGURING_PROJECT].includes(mode)}
tooltip={translator.t('Configure project')}
onClick={event => projectActions.openProjectConfigurator()}>
<IconConfigure/>
</ToolbarButton>
}
];
sorter = sorter.concat(toolbarButtons.map((Component, key) => {
return Component.prototype ? //if is a react component
{
condition: true,
dom: React.createElement(Component, {mode, state, key})
} :
{ //else is a sortable toolbar button
index: Component.index,
condition: Component.condition,
dom: React.createElement(Component.dom, {mode, state, key})
};
}));
return (
<aside style={{...ASIDE_STYLE, maxWidth: width, maxHeight: height}} className='toolbar'>
{sorter.sort(sortButtonsCb).map(mapButtonsCb)}
</aside>
)
}
}
Toolbar.propTypes = {
state: PropTypes.object.isRequired,
width: PropTypes.number.isRequired,
height: PropTypes.number.isRequired,
allowProjectFileSupport: PropTypes.bool.isRequired,
toolbarButtons: PropTypes.array
};
Toolbar.contextTypes = {
projectActions: PropTypes.object.isRequired,
viewer2DActions: PropTypes.object.isRequired,
viewer3DActions: PropTypes.object.isRequired,
linesActions: PropTypes.object.isRequired,
holesActions: PropTypes.object.isRequired,
itemsActions: PropTypes.object.isRequired,
translator: PropTypes.object.isRequired,
};