2017-10-11 11:32:51 -04:00
|
|
|
import {clearSelection, getSelectedLeafItems} from '../selection';
|
2017-09-21 10:36:26 -04:00
|
|
|
|
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
|
|
|
/**
|
2017-10-02 15:25:04 -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
|
|
|
|
*/
|
2017-10-05 18:12:22 -04:00
|
|
|
constructor (setSelectedItems, clearSelectedItems, onUpdateSvg) {
|
2017-09-21 10:36:26 -04:00
|
|
|
this.hitType = null;
|
2017-10-02 15:25:04 -04:00
|
|
|
this.setSelectedItems = setSelectedItems;
|
|
|
|
this.clearSelectedItems = clearSelectedItems;
|
2017-09-21 18:20:44 -04:00
|
|
|
this.onUpdateSvg = onUpdateSvg;
|
2017-10-05 15:41:22 -04:00
|
|
|
this.selectedItems = [];
|
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) {
|
2017-10-02 15:25:04 -04:00
|
|
|
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) {
|
2017-10-05 15:41:22 -04:00
|
|
|
this.selectedItems = getSelectedLeafItems();
|
2017-12-20 11:54:43 -05:00
|
|
|
|
2017-10-05 15:41:22 -04:00
|
|
|
for (const item of this.selectedItems) {
|
2017-09-21 10:36:26 -04:00
|
|
|
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 {
|
|
|
|
seg.handleOut = seg.handleOut.add(event.delta);
|
2017-12-20 11:54:43 -05:00
|
|
|
seg.handleIn = seg.handleOut.multiply(-seg.handleIn.length / seg.handleOut.length);
|
2017-09-21 10:36:26 -04:00
|
|
|
}
|
|
|
|
} 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 {
|
|
|
|
seg.handleIn = seg.handleIn.add(event.delta);
|
2017-12-20 11:54:43 -05:00
|
|
|
seg.handleOut = seg.handleIn.multiply(-seg.handleOut.length / seg.handleIn.length);
|
2017-09-21 10:36:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
onMouseUp () {
|
2017-10-05 15:41:22 -04:00
|
|
|
// resetting the items and segments origin points for the next usage
|
|
|
|
let moved = false;
|
|
|
|
for (const item of this.selectedItems) {
|
|
|
|
if (!item.segments) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (const seg of item.segments) {
|
|
|
|
if (seg.origPoint && !seg.equals(seg.origPoint)) {
|
|
|
|
moved = true;
|
|
|
|
}
|
|
|
|
seg.origPoint = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (moved) {
|
|
|
|
this.onUpdateSvg();
|
|
|
|
}
|
|
|
|
this.selectedItems = [];
|
2017-09-21 10:36:26 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export default HandleTool;
|