diff --git a/src/components/mode-tools/mode-tools.jsx b/src/components/mode-tools/mode-tools.jsx index c9d4d1b4..ee0ef05f 100644 --- a/src/components/mode-tools/mode-tools.jsx +++ b/src/components/mode-tools/mode-tools.jsx @@ -21,8 +21,8 @@ import pasteIcon from './icons/paste.svg'; import brushIcon from '../brush-mode/brush.svg'; import curvedPointIcon from './icons/curved-point.svg'; import eraserIcon from '../eraser-mode/eraser.svg'; -// import flipHorizontalIcon from './icons/flip-horizontal.svg'; -// import flipVerticalIcon from './icons/flip-vertical.svg'; +import flipHorizontalIcon from './icons/flip-horizontal.svg'; +import flipVerticalIcon from './icons/flip-vertical.svg'; import straightPointIcon from './icons/straight-point.svg'; import {MAX_STROKE_WIDTH} from '../../reducers/stroke-width'; @@ -59,6 +59,16 @@ const ModeToolsComponent = props => { defaultMessage: 'Pointed', description: 'Label for the button that converts selected points to sharp points', id: 'paint.modeTools.pointed' + }, + flipHorizontal: { + defaultMessage: 'Flip Horizontal', + description: 'Label for the button to flip the image horizontally', + id: 'paint.modeTools.flipHorizontal' + }, + flipVertical: { + defaultMessage: 'Flip Vertical', + description: 'Label for the button to flip the image vertically', + id: 'paint.modeTools.flipVertical' } }); @@ -135,18 +145,18 @@ const ModeToolsComponent = props => { onClick={props.onPasteFromClipboard} /> - {/* */} + title={props.intl.formatMessage(messages.flipVertical)} + onClick={props.onFlipVertical} + /> ); default: @@ -170,6 +180,8 @@ ModeToolsComponent.propTypes = { onCopyToClipboard: PropTypes.func.isRequired, onCurvePoints: PropTypes.func.isRequired, onEraserSliderChange: PropTypes.func, + onFlipHorizontal: PropTypes.func.isRequired, + onFlipVertical: PropTypes.func.isRequired, onPasteFromClipboard: PropTypes.func.isRequired, onPointPoints: PropTypes.func.isRequired, selectedItems: PropTypes.arrayOf(PropTypes.instanceOf(paper.Item)) diff --git a/src/containers/mode-tools.jsx b/src/containers/mode-tools.jsx index 7b06fd71..22131329 100644 --- a/src/containers/mode-tools.jsx +++ b/src/containers/mode-tools.jsx @@ -20,6 +20,8 @@ class ModeTools extends React.Component { 'hasSelectedUnpointedPoints', 'handleCopyToClipboard', 'handleCurvePoints', + 'handleFlipHorizontal', + 'handleFlipVertical', 'handlePasteFromClipboard', 'handlePointPoints' ]); @@ -134,6 +136,33 @@ class ModeTools extends React.Component { this.props.onUpdateSvg(); } } + _handleFlip (horizontalScale, verticalScale) { + const selectedItems = getSelectedRootItems(); + // Record old indices + for (const item of selectedItems) { + item.data.index = item.index; + } + + // Group items so that they flip as a unit + const itemGroup = new paper.Group(selectedItems); + // Flip + itemGroup.scale(horizontalScale, verticalScale); + + // Remove flipped item from group and insert at old index. Must insert from bottom index up. + for (let i = 0; i < selectedItems.length; i++) { + itemGroup.layer.insertChild(selectedItems[i].data.index, selectedItems[i]); + selectedItems[i].data.index = null; + } + itemGroup.remove(); + + this.props.onUpdateSvg(); + } + handleFlipHorizontal () { + this._handleFlip(-1, 1); + } + handleFlipVertical () { + this._handleFlip(1, -1); + } handleCopyToClipboard () { const selectedItems = getSelectedRootItems(); if (selectedItems.length > 0) { @@ -171,6 +200,8 @@ class ModeTools extends React.Component { hasSelectedUnpointedPoints={this.hasSelectedUnpointedPoints()} onCopyToClipboard={this.handleCopyToClipboard} onCurvePoints={this.handleCurvePoints} + onFlipHorizontal={this.handleFlipHorizontal} + onFlipVertical={this.handleFlipVertical} onPasteFromClipboard={this.handlePasteFromClipboard} onPointPoints={this.handlePointPoints} />