in packages/ketcher-react/src/script/editor/tool/sgroup.ts [284:499]
mouseup(event) {
const struct = this.editor.render.ctab;
const sgroups = struct.sgroups;
const molecule = struct.molecule;
const functionalGroups = molecule.functionalGroups;
const ci = this.editor.findItem(event, searchMaps);
const selected = this.editor.selection();
const newSelected: Record<string, Array<any>> = { atoms: [], bonds: [] };
let actualSgroupId;
let atomsResult: Array<number> | null = [];
let extraAtoms;
let bondsResult: Array<number> | null = [];
let extraBonds;
const result: Array<number> = [];
if (
ci &&
ci.map === 'functionalGroups' &&
functionalGroups.size &&
FunctionalGroup.isContractedFunctionalGroup(ci.id, functionalGroups)
)
return;
if (selected && functionalGroups.size && selected.atoms) {
for (const atom of selected.atoms) {
const atomId = FunctionalGroup.atomsInFunctionalGroup(
functionalGroups,
atom,
);
if (atomId == null) {
extraAtoms = true;
}
const atomFromStruct = atomId !== null && struct.atoms.get(atomId)?.a;
if (atomFromStruct) {
for (const sgId of atomFromStruct.sgs.values()) {
actualSgroupId = sgId;
}
}
if (
atomFromStruct &&
(FunctionalGroup.isAtomInContractedFunctionalGroup(
atomFromStruct,
sgroups,
functionalGroups,
true,
) ||
SGroup.isAtomInContractedSGroup(atomFromStruct, sgroups))
) {
const sgroupAtoms =
actualSgroupId !== undefined &&
SGroup.getAtoms(molecule, struct.sgroups.get(actualSgroupId)?.item);
const sgroupBonds =
actualSgroupId !== undefined &&
SGroup.getBonds(molecule, struct.sgroups.get(actualSgroupId)?.item);
atom === sgroupAtoms[0] &&
newSelected.atoms.push(...(sgroupAtoms as Array<any>)) &&
newSelected.bonds.push(...(sgroupBonds as Array<any>));
}
if (atomFromStruct) {
atomsResult.push(atomId);
}
}
}
if (selected && functionalGroups.size && selected.bonds) {
for (const bond of selected.bonds) {
const bondId = FunctionalGroup.bondsInFunctionalGroup(
molecule,
functionalGroups,
bond,
);
if (bondId === null) {
extraBonds = true;
}
const bondFromStruct = bondId !== null && struct.bonds.get(bondId)?.b;
if (bondFromStruct) {
bondsResult.push(bondId);
}
}
}
if (atomsResult.length) {
atomsResult.forEach((id) => {
const fgId = FunctionalGroup.findFunctionalGroupByAtom(
functionalGroups,
id,
);
if (fgId === null) {
return;
}
const sgroupAtoms = SGroup.getAtoms(
molecule,
struct.sgroups.get(fgId)?.item,
);
newSelected.atoms.push(...sgroupAtoms);
});
}
if (bondsResult.length) {
bondsResult.forEach((id) => {
const fgId = FunctionalGroup.findFunctionalGroupByBond(
molecule,
functionalGroups,
id,
);
if (fgId === null) {
return;
}
const sgroupBonds = SGroup.getBonds(
molecule,
struct.sgroups.get(fgId)?.item,
);
newSelected.bonds.push(...sgroupBonds);
});
}
if (extraAtoms || extraBonds) {
atomsResult = null;
bondsResult = null;
}
if (atomsResult && atomsResult.length > 0) {
for (const id of atomsResult) {
const fgId = FunctionalGroup.findFunctionalGroupByAtom(
functionalGroups,
id,
);
if (fgId !== null && !result.includes(fgId)) {
result.push(fgId);
}
}
}
if (bondsResult && bondsResult.length > 0) {
for (const id of bondsResult) {
const fgId = FunctionalGroup.findFunctionalGroupByBond(
molecule,
functionalGroups,
id,
);
if (fgId !== null && !result.includes(fgId)) {
result.push(fgId);
}
}
}
if (result.length === 1) {
this.editor.selection(null);
this.lassoHelper.cancel();
this.editor.event.removeFG.dispatch({ fgIds: result });
return;
}
let id: number | null = null; // id of an existing group, if we're editing one
let selection: any = null; // atoms to include in a newly created group
if (this.lassoHelper.running(event)) {
// TODO it catches more events than needed, to be re-factored
selection =
newSelected.atoms.length > 0
? selMerge(this.lassoHelper.end(event), newSelected, false)
: this.lassoHelper.end(event);
const filteredAtomsAndBonds = filterNotPartOfSuperatomWithoutLabel(
{ atoms: selection.atoms, bonds: selection.bonds },
molecule,
);
selection = {
...selection,
atoms: filteredAtomsAndBonds.atoms,
bonds: filteredAtomsAndBonds.bonds,
};
this.editor.selection(selection);
} else {
if (!ci) {
// ci.type == 'Canvas'
return;
}
this.editor.hover(this.editor.findItem(event, searchMaps), null, event);
if (ci.map === 'atoms') {
// if we click the SGroup tool on a single atom or bond, make a group out of those
selection = { atoms: [ci.id] };
} else if (ci.map === 'bonds') {
const bond = this.editor.render.ctab.bonds.get(ci.id);
selection = {
atoms: [bond?.b.begin, bond?.b.end],
bonds: [ci.id],
};
} else if (ci.map === 'sgroups' || ci.map === 'sgroupData') {
id = ci.id;
} else {
return;
}
}
const isAtomsOrBondsSelected =
selection?.atoms?.length || selection?.bonds?.length;
// TODO: handle click on an existing group?
if (id !== null || isAtomsOrBondsSelected) {
this.editor.selection(selection);
SGroupTool.sgroupDialog(this.editor, id);
}
}