mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-23 05:52:42 -05:00
Merge pull request #112 from paulkaplan/transparent-state
Fix several color state inconsistencies
This commit is contained in:
commit
c1ce433f72
17 changed files with 185 additions and 12 deletions
|
@ -5,6 +5,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-button-swatch {
|
.color-button-swatch {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-basis: 2rem;
|
flex-basis: 2rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
@ -30,3 +31,23 @@
|
||||||
color: #575e75;
|
color: #575e75;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.swatch-icon {
|
||||||
|
width: 1.75rem;
|
||||||
|
margin: auto;
|
||||||
|
/* Make sure it appears above the outline box */
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outline-swatch:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: calc(0.5rem + 1px);
|
||||||
|
left: calc(0.5rem + 1px);
|
||||||
|
width: 0.75rem;
|
||||||
|
height: 0.75rem;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||||
|
/* Make sure it appears below the transparent icon */
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
|
@ -1,26 +1,55 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import {MIXED} from '../../helper/style-path';
|
||||||
|
|
||||||
|
import noFillIcon from './no-fill.svg';
|
||||||
|
import mixedFillIcon from './mixed-fill.svg';
|
||||||
import styles from './color-button.css';
|
import styles from './color-button.css';
|
||||||
|
|
||||||
|
const colorToBackground = color => {
|
||||||
|
if (color === MIXED || color === null) return 'white';
|
||||||
|
return color;
|
||||||
|
};
|
||||||
|
|
||||||
const ColorButtonComponent = props => (
|
const ColorButtonComponent = props => (
|
||||||
<div
|
<div
|
||||||
className={styles.colorButton}
|
className={styles.colorButton}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={styles.colorButtonSwatch}
|
className={classNames(styles.colorButtonSwatch, {
|
||||||
|
[styles.outlineSwatch]: props.outline
|
||||||
|
})}
|
||||||
style={{
|
style={{
|
||||||
background: props.color
|
background: colorToBackground(props.color)
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
{props.color === null ? (
|
||||||
|
<img
|
||||||
|
className={styles.swatchIcon}
|
||||||
|
src={noFillIcon}
|
||||||
/>
|
/>
|
||||||
|
) : ((props.color === MIXED ? (
|
||||||
|
<img
|
||||||
|
className={styles.swatchIcon}
|
||||||
|
src={mixedFillIcon}
|
||||||
|
/>
|
||||||
|
) : null))}
|
||||||
|
</div>
|
||||||
<div className={styles.colorButtonArrow}>▾</div>
|
<div className={styles.colorButtonArrow}>▾</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
ColorButtonComponent.propTypes = {
|
ColorButtonComponent.propTypes = {
|
||||||
color: PropTypes.string,
|
color: PropTypes.string,
|
||||||
onClick: PropTypes.func.isRequired
|
onClick: PropTypes.func.isRequired,
|
||||||
|
outline: PropTypes.bool.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
ColorButtonComponent.defaultProps = {
|
||||||
|
outline: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ColorButtonComponent;
|
export default ColorButtonComponent;
|
||||||
|
|
16
src/components/color-button/mixed-fill.svg
Normal file
16
src/components/color-button/mixed-fill.svg
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>mixed-fill</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" fill-opacity="0.75">
|
||||||
|
<g id="mixed-fill">
|
||||||
|
<g id="mixed-fill-icon" transform="translate(2.000000, 2.500000)">
|
||||||
|
<circle id="blue" fill="#4C97FF" cx="4.5" cy="10.5" r="4.5"></circle>
|
||||||
|
<circle id="red" fill="#FF5500" cx="8" cy="4.5" r="4.5"></circle>
|
||||||
|
<circle id="yellow" fill="#FFBF00" cx="11.4099998" cy="10.5" r="4.5"></circle>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 888 B |
12
src/components/color-button/no-fill.svg
Normal file
12
src/components/color-button/no-fill.svg
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>no-fill</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="square">
|
||||||
|
<g id="no-fill" stroke="#FF661A" stroke-width="2">
|
||||||
|
<path d="M3,17 L17,3" id="Line"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 612 B |
|
@ -48,3 +48,7 @@
|
||||||
border: 1px solid #4C97FF;
|
border: 1px solid #4C97FF;
|
||||||
box-shadow: 0px 0px 0px 3px hsla(215, 100%, 65%, 0.2);
|
box-shadow: 0px 0px 0px 3px hsla(215, 100%, 65%, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.swatch > img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {MIXED} from '../../helper/style-path';
|
||||||
|
|
||||||
import Slider from '../forms/slider.jsx';
|
import Slider from '../forms/slider.jsx';
|
||||||
import styles from './color-picker.css';
|
import styles from './color-picker.css';
|
||||||
|
import noFillIcon from '../color-button/no-fill.svg';
|
||||||
|
|
||||||
const colorStringToHsv = hexString => {
|
const colorStringToHsv = hexString => {
|
||||||
const hsv = parseColor(hexString).hsv;
|
const hsv = parseColor(hexString).hsv;
|
||||||
|
@ -179,7 +180,9 @@ class ColorPickerComponent extends React.Component {
|
||||||
[styles.activeSwatch]: this.props.color === null
|
[styles.activeSwatch]: this.props.color === null
|
||||||
})}
|
})}
|
||||||
onClick={this.handleTransparent}
|
onClick={this.handleTransparent}
|
||||||
/>
|
>
|
||||||
|
<img src={noFillIcon} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -17,7 +17,7 @@ const messages = defineMessages({
|
||||||
});
|
});
|
||||||
|
|
||||||
const FillColorIndicatorComponent = props => (
|
const FillColorIndicatorComponent = props => (
|
||||||
<InputGroup>
|
<InputGroup disabled={props.disabled}>
|
||||||
<Popover
|
<Popover
|
||||||
body={
|
body={
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
|
@ -40,6 +40,7 @@ const FillColorIndicatorComponent = props => (
|
||||||
);
|
);
|
||||||
|
|
||||||
FillColorIndicatorComponent.propTypes = {
|
FillColorIndicatorComponent.propTypes = {
|
||||||
|
disabled: PropTypes.bool.isRequired,
|
||||||
fillColor: PropTypes.string,
|
fillColor: PropTypes.string,
|
||||||
fillColorModalVisible: PropTypes.bool.isRequired,
|
fillColorModalVisible: PropTypes.bool.isRequired,
|
||||||
intl: intlShape,
|
intl: intlShape,
|
||||||
|
|
|
@ -3,3 +3,9 @@
|
||||||
.input-group + .input-group {
|
.input-group + .input-group {
|
||||||
margin-left: calc(3 * $grid-unit);
|
margin-left: calc(3 * $grid-unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
/* Prevent any user actions */
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
|
@ -5,14 +5,19 @@ import PropTypes from 'prop-types';
|
||||||
import styles from './input-group.css';
|
import styles from './input-group.css';
|
||||||
|
|
||||||
const InputGroup = props => (
|
const InputGroup = props => (
|
||||||
<div className={classNames(props.className, styles.inputGroup)}>
|
<div
|
||||||
|
className={classNames(props.className, styles.inputGroup, {
|
||||||
|
[styles.disabled]: props.disabled
|
||||||
|
})}
|
||||||
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
InputGroup.propTypes = {
|
InputGroup.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
className: PropTypes.string
|
className: PropTypes.string,
|
||||||
|
disabled: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
export default InputGroup;
|
export default InputGroup;
|
||||||
|
|
|
@ -17,7 +17,7 @@ const messages = defineMessages({
|
||||||
});
|
});
|
||||||
|
|
||||||
const StrokeColorIndicatorComponent = props => (
|
const StrokeColorIndicatorComponent = props => (
|
||||||
<InputGroup>
|
<InputGroup disabled={props.disabled}>
|
||||||
<Popover
|
<Popover
|
||||||
body={
|
body={
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
|
@ -31,6 +31,7 @@ const StrokeColorIndicatorComponent = props => (
|
||||||
>
|
>
|
||||||
<Label text={props.intl.formatMessage(messages.stroke)}>
|
<Label text={props.intl.formatMessage(messages.stroke)}>
|
||||||
<ColorButton
|
<ColorButton
|
||||||
|
outline
|
||||||
color={props.strokeColor}
|
color={props.strokeColor}
|
||||||
onClick={props.onOpenStrokeColor}
|
onClick={props.onOpenStrokeColor}
|
||||||
/>
|
/>
|
||||||
|
@ -40,6 +41,7 @@ const StrokeColorIndicatorComponent = props => (
|
||||||
);
|
);
|
||||||
|
|
||||||
StrokeColorIndicatorComponent.propTypes = {
|
StrokeColorIndicatorComponent.propTypes = {
|
||||||
|
disabled: PropTypes.bool.isRequired,
|
||||||
intl: intlShape,
|
intl: intlShape,
|
||||||
onChangeStrokeColor: PropTypes.func.isRequired,
|
onChangeStrokeColor: PropTypes.func.isRequired,
|
||||||
onCloseStrokeColor: PropTypes.func.isRequired,
|
onCloseStrokeColor: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -9,9 +9,10 @@ import {MAX_STROKE_WIDTH} from '../reducers/stroke-width';
|
||||||
|
|
||||||
const BufferedInput = BufferedInputHOC(Input);
|
const BufferedInput = BufferedInputHOC(Input);
|
||||||
const StrokeWidthIndicatorComponent = props => (
|
const StrokeWidthIndicatorComponent = props => (
|
||||||
<InputGroup>
|
<InputGroup disabled={props.disabled}>
|
||||||
<BufferedInput
|
<BufferedInput
|
||||||
small
|
small
|
||||||
|
disabled={props.disabled}
|
||||||
max={MAX_STROKE_WIDTH}
|
max={MAX_STROKE_WIDTH}
|
||||||
min="0"
|
min="0"
|
||||||
type="number"
|
type="number"
|
||||||
|
@ -22,6 +23,7 @@ const StrokeWidthIndicatorComponent = props => (
|
||||||
);
|
);
|
||||||
|
|
||||||
StrokeWidthIndicatorComponent.propTypes = {
|
StrokeWidthIndicatorComponent.propTypes = {
|
||||||
|
disabled: PropTypes.bool.isRequired,
|
||||||
onChangeStrokeWidth: PropTypes.func.isRequired,
|
onChangeStrokeWidth: PropTypes.func.isRequired,
|
||||||
strokeWidth: PropTypes.number
|
strokeWidth: PropTypes.number
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,9 @@ import {connect} from 'react-redux';
|
||||||
import bindAll from 'lodash.bindall';
|
import bindAll from 'lodash.bindall';
|
||||||
import Modes from '../modes/modes';
|
import Modes from '../modes/modes';
|
||||||
import Blobbiness from '../helper/blob-tools/blob';
|
import Blobbiness from '../helper/blob-tools/blob';
|
||||||
|
import {MIXED} from '../helper/style-path';
|
||||||
|
|
||||||
|
import {changeFillColor} from '../reducers/fill-color';
|
||||||
import {changeBrushSize} from '../reducers/brush-mode';
|
import {changeBrushSize} from '../reducers/brush-mode';
|
||||||
import {changeMode} from '../reducers/modes';
|
import {changeMode} from '../reducers/modes';
|
||||||
import {clearSelectedItems} from '../reducers/selected-items';
|
import {clearSelectedItems} from '../reducers/selected-items';
|
||||||
|
@ -13,6 +15,9 @@ import {clearSelection} from '../helper/selection';
|
||||||
import BrushModeComponent from '../components/brush-mode/brush-mode.jsx';
|
import BrushModeComponent from '../components/brush-mode/brush-mode.jsx';
|
||||||
|
|
||||||
class BrushMode extends React.Component {
|
class BrushMode extends React.Component {
|
||||||
|
static get DEFAULT_COLOR () {
|
||||||
|
return '#9966FF';
|
||||||
|
}
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
bindAll(this, [
|
bindAll(this, [
|
||||||
|
@ -49,6 +54,12 @@ class BrushMode extends React.Component {
|
||||||
// analogous to how selection works with eraser
|
// analogous to how selection works with eraser
|
||||||
clearSelection(this.props.clearSelectedItems);
|
clearSelection(this.props.clearSelectedItems);
|
||||||
|
|
||||||
|
// Force the default brush color if fill is MIXED or transparent
|
||||||
|
const {fillColor} = this.props.colorState;
|
||||||
|
if (fillColor === MIXED || fillColor === null) {
|
||||||
|
this.props.onChangeFillColor(BrushMode.DEFAULT_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: This is temporary until a component that provides the brush size is hooked up
|
// TODO: This is temporary until a component that provides the brush size is hooked up
|
||||||
this.props.canvas.addEventListener('mousewheel', this.onScroll);
|
this.props.canvas.addEventListener('mousewheel', this.onScroll);
|
||||||
this.blob.activateTool({
|
this.blob.activateTool({
|
||||||
|
@ -93,6 +104,7 @@ BrushMode.propTypes = {
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
handleMouseDown: PropTypes.func.isRequired,
|
handleMouseDown: PropTypes.func.isRequired,
|
||||||
isBrushModeActive: PropTypes.bool.isRequired,
|
isBrushModeActive: PropTypes.bool.isRequired,
|
||||||
|
onChangeFillColor: PropTypes.func.isRequired,
|
||||||
onUpdateSvg: PropTypes.func.isRequired
|
onUpdateSvg: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -110,6 +122,9 @@ const mapDispatchToProps = dispatch => ({
|
||||||
},
|
},
|
||||||
handleMouseDown: () => {
|
handleMouseDown: () => {
|
||||||
dispatch(changeMode(Modes.BRUSH));
|
dispatch(changeMode(Modes.BRUSH));
|
||||||
|
},
|
||||||
|
onChangeFillColor: fillColor => {
|
||||||
|
dispatch(changeFillColor(fillColor));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||||
import bindAll from 'lodash.bindall';
|
import bindAll from 'lodash.bindall';
|
||||||
import {changeFillColor} from '../reducers/fill-color';
|
import {changeFillColor} from '../reducers/fill-color';
|
||||||
import {openFillColor, closeFillColor} from '../reducers/modals';
|
import {openFillColor, closeFillColor} from '../reducers/modals';
|
||||||
|
import Modes from '../modes/modes';
|
||||||
|
|
||||||
import FillColorIndicatorComponent from '../components/fill-color-indicator.jsx';
|
import FillColorIndicatorComponent from '../components/fill-color-indicator.jsx';
|
||||||
import {applyFillColorToSelection} from '../helper/style-path';
|
import {applyFillColorToSelection} from '../helper/style-path';
|
||||||
|
@ -30,6 +31,7 @@ class FillColorIndicator extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
disabled: state.scratchPaint.mode === Modes.PEN,
|
||||||
fillColor: state.scratchPaint.color.fillColor,
|
fillColor: state.scratchPaint.color.fillColor,
|
||||||
fillColorModalVisible: state.scratchPaint.modals.fillColor
|
fillColorModalVisible: state.scratchPaint.modals.fillColor
|
||||||
});
|
});
|
||||||
|
@ -47,6 +49,7 @@ const mapDispatchToProps = dispatch => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
FillColorIndicator.propTypes = {
|
FillColorIndicator.propTypes = {
|
||||||
|
disabled: PropTypes.bool.isRequired,
|
||||||
fillColor: PropTypes.string,
|
fillColor: PropTypes.string,
|
||||||
onChangeFillColor: PropTypes.func.isRequired,
|
onChangeFillColor: PropTypes.func.isRequired,
|
||||||
onUpdateSvg: PropTypes.func.isRequired
|
onUpdateSvg: PropTypes.func.isRequired
|
||||||
|
|
|
@ -8,8 +8,11 @@ import {clearSelection} from '../helper/selection';
|
||||||
import {endPointHit, touching} from '../helper/snapping';
|
import {endPointHit, touching} from '../helper/snapping';
|
||||||
import {drawHitPoint, removeHitPoint} from '../helper/guides';
|
import {drawHitPoint, removeHitPoint} from '../helper/guides';
|
||||||
import {stylePath} from '../helper/style-path';
|
import {stylePath} from '../helper/style-path';
|
||||||
|
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||||
|
import {changeStrokeWidth} from '../reducers/stroke-width';
|
||||||
import {changeMode} from '../reducers/modes';
|
import {changeMode} from '../reducers/modes';
|
||||||
import {clearSelectedItems} from '../reducers/selected-items';
|
import {clearSelectedItems} from '../reducers/selected-items';
|
||||||
|
import {MIXED} from '../helper/style-path';
|
||||||
|
|
||||||
import LineModeComponent from '../components/line-mode/line-mode.jsx';
|
import LineModeComponent from '../components/line-mode/line-mode.jsx';
|
||||||
|
|
||||||
|
@ -17,6 +20,9 @@ class LineMode extends React.Component {
|
||||||
static get SNAP_TOLERANCE () {
|
static get SNAP_TOLERANCE () {
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
static get DEFAULT_COLOR () {
|
||||||
|
return '#000000';
|
||||||
|
}
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
bindAll(this, [
|
bindAll(this, [
|
||||||
|
@ -46,6 +52,16 @@ class LineMode extends React.Component {
|
||||||
}
|
}
|
||||||
activateTool () {
|
activateTool () {
|
||||||
clearSelection(this.props.clearSelectedItems);
|
clearSelection(this.props.clearSelectedItems);
|
||||||
|
|
||||||
|
// Force the default line color if stroke is MIXED or transparent
|
||||||
|
const {strokeColor} = this.props.colorState;
|
||||||
|
if (strokeColor === MIXED || strokeColor === null) {
|
||||||
|
this.props.onChangeStrokeColor(LineMode.DEFAULT_COLOR);
|
||||||
|
}
|
||||||
|
// Force a minimum stroke width
|
||||||
|
if (!this.props.colorState.strokeWidth) {
|
||||||
|
this.props.onChangeStrokeWidth(1);
|
||||||
|
}
|
||||||
this.tool = new paper.Tool();
|
this.tool = new paper.Tool();
|
||||||
|
|
||||||
this.path = null;
|
this.path = null;
|
||||||
|
@ -220,6 +236,8 @@ LineMode.propTypes = {
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
handleMouseDown: PropTypes.func.isRequired,
|
handleMouseDown: PropTypes.func.isRequired,
|
||||||
isLineModeActive: PropTypes.bool.isRequired,
|
isLineModeActive: PropTypes.bool.isRequired,
|
||||||
|
onChangeStrokeColor: PropTypes.func.isRequired,
|
||||||
|
onChangeStrokeWidth: PropTypes.func.isRequired,
|
||||||
onUpdateSvg: PropTypes.func.isRequired
|
onUpdateSvg: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -233,6 +251,12 @@ const mapDispatchToProps = dispatch => ({
|
||||||
},
|
},
|
||||||
handleMouseDown: () => {
|
handleMouseDown: () => {
|
||||||
dispatch(changeMode(Modes.LINE));
|
dispatch(changeMode(Modes.LINE));
|
||||||
|
},
|
||||||
|
onChangeStrokeColor: strokeColor => {
|
||||||
|
dispatch(changeStrokeColor(strokeColor));
|
||||||
|
},
|
||||||
|
onChangeStrokeWidth: strokeWidth => {
|
||||||
|
dispatch(changeStrokeWidth(strokeWidth));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,20 @@ import {connect} from 'react-redux';
|
||||||
import bindAll from 'lodash.bindall';
|
import bindAll from 'lodash.bindall';
|
||||||
import Modes from '../modes/modes';
|
import Modes from '../modes/modes';
|
||||||
|
|
||||||
|
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||||
|
import {changeStrokeWidth} from '../reducers/stroke-width';
|
||||||
import {changeMode} from '../reducers/modes';
|
import {changeMode} from '../reducers/modes';
|
||||||
import {clearSelectedItems} from '../reducers/selected-items';
|
import {clearSelectedItems} from '../reducers/selected-items';
|
||||||
|
import {MIXED} from '../helper/style-path';
|
||||||
|
|
||||||
import {clearSelection} from '../helper/selection';
|
import {clearSelection} from '../helper/selection';
|
||||||
import PenTool from '../helper/tools/pen-tool';
|
import PenTool from '../helper/tools/pen-tool';
|
||||||
import PenModeComponent from '../components/pen-mode/pen-mode.jsx';
|
import PenModeComponent from '../components/pen-mode/pen-mode.jsx';
|
||||||
|
|
||||||
class PenMode extends React.Component {
|
class PenMode extends React.Component {
|
||||||
|
static get DEFAULT_COLOR () {
|
||||||
|
return '#000000';
|
||||||
|
}
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
bindAll(this, [
|
bindAll(this, [
|
||||||
|
@ -42,6 +48,15 @@ class PenMode extends React.Component {
|
||||||
}
|
}
|
||||||
activateTool () {
|
activateTool () {
|
||||||
clearSelection(this.props.clearSelectedItems);
|
clearSelection(this.props.clearSelectedItems);
|
||||||
|
// Force the default pen color if stroke is MIXED or transparent
|
||||||
|
const {strokeColor} = this.props.colorState;
|
||||||
|
if (strokeColor === MIXED || strokeColor === null) {
|
||||||
|
this.props.onChangeStrokeColor(PenMode.DEFAULT_COLOR);
|
||||||
|
}
|
||||||
|
// Force a minimum stroke width
|
||||||
|
if (!this.props.colorState.strokeWidth) {
|
||||||
|
this.props.onChangeStrokeWidth(1);
|
||||||
|
}
|
||||||
this.tool = new PenTool(
|
this.tool = new PenTool(
|
||||||
this.props.clearSelectedItems,
|
this.props.clearSelectedItems,
|
||||||
this.props.onUpdateSvg
|
this.props.onUpdateSvg
|
||||||
|
@ -73,6 +88,8 @@ PenMode.propTypes = {
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
handleMouseDown: PropTypes.func.isRequired,
|
handleMouseDown: PropTypes.func.isRequired,
|
||||||
isPenModeActive: PropTypes.bool.isRequired,
|
isPenModeActive: PropTypes.bool.isRequired,
|
||||||
|
onChangeStrokeColor: PropTypes.func.isRequired,
|
||||||
|
onChangeStrokeWidth: PropTypes.func.isRequired,
|
||||||
onUpdateSvg: PropTypes.func.isRequired
|
onUpdateSvg: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,6 +106,12 @@ const mapDispatchToProps = dispatch => ({
|
||||||
dispatch(changeMode(Modes.PEN));
|
dispatch(changeMode(Modes.PEN));
|
||||||
},
|
},
|
||||||
deactivateTool () {
|
deactivateTool () {
|
||||||
|
},
|
||||||
|
onChangeStrokeColor: strokeColor => {
|
||||||
|
dispatch(changeStrokeColor(strokeColor));
|
||||||
|
},
|
||||||
|
onChangeStrokeWidth: strokeWidth => {
|
||||||
|
dispatch(changeStrokeWidth(strokeWidth));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||||
import bindAll from 'lodash.bindall';
|
import bindAll from 'lodash.bindall';
|
||||||
import {changeStrokeColor} from '../reducers/stroke-color';
|
import {changeStrokeColor} from '../reducers/stroke-color';
|
||||||
import {openStrokeColor, closeStrokeColor} from '../reducers/modals';
|
import {openStrokeColor, closeStrokeColor} from '../reducers/modals';
|
||||||
|
import Modes from '../modes/modes';
|
||||||
|
|
||||||
import StrokeColorIndicatorComponent from '../components/stroke-color-indicator.jsx';
|
import StrokeColorIndicatorComponent from '../components/stroke-color-indicator.jsx';
|
||||||
import {applyStrokeColorToSelection} from '../helper/style-path';
|
import {applyStrokeColorToSelection} from '../helper/style-path';
|
||||||
|
@ -30,6 +31,7 @@ class StrokeColorIndicator extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
disabled: state.scratchPaint.mode === Modes.BRUSH,
|
||||||
strokeColor: state.scratchPaint.color.strokeColor,
|
strokeColor: state.scratchPaint.color.strokeColor,
|
||||||
strokeColorModalVisible: state.scratchPaint.modals.strokeColor
|
strokeColorModalVisible: state.scratchPaint.modals.strokeColor
|
||||||
});
|
});
|
||||||
|
@ -47,6 +49,7 @@ const mapDispatchToProps = dispatch => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
StrokeColorIndicator.propTypes = {
|
StrokeColorIndicator.propTypes = {
|
||||||
|
disabled: PropTypes.bool.isRequired,
|
||||||
onChangeStrokeColor: PropTypes.func.isRequired,
|
onChangeStrokeColor: PropTypes.func.isRequired,
|
||||||
onUpdateSvg: PropTypes.func.isRequired,
|
onUpdateSvg: PropTypes.func.isRequired,
|
||||||
strokeColor: PropTypes.string
|
strokeColor: PropTypes.string
|
||||||
|
|
|
@ -5,6 +5,7 @@ import bindAll from 'lodash.bindall';
|
||||||
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 {applyStrokeWidthToSelection} from '../helper/style-path';
|
import {applyStrokeWidthToSelection} from '../helper/style-path';
|
||||||
|
import Modes from '../modes/modes';
|
||||||
|
|
||||||
class StrokeWidthIndicator extends React.Component {
|
class StrokeWidthIndicator extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
@ -20,6 +21,7 @@ class StrokeWidthIndicator extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<StrokeWidthIndicatorComponent
|
<StrokeWidthIndicatorComponent
|
||||||
|
disabled={this.props.disabled}
|
||||||
strokeWidth={this.props.strokeWidth}
|
strokeWidth={this.props.strokeWidth}
|
||||||
onChangeStrokeWidth={this.handleChangeStrokeWidth}
|
onChangeStrokeWidth={this.handleChangeStrokeWidth}
|
||||||
/>
|
/>
|
||||||
|
@ -28,6 +30,7 @@ class StrokeWidthIndicator extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
disabled: state.scratchPaint.mode === Modes.BRUSH,
|
||||||
strokeWidth: state.scratchPaint.color.strokeWidth
|
strokeWidth: state.scratchPaint.color.strokeWidth
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
@ -37,6 +40,7 @@ const mapDispatchToProps = dispatch => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
StrokeWidthIndicator.propTypes = {
|
StrokeWidthIndicator.propTypes = {
|
||||||
|
disabled: PropTypes.bool.isRequired,
|
||||||
onChangeStrokeWidth: PropTypes.func.isRequired,
|
onChangeStrokeWidth: PropTypes.func.isRequired,
|
||||||
onUpdateSvg: PropTypes.func.isRequired,
|
onUpdateSvg: PropTypes.func.isRequired,
|
||||||
strokeWidth: PropTypes.number
|
strokeWidth: PropTypes.number
|
||||||
|
|
Loading…
Reference in a new issue