diff --git a/packages/ketcher-core/src/application/editor/tools/Bond.ts b/packages/ketcher-core/src/application/editor/tools/Bond.ts index 4eb3aadd41..b879f58ff6 100644 --- a/packages/ketcher-core/src/application/editor/tools/Bond.ts +++ b/packages/ketcher-core/src/application/editor/tools/Bond.ts @@ -65,9 +65,9 @@ class PolymerBond implements BaseTool { } public mouseLeavePolymerBond(event) { - if (this.bondRenderer) return; - const renderer: PolymerBondRenderer = event.target.__data__; + if (this.bondRenderer || !renderer.polymerBond) return; + const modelChanges = this.editor.drawingEntitiesManager.hidePolymerBondInformation( renderer.polymerBond, diff --git a/packages/ketcher-core/src/application/render/renderers/BaseMonomerRenderer.ts b/packages/ketcher-core/src/application/render/renderers/BaseMonomerRenderer.ts index 78e02a8272..ceff44a847 100644 --- a/packages/ketcher-core/src/application/render/renderers/BaseMonomerRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/BaseMonomerRenderer.ts @@ -34,8 +34,13 @@ export abstract class BaseMonomerRenderer extends BaseRenderer { private isSnakeBondForAttachmentPoint( attachmentPointName: AttachmentPointName, ) { - return this.monomer.attachmentPointsToBonds[attachmentPointName]?.renderer - ?.isSnake; + return ( + this.monomer.attachmentPointsToBonds[attachmentPointName]?.renderer + ?.isSnake && + !this.monomer.attachmentPointsToBonds[ + attachmentPointName + ]?.renderer?.isMonomersOnSameHorizontalLine() + ); } public get center() { diff --git a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts index 8646e7eb2c..5a8153b13c 100644 --- a/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts +++ b/packages/ketcher-core/src/application/render/renderers/PolymerBondRenderer.ts @@ -22,7 +22,7 @@ export class PolymerBondRenderer extends BaseRenderer { private editorEvents: typeof editorEvents; private selectionElement; private path = ''; - + private previousStateOfIsMonomersOnSameHorisontalLine: boolean | undefined; constructor(public polymerBond: PolymerBond) { super(polymerBond as DrawingEntity); this.polymerBond.setRenderer(this); @@ -85,13 +85,23 @@ export class PolymerBondRenderer extends BaseRenderer { } public moveSelection() { - assert(this.rootElement); - this.moveStart(); - this.moveEnd(); + if ( + this.previousStateOfIsMonomersOnSameHorisontalLine !== + this.isMonomersOnSameHorizontalLine() + ) { + this.remove(); + this.show(); + } else { + assert(this.rootElement); + this.moveStart(); + this.moveEnd(); + } + this.previousStateOfIsMonomersOnSameHorisontalLine = + this.isMonomersOnSameHorizontalLine(); } public appendBond(rootElement) { - if (this.isSnake) { + if (this.isSnake && !this.isMonomersOnSameHorizontalLine()) { this.appendSnakeBond(rootElement); } else { this.appendBondGraph(rootElement); @@ -136,10 +146,6 @@ export class PolymerBondRenderer extends BaseRenderer { } private updateSnakeBondPath(startPosition, endPosition) { - if (this.isMonomersOnSameHorizontalLine()) { - this.addRandomLine(startPosition, endPosition); - return; - } if (this.isSecondMonomerBottomRight(startPosition, endPosition)) { this.addLine( LINE_DIRECTION.Horizontal, @@ -437,7 +443,7 @@ export class PolymerBondRenderer extends BaseRenderer { } public moveEnd() { - if (this.isSnake) { + if (this.isSnake && !this.isMonomersOnSameHorizontalLine()) { this.moveSnakeBondEnd(); } else { this.moveGraphBondEnd(); @@ -474,7 +480,7 @@ export class PolymerBondRenderer extends BaseRenderer { } public moveStart() { - if (this.isSnake) { + if (this.isSnake && !this.isMonomersOnSameHorizontalLine()) { this.moveSnakeBondStart(); } else { this.moveGraphBondStart(); @@ -511,7 +517,7 @@ export class PolymerBondRenderer extends BaseRenderer { } protected appendHoverAreaElement() { - if (this.isSnake) { + if (this.isSnake && !this.isMonomersOnSameHorizontalLine()) { ( | undefined>( this.hoverAreaElement )) = this.rootElement diff --git a/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts b/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts index ee425529db..0cc7332916 100644 --- a/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts +++ b/packages/ketcher-core/src/application/render/renderers/RenderersManager.ts @@ -85,7 +85,7 @@ export class RenderersManager { public finishPolymerBondCreation(polymerBond) { assert(polymerBond.secondMonomer); - polymerBond.renderer?.moveEnd(); + polymerBond.renderer?.moveSelection(); polymerBond.renderer?.redrawHover(); polymerBond.firstMonomer.renderer?.redrawAttachmentPoints(); polymerBond.firstMonomer.renderer?.drawSelection(); diff --git a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts index a64bcafee3..bd2f2ffcc4 100644 --- a/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts +++ b/packages/ketcher-core/src/domain/entities/DrawingEntitiesManager.ts @@ -303,10 +303,7 @@ export class DrawingEntitiesManager { polymerBond.firstMonomer.removePotentialBonds(); polymerBond.secondMonomer.removePotentialBonds(); - polymerBond.moveBondEndAbsolute( - secondMonomer.renderer.center.x, - secondMonomer.renderer.center.y, - ); + polymerBond.moveToLinkedMonomers(); polymerBond.firstMonomer.turnOffSelection(); polymerBond.firstMonomer.turnOffHover(); @@ -379,7 +376,6 @@ export class DrawingEntitiesManager { polymerBond?: PolymerBond, ) { const command = new Command(); - assert(polymerBond); if ( polymerBond && polymerBond.firstMonomer.getPotentialAttachmentPointByBond( @@ -530,6 +526,27 @@ export class DrawingEntitiesManager { return command; } + private findChainByMonomer( + monomer: BaseMonomer, + monomerChain = [], + previousMonomer?: BaseMonomer, + ) { + monomerChain.push(monomer); + for (const attachmentPointName in monomer.attachmentPointsToBonds) { + const polymerBond = monomer.attachmentPointsToBonds[attachmentPointName]; + if (polymerBond) { + const nextMonomer = + monomer === polymerBond.firstMonomer + ? polymerBond.secondMonomer + : polymerBond.firstMonomer; + if (previousMonomer !== nextMonomer) { + this.findChainByMonomer(nextMonomer, monomerChain, monomer); + } + } + } + return monomerChain; + } + private rearrangeChain( monomer: BaseMonomer, initialPosition: Vec2, @@ -564,12 +581,14 @@ export class DrawingEntitiesManager { polymerBond.secondMonomer === monomer ? polymerBond.firstMonomer : polymerBond.secondMonomer; - if (attachmentPointName === 'R1' || nextMonomer === lastMonomer) { + if (nextMonomer === lastMonomer) { continue; } if ( - attachmentPointName === 'R2' && - nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1' + (attachmentPointName === 'R2' && + nextMonomer.getAttachmentPointByBond(polymerBond) === 'R1') || + (attachmentPointName === 'R1' && + nextMonomer.getAttachmentPointByBond(polymerBond) === 'R2') ) { const isMonomerFitCanvas = newPosition.x + @@ -658,14 +677,35 @@ export class DrawingEntitiesManager { ) === 'R1' ); }); + firstMonomersInChains.sort((monomer1, monomer2) => { if ( monomer2.position.x + monomer2.position.y < monomer1.position.x + monomer1.position.y ) { - return 1; - } else { return -1; + } else { + return 1; + } + }); + + const filteredFirstMonomersInChains = []; + + firstMonomersInChains.forEach((monomer, monomerIndex) => { + const currentMonomerChain = this.findChainByMonomer(monomer); + let isFirstMonomerInChain = true; + firstMonomersInChains.forEach( + (potentialFirstMonomer, potentialFirstMonomerIndex) => { + if ( + potentialFirstMonomerIndex > monomerIndex && + currentMonomerChain.includes(potentialFirstMonomer) + ) { + isFirstMonomerInChain = false; + } + }, + ); + if (isFirstMonomerInChain) { + filteredFirstMonomersInChains.push(monomer); } }); const command = new Command(); @@ -674,7 +714,7 @@ export class DrawingEntitiesManager { y: MONOMER_START_Y_POSITION, }); - firstMonomersInChains.forEach((monomer, monomerIndex) => { + filteredFirstMonomersInChains.reverse().forEach((monomer, monomerIndex) => { const rearrangeResult = this.rearrangeChain( monomer, lastPosition,