mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2025-08-28 22:21:12 -04:00
commit
c1010b95fb
3 changed files with 98 additions and 54 deletions
|
@ -1,8 +1,8 @@
|
||||||
|
import paper from '@scratch/paper';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||||
import MediaQuery from 'react-responsive';
|
import MediaQuery from 'react-responsive';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import paper from '@scratch/paper';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import PaperCanvas from '../../containers/paper-canvas.jsx';
|
import PaperCanvas from '../../containers/paper-canvas.jsx';
|
||||||
|
@ -25,7 +25,7 @@ import Label from '../forms/label.jsx';
|
||||||
import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx';
|
import LabeledIconButton from '../labeled-icon-button/labeled-icon-button.jsx';
|
||||||
import LineMode from '../../containers/line-mode.jsx';
|
import LineMode from '../../containers/line-mode.jsx';
|
||||||
import Loupe from '../loupe/loupe.jsx';
|
import Loupe from '../loupe/loupe.jsx';
|
||||||
import ModeToolsComponent from '../mode-tools/mode-tools.jsx';
|
import ModeToolsContainer from '../../containers/mode-tools.jsx';
|
||||||
import OvalMode from '../../containers/oval-mode.jsx';
|
import OvalMode from '../../containers/oval-mode.jsx';
|
||||||
import RectMode from '../../containers/rect-mode.jsx';
|
import RectMode from '../../containers/rect-mode.jsx';
|
||||||
import ReshapeMode from '../../containers/reshape-mode.jsx';
|
import ReshapeMode from '../../containers/reshape-mode.jsx';
|
||||||
|
@ -312,9 +312,8 @@ const PaintEditorComponent = props => {
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
<InputGroup className={styles.modModeTools}>
|
<InputGroup className={styles.modModeTools}>
|
||||||
<ModeToolsComponent
|
<ModeToolsContainer
|
||||||
onCopyToClipboard={props.onCopyToClipboard}
|
onUpdateSvg={props.onUpdateSvg}
|
||||||
onPasteFromClipboard={props.onPasteFromClipboard}
|
|
||||||
/>
|
/>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</div>
|
</div>
|
||||||
|
@ -428,9 +427,7 @@ PaintEditorComponent.propTypes = {
|
||||||
intl: intlShape,
|
intl: intlShape,
|
||||||
isEyeDropping: PropTypes.bool,
|
isEyeDropping: PropTypes.bool,
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
onCopyToClipboard: PropTypes.func.isRequired,
|
|
||||||
onGroup: PropTypes.func.isRequired,
|
onGroup: PropTypes.func.isRequired,
|
||||||
onPasteFromClipboard: PropTypes.func.isRequired,
|
|
||||||
onRedo: PropTypes.func.isRequired,
|
onRedo: PropTypes.func.isRequired,
|
||||||
onSendBackward: PropTypes.func.isRequired,
|
onSendBackward: PropTypes.func.isRequired,
|
||||||
onSendForward: PropTypes.func.isRequired,
|
onSendForward: PropTypes.func.isRequired,
|
||||||
|
|
92
src/containers/mode-tools.jsx
Normal file
92
src/containers/mode-tools.jsx
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
import paper from '@scratch/paper';
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import bindAll from 'lodash.bindall';
|
||||||
|
|
||||||
|
import ModeToolsComponent from '../components/mode-tools/mode-tools.jsx';
|
||||||
|
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
|
||||||
|
import {incrementPasteOffset, setClipboardItems} from '../reducers/clipboard';
|
||||||
|
import {clearSelection, getSelectedLeafItems, getSelectedRootItems} from '../helper/selection';
|
||||||
|
|
||||||
|
class ModeTools extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
bindAll(this, [
|
||||||
|
'handleCopyToClipboard',
|
||||||
|
'handlePasteFromClipboard'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
handleCopyToClipboard () {
|
||||||
|
const selectedItems = getSelectedRootItems();
|
||||||
|
if (selectedItems.length > 0) {
|
||||||
|
const clipboardItems = [];
|
||||||
|
for (let i = 0; i < selectedItems.length; i++) {
|
||||||
|
const jsonItem = selectedItems[i].exportJSON({asString: false});
|
||||||
|
clipboardItems.push(jsonItem);
|
||||||
|
}
|
||||||
|
this.props.setClipboardItems(clipboardItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handlePasteFromClipboard () {
|
||||||
|
clearSelection(this.props.clearSelectedItems);
|
||||||
|
|
||||||
|
if (this.props.clipboardItems.length > 0) {
|
||||||
|
for (let i = 0; i < this.props.clipboardItems.length; i++) {
|
||||||
|
const item = paper.Base.importJSON(this.props.clipboardItems[i]);
|
||||||
|
if (item) {
|
||||||
|
item.selected = true;
|
||||||
|
}
|
||||||
|
const placedItem = paper.project.getActiveLayer().addChild(item);
|
||||||
|
placedItem.position.x += 10 * this.props.pasteOffset;
|
||||||
|
placedItem.position.y += 10 * this.props.pasteOffset;
|
||||||
|
}
|
||||||
|
this.props.incrementPasteOffset();
|
||||||
|
this.props.setSelectedItems();
|
||||||
|
paper.project.view.update();
|
||||||
|
this.props.onUpdateSvg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<ModeToolsComponent
|
||||||
|
onCopyToClipboard={this.handleCopyToClipboard}
|
||||||
|
onPasteFromClipboard={this.handlePasteFromClipboard}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ModeTools.propTypes = {
|
||||||
|
clearSelectedItems: PropTypes.func.isRequired,
|
||||||
|
clipboardItems: PropTypes.arrayOf(PropTypes.array),
|
||||||
|
incrementPasteOffset: PropTypes.func.isRequired,
|
||||||
|
onUpdateSvg: PropTypes.func.isRequired,
|
||||||
|
pasteOffset: PropTypes.number,
|
||||||
|
setClipboardItems: PropTypes.func.isRequired,
|
||||||
|
setSelectedItems: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({
|
||||||
|
clipboardItems: state.scratchPaint.clipboard.items,
|
||||||
|
pasteOffset: state.scratchPaint.clipboard.pasteOffset
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
setClipboardItems: items => {
|
||||||
|
dispatch(setClipboardItems(items));
|
||||||
|
},
|
||||||
|
incrementPasteOffset: () => {
|
||||||
|
dispatch(incrementPasteOffset());
|
||||||
|
},
|
||||||
|
clearSelectedItems: () => {
|
||||||
|
dispatch(clearSelectedItems());
|
||||||
|
},
|
||||||
|
setSelectedItems: () => {
|
||||||
|
dispatch(setSelectedItems(getSelectedLeafItems()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(ModeTools);
|
|
@ -1,3 +1,4 @@
|
||||||
|
import paper from '@scratch/paper';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PaintEditorComponent from '../components/paint-editor/paint-editor.jsx';
|
import PaintEditorComponent from '../components/paint-editor/paint-editor.jsx';
|
||||||
|
@ -5,21 +6,19 @@ import PaintEditorComponent from '../components/paint-editor/paint-editor.jsx';
|
||||||
import {changeMode} from '../reducers/modes';
|
import {changeMode} from '../reducers/modes';
|
||||||
import {undo, redo, undoSnapshot} from '../reducers/undo';
|
import {undo, redo, undoSnapshot} from '../reducers/undo';
|
||||||
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
|
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
|
||||||
import {incrementPasteOffset, setClipboardItems} from '../reducers/clipboard';
|
|
||||||
import {deactivateEyeDropper} from '../reducers/eye-dropper';
|
import {deactivateEyeDropper} from '../reducers/eye-dropper';
|
||||||
|
|
||||||
import {hideGuideLayers, showGuideLayers} from '../helper/layer';
|
import {hideGuideLayers, showGuideLayers} from '../helper/layer';
|
||||||
import {performUndo, performRedo, performSnapshot, shouldShowUndo, shouldShowRedo} from '../helper/undo';
|
import {performUndo, performRedo, performSnapshot, shouldShowUndo, shouldShowRedo} from '../helper/undo';
|
||||||
import {bringToFront, sendBackward, sendToBack, bringForward} from '../helper/order';
|
import {bringToFront, sendBackward, sendToBack, bringForward} from '../helper/order';
|
||||||
import {groupSelection, ungroupSelection} from '../helper/group';
|
import {groupSelection, ungroupSelection} from '../helper/group';
|
||||||
import {clearSelection, getSelectedLeafItems, getSelectedRootItems} from '../helper/selection';
|
import {getSelectedLeafItems} from '../helper/selection';
|
||||||
import {resetZoom, zoomOnSelection} from '../helper/view';
|
import {resetZoom, zoomOnSelection} from '../helper/view';
|
||||||
import EyeDropperTool from '../helper/tools/eye-dropper';
|
import EyeDropperTool from '../helper/tools/eye-dropper';
|
||||||
|
|
||||||
import Modes from '../lib/modes';
|
import Modes from '../lib/modes';
|
||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import bindAll from 'lodash.bindall';
|
import bindAll from 'lodash.bindall';
|
||||||
import paper from '@scratch/paper';
|
|
||||||
|
|
||||||
class PaintEditor extends React.Component {
|
class PaintEditor extends React.Component {
|
||||||
static get ZOOM_INCREMENT () {
|
static get ZOOM_INCREMENT () {
|
||||||
|
@ -39,8 +38,6 @@ class PaintEditor extends React.Component {
|
||||||
'handleUngroup',
|
'handleUngroup',
|
||||||
'canRedo',
|
'canRedo',
|
||||||
'canUndo',
|
'canUndo',
|
||||||
'handleCopyToClipboard',
|
|
||||||
'handlePasteFromClipboard',
|
|
||||||
'onMouseDown',
|
'onMouseDown',
|
||||||
'setCanvas',
|
'setCanvas',
|
||||||
'startEyeDroppingLoop',
|
'startEyeDroppingLoop',
|
||||||
|
@ -118,36 +115,6 @@ class PaintEditor extends React.Component {
|
||||||
handleSendToFront () {
|
handleSendToFront () {
|
||||||
bringToFront(this.handleUpdateSvg);
|
bringToFront(this.handleUpdateSvg);
|
||||||
}
|
}
|
||||||
handleCopyToClipboard () {
|
|
||||||
const selectedItems = getSelectedRootItems();
|
|
||||||
if (selectedItems.length > 0) {
|
|
||||||
const clipboardItems = [];
|
|
||||||
for (let i = 0; i < selectedItems.length; i++) {
|
|
||||||
const jsonItem = selectedItems[i].exportJSON({asString: false});
|
|
||||||
clipboardItems.push(jsonItem);
|
|
||||||
}
|
|
||||||
this.props.setClipboardItems(clipboardItems);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handlePasteFromClipboard () {
|
|
||||||
clearSelection(this.props.clearSelectedItems);
|
|
||||||
|
|
||||||
if (this.props.clipboardItems.length > 0) {
|
|
||||||
for (let i = 0; i < this.props.clipboardItems.length; i++) {
|
|
||||||
const item = paper.Base.importJSON(this.props.clipboardItems[i]);
|
|
||||||
if (item) {
|
|
||||||
item.selected = true;
|
|
||||||
}
|
|
||||||
const placedItem = paper.project.getActiveLayer().addChild(item);
|
|
||||||
placedItem.position.x += 10 * this.props.pasteOffset;
|
|
||||||
placedItem.position.y += 10 * this.props.pasteOffset;
|
|
||||||
}
|
|
||||||
this.props.incrementPasteOffset();
|
|
||||||
this.props.setSelectedItems();
|
|
||||||
paper.project.view.update();
|
|
||||||
this.handleUpdateSvg();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
canUndo () {
|
canUndo () {
|
||||||
return shouldShowUndo(this.props.undoState);
|
return shouldShowUndo(this.props.undoState);
|
||||||
}
|
}
|
||||||
|
@ -239,9 +206,7 @@ class PaintEditor extends React.Component {
|
||||||
setCanvas={this.setCanvas}
|
setCanvas={this.setCanvas}
|
||||||
svg={this.props.svg}
|
svg={this.props.svg}
|
||||||
svgId={this.props.svgId}
|
svgId={this.props.svgId}
|
||||||
onCopyToClipboard={this.handleCopyToClipboard}
|
|
||||||
onGroup={this.handleGroup}
|
onGroup={this.handleGroup}
|
||||||
onPasteFromClipboard={this.handlePasteFromClipboard}
|
|
||||||
onRedo={this.handleRedo}
|
onRedo={this.handleRedo}
|
||||||
onSendBackward={this.handleSendBackward}
|
onSendBackward={this.handleSendBackward}
|
||||||
onSendForward={this.handleSendForward}
|
onSendForward={this.handleSendForward}
|
||||||
|
@ -262,8 +227,6 @@ class PaintEditor extends React.Component {
|
||||||
PaintEditor.propTypes = {
|
PaintEditor.propTypes = {
|
||||||
changeColorToEyeDropper: PropTypes.func,
|
changeColorToEyeDropper: PropTypes.func,
|
||||||
clearSelectedItems: PropTypes.func.isRequired,
|
clearSelectedItems: PropTypes.func.isRequired,
|
||||||
clipboardItems: PropTypes.arrayOf(PropTypes.array),
|
|
||||||
incrementPasteOffset: PropTypes.func.isRequired,
|
|
||||||
isEyeDropping: PropTypes.bool,
|
isEyeDropping: PropTypes.bool,
|
||||||
name: PropTypes.string,
|
name: PropTypes.string,
|
||||||
onDeactivateEyeDropper: PropTypes.func.isRequired,
|
onDeactivateEyeDropper: PropTypes.func.isRequired,
|
||||||
|
@ -272,14 +235,12 @@ PaintEditor.propTypes = {
|
||||||
onUndo: PropTypes.func.isRequired,
|
onUndo: PropTypes.func.isRequired,
|
||||||
onUpdateName: PropTypes.func.isRequired,
|
onUpdateName: PropTypes.func.isRequired,
|
||||||
onUpdateSvg: PropTypes.func.isRequired,
|
onUpdateSvg: PropTypes.func.isRequired,
|
||||||
pasteOffset: PropTypes.number,
|
|
||||||
previousTool: PropTypes.shape({ // paper.Tool
|
previousTool: PropTypes.shape({ // paper.Tool
|
||||||
activate: PropTypes.func.isRequired,
|
activate: PropTypes.func.isRequired,
|
||||||
remove: PropTypes.func.isRequired
|
remove: PropTypes.func.isRequired
|
||||||
}),
|
}),
|
||||||
rotationCenterX: PropTypes.number,
|
rotationCenterX: PropTypes.number,
|
||||||
rotationCenterY: PropTypes.number,
|
rotationCenterY: PropTypes.number,
|
||||||
setClipboardItems: PropTypes.func.isRequired,
|
|
||||||
setSelectedItems: PropTypes.func.isRequired,
|
setSelectedItems: PropTypes.func.isRequired,
|
||||||
svg: PropTypes.string,
|
svg: PropTypes.string,
|
||||||
svgId: PropTypes.string,
|
svgId: PropTypes.string,
|
||||||
|
@ -326,12 +287,6 @@ const mapDispatchToProps = dispatch => ({
|
||||||
undoSnapshot: snapshot => {
|
undoSnapshot: snapshot => {
|
||||||
dispatch(undoSnapshot(snapshot));
|
dispatch(undoSnapshot(snapshot));
|
||||||
},
|
},
|
||||||
setClipboardItems: items => {
|
|
||||||
dispatch(setClipboardItems(items));
|
|
||||||
},
|
|
||||||
incrementPasteOffset: () => {
|
|
||||||
dispatch(incrementPasteOffset());
|
|
||||||
},
|
|
||||||
onDeactivateEyeDropper: () => {
|
onDeactivateEyeDropper: () => {
|
||||||
// set redux values to default for eye dropper reducer
|
// set redux values to default for eye dropper reducer
|
||||||
dispatch(deactivateEyeDropper());
|
dispatch(deactivateEyeDropper());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue