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 bindAll from 'lodash.bindall';
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 StrokeWidthIndicatorComponent from '../components/stroke-width-indicator.jsx';
import {getSelectedLeafItems} from '../helper/selection';
import {applyColorToSelection, applyStrokeWidthToSelection, getColorsFromSelection, MIXED}
from '../helper/style-path';
import GradientTypes from '../lib/gradient-types';
import Modes from '../lib/modes';
import Formats from '../lib/format';
import {isBitmap} from '../lib/format';
@ -23,8 +24,15 @@ class StrokeWidthIndicator extends React.Component {
handleChangeStrokeWidth (newWidth) {
let changed = applyStrokeWidthToSelection(newWidth, this.props.textEditTarget);
if ((!this.props.strokeWidth || this.props.strokeWidth === 0) && newWidth > 0) {
let currentColor = getColorsFromSelection(getSelectedLeafItems(), isBitmap(this.props.format)).strokeColor;
if (currentColor === null) {
const currentColorState = getColorsFromSelection(getSelectedLeafItems(), isBitmap(this.props.format));
// 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(
'#000',
0, // colorIndex,
@ -32,11 +40,15 @@ class StrokeWidthIndicator extends React.Component {
true, // applyToStroke
this.props.textEditTarget) ||
changed;
currentColor = '#000';
} else if (currentColor !== MIXED) {
currentColor = parseColor(currentColor).hex;
// If there's no previous stroke color, default to solid black
this.props.onChangeStrokeGradientType(GradientTypes.SOLID);
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);
if (changed) this.props.onUpdateImage();
@ -64,6 +76,12 @@ const mapDispatchToProps = dispatch => ({
onChangeStrokeColor: strokeColor => {
dispatch(changeStrokeColor(strokeColor));
},
onChangeStrokeColor2: strokeColor => {
dispatch(changeStrokeColor2(strokeColor));
},
onChangeStrokeGradientType: strokeColor => {
dispatch(changeStrokeGradientType(strokeColor));
},
onChangeStrokeWidth: strokeWidth => {
dispatch(changeStrokeWidth(strokeWidth));
}
@ -73,6 +91,8 @@ StrokeWidthIndicator.propTypes = {
disabled: PropTypes.bool.isRequired,
format: PropTypes.oneOf(Object.keys(Formats)),
onChangeStrokeColor: PropTypes.func.isRequired,
onChangeStrokeColor2: PropTypes.func.isRequired,
onChangeStrokeGradientType: PropTypes.func.isRequired,
onChangeStrokeWidth: PropTypes.func.isRequired,
onUpdateImage: PropTypes.func.isRequired,
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 DEFAULT_COLOR = '#000000';
import {CHANGE_STROKE_WIDTH} from './stroke-width';
const reducer = makeColorStyleReducer({
changePrimaryColorAction: CHANGE_STROKE_COLOR,
changeSecondaryColorAction: CHANGE_STROKE_COLOR_2,
@ -17,6 +19,22 @@ const reducer = makeColorStyleReducer({
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 ==================================
const changeStrokeColor = function (strokeColor) {
return {
@ -46,7 +64,7 @@ const clearStrokeGradient = function () {
};
export {
reducer as default,
strokeReducer as default,
changeStrokeColor,
changeStrokeColor2,
changeStrokeGradientType,