react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
230 lines (177 loc) • 6.67 kB
JavaScript
import { Layer, Group } from './export';
import {
IDBroker,
NameGenerator
} from '../utils/export';
import { Map, fromJS } from 'immutable';
import {
MODE_IDLE,
MODE_DRAWING_ITEM,
MODE_DRAGGING_ITEM,
MODE_ROTATING_ITEM
} from '../constants';
class Item{
static create( state, layerID, type, x, y, width, height, rotation ) {
let itemID = IDBroker.acquireID();
let item = state.catalog.factoryElement(type, {
id: itemID,
name: NameGenerator.generateName('items', state.catalog.getIn(['elements', type, 'info', 'title'])),
type,
height,
width,
x,
y,
rotation
});
state = state.setIn(['scene', 'layers', layerID, 'items', itemID], item);
return { updatedState: state, item };
}
static select( state, layerID, itemID ){
state = Layer.select( state, layerID ).updatedState;
state = Layer.selectElement( state, layerID, 'items', itemID ).updatedState;
return {updatedState: state};
}
static remove( state, layerID, itemID ) {
state = this.unselect( state, layerID, itemID ).updatedState;
state = Layer.removeElement( state, layerID, 'items', itemID ).updatedState;
state.getIn(['scene', 'groups']).forEach( group => state = Group.removeElement(state, group.id, layerID, 'items', itemID).updatedState );
return { updatedState: state };
}
static unselect( state, layerID, itemID ) {
state = Layer.unselect( state, layerID, 'items', itemID ).updatedState;
return { updatedState: state };
}
static selectToolDrawingItem(state, sceneComponentType) {
state = state.merge({
mode: MODE_DRAWING_ITEM,
drawingSupport: new Map({
type: sceneComponentType
})
});
return { updatedState: state };
}
static updateDrawingItem(state, layerID, x, y) {
if (state.hasIn(['drawingSupport','currentID'])) {
state = state.updateIn(['scene', 'layers', layerID, 'items', state.getIn(['drawingSupport','currentID'])], item => item.merge({x, y}));
}
else {
let { updatedState: stateI, item } = this.create( state, layerID, state.getIn(['drawingSupport','type']), x, y, 200, 100, 0);
state = Item.select( stateI, layerID, item.id ).updatedState;
state = state.setIn(['drawingSupport','currentID'], item.id);
}
return { updatedState: state };
}
static endDrawingItem(state, layerID, x, y) {
let catalog = state.catalog;
state = this.updateDrawingItem(state, layerID, x, y, catalog).updatedState;
state = Layer.unselectAll( state, layerID ).updatedState;
state = state.merge({
drawingSupport: Map({
type: state.drawingSupport.get('type')
})
});
return { updatedState: state };
}
static beginDraggingItem(state, layerID, itemID, x, y) {
let item = state.getIn(['scene', 'layers', layerID, 'items', itemID]);
state = state.merge({
mode: MODE_DRAGGING_ITEM,
draggingSupport: Map({
layerID,
itemID,
startPointX: x,
startPointY: y,
originalX: item.x,
originalY: item.y
})
});
return { updatedState: state };
}
static updateDraggingItem(state, x, y) {
let {draggingSupport, scene} = state;
let layerID = draggingSupport.get('layerID');
let itemID = draggingSupport.get('itemID');
let startPointX = draggingSupport.get('startPointX');
let startPointY = draggingSupport.get('startPointY');
let originalX = draggingSupport.get('originalX');
let originalY = draggingSupport.get('originalY');
let diffX = startPointX - x;
let diffY = startPointY - y;
let item = scene.getIn(['layers', layerID, 'items', itemID]);
item = item.merge({
x: originalX - diffX,
y: originalY - diffY
});
state = state.merge({
scene: scene.mergeIn(['layers', layerID, 'items', itemID], item)
});
return { updatedState: state };
}
static endDraggingItem(state, x, y) {
state = this.updateDraggingItem(state, x, y).updatedState;
state = state.merge({ mode: MODE_IDLE });
return { updatedState: state };
}
static beginRotatingItem(state, layerID, itemID, x, y) {
state = state.merge({
mode: MODE_ROTATING_ITEM,
rotatingSupport: Map({
layerID,
itemID
})
});
return { updatedState: state };
}
static updateRotatingItem(state, x, y) {
let {rotatingSupport, scene} = state;
let layerID = rotatingSupport.get('layerID');
let itemID = rotatingSupport.get('itemID');
let item = state.getIn(['scene', 'layers', layerID, 'items', itemID]);
let deltaX = x - item.x;
let deltaY = y - item.y;
let rotation = Math.atan2(deltaY, deltaX) * 180 / Math.PI - 90;
if (-5 < rotation && rotation < 5) rotation = 0;
if (-95 < rotation && rotation < -85) rotation = -90;
if (-185 < rotation && rotation < -175) rotation = -180;
if (85 < rotation && rotation < 90) rotation = 90;
if (-270 < rotation && rotation < -265) rotation = 90;
item = item.merge({
rotation,
});
state = state.merge({
scene: scene.mergeIn(['layers', layerID, 'items', itemID], item)
});
return { updatedState: state };
}
static endRotatingItem(state, x, y) {
state = this.updateRotatingItem(state, x, y).updatedState;
state = state.merge({ mode: MODE_IDLE });
return { updatedState: state };
}
static setProperties( state, layerID, itemID, properties ) {
state = state.mergeIn(['scene', 'layers', layerID, 'items', itemID, 'properties'], properties);
return { updatedState: state };
}
static setJsProperties( state, layerID, itemID, properties ) {
return this.setProperties( state, layerID, itemID, fromJS(properties) );
}
static updateProperties( state, layerID, itemID, properties) {
properties.forEach( ( v, k ) => {
if( state.hasIn(['scene', 'layers', layerID, 'items', itemID, 'properties', k]) )
state = state.mergeIn(['scene', 'layers', layerID, 'items', itemID, 'properties', k], v);
});
return { updatedState: state };
}
static updateJsProperties( state, layerID, itemID, properties) {
return this.updateProperties( state, layerID, itemID, fromJS(properties) );
}
static setAttributes( state, layerID, itemID, itemAttributes) {
state = state.mergeIn(['scene', 'layers', layerID, 'items', itemID], itemAttributes);
return { updatedState: state };
}
static setJsAttributes( state, layerID, itemID, itemAttributes) {
itemAttributes = fromJS(itemAttributes);
return this.setAttributes(state, layerID, itemID, itemAttributes);
}
}
export { Item as default };