in packages/ketcher-core/src/application/editor/actions/paste.ts [54:253]
export function fromPaste(
restruct,
pstruct,
point,
angle = 0,
isPreview = false,
): [Action, { atoms: number[]; bonds: number[] }, CreatedItems] {
const xy0 = getStructCenter(pstruct);
const offset = Vec2.diff(point, xy0);
const action = new Action();
const aidMap = new Map();
const fridMap = new Map();
const pasteItems = {
// only atoms and bonds now
atoms: [] as number[],
bonds: [] as number[],
};
const items: CreatedItems = {
atoms: [],
bonds: [],
rxnArrows: [],
rxnPluses: [],
texts: [],
images: [],
simpleObjects: [],
multitailArrows: [],
};
pstruct.atoms.forEach((atom, aid) => {
if (!fridMap.has(atom.fragment) && !pstruct.isAtomFromMacromolecule(aid)) {
fridMap.set(
atom.fragment,
(
action.addOp(
new FragmentAdd(null, atom.fragment.properties).perform(restruct),
) as FragmentAdd
).frid,
);
}
const tmpAtom = Object.assign(atom.clone(), {
fragment: fridMap.get(atom.fragment),
});
const operation = new AtomAdd(
tmpAtom,
Vec2.diff(atom.pp, xy0).rotate(angle).add(point),
).perform(restruct) as AtomAdd;
action.addOp(operation);
aidMap.set(aid, operation.data.aid);
pasteItems.atoms.push(operation.data.aid);
items.atoms.push(operation.data.aid);
action.mergeWith(
fromRGroupAttachmentPointAddition(
restruct,
tmpAtom.attachmentPoints,
operation.data.aid,
),
);
});
pstruct.frags.forEach((frag, frid) => {
if (!frag) return;
if (frag.properties) {
action.addOp(
new FragmentSetProperties(fridMap.get(frid), frag.properties).perform(
restruct,
),
);
}
frag.stereoAtoms.forEach((aid) =>
action.addOp(
new FragmentAddStereoAtom(fridMap.get(frid), aidMap.get(aid)).perform(
restruct,
),
),
);
});
pstruct.bonds.forEach((bond) => {
const operation = new BondAdd(
aidMap.get(bond.begin),
aidMap.get(bond.end),
bond,
false,
).perform(restruct) as BondAdd;
action.addOp(operation);
pasteItems.bonds.push(operation.data.bid);
items.bonds.push(operation.data.bid);
new BondAttr(operation.data.bid, 'isPreview', isPreview, false).perform(
restruct,
);
});
pstruct.sgroups.forEach((sg: SGroup) => {
const newsgid = restruct.molecule.sgroups.newId();
const sgAtoms = sg.atoms.map((aid) => aidMap.get(aid));
const attachmentPoints = sg.cloneAttachmentPoints(aidMap);
if (
sg.isNotContractible(pstruct) &&
!(sg instanceof MonomerMicromolecule)
) {
sg.setAttr('expanded', true);
}
const sgAction = fromSgroupAddition(
restruct,
sg.type,
sgAtoms,
sg.data,
newsgid,
attachmentPoints,
sg.pp ? sg.pp.add(offset) : null,
sg.type === 'SUP' ? sg.isExpanded() : null,
sg.data.name,
sg,
);
sgAction.operations.reverse().forEach((oper) => {
action.addOp(oper);
});
});
pasteItems.atoms.forEach((aid) => {
action.addOp(new CalcImplicitH([aid]).perform(restruct));
new AtomAttr(aid, 'isPreview', isPreview).perform(restruct);
});
pstruct.rxnArrows.forEach((rxnArrow) => {
const operation = new RxnArrowAdd(
rxnArrow.pos.map((p) => p.add(offset)),
rxnArrow.mode,
).perform(restruct);
action.addOp(operation);
items.rxnArrows.push(operation.data.id);
});
pstruct.rxnPluses.forEach((plus) => {
const operation = new RxnPlusAdd(plus.pp.add(offset)).perform(restruct);
action.addOp(operation);
items.rxnPluses.push(operation.data.plid);
});
pstruct.simpleObjects.forEach((simpleObject) => {
const operation = new SimpleObjectAdd(
simpleObject.pos.map((p) => p.add(offset)),
simpleObject.mode,
).perform(restruct);
action.addOp(operation);
items.simpleObjects.push(operation.data.id);
});
pstruct.texts.forEach((text) => {
const operation = new TextCreate(
text.content,
text.position.add(offset),
text.pos.map((p) => p.add(offset)),
).perform(restruct);
action.addOp(operation);
items.texts.push(operation.data.id);
});
pstruct.images.forEach((image: Image) => {
const clonedImage = image.clone();
clonedImage.addPositionOffset(offset);
const operation = new ImageUpsert(clonedImage).perform(restruct);
action.addOp(operation);
items.images.push(operation.data.id);
});
pstruct.multitailArrows.forEach((multitailArrow: MultitailArrow) => {
const clonedMultitailArrow = multitailArrow.clone();
clonedMultitailArrow.move(offset);
const operation = new MultitailArrowUpsert(clonedMultitailArrow).perform(
restruct,
);
action.addOp(operation);
items.multitailArrows.push(operation.data.id);
});
pstruct.rgroups.forEach((rg, rgid) => {
rg.frags.forEach((__frag, frid) => {
action.addOp(
new RGroupFragment(rgid, fridMap.get(frid)).perform(restruct),
);
});
const ifThen = pstruct.rgroups.get(rgid).ifthen;
const newRgId = pstruct.rgroups.get(ifThen) ? ifThen : 0;
action
.mergeWith(fromRGroupAttrs(restruct, rgid, rg.getAttrs()))
.mergeWith(fromUpdateIfThen(restruct, newRgId, rg.ifthen));
});
action.operations.reverse();
return [action, pasteItems, items];
}