mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-22 21:42:30 -05:00
Wire up stroke gradient controls
* Abstract FillColorIndicator and StrokeColorIndicator to ColorIndicator * Replace stroke color reducer with stroke style reducer * Add color style proptype * Clear stroke gradient in line mode
This commit is contained in:
parent
a23fabd778
commit
6094953ef4
17 changed files with 338 additions and 398 deletions
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Popover from 'react-popover';
|
||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
import ColorButton from './color-button/color-button.jsx';
|
||||
import ColorPicker from '../containers/color-picker.jsx';
|
||||
|
@ -10,15 +9,7 @@ import Label from './forms/label.jsx';
|
|||
|
||||
import GradientTypes from '../lib/gradient-types';
|
||||
|
||||
const messages = defineMessages({
|
||||
fill: {
|
||||
id: 'paint.paintEditor.fill',
|
||||
description: 'Label for the color picker for the fill color',
|
||||
defaultMessage: 'Fill'
|
||||
}
|
||||
});
|
||||
|
||||
const FillColorIndicatorComponent = props => (
|
||||
const ColorIndicatorComponent = props => (
|
||||
<InputGroup
|
||||
className={props.className}
|
||||
disabled={props.disabled}
|
||||
|
@ -26,45 +17,47 @@ const FillColorIndicatorComponent = props => (
|
|||
<Popover
|
||||
body={
|
||||
<ColorPicker
|
||||
color={props.fillColor}
|
||||
color2={props.fillColor2}
|
||||
color={props.color}
|
||||
color2={props.color2}
|
||||
gradientType={props.gradientType}
|
||||
shouldShowGradientTools={props.shouldShowGradientTools}
|
||||
onChangeColor={props.onChangeFillColor}
|
||||
onChangeColor={props.onChangeColor}
|
||||
onChangeGradientType={props.onChangeGradientType}
|
||||
onSwap={props.onSwap}
|
||||
/>
|
||||
}
|
||||
isOpen={props.fillColorModalVisible}
|
||||
isOpen={props.colorModalVisible}
|
||||
preferPlace="below"
|
||||
onOuterAction={props.onCloseFillColor}
|
||||
onOuterAction={props.onCloseColor}
|
||||
>
|
||||
<Label text={props.intl.formatMessage(messages.fill)}>
|
||||
<Label text={props.label}>
|
||||
<ColorButton
|
||||
color={props.fillColor}
|
||||
color2={props.fillColor2}
|
||||
color={props.color}
|
||||
color2={props.color2}
|
||||
gradientType={props.gradientType}
|
||||
onClick={props.onOpenFillColor}
|
||||
onClick={props.onOpenColor}
|
||||
outline={props.outline}
|
||||
/>
|
||||
</Label>
|
||||
</Popover>
|
||||
</InputGroup>
|
||||
);
|
||||
|
||||
FillColorIndicatorComponent.propTypes = {
|
||||
ColorIndicatorComponent.propTypes = {
|
||||
className: PropTypes.string,
|
||||
disabled: PropTypes.bool.isRequired,
|
||||
fillColor: PropTypes.string,
|
||||
fillColor2: PropTypes.string,
|
||||
fillColorModalVisible: PropTypes.bool.isRequired,
|
||||
color: PropTypes.string,
|
||||
color2: PropTypes.string,
|
||||
colorModalVisible: PropTypes.bool.isRequired,
|
||||
gradientType: PropTypes.oneOf(Object.keys(GradientTypes)).isRequired,
|
||||
intl: intlShape,
|
||||
onChangeFillColor: PropTypes.func.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
onChangeColor: PropTypes.func.isRequired,
|
||||
onChangeGradientType: PropTypes.func.isRequired,
|
||||
onCloseFillColor: PropTypes.func.isRequired,
|
||||
onOpenFillColor: PropTypes.func.isRequired,
|
||||
onCloseColor: PropTypes.func.isRequired,
|
||||
onOpenColor: PropTypes.func.isRequired,
|
||||
onSwap: PropTypes.func.isRequired,
|
||||
outline: PropTypes.bool.isRequired,
|
||||
shouldShowGradientTools: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default injectIntl(FillColorIndicatorComponent);
|
||||
export default ColorIndicatorComponent;
|
|
@ -1,65 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Popover from 'react-popover';
|
||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
import ColorButton from './color-button/color-button.jsx';
|
||||
import ColorPicker from '../containers/color-picker.jsx';
|
||||
import InputGroup from './input-group/input-group.jsx';
|
||||
import Label from './forms/label.jsx';
|
||||
import GradientTypes from '../lib/gradient-types';
|
||||
|
||||
const messages = defineMessages({
|
||||
stroke: {
|
||||
id: 'paint.paintEditor.stroke',
|
||||
description: 'Label for the color picker for the outline color',
|
||||
defaultMessage: 'Outline'
|
||||
}
|
||||
});
|
||||
|
||||
const StrokeColorIndicatorComponent = props => (
|
||||
<InputGroup
|
||||
className={props.className}
|
||||
disabled={props.disabled}
|
||||
>
|
||||
<Popover
|
||||
body={
|
||||
<ColorPicker
|
||||
color={props.strokeColor}
|
||||
color2={null}
|
||||
gradientType={GradientTypes.SOLID}
|
||||
shouldShowGradientTools={false}
|
||||
// @todo handle stroke gradient
|
||||
onChangeColor={props.onChangeStrokeColor}
|
||||
/>
|
||||
}
|
||||
isOpen={props.strokeColorModalVisible}
|
||||
preferPlace="below"
|
||||
onOuterAction={props.onCloseStrokeColor}
|
||||
>
|
||||
<Label text={props.intl.formatMessage(messages.stroke)}>
|
||||
<ColorButton
|
||||
outline
|
||||
color={props.strokeColor}
|
||||
color2={null}
|
||||
gradientType={GradientTypes.SOLID}
|
||||
// @todo handle stroke gradient
|
||||
onClick={props.onOpenStrokeColor}
|
||||
/>
|
||||
</Label>
|
||||
</Popover>
|
||||
</InputGroup>
|
||||
);
|
||||
|
||||
StrokeColorIndicatorComponent.propTypes = {
|
||||
className: PropTypes.string,
|
||||
disabled: PropTypes.bool.isRequired,
|
||||
intl: intlShape,
|
||||
onChangeStrokeColor: PropTypes.func.isRequired,
|
||||
onCloseStrokeColor: PropTypes.func.isRequired,
|
||||
onOpenStrokeColor: PropTypes.func.isRequired,
|
||||
strokeColor: PropTypes.string,
|
||||
strokeColorModalVisible: PropTypes.bool.isRequired
|
||||
};
|
||||
|
||||
export default injectIntl(StrokeColorIndicatorComponent);
|
|
@ -3,6 +3,7 @@ import React from 'react';
|
|||
import {connect} from 'react-redux';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import Modes from '../lib/modes';
|
||||
import ColorStyleProptype from '../lib/color-style-proptype';
|
||||
import Blobbiness from '../helper/blob-tools/blob';
|
||||
import {MIXED} from '../helper/style-path';
|
||||
|
||||
|
@ -38,7 +39,7 @@ class BrushMode extends React.Component {
|
|||
this.blob.setOptions({
|
||||
isEraser: false,
|
||||
fillColor: fillColor.primary,
|
||||
strokeColor,
|
||||
strokeColor: strokeColor.primary,
|
||||
strokeWidth,
|
||||
...nextProps.brushModeState
|
||||
});
|
||||
|
@ -88,11 +89,8 @@ BrushMode.propTypes = {
|
|||
clearGradient: PropTypes.func.isRequired,
|
||||
clearSelectedItems: PropTypes.func.isRequired,
|
||||
colorState: PropTypes.shape({
|
||||
fillColor: PropTypes.shape({
|
||||
primary: PropTypes.string,
|
||||
secondary: PropTypes.string
|
||||
}),
|
||||
strokeColor: PropTypes.string,
|
||||
fillColor: ColorStyleProptype,
|
||||
strokeColor: ColorStyleProptype,
|
||||
strokeWidth: PropTypes.number
|
||||
}).isRequired,
|
||||
handleMouseDown: PropTypes.func.isRequired,
|
||||
|
|
156
src/containers/color-indicator.jsx
Normal file
156
src/containers/color-indicator.jsx
Normal file
|
@ -0,0 +1,156 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import parseColor from 'parse-color';
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
import {getSelectedLeafItems} from '../helper/selection';
|
||||
import Formats from '../lib/format';
|
||||
import {isBitmap} from '../lib/format';
|
||||
import GradientTypes from '../lib/gradient-types';
|
||||
|
||||
import ColorIndicatorComponent from '../components/color-indicator.jsx';
|
||||
import {applyColorToSelection,
|
||||
applyGradientTypeToSelection,
|
||||
applyStrokeWidthToSelection,
|
||||
getRotatedColor,
|
||||
swapColorsInSelection,
|
||||
MIXED} from '../helper/style-path';
|
||||
|
||||
const makeColorIndicator = (label, isStroke) => {
|
||||
class ColorIndicator extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'handleChangeColor',
|
||||
'handleChangeGradientType',
|
||||
'handleCloseColor',
|
||||
'handleSwap'
|
||||
]);
|
||||
|
||||
// Flag to track whether an svg-update-worthy change has been made
|
||||
this._hasChanged = false;
|
||||
}
|
||||
componentWillReceiveProps (newProps) {
|
||||
const {colorModalVisible, onUpdateImage} = this.props;
|
||||
if (colorModalVisible && !newProps.colorModalVisible) {
|
||||
// Submit the new SVG, which also stores a single undo/redo action.
|
||||
if (this._hasChanged) onUpdateImage();
|
||||
this._hasChanged = false;
|
||||
}
|
||||
}
|
||||
handleChangeColor (newColor) {
|
||||
// Stroke-selector-specific logic: if we change the stroke color from "none" to something visible, ensure
|
||||
// there's a nonzero stroke width. If we change the stroke color to "none", set the stroke width to zero.
|
||||
if (isStroke) {
|
||||
if (this.props.color === null && newColor !== null) {
|
||||
this._hasChanged = applyStrokeWidthToSelection(1, this.props.textEditTarget) || this._hasChanged;
|
||||
this.props.onChangeStrokeWidth(1);
|
||||
} else if (this.props.color !== null && newColor === null) {
|
||||
this._hasChanged = applyStrokeWidthToSelection(0, this.props.textEditTarget) || this._hasChanged;
|
||||
this.props.onChangeStrokeWidth(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply color and update redux, but do not update svg until picker closes.
|
||||
const isDifferent = applyColorToSelection(
|
||||
newColor,
|
||||
this.props.colorIndex,
|
||||
this.props.gradientType === GradientTypes.SOLID,
|
||||
isBitmap(this.props.format),
|
||||
isStroke,
|
||||
this.props.textEditTarget);
|
||||
this._hasChanged = this._hasChanged || isDifferent;
|
||||
this.props.onChangeColor(newColor, this.props.colorIndex);
|
||||
}
|
||||
handleChangeGradientType (gradientType) {
|
||||
// Apply color and update redux, but do not update svg until picker closes.
|
||||
const isDifferent = applyGradientTypeToSelection(
|
||||
gradientType,
|
||||
isBitmap(this.props.format),
|
||||
isStroke,
|
||||
this.props.textEditTarget);
|
||||
this._hasChanged = this._hasChanged || isDifferent;
|
||||
const hasSelectedItems = getSelectedLeafItems().length > 0;
|
||||
if (hasSelectedItems) {
|
||||
if (isDifferent) {
|
||||
// Recalculates the swatch colors
|
||||
this.props.setSelectedItems();
|
||||
}
|
||||
}
|
||||
if (this.props.gradientType === GradientTypes.SOLID && gradientType !== GradientTypes.SOLID) {
|
||||
// Generate color 2 and change to the 2nd swatch when switching from solid to gradient
|
||||
if (!hasSelectedItems) {
|
||||
this.props.onChangeColor(getRotatedColor(this.props.color), 1);
|
||||
}
|
||||
this.props.onChangeColorIndex(1);
|
||||
}
|
||||
if (this.props.onChangeGradientType) this.props.onChangeGradientType(gradientType);
|
||||
}
|
||||
handleCloseColor () {
|
||||
// If the eyedropper is currently being used, don't
|
||||
// close the color menu.
|
||||
if (this.props.isEyeDropping) return;
|
||||
|
||||
// Otherwise, close the color menu and
|
||||
// also reset the color index to indicate
|
||||
// that `color1` is selected.
|
||||
this.props.onCloseColor();
|
||||
this.props.onChangeColorIndex(0);
|
||||
}
|
||||
handleSwap () {
|
||||
if (getSelectedLeafItems().length) {
|
||||
const isDifferent = swapColorsInSelection(
|
||||
isBitmap(this.props.format),
|
||||
isStroke,
|
||||
this.props.textEditTarget);
|
||||
this.props.setSelectedItems();
|
||||
this._hasChanged = this._hasChanged || isDifferent;
|
||||
} else {
|
||||
let color1 = this.props.color;
|
||||
let color2 = this.props.color2;
|
||||
color1 = color1 === null || color1 === MIXED ? color1 : parseColor(color1).hex;
|
||||
color2 = color2 === null || color2 === MIXED ? color2 : parseColor(color2).hex;
|
||||
this.props.onChangeColor(color1, 1);
|
||||
this.props.onChangeColor(color2, 0);
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<ColorIndicatorComponent
|
||||
{...this.props}
|
||||
label={this.props.intl.formatMessage(label)}
|
||||
outline={isStroke}
|
||||
onChangeColor={this.handleChangeColor}
|
||||
onChangeGradientType={this.handleChangeGradientType}
|
||||
onCloseColor={this.handleCloseColor}
|
||||
onSwap={this.handleSwap}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ColorIndicator.propTypes = {
|
||||
colorIndex: PropTypes.number.isRequired,
|
||||
disabled: PropTypes.bool.isRequired,
|
||||
color: PropTypes.string,
|
||||
color2: PropTypes.string,
|
||||
colorModalVisible: PropTypes.bool.isRequired,
|
||||
format: PropTypes.oneOf(Object.keys(Formats)),
|
||||
gradientType: PropTypes.oneOf(Object.keys(GradientTypes)).isRequired,
|
||||
intl: intlShape,
|
||||
isEyeDropping: PropTypes.bool.isRequired,
|
||||
onChangeColorIndex: PropTypes.func.isRequired,
|
||||
onChangeColor: PropTypes.func.isRequired,
|
||||
onChangeGradientType: PropTypes.func,
|
||||
onChangeStrokeWidth: PropTypes.func,
|
||||
onCloseColor: PropTypes.func.isRequired,
|
||||
onUpdateImage: PropTypes.func.isRequired,
|
||||
setSelectedItems: PropTypes.func.isRequired,
|
||||
textEditTarget: PropTypes.number
|
||||
};
|
||||
|
||||
return injectIntl(ColorIndicator);
|
||||
};
|
||||
|
||||
export default makeColorIndicator;
|
|
@ -1,8 +1,5 @@
|
|||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import parseColor from 'parse-color';
|
||||
import {defineMessages} from 'react-intl';
|
||||
|
||||
import {changeColorIndex} from '../reducers/color-index';
|
||||
import {changeFillColor, changeFillColor2} from '../reducers/fill-style';
|
||||
|
@ -11,121 +8,26 @@ import {openFillColor, closeFillColor} from '../reducers/modals';
|
|||
import {getSelectedLeafItems} from '../helper/selection';
|
||||
import {setSelectedItems} from '../reducers/selected-items';
|
||||
import Modes from '../lib/modes';
|
||||
import Formats from '../lib/format';
|
||||
import {isBitmap} from '../lib/format';
|
||||
import GradientTypes from '../lib/gradient-types';
|
||||
|
||||
import FillColorIndicatorComponent from '../components/fill-color-indicator.jsx';
|
||||
import {applyColorToSelection,
|
||||
applyGradientTypeToSelection,
|
||||
getRotatedColor,
|
||||
swapColorsInSelection,
|
||||
MIXED} from '../helper/style-path';
|
||||
import makeColorIndicator from './color-indicator.jsx';
|
||||
|
||||
class FillColorIndicator extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'handleChangeFillColor',
|
||||
'handleChangeGradientType',
|
||||
'handleCloseFillColor',
|
||||
'handleSwap'
|
||||
]);
|
||||
const messages = defineMessages({
|
||||
label: {
|
||||
id: 'paint.paintEditor.fill',
|
||||
description: 'Label for the color picker for the fill color',
|
||||
defaultMessage: 'Fill'
|
||||
}
|
||||
});
|
||||
|
||||
// Flag to track whether an svg-update-worthy change has been made
|
||||
this._hasChanged = false;
|
||||
}
|
||||
componentWillReceiveProps (newProps) {
|
||||
const {fillColorModalVisible, onUpdateImage} = this.props;
|
||||
if (fillColorModalVisible && !newProps.fillColorModalVisible) {
|
||||
// Submit the new SVG, which also stores a single undo/redo action.
|
||||
if (this._hasChanged) onUpdateImage();
|
||||
this._hasChanged = false;
|
||||
}
|
||||
}
|
||||
handleChangeFillColor (newColor) {
|
||||
// Apply color and update redux, but do not update svg until picker closes.
|
||||
const isDifferent = applyColorToSelection(
|
||||
newColor,
|
||||
this.props.colorIndex,
|
||||
this.props.gradientType === GradientTypes.SOLID,
|
||||
isBitmap(this.props.format),
|
||||
false, // applyToStroke
|
||||
this.props.textEditTarget);
|
||||
this._hasChanged = this._hasChanged || isDifferent;
|
||||
this.props.onChangeFillColor(newColor, this.props.colorIndex);
|
||||
}
|
||||
handleChangeGradientType (gradientType) {
|
||||
// Apply color and update redux, but do not update svg until picker closes.
|
||||
const isDifferent = applyGradientTypeToSelection(
|
||||
gradientType,
|
||||
isBitmap(this.props.format),
|
||||
false, // applyToStroke
|
||||
this.props.textEditTarget);
|
||||
this._hasChanged = this._hasChanged || isDifferent;
|
||||
const hasSelectedItems = getSelectedLeafItems().length > 0;
|
||||
if (hasSelectedItems) {
|
||||
if (isDifferent) {
|
||||
// Recalculates the swatch colors
|
||||
this.props.setSelectedItems();
|
||||
}
|
||||
}
|
||||
if (this.props.gradientType === GradientTypes.SOLID && gradientType !== GradientTypes.SOLID) {
|
||||
// Generate color 2 and change to the 2nd swatch when switching from solid to gradient
|
||||
if (!hasSelectedItems) {
|
||||
this.props.onChangeFillColor(getRotatedColor(this.props.fillColor), 1);
|
||||
}
|
||||
this.props.onChangeColorIndex(1);
|
||||
}
|
||||
this.props.onChangeGradientType(gradientType);
|
||||
}
|
||||
handleCloseFillColor () {
|
||||
// If the eyedropper is currently being used, don't
|
||||
// close the fill color menu.
|
||||
if (this.props.isEyeDropping) return;
|
||||
|
||||
// Otherwise, close the fill color menu and
|
||||
// also reset the color index to indicate
|
||||
// that `color1` is selected.
|
||||
this.props.onCloseFillColor();
|
||||
this.props.onChangeColorIndex(0);
|
||||
}
|
||||
handleSwap () {
|
||||
if (getSelectedLeafItems().length) {
|
||||
const isDifferent = swapColorsInSelection(
|
||||
isBitmap(this.props.format),
|
||||
false, // applyToStroke
|
||||
this.props.textEditTarget);
|
||||
this.props.setSelectedItems();
|
||||
this._hasChanged = this._hasChanged || isDifferent;
|
||||
} else {
|
||||
let color1 = this.props.fillColor;
|
||||
let color2 = this.props.fillColor2;
|
||||
color1 = color1 === null || color1 === MIXED ? color1 : parseColor(color1).hex;
|
||||
color2 = color2 === null || color2 === MIXED ? color2 : parseColor(color2).hex;
|
||||
this.props.onChangeFillColor(color1, 1);
|
||||
this.props.onChangeFillColor(color2, 0);
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<FillColorIndicatorComponent
|
||||
{...this.props}
|
||||
onChangeFillColor={this.handleChangeFillColor}
|
||||
onChangeGradientType={this.handleChangeGradientType}
|
||||
onCloseFillColor={this.handleCloseFillColor}
|
||||
onSwap={this.handleSwap}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
const FillColorIndicator = makeColorIndicator(messages.label, false);
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
colorIndex: state.scratchPaint.fillMode.colorIndex,
|
||||
disabled: state.scratchPaint.mode === Modes.LINE,
|
||||
fillColor: state.scratchPaint.color.fillColor.primary,
|
||||
fillColor2: state.scratchPaint.color.fillColor.secondary,
|
||||
fillColorModalVisible: state.scratchPaint.modals.fillColor,
|
||||
color: state.scratchPaint.color.fillColor.primary,
|
||||
color2: state.scratchPaint.color.fillColor.secondary,
|
||||
colorModalVisible: state.scratchPaint.modals.fillColor,
|
||||
format: state.scratchPaint.format,
|
||||
gradientType: state.scratchPaint.color.fillColor.gradientType,
|
||||
isEyeDropping: state.scratchPaint.color.eyeDropper.active,
|
||||
|
@ -142,17 +44,17 @@ const mapDispatchToProps = dispatch => ({
|
|||
onChangeColorIndex: index => {
|
||||
dispatch(changeColorIndex(index));
|
||||
},
|
||||
onChangeFillColor: (fillColor, index) => {
|
||||
onChangeColor: (fillColor, index) => {
|
||||
if (index === 0) {
|
||||
dispatch(changeFillColor(fillColor));
|
||||
} else if (index === 1) {
|
||||
dispatch(changeFillColor2(fillColor));
|
||||
}
|
||||
},
|
||||
onOpenFillColor: () => {
|
||||
onOpenColor: () => {
|
||||
dispatch(openFillColor());
|
||||
},
|
||||
onCloseFillColor: () => {
|
||||
onCloseColor: () => {
|
||||
dispatch(closeFillColor());
|
||||
},
|
||||
onChangeGradientType: gradientType => {
|
||||
|
@ -163,24 +65,6 @@ const mapDispatchToProps = dispatch => ({
|
|||
}
|
||||
});
|
||||
|
||||
FillColorIndicator.propTypes = {
|
||||
colorIndex: PropTypes.number.isRequired,
|
||||
disabled: PropTypes.bool.isRequired,
|
||||
fillColor: PropTypes.string,
|
||||
fillColor2: PropTypes.string,
|
||||
fillColorModalVisible: PropTypes.bool.isRequired,
|
||||
format: PropTypes.oneOf(Object.keys(Formats)),
|
||||
gradientType: PropTypes.oneOf(Object.keys(GradientTypes)).isRequired,
|
||||
isEyeDropping: PropTypes.bool.isRequired,
|
||||
onChangeColorIndex: PropTypes.func.isRequired,
|
||||
onChangeFillColor: PropTypes.func.isRequired,
|
||||
onChangeGradientType: PropTypes.func.isRequired,
|
||||
onCloseFillColor: PropTypes.func.isRequired,
|
||||
onUpdateImage: PropTypes.func.isRequired,
|
||||
setSelectedItems: PropTypes.func.isRequired,
|
||||
textEditTarget: PropTypes.number
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
|
|
|
@ -4,11 +4,12 @@ import React from 'react';
|
|||
import {connect} from 'react-redux';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import Modes from '../lib/modes';
|
||||
import ColorStyleProptype from '../lib/color-style-proptype';
|
||||
import {clearSelection} from '../helper/selection';
|
||||
import {endPointHit, touching} from '../helper/snapping';
|
||||
import {drawHitPoint, removeHitPoint} from '../helper/guides';
|
||||
import {stylePath} from '../helper/style-path';
|
||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||
import {changeStrokeColor, clearStrokeGradient} from '../reducers/stroke-style';
|
||||
import {changeStrokeWidth} from '../reducers/stroke-width';
|
||||
import {changeMode} from '../reducers/modes';
|
||||
import {clearSelectedItems} from '../reducers/selected-items';
|
||||
|
@ -58,9 +59,10 @@ class LineMode extends React.Component {
|
|||
}
|
||||
activateTool () {
|
||||
clearSelection(this.props.clearSelectedItems);
|
||||
this.props.clearGradient();
|
||||
|
||||
// Force the default line color if stroke is MIXED or transparent
|
||||
const {strokeColor} = this.props.colorState;
|
||||
const strokeColor = this.props.colorState.strokeColor.primary;
|
||||
if (strokeColor === MIXED || strokeColor === null) {
|
||||
this.props.onChangeStrokeColor(LineMode.DEFAULT_COLOR);
|
||||
}
|
||||
|
@ -101,7 +103,7 @@ class LineMode extends React.Component {
|
|||
this.hitResult = endPointHit(event.point, LineMode.SNAP_TOLERANCE);
|
||||
if (this.hitResult) {
|
||||
this.path = this.hitResult.path;
|
||||
stylePath(this.path, this.props.colorState.strokeColor, this.props.colorState.strokeWidth);
|
||||
stylePath(this.path, this.props.colorState.strokeColor.primary, this.props.colorState.strokeWidth);
|
||||
if (this.hitResult.isFirst) {
|
||||
this.path.reverse();
|
||||
}
|
||||
|
@ -114,7 +116,7 @@ class LineMode extends React.Component {
|
|||
if (!this.path) {
|
||||
this.path = new paper.Path();
|
||||
this.path.strokeCap = 'round';
|
||||
stylePath(this.path, this.props.colorState.strokeColor, this.props.colorState.strokeWidth);
|
||||
stylePath(this.path, this.props.colorState.strokeColor.primary, this.props.colorState.strokeWidth);
|
||||
|
||||
this.path.add(event.point);
|
||||
this.path.add(event.point); // Add second point, which is what will move when dragged
|
||||
|
@ -253,13 +255,11 @@ class LineMode extends React.Component {
|
|||
}
|
||||
|
||||
LineMode.propTypes = {
|
||||
clearGradient: PropTypes.func.isRequired,
|
||||
clearSelectedItems: PropTypes.func.isRequired,
|
||||
colorState: PropTypes.shape({
|
||||
fillColor: PropTypes.shape({
|
||||
primary: PropTypes.string,
|
||||
secondary: PropTypes.string
|
||||
}),
|
||||
strokeColor: PropTypes.string,
|
||||
fillColor: ColorStyleProptype,
|
||||
strokeColor: ColorStyleProptype,
|
||||
strokeWidth: PropTypes.number
|
||||
}).isRequired,
|
||||
handleMouseDown: PropTypes.func.isRequired,
|
||||
|
@ -274,6 +274,9 @@ const mapStateToProps = state => ({
|
|||
isLineModeActive: state.scratchPaint.mode === Modes.LINE
|
||||
});
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
clearGradient: () => {
|
||||
dispatch(clearStrokeGradient());
|
||||
},
|
||||
clearSelectedItems: () => {
|
||||
dispatch(clearSelectedItems());
|
||||
},
|
||||
|
|
|
@ -4,10 +4,11 @@ import React from 'react';
|
|||
import {connect} from 'react-redux';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import Modes from '../lib/modes';
|
||||
import ColorStyleProptype from '../lib/color-style-proptype';
|
||||
import {MIXED} from '../helper/style-path';
|
||||
|
||||
import {changeFillColor, clearFillGradient, DEFAULT_COLOR} from '../reducers/fill-style';
|
||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||
import {changeStrokeColor} from '../reducers/stroke-style';
|
||||
import {changeMode} from '../reducers/modes';
|
||||
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
|
||||
import {setCursor} from '../reducers/cursor';
|
||||
|
@ -57,8 +58,9 @@ class OvalMode extends React.Component {
|
|||
// If fill and stroke color are both mixed/transparent/absent, set fill to default and stroke to transparent.
|
||||
// If exactly one of fill or stroke color is set, set the other one to transparent.
|
||||
// This way the tool won't draw an invisible state, or be unclear about what will be drawn.
|
||||
const {strokeColor, strokeWidth} = this.props.colorState;
|
||||
const {strokeWidth} = this.props.colorState;
|
||||
const fillColor = this.props.colorState.fillColor.primary;
|
||||
const strokeColor = this.props.colorState.strokeColor.primary;
|
||||
const fillColorPresent = fillColor !== MIXED && fillColor !== null;
|
||||
const strokeColorPresent =
|
||||
strokeColor !== MIXED && strokeColor !== null && strokeWidth !== null && strokeWidth !== 0;
|
||||
|
@ -98,11 +100,8 @@ OvalMode.propTypes = {
|
|||
clearGradient: PropTypes.func.isRequired,
|
||||
clearSelectedItems: PropTypes.func.isRequired,
|
||||
colorState: PropTypes.shape({
|
||||
fillColor: PropTypes.shape({
|
||||
primary: PropTypes.string,
|
||||
secondary: PropTypes.string
|
||||
}),
|
||||
strokeColor: PropTypes.string,
|
||||
fillColor: ColorStyleProptype,
|
||||
strokeColor: ColorStyleProptype,
|
||||
strokeWidth: PropTypes.number
|
||||
}).isRequired,
|
||||
handleMouseDown: PropTypes.func.isRequired,
|
||||
|
|
|
@ -4,10 +4,11 @@ import React from 'react';
|
|||
import {connect} from 'react-redux';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import Modes from '../lib/modes';
|
||||
import ColorStyleProptype from '../lib/color-style-proptype';
|
||||
import {MIXED} from '../helper/style-path';
|
||||
|
||||
import {changeFillColor, clearFillGradient, DEFAULT_COLOR} from '../reducers/fill-style';
|
||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||
import {changeStrokeColor} from '../reducers/stroke-style';
|
||||
import {changeMode} from '../reducers/modes';
|
||||
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
|
||||
import {setCursor} from '../reducers/cursor';
|
||||
|
@ -57,8 +58,9 @@ class RectMode extends React.Component {
|
|||
// If fill and stroke color are both mixed/transparent/absent, set fill to default and stroke to transparent.
|
||||
// If exactly one of fill or stroke color is set, set the other one to transparent.
|
||||
// This way the tool won't draw an invisible state, or be unclear about what will be drawn.
|
||||
const {strokeColor, strokeWidth} = this.props.colorState;
|
||||
const {strokeWidth} = this.props.colorState;
|
||||
const fillColor = this.props.colorState.fillColor.primary;
|
||||
const strokeColor = this.props.colorState.strokeColor.primary;
|
||||
const fillColorPresent = fillColor !== MIXED && fillColor !== null;
|
||||
const strokeColorPresent =
|
||||
strokeColor !== MIXED && strokeColor !== null && strokeWidth !== null && strokeWidth !== 0;
|
||||
|
@ -98,11 +100,8 @@ RectMode.propTypes = {
|
|||
clearGradient: PropTypes.func.isRequired,
|
||||
clearSelectedItems: PropTypes.func.isRequired,
|
||||
colorState: PropTypes.shape({
|
||||
fillColor: PropTypes.shape({
|
||||
primary: PropTypes.string,
|
||||
secondary: PropTypes.string
|
||||
}),
|
||||
strokeColor: PropTypes.string,
|
||||
fillColor: ColorStyleProptype,
|
||||
strokeColor: ColorStyleProptype,
|
||||
strokeWidth: PropTypes.number
|
||||
}).isRequired,
|
||||
handleMouseDown: PropTypes.func.isRequired,
|
||||
|
|
|
@ -1,109 +1,73 @@
|
|||
import {connect} from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||
import {defineMessages} from 'react-intl';
|
||||
|
||||
import {changeColorIndex} from '../reducers/color-index';
|
||||
import {changeStrokeColor, changeStrokeColor2} from '../reducers/stroke-style';
|
||||
import {changeStrokeWidth} from '../reducers/stroke-width';
|
||||
import {changeStrokeGradientType} from '../reducers/stroke-style';
|
||||
import {openStrokeColor, closeStrokeColor} from '../reducers/modals';
|
||||
import {getSelectedLeafItems} from '../helper/selection';
|
||||
import {setSelectedItems} from '../reducers/selected-items';
|
||||
import Modes from '../lib/modes';
|
||||
import Formats from '../lib/format';
|
||||
import {isBitmap} from '../lib/format';
|
||||
|
||||
import StrokeColorIndicatorComponent from '../components/stroke-color-indicator.jsx';
|
||||
import {applyColorToSelection, applyStrokeWidthToSelection} from '../helper/style-path';
|
||||
import makeColorIndicator from './color-indicator.jsx';
|
||||
|
||||
class StrokeColorIndicator extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'handleChangeStrokeColor',
|
||||
'handleCloseStrokeColor'
|
||||
]);
|
||||
const messages = defineMessages({
|
||||
label: {
|
||||
id: 'paint.paintEditor.stroke',
|
||||
description: 'Label for the color picker for the outline color',
|
||||
defaultMessage: 'Outline'
|
||||
}
|
||||
});
|
||||
|
||||
// Flag to track whether an svg-update-worthy change has been made
|
||||
this._hasChanged = false;
|
||||
}
|
||||
componentWillReceiveProps (newProps) {
|
||||
const {strokeColorModalVisible, onUpdateImage} = this.props;
|
||||
if (strokeColorModalVisible && !newProps.strokeColorModalVisible) {
|
||||
// Submit the new SVG, which also stores a single undo/redo action.
|
||||
if (this._hasChanged) onUpdateImage();
|
||||
this._hasChanged = false;
|
||||
}
|
||||
}
|
||||
handleChangeStrokeColor (newColor) {
|
||||
if (this.props.strokeColor === null && newColor !== null) {
|
||||
this._hasChanged = applyStrokeWidthToSelection(1, this.props.textEditTarget) || this._hasChanged;
|
||||
this.props.onChangeStrokeWidth(1);
|
||||
} else if (this.props.strokeColor !== null && newColor === null) {
|
||||
this._hasChanged = applyStrokeWidthToSelection(0, this.props.textEditTarget) || this._hasChanged;
|
||||
this.props.onChangeStrokeWidth(0);
|
||||
}
|
||||
// Apply color and update redux, but do not update svg until picker closes.
|
||||
this._hasChanged = applyColorToSelection(
|
||||
newColor,
|
||||
0, // colorIndex,
|
||||
true, // isSolidGradient
|
||||
isBitmap(this.props.format),
|
||||
true, // applyToStroke
|
||||
this.props.textEditTarget) ||
|
||||
this._hasChanged;
|
||||
this.props.onChangeStrokeColor(newColor);
|
||||
}
|
||||
handleCloseStrokeColor () {
|
||||
if (!this.props.isEyeDropping) {
|
||||
this.props.onCloseStrokeColor();
|
||||
}
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
<StrokeColorIndicatorComponent
|
||||
{...this.props}
|
||||
onChangeStrokeColor={this.handleChangeStrokeColor}
|
||||
onCloseStrokeColor={this.handleCloseStrokeColor}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
const StrokeColorIndicator = makeColorIndicator(messages.label, true);
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
colorIndex: state.scratchPaint.fillMode.colorIndex,
|
||||
disabled: state.scratchPaint.mode === Modes.BRUSH ||
|
||||
state.scratchPaint.mode === Modes.TEXT ||
|
||||
state.scratchPaint.mode === Modes.FILL,
|
||||
color: state.scratchPaint.color.strokeColor.primary,
|
||||
color2: state.scratchPaint.color.strokeColor.secondary,
|
||||
colorModalVisible: state.scratchPaint.modals.strokeColor,
|
||||
format: state.scratchPaint.format,
|
||||
gradientType: state.scratchPaint.color.strokeColor.gradientType,
|
||||
isEyeDropping: state.scratchPaint.color.eyeDropper.active,
|
||||
strokeColor: state.scratchPaint.color.strokeColor,
|
||||
strokeColorModalVisible: state.scratchPaint.modals.strokeColor,
|
||||
mode: state.scratchPaint.mode,
|
||||
shouldShowGradientTools: state.scratchPaint.mode === Modes.SELECT ||
|
||||
state.scratchPaint.mode === Modes.RESHAPE,
|
||||
textEditTarget: state.scratchPaint.textEditTarget
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onChangeStrokeColor: strokeColor => {
|
||||
onChangeColorIndex: index => {
|
||||
dispatch(changeColorIndex(index));
|
||||
},
|
||||
onChangeColor: (strokeColor, index) => {
|
||||
if (index === 0) {
|
||||
dispatch(changeStrokeColor(strokeColor));
|
||||
} else if (index === 1) {
|
||||
dispatch(changeStrokeColor2(strokeColor));
|
||||
}
|
||||
},
|
||||
onChangeStrokeWidth: strokeWidth => {
|
||||
dispatch(changeStrokeWidth(strokeWidth));
|
||||
},
|
||||
onOpenStrokeColor: () => {
|
||||
onOpenColor: () => {
|
||||
dispatch(openStrokeColor());
|
||||
},
|
||||
onCloseStrokeColor: () => {
|
||||
onCloseColor: () => {
|
||||
dispatch(closeStrokeColor());
|
||||
},
|
||||
onChangeGradientType: gradientType => {
|
||||
dispatch(changeStrokeGradientType(gradientType));
|
||||
},
|
||||
setSelectedItems: format => {
|
||||
dispatch(setSelectedItems(getSelectedLeafItems(), isBitmap(format)));
|
||||
}
|
||||
});
|
||||
|
||||
StrokeColorIndicator.propTypes = {
|
||||
format: PropTypes.oneOf(Object.keys(Formats)),
|
||||
isEyeDropping: PropTypes.bool.isRequired,
|
||||
onChangeStrokeColor: PropTypes.func.isRequired,
|
||||
onChangeStrokeWidth: PropTypes.func.isRequired,
|
||||
onCloseStrokeColor: PropTypes.func.isRequired,
|
||||
onUpdateImage: PropTypes.func.isRequired,
|
||||
strokeColor: PropTypes.string,
|
||||
strokeColorModalVisible: PropTypes.bool.isRequired,
|
||||
textEditTarget: PropTypes.number
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
import bindAll from 'lodash.bindall';
|
||||
import parseColor from 'parse-color';
|
||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||
import {changeStrokeColor} from '../reducers/stroke-style';
|
||||
import {changeStrokeWidth} from '../reducers/stroke-width';
|
||||
import StrokeWidthIndicatorComponent from '../components/stroke-width-indicator.jsx';
|
||||
import {getSelectedLeafItems} from '../helper/selection';
|
||||
|
|
|
@ -5,11 +5,12 @@ import {connect} from 'react-redux';
|
|||
import bindAll from 'lodash.bindall';
|
||||
import Fonts from '../lib/fonts';
|
||||
import Modes from '../lib/modes';
|
||||
import ColorStyleProptype from '../lib/color-style-proptype';
|
||||
import {MIXED} from '../helper/style-path';
|
||||
|
||||
import {changeFont} from '../reducers/font';
|
||||
import {changeFillColor, clearFillGradient, DEFAULT_COLOR} from '../reducers/fill-style';
|
||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||
import {changeStrokeColor} from '../reducers/stroke-style';
|
||||
import {changeMode} from '../reducers/modes';
|
||||
import {setTextEditTarget} from '../reducers/text-edit-target';
|
||||
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
|
||||
|
@ -81,8 +82,9 @@ class TextMode extends React.Component {
|
|||
// If fill and stroke color are both mixed/transparent/absent, set fill to default and stroke to transparent.
|
||||
// If exactly one of fill or stroke color is set, set the other one to transparent.
|
||||
// This way the tool won't draw an invisible state, or be unclear about what will be drawn.
|
||||
const {strokeColor, strokeWidth} = nextProps.colorState;
|
||||
const fillColor = this.props.colorState.fillColor.primary;
|
||||
const {strokeWidth} = nextProps.colorState;
|
||||
const fillColor = nextProps.colorState.fillColor.primary;
|
||||
const strokeColor = nextProps.colorState.strokeColor.primary;
|
||||
const fillColorPresent = fillColor !== MIXED && fillColor !== null;
|
||||
const strokeColorPresent = nextProps.isBitmap ? false :
|
||||
strokeColor !== MIXED && strokeColor !== null && strokeWidth !== null && strokeWidth !== 0;
|
||||
|
@ -143,11 +145,8 @@ TextMode.propTypes = {
|
|||
clearGradient: PropTypes.func.isRequired,
|
||||
clearSelectedItems: PropTypes.func.isRequired,
|
||||
colorState: PropTypes.shape({
|
||||
fillColor: PropTypes.shape({
|
||||
primary: PropTypes.string,
|
||||
secondary: PropTypes.string
|
||||
}),
|
||||
strokeColor: PropTypes.string,
|
||||
fillColor: ColorStyleProptype,
|
||||
strokeColor: ColorStyleProptype,
|
||||
strokeWidth: PropTypes.number
|
||||
}).isRequired,
|
||||
font: PropTypes.string,
|
||||
|
|
|
@ -516,10 +516,6 @@ const getColorsFromSelection = function (selectedItems, bitmapMode) {
|
|||
};
|
||||
}
|
||||
|
||||
// Treat stroke gradients as MIXED
|
||||
// TODO: remove this once stroke gradients are supported
|
||||
if (selectionStrokeGradientType !== GradientTypes.SOLID) selectionStrokeColorString = MIXED;
|
||||
|
||||
return {
|
||||
fillColor: selectionFillColorString ? selectionFillColorString : null,
|
||||
fillColor2: selectionFillColor2String ? selectionFillColor2String : null,
|
||||
|
@ -566,7 +562,7 @@ const styleCursorPreview = function (path, options) {
|
|||
// TODO: style using gradient?
|
||||
const styleShape = function (path, options) {
|
||||
path.fillColor = options.fillColor.primary;
|
||||
path.strokeColor = options.strokeColor;
|
||||
path.strokeColor = options.strokeColor.primary;
|
||||
path.strokeWidth = options.strokeWidth;
|
||||
};
|
||||
|
||||
|
|
9
src/lib/color-style-proptype.js
Normal file
9
src/lib/color-style-proptype.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import {PropTypes} from 'prop-types';
|
||||
|
||||
import GradientTypes from './gradient-types';
|
||||
|
||||
export default PropTypes.shape({
|
||||
primary: PropTypes.string,
|
||||
secondary: PropTypes.string,
|
||||
gradientType: PropTypes.oneOf(Object.keys(GradientTypes)).isRequired
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
import {combineReducers} from 'redux';
|
||||
import eyeDropperReducer from './eye-dropper';
|
||||
import fillColorReducer from './fill-style';
|
||||
import strokeColorReducer from './stroke-color';
|
||||
import strokeColorReducer from './stroke-style';
|
||||
import strokeWidthReducer from './stroke-width';
|
||||
|
||||
export default combineReducers({
|
||||
|
|
|
@ -35,7 +35,7 @@ const changeFillColor2 = function (fillColor) {
|
|||
const changeFillGradientType = function (gradientType) {
|
||||
return {
|
||||
type: CHANGE_FILL_GRADIENT_TYPE,
|
||||
gradientType: gradientType
|
||||
gradientType
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
import log from '../log/log';
|
||||
import {CHANGE_SELECTED_ITEMS} from './selected-items';
|
||||
import {CHANGE_STROKE_WIDTH} from './stroke-width';
|
||||
import {getColorsFromSelection, MIXED} from '../helper/style-path';
|
||||
|
||||
const CHANGE_STROKE_COLOR = 'scratch-paint/stroke-color/CHANGE_STROKE_COLOR';
|
||||
const initialState = '#000';
|
||||
// Matches hex colors
|
||||
const regExp = /^#([0-9a-f]{3}){1,2}$/i;
|
||||
|
||||
const reducer = function (state, action) {
|
||||
if (typeof state === 'undefined') state = initialState;
|
||||
switch (action.type) {
|
||||
case CHANGE_STROKE_WIDTH:
|
||||
if (Math.max(0, action.strokeWidth) === 0) {
|
||||
return null;
|
||||
}
|
||||
return state;
|
||||
case CHANGE_STROKE_COLOR:
|
||||
if (!regExp.test(action.strokeColor) && action.strokeColor !== null && action.strokeColor !== MIXED) {
|
||||
log.warn(`Invalid hex color code: ${action.fillColor}`);
|
||||
return state;
|
||||
}
|
||||
return action.strokeColor;
|
||||
case CHANGE_SELECTED_ITEMS:
|
||||
// Don't change state if no selection
|
||||
if (!action.selectedItems || !action.selectedItems.length) {
|
||||
return state;
|
||||
}
|
||||
// Bitmap mode doesn't have stroke color
|
||||
if (action.bitmapMode) {
|
||||
return state;
|
||||
}
|
||||
return getColorsFromSelection(action.selectedItems, action.bitmapMode).strokeColor;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
// Action creators ==================================
|
||||
const changeStrokeColor = function (strokeColor) {
|
||||
return {
|
||||
type: CHANGE_STROKE_COLOR,
|
||||
strokeColor: strokeColor
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
reducer as default,
|
||||
changeStrokeColor
|
||||
};
|
56
src/reducers/stroke-style.js
Normal file
56
src/reducers/stroke-style.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
import makeColorStyleReducer from '../lib/make-color-style-reducer';
|
||||
|
||||
const CHANGE_STROKE_COLOR = 'scratch-paint/stroke-style/CHANGE_STROKE_COLOR';
|
||||
const CHANGE_STROKE_COLOR_2 = 'scratch-paint/stroke-style/CHANGE_STROKE_COLOR_2';
|
||||
const CHANGE_STROKE_GRADIENT_TYPE = 'scratch-paint/stroke-style/CHANGE_STROKE_GRADIENT_TYPE';
|
||||
const CLEAR_STROKE_GRADIENT = 'scratch-paint/stroke-style/CLEAR_STROKE_GRADIENT';
|
||||
const DEFAULT_COLOR = '#000000';
|
||||
|
||||
const reducer = makeColorStyleReducer({
|
||||
changePrimaryColorAction: CHANGE_STROKE_COLOR,
|
||||
changeSecondaryColorAction: CHANGE_STROKE_COLOR_2,
|
||||
changeGradientTypeAction: CHANGE_STROKE_GRADIENT_TYPE,
|
||||
clearGradientAction: CLEAR_STROKE_GRADIENT,
|
||||
defaultColor: DEFAULT_COLOR,
|
||||
selectionPrimaryColorKey: 'strokeColor',
|
||||
selectionSecondaryColorKey: 'strokeColor2',
|
||||
selectionGradientTypeKey: 'strokeGradientType'
|
||||
});
|
||||
|
||||
// Action creators ==================================
|
||||
const changeStrokeColor = function (strokeColor) {
|
||||
return {
|
||||
type: CHANGE_STROKE_COLOR,
|
||||
color: strokeColor
|
||||
};
|
||||
};
|
||||
|
||||
const changeStrokeColor2 = function (strokeColor) {
|
||||
return {
|
||||
type: CHANGE_STROKE_COLOR_2,
|
||||
color: strokeColor
|
||||
};
|
||||
};
|
||||
|
||||
const changeStrokeGradientType = function (gradientType) {
|
||||
return {
|
||||
type: CHANGE_STROKE_GRADIENT_TYPE,
|
||||
gradientType
|
||||
};
|
||||
};
|
||||
|
||||
const clearStrokeGradient = function () {
|
||||
return {
|
||||
type: CLEAR_STROKE_GRADIENT
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
reducer as default,
|
||||
changeStrokeColor,
|
||||
changeStrokeColor2,
|
||||
changeStrokeGradientType,
|
||||
clearStrokeGradient,
|
||||
DEFAULT_COLOR,
|
||||
CHANGE_STROKE_GRADIENT_TYPE
|
||||
};
|
Loading…
Reference in a new issue