From 35749e5b37c66ca0a872dccb35805ea8cf71ec7e Mon Sep 17 00:00:00 2001 From: DD Liu Date: Fri, 21 Aug 2020 10:28:08 -0400 Subject: [PATCH 1/8] Make transparent color switch to black and white when a gradient type is applied --- src/helper/style-path.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/helper/style-path.js b/src/helper/style-path.js index 07663296cb..469dbfce19 100644 --- a/src/helper/style-path.js +++ b/src/helper/style-path.js @@ -309,6 +309,9 @@ const applyGradientTypeToSelection = function (gradientType, applyToStroke, text if (noStrokeOriginally && hasGradientNow) { // Make outline visible item.strokeWidth = 1; + // Make the gradient black to white + itemColor1 = 'black'; + itemColor2 = 'white'; } } From 544d833b5399e69f18432f9d87a861f11a344655 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Fri, 21 Aug 2020 11:23:54 -0400 Subject: [PATCH 2/8] Remove transparent to transparent gradients. Hide the second color of stroke width 0 gradients again. --- src/helper/style-path.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/helper/style-path.js b/src/helper/style-path.js index 469dbfce19..7d6504bf8c 100644 --- a/src/helper/style-path.js +++ b/src/helper/style-path.js @@ -465,11 +465,23 @@ const getColorsFromSelection = function (selectedItems, bitmapMode) { let strokeColorString = primary; const strokeColor2String = secondary; - const strokeGradientType = gradientType; + let strokeGradientType = gradientType; + + if (strokeGradientType !== GradientTypes.SOLID && + item.strokeColor.gradient.stops.length === 2 && + item.strokeColor.gradient.stops[0].color.alpha === 0 && + item.strokeColor.gradient.stops[1].color.alpha === 0) { + // Clear the gradient if both colors are transparent + item.strokeColor = null; + strokeGradientType = GradientTypes.SOLID; + } // If the item's stroke width is 0, pretend the stroke color is null if (!item.strokeWidth) { strokeColorString = null; + // Hide the second color. This way if you choose a second color, remove + // the gradient, and re-add it, your second color selection is preserved. + strokeGradientType = GradientTypes.SOLID; } // Stroke color is fill color in bitmap From c62093febeb6f542b6d22ba47e654c3b9d85dae5 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Tue, 25 Aug 2020 06:00:26 -0400 Subject: [PATCH 3/8] Change transparent fills to black and white when a gradient is added --- src/helper/style-path.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/helper/style-path.js b/src/helper/style-path.js index 7d6504bf8c..368af801bb 100644 --- a/src/helper/style-path.js +++ b/src/helper/style-path.js @@ -298,17 +298,20 @@ const applyGradientTypeToSelection = function (gradientType, applyToStroke, text continue; } - if (!hasGradient && applyToStroke) { - const noStrokeOriginally = item.strokeWidth === 0 || !itemColor || + if (!hasGradient) { + const noColorOriginally = !itemColor || (itemColor.gradient && itemColor.gradient.stops && itemColor.gradient.stops.length === 2 && itemColor.gradient.stops[0].color.alpha === 0 && itemColor.gradient.stops[1].color.alpha === 0); + const addingStroke = applyToStroke && item.strokeWidth === 0; const hasGradientNow = itemColor1 || itemColor2; - if (noStrokeOriginally && hasGradientNow) { - // Make outline visible - item.strokeWidth = 1; + if ((noColorOriginally || addingStroke) && hasGradientNow) { + if (applyToStroke) { + // Make outline visible + item.strokeWidth = 1; + } // Make the gradient black to white itemColor1 = 'black'; itemColor2 = 'white'; From 84da7aa842163b14de83e12020a83ee11dc05a9e Mon Sep 17 00:00:00 2001 From: DD Liu Date: Fri, 28 Aug 2020 00:46:33 -0400 Subject: [PATCH 4/8] Revert the code that converted a transparent-to-transparent gradient to a transparent solid color on select, because that was causing the bug where when you switched gradient twice with trans-trans, it became black-white. Instead, leave the color as a trans-trans gradient, but treat it as if its solid when switching colors. Its starting to keep track of a lot of secret state, which seems brittle... --- src/helper/style-path.js | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/src/helper/style-path.js b/src/helper/style-path.js index 368af801bb..a5c873c9b3 100644 --- a/src/helper/style-path.js +++ b/src/helper/style-path.js @@ -298,7 +298,11 @@ const applyGradientTypeToSelection = function (gradientType, applyToStroke, text continue; } - if (!hasGradient) { + // If this is a stroke, we don't display it as having a gradient in the color picker + // if there's no stroke width. Then treat it as if it doesn't have a gradient. + let hasDisplayGradient = hasGradient; + if (applyToStroke) hasDisplayGradient = hasGradient && item.strokeWidth > 0; + if (!hasDisplayGradient) { const noColorOriginally = !itemColor || (itemColor.gradient && itemColor.gradient.stops && @@ -329,18 +333,18 @@ const applyGradientTypeToSelection = function (gradientType, applyToStroke, text // If the item's gradient type differs from the gradient type we want to apply, then we change it switch (gradientType) { case GradientTypes.RADIAL: { - const hasRadialGradient = hasGradient && itemColor.gradient.radial; + const hasRadialGradient = hasDisplayGradient && itemColor.gradient.radial; gradientTypeDiffers = !hasRadialGradient; break; } case GradientTypes.HORIZONTAL: { - const hasHorizontalGradient = hasGradient && !itemColor.gradient.radial && + const hasHorizontalGradient = hasDisplayGradient && !itemColor.gradient.radial && Math.abs(itemColor.origin.y - itemColor.destination.y) < 1e-8; gradientTypeDiffers = !hasHorizontalGradient; break; } case GradientTypes.VERTICAL: { - const hasVerticalGradient = hasGradient && !itemColor.gradient.radial && + const hasVerticalGradient = hasDisplayGradient && !itemColor.gradient.radial && Math.abs(itemColor.origin.x - itemColor.destination.x) < 1e-8; gradientTypeDiffers = !hasVerticalGradient; break; @@ -470,15 +474,6 @@ const getColorsFromSelection = function (selectedItems, bitmapMode) { const strokeColor2String = secondary; let strokeGradientType = gradientType; - if (strokeGradientType !== GradientTypes.SOLID && - item.strokeColor.gradient.stops.length === 2 && - item.strokeColor.gradient.stops[0].color.alpha === 0 && - item.strokeColor.gradient.stops[1].color.alpha === 0) { - // Clear the gradient if both colors are transparent - item.strokeColor = null; - strokeGradientType = GradientTypes.SOLID; - } - // If the item's stroke width is 0, pretend the stroke color is null if (!item.strokeWidth) { strokeColorString = null; From 889cd0a0ddb787da2b4f65548556f91fe3796030 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Fri, 28 Aug 2020 01:12:11 -0400 Subject: [PATCH 5/8] If theres no display gradient, the second color of the gradient is ignored. --- src/helper/style-path.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/helper/style-path.js b/src/helper/style-path.js index a5c873c9b3..839a5a0747 100644 --- a/src/helper/style-path.js +++ b/src/helper/style-path.js @@ -306,9 +306,7 @@ const applyGradientTypeToSelection = function (gradientType, applyToStroke, text const noColorOriginally = !itemColor || (itemColor.gradient && itemColor.gradient.stops && - itemColor.gradient.stops.length === 2 && - itemColor.gradient.stops[0].color.alpha === 0 && - itemColor.gradient.stops[1].color.alpha === 0); + itemColor.gradient.stops[0].color.alpha === 0); const addingStroke = applyToStroke && item.strokeWidth === 0; const hasGradientNow = itemColor1 || itemColor2; if ((noColorOriginally || addingStroke) && hasGradientNow) { From 740f0e6b2b31c069b8df72735ad9e29a08c8f9bb Mon Sep 17 00:00:00 2001 From: DD Liu Date: Fri, 28 Aug 2020 04:23:54 -0400 Subject: [PATCH 6/8] Remove mixed from the color state when switching to the shape tools --- src/containers/oval-mode.jsx | 82 +++++++++++++++++++++++++++--------- src/containers/rect-mode.jsx | 82 +++++++++++++++++++++++++++--------- 2 files changed, 122 insertions(+), 42 deletions(-) diff --git a/src/containers/oval-mode.jsx b/src/containers/oval-mode.jsx index 03678acd7c..c21b2af188 100644 --- a/src/containers/oval-mode.jsx +++ b/src/containers/oval-mode.jsx @@ -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 {MIXED} from '../helper/style-path'; +import ColorStyleProptype from '../lib/color-style-proptype'; +import GradientTypes from '../lib/gradient-types'; -import {changeFillColor, DEFAULT_COLOR} from '../reducers/fill-style'; -import {changeStrokeColor} from '../reducers/stroke-style'; +import {changeFillColor, clearFillGradient, DEFAULT_COLOR} from '../reducers/fill-style'; +import {changeStrokeColor, clearStrokeGradient} from '../reducers/stroke-style'; import {changeMode} from '../reducers/modes'; import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items'; import {setCursor} from '../reducers/cursor'; @@ -22,7 +23,8 @@ class OvalMode extends React.Component { super(props); bindAll(this, [ 'activateTool', - 'deactivateTool' + 'deactivateTool', + 'validateColorState' ]); } componentDidMount () { @@ -54,23 +56,8 @@ class OvalMode extends React.Component { } activateTool () { clearSelection(this.props.clearSelectedItems); - // 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 {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; - if (!fillColorPresent && !strokeColorPresent) { - this.props.onChangeFillColor(DEFAULT_COLOR); - this.props.onChangeStrokeColor(null); - } else if (!fillColorPresent && strokeColorPresent) { - this.props.onChangeFillColor(null); - } else if (fillColorPresent && !strokeColorPresent) { - this.props.onChangeStrokeColor(null); - } + this.validateColorState(); + this.tool = new OvalTool( this.props.setSelectedItems, this.props.clearSelectedItems, @@ -85,6 +72,51 @@ class OvalMode extends React.Component { this.tool.remove(); this.tool = null; } + validateColorState () { + // Make sure that at least one of fill/stroke is set, and that MIXED is not one of the colors. + // If fill and stroke color are both missing, set fill to default and stroke to transparent. + // If exactly one of fill or stroke color is set, set the other one to transparent. + const {strokeWidth} = this.props.colorState; + const fillColor1 = this.props.colorState.fillColor.primary; + let fillColor2 = this.props.colorState.fillColor.secondary; + let fillGradient = this.props.colorState.fillColor.gradientType; + const strokeColor1 = this.props.colorState.strokeColor.primary; + let strokeColor2 = this.props.colorState.strokeColor.secondary; + let strokeGradient = this.props.colorState.strokeColor.gradientType; + if (strokeColor1 === MIXED || + (strokeColor1 === null && + (strokeColor2 === null || strokeColor2 === MIXED))) { + this.props.onChangeStrokeColor(DEFAULT_COLOR); + } + if (fillColor2 === MIXED) { + this.props.clearFillGradient(); + fillColor2 = null; + fillGradient = GradientTypes.SOLID; + } + if (strokeColor2 === MIXED) { + this.props.clearStrokeGradient(); + strokeColor2 = null; + strokeGradient = GradientTypes.SOLID; + } + + const fillColorMissing = fillColor1 === MIXED || + (fillGradient === GradientTypes.SOLID && fillColor1 === null) || + (fillGradient !== GradientTypes.SOLID && fillColor1 === null && fillColor2 === null); + const strokeColorMissing = strokeColor1 === MIXED || + strokeWidth === null || + strokeWidth === 0 || + (strokeGradient === GradientTypes.SOLID && strokeColor1 === null) || + (strokeGradient !== GradientTypes.SOLID && strokeColor1 === null && strokeColor2 === null); + + if (fillColorMissing && strokeColorMissing) { + this.props.onChangeFillColor(DEFAULT_COLOR); + this.props.onChangeStrokeColor(null); + } else if (fillColorMissing && !strokeColorMissing) { + this.props.onChangeFillColor(null); + } else if (!fillColorMissing && strokeColorMissing) { + this.props.onChangeStrokeColor(null); + } + } render () { return ( ({ clearSelectedItems: () => { dispatch(clearSelectedItems()); }, + clearFillGradient: () => { + dispatch(clearFillGradient()); + }, + clearStrokeGradient: () => { + dispatch(clearStrokeGradient()); + }, setCursor: cursorString => { dispatch(setCursor(cursorString)); }, diff --git a/src/containers/rect-mode.jsx b/src/containers/rect-mode.jsx index df8c8a3efc..015d65307d 100644 --- a/src/containers/rect-mode.jsx +++ b/src/containers/rect-mode.jsx @@ -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 {MIXED} from '../helper/style-path'; +import ColorStyleProptype from '../lib/color-style-proptype'; +import GradientTypes from '../lib/gradient-types'; -import {changeFillColor, DEFAULT_COLOR} from '../reducers/fill-style'; -import {changeStrokeColor} from '../reducers/stroke-style'; +import {changeFillColor, clearFillGradient, DEFAULT_COLOR} from '../reducers/fill-style'; +import {changeStrokeColor, clearStrokeGradient} from '../reducers/stroke-style'; import {changeMode} from '../reducers/modes'; import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items'; import {setCursor} from '../reducers/cursor'; @@ -22,7 +23,8 @@ class RectMode extends React.Component { super(props); bindAll(this, [ 'activateTool', - 'deactivateTool' + 'deactivateTool', + 'validateColorState' ]); } componentDidMount () { @@ -54,23 +56,8 @@ class RectMode extends React.Component { } activateTool () { clearSelection(this.props.clearSelectedItems); - // 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 {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; - if (!fillColorPresent && !strokeColorPresent) { - this.props.onChangeFillColor(DEFAULT_COLOR); - this.props.onChangeStrokeColor(null); - } else if (!fillColorPresent && strokeColorPresent) { - this.props.onChangeFillColor(null); - } else if (fillColorPresent && !strokeColorPresent) { - this.props.onChangeStrokeColor(null); - } + this.validateColorState(); + this.tool = new RectTool( this.props.setSelectedItems, this.props.clearSelectedItems, @@ -80,6 +67,51 @@ class RectMode extends React.Component { this.tool.setColorState(this.props.colorState); this.tool.activate(); } + validateColorState () { // TODO move to shared class + // Make sure that at least one of fill/stroke is set, and that MIXED is not one of the colors. + // If fill and stroke color are both missing, set fill to default and stroke to transparent. + // If exactly one of fill or stroke color is set, set the other one to transparent. + const {strokeWidth} = this.props.colorState; + const fillColor1 = this.props.colorState.fillColor.primary; + let fillColor2 = this.props.colorState.fillColor.secondary; + let fillGradient = this.props.colorState.fillColor.gradientType; + const strokeColor1 = this.props.colorState.strokeColor.primary; + let strokeColor2 = this.props.colorState.strokeColor.secondary; + let strokeGradient = this.props.colorState.strokeColor.gradientType; + if (strokeColor1 === MIXED || + (strokeColor1 === null && + (strokeColor2 === null || strokeColor2 === MIXED))) { + this.props.onChangeStrokeColor(DEFAULT_COLOR); + } + if (fillColor2 === MIXED) { + this.props.clearFillGradient(); + fillColor2 = null; + fillGradient = GradientTypes.SOLID; + } + if (strokeColor2 === MIXED) { + this.props.clearStrokeGradient(); + strokeColor2 = null; + strokeGradient = GradientTypes.SOLID; + } + + const fillColorMissing = fillColor1 === MIXED || + (fillGradient === GradientTypes.SOLID && fillColor1 === null) || + (fillGradient !== GradientTypes.SOLID && fillColor1 === null && fillColor2 === null); + const strokeColorMissing = strokeColor1 === MIXED || + strokeWidth === null || + strokeWidth === 0 || + (strokeGradient === GradientTypes.SOLID && strokeColor1 === null) || + (strokeGradient !== GradientTypes.SOLID && strokeColor1 === null && strokeColor2 === null); + + if (fillColorMissing && strokeColorMissing) { + this.props.onChangeFillColor(DEFAULT_COLOR); + this.props.onChangeStrokeColor(null); + } else if (fillColorMissing && !strokeColorMissing) { + this.props.onChangeFillColor(null); + } else if (!fillColorMissing && strokeColorMissing) { + this.props.onChangeStrokeColor(null); + } + } deactivateTool () { this.tool.deactivateTool(); this.tool.remove(); @@ -96,6 +128,8 @@ class RectMode extends React.Component { } RectMode.propTypes = { + clearFillGradient: PropTypes.func.isRequired, + clearStrokeGradient: PropTypes.func.isRequired, clearSelectedItems: PropTypes.func.isRequired, colorState: PropTypes.shape({ fillColor: ColorStyleProptype, @@ -121,6 +155,12 @@ const mapDispatchToProps = dispatch => ({ clearSelectedItems: () => { dispatch(clearSelectedItems()); }, + clearFillGradient: () => { + dispatch(clearFillGradient()); + }, + clearStrokeGradient: () => { + dispatch(clearStrokeGradient()); + }, setSelectedItems: () => { dispatch(setSelectedItems(getSelectedLeafItems(), false /* bitmapMode */)); }, From cf507eac065e9a8b13eb92afa402a10e75031273 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Mon, 31 Aug 2020 01:56:30 -0400 Subject: [PATCH 7/8] Clear out gradients when setting default colors --- src/containers/oval-mode.jsx | 10 +++++----- src/containers/rect-mode.jsx | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/containers/oval-mode.jsx b/src/containers/oval-mode.jsx index c21b2af188..0d24e88797 100644 --- a/src/containers/oval-mode.jsx +++ b/src/containers/oval-mode.jsx @@ -83,11 +83,7 @@ class OvalMode extends React.Component { const strokeColor1 = this.props.colorState.strokeColor.primary; let strokeColor2 = this.props.colorState.strokeColor.secondary; let strokeGradient = this.props.colorState.strokeColor.gradientType; - if (strokeColor1 === MIXED || - (strokeColor1 === null && - (strokeColor2 === null || strokeColor2 === MIXED))) { - this.props.onChangeStrokeColor(DEFAULT_COLOR); - } + if (fillColor2 === MIXED) { this.props.clearFillGradient(); fillColor2 = null; @@ -110,11 +106,15 @@ class OvalMode extends React.Component { if (fillColorMissing && strokeColorMissing) { this.props.onChangeFillColor(DEFAULT_COLOR); + this.props.clearFillGradient(); this.props.onChangeStrokeColor(null); + this.props.clearStrokeGradient(); } else if (fillColorMissing && !strokeColorMissing) { this.props.onChangeFillColor(null); + this.props.clearFillGradient(); } else if (!fillColorMissing && strokeColorMissing) { this.props.onChangeStrokeColor(null); + this.props.clearStrokeGradient(); } } render () { diff --git a/src/containers/rect-mode.jsx b/src/containers/rect-mode.jsx index 015d65307d..49a9bb5ce9 100644 --- a/src/containers/rect-mode.jsx +++ b/src/containers/rect-mode.jsx @@ -78,11 +78,7 @@ class RectMode extends React.Component { const strokeColor1 = this.props.colorState.strokeColor.primary; let strokeColor2 = this.props.colorState.strokeColor.secondary; let strokeGradient = this.props.colorState.strokeColor.gradientType; - if (strokeColor1 === MIXED || - (strokeColor1 === null && - (strokeColor2 === null || strokeColor2 === MIXED))) { - this.props.onChangeStrokeColor(DEFAULT_COLOR); - } + if (fillColor2 === MIXED) { this.props.clearFillGradient(); fillColor2 = null; @@ -105,11 +101,15 @@ class RectMode extends React.Component { if (fillColorMissing && strokeColorMissing) { this.props.onChangeFillColor(DEFAULT_COLOR); + this.props.clearFillGradient(); this.props.onChangeStrokeColor(null); + this.props.clearStrokeGradient(); } else if (fillColorMissing && !strokeColorMissing) { this.props.onChangeFillColor(null); + this.props.clearFillGradient(); } else if (!fillColorMissing && strokeColorMissing) { this.props.onChangeStrokeColor(null); + this.props.clearStrokeGradient(); } } deactivateTool () { From 517ff63670a08493e752d93c80b7d037ccb38e74 Mon Sep 17 00:00:00 2001 From: DD Liu Date: Mon, 31 Aug 2020 02:17:16 -0400 Subject: [PATCH 8/8] Fix lint --- src/containers/oval-mode.jsx | 2 +- src/containers/rect-mode.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/containers/oval-mode.jsx b/src/containers/oval-mode.jsx index 0d24e88797..da8d441550 100644 --- a/src/containers/oval-mode.jsx +++ b/src/containers/oval-mode.jsx @@ -98,7 +98,7 @@ class OvalMode extends React.Component { const fillColorMissing = fillColor1 === MIXED || (fillGradient === GradientTypes.SOLID && fillColor1 === null) || (fillGradient !== GradientTypes.SOLID && fillColor1 === null && fillColor2 === null); - const strokeColorMissing = strokeColor1 === MIXED || + const strokeColorMissing = strokeColor1 === MIXED || strokeWidth === null || strokeWidth === 0 || (strokeGradient === GradientTypes.SOLID && strokeColor1 === null) || diff --git a/src/containers/rect-mode.jsx b/src/containers/rect-mode.jsx index 49a9bb5ce9..887f32f2f0 100644 --- a/src/containers/rect-mode.jsx +++ b/src/containers/rect-mode.jsx @@ -93,7 +93,7 @@ class RectMode extends React.Component { const fillColorMissing = fillColor1 === MIXED || (fillGradient === GradientTypes.SOLID && fillColor1 === null) || (fillGradient !== GradientTypes.SOLID && fillColor1 === null && fillColor2 === null); - const strokeColorMissing = strokeColor1 === MIXED || + const strokeColorMissing = strokeColor1 === MIXED || strokeWidth === null || strokeWidth === 0 || (strokeGradient === GradientTypes.SOLID && strokeColor1 === null) ||