scratch-paint/src/helper/tools/rect-tool.js

119 lines
4 KiB
JavaScript
Raw Normal View History

import paper from '@scratch/paper';
2017-10-19 16:52:24 -04:00
import Modes from '../../modes/modes';
import {styleShape} from '../style-path';
import {clearSelection} from '../selection';
2017-10-19 16:52:24 -04:00
import BoundingBoxTool from '../selection-tools/bounding-box-tool';
/**
* Tool for drawing rectangles.
*/
class RectTool extends paper.Tool {
2017-10-19 18:29:32 -04:00
static get TOLERANCE () {
return 6;
}
/**
* @param {function} setSelectedItems Callback to set the set of selected items in the Redux state
* @param {function} clearSelectedItems Callback to clear the set of selected items in the Redux state
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
*/
constructor (setSelectedItems, clearSelectedItems, onUpdateSvg) {
super();
2017-10-19 18:29:32 -04:00
this.clearSelectedItems = clearSelectedItems;
this.onUpdateSvg = onUpdateSvg;
this.prevHoveredItemId = null;
this.boundingBoxTool = new BoundingBoxTool(Modes.RECT, setSelectedItems, clearSelectedItems, onUpdateSvg);
// We have to set these functions instead of just declaring them because
// paper.js tools hook up the listeners in the setter functions.
2017-10-19 18:29:32 -04:00
this.onMouseDown = this.handleMouseDown;
this.onMouseDrag = this.handleMouseDrag;
this.onMouseUp = this.handleMouseUp;
2017-10-19 16:52:24 -04:00
this.rect = null;
this.colorState = null;
2017-10-19 18:29:32 -04:00
this.isBoundingBoxMode = null;
}
getHitOptions () {
return {
segments: true,
stroke: true,
curves: true,
fill: true,
guide: false,
match: hitResult =>
(hitResult.item.data && hitResult.item.data.isHelperItem) ||
hitResult.item.selected, // Allow hits on bounding box and selected only
tolerance: RectTool.TOLERANCE / paper.view.zoom
};
}
2017-10-23 15:38:52 -04:00
/**
* Should be called if the selection changes to update the bounds of the bounding box.
* @param {Array<paper.Item>} selectedItems Array of selected items.
*/
onSelectionChanged (selectedItems) {
this.boundingBoxTool.onSelectionChanged(selectedItems);
}
2017-10-19 16:52:24 -04:00
setColorState (colorState) {
this.colorState = colorState;
}
2017-10-19 18:29:32 -04:00
handleMouseDown (event) {
2017-10-19 20:43:28 -04:00
if (this.boundingBoxTool.onMouseDown(event, false /* clone */, false /* multiselect */, this.getHitOptions())) {
2017-10-19 18:29:32 -04:00
this.isBoundingBoxMode = true;
} else {
this.isBoundingBoxMode = false;
clearSelection(this.clearSelectedItems);
}
}
2017-10-19 16:52:24 -04:00
handleMouseDrag (event) {
2017-10-19 20:43:28 -04:00
if (event.event.button > 0) return; // only first mouse button
2017-10-19 16:52:24 -04:00
2017-10-19 18:29:32 -04:00
if (this.isBoundingBoxMode) {
this.boundingBoxTool.onMouseDrag(event);
return;
}
2017-10-19 16:52:24 -04:00
if (this.rect) {
this.rect.remove();
}
2017-10-19 18:29:32 -04:00
const rect = new paper.Rectangle(event.downPoint, event.point);
2017-10-19 16:52:24 -04:00
if (event.modifiers.shift) {
2017-10-19 18:29:32 -04:00
rect.height = rect.width;
2017-10-19 16:52:24 -04:00
}
2017-10-19 18:29:32 -04:00
this.rect = new paper.Path.Rectangle(rect);
2017-10-19 16:52:24 -04:00
if (event.modifiers.alt) {
this.rect.position = event.downPoint;
}
styleShape(this.rect, this.colorState);
}
2017-10-19 16:52:24 -04:00
handleMouseUp (event) {
2017-10-19 20:43:28 -04:00
if (event.event.button > 0) return; // only first mouse button
2017-10-19 16:52:24 -04:00
2017-10-19 18:29:32 -04:00
if (this.isBoundingBoxMode) {
this.boundingBoxTool.onMouseUp(event);
this.isBoundingBoxMode = null;
return;
}
2017-10-19 16:52:24 -04:00
if (this.rect) {
2017-10-19 20:43:28 -04:00
if (this.rect.area < RectTool.TOLERANCE / paper.view.zoom) {
// Tiny rectangle created unintentionally?
this.rect.remove();
this.rect = null;
} else {
this.rect.selected = true;
this.boundingBoxTool.setSelectionBounds();
this.onUpdateSvg();
this.rect = null;
}
2017-10-19 16:52:24 -04:00
}
}
deactivateTool () {
2017-10-19 18:29:32 -04:00
this.boundingBoxTool.removeBoundsPath();
}
}
export default RectTool;