This commit is contained in:
DD 2018-03-22 14:06:51 -04:00
parent 86ee3d8cdd
commit c75d3f63ba
3 changed files with 56 additions and 15 deletions

View file

@ -7,6 +7,7 @@ import {changeMode} from '../reducers/modes';
import {undo, redo, undoSnapshot} from '../reducers/undo'; import {undo, redo, undoSnapshot} from '../reducers/undo';
import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items'; import {clearSelectedItems, setSelectedItems} from '../reducers/selected-items';
import {deactivateEyeDropper} from '../reducers/eye-dropper'; import {deactivateEyeDropper} from '../reducers/eye-dropper';
import {setTextEditTarget} from '../reducers/text-edit-target';
import {hideGuideLayers, showGuideLayers} from '../helper/layer'; import {hideGuideLayers, showGuideLayers} from '../helper/layer';
import {performUndo, performRedo, performSnapshot, shouldShowUndo, shouldShowRedo} from '../helper/undo'; import {performUndo, performRedo, performSnapshot, shouldShowUndo, shouldShowRedo} from '../helper/undo';
@ -15,6 +16,7 @@ import {groupSelection, ungroupSelection} from '../helper/group';
import {getSelectedLeafItems} from '../helper/selection'; import {getSelectedLeafItems} from '../helper/selection';
import {resetZoom, zoomOnSelection} from '../helper/view'; import {resetZoom, zoomOnSelection} from '../helper/view';
import EyeDropperTool from '../helper/tools/eye-dropper'; import EyeDropperTool from '../helper/tools/eye-dropper';
import styles from '../components/paint-editor/paint-editor.css'
import Modes from '../lib/modes'; import Modes from '../lib/modes';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
@ -155,6 +157,12 @@ class PaintEditor extends React.Component {
document.activeElement.blur(); document.activeElement.blur();
} }
if (event.target !== paper.view.element && !event.target.classList.contains(styles.textArea)) {
debugger;
// Exit text edit mode if you click anywhere outside of canvas
this.props.removeTextEditTarget();
}
if (this.props.isEyeDropping) { if (this.props.isEyeDropping) {
const colorString = this.eyeDropper.colorString; const colorString = this.eyeDropper.colorString;
const callback = this.props.changeColorToEyeDropper; const callback = this.props.changeColorToEyeDropper;
@ -303,6 +311,9 @@ const mapDispatchToProps = dispatch => ({
clearSelectedItems: () => { clearSelectedItems: () => {
dispatch(clearSelectedItems()); dispatch(clearSelectedItems());
}, },
removeTextEditTarget: () => {
dispatch(setTextEditTarget());
},
setSelectedItems: () => { setSelectedItems: () => {
dispatch(setSelectedItems(getSelectedLeafItems())); dispatch(setSelectedItems(getSelectedLeafItems()));
}, },

View file

@ -36,6 +36,9 @@ class TextMode extends React.Component {
if (this.tool && nextProps.selectedItems !== this.props.selectedItems) { if (this.tool && nextProps.selectedItems !== this.props.selectedItems) {
this.tool.onSelectionChanged(nextProps.selectedItems); this.tool.onSelectionChanged(nextProps.selectedItems);
} }
if (this.tool && !nextProps.textEditTarget && this.props.textEditTarget) {
this.tool.onTextEditCancelled();
}
if (nextProps.isTextModeActive && !this.props.isTextModeActive) { if (nextProps.isTextModeActive && !this.props.isTextModeActive) {
this.activateTool(); this.activateTool();
@ -103,13 +106,15 @@ TextMode.propTypes = {
selectedItems: PropTypes.arrayOf(PropTypes.instanceOf(paper.Item)), selectedItems: PropTypes.arrayOf(PropTypes.instanceOf(paper.Item)),
setSelectedItems: PropTypes.func.isRequired, setSelectedItems: PropTypes.func.isRequired,
setTextEditTarget: PropTypes.func.isRequired, setTextEditTarget: PropTypes.func.isRequired,
textArea: PropTypes.instanceOf(Element) textArea: PropTypes.instanceOf(Element),
textEditTarget: PropTypes.number
}; };
const mapStateToProps = state => ({ const mapStateToProps = state => ({
colorState: state.scratchPaint.color, colorState: state.scratchPaint.color,
isTextModeActive: state.scratchPaint.mode === Modes.TEXT, isTextModeActive: state.scratchPaint.mode === Modes.TEXT,
selectedItems: state.scratchPaint.selectedItems selectedItems: state.scratchPaint.selectedItems,
textEditTarget: state.scratchPaint.textEditTarget
}); });
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
clearSelectedItems: () => { clearSelectedItems: () => {

View file

@ -24,6 +24,10 @@ class TextTool extends paper.Tool {
static get DOUBLE_CLICK_MILLIS () { static get DOUBLE_CLICK_MILLIS () {
return 250; return 250;
} }
/** Typing with no pauses longer than this amount of type will count as 1 action */
static get TYPING_TIMEOUT_MILLIS () {
return 1000;
}
static get TEXT_PADDING () { static get TEXT_PADDING () {
return 8; return 8;
} }
@ -59,6 +63,7 @@ class TextTool extends paper.Tool {
this.colorState = null; this.colorState = null;
this.mode = null; this.mode = null;
this.active = false; this.active = false;
this.lastTypeEvent = null;
// If text selected and then activate this tool, switch to text edit mode for that text // If text selected and then activate this tool, switch to text edit mode for that text
// If double click on text while in select mode, does mode change to text mode? Text fully selected by default // If double click on text while in select mode, does mode change to text mode? Text fully selected by default
@ -95,6 +100,10 @@ class TextTool extends paper.Tool {
onSelectionChanged (selectedItems) { onSelectionChanged (selectedItems) {
this.boundingBoxTool.onSelectionChanged(selectedItems); this.boundingBoxTool.onSelectionChanged(selectedItems);
} }
// Allow other tools to cancel text edit mode
onTextEditCancelled () {
this.endTextEdit();
}
setColorState (colorState) { setColorState (colorState) {
this.colorState = colorState; this.colorState = colorState;
} }
@ -110,12 +119,6 @@ class TextTool extends paper.Tool {
if (event.event.button > 0) return; // only first mouse button if (event.event.button > 0) return; // only first mouse button
this.active = true; this.active = true;
// Remove invisible textboxes
if (this.textBox && this.textBox.content.trim() === '') {
this.textBox.remove();
this.textBox = null;
}
// Check if double clicked // Check if double clicked
let doubleClicked = false; let doubleClicked = false;
if (this.lastEvent) { if (this.lastEvent) {
@ -142,10 +145,12 @@ class TextTool extends paper.Tool {
return; return;
} }
const lastMode = this.mode;
// We clicked away from the item, so end the current mode // We clicked away from the item, so end the current mode
if (this.mode === TextTool.SELECT_MODE) { if (lastMode === TextTool.SELECT_MODE) {
clearSelection(this.clearSelectedItems); clearSelection(this.clearSelectedItems);
} else if (this.mode === TextTool.TEXT_EDIT_MODE) { this.mode = null;
} else if (lastMode === TextTool.TEXT_EDIT_MODE) {
this.endTextEdit(); this.endTextEdit();
} }
@ -154,14 +159,12 @@ class TextTool extends paper.Tool {
// Clicking a different text item to begin text edit mode on that item // Clicking a different text item to begin text edit mode on that item
this.textBox = hitResults[0].item; this.textBox = hitResults[0].item;
this.beginTextEdit(this.textBox.content, this.textBox.matrix); this.beginTextEdit(this.textBox.content, this.textBox.matrix);
} else if (this.mode === TextTool.TEXT_EDIT_MODE) { } else if (lastMode === TextTool.TEXT_EDIT_MODE) {
// In text mode clicking away to begin select mode // In text mode clicking away to begin select mode
if (this.textBox) { if (this.textBox) {
this.mode = TextTool.SELECT_MODE; this.mode = TextTool.SELECT_MODE;
this.textBox.selected = true; this.textBox.selected = true;
this.setSelectedItems(); this.setSelectedItems();
} else {
this.mode = null;
} }
} else { } else {
// In no mode or select mode clicking away to begin text edit mode // In no mode or select mode clicking away to begin text edit mode
@ -214,7 +217,12 @@ class TextTool extends paper.Tool {
this.nudgeTool.onKeyUp(event); this.nudgeTool.onKeyUp(event);
} }
} }
handleTextInput () { handleTextInput (event) {
// Save undo state if you paused typing for long enough.
if (this.lastTypeEvent && event.timeStamp - this.lastTypeEvent.timeStamp > TextTool.TYPING_TIMEOUT_MILLIS) {
this.onUpdateSvg();
}
this.lastTypeEvent = event;
if (this.mode === TextTool.TEXT_EDIT_MODE) { if (this.mode === TextTool.TEXT_EDIT_MODE) {
this.textBox.content = this.element.value; this.textBox.content = this.element.value;
} }
@ -237,7 +245,6 @@ class TextTool extends paper.Tool {
this.setTextEditTarget(this.textBox.id); this.setTextEditTarget(this.textBox.id);
// TODO text not positioned correctly when zoomed in // TODO text not positioned correctly when zoomed in
// TODO holding shift when rotating in select mode does weird things
// TODO undo states // TODO undo states
this.element.style.display = 'initial'; this.element.style.display = 'initial';
@ -259,6 +266,18 @@ class TextTool extends paper.Tool {
this.resizeGuide(); this.resizeGuide();
} }
endTextEdit () { endTextEdit () {
if (this.mode !== TextTool.TEXT_EDIT_MODE) {
return;
}
this.mode = null;
// Remove invisible textboxes
if (this.textBox && this.textBox.content.trim() === '') {
this.textBox.remove();
this.textBox = null;
}
// Remove guide
if (this.guide) { if (this.guide) {
this.guide.remove(); this.guide.remove();
this.guide = null; this.guide = null;
@ -269,6 +288,12 @@ class TextTool extends paper.Tool {
this.element.removeEventListener('input', this.eventListener); this.element.removeEventListener('input', this.eventListener);
this.eventListener = null; this.eventListener = null;
} }
this.lastTypeEvent = null;
// If you finished editing a textbox, save undo state
if (this.textBox && this.textBox.content.trim().length) {
this.onUpdateSvg();
}
} }
deactivateTool () { deactivateTool () {
if (this.textBox && this.textBox.content.trim() === '') { if (this.textBox && this.textBox.content.trim() === '') {