mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-22 13:32:28 -05:00
add state to switch tools, and keyboard shortcuts to do so
This commit is contained in:
parent
eba604d242
commit
435f00b745
9 changed files with 141 additions and 15 deletions
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
48
src/containers/paint-editor.jsx
Normal file
48
src/containers/paint-editor.jsx
Normal 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);
|
|
@ -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;
|
|
@ -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};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
5
src/reducers/combine-reducers.js
Normal file
5
src/reducers/combine-reducers.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import {combineReducers} from 'redux';
|
||||||
|
|
||||||
|
module.exports = combineReducers({
|
||||||
|
tool: require('./tools')
|
||||||
|
});
|
32
src/reducers/tools.js
Normal file
32
src/reducers/tools.js
Normal 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
12
src/tools/tool-types.js
Normal 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;
|
Loading…
Reference in a new issue