Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(common): ensuring consistent hierarchy of all selected elements when add group #WIK-14768 #824

Merged
merged 4 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/hip-apricots-crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@plait/common': patch
'@plait/core': patch
---

ensuring consistent hierarchy of all selected elements when add group
4 changes: 2 additions & 2 deletions packages/common/src/transforms/z-index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PlaitBoard } from '@plait/core';
import { getOneMoveOptions, moveElementsToNewPath, getAllMoveOptions } from '../utils';
import { moveElementsToNewPath, PlaitBoard } from '@plait/core';
import { getOneMoveOptions, getAllMoveOptions } from '../utils';

const moveToTop = (board: PlaitBoard) => {
const moveOptions = getAllMoveOptions(board, 'up');
Expand Down
55 changes: 11 additions & 44 deletions packages/common/src/utils/z-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,19 @@ import {
getGroupByElement,
PlaitGroup,
getElementsInGroup,
Transforms,
Path,
findIndex
findIndex,
getElementsIndices,
MoveNodeOption,
sortElements,
} from '@plait/core';

export interface ZIndexMoveOption {
element: PlaitElement;
newPath: Path;
}

export const moveElementsToNewPath = (board: PlaitBoard, zIndexMoveOption: ZIndexMoveOption[]) => {
zIndexMoveOption
.map(item => {
const path = PlaitBoard.findPath(board, item.element);
const ref = board.pathRef(path);
return () => {
ref.current && Transforms.moveNode(board, ref.current, item.newPath);
ref.unref();
};
})
.forEach(action => {
action();
});
};

export const getOneMoveOptions = (board: PlaitBoard, direction: 'down' | 'up'): ZIndexMoveOption[] => {
export const getOneMoveOptions = (board: PlaitBoard, direction: 'down' | 'up'): MoveNodeOption[] => {
const indicesToMove = getIndicesToMove(board);
let groupedIndices = toContiguousGroups(board, indicesToMove);
if (direction === 'up') {
groupedIndices = groupedIndices.reverse();
}
let moveContents: ZIndexMoveOption[] = [];
let moveContents: MoveNodeOption[] = [];
groupedIndices.forEach((indices, i) => {
const leadingIndex = indices[0];
const trailingIndex = indices[indices.length - 1];
Expand All @@ -65,10 +46,10 @@ export const getOneMoveOptions = (board: PlaitBoard, direction: 'down' | 'up'):
return moveContents;
};

export const getAllMoveOptions = (board: PlaitBoard, direction: 'down' | 'up'): ZIndexMoveOption[] => {
export const getAllMoveOptions = (board: PlaitBoard, direction: 'down' | 'up'): MoveNodeOption[] => {
const indicesToMove = getIndicesToMove(board);
let groupedIndices = toContiguousGroups(board, indicesToMove);
let moveContents: ZIndexMoveOption[] = [];
let moveContents: MoveNodeOption[] = [];
if (direction === 'up') {
groupedIndices = groupedIndices.reverse();
}
Expand All @@ -80,7 +61,7 @@ export const getAllMoveOptions = (board: PlaitBoard, direction: 'down' | 'up'):
const editingGroup = getEditingGroup(board, sourceElement);
let targetIndex = direction === 'down' ? 0 : board.children.length - 1;
if (editingGroup) {
const elementsInGroup = ascendingSortElements(board, getElementsInGroup(board, editingGroup, true, true));
const elementsInGroup = sortElements(board, getElementsInGroup(board, editingGroup, true, true));
targetIndex =
direction === 'down'
? board.children.indexOf(elementsInGroup[0])
Expand Down Expand Up @@ -190,20 +171,6 @@ const getTargetIndex = (board: PlaitBoard, boundaryIndex: number, direction: 'do
};

const getIndicesToMove = (board: PlaitBoard) => {
const selectedElements = [...getSelectedElements(board), ...getSelectedGroups(board)].filter(item => board.canSetZIndex(item));
return selectedElements
.map(item => {
return board.children.indexOf(item);
})
.sort((a, b) => {
return a - b;
});
};

const ascendingSortElements = (board: PlaitBoard, elements: PlaitElement[] = []) => {
return elements.sort((a, b) => {
const indexA = board.children.findIndex(child => child.id === a.id);
const indexB = board.children.findIndex(child => child.id === b.id);
return indexA - indexB;
});
const selectedElements = [...getSelectedElements(board), ...getSelectedGroups(board)];
return getElementsIndices(board, selectedElements);
};
19 changes: 16 additions & 3 deletions packages/core/src/transforms/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import {
canAddGroup,
hasSelectedElementsInSameGroup,
canRemoveGroup,
findElements
findElements,
getElementsIndices,
isIndicesContinuous,
getSelectedElements,
getHighestIndexOfElement,
moveElementsToNewPathAfterAddGroup
} from '../utils';
import { NodeTransforms } from './node';

Expand All @@ -20,6 +25,14 @@ export const addGroup = (board: PlaitBoard, elements?: PlaitElement[]) => {
const path = PlaitBoard.findPath(board, item);
NodeTransforms.setNode(board, { groupId: group.id }, path);
});
const selectedElements = getSelectedElements(board);
const highestIndexOfSelectedElement = getHighestIndexOfElement(board, [...selectedElements, ...selectedGroups]);
const indices = getElementsIndices(board, highestSelectedElements);
const isContinuous = isIndicesContinuous(indices);
if (!isContinuous) {
moveElementsToNewPathAfterAddGroup(board, [...selectedElements, ...selectedGroups], [highestIndexOfSelectedElement - 1]);
}
const groupPath = [highestIndexOfSelectedElement + 1];
if (hasSelectedElementsInSameGroup(highestSelectedElements)) {
const newGroupId = selectedIsolatedElements[0].groupId;
NodeTransforms.insertNode(
Expand All @@ -28,10 +41,10 @@ export const addGroup = (board: PlaitBoard, elements?: PlaitElement[]) => {
...group,
groupId: newGroupId
},
[board.children.length]
groupPath
);
} else {
NodeTransforms.insertNode(board, group, [board.children.length]);
NodeTransforms.insertNode(board, group, groupPath);
}
}
};
Expand Down
35 changes: 35 additions & 0 deletions packages/core/src/utils/common.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { Path, PlaitElement } from '../interfaces';
import { PlaitBoard } from '../interfaces/board';
import { Subscription, timer } from 'rxjs';
import { NodeTransforms } from '../transforms/node';
import { sortElements } from './position';

const BOARD_TO_RAF = new WeakMap<PlaitBoard, { [key: string]: number | null }>();

export interface MoveNodeOption {
element: PlaitElement;
newPath: Path;
}

const getTimerId = (board: PlaitBoard, key: string) => {
const state = getRAFState(board);
return state[key] || null;
Expand Down Expand Up @@ -49,3 +57,30 @@ export const debounce = (func: () => void, wait: number, options?: { leading: bo
}
};
};

export const getElementsIndices = (board: PlaitBoard, elements: PlaitElement[]): number[] => {
sortElements(board, elements);
return elements.map(item => {
return board.children.map(item => item.id).indexOf(item.id);
});
};

export const getHighestIndexOfElement = (board: PlaitBoard, elements: PlaitElement[]) => {
huanhuanwa marked this conversation as resolved.
Show resolved Hide resolved
const indices = getElementsIndices(board, elements);
return indices[indices.length-1];
};

export const moveElementsToNewPath = (board: PlaitBoard, moveOptions: MoveNodeOption[]) => {
moveOptions
.map(item => {
const path = PlaitBoard.findPath(board, item.element);
const ref = board.pathRef(path);
return () => {
ref.current && NodeTransforms.moveNode(board, ref.current, item.newPath);
ref.unref();
};
})
.forEach(action => {
action();
});
};
21 changes: 18 additions & 3 deletions packages/core/src/utils/group.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ACTIVE_STROKE_WIDTH } from '../constants';
import { PlaitBoard, PlaitElement, PlaitGroup, PlaitGroupElement, RectangleClient, SELECTION_BORDER_COLOR } from '../interfaces';
import { Path, PlaitBoard, PlaitElement, PlaitGroup, PlaitGroupElement, RectangleClient, SELECTION_BORDER_COLOR } from '../interfaces';
import { getSelectionAngle } from './angle';
import { createG, setAngleForG } from './dom';
import { drawRectangle } from './drawing/rectangle';
Expand All @@ -8,6 +8,8 @@ import { idCreator } from './id-creator';
import { getSelectedElements } from './selected-element';
import { isSelectionMoving } from './selection';
import { depthFirstRecursion } from './tree';
import { moveElementsToNewPath } from './common';
import { sortElements } from './position';

export const getElementsInGroup = (board: PlaitBoard, group: PlaitGroup, recursion?: boolean, includeGroup?: boolean) => {
let result: PlaitElement[] = [];
Expand Down Expand Up @@ -234,7 +236,6 @@ export const canRemoveGroup = (board: PlaitBoard, elements?: PlaitElement[]) =>
return selectedElements.length > 0 && selectedGroups.length > 0;
};


export const getEditingGroup = (board: PlaitBoard, element: PlaitElement) => {
const groups = getGroupByElement(board, element, true) as PlaitGroup[];
let editingGroup = null;
Expand All @@ -247,4 +248,18 @@ export const getEditingGroup = (board: PlaitBoard, element: PlaitElement) => {
}
}
return editingGroup;
};
};

export const moveElementsToNewPathAfterAddGroup = (board: PlaitBoard, moveElements: PlaitElement[], newPath: Path) => {
sortElements(board, moveElements);
moveElements.pop();
moveElementsToNewPath(
board,
moveElements.map(element => {
return {
element,
newPath
};
})
);
};
10 changes: 10 additions & 0 deletions packages/core/src/utils/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,13 @@ export const findIndex = <T>(
}
return -1;
};

export const isIndicesContinuous = (indexes: number[]): boolean => {
indexes.sort((a, b) => a - b);
for (let i = 1; i < indexes.length; i++) {
if (indexes[i] !== indexes[i - 1] + 1) {
return false;
}
}
return true;
};
3 changes: 2 additions & 1 deletion packages/core/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ export * from './group';
export * from './selection';
export * from './angle';
export * from './fragment';
export * from './snap/snap';
export * from './snap/snap';
export * from './position';
4 changes: 2 additions & 2 deletions packages/core/src/utils/position.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { PlaitBoard, PlaitElement } from '../interfaces';

export const sortElements = (board: PlaitBoard, elements: PlaitElement[]) => {
export const sortElements = (board: PlaitBoard, elements: PlaitElement[], ascendingOrder = true) => {
return [...elements].sort((a: PlaitElement, b: PlaitElement) => {
const pathA = PlaitBoard.findPath(board, a);
const pathB = PlaitBoard.findPath(board, b);
return pathA[0] - pathB[0];
return ascendingOrder ? pathA[0] - pathB[0] : pathB[0] - pathA[0];
});
};