Fix zero-width-outline logic

- Set the stroke color to "null" when the width is set to 0
- Properly set the stroke color state when the width is increased from 0
This commit is contained in:
adroitwhiz 2020-07-28 08:36:34 -04:00
parent 852eefc2d7
commit cca0832f0d
2 changed files with 46 additions and 8 deletions

View file

@ -3,12 +3,13 @@ import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import bindAll from 'lodash.bindall'; import bindAll from 'lodash.bindall';
import parseColor from 'parse-color'; import parseColor from 'parse-color';
import {changeStrokeColor} from '../reducers/stroke-style'; import {changeStrokeColor, changeStrokeColor2, changeStrokeGradientType} from '../reducers/stroke-style';
import {changeStrokeWidth} from '../reducers/stroke-width'; import {changeStrokeWidth} from '../reducers/stroke-width';
import StrokeWidthIndicatorComponent from '../components/stroke-width-indicator.jsx'; import StrokeWidthIndicatorComponent from '../components/stroke-width-indicator.jsx';
import {getSelectedLeafItems} from '../helper/selection'; import {getSelectedLeafItems} from '../helper/selection';
import {applyColorToSelection, applyStrokeWidthToSelection, getColorsFromSelection, MIXED} import {applyColorToSelection, applyStrokeWidthToSelection, getColorsFromSelection, MIXED}
from '../helper/style-path'; from '../helper/style-path';
import GradientTypes from '../lib/gradient-types';
import Modes from '../lib/modes'; import Modes from '../lib/modes';
import Formats from '../lib/format'; import Formats from '../lib/format';
import {isBitmap} from '../lib/format'; import {isBitmap} from '../lib/format';
@ -23,8 +24,15 @@ class StrokeWidthIndicator extends React.Component {
handleChangeStrokeWidth (newWidth) { handleChangeStrokeWidth (newWidth) {
let changed = applyStrokeWidthToSelection(newWidth, this.props.textEditTarget); let changed = applyStrokeWidthToSelection(newWidth, this.props.textEditTarget);
if ((!this.props.strokeWidth || this.props.strokeWidth === 0) && newWidth > 0) { if ((!this.props.strokeWidth || this.props.strokeWidth === 0) && newWidth > 0) {
let currentColor = getColorsFromSelection(getSelectedLeafItems(), isBitmap(this.props.format)).strokeColor; const currentColorState = getColorsFromSelection(getSelectedLeafItems(), isBitmap(this.props.format));
if (currentColor === null) {
// Color counts as null if either both colors are null or the primary color is null and it's solid
// TODO: consolidate this check in one place
const wasNull = currentColorState.strokeColor === null &&
(currentColorState.strokeColor2 === null ||
currentColorState.strokeGradientType === GradientTypes.SOLID);
if (wasNull) {
changed = applyColorToSelection( changed = applyColorToSelection(
'#000', '#000',
0, // colorIndex, 0, // colorIndex,
@ -32,11 +40,15 @@ class StrokeWidthIndicator extends React.Component {
true, // applyToStroke true, // applyToStroke
this.props.textEditTarget) || this.props.textEditTarget) ||
changed; changed;
currentColor = '#000'; // If there's no previous stroke color, default to solid black
} else if (currentColor !== MIXED) { this.props.onChangeStrokeGradientType(GradientTypes.SOLID);
currentColor = parseColor(currentColor).hex; this.props.onChangeStrokeColor('#000');
} else if (currentColorState.strokeColor !== MIXED) {
// Set color state from the selected item's stroke color
this.props.onChangeStrokeGradientType(currentColorState.strokeGradientType);
this.props.onChangeStrokeColor(parseColor(currentColorState.strokeColor).hex);
this.props.onChangeStrokeColor2(parseColor(currentColorState.strokeColor2).hex);
} }
this.props.onChangeStrokeColor(currentColor);
} }
this.props.onChangeStrokeWidth(newWidth); this.props.onChangeStrokeWidth(newWidth);
if (changed) this.props.onUpdateImage(); if (changed) this.props.onUpdateImage();
@ -64,6 +76,12 @@ const mapDispatchToProps = dispatch => ({
onChangeStrokeColor: strokeColor => { onChangeStrokeColor: strokeColor => {
dispatch(changeStrokeColor(strokeColor)); dispatch(changeStrokeColor(strokeColor));
}, },
onChangeStrokeColor2: strokeColor => {
dispatch(changeStrokeColor2(strokeColor));
},
onChangeStrokeGradientType: strokeColor => {
dispatch(changeStrokeGradientType(strokeColor));
},
onChangeStrokeWidth: strokeWidth => { onChangeStrokeWidth: strokeWidth => {
dispatch(changeStrokeWidth(strokeWidth)); dispatch(changeStrokeWidth(strokeWidth));
} }
@ -73,6 +91,8 @@ StrokeWidthIndicator.propTypes = {
disabled: PropTypes.bool.isRequired, disabled: PropTypes.bool.isRequired,
format: PropTypes.oneOf(Object.keys(Formats)), format: PropTypes.oneOf(Object.keys(Formats)),
onChangeStrokeColor: PropTypes.func.isRequired, onChangeStrokeColor: PropTypes.func.isRequired,
onChangeStrokeColor2: PropTypes.func.isRequired,
onChangeStrokeGradientType: PropTypes.func.isRequired,
onChangeStrokeWidth: PropTypes.func.isRequired, onChangeStrokeWidth: PropTypes.func.isRequired,
onUpdateImage: PropTypes.func.isRequired, onUpdateImage: PropTypes.func.isRequired,
strokeWidth: PropTypes.number, strokeWidth: PropTypes.number,

View file

@ -6,6 +6,8 @@ const CHANGE_STROKE_GRADIENT_TYPE = 'scratch-paint/stroke-style/CHANGE_STROKE_GR
const CLEAR_STROKE_GRADIENT = 'scratch-paint/stroke-style/CLEAR_STROKE_GRADIENT'; const CLEAR_STROKE_GRADIENT = 'scratch-paint/stroke-style/CLEAR_STROKE_GRADIENT';
const DEFAULT_COLOR = '#000000'; const DEFAULT_COLOR = '#000000';
import {CHANGE_STROKE_WIDTH} from './stroke-width';
const reducer = makeColorStyleReducer({ const reducer = makeColorStyleReducer({
changePrimaryColorAction: CHANGE_STROKE_COLOR, changePrimaryColorAction: CHANGE_STROKE_COLOR,
changeSecondaryColorAction: CHANGE_STROKE_COLOR_2, changeSecondaryColorAction: CHANGE_STROKE_COLOR_2,
@ -17,6 +19,22 @@ const reducer = makeColorStyleReducer({
selectionGradientTypeKey: 'strokeGradientType' selectionGradientTypeKey: 'strokeGradientType'
}); });
// This is mostly the same as the generated reducer, but with one piece of extra logic to set the color to null when the
// stroke width is set to 0.
// https://redux.js.org/recipes/structuring-reducers/reusing-reducer-logic
const strokeReducer = function (state, action) {
if (action.type === CHANGE_STROKE_WIDTH && Math.max(action.strokeWidth, 0) === 0) {
// TODO: this preserves the gradient type when you change the stroke width to 0.
// Alternatively, we could set gradientType to SOLID instead of setting secondary to null, but since
// the stroke width is automatically set to 0 as soon as a "null" color is detected (including a gradient for
// which both colors are null), that would change the gradient type back to solid if you selected null for both
// gradient colors.
return {...state, primary: null, secondary: null};
}
return reducer(state, action);
};
// Action creators ================================== // Action creators ==================================
const changeStrokeColor = function (strokeColor) { const changeStrokeColor = function (strokeColor) {
return { return {
@ -46,7 +64,7 @@ const clearStrokeGradient = function () {
}; };
export { export {
reducer as default, strokeReducer as default,
changeStrokeColor, changeStrokeColor,
changeStrokeColor2, changeStrokeColor2,
changeStrokeGradientType, changeStrokeGradientType,