Skip to content

Commit

Permalink
#5224 – update 2
Browse files Browse the repository at this point in the history
  • Loading branch information
svvald committed Sep 2, 2024
1 parent 0447021 commit ccea823
Show file tree
Hide file tree
Showing 18 changed files with 146 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,15 @@ export class AmbiguousMonomerRenderer extends BaseMonomerRenderer {
selected: selectedAttachmentPoint === attachmentPointName,
usage,
canvas: params.canvas,
applyZoomForPositionCalculation: false,
});
}

public showExternal(params: PreviewAttachmentPointParams) {
this.rootElement = this.appendRootElement(params.canvas);
this.appendBody(this.rootElement);
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this.bodyElement = this.appendBody(this.rootElement);
this.appendLabel(this.rootElement);
this.appendNumberOfMonomers();
this.drawAttachmentPoints(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ export abstract class BaseMonomerRenderer extends BaseRenderer {
this.monomer.isAttachmentPointPotentiallyUsed(attachmentPointName) ||
this.hoveredAttachmentPoint === attachmentPointName,
angle: customAngle ?? rotation,
applyZoomForPositionCalculation: true,
// FIXME: `BaseMonomerRenderer` should not know about `isSnake`.
isSnake: this.isSnakeBondForAttachmentPoint(attachmentPointName),
};
Expand Down
7 changes: 7 additions & 0 deletions packages/ketcher-core/src/domain/AttachmentPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export class AttachmentPoint {
private isUsed: boolean;
private isSnake;
private editorEvents: typeof editorEvents;
private applyZoomForPositionCalculation: boolean;

constructor(
constructorParams: AttachmentPointConstructorParams,
Expand All @@ -70,6 +71,8 @@ export class AttachmentPoint {
this.isSnake = constructorParams.isSnake;
this.isUsed = constructorParams.isUsed;
this.initialAngle = constructorParams.angle;
this.applyZoomForPositionCalculation =
constructorParams.applyZoomForPositionCalculation;
this.editorEvents = editorEvents;
this.attachmentPoint = null;

Expand Down Expand Up @@ -390,9 +393,13 @@ export class AttachmentPoint {
this.monomer,
);

const applyZoomForPositionCalculation =
this.applyZoomForPositionCalculation;

const pointOnBorder = findPointOnMonomerBorder(
currentMonomerCenter,
(this.bodyWidth + this.bodyHeight) / 2,
applyZoomForPositionCalculation,
);

const [labelPoint, pointOfAttachment] = findLabelPoint(
Expand Down
20 changes: 16 additions & 4 deletions packages/ketcher-core/src/domain/PreviewAttachmentPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Coordinates } from 'domain/helpers/attachmentPointCalculations';
import { PreviewAttachmentPointConstructorParams } from 'domain/types';
import { UsageInMacromolecule } from 'application/render';
import util from 'application/render/util';
import { Vec2 } from 'domain/entities';

export class PreviewAttachmentPoint extends AttachmentPoint {
private connected: boolean;
Expand Down Expand Up @@ -50,10 +51,21 @@ export class PreviewAttachmentPoint extends AttachmentPoint {

const labelGroup = this.attachmentPoint?.append('g');

const angleInRadians = Vec2.degrees_to_radians(this.initialAngle);
const cos = Math.cos(angleInRadians);
const sin = Math.sin(angleInRadians);

const centerX = attachmentPointCoordinates.x - 10;
const centerY = attachmentPointCoordinates.y - 8;
const rectX = centerX - 10 * cos;
const rectY = centerY - 10 * sin;
const labelX = attachmentPointCoordinates.x - 10 * cos;
const labelY = attachmentPointCoordinates.y - 10 * sin;

labelGroup
.append('rect')
.attr('x', attachmentPointCoordinates.x - 10)
.attr('y', attachmentPointCoordinates.y - 8)
.attr('x', rectX)
.attr('y', rectY)
.attr('rx', 4)
.attr('ry', 4)
.attr('width', 20)
Expand All @@ -64,8 +76,8 @@ export class PreviewAttachmentPoint extends AttachmentPoint {

labelGroup
.append('text')
.attr('x', attachmentPointCoordinates.x)
.attr('y', attachmentPointCoordinates.y)
.attr('x', labelX)
.attr('y', labelY)
.attr('fill', color)
.attr('font-size', '10px')
.attr('text-anchor', 'middle')
Expand Down
26 changes: 25 additions & 1 deletion packages/ketcher-core/src/domain/entities/AmbiguousMonomer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { monomerFactory } from 'application/editor/operations/monomer/monomerFac
import { KetMonomerClass } from 'application/formatters';
import { MONOMER_CLASS_TO_CONSTRUCTOR } from 'domain/constants/monomers';
import { IVariantMonomer } from 'domain/entities/types';
import { AmbiguousMonomerType } from 'domain/types';
import { AmbiguousMonomerType, AttachmentPointName } from 'domain/types';
export const DEFAULT_VARIANT_MONOMER_LABEL = '%';

export class AmbiguousMonomer extends BaseMonomer implements IVariantMonomer {
Expand Down Expand Up @@ -83,6 +83,30 @@ export class AmbiguousMonomer extends BaseMonomer implements IVariantMonomer {
});
}

public get monomerCaps() {
let monomerCaps: Partial<Record<AttachmentPointName, string>> | undefined;

this.monomers.forEach((monomer) => {
if (monomer.monomerItem.props.MonomerCaps) {
if (!monomerCaps) {
monomerCaps = { ...monomer.monomerItem.props.MonomerCaps };
} else {
for (const [attachmentPointName, label] of Object.entries(
monomer.monomerItem.props.MonomerCaps,
)) {
if (!monomerCaps[attachmentPointName]) {
delete monomerCaps[attachmentPointName];
} else if (monomerCaps[attachmentPointName] !== label) {
monomerCaps[attachmentPointName] = '';
}
}
}
}
});

return monomerCaps;
}

public getValidSourcePoint(_secondMonomer?: BaseMonomer) {
return MONOMER_CLASS_TO_CONSTRUCTOR[
this.monomerClass
Expand Down
4 changes: 4 additions & 0 deletions packages/ketcher-core/src/domain/entities/BaseMonomer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,4 +506,8 @@ export abstract class BaseMonomer extends DrawingEntity {
});
return sideConnections;
}

public get monomerCaps() {
return this.monomerItem.props.MonomerCaps;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export function getSearchFunction(
return function findPointOnMonomerBorder(
coordStart: Coordinates,
length: number,
applyZoomForPositionCalculation: boolean,
angle = initialAngle,
) {
const angleRadians = Vec2.degrees_to_radians(angle);
Expand All @@ -123,15 +124,14 @@ export function getSearchFunction(
const newLength = Math.round(diff.length() / 1.4);
const newCoordStart = { x: secondPoint.x, y: secondPoint.y };

const zoomedCoordinateOfSecondPoint = CoordinatesTool.canvasToView(
new Vec2(secondPoint),
);
const zoomedCoordinateOfSecondPoint = applyZoomForPositionCalculation
? CoordinatesTool.canvasToView(new Vec2(secondPoint))
: new Vec2(secondPoint);

const newPointCoord = {
x: Math.round(zoomedCoordinateOfSecondPoint.x) + canvasOffset.x,
y: Math.round(zoomedCoordinateOfSecondPoint.y) + canvasOffset.y,
};
let newAngle: number = initialAngle;

const elementsAtPoint = document.elementsFromPoint(
newPointCoord.x,
Expand All @@ -141,13 +141,20 @@ export function getSearchFunction(
const isCurrentMonomerAtNewPoint = elementsAtPoint.some(
(element) => element === monomer.renderer?.bodyElement?.node(),
);

let newAngle: number;
if (isCurrentMonomerAtNewPoint) {
newAngle = initialAngle;
} else {
newAngle = initialAngle - 180;
}

return findPointOnMonomerBorder(newCoordStart, newLength, newAngle);
return findPointOnMonomerBorder(
newCoordStart,
newLength,
applyZoomForPositionCalculation,
newAngle,
);
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ export function createMonomersForVariantMonomer(
attachmentPoints: monomerTemplate.attachmentPoints,
};
const [MonomerConstructor] = monomerFactory(monomerItem);
KetSerializer.fillStructRgLabelsByMonomerTemplate(
monomerTemplate,
monomerItem,
);

return new MonomerConstructor(monomerItem, undefined, {
generateId: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,12 +379,15 @@ export class KetSerializer implements Serializer<Struct> {
props: templateToMonomerProps(template),
attachmentPoints: KetSerializer.getTemplateAttachmentPoints(template),
};
this.fillStructRgLabelsByMonomerTemplate(template, monomerLibraryItem);
KetSerializer.fillStructRgLabelsByMonomerTemplate(
template,
monomerLibraryItem,
);

return monomerLibraryItem;
}

public fillStructRgLabelsByMonomerTemplate(
public static fillStructRgLabelsByMonomerTemplate(
template: IKetMonomerTemplate,
monomerItem: MonomerItemType,
) {
Expand Down Expand Up @@ -455,7 +458,7 @@ export class KetSerializer implements Serializer<Struct> {
.monomer as BaseMonomer;
monomerIdsMap[node.$ref] = monomer?.id;

this.fillStructRgLabelsByMonomerTemplate(
KetSerializer.fillStructRgLabelsByMonomerTemplate(
template,
monomer.monomerItem,
);
Expand Down
25 changes: 13 additions & 12 deletions packages/ketcher-core/src/domain/types/monomers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ export type MonomerColorScheme = {
hover: string;
};

export enum AttachmentPointName {
R1 = 'R1',
R2 = 'R2',
R3 = 'R3',
R4 = 'R4',
R5 = 'R5',
R6 = 'R6',
R7 = 'R7',
R8 = 'R8',
}

export type MonomerItemType = {
label: string;
colorScheme?: MonomerColorScheme;
Expand All @@ -36,7 +47,7 @@ export type MonomerItemType = {
Name: string;
// TODO determine whenever these props are optional or not
BranchMonomer?: string;
MonomerCaps?: { [key: string]: string };
MonomerCaps?: Partial<Record<AttachmentPointName, string>>;
MonomerCode?: string;
MonomerType?: string;
MonomerClass?: KetMonomerClass;
Expand All @@ -62,17 +73,6 @@ export type AmbiguousMonomerType = {

export type MonomerOrAmbiguousType = MonomerItemType | AmbiguousMonomerType;

export enum AttachmentPointName {
R1 = 'R1',
R2 = 'R2',
R3 = 'R3',
R4 = 'R4',
R5 = 'R5',
R6 = 'R6',
R7 = 'R7',
R8 = 'R8',
}

export const attachmentPointNames = [
'R1',
'R2',
Expand All @@ -97,6 +97,7 @@ export type AttachmentPointConstructorParams = {
isPotentiallyUsed: boolean;
angle: number;
isSnake: boolean;
applyZoomForPositionCalculation: boolean;
};

export type PreviewAttachmentPointConstructorParams =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import {
ModalContent,
} from './styledComponents';
import { MonomerConnectionProps } from '../modalContainer/types';
import { BaseMonomer, LeavingGroup, UsageInMacromolecule } from 'ketcher-core';
import {
AmbiguousMonomer,
BaseMonomer,
LeavingGroup,
UsageInMacromolecule,
} from 'ketcher-core';
import hydrateLeavingGroup from 'helpers/hydrateLeavingGroup';
import { getConnectedAttachmentPoints } from 'helpers';
import MonomerOverview from 'components/shared/ConnectionOverview/components/MonomerOverview/MonomerOverview';
Expand Down Expand Up @@ -203,13 +208,14 @@ function AttachmentPointSelectionPanel({
setConnectedAttachmentPoints(newConnectedAttachmentPoints);
}, [bonds]);

const getLeavingGroup = (attachmentPoint): LeavingGroup => {
const { MonomerCaps } = monomer.monomerItem.props;
const getLeavingGroup = (attachmentPoint): LeavingGroup | null => {
const MonomerCaps = monomer.monomerCaps;
const isAmbiguousMonomer = monomer instanceof AmbiguousMonomer;
if (!MonomerCaps) {
return 'H';
return isAmbiguousMonomer ? null : 'H';
}
const leavingGroup = MonomerCaps[attachmentPoint];
return hydrateLeavingGroup(leavingGroup) as LeavingGroup;
return hydrateLeavingGroup(leavingGroup);
};

const handleSelectAttachmentPoint = (attachmentPoint: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ const BondPreview = ({ className }: Props) => {
preparedAttachmentPointsData: firstMonomerPreparedAPsData,
connectedAttachmentPoints: firstMonomerConnectedAPs,
} = useAttachmentPoints({
monomer: firstMonomer.monomerItem,
monomerCaps: firstMonomer.monomerCaps,
attachmentPointsToBonds: firstMonomer.attachmentPointsToBonds,
});

const {
preparedAttachmentPointsData: secondMonomerPreparedAPsData,
connectedAttachmentPoints: secondMonomerConnectedAPs,
} = useAttachmentPoints({
monomer: secondMonomer?.monomerItem,
monomerCaps: secondMonomer?.monomerCaps,
attachmentPointsToBonds: secondMonomer?.attachmentPointsToBonds,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const MonomerPreview = ({ className }: Props) => {

const { preparedAttachmentPointsData, connectedAttachmentPoints } =
useAttachmentPoints({
monomer,
monomerCaps: monomer?.props.MonomerCaps,
attachmentPointsToBonds,
});

Expand Down
Loading

0 comments on commit ccea823

Please sign in to comment.