Skip to content

Commit

Permalink
#5403 - Introduce hydrogen bonds in macromolecules mode
Browse files Browse the repository at this point in the history
  • Loading branch information
rrodionov91 committed Oct 25, 2024
1 parent 6b290e3 commit cabaa61
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { RenderersManager } from 'application/render/renderers/RenderersManager'
import { createPolymerEditorCanvas } from '../../helpers/dom';
import { CoreEditor } from 'application/editor';
import { FlexMode } from 'application/editor/modes/FlexMode';
import { MACROMOLECULES_BOND_TYPES } from 'application/editor/tools/Bond';

describe('Drawing Entities Manager', () => {
it('should create monomer', () => {
Expand All @@ -42,6 +43,7 @@ describe('Drawing Entities Manager', () => {
new Peptide(peptideMonomerItem),
new Vec2(0, 0),
new Vec2(10, 10),
MACROMOLECULES_BOND_TYPES.SINGLE,
);
expect(command.operations.length).toEqual(1);
expect(command.operations[0]).toBeInstanceOf(PolymerBondAddOperation);
Expand All @@ -64,6 +66,7 @@ describe('Drawing Entities Manager', () => {
firstPeptide,
new Vec2(0, 0),
new Vec2(10, 10),
MACROMOLECULES_BOND_TYPES.SINGLE,
);

const resultingOperations =
Expand Down Expand Up @@ -118,6 +121,7 @@ describe('Drawing Entities Manager', () => {
new Peptide(peptideMonomerItem),
new Vec2(0, 0),
new Vec2(10, 10),
MACROMOLECULES_BOND_TYPES.SINGLE,
);
expect(
Array.from(drawingEntitiesManager.polymerBonds)[0][1],
Expand Down
7 changes: 4 additions & 3 deletions packages/ketcher-core/src/application/editor/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import { Coordinates } from './shared/coordinates';
import ZoomTool from './tools/Zoom';
import { ViewModel } from 'application/render/view-model/ViewModel';
import { HandTool } from 'application/editor/tools/Hand';
import { HydrogenBond } from 'domain/entities/HydrogenBond';

interface ICoreEditorConstructorParams {
theme;
Expand Down Expand Up @@ -223,7 +224,8 @@ export class CoreEditor {
);
} else if (
eventData instanceof FlexModePolymerBondRenderer ||
eventData instanceof SnakeModePolymerBondRenderer
(eventData instanceof SnakeModePolymerBondRenderer &&
!(eventData.polymerBond instanceof HydrogenBond))
) {
this.events.rightClickPolymerBond.dispatch(event, eventData);
} else if (isClickOnCanvas) {
Expand Down Expand Up @@ -317,7 +319,7 @@ export class CoreEditor {
}
}

public onSelectTool(tool: ToolName, options?: {}) {
public onSelectTool(tool: ToolName, options?: object) {
this.selectTool(tool, options);
}

Expand Down Expand Up @@ -433,7 +435,6 @@ export class CoreEditor {
}

public selectTool(name: ToolName, options?) {
console.log(options);
const ToolConstructor: ToolConstructorInterface = toolsMap[name];
const oldTool = this.tool;

Expand Down
8 changes: 6 additions & 2 deletions packages/ketcher-core/src/application/editor/tools/Bond.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class PolymerBond implements BaseTool {
private bondRenderer?: FlexModeOrSnakeModePolymerBondRenderer;
private isBondConnectionModalOpen = false;
private history: EditorHistory;
private bondType: string;
private bondType: MACROMOLECULES_BOND_TYPES;

constructor(private editor: CoreEditor, options: { toolName: string }) {
this.editor = editor;
Expand Down Expand Up @@ -110,6 +110,7 @@ class PolymerBond implements BaseTool {
selectedRenderer.monomer,
selectedRenderer.monomer.position,
Coordinates.canvasToModel(this.editor.lastCursorPositionOfCanvas),
this.bondType,
);

this.editor.renderersContainer.update(modelChanges);
Expand Down Expand Up @@ -438,7 +439,10 @@ class PolymerBond implements BaseTool {
}

public mouseUpAtom(event) {
if (!this.bondRenderer) {
if (
!this.bondRenderer ||
this.bondType === MACROMOLECULES_BOND_TYPES.HYDROGEN
) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { PolymerBond } from 'domain/entities/PolymerBond';
import { getSugarFromRnaBase } from 'domain/helpers/monomers';
import { BaseRenderer } from '../BaseRenderer';
import { HydrogenBond } from 'domain/entities/HydrogenBond';
import { SnakeMode } from 'application/editor';

enum LineDirection {
Horizontal = 'Horizontal',
Expand Down Expand Up @@ -125,7 +126,8 @@ export class SnakeModePolymerBondRenderer extends BaseRenderer {
const cells = matrix?.polymerBondToCells.get(this.polymerBond);

if (
(this.isHydrogenBond || this.polymerBond.isSideChainConnection) &&
this.polymerBond.isSideChainConnection &&
(!this.isHydrogenBond || editor.mode instanceof SnakeMode) &&
cells
) {
this.appendSideConnectionBond(rootElement, cells);
Expand Down Expand Up @@ -755,7 +757,7 @@ export class SnakeModePolymerBondRenderer extends BaseRenderer {
this.selectionElement?.remove();
if (
(this.isSnakeBond && !this.isMonomersOnSameHorizontalLine()) ||
this.polymerBond.isSideChainConnection
(this.polymerBond.isSideChainConnection && this.path)
) {
this.selectionElement = this.rootElement
?.insert('path', ':first-child')
Expand Down Expand Up @@ -865,7 +867,7 @@ export class SnakeModePolymerBondRenderer extends BaseRenderer {
protected appendHoverAreaElement(): void {
if (
(this.isSnakeBond && !this.isMonomersOnSameHorizontalLine()) ||
this.polymerBond.isSideChainConnection
(this.polymerBond.isSideChainConnection && this.path)
) {
(<D3SvgElementSelection<SVGPathElement, void> | undefined>(
this.hoverAreaElement
Expand Down Expand Up @@ -921,9 +923,7 @@ export class SnakeModePolymerBondRenderer extends BaseRenderer {
);
}

this.bodyElement
.attr('stroke', this.isHydrogenBond ? '#333333' : '#0097A8')
.attr('pointer-events', 'none');
this.bodyElement.attr('stroke', '#0097A8').attr('pointer-events', 'none');

if (this.polymerBond.selected && this.selectionElement) {
this.selectionElement.attr('stroke', '#CCFFDD');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ export class DrawingEntitiesManager {
// This check helps to avoid operations duplication
if (bond.selected) return;

if (bond instanceof PolymerBond) {
if (bond instanceof PolymerBond || bond instanceof HydrogenBond) {
// We need to remove connected bond when doing a group selection even if it is not selected
// and mark it as selected to avoid operations duplication
bond.turnOnSelection();
Expand Down Expand Up @@ -631,14 +631,18 @@ export class DrawingEntitiesManager {
firstMonomer,
startPosition,
endPosition,
bondType = MACROMOLECULES_BOND_TYPES.SINGLE,
_polymerBond?: PolymerBond,
) {
if (_polymerBond) {
this.polymerBonds.set(_polymerBond.id, _polymerBond);
return _polymerBond;
}

const polymerBond = new PolymerBond(firstMonomer);
const polymerBond =
bondType === MACROMOLECULES_BOND_TYPES.HYDROGEN
? new HydrogenBond(firstMonomer)
: new PolymerBond(firstMonomer);
this.polymerBonds.set(polymerBond.id, polymerBond);
// If we started from a specific AP, we need to 'attach' the bond to the first monomer
if (firstMonomer.chosenFirstAttachmentPointForBond) {
Expand All @@ -651,7 +655,12 @@ export class DrawingEntitiesManager {
return polymerBond;
}

public startPolymerBondCreation(firstMonomer, startPosition, endPosition) {
public startPolymerBondCreation(
firstMonomer: BaseMonomer,
startPosition: Vec2,
endPosition: Vec2,
bondType: MACROMOLECULES_BOND_TYPES,
) {
const command = new Command();

const operation = new PolymerBondAddOperation(
Expand All @@ -660,6 +669,7 @@ export class DrawingEntitiesManager {
firstMonomer,
startPosition,
endPosition,
bondType,
),
this.deletePolymerBondChangeModel.bind(this),
);
Expand Down Expand Up @@ -692,7 +702,7 @@ export class DrawingEntitiesManager {
}
}

public deletePolymerBond(polymerBond: PolymerBond) {
public deletePolymerBond(polymerBond: PolymerBond | HydrogenBond) {
const command = new Command();

const operation = new PolymerBondDeleteOperation(
Expand Down Expand Up @@ -1020,12 +1030,15 @@ export class DrawingEntitiesManager {

polymerBond.turnOnHover();
polymerBond.firstMonomer.turnOnHover();
polymerBond.firstMonomer.turnOnAttachmentPointsVisibility();

assert(polymerBond.secondMonomer);

polymerBond.secondMonomer.turnOnHover();
polymerBond.secondMonomer.turnOnAttachmentPointsVisibility();

if (!(polymerBond instanceof HydrogenBond)) {
polymerBond.firstMonomer.turnOnAttachmentPointsVisibility();
polymerBond.secondMonomer.turnOnAttachmentPointsVisibility();
}

const operation = new PolymerBondShowInfoOperation(polymerBond);

Expand Down
1 change: 1 addition & 0 deletions packages/ketcher-core/src/domain/entities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ export * from './UnsplitNucleotide';
export * from './PolymerBond';
export * from './AmbiguousMonomer';
export * from './MonomerToAtomBond';
export * from './HydrogenBond';
6 changes: 5 additions & 1 deletion packages/ketcher-macromolecules/src/EditorEvents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
Nucleoside,
Nucleotide,
PolymerBond,
HydrogenBond,
} from 'ketcher-core';
import { selectAllPresets } from 'state/rna-builder';
import {
Expand Down Expand Up @@ -164,7 +165,10 @@ export const EditorEvents = () => {
(e) => {
const polymerBond = e.target.__data__?.polymerBond;

if (polymerBond && !polymerBond.finished) {
if (
(polymerBond && !polymerBond.finished) ||
polymerBond instanceof HydrogenBond
) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function LeftMenuComponent() {
<Menu.Submenu
disabled={isSequenceMode}
testId="bond-tool-submenu"
needOpenByMenuItemClick={true}
needOpenByMenuItemClick={false}
>
<Menu.Item
itemId="bond-single"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const OptionsContainer = styled.div<OptionsContainerProps>`
display: flex;
position: absolute;
left: ${({ isVertical }) => (isVertical ? '-34px' : '5px')};
top: ${({ isVertical }) => (isVertical ? '38px' : '0')};
top: ${({ isVertical }) => (isVertical ? '38px' : '-19px')};
border-radius: 4px;
flex-direction: ${({ isVertical }) => (isVertical ? 'column' : 'row')};
z-index: 1;
Expand Down

0 comments on commit cabaa61

Please sign in to comment.