scratch-paint/src/helper/selection-tools/handle-tool.js

75 lines
3.2 KiB
JavaScript
Raw Normal View History

2017-09-21 10:36:26 -04:00
import {clearSelection, getSelectedItems} from '../selection';
2017-09-22 14:14:48 -04:00
/** Sub tool of the Reshape tool for moving handles, which adjust bezier curves. */
2017-09-21 10:36:26 -04:00
class HandleTool {
2017-09-21 18:20:44 -04:00
/**
* @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
2017-09-21 18:20:44 -04:00
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
*/
constructor (setSelectedItems, clearSelectedItems, onUpdateSvg) {
2017-09-21 10:36:26 -04:00
this.hitType = null;
this.setSelectedItems = setSelectedItems;
this.clearSelectedItems = clearSelectedItems;
2017-09-21 18:20:44 -04:00
this.onUpdateSvg = onUpdateSvg;
2017-09-21 10:36:26 -04:00
}
/**
* @param {!object} hitProperties Describes the mouse event
* @param {?boolean} hitProperties.multiselect Whether to multiselect on mouse down (e.g. shift key held)
* select the whole group.
*/
onMouseDown (hitProperties) {
if (!hitProperties.multiselect) {
clearSelection(this.clearSelectedItems);
2017-09-21 10:36:26 -04:00
}
hitProperties.hitResult.segment.handleIn.selected = true;
hitProperties.hitResult.segment.handleOut.selected = true;
this.hitType = hitProperties.hitResult.type;
}
onMouseDrag (event) {
const selectedItems = getSelectedItems(true /* recursive */);
for (const item of selectedItems) {
for (const seg of item.segments) {
// add the point of the segment before the drag started
// for later use in the snap calculation
if (!seg.origPoint) {
seg.origPoint = seg.point.clone();
}
if (seg.handleOut.selected && this.hitType === 'handle-out'){
// if option is pressed or handles have been split,
// they're no longer parallel and move independently
if (event.modifiers.option ||
!seg.handleOut.isColinear(seg.handleIn)) {
seg.handleOut = seg.handleOut.add(event.delta);
} else {
const oldLength = seg.handleOut.length;
seg.handleOut = seg.handleOut.add(event.delta);
seg.handleIn = seg.handleOut.multiply(-seg.handleIn.length / oldLength);
}
} else if (seg.handleIn.selected && this.hitType === 'handle-in') {
// if option is pressed or handles have been split,
// they're no longer parallel and move independently
if (event.modifiers.option ||
!seg.handleOut.isColinear(seg.handleIn)) {
seg.handleIn = seg.handleIn.add(event.delta);
} else {
const oldLength = seg.handleIn.length;
seg.handleIn = seg.handleIn.add(event.delta);
seg.handleOut = seg.handleIn.multiply(-seg.handleOut.length / oldLength);
}
}
}
}
}
onMouseUp () {
// @todo add back undo
2017-09-21 18:20:44 -04:00
this.onUpdateSvg();
2017-09-21 10:36:26 -04:00
}
}
export default HandleTool;