add state to switch tools, and keyboard shortcuts to do so

This commit is contained in:
DD Liu 2017-07-17 18:39:50 -04:00
parent eba604d242
commit 435f00b745
9 changed files with 141 additions and 15 deletions

View file

@ -49,6 +49,7 @@
"react": "15.5.4", "react": "15.5.4",
"react-dom": "15.5.4", "react-dom": "15.5.4",
"react-intl": "2.3.0", "react-intl": "2.3.0",
"react-redux": "5.0.5",
"redux": "3.6.0", "redux": "3.6.0",
"redux-throttle": "0.1.1", "redux-throttle": "0.1.1",
"rimraf": "^2.6.1", "rimraf": "^2.6.1",

View file

@ -1,13 +1,18 @@
import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import PaperCanvas from './paper-canvas.jsx'; import PaperCanvas from '../containers/paper-canvas.jsx';
export default class PaintEditorComponent extends React.Component { const PaintEditorComponent = props => (
render () { <PaperCanvas
return ( tool={props.tool}
<PaperCanvas /> />
); );
}
}
PaintEditorComponent.defaultProps = { PaintEditorComponent.propTypes = {
tool: PropTypes.shape({
name: PropTypes.string.isRequired
})
}; };
module.exports = PaintEditorComponent;

View file

@ -0,0 +1,48 @@
import PropTypes from 'prop-types';
import React from 'react';
import PaintEditorComponent from '../components/paint-editor.jsx';
import tools from '../reducers/tools';
import ToolTypes from '../tools/tool-types.js';
import {connect} from 'react-redux';
class PaintEditor extends React.Component {
componentDidMount () {
const onKeyPress = this.props.onKeyPress;
document.onkeydown = function (e) {
e = e || window.event;
onKeyPress(e);
};
}
render () {
return (
<PaintEditorComponent
tool={this.props.tool}
/>
);
}
}
PaintEditor.propTypes = {
onKeyPress: PropTypes.func.isRequired,
tool: PropTypes.shape({
name: PropTypes.string.isRequired
})
};
const mapStateToProps = state => ({
tool: state.tool
});
const mapDispatchToProps = dispatch => ({
onKeyPress: e => {
if (e.key === 'e') {
dispatch(tools.changeTool(ToolTypes.ERASER));
} else if (e.key === 'b') {
dispatch(tools.changeTool(ToolTypes.BRUSH));
}
}
});
module.exports = connect(
mapStateToProps,
mapDispatchToProps
)(PaintEditor);

View file

@ -1,5 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import paper from 'paper'; import paper from 'paper';
import ToolTypes from '../tools/tool-types.js';
class PaperCanvas extends React.Component { class PaperCanvas extends React.Component {
constructor (props) { constructor (props) {
@ -22,6 +24,11 @@ class PaperCanvas extends React.Component {
// Draw the view now: // Draw the view now:
paper.view.draw(); paper.view.draw();
} }
componentWillReceiveProps (nextProps) {
if (nextProps.tool !== this.props.tool && nextProps.tool instanceof ToolTypes) {
// TODO switch tool
}
}
componentWillUnmount () { componentWillUnmount () {
} }
render () { render () {
@ -31,6 +38,10 @@ class PaperCanvas extends React.Component {
} }
} }
PaperCanvas.propTypes = {}; PaperCanvas.propTypes = {
tool: PropTypes.shape({
name: PropTypes.string.isRequired
})
};
module.exports = PaperCanvas; module.exports = PaperCanvas;

View file

@ -1,3 +1,3 @@
import PaintEditorComponent from './components/paint-editor.jsx'; import PaintEditor from './containers/paint-editor.jsx';
export {PaintEditorComponent as default}; export {PaintEditor as default};

View file

@ -1,9 +1,21 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import PaintEditor from '..'; import PaintEditor from '..';
import {Provider} from 'react-redux';
import {createStore, applyMiddleware} from 'redux';
import throttle from 'redux-throttle';
import reducer from '../reducers/combine-reducers';
const appTarget = document.createElement('div'); const appTarget = document.createElement('div');
document.body.appendChild(appTarget); document.body.appendChild(appTarget);
ReactDOM.render( const store = applyMiddleware(
<PaintEditor />, throttle(300, {leading: true, trailing: true})
appTarget); )(createStore)(
reducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);
ReactDOM.render((
<Provider store={store}>
<PaintEditor />
</Provider>
), appTarget);

View file

@ -0,0 +1,5 @@
import {combineReducers} from 'redux';
module.exports = combineReducers({
tool: require('./tools')
});

32
src/reducers/tools.js Normal file
View file

@ -0,0 +1,32 @@
import ToolTypes from '../tools/tool-types.js';
const CHANGE_TOOL = 'scratch-paint/tools/CHANGE_TOOL';
const initialState = ToolTypes.BRUSH;
const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
switch (action.type) {
case CHANGE_TOOL:
if (action.tool instanceof ToolTypes) {
return action.tool;
}
// TODO switch to minilog
console.warn('Warning: Tool type does not exist: ${action.tool}');
/* falls through */
default:
return state;
}
};
// Action creators ==================================
reducer.changeTool = function (tool) {
return {
type: CHANGE_TOOL,
tool: tool,
meta: {
throttle: 30
}
};
};
module.exports = reducer;

12
src/tools/tool-types.js Normal file
View file

@ -0,0 +1,12 @@
class ToolTypes {
constructor (name) {
this.name = name;
}
toString () {
return `ToolTypes.${this.name}`;
}
}
ToolTypes.BRUSH = new ToolTypes('BRUSH');
ToolTypes.ERASER = new ToolTypes('ERASER');
module.exports = ToolTypes;