diff --git a/src/components/mode-tools/mode-tools.jsx b/src/components/mode-tools/mode-tools.jsx index 9aa4942696..a3055f1d18 100644 --- a/src/components/mode-tools/mode-tools.jsx +++ b/src/components/mode-tools/mode-tools.jsx @@ -7,6 +7,7 @@ import {changeBrushSize} from '../../reducers/brush-mode'; import {changeBrushSize as changeEraserSize} from '../../reducers/eraser-mode'; import {changeBitBrushSize} from '../../reducers/bit-brush-size'; import {changeBitEraserSize} from '../../reducers/bit-eraser-size'; +import {changeRectRadius} from '../../reducers/rect-mode'; import {setShapesFilled} from '../../reducers/fill-bitmap-shapes'; import FontDropdown from '../../containers/font-dropdown.jsx'; @@ -33,6 +34,7 @@ import curvedPointIcon from '!../../tw-recolor/build!./icons/curved-point.svg'; import eraserIcon from '../eraser-mode/eraser.svg'; import flipHorizontalIcon from '!../../tw-recolor/build!./icons/flip-horizontal.svg'; import flipVerticalIcon from '!../../tw-recolor/build!./icons/flip-vertical.svg'; +import roundRectIcon from '../rounded-rect-mode/rounded-rectangle.svg'; import straightPointIcon from '!../../tw-recolor/build!./icons/straight-point.svg'; import bitOvalIcon from '../bit-oval-mode/oval.svg'; import bitRectIcon from '../bit-rect-mode/rectangle.svg'; @@ -54,6 +56,11 @@ const ModeToolsComponent = props => { description: 'Label for the eraser size input', id: 'paint.modeTools.eraserSize' }, + rectRadius: { + defaultMessage: 'Corner radius', + description: 'Label for the corner radius input', + id: 'paint.modeTools.rectRadius' + }, copy: { defaultMessage: 'Copy', description: 'Label for the copy button', @@ -140,6 +147,34 @@ const ModeToolsComponent = props => { ); } + case Modes.RECT: + { + // to do: use reducers + const currentIcon = roundRectIcon; + const currentRadiusValue = props.rectRadius; + const changeFunction = props.onRectRadiusSliderChange; + return ( +
+
+ {props.intl.formatMessage(messages.rectRadius)} +
+ +
+ ); + } case Modes.BIT_ERASER: /* falls through */ case Modes.ERASER: @@ -314,6 +349,7 @@ ModeToolsComponent.propTypes = { className: PropTypes.string, clipboardItems: PropTypes.arrayOf(PropTypes.array), eraserValue: PropTypes.number, + rectRadius: PropTypes.number, fillBitmapShapes: PropTypes.bool, format: PropTypes.oneOf(Object.keys(Formats)), hasSelectedUncurvedPoints: PropTypes.bool, @@ -323,6 +359,7 @@ ModeToolsComponent.propTypes = { onBitBrushSliderChange: PropTypes.func.isRequired, onBitEraserSliderChange: PropTypes.func.isRequired, onBrushSliderChange: PropTypes.func.isRequired, + onRectRadiusSliderChange: PropTypes.func, onCopyToClipboard: PropTypes.func.isRequired, onCurvePoints: PropTypes.func.isRequired, onDelete: PropTypes.func.isRequired, @@ -345,7 +382,8 @@ const mapStateToProps = state => ({ bitEraserSize: state.scratchPaint.bitEraserSize, brushValue: state.scratchPaint.brushMode.brushSize, clipboardItems: state.scratchPaint.clipboard.items, - eraserValue: state.scratchPaint.eraserMode.brushSize + eraserValue: state.scratchPaint.eraserMode.brushSize, + rectRadius: state.scratchPaint.rectMode.rectRadius }); const mapDispatchToProps = dispatch => ({ onBrushSliderChange: brushSize => { @@ -360,6 +398,9 @@ const mapDispatchToProps = dispatch => ({ onEraserSliderChange: eraserSize => { dispatch(changeEraserSize(eraserSize)); }, + onRectRadiusSliderChange: rectRadius => { + dispatch(changeRectRadius(rectRadius)); + }, onFillShapes: () => { dispatch(setShapesFilled(true)); }, diff --git a/src/containers/rect-mode.jsx b/src/containers/rect-mode.jsx index 872316b17e..0357cc5105 100644 --- a/src/containers/rect-mode.jsx +++ b/src/containers/rect-mode.jsx @@ -10,6 +10,7 @@ import GradientTypes from '../lib/gradient-types'; import {changeFillColor, clearFillGradient, DEFAULT_COLOR} from '../reducers/fill-style'; import {changeStrokeColor, clearStrokeGradient} from '../reducers/stroke-style'; +import {changeRectRadius} from '../reducers/rect-mode'; import {changeMode} from '../reducers/modes'; import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items'; import {setCursor} from '../reducers/cursor'; @@ -36,6 +37,9 @@ class RectMode extends React.Component { if (this.tool && nextProps.colorState !== this.props.colorState) { this.tool.setColorState(nextProps.colorState); } + if (this.tool && nextProps.rectRadius !== this.props.rectRadius) { + this.tool.setRectRadius(nextProps.rectRadius); + } if (this.tool && nextProps.selectedItems !== this.props.selectedItems) { this.tool.onSelectionChanged(nextProps.selectedItems); } @@ -65,6 +69,7 @@ class RectMode extends React.Component { this.props.onUpdateImage ); this.tool.setColorState(this.props.colorState); + this.tool.setRectRadius(this.props.rectRadius); this.tool.activate(); } validateColorState () { // TODO move to shared class @@ -140,7 +145,10 @@ RectMode.propTypes = { isRectModeActive: PropTypes.bool.isRequired, onChangeFillColor: PropTypes.func.isRequired, onChangeStrokeColor: PropTypes.func.isRequired, + // eslint-disable-next-line react/no-unused-prop-types + onChangeRectRadius: PropTypes.func.isRequired, onUpdateImage: PropTypes.func.isRequired, + rectRadius: PropTypes.number, selectedItems: PropTypes.arrayOf(PropTypes.instanceOf(paper.Item)), setCursor: PropTypes.func.isRequired, setSelectedItems: PropTypes.func.isRequired @@ -148,6 +156,7 @@ RectMode.propTypes = { const mapStateToProps = state => ({ colorState: state.scratchPaint.color, + rectRadius: state.scratchPaint.rectMode.rectRadius, isRectModeActive: state.scratchPaint.mode === Modes.RECT, selectedItems: state.scratchPaint.selectedItems }); @@ -175,6 +184,9 @@ const mapDispatchToProps = dispatch => ({ }, onChangeStrokeColor: strokeColor => { dispatch(changeStrokeColor(strokeColor)); + }, + onChangeRectRadius: rectRadius => { + dispatch(changeRectRadius(rectRadius)); } }); diff --git a/src/helper/tools/rect-tool.js b/src/helper/tools/rect-tool.js index 3bd84a0a25..2d90800073 100644 --- a/src/helper/tools/rect-tool.js +++ b/src/helper/tools/rect-tool.js @@ -46,6 +46,7 @@ class RectTool extends paper.Tool { this.colorState = null; this.isBoundingBoxMode = null; this.active = false; + this.rectRadius = 16; } getHitOptions () { return { @@ -60,6 +61,9 @@ class RectTool extends paper.Tool { tolerance: RectTool.TOLERANCE / paper.view.zoom }; } + setRectRadius (rectRadius) { + this.rectRadius = rectRadius; + } /** * Should be called if the selection changes to update the bounds of the bounding box. * @param {Array} selectedItems Array of selected items. @@ -100,7 +104,7 @@ class RectTool extends paper.Tool { rect.size = squareDimensions.size.abs(); } - this.rect = new paper.Path.Rectangle(rect); + this.rect = new paper.Path.Rectangle(rect, this.rectRadius); if (event.modifiers.alt) { this.rect.position = event.downPoint; } else if (event.modifiers.shift) { diff --git a/src/reducers/rect-mode.js b/src/reducers/rect-mode.js new file mode 100644 index 0000000000..5b3796e2a5 --- /dev/null +++ b/src/reducers/rect-mode.js @@ -0,0 +1,31 @@ +import log from '../log/log'; + +const CHANGE_RECT_RADIUS = 'scratch-paint/rect-mode/CHANGE_RECT_RADIUS'; +const initialState = {rectRadius: 0}; + +const reducer = function (state, action) { + if (typeof state === 'undefined') state = initialState; + switch (action.type) { + case CHANGE_RECT_RADIUS: + if (isNaN(action.rectRadius)) { + log.warn(`Invalid corner radius: ${action.rectRadius}`); + return state; + } + return {rectRadius: Math.max(1, action.rectRadius)}; + default: + return state; + } +}; + +// Action creators ================================== +const changeRectRadius = function (rectRadius) { + return { + type: CHANGE_RECT_RADIUS, + rectRadius: rectRadius + }; +}; + +export { + reducer as default, + changeRectRadius +}; diff --git a/src/reducers/scratch-paint-reducer.js b/src/reducers/scratch-paint-reducer.js index 3dc9be3308..cff5d33498 100644 --- a/src/reducers/scratch-paint-reducer.js +++ b/src/reducers/scratch-paint-reducer.js @@ -15,6 +15,7 @@ import formatReducer from './format'; import hoverReducer from './hover'; import layoutReducer from './layout'; import modalsReducer from './modals'; +import rectModeReducer from './rect-mode'; import selectedItemReducer from './selected-items'; import textEditTargetReducer from './text-edit-target'; import themeReducer from './theme'; @@ -39,6 +40,7 @@ export default combineReducers({ hoveredItemId: hoverReducer, layout: layoutReducer, modals: modalsReducer, + rectMode: rectModeReducer, selectedItems: selectedItemReducer, textEditTarget: textEditTargetReducer, theme: themeReducer,