scratch-paint/src/helper/group.js

164 lines
5.7 KiB
JavaScript
Raw Normal View History

2017-10-12 18:35:30 -04:00
import paper from '@scratch/paper';
2017-09-11 14:23:30 -04:00
import {getRootItem, isGroupItem} from './item';
import {clearSelection, getSelectedRootItems, setItemSelection} from './selection';
2017-09-11 14:23:30 -04:00
const isGroup = function (item) {
return isGroupItem(item);
};
2017-10-23 15:55:30 -04:00
/**
* Groups the given items. Other things are then deselected and the new group is selected.
* @param {!Array<paper.Item>} items Root level items to group
* @param {!function} clearSelectedItems Function to clear Redux state's selected items
* @param {!function} setSelectedItems Function to set Redux state with new list of selected items
* @param {!function} onUpdateImage Function to let listeners know that SVG has changed.
2017-10-23 15:55:30 -04:00
* @return {paper.Group} the group if one is created, otherwise false.
*/
const groupItems = function (items, clearSelectedItems, setSelectedItems, onUpdateImage) {
2017-09-11 14:23:30 -04:00
if (items.length > 0) {
const group = new paper.Group(items);
clearSelection(clearSelectedItems);
2017-09-11 14:23:30 -04:00
setItemSelection(group, true);
for (let i = 0; i < group.children.length; i++) {
group.children[i].selected = true;
}
2017-10-23 15:38:52 -04:00
setSelectedItems();
onUpdateImage();
2017-09-11 14:23:30 -04:00
return group;
}
return false;
};
2017-10-23 15:55:30 -04:00
/**
* Groups the selected items. Other things are then deselected and the new group is selected.
* @param {!function} clearSelectedItems Function to clear Redux state's selected items
* @param {!function} setSelectedItems Function to set Redux state with new list of selected items
* @param {!function} onUpdateImage Function to let listeners know that SVG has changed.
2017-10-23 15:55:30 -04:00
* @return {paper.Group} the group if one is created, otherwise false.
*/
const groupSelection = function (clearSelectedItems, setSelectedItems, onUpdateImage) {
2017-10-23 15:38:52 -04:00
const items = getSelectedRootItems();
return groupItems(items, clearSelectedItems, setSelectedItems, onUpdateImage);
2017-10-23 15:38:52 -04:00
};
2017-10-23 15:55:30 -04:00
const _ungroupLoop = function (group, recursive, setSelectedItems) {
// Can't ungroup items that are not groups
2017-09-11 14:23:30 -04:00
if (!group || !group.children || !isGroup(group)) return;
group.applyMatrix = true;
// iterate over group children recursively
for (let i = 0; i < group.children.length; i++) {
let groupChild = group.children[i];
if (groupChild instanceof paper.Group && groupChild.hasChildren()) {
2017-09-11 14:23:30 -04:00
// recursion (groups can contain groups, ie. from SVG import)
if (recursive) {
2017-10-23 15:55:30 -04:00
_ungroupLoop(groupChild, recursive, setSelectedItems);
2017-09-11 14:23:30 -04:00
continue;
}
if (groupChild.children.length === 1) {
groupChild = groupChild.reduce();
}
2017-09-11 14:23:30 -04:00
}
groupChild.applyMatrix = true;
// move items from the group to the activeLayer (ungrouping)
groupChild.insertBelow(group);
2017-10-23 15:38:52 -04:00
if (setSelectedItems) {
groupChild.selected = true;
}
2017-09-11 14:23:30 -04:00
i--;
}
};
2017-10-23 15:55:30 -04:00
/**
* Ungroups the given items. The new group is selected only if setSelectedItems is passed in.
* onUpdateImage is called to notify listeners of a change on the SVG only if onUpdateImage is passed in.
2017-10-23 15:55:30 -04:00
* The reason these arguments are optional on ungroupItems is because ungroupItems is used for parts of
* SVG import, which shouldn't change the selection or undo state.
*
* @param {!Array<paper.Item>} items Items to ungroup if they are groups
* @param {?function} setSelectedItems Function to set Redux state with new list of selected items
* @param {?function} onUpdateImage Function to let listeners know that SVG has changed.
2017-10-23 15:55:30 -04:00
*/
const ungroupItems = function (items, setSelectedItems, onUpdateImage) {
2017-10-23 15:38:52 -04:00
if (items.length === 0) {
return;
}
2017-09-11 14:23:30 -04:00
const emptyGroups = [];
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (isGroup(item) && !item.data.isPGTextItem) {
2017-10-23 15:55:30 -04:00
_ungroupLoop(item, false /* recursive */, setSelectedItems);
2017-09-11 14:23:30 -04:00
if (!item.hasChildren()) {
emptyGroups.push(item);
}
}
}
2017-10-23 15:38:52 -04:00
if (setSelectedItems) {
setSelectedItems();
}
2017-09-11 14:23:30 -04:00
// remove all empty groups after ungrouping
for (let j = 0; j < emptyGroups.length; j++) {
emptyGroups[j].remove();
}
2017-10-23 15:55:30 -04:00
// @todo: enable/disable grouping icons
if (onUpdateImage) {
onUpdateImage();
2017-10-23 15:38:52 -04:00
}
2017-09-11 14:23:30 -04:00
};
2017-10-23 15:55:30 -04:00
/**
* Ungroups the selected items. Other items are deselected and the ungrouped items are selected.
*
* @param {!function} clearSelectedItems Function to clear Redux state's selected items
* @param {!function} setSelectedItems Function to set Redux state with new list of selected items
* @param {!function} onUpdateImage Function to let listeners know that SVG has changed.
2017-10-23 15:55:30 -04:00
*/
const ungroupSelection = function (clearSelectedItems, setSelectedItems, onUpdateImage) {
const items = getSelectedRootItems();
clearSelection(clearSelectedItems);
ungroupItems(items, setSelectedItems, onUpdateImage);
2017-09-11 14:23:30 -04:00
};
const getItemsGroup = function (item) {
const itemParent = item.parent;
if (isGroup(itemParent)) {
return itemParent;
}
return null;
};
const isGroupChild = function (item) {
const rootItem = getRootItem(item);
return isGroup(rootItem);
};
const shouldShowGroup = function () {
const items = getSelectedRootItems();
2017-09-11 14:23:30 -04:00
return items.length > 1;
};
const shouldShowUngroup = function () {
const items = getSelectedRootItems();
2017-09-11 14:23:30 -04:00
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (isGroup(item) && !item.data.isPGTextItem && item.children && item.children.length > 0) {
return true;
}
}
return false;
};
export {
groupSelection,
ungroupSelection,
groupItems,
ungroupItems,
getItemsGroup,
isGroup,
isGroupChild,
shouldShowGroup,
shouldShowUngroup
};