mirror of
https://github.com/scratchfoundation/scratch-paint.git
synced 2024-12-22 21:42:30 -05:00
Pull in changes from reshape branch
This commit is contained in:
parent
99e023eea6
commit
2c374444b3
9 changed files with 202 additions and 191 deletions
|
@ -33,7 +33,15 @@ class PaperCanvas extends React.Component {
|
|||
onLoad: function (item) {
|
||||
// Remove viewbox
|
||||
if (item.clipped) {
|
||||
let mask;
|
||||
for (const child of item.children) {
|
||||
if (child.isClipMask()) {
|
||||
mask = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
item.clipped = false;
|
||||
mask.remove();
|
||||
// Consider removing clip mask here?
|
||||
}
|
||||
while (item.reduce() !== item) {
|
||||
|
|
|
@ -7,35 +7,17 @@ import Modes from '../modes/modes';
|
|||
import {changeMode} from '../reducers/modes';
|
||||
import {setHoveredItem, clearHoveredItem} from '../reducers/hover';
|
||||
|
||||
import {getHoveredItem} from '../helper/hover';
|
||||
import {rectSelect} from '../helper/guides';
|
||||
import {selectRootItem, processRectangularSelection} from '../helper/selection';
|
||||
|
||||
import SelectTool from '../helper/selection-tools/select-tool';
|
||||
import SelectModeComponent from '../components/select-mode.jsx';
|
||||
import BoundingBoxTool from '../helper/bounding-box/bounding-box-tool';
|
||||
import paper from 'paper';
|
||||
|
||||
class SelectMode extends React.Component {
|
||||
static get TOLERANCE () {
|
||||
return 6;
|
||||
}
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [
|
||||
'activateTool',
|
||||
'deactivateTool',
|
||||
'getHitOptions'
|
||||
'deactivateTool'
|
||||
]);
|
||||
this._hitOptions = {
|
||||
segments: true,
|
||||
stroke: true,
|
||||
curves: true,
|
||||
fill: true,
|
||||
guide: false
|
||||
};
|
||||
this.boundingBoxTool = new BoundingBoxTool();
|
||||
this.selectionBoxMode = false;
|
||||
this.selectionRect = null;
|
||||
}
|
||||
componentDidMount () {
|
||||
if (this.props.isSelectModeActive) {
|
||||
|
@ -43,6 +25,10 @@ class SelectMode extends React.Component {
|
|||
}
|
||||
}
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (this.tool && nextProps.hoveredItem !== this.props.hoveredItem) {
|
||||
this.tool.setPrevHoveredItem(nextProps.hoveredItem);
|
||||
}
|
||||
|
||||
if (nextProps.isSelectModeActive && !this.props.isSelectModeActive) {
|
||||
this.activateTool();
|
||||
} else if (!nextProps.isSelectModeActive && this.props.isSelectModeActive) {
|
||||
|
@ -52,84 +38,14 @@ class SelectMode extends React.Component {
|
|||
shouldComponentUpdate () {
|
||||
return false; // Static component, for now
|
||||
}
|
||||
getHitOptions (preselectedOnly) {
|
||||
this._hitOptions.tolerance = SelectMode.TOLERANCE / paper.view.zoom;
|
||||
if (preselectedOnly) {
|
||||
this._hitOptions.selected = true;
|
||||
} else {
|
||||
delete this._hitOptions.selected;
|
||||
}
|
||||
return this._hitOptions;
|
||||
}
|
||||
activateTool () {
|
||||
selectRootItem();
|
||||
this.boundingBoxTool.setSelectionBounds();
|
||||
this.tool = new paper.Tool();
|
||||
|
||||
// Define these to sate linter
|
||||
const selectMode = this;
|
||||
|
||||
this.tool.onMouseDown = function (event) {
|
||||
if (event.event.button > 0) return; // only first mouse button
|
||||
|
||||
selectMode.props.clearHoveredItem();
|
||||
if (!selectMode.boundingBoxTool
|
||||
.onMouseDown(
|
||||
event,
|
||||
event.modifiers.alt,
|
||||
event.modifiers.shift,
|
||||
selectMode.getHitOptions(false /* preseelectedOnly */))) {
|
||||
selectMode.selectionBoxMode = true;
|
||||
}
|
||||
};
|
||||
|
||||
this.tool.onMouseMove = function (event) {
|
||||
const hoveredItem = getHoveredItem(event, selectMode.getHitOptions());
|
||||
const oldHoveredItem = selectMode.props.hoveredItem;
|
||||
if ((!hoveredItem && oldHoveredItem) || // There is no longer a hovered item
|
||||
(hoveredItem && !oldHoveredItem) || // There is now a hovered item
|
||||
(hoveredItem && oldHoveredItem && hoveredItem.id !== oldHoveredItem.id)) { // hovered item changed
|
||||
selectMode.props.setHoveredItem(hoveredItem);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.tool.onMouseDrag = function (event) {
|
||||
if (event.event.button > 0) return; // only first mouse button
|
||||
|
||||
if (selectMode.selectionBoxMode) {
|
||||
selectMode.selectionRect = rectSelect(event);
|
||||
// Remove this rect on the next drag and up event
|
||||
selectMode.selectionRect.removeOnDrag();
|
||||
} else {
|
||||
selectMode.boundingBoxTool.onMouseDrag(event);
|
||||
}
|
||||
};
|
||||
|
||||
this.tool.onMouseUp = function (event) {
|
||||
if (event.event.button > 0) return; // only first mouse button
|
||||
|
||||
if (selectMode.selectionBoxMode) {
|
||||
if (selectMode.selectionRect) {
|
||||
processRectangularSelection(event, selectMode.selectionRect, Modes.SELECT);
|
||||
selectMode.selectionRect.remove();
|
||||
}
|
||||
selectMode.boundingBoxTool.setSelectionBounds();
|
||||
} else {
|
||||
selectMode.boundingBoxTool.onMouseUp(event);
|
||||
selectMode.props.onUpdateSvg();
|
||||
}
|
||||
selectMode.selectionBoxMode = false;
|
||||
selectMode.selectionRect = null;
|
||||
};
|
||||
this.tool = new SelectTool(this.props.setHoveredItem, this.props.clearHoveredItem, this.props.onUpdateSvg);
|
||||
this.tool.activate();
|
||||
}
|
||||
deactivateTool () {
|
||||
this.props.clearHoveredItem();
|
||||
this.boundingBoxTool.removeBoundsPath();
|
||||
this.tool.deactivateTool();
|
||||
this.tool.remove();
|
||||
this.tool = null;
|
||||
this.hitResult = null;
|
||||
}
|
||||
render () {
|
||||
return (
|
||||
|
@ -141,10 +57,10 @@ class SelectMode extends React.Component {
|
|||
SelectMode.propTypes = {
|
||||
clearHoveredItem: PropTypes.func.isRequired,
|
||||
handleMouseDown: PropTypes.func.isRequired,
|
||||
hoveredItem: PropTypes.instanceOf(paper.Item), // eslint-disable-line react/no-unused-prop-types
|
||||
hoveredItem: PropTypes.instanceOf(paper.Item),
|
||||
isSelectModeActive: PropTypes.bool.isRequired,
|
||||
onUpdateSvg: PropTypes.func.isRequired, // eslint-disable-line react/no-unused-prop-types
|
||||
setHoveredItem: PropTypes.func.isRequired // eslint-disable-line react/no-unused-prop-types
|
||||
onUpdateSvg: PropTypes.func.isRequired,
|
||||
setHoveredItem: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
import {isGroup} from '../group';
|
||||
import {isCompoundPathItem, getRootItem} from '../item';
|
||||
import {snapDeltaToAngle} from '../math';
|
||||
import {clearSelection, cloneSelection, getSelectedItems, setItemSelection} from '../selection';
|
||||
|
||||
class MoveTool {
|
||||
constructor () {
|
||||
this.selectedItems = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!paper.HitResult} hitResult Data about the location of the mouse click
|
||||
* @param {boolean} clone Whether to clone on mouse down (e.g. alt key held)
|
||||
* @param {boolean} multiselect Whether to multiselect on mouse down (e.g. shift key held)
|
||||
*/
|
||||
onMouseDown (hitResult, clone, multiselect) {
|
||||
const root = getRootItem(hitResult.item);
|
||||
const item = isCompoundPathItem(root) || isGroup(root) ? root : hitResult.item;
|
||||
if (!item.selected) {
|
||||
// deselect all by default if multiselect isn't on
|
||||
if (!multiselect) {
|
||||
clearSelection();
|
||||
}
|
||||
setItemSelection(item, true);
|
||||
} else if (multiselect) {
|
||||
setItemSelection(item, false);
|
||||
}
|
||||
if (clone) cloneSelection();
|
||||
this.selectedItems = getSelectedItems();
|
||||
}
|
||||
onMouseDrag (event) {
|
||||
const dragVector = event.point.subtract(event.downPoint);
|
||||
for (const item of this.selectedItems) {
|
||||
// add the position of the item before the drag started
|
||||
// for later use in the snap calculation
|
||||
if (!item.data.origPos) {
|
||||
item.data.origPos = item.position;
|
||||
}
|
||||
|
||||
if (event.modifiers.shift) {
|
||||
item.position = item.data.origPos.add(snapDeltaToAngle(dragVector, Math.PI / 4));
|
||||
} else {
|
||||
item.position = item.data.origPos.add(dragVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
onMouseUp () {
|
||||
// resetting the items origin point for the next usage
|
||||
for (const item of this.selectedItems) {
|
||||
item.data.origPos = null;
|
||||
}
|
||||
this.selectedItems = null;
|
||||
|
||||
// @todo add back undo
|
||||
// pg.undo.snapshot('moveSelection');
|
||||
}
|
||||
}
|
||||
|
||||
export default MoveTool;
|
|
@ -28,17 +28,19 @@ const Modes = keyMirror({
|
|||
* 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.
|
||||
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
|
||||
*/
|
||||
class BoundingBoxTool {
|
||||
constructor () {
|
||||
constructor (onUpdateSvg) {
|
||||
this.onUpdateSvg = onUpdateSvg;
|
||||
this.mode = null;
|
||||
this.boundsPath = null;
|
||||
this.boundsScaleHandles = [];
|
||||
this.boundsRotHandles = [];
|
||||
this._modeMap = {};
|
||||
this._modeMap[Modes.SCALE] = new ScaleTool();
|
||||
this._modeMap[Modes.ROTATE] = new RotateTool();
|
||||
this._modeMap[Modes.MOVE] = new MoveTool();
|
||||
this._modeMap[Modes.SCALE] = new ScaleTool(onUpdateSvg);
|
||||
this._modeMap[Modes.ROTATE] = new RotateTool(onUpdateSvg);
|
||||
this._modeMap[Modes.MOVE] = new MoveTool(onUpdateSvg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,8 +77,13 @@ class BoundingBoxTool {
|
|||
this.mode = Modes.MOVE;
|
||||
}
|
||||
|
||||
const hitProperties = {
|
||||
hitResult: hitResult,
|
||||
clone: event.modifiers.alt,
|
||||
multiselect: event.modifiers.shift
|
||||
};
|
||||
if (this.mode === Modes.MOVE) {
|
||||
this._modeMap[this.mode].onMouseDown(hitResult, clone, multiselect);
|
||||
this._modeMap[this.mode].onMouseDown(hitProperties);
|
||||
} else if (this.mode === Modes.SCALE) {
|
||||
this._modeMap[this.mode].onMouseDown(
|
||||
hitResult, this.boundsPath, this.boundsScaleHandles, this.boundsRotHandles, getSelectedItems());
|
||||
|
@ -102,7 +109,7 @@ class BoundingBoxTool {
|
|||
setSelectionBounds () {
|
||||
this.removeBoundsPath();
|
||||
|
||||
const items = getSelectedItems();
|
||||
const items = getSelectedItems(true /* recursive */);
|
||||
if (items.length <= 0) return;
|
||||
|
||||
let rect = null;
|
101
src/helper/selection-tools/move-tool.js
Normal file
101
src/helper/selection-tools/move-tool.js
Normal file
|
@ -0,0 +1,101 @@
|
|||
import {isGroup} from '../group';
|
||||
import {isCompoundPathItem, getRootItem} from '../item';
|
||||
import {snapDeltaToAngle} from '../math';
|
||||
import {clearSelection, cloneSelection, getSelectedItems, setItemSelection} from '../selection';
|
||||
|
||||
class MoveTool {
|
||||
/**
|
||||
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
|
||||
*/
|
||||
constructor (onUpdateSvg) {
|
||||
this.selectedItems = null;
|
||||
this.onUpdateSvg = onUpdateSvg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!object} hitProperties Describes the mouse event
|
||||
* @param {!paper.HitResult} hitProperties.hitResult Data about the location of the mouse click
|
||||
* @param {?boolean} hitProperties.clone Whether to clone on mouse down (e.g. alt key held)
|
||||
* @param {?boolean} hitProperties.multiselect Whether to multiselect on mouse down (e.g. shift key held)
|
||||
* @param {?boolean} hitProperties.doubleClicked True if this is the second click in a short amout of time
|
||||
* @param {?boolean} hitProperties.subselect True if we allow selection of subgroups, false if we should
|
||||
* select the whole group.
|
||||
*/
|
||||
onMouseDown (hitProperties) {
|
||||
let item = hitProperties.hitResult.item;
|
||||
if (!hitProperties.subselect) {
|
||||
const root = getRootItem(hitProperties.hitResult.item);
|
||||
item = isCompoundPathItem(root) || isGroup(root) ? root : hitProperties.hitResult.item;
|
||||
}
|
||||
if (item.selected) {
|
||||
// Double click causes all points to be selected in subselect mode.
|
||||
if (hitProperties.doubleClicked) {
|
||||
if (!hitProperties.multiselect) {
|
||||
clearSelection();
|
||||
}
|
||||
this._select(item, true /* state */, hitProperties.subselect, true /* fullySelect */);
|
||||
} else if (hitProperties.multiselect) {
|
||||
this._select(item, false /* state */, hitProperties.subselect);
|
||||
}
|
||||
} else {
|
||||
// deselect all by default if multiselect isn't on
|
||||
if (!hitProperties.multiselect) {
|
||||
clearSelection();
|
||||
}
|
||||
this._select(item, true, hitProperties.subselect);
|
||||
}
|
||||
if (hitProperties.clone) cloneSelection(hitProperties.subselect);
|
||||
this.selectedItems = getSelectedItems(true /* subselect */);
|
||||
}
|
||||
/**
|
||||
* Sets the selection state of an item.
|
||||
* @param {!paper.Item} item Item to select or deselect
|
||||
* @param {?boolean} state True if item should be selected, false if deselected
|
||||
* @param {?boolean} subselect True if a subset of all points in an item are allowed to be
|
||||
* selected, false if items must be selected all or nothing.
|
||||
* @param {?boolean} fullySelect True if in addition to the item being selected, all of its
|
||||
* control points should be selected. False if the item should be selected but not its
|
||||
* points. Only relevant when subselect is true.
|
||||
*/
|
||||
_select (item, state, subselect, fullySelect) {
|
||||
if (subselect) {
|
||||
item.selected = false;
|
||||
if (fullySelect) {
|
||||
item.fullySelected = state;
|
||||
} else {
|
||||
item.selected = state;
|
||||
}
|
||||
} else {
|
||||
setItemSelection(item, state);
|
||||
}
|
||||
}
|
||||
onMouseDrag (event) {
|
||||
const dragVector = event.point.subtract(event.downPoint);
|
||||
for (const item of this.selectedItems) {
|
||||
// add the position of the item before the drag started
|
||||
// for later use in the snap calculation
|
||||
if (!item.data.origPos) {
|
||||
item.data.origPos = item.position;
|
||||
}
|
||||
|
||||
if (event.modifiers.shift) {
|
||||
item.position = item.data.origPos.add(snapDeltaToAngle(dragVector, Math.PI / 4));
|
||||
} else {
|
||||
item.position = item.data.origPos.add(dragVector);
|
||||
}
|
||||
}
|
||||
}
|
||||
onMouseUp () {
|
||||
// resetting the items origin point for the next usage
|
||||
for (const item of this.selectedItems) {
|
||||
item.data.origPos = null;
|
||||
}
|
||||
this.selectedItems = null;
|
||||
|
||||
// @todo add back undo
|
||||
// pg.undo.snapshot('moveSelection');
|
||||
this.onUpdateSvg();
|
||||
}
|
||||
}
|
||||
|
||||
export default MoveTool;
|
|
@ -1,10 +1,14 @@
|
|||
import paper from 'paper';
|
||||
|
||||
class RotateTool {
|
||||
constructor () {
|
||||
/**
|
||||
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
|
||||
*/
|
||||
constructor (onUpdateSvg) {
|
||||
this.rotItems = [];
|
||||
this.rotGroupPivot = null;
|
||||
this.prevRot = [];
|
||||
this.onUpdateSvg = onUpdateSvg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,7 +61,7 @@ class RotateTool {
|
|||
this.prevRot = [];
|
||||
|
||||
// @todo add back undo
|
||||
// pg.undo.snapshot('rotateSelection');
|
||||
this.onUpdateSvg();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
import paper from 'paper';
|
||||
|
||||
class ScaleTool {
|
||||
constructor () {
|
||||
/**
|
||||
* @param {!function} onUpdateSvg A callback to call when the image visibly changes
|
||||
*/
|
||||
constructor (onUpdateSvg) {
|
||||
this.pivot = null;
|
||||
this.origPivot = null;
|
||||
this.corner = null;
|
||||
|
@ -14,6 +17,7 @@ class ScaleTool {
|
|||
this.scaleItems = [];
|
||||
this.boundsScaleHandles = [];
|
||||
this.boundsRotHandles = [];
|
||||
this.onUpdateSvg = onUpdateSvg;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,7 +154,7 @@ class ScaleTool {
|
|||
this.itemGroup.remove();
|
||||
|
||||
// @todo add back undo
|
||||
// pg.undo.snapshot('scaleSelection');
|
||||
this.onUpdateSvg();
|
||||
}
|
||||
getRectCornerNameByIndex (index) {
|
||||
switch (index) {
|
32
src/helper/selection-tools/selection-box-tool.js
Normal file
32
src/helper/selection-tools/selection-box-tool.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
import Modes from '../../modes/modes';
|
||||
import {rectSelect} from '../guides';
|
||||
import {clearSelection, processRectangularSelection} from '../selection';
|
||||
|
||||
class SelectionBoxTool {
|
||||
constructor (mode) {
|
||||
this.selectionRect = null;
|
||||
this.mode = mode;
|
||||
}
|
||||
/**
|
||||
* @param {boolean} multiselect Whether to multiselect on mouse down (e.g. shift key held)
|
||||
*/
|
||||
onMouseDown (multiselect) {
|
||||
if (!multiselect) {
|
||||
clearSelection();
|
||||
}
|
||||
}
|
||||
onMouseDrag (event) {
|
||||
this.selectionRect = rectSelect(event);
|
||||
// Remove this rect on the next drag and up event
|
||||
this.selectionRect.removeOnDrag();
|
||||
}
|
||||
onMouseUp (event) {
|
||||
if (this.selectionRect) {
|
||||
processRectangularSelection(event, this.selectionRect, Modes.RESHAPE);
|
||||
this.selectionRect.remove();
|
||||
this.selectionRect = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default SelectionBoxTool;
|
|
@ -34,37 +34,40 @@ const selectItemSegments = function (item, state) {
|
|||
}
|
||||
};
|
||||
|
||||
const setGroupSelection = function (root, selected) {
|
||||
// fully selected segments need to be unselected first
|
||||
root.fullySelected = false;
|
||||
// then the item can be normally selected
|
||||
const setGroupSelection = function (root, selected, fullySelected) {
|
||||
root.fullySelected = fullySelected;
|
||||
root.selected = selected;
|
||||
// select children of compound-path or group
|
||||
if (isCompoundPath(root) || isGroup(root)) {
|
||||
const children = root.children;
|
||||
if (children) {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
children[i].selected = selected;
|
||||
for (const child of children) {
|
||||
if (isGroup(child)) {
|
||||
setGroupSelection(child, selected, fullySelected);
|
||||
} else {
|
||||
child.fullySelected = fullySelected;
|
||||
child.selected = selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const setItemSelection = function (item, state) {
|
||||
const setItemSelection = function (item, state, fullySelected) {
|
||||
const parentGroup = getItemsGroup(item);
|
||||
const itemsCompoundPath = getItemsCompoundPath(item);
|
||||
|
||||
// if selection is in a group, select group not individual items
|
||||
if (parentGroup) {
|
||||
// do it recursive
|
||||
setItemSelection(parentGroup, state);
|
||||
setItemSelection(parentGroup, state, fullySelected);
|
||||
} else if (itemsCompoundPath) {
|
||||
setItemSelection(itemsCompoundPath, state);
|
||||
setGroupSelection(itemsCompoundPath, state, fullySelected);
|
||||
} else {
|
||||
if (item.data && item.data.noSelect) {
|
||||
return;
|
||||
}
|
||||
setGroupSelection(item, state);
|
||||
setGroupSelection(item, state, fullySelected);
|
||||
}
|
||||
// @todo: Update toolbar state on change
|
||||
|
||||
|
@ -355,11 +358,9 @@ const handleRectangularSelectionItems = function (item, event, rect, mode) {
|
|||
seg.selected = true;
|
||||
}
|
||||
segmentMode = true;
|
||||
|
||||
} else {
|
||||
if (event.modifiers.shift && item.selected) {
|
||||
setItemSelection(item, false);
|
||||
|
||||
} else {
|
||||
setItemSelection(item, true);
|
||||
}
|
||||
|
@ -371,7 +372,7 @@ const handleRectangularSelectionItems = function (item, event, rect, mode) {
|
|||
// second round checks for path intersections
|
||||
const intersections = item.getIntersections(rect);
|
||||
if (intersections.length > 0 && !segmentMode) {
|
||||
// if in detail select mode, select the curves that intersect
|
||||
// if in reshape mode, select the curves that intersect
|
||||
// with the selectionRect
|
||||
if (mode === Modes.RESHAPE) {
|
||||
for (let k = 0; k < intersections.length; k++) {
|
||||
|
@ -389,7 +390,6 @@ const handleRectangularSelectionItems = function (item, event, rect, mode) {
|
|||
curve.selected = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (event.modifiers.shift && item.selected) {
|
||||
setItemSelection(item, false);
|
||||
|
@ -417,9 +417,8 @@ const rectangularSelectionGroupLoop = function (group, rect, root, event, mode)
|
|||
|
||||
if (isGroup(child) || isCompoundPathItem(child)) {
|
||||
rectangularSelectionGroupLoop(child, rect, root, event, mode);
|
||||
|
||||
} else if (!handleRectangularSelectionItems(child, event, rect, mode)) {
|
||||
return false;
|
||||
} else {
|
||||
handleRectangularSelectionItems(child, event, rect, mode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -428,20 +427,16 @@ const rectangularSelectionGroupLoop = function (group, rect, root, event, mode)
|
|||
const processRectangularSelection = function (event, rect, mode) {
|
||||
const allItems = getAllSelectableItems();
|
||||
|
||||
itemLoop:
|
||||
for (let i = 0; i < allItems.length; i++) {
|
||||
const item = allItems[i];
|
||||
if (mode === Modes.RESHAPE && isPGTextItem(getRootItem(item))) {
|
||||
continue itemLoop;
|
||||
continue;
|
||||
}
|
||||
// check for item segment points inside selectionRect
|
||||
if (isGroup(item) || isCompoundPathItem(item)) {
|
||||
if (!rectangularSelectionGroupLoop(item, rect, item, event, mode)) {
|
||||
continue itemLoop;
|
||||
}
|
||||
|
||||
} else if (!handleRectangularSelectionItems(item, event, rect, mode)) {
|
||||
continue itemLoop;
|
||||
rectangularSelectionGroupLoop(item, rect, item, event, mode);
|
||||
} else {
|
||||
handleRectangularSelectionItems(item, event, rect, mode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -454,8 +449,11 @@ const selectRootItem = function () {
|
|||
for (const item of items) {
|
||||
if (isCompoundPathChild(item)) {
|
||||
const cp = getItemsCompoundPath(item);
|
||||
setItemSelection(item, false);
|
||||
setItemSelection(cp, true);
|
||||
setItemSelection(cp, true, true /* fullySelected */);
|
||||
}
|
||||
const rootItem = getRootItem(item);
|
||||
if (item !== rootItem) {
|
||||
setItemSelection(rootItem, true, true /* fullySelected */);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue