Skip to content

Commit

Permalink
#5935 - Unable to establish hydrogen bond connection if monomer has n…
Browse files Browse the repository at this point in the history
…o free attachment points (#5955) (#5958)

#5940 - Copy/paste operation works wrong (copy only two hydrogen bonds and drops others)

#5941 - Hydrogen bonds remain in place on monomer delete

#5933 - Error message is wrong if user tries to establish hydrogen bond if it is already exist
  • Loading branch information
rrodionov91 authored Nov 12, 2024
1 parent 0bb3715 commit d2f5aa6
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 25 deletions.
16 changes: 12 additions & 4 deletions packages/ketcher-core/src/application/editor/modes/BaseMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import { PolymerBond } from 'domain/entities/PolymerBond';
import { ketcherProvider } from 'application/utils';
import { DrawingEntitiesManager } from 'domain/entities/DrawingEntitiesManager';
import { HydrogenBond } from 'domain/entities/HydrogenBond';
import { AttachmentPointName } from 'domain/types';
import { MACROMOLECULES_BOND_TYPES } from 'application/editor/tools/Bond';

export abstract class BaseMode {
private _pasteIsInProgress = false;
Expand Down Expand Up @@ -115,10 +117,7 @@ export abstract class BaseMode {
entity.position,
entity,
);
} else if (
(entity instanceof PolymerBond || entity instanceof HydrogenBond) &&
entity.secondMonomer
) {
} else if (entity instanceof PolymerBond && entity.secondMonomer) {
const firstAttachmentPoint =
entity.firstMonomer.getAttachmentPointByBond(entity);
const secondAttachmentPoint =
Expand All @@ -138,6 +137,15 @@ export abstract class BaseMode {
entity,
);
}
} else if (entity instanceof HydrogenBond && entity.secondMonomer) {
drawingEntitiesManager.finishPolymerBondCreationModelChange(
entity.firstMonomer,
entity.secondMonomer,
AttachmentPointName.HYDROGEN,
AttachmentPointName.HYDROGEN,
MACROMOLECULES_BOND_TYPES.HYDROGEN,
entity,
);
}
});
const ketSerializer = new KetSerializer();
Expand Down
22 changes: 20 additions & 2 deletions packages/ketcher-core/src/application/editor/tools/Bond.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class PolymerBond implements BaseTool {
const startAttachmentPoint =
selectedRenderer.monomer.startBondAttachmentPoint;

if (!startAttachmentPoint) {
if (!startAttachmentPoint && !this.isHydrogenBond) {
this.editor.events.error.dispatch(
"Selected monomer doesn't have any free attachment points",
);
Expand Down Expand Up @@ -339,14 +339,32 @@ class PolymerBond implements BaseTool {

private finishBondCreation(secondMonomer: BaseMonomer) {
assert(this.bondRenderer);
if (!secondMonomer.hasFreeAttachmentPoint) {

if (!this.isHydrogenBond && !secondMonomer.hasFreeAttachmentPoint) {
this.editor.events.error.dispatch(
"Monomers don't have any connection point available",
);

return this.editor.drawingEntitiesManager.cancelPolymerBondCreation(
this.bondRenderer.polymerBond,
);
}

if (
this.isHydrogenBond &&
secondMonomer.hasHydrogenBondWithMonomer(
this.bondRenderer?.polymerBond.firstMonomer,
)
) {
this.editor.events.error.dispatch(
'Unable to establish multiple hydrogen bonds between two monomers',
);

return this.editor.drawingEntitiesManager.cancelPolymerBondCreation(
this.bondRenderer.polymerBond,
);
}

const firstMonomerAttachmentPoint = this.isHydrogenBond
? AttachmentPointName.HYDROGEN
: this.bondRenderer.polymerBond.firstMonomer.getPotentialAttachmentPointByBond(
Expand Down
63 changes: 52 additions & 11 deletions packages/ketcher-core/src/domain/entities/BaseMonomer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export abstract class BaseMonomer extends DrawingEntity {
public attachmentPointsVisible = false;
public monomerItem: MonomerItemType;
public isMonomerInRnaChainRow = false;
public hydrogenBonds: HydrogenBond[] = [];

constructor(
monomerItem: MonomerItemType,
Expand Down Expand Up @@ -108,16 +109,28 @@ export abstract class BaseMonomer extends DrawingEntity {

public setPotentialBond(
attachmentPoint: string | undefined,
potentialBond?: PolymerBond | null,
potentialBond?: PolymerBond | HydrogenBond | null,
) {
if (potentialBond instanceof HydrogenBond) {
this.hydrogenBonds.push(potentialBond);

return;
}

if (attachmentPoint !== undefined) {
this.potentialAttachmentPointsToBonds[attachmentPoint] = potentialBond;
}
}

public getAttachmentPointByBond(
bond: PolymerBond | MonomerToAtomBond,
bond: PolymerBond | MonomerToAtomBond | HydrogenBond,
): AttachmentPointName | undefined {
if (bond instanceof HydrogenBond) {
return this.hydrogenBonds.find((hydrogenBond) => hydrogenBond === bond)
? AttachmentPointName.HYDROGEN
: undefined;
}

for (const attachmentPointName in this.attachmentPointsToBonds) {
if (this.attachmentPointsToBonds[attachmentPointName] === bond) {
return attachmentPointName as AttachmentPointName;
Expand Down Expand Up @@ -206,7 +219,7 @@ export abstract class BaseMonomer extends DrawingEntity {

public forEachBond(
callback: (
polymerBond: PolymerBond | MonomerToAtomBond,
polymerBond: PolymerBond | MonomerToAtomBond | HydrogenBond,
attachmentPointName: AttachmentPointName,
) => void,
) {
Expand All @@ -218,21 +231,42 @@ export abstract class BaseMonomer extends DrawingEntity {
);
}
}

this.hydrogenBonds.forEach((hydrogenBond) => {
callback(hydrogenBond, AttachmentPointName.HYDROGEN);
});
}

public setBond(
attachmentPointName: AttachmentPointName,
bond: PolymerBond | MonomerToAtomBond | HydrogenBond,
) {
this.attachmentPointsToBonds[
bond instanceof HydrogenBond
? AttachmentPointName.HYDROGEN
: attachmentPointName
] = bond;
if (!(bond instanceof HydrogenBond)) {
this.attachmentPointsToBonds[attachmentPointName] = bond;

return;
}

if (!this.hydrogenBonds.includes(bond)) {
this.hydrogenBonds.push(bond);
}
}

public unsetBond(attachmentPointName: AttachmentPointName) {
this.attachmentPointsToBonds[attachmentPointName] = null;
public unsetBond(
attachmentPointName?: AttachmentPointName,
bondToDelete?: HydrogenBond | PolymerBond,
) {
if (bondToDelete instanceof HydrogenBond) {
this.hydrogenBonds = this.hydrogenBonds.filter(
(bond) => bond !== bondToDelete,
);

return;
}

if (attachmentPointName) {
this.attachmentPointsToBonds[attachmentPointName] = null;
}
}

public get hasBonds() {
Expand All @@ -242,7 +276,14 @@ export abstract class BaseMonomer extends DrawingEntity {
hasBonds = true;
}
}
return hasBonds;

return hasBonds || this.hydrogenBonds.length > 0;
}

public hasHydrogenBondWithMonomer(monomer: BaseMonomer) {
return this.hydrogenBonds.find(
(bond) => bond.firstMonomer === monomer || bond.secondMonomer === monomer,
);
}

public hasPotentialBonds() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -698,11 +698,17 @@ export class DrawingEntitiesManager {
polymerBond.secondMonomer?.removePotentialBonds();
polymerBond.firstMonomer.turnOffSelection();
polymerBond.secondMonomer?.turnOffSelection();
if (firstMonomerAttachmentPoint) {
polymerBond.firstMonomer.unsetBond(firstMonomerAttachmentPoint);
if (firstMonomerAttachmentPoint || polymerBond instanceof HydrogenBond) {
polymerBond.firstMonomer.unsetBond(
firstMonomerAttachmentPoint,
polymerBond,
);
}
if (secondMonomerAttachmentPoint) {
polymerBond.secondMonomer?.unsetBond(secondMonomerAttachmentPoint);
if (secondMonomerAttachmentPoint || polymerBond instanceof HydrogenBond) {
polymerBond.secondMonomer?.unsetBond(
secondMonomerAttachmentPoint,
polymerBond,
);
}
}

Expand Down
8 changes: 5 additions & 3 deletions packages/ketcher-core/src/domain/entities/HydrogenBond.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { BaseRenderer } from 'application/render/renderers/BaseRenderer';
import { SnakeModePolymerBondRenderer } from 'application/render/renderers/PolymerBondRenderer/SnakeModePolymerBondRenderer';
import { BaseMonomer } from './BaseMonomer';
import { BaseBond } from './BaseBond';
import { FlexOrSequenceOrSnakeModePolymerBondRenderer } from 'domain/entities/PolymerBond';

export class HydrogenBond extends BaseBond {
public secondMonomer?: BaseMonomer;
public renderer?: SnakeModePolymerBondRenderer = undefined;
public renderer?: FlexOrSequenceOrSnakeModePolymerBondRenderer = undefined;

constructor(public firstMonomer: BaseMonomer, secondMonomer?: BaseMonomer) {
super();
Expand All @@ -21,7 +21,9 @@ export class HydrogenBond extends BaseBond {
this.secondMonomer = monomer;
}

public setRenderer(renderer: SnakeModePolymerBondRenderer): void {
public setRenderer(
renderer: FlexOrSequenceOrSnakeModePolymerBondRenderer,
): void {
super.setBaseRenderer(renderer as BaseRenderer);
this.renderer = renderer;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/ketcher-core/src/domain/entities/PolymerBond.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { AttachmentPointName } from 'domain/types';
import { BaseMonomer } from './BaseMonomer';
import { BaseBond } from 'domain/entities/BaseBond';

type FlexOrSequenceOrSnakeModePolymerBondRenderer =
export type FlexOrSequenceOrSnakeModePolymerBondRenderer =
| BackBoneBondSequenceRenderer
| FlexModePolymerBondRenderer
| PolymerBondSequenceRenderer
Expand Down

0 comments on commit d2f5aa6

Please sign in to comment.