mouseup()

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);
    }
  }