Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#5236 - Replace monomer from library at view mode goes wrong for all types of monomer converded to @ symbol #5478

Open
wants to merge 1 commit into
base: release/2.25
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 117 additions & 35 deletions packages/ketcher-core/src/application/editor/modes/SequenceMode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,46 @@ export class SequenceMode extends BaseMode {
const hasNextNodeInChain =
selection.node.lastMonomerInNode.attachmentPointsToBonds.R2;

let newSequenceNode;

if (selection.node instanceof LinkerSequenceNode) {
const addedMonomers: BaseMonomer[] = [];

selection.node.monomers.forEach((_, monomerIndex) => {
const monomerAddCommand = editor.drawingEntitiesManager.addMonomer(
monomerItem,
position,
);
const newMonomer = monomerAddCommand.operations[0]
.monomer as BaseMonomer;

modelChanges.merge(monomerAddCommand);
addedMonomers.push(newMonomer);

if (monomerIndex > 0) {
modelChanges.merge(
editor.drawingEntitiesManager.createPolymerBond(
addedMonomers[monomerIndex - 1],
newMonomer,
AttachmentPointName.R2,
AttachmentPointName.R1,
),
);
}
});

newSequenceNode = new LinkerSequenceNode(addedMonomers[0]);
} else {
const monomerAddCommand = editor.drawingEntitiesManager.addMonomer(
monomerItem,
position,
);
const newMonomer = monomerAddCommand.operations[0].monomer as BaseMonomer;
modelChanges.merge(monomerAddCommand);

newSequenceNode = new MonomerSequenceNode(newMonomer);
}

selection.node.monomers.forEach((monomer) => {
modelChanges.merge(editor.drawingEntitiesManager.deleteMonomer(monomer));
monomer.forEachBond((polymerBond) => {
Expand All @@ -1104,17 +1144,9 @@ export class SequenceMode extends BaseMode {
});
});

const monomerAddCommand = editor.drawingEntitiesManager.addMonomer(
monomerItem,
position,
);
const newMonomer = monomerAddCommand.operations[0].monomer as BaseMonomer;
const newMonomerSequenceNode = new MonomerSequenceNode(newMonomer);

modelChanges.merge(monomerAddCommand);
modelChanges.merge(
this.insertNewSequenceFragment(
newMonomerSequenceNode,
newSequenceNode,
nextNode || null,
previousSelectionNode,
Boolean(hasPreviousNodeInChain),
Expand All @@ -1131,7 +1163,7 @@ export class SequenceMode extends BaseMode {
} = sideConnectionData;
if (
!this.isConnectionPossible(
newMonomer,
newSequenceNode.monomer,
firstMonomerAttachmentPointName,
secondMonomer,
secondMonomerAttachmentPointName,
Expand All @@ -1142,15 +1174,15 @@ export class SequenceMode extends BaseMode {

modelChanges.merge(
editor.drawingEntitiesManager.createPolymerBond(
newMonomer,
newSequenceNode.monomer,
secondMonomer,
firstMonomerAttachmentPointName,
secondMonomerAttachmentPointName,
),
);
});

return newMonomerSequenceNode;
return newSequenceNode;
}

private replaceSelectionsWithMonomer(
Expand Down Expand Up @@ -1488,6 +1520,43 @@ export class SequenceMode extends BaseMode {
selection.node.lastMonomerInNode.attachmentPointsToBonds.R2;

const sideChainConnections = this.preserveSideChainConnections(selection);
const newPresetNodes: Array<Nucleoside | Nucleotide | LinkerSequenceNode> =
[];

if (selection.node instanceof LinkerSequenceNode) {
selection.node.monomers.forEach((_, monomerIndex) => {
const newPresetNode = this.createRnaPresetNode(preset, position);

assert(newPresetNode);

const rnaPresetAddModelChanges =
editor.drawingEntitiesManager.addRnaPresetFromNode(newPresetNode);

modelChanges.merge(rnaPresetAddModelChanges);
newPresetNodes.push(newPresetNode);

if (monomerIndex > 0) {
modelChanges.merge(
editor.drawingEntitiesManager.createPolymerBond(
newPresetNodes[monomerIndex - 1].lastMonomerInNode,
newPresetNode.firstMonomerInNode,
AttachmentPointName.R2,
AttachmentPointName.R1,
),
);
}
});
} else {
const newPresetNode = this.createRnaPresetNode(preset, position);

assert(newPresetNode);

const rnaPresetAddModelChanges =
editor.drawingEntitiesManager.addRnaPresetFromNode(newPresetNode);

modelChanges.merge(rnaPresetAddModelChanges);
newPresetNodes.push(newPresetNode);
}

selection.node.monomers.forEach((monomer) => {
modelChanges.merge(editor.drawingEntitiesManager.deleteMonomer(monomer));
Expand All @@ -1498,31 +1567,44 @@ export class SequenceMode extends BaseMode {
});
});

const newPresetNode = this.createRnaPresetNode(preset, position);

assert(newPresetNode);

const rnaPresetAddModelChanges =
editor.drawingEntitiesManager.addRnaPresetFromNode(newPresetNode);

modelChanges.merge(rnaPresetAddModelChanges);
modelChanges.merge(
this.insertNewSequenceFragment(
newPresetNode,
nextNode || null,
previousSelectionNode,
Boolean(hasPreviousNodeInChain),
Boolean(hasNextNodeInChain),
),
);
if (newPresetNodes.length > 1) {
modelChanges.merge(
this.insertNewSequenceFragment(
newPresetNodes[0],
null,
previousSelectionNode,
Boolean(hasPreviousNodeInChain),
Boolean(hasNextNodeInChain),
),
);
modelChanges.merge(
this.insertNewSequenceFragment(
newPresetNodes[newPresetNodes.length - 1],
nextNode,
undefined,
Boolean(hasPreviousNodeInChain),
Boolean(hasNextNodeInChain),
),
);
} else {
modelChanges.merge(
this.insertNewSequenceFragment(
newPresetNodes[0],
nextNode || null,
previousSelectionNode,
Boolean(hasPreviousNodeInChain),
Boolean(hasNextNodeInChain),
),
);
}

// TODO: This check breaks some side chains (e.g. Sugar-to-Sugar for Nucleotides), need another way of preserving connections
const monomerForSideConnections =
newPresetNode instanceof Nucleotide
? newPresetNode.phosphate
: newPresetNode instanceof Nucleoside
? newPresetNode.sugar
: newPresetNode.monomer;
newPresetNodes[0] instanceof Nucleotide
? newPresetNodes[0].phosphate
: newPresetNodes[0] instanceof Nucleoside
? newPresetNodes[0].sugar
: newPresetNodes[0].monomer;

sideChainConnections?.forEach((sideConnectionData) => {
const {
Expand Down Expand Up @@ -1551,7 +1633,7 @@ export class SequenceMode extends BaseMode {
);
});

return newPresetNode;
return newPresetNodes.at(-1);
}

private replaceSelectionsWithPreset(
Expand Down
Loading