diff --git a/packages/ketcher-react/src/script/editor/tool/helper/filterNotInCollapsedSGroup.ts b/packages/ketcher-react/src/script/editor/tool/helper/filterNotInCollapsedSGroup.ts new file mode 100644 index 0000000000..6c96d116dd --- /dev/null +++ b/packages/ketcher-react/src/script/editor/tool/helper/filterNotInCollapsedSGroup.ts @@ -0,0 +1,40 @@ +import { Struct, FunctionalGroup } from 'ketcher-core' + +/** + * return only such elements ids that not part of collapsed group + * Addition: if an atom in the collapsed SGroup, but is an AttachmentPoint it will be returned as well. + */ +export function filterNotInCollapsedSGroup( + itemsToFilter: { atoms?: number[]; bonds?: number[] }, + struct: Struct +) { + return { + atoms: + itemsToFilter.atoms?.filter((atomId) => { + const groupId = struct.getGroupIdFromAtomId(atomId) + if (isNotCollapsedSGroup(groupId, struct)) { + return true + } else { + return FunctionalGroup.isAttachmentPointAtom(atomId, struct) + } + }) ?? [], + bonds: + itemsToFilter.bonds?.filter((bondId) => { + const groupId = struct.getGroupIdFromBondId(bondId) + return isNotCollapsedSGroup(groupId, struct) + }) ?? [] + } +} + +function isNotCollapsedSGroup(groupId: number | null, struct: Struct): boolean { + if (groupId === null) { + return true + } + const sGroup = struct.sgroups.get(groupId) + if (!sGroup) { + throw new Error( + `sGroup with id = "${groupId}" must be defined, unexpected behaviour` + ) + } + return sGroup.checkAttr('expanded', true) +} diff --git a/packages/ketcher-react/src/script/editor/tool/paste.ts b/packages/ketcher-react/src/script/editor/tool/paste.ts index 5489579964..f27afef37f 100644 --- a/packages/ketcher-react/src/script/editor/tool/paste.ts +++ b/packages/ketcher-react/src/script/editor/tool/paste.ts @@ -30,6 +30,7 @@ import Editor from '../Editor' import { dropAndMerge } from './helper/dropAndMerge' import { getGroupIdsFromItemArrays } from './helper/getGroupIdsFromItems' import utils from '../shared/utils' +import { filterNotInCollapsedSGroup } from './helper/filterNotInCollapsedSGroup' class PasteTool { editor: Editor @@ -180,8 +181,12 @@ class PasteTool { ) this.action = action this.editor.update(this.action, true, { resizeCanvas: false }) + const visiblePasteItems = filterNotInCollapsedSGroup( + pasteItems, + this.editor.struct() + ) - this.mergeItems = getItemsToFuse(this.editor, pasteItems) + this.mergeItems = getItemsToFuse(this.editor, visiblePasteItems) this.editor.hover(getHoverToFuse(this.mergeItems)) } } diff --git a/packages/ketcher-react/src/script/editor/tool/select.ts b/packages/ketcher-react/src/script/editor/tool/select.ts index ed3f54a0df..3fb8fce4a9 100644 --- a/packages/ketcher-react/src/script/editor/tool/select.ts +++ b/packages/ketcher-react/src/script/editor/tool/select.ts @@ -48,6 +48,7 @@ import { getGroupIdsFromItemArrays } from './helper/getGroupIdsFromItems' import { updateSelectedAtoms } from 'src/script/ui/state/modal/atoms' import { updateSelectedBonds } from 'src/script/ui/state/modal/bonds' import { hasAtomsOutsideCanvas } from './helper/isAtomOutSideCanvas' +import { filterNotInCollapsedSGroup } from './helper/filterNotInCollapsedSGroup' class SelectTool { #mode: string @@ -207,7 +208,11 @@ class SelectTool { editor.render.page2obj(event).sub(dragCtx.xy0) ) - dragCtx.mergeItems = getItemsToFuse(editor, expSel) + const visibleSelectedItems = filterNotInCollapsedSGroup( + expSel, + this.editor.struct() + ) + dragCtx.mergeItems = getItemsToFuse(editor, visibleSelectedItems) editor.hover(getHoverToFuse(dragCtx.mergeItems)) resizeCanvas(rnd, event)