add comments and clean up

This commit is contained in:
DD 2017-09-22 12:12:07 -04:00
parent dc66283bd2
commit 5db66af0a1
12 changed files with 109 additions and 90 deletions

View file

@ -4,5 +4,7 @@
margin: auto;
position: relative;
background-color: #fff;
/* Turn off anti-aliasing for the drawing canvas. Each time it's updated it switches
back and forth from aliased to unaliased and that looks bad */
image-rendering: pixelated;
}

View file

@ -3,7 +3,7 @@ import React from 'react';
import {connect} from 'react-redux';
import paper from 'paper';
const SelectionHOV = function (WrappedComponent) {
const SelectionHOC = function (WrappedComponent) {
class SelectionComponent extends React.Component {
componentDidMount () {
if (this.props.hoveredItem) {
@ -43,4 +43,4 @@ const SelectionHOV = function (WrappedComponent) {
)(SelectionComponent);
};
export default SelectionHOV;
export default SelectionHOC;

View file

@ -1,6 +1,6 @@
import paper from 'paper';
import {getGuideLayer} from './layer';
import {removePaperItemsByTags, removePaperItemsByDataTags} from './helper';
import {getAllPaperItems} from './selection';
const GUIDE_BLUE = '#009dec';
const GUIDE_GREY = '#aaaaaa';
@ -65,12 +65,34 @@ const getGuideColor = function (colorName) {
}
};
const _removePaperItemsByDataTags = function (tags) {
const allItems = getAllPaperItems(true);
for (const item of allItems) {
for (const tag of tags) {
if (item.data && item.data[tag]) {
item.remove();
}
}
}
};
const _removePaperItemsByTags = function (tags) {
const allItems = getAllPaperItems(true);
for (const item of allItems) {
for (const tag of tags) {
if (item[tag]) {
item.remove();
}
}
}
};
const removeHelperItems = function () {
removePaperItemsByDataTags(['isHelperItem']);
_removePaperItemsByDataTags(['isHelperItem']);
};
const removeAllGuides = function () {
removePaperItemsByTags(['guide']);
_removePaperItemsByTags(['guide']);
};
export {

View file

@ -1,63 +0,0 @@
import paper from 'paper';
/**
* @param {boolean} includeGuides True if guide layer items like the bounding box should
* be included in the returned items.
* @return {Array<paper.item>} all top-level (direct descendants of a paper.Layer) items
*/
const getAllPaperItems = function (includeGuides) {
includeGuides = includeGuides || false;
const allItems = [];
for (const layer of paper.project.layers) {
for (const child of layer.children) {
// don't give guides back
if (!includeGuides && child.guide) {
continue;
}
allItems.push(child);
}
}
return allItems;
};
const getPaperItemsByTags = function (tags) {
const allItems = getAllPaperItems(true);
const foundItems = [];
for (const item of allItems) {
for (const tag of tags) {
if (item[tag] && foundItems.indexOf(item) === -1) {
foundItems.push(item);
}
}
}
return foundItems;
};
const removePaperItemsByDataTags = function (tags) {
const allItems = getAllPaperItems(true);
for (const item of allItems) {
for (const tag of tags) {
if (item.data && item.data[tag]) {
item.remove();
}
}
}
};
const removePaperItemsByTags = function (tags) {
const allItems = getAllPaperItems(true);
for (const item of allItems) {
for (const tag of tags) {
if (item[tag]) {
item.remove();
}
}
}
};
export {
getAllPaperItems,
getPaperItemsByTags,
removePaperItemsByDataTags,
removePaperItemsByTags
};

View file

@ -24,7 +24,7 @@ const Modes = keyMirror({
});
/**
* A paper.Tool that handles transforming the selection and drawing a bounding box with handles.
* Tool that handles transforming the selection and drawing a bounding box with handles.
* On mouse down, the type of function (move, scale, rotate) is determined based on what is clicked
* (scale handle, rotate handle, the object itself). This determines the mode of the tool, which then
* delegates actions to the MoveTool, RotateTool or ScaleTool accordingly.

View file

@ -3,6 +3,9 @@ import {isCompoundPathItem, getRootItem} from '../item';
import {snapDeltaToAngle} from '../math';
import {clearSelection, cloneSelection, getSelectedItems, setItemSelection} from '../selection';
/**
* Tool to handle dragging an item to reposition it in a selection mode.
*/
class MoveTool {
/**
* @param {!function} onUpdateSvg A callback to call when the image visibly changes

View file

@ -1,5 +1,8 @@
import paper from 'paper';
/**
* Tool to handle rotation when dragging the rotation handle in the bounding box tool.
*/
class RotateTool {
/**
* @param {!function} onUpdateSvg A callback to call when the image visibly changes

View file

@ -1,5 +1,9 @@
import paper from 'paper';
/**
* Tool to handle scaling items by pulling on the handles around the edges of the bounding
* box when in the bounding box tool.
*/
class ScaleTool {
/**
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
@ -34,9 +38,9 @@ class ScaleTool {
this.boundsPath = boundsPath;
this.boundsScaleHandles = boundsScaleHandles;
this.boundsRotHandles = boundsRotHandles;
this.pivot = this.boundsPath.bounds[this.getOpposingRectCornerNameByIndex(index)].clone();
this.origPivot = this.boundsPath.bounds[this.getOpposingRectCornerNameByIndex(index)].clone();
this.corner = this.boundsPath.bounds[this.getRectCornerNameByIndex(index)].clone();
this.pivot = this.boundsPath.bounds[this._getOpposingRectCornerNameByIndex(index)].clone();
this.origPivot = this.boundsPath.bounds[this._getOpposingRectCornerNameByIndex(index)].clone();
this.corner = this.boundsPath.bounds[this._getRectCornerNameByIndex(index)].clone();
this.origSize = this.corner.subtract(this.pivot);
this.origCenter = this.boundsPath.bounds.center;
for (const item of selectedItems) {
@ -105,14 +109,14 @@ class ScaleTool {
for (let i = 0; i < this.boundsScaleHandles.length; i++) {
const handle = this.boundsScaleHandles[i];
handle.position = this.itemGroup.bounds[this.getRectCornerNameByIndex(i)];
handle.position = this.itemGroup.bounds[this._getRectCornerNameByIndex(i)];
handle.bringToFront();
}
for (let i = 0; i < this.boundsRotHandles.length; i++) {
const handle = this.boundsRotHandles[i];
if (handle) {
handle.position = this.itemGroup.bounds[this.getRectCornerNameByIndex(i)] + handle.data.offset;
handle.position = this.itemGroup.bounds[this._getRectCornerNameByIndex(i)] + handle.data.offset;
handle.bringToFront();
}
}
@ -156,7 +160,7 @@ class ScaleTool {
// @todo add back undo
this.onUpdateSvg();
}
getRectCornerNameByIndex (index) {
_getRectCornerNameByIndex (index) {
switch (index) {
case 0:
return 'bottomLeft';
@ -176,7 +180,7 @@ class ScaleTool {
return 'bottomCenter';
}
}
getOpposingRectCornerNameByIndex (index) {
_getOpposingRectCornerNameByIndex (index) {
switch (index) {
case 0:
return 'topRight';

View file

@ -6,10 +6,23 @@ import BoundingBoxTool from './bounding-box-tool';
import SelectionBoxTool from './selection-box-tool';
import paper from 'paper';
/**
* paper.Tool that handles select mode. This is made up of 2 subtools.
* - The selection box tool is active when the user clicks an empty space and drags.
* It selects all items in the rectangle.
* - The bounding box tool is active if the user clicks on a non-empty space. It handles
* reshaping the item that was clicked.
*/
class SelectTool extends paper.Tool {
/** The distance within which mouse events count as a hit against an item */
static get TOLERANCE () {
return 6;
}
/**
* @param {function} setHoveredItem Callback to set the hovered item
* @param {function} clearHoveredItem Callback to clear the hovered item
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
*/
constructor (setHoveredItem, clearHoveredItem, onUpdateSvg) {
super();
this.setHoveredItem = setHoveredItem;
@ -18,13 +31,6 @@ class SelectTool extends paper.Tool {
this.boundingBoxTool = new BoundingBoxTool(onUpdateSvg);
this.selectionBoxTool = new SelectionBoxTool(Modes.SELECT);
this.selectionBoxMode = false;
this._hitOptions = {
segments: true,
stroke: true,
curves: true,
fill: true,
guide: false
};
// We have to set these functions instead of just declaring them because
// paper.js tools hook up the listeners in the setter functions.
@ -37,21 +43,42 @@ class SelectTool extends paper.Tool {
selectRootItem();
this.boundingBoxTool.setSelectionBounds();
}
/**
* To be called when the hovered item changes. When the select tool hovers over a
* new item, it compares against this to see if a hover item change event needs to
* be fired.
* @param {paper.Item} prevHoveredItem The highlight that indicates the mouse is over
* a given item currently
*/
setPrevHoveredItem (prevHoveredItem) {
this.prevHoveredItem = prevHoveredItem;
}
/**
* Returns the hit options to use when conducting hit tests.
* @param {boolean} preselectedOnly True if we should only return results that are already
* selected.
* @return {object} See paper.Item.hitTest for definition of options
*/
getHitOptions (preselectedOnly) {
this._hitOptions.tolerance = SelectTool.TOLERANCE / paper.view.zoom;
// Tolerance needs to be scaled when the view is zoomed in in order to represent the same
// distance for the user to move the mouse.
const hitOptions = {
segments: true,
stroke: true,
curves: true,
fill: true,
guide: false,
tolerance: SelectTool.TOLERANCE / paper.view.zoom
};
if (preselectedOnly) {
this._hitOptions.selected = true;
} else {
delete this._hitOptions.selected;
hitOptions.selected = true;
}
return this._hitOptions;
return hitOptions;
}
handleMouseDown (event) {
if (event.event.button > 0) return; // only first mouse button
// If bounding box tool does not find an item that was hit, use selection box tool.
this.clearHoveredItem();
if (!this.boundingBoxTool
.onMouseDown(

View file

@ -1,6 +1,7 @@
import {rectSelect} from '../guides';
import {clearSelection, processRectangularSelection} from '../selection';
/** Tool to handle drag selection. A dotted line box appears and everything enclosed is selected. */
class SelectionBoxTool {
constructor (mode) {
this.selectionRect = null;

View file

@ -1,11 +1,30 @@
import paper from 'paper';
import Modes from '../modes/modes';
import {getAllPaperItems} from './helper';
import {getItemsGroup, isGroup} from './group';
import {getRootItem, isCompoundPathItem, isBoundsItem, isPathItem, isPGTextItem} from './item';
import {getItemsCompoundPath, isCompoundPath, isCompoundPathChild} from './compound-path';
/**
* @param {boolean} includeGuides True if guide layer items like the bounding box should
* be included in the returned items.
* @return {Array<paper.item>} all top-level (direct descendants of a paper.Layer) items
*/
const getAllPaperItems = function (includeGuides) {
includeGuides = includeGuides || false;
const allItems = [];
for (const layer of paper.project.layers) {
for (const child of layer.children) {
// don't give guides back
if (!includeGuides && child.guide) {
continue;
}
allItems.push(child);
}
}
return allItems;
};
/**
* @return {Array<paper.item>} all top-level (direct descendants of a paper.Layer) items
* that aren't guide items or helper items.
@ -489,6 +508,7 @@ const shouldShowSelectAll = function () {
};
export {
getAllPaperItems,
selectAllItems,
selectAllSegments,
clearSelection,

View file

@ -1,5 +1,5 @@
import PaintEditor from './containers/paint-editor.jsx';
import SelectionHOV from './containers/selection-hov.jsx';
import SelectionHOV from './containers/selection-hoc.jsx';
import ScratchPaintReducer from './reducers/scratch-paint-reducer';
const Wrapped = SelectionHOV(PaintEditor);