Doodle3D-Core/src/components/App.js

221 lines
5.8 KiB
JavaScript
Raw Normal View History

2017-11-15 00:46:02 +01:00
import React from 'react';
import PropTypes from 'proptypes';
import injectSheet from 'react-jss';
import { connect } from 'react-redux';
2017-11-23 15:56:04 +01:00
import * as actions from '../actions/index.js';
2017-11-15 00:46:02 +01:00
import Logo from './Logo.js';
import D2Panel from './D2Panel.js';
import D3Panel from './D3Panel.js';
import SketcherToolbars from './SketcherToolbars.js';
2017-11-15 15:13:49 +01:00
import Button from './Button.js';
import vlineImageURL from '../../img/vline.png';
import btnUndoImageURL from '../../img/mainmenu/btnUndo.png';
import btnRedoImageURL from '../../img/mainmenu/btnRedo.png';
import InlineIconsLoader from './InlineIconsLoader.js';
2017-11-23 16:07:54 +01:00
import JSONToSketchData from '../shape/JSONToSketchData.js';
2017-12-14 10:59:06 +01:00
import keycode from 'keycode';
import bowser from 'bowser';
import * as d2Tools from '../constants/d2Tools.js';
2018-02-21 11:54:25 +01:00
import { isLoaded, load } from '../utils/loaded.js';
2017-11-15 00:46:02 +01:00
const styles = {
container: {
2017-11-15 15:13:49 +01:00
position: 'relative',
userSelect: 'none',
2017-11-15 00:46:02 +01:00
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
height: '100%'
},
appContainer: {
flexGrow: 1,
display: 'flex',
alignItems: 'stretch',
overflow: 'hidden'
},
vLine: {
backgroundSize: '14px auto',
backgroundImage: `url('${vlineImageURL}')`,
width: '28px'
},
undoMenu: {
display: 'flex',
position: 'absolute',
top: 0,
left: '50%',
marginLeft: '-68px'
},
undo: {
cursor: 'pointer',
backgroundSize: '68px auto',
width: '68px',
height: '58px',
backgroundImage: `url('${btnUndoImageURL}')`
},
redo: {
cursor: 'pointer',
backgroundSize: '71px auto',
width: '71px',
height: '58px',
backgroundImage: `url('${btnRedoImageURL}')`
}
};
class App extends React.Component {
static propTypes = {
2017-11-23 15:56:04 +01:00
openSketch: PropTypes.func.isRequired,
addImage: PropTypes.func.isRequired,
2017-11-15 00:46:02 +01:00
undo: PropTypes.func.isRequired,
redo: PropTypes.func.isRequired,
2017-12-14 10:59:06 +01:00
classes: PropTypes.objectOf(PropTypes.string),
deleteSelection: PropTypes.func.isRequired,
selectAll: PropTypes.func.isRequired,
d2ChangeTool: PropTypes.func.isRequired,
moveSelection: PropTypes.func.isRequired,
selectedPen: PropTypes.string.isRequired
2017-11-15 00:46:02 +01:00
};
2018-02-21 11:54:25 +01:00
state = {
loaded: isLoaded()
};
2017-11-23 15:56:04 +01:00
componentDidMount() {
const { container } = this.refs;
2018-02-21 11:54:25 +01:00
if (!this.state.loaded) load.then(() => this.setState({ loaded: true }));
2017-11-23 15:56:04 +01:00
container.addEventListener('dragover', event => event.preventDefault());
container.addEventListener('drop', this.onDrop);
2017-12-14 10:59:06 +01:00
window.addEventListener('keydown', this.onKeyDown);
}
componentWillUnmount() {
const { container } = this.refs;
container.removeEventListener('drop', this.onDrop);
window.removeEventListener('keydown', this.onKeyDown);
2017-11-23 15:56:04 +01:00
}
onDrop = async event => {
const { openSketch, addImage } = this.props;
event.preventDefault();
for (const file of event.dataTransfer.files) {
2017-12-13 17:25:42 +01:00
const extentions = file.name.split('.').pop();
2017-11-23 15:56:04 +01:00
2017-12-13 17:25:42 +01:00
switch (extentions.toUpperCase()) {
2017-11-23 15:56:04 +01:00
case 'D3SKETCH':
case 'JSON':
const url = URL.createObjectURL(file);
const json = await fetch(url).then(result => result.json());
const data = await JSONToSketchData(json);
openSketch({ data });
2017-11-23 15:56:04 +01:00
break;
case 'JPG':
case 'JPEG':
case 'PNG':
case 'GIF':
await addImage(file);
break;
default:
break;
}
}
};
2017-12-14 10:59:06 +01:00
onKeyDown = (event) => {
const { undo, redo, deleteSelection, selectAll, d2ChangeTool, moveSelection, selectedPen } = this.props;
const { metaKey, ctrlKey, shiftKey } = event;
const key = keycode(event);
const commandKey = bowser.mac ? metaKey : ctrlKey;
const targetTag = event.target.tagName.toLowerCase();
if (targetTag === 'input' || targetTag === 'textarea') return;
switch (key) {
case 'backspace':
case 'delete':
event.preventDefault();
deleteSelection();
break;
case 'a':
if (commandKey) selectAll();
break;
case 'z':
if (commandKey) {
if (shiftKey) {
redo();
} else {
undo();
}
}
break;
case 't': {
if (!commandKey) d2ChangeTool(d2Tools.TEXT);
break;
}
case 'b': {
if (!commandKey) d2ChangeTool(selectedPen);
break;
}
case 'left':
case 'right':
case 'up':
case 'down': {
const delta = shiftKey ? 10 : 1;
const deltas = {
left: { deltaX: -delta, deltaY: 0 },
right: { deltaX: delta, deltaY: 0 },
up: { deltaX: 0, deltaY: -delta },
down: { deltaX: 0, deltaY: delta }
};
const { deltaX, deltaY } = deltas[key];
moveSelection(deltaX, deltaY);
}
default:
break;
}
2017-11-23 15:56:04 +01:00
}
2017-11-15 00:46:02 +01:00
render() {
const { classes, undo, redo } = this.props;
2018-02-21 11:54:25 +01:00
const { loaded } = this.state;
2017-11-15 00:46:02 +01:00
return (
2017-11-23 15:56:04 +01:00
<div ref="container" className={classes.container}>
<InlineIconsLoader />
2018-02-21 11:54:25 +01:00
{loaded && <div className={classes.appContainer}>
2017-11-15 00:46:02 +01:00
<D2Panel />
<div className={classes.vLine} />
<D3Panel />
2018-02-21 11:54:25 +01:00
</div>}
2017-11-15 00:46:02 +01:00
<Logo />
<div className={classes.undoMenu}>
2017-11-15 15:13:49 +01:00
<Button onSelect={undo} className={classes.undo} />
<Button onSelect={redo} className={classes.redo} />
2017-11-15 00:46:02 +01:00
</div>
2017-11-15 15:13:49 +01:00
<SketcherToolbars />
2017-11-15 00:46:02 +01:00
</div>
);
}
}
2017-12-14 10:59:06 +01:00
export default injectSheet(styles)(connect(state => ({
selectedPen: state.sketcher.present.menus['pen-tools'].selected
}), {
2017-11-15 00:46:02 +01:00
undo: actions.undo.undo,
2017-11-23 15:56:04 +01:00
redo: actions.undo.redo,
openSketch: actions.openSketch,
2017-12-14 10:59:06 +01:00
addImage: actions.addImage,
deleteSelection: actions.deleteSelection,
selectAll: actions.selectAll,
d2ChangeTool: actions.d2ChangeTool,
moveSelection: actions.moveSelection
2017-11-15 00:46:02 +01:00
})(App));