react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
213 lines (186 loc) • 8.14 kB
JSX
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import Panel from './panel';
import * as SharedStyle from '../../shared-style';
import {TiPlus, TiDelete} from 'react-icons/ti';
import {FaTrash, FaEye, FaLink, FaUnlink} from 'react-icons/fa';
import { Map } from 'immutable';
import {
MODE_IDLE, MODE_2D_ZOOM_IN, MODE_2D_ZOOM_OUT, MODE_2D_PAN, MODE_3D_VIEW, MODE_3D_FIRST_PERSON,
MODE_WAITING_DRAWING_LINE, MODE_DRAWING_LINE, MODE_DRAWING_HOLE, MODE_DRAWING_ITEM, MODE_DRAGGING_LINE,
MODE_DRAGGING_VERTEX, MODE_DRAGGING_ITEM, MODE_DRAGGING_HOLE, MODE_FITTING_IMAGE, MODE_UPLOADING_IMAGE,
MODE_ROTATING_ITEM
} from '../../constants';
const VISIBILITY_MODE = {
MODE_IDLE, MODE_2D_ZOOM_IN, MODE_2D_ZOOM_OUT, MODE_2D_PAN, MODE_3D_VIEW, MODE_3D_FIRST_PERSON,
MODE_WAITING_DRAWING_LINE, MODE_DRAWING_LINE, MODE_DRAWING_HOLE, MODE_DRAWING_ITEM, MODE_DRAGGING_LINE,
MODE_DRAGGING_VERTEX, MODE_DRAGGING_ITEM, MODE_DRAGGING_HOLE, MODE_FITTING_IMAGE, MODE_UPLOADING_IMAGE,
MODE_ROTATING_ITEM
};
const styleEditButton = {
marginLeft: '5px',
border: '0px',
background: 'none',
color: SharedStyle.COLORS.white,
fontSize: '14px',
outline: '0px'
};
const tablegroupStyle = {
width: '100%',
cursor: 'pointer',
maxHeight: '20em',
padding: '0 1em',
marginLeft: '1px'
};
const iconColStyle = {width: '2em', textAlign: 'center'};
const styleHoverColor = {color: SharedStyle.SECONDARY_COLOR.main};
const styleEditButtonHover = {...styleEditButton, ...styleHoverColor};
const styleAddLabel = {fontSize: '10px', marginLeft: '5px'};
const styleEyeVisible = {fontSize: '1.25em'};
const styleEyeHidden = {...styleEyeVisible, color: '#a5a1a1'};
const newLayerLableStyle = {fontSize: '1.3em', cursor: 'pointer', textAlign: 'center'};
const newLayerLableHoverStyle = {...newLayerLableStyle, ...styleHoverColor};
export default class PanelGroups extends Component {
constructor(props, context) {
super(props, context);
this.state = {
newEmptyHover: false,
newSelectedHover: false
};
}
shouldComponentUpdate(nextProps, nextState) {
return (
this.props.groups.hashCode() !== nextProps.groups.hashCode() ||
this.props.layers.hashCode() !== nextProps.layers.hashCode() ||
this.props.mode !== nextProps.mode
);
}
render() {
let { mode, groups, layers } = this.props;
if (!VISIBILITY_MODE[ mode ]) return null;
return (
<Panel name={this.context.translator.t('Groups')} opened={groups.size > 0}>
{ groups.size ? <table style={tablegroupStyle}>
<thead>
<tr>
<th colSpan="4"></th>
<th>{this.context.translator.t('Elements')}</th>
<th>{this.context.translator.t('Name')}</th>
</tr>
</thead>
<tbody>
{
groups.entrySeq().map(([ groupID, group ]) => {
let selectClick = e => this.context.groupsActions.selectGroup(groupID);
let swapVisibility = e => {
e.stopPropagation();
this.context.groupsActions.setGroupProperties(groupID, new Map({visible: !group.get('visible')}));
};
let chainToGroup = e => {
layers.forEach((layer) => {
let layerID = layer.get('id');
let layerElements = {
'lines': layer.get('lines'),
'items': layer.get('items'),
'holes': layer.get('holes'),
'areas': layer.get('areas')
};
for( let elementPrototype in layerElements )
{
let ElementList = layerElements[elementPrototype];
ElementList.filter( el => el.get('selected') ).forEach( element => {
this.context.groupsActions.addToGroup( groupID, layerID, elementPrototype, element.get('id') );
});
}
});
selectClick(e);
};
let isCurrentgroup = group.get('selected');
let shouldHighlight = isCurrentgroup;
let rowStyle = !shouldHighlight ? null : styleHoverColor;
let dimension = group.get('elements').reduce( ( sum, layer ) => {
return sum + layer.reduce( ( lSum, elProt ) => lSum + elProt.size, 0 );
}, 0);
return (
<tr
key={groupID}
style={rowStyle}
>
<td style={iconColStyle} title={this.context.translator.t('Toggle Group Visibility')}>
<FaEye
onClick={swapVisibility}
style={!group.get('visible') ? styleEyeHidden : styleEyeVisible}
/>
</td>
<td style={iconColStyle} title={this.context.translator.t('Chain selected Elements to Group')}>
<FaLink
onClick={chainToGroup}
style={!shouldHighlight ? styleEditButton : styleEditButtonHover}
/>
</td>
<td style={iconColStyle} title={this.context.translator.t('Un-chain all Group\'s Elements and remove Group')}>
<FaUnlink
onClick={ e => this.context.groupsActions.removeGroup(groupID) }
style={!shouldHighlight ? styleEditButton : styleEditButtonHover}
/>
</td>
<td style={iconColStyle} title={this.context.translator.t('Delete group and all Elements')}>
<FaTrash
onClick={ e => this.context.groupsActions.removeGroupAndDeleteElements(groupID) }
style={!shouldHighlight ? styleEditButton : styleEditButtonHover}
/>
</td>
<td onClick={selectClick} style={{width:'0em', textAlign:'center'}}>
{ dimension }
</td>
<td onClick={selectClick}>
{group.get('name')}
</td>
</tr>
);
})
}
</tbody>
</table> : null }
<table style={{width:'100%', marginTop: '0.1em'}}>
<tbody>
<tr>
<td
style={ !this.state.newEmptyHover ? newLayerLableStyle : newLayerLableHoverStyle }
onMouseOver={ () => this.setState({newEmptyHover: true}) }
onMouseOut={ () => this.setState({newEmptyHover: false}) }
onClick={ e => this.context.groupsActions.addGroup() }
>
<TiPlus />
<b style={styleAddLabel}>{this.context.translator.t('New Empty Group')}</b>
</td>
<td
style={ !this.state.newSelectedHover ? newLayerLableStyle : newLayerLableHoverStyle }
onMouseOver={ () => this.setState({newSelectedHover: true}) }
onMouseOut={ () => this.setState({newSelectedHover: false}) }
onClick={ e => this.context.groupsActions.addGroupFromSelected() }
>
<TiPlus />
<b style={styleAddLabel}>{this.context.translator.t('New Group from selected')}</b>
</td>
</tr>
</tbody>
</table>
</Panel>
)
}
}
PanelGroups.propTypes = {
mode: PropTypes.string.isRequired,
groups: PropTypes.object.isRequired,
layers: PropTypes.object.isRequired
};
PanelGroups.contextTypes = {
catalog: PropTypes.object.isRequired,
translator: PropTypes.object.isRequired,
itemsActions: PropTypes.object.isRequired,
linesActions: PropTypes.object.isRequired,
holesActions: PropTypes.object.isRequired,
groupsActions: PropTypes.object.isRequired,
projectActions: PropTypes.object.isRequired
};