in packages/ketcher-react/src/script/editor/tool/bond.ts [146:306]
mousemove(event) {
const struct = this.editor.render.ctab;
const molecule = struct.molecule;
const functionalGroups = molecule.functionalGroups;
const editor = this.editor;
const rnd = editor.render;
if (isBondingWithMacroMolecule(this.editor, event)) {
return true;
}
if ('dragCtx' in this) {
const dragCtx = this.dragCtx;
const pos = rnd.page2obj(event);
let angle = vectorUtils.calcAngle(dragCtx.xy0, pos);
if (!event.ctrlKey) angle = vectorUtils.fracAngle(angle, null);
const degrees = vectorUtils.degrees(angle);
this.editor.event.message.dispatch({ info: degrees + 'º' });
if (!('item' in dragCtx) || dragCtx.item.map === 'atoms') {
if ('action' in dragCtx) dragCtx.action.perform(rnd.ctab);
let beginAtom;
let endAtom;
let beginPos;
let endPos;
if ('item' in dragCtx && dragCtx.item.map === 'atoms') {
// first mousedown event intersect with any atom
beginAtom = dragCtx.item.id;
endAtom = editor.findItem(event, ['atoms'], dragCtx.item);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const closestSGroup = editor.findItem(event, ['functionalGroups'])!;
const sgroup = molecule.sgroups.get(closestSGroup?.id);
if (sgroup) {
const closestAttachmentAtomId = sgroup.getAttachmentAtomId();
if (sgroup.isContracted()) {
const hasAttachmentPoint = closestAttachmentAtomId === undefined;
const isBeginFunctionalGroupItself =
closestAttachmentAtomId === beginAtom;
if (!hasAttachmentPoint && !isBeginFunctionalGroupItself) {
endAtom = {
id: closestAttachmentAtomId,
map: 'atoms',
};
}
}
if (endAtom) {
if (endAtom.id !== closestAttachmentAtomId) {
this.editor.event.removeFG.dispatch({ fgIds: [sgroup.id] });
endAtom = null;
}
}
}
} else {
// first mousedown event intersect with any canvas
beginAtom = this.atomProps;
beginPos = dragCtx.xy0;
endAtom = editor.findItem(event, ['atoms', 'functionalGroups']);
const atomResult: Array<number> = [];
const result: Array<number> = [];
if (
endAtom &&
endAtom.map === 'atoms' &&
functionalGroups.size &&
this.dragCtx
) {
const atomId = FunctionalGroup.atomsInFunctionalGroup(
functionalGroups,
endAtom.id,
);
if (atomId !== null) atomResult.push(atomId);
} else if (endAtom?.map === 'functionalGroups') {
const functionalGroup = molecule.functionalGroups.get(endAtom.id);
if (!SGroup.isSaltOrSolvent(functionalGroup?.name || '')) {
const attachmentAtomId =
functionalGroup?.relatedSGroup.getAttachmentAtomId();
endAtom =
attachmentAtomId === undefined
? null
: {
map: 'atoms',
id: attachmentAtomId,
};
}
}
if (atomResult.length > 0) {
for (const id of atomResult) {
const fgId = FunctionalGroup.findFunctionalGroupByAtom(
functionalGroups,
id,
);
fgId !== null && !result.includes(fgId) && result.push(fgId);
}
}
if (result.length > 0) {
this.editor.event.removeFG.dispatch({ fgIds: result });
delete this.dragCtx;
return;
}
}
let dist = Number.MAX_VALUE;
if (endAtom?.map === 'atoms') {
// after mousedown events is appered, cursor is moved and then cursor intersects any atoms
endAtom = endAtom.id;
} else {
endAtom = this.atomProps;
const xy1 = rnd.page2obj(event);
dist = Vec2.dist(dragCtx.xy0, xy1);
if (beginPos) {
// rotation only, leght of bond = 1;
endPos = vectorUtils.calcNewAtomPos(beginPos, xy1, event.ctrlKey);
} else {
// first mousedown event intersect with any atom and
// rotation only, leght of bond = 1;
const atom = rnd.ctab.molecule.atoms.get(beginAtom);
endPos = vectorUtils.calcNewAtomPos(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
atom!.pp.get_xy0(),
xy1,
event.ctrlKey,
);
}
}
// don't rotate the bond if the distance between the start and end point is too small
if (dist > 0.3) {
const [existingBondId, bond] = this.getExistingBond(
molecule,
beginAtom,
endAtom,
);
dragCtx.action = fromBondAddition(
rnd.ctab,
this.bondProps,
beginAtom,
endAtom,
beginPos,
endPos,
)[0];
if (existingBondId !== null) {
this.dragCtx.existedBond = bond;
this.dragCtx.action.mergeWith(
fromOneBondDeletion(rnd.ctab, existingBondId),
);
}
} else {
delete dragCtx.action;
}
this.restoreBondWhenHoveringOnCanvas(event);
if (dragCtx.action) this.editor.update(dragCtx.action, true);
return true;
}
}
this.editor.hover(
this.editor.findItem(event, ['atoms', 'bonds', 'functionalGroups']),
null,
event,
);
return true;
}