Skip to content

Commit

Permalink
feat(group): remove group with only one element #WIK-14744 (#779)
Browse files Browse the repository at this point in the history
  • Loading branch information
huanhuanwa authored Mar 21, 2024
1 parent 3c27329 commit 18b05a8
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .changeset/silly-moose-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@plait/common': patch
---

remove group with only one element
123 changes: 96 additions & 27 deletions packages/common/src/plugins/with-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,18 @@ import {
Selection,
Point,
Transforms,
WritableClipboardContext,
RectangleClient,
addClipboardContext,
createClipboardContext,
WritableClipboardType,
idCreator,
getSelectedElements
getSelectedElements,
getGroupByElement,
getElementsInGroup
} from '@plait/core';
import { GroupComponent } from '../core/group.component';

export function withGroup(board: PlaitBoard) {
let groupRectangleG: SVGGElement | null;
let removeGroups: PlaitGroup[] | null;

const { drawElement, pointerMove, globalPointerUp, setFragment, insertFragment, getRelatedFragment } = board;
const { drawElement, pointerMove, globalPointerUp, insertFragment, getDeletedFragment, deleteFragment, getRelatedFragment } = board;

board.drawElement = (context: PlaitPluginElementContext) => {
if (PlaitGroupElement.isGroup(context.element)) {
Expand Down Expand Up @@ -60,27 +58,9 @@ export function withGroup(board: PlaitBoard) {
};

board.getRelatedFragment = (elements: PlaitElement[]) => {
return getSelectedGroups(board, elements);
};

board.setFragment = (
data: DataTransfer | null,
clipboardContext: WritableClipboardContext | null,
rectangle: RectangleClient | null,
type: 'copy' | 'cut'
) => {
const selectedElements = getSelectedElements(board);
const selectedGroups = board.getRelatedFragment(selectedElements);
if (!clipboardContext) {
clipboardContext = createClipboardContext(WritableClipboardType.elements, selectedGroups, '');
} else {
clipboardContext = addClipboardContext(clipboardContext, {
text: '',
type: WritableClipboardType.elements,
data: selectedGroups
});
}
setFragment(data, clipboardContext, rectangle, type);
const groups = getSelectedGroups(board, selectedElements);
return getRelatedFragment([...elements, ...groups]);
};

board.insertFragment = (data: DataTransfer | null, clipboardData: ClipboardData | null, targetPoint: Point) => {
Expand Down Expand Up @@ -108,6 +88,22 @@ export function withGroup(board: PlaitBoard) {
insertFragment(data, clipboardData, targetPoint);
};

board.getDeletedFragment = (data: PlaitElement[]) => {
if (removeGroups && removeGroups.length) {
data.push(...removeGroups);
}
return getDeletedFragment(data);
};

board.deleteFragment = (data: DataTransfer | null) => {
removeGroups = getRemoveGroups(board);
if (removeGroups?.length) {
updateSiblingElementGroupId(board, removeGroups);
}
deleteFragment(data);
removeGroups = null;
};

return board;
}

Expand All @@ -134,3 +130,76 @@ const updateElementsGroupId = (group: PlaitGroup, clipboardDataElements: PlaitEl
}
return elements;
};

const getRemoveGroups = (board: PlaitBoard) => {
const selectedGroups = board.getRelatedFragment([]) as PlaitGroup[];
const removeGroups = [...selectedGroups];
const highestSelectedGroups = getHighestSelectedGroups(board);
const selectedIsolatedElements = getSelectedIsolatedElements(board);
const removeNodes = [...highestSelectedGroups, ...selectedIsolatedElements];
removeNodes.forEach(item => {
const hitElementGroups = getGroupByElement(board, item, true) as PlaitGroup[];
if (hitElementGroups.length) {
const elementsInGroup = getElementsInGroup(board, hitElementGroups[0], false, true);
const siblingElements = elementsInGroup.filter(
element => ![...removeNodes, ...removeGroups].map(item => item.id).includes(element.id)
);
if (siblingElements.length === 1 || siblingElements.length === 0) {
if (!removeGroups.includes(hitElementGroups[0])) {
removeGroups.push(hitElementGroups[0]);
}
if (siblingElements.length === 1) {
if (hitElementGroups.length > 1) {
const aboveGroup = findAboveGroupWithAnotherElement(board, hitElementGroups.slice(1, hitElementGroups.length), [
...removeNodes,
...removeGroups
]);
let index = hitElementGroups.length;
if (aboveGroup) {
index = hitElementGroups.findIndex(item => item.id === aboveGroup.id);
}
[...hitElementGroups.slice(1, index)].forEach(item => {
if (!removeGroups.includes(item)) {
removeGroups.push(item);
}
});
}
}
}
}
});
return removeGroups;
};

const findAboveGroupWithAnotherElement = (board: PlaitBoard, groups: PlaitGroup[], excludeNodes: PlaitElement[]) => {
let group: PlaitGroup | null = null;
for (let i = 0; i < groups.length; i++) {
const elementsInGroup = getElementsInGroup(board, groups[i], false, true);
const siblingElements = elementsInGroup.filter(element => !excludeNodes.map(item => item.id).includes(element.id));
if (siblingElements.length > 0) {
group = groups[i];
break;
}
}
return group;
};

const updateSiblingElementGroupId = (board: PlaitBoard, removeGroups: PlaitGroup[]) => {
const selectedIsolatedElements = getSelectedIsolatedElements(board);
const highestSelectedGroups = getHighestSelectedGroups(board);
const isolatedElementsInGroup = selectedIsolatedElements.filter(item => item.groupId);
[...highestSelectedGroups, ...isolatedElementsInGroup].forEach(item => {
const hitElementGroups = getGroupByElement(board, item, true) as PlaitGroup[];
if (hitElementGroups.length) {
const elementsInGroup = getElementsInGroup(board, hitElementGroups[0], false, true);
const siblingElements = elementsInGroup.filter(element => element.id !== item.id);
if (siblingElements.length === 1) {
if (hitElementGroups.some(group => removeGroups.includes(group))) {
const group = hitElementGroups.find(group => !removeGroups.includes(group));
const path = PlaitBoard.findPath(board, siblingElements[0]);
Transforms.setNode(board, { groupId: group?.id || undefined }, path);
}
}
}
});
};
11 changes: 7 additions & 4 deletions packages/core/src/board/board.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import { PlaitContextService } from '../services/image-context.service';
import { isPreventTouchMove } from '../utils/touch';
import { PlaitChildrenElementComponent } from '../core/children/children.component';
import { ZOOM_STEP } from '../constants/zoom';
import { withRelatedFragment } from '../plugins/with-related-fragment';

const ElementHostClass = 'element-host';
const ElementUpperHostClass = 'element-upper-host';
Expand Down Expand Up @@ -260,10 +261,12 @@ export class PlaitBoardComponent implements BoardComponentInterface, OnInit, OnC
}

private initializePlugins() {
let board = withHotkey(
withHandPointer(
withHistory(
withSelection(withMoving(withBoard(withViewport(withOptions(createBoard(this.plaitValue, this.plaitOptions))))))
let board = withRelatedFragment(
withHotkey(
withHandPointer(
withHistory(
withSelection(withMoving(withBoard(withViewport(withOptions(createBoard(this.plaitValue, this.plaitOptions))))))
)
)
)
);
Expand Down
32 changes: 32 additions & 0 deletions packages/core/src/plugins/with-related-fragment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { PlaitBoard, RectangleClient } from '../interfaces';
import {
WritableClipboardContext,
createClipboardContext,
WritableClipboardType,
addClipboardContext
} from '../utils';

export function withRelatedFragment(board: PlaitBoard) {
const { setFragment } = board;

board.setFragment = (
data: DataTransfer | null,
clipboardContext: WritableClipboardContext | null,
rectangle: RectangleClient | null,
type: 'copy' | 'cut'
) => {
const relatedFragment = board.getRelatedFragment([]);
if (!clipboardContext) {
clipboardContext = createClipboardContext(WritableClipboardType.elements, relatedFragment, '');
} else {
clipboardContext = addClipboardContext(clipboardContext, {
text: '',
type: WritableClipboardType.elements,
data: relatedFragment
});
}
setFragment(data, clipboardContext, rectangle, type);
};

return board;
}

0 comments on commit 18b05a8

Please sign in to comment.