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

#2276 Click & drag an 'Atom' on FG, Salts and Solvents, FG connected with Atom forms many atoms #2577

Merged
merged 4 commits into from
May 16, 2023
Merged
Changes from 2 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
286 changes: 151 additions & 135 deletions packages/ketcher-react/src/script/editor/tool/atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,174 +65,190 @@ class AtomTool {
}

mousedown(event) {
const struct = this.editor.render.ctab
const sgroups = struct.sgroups
const molecule = struct.molecule
const functionalGroups = molecule.functionalGroups
this.editor.hover(null)
this.editor.selection(null)
const ci = this.editor.findItem(event, ['atoms', 'functionalGroups'])
if (
ci &&
ci.map === 'functionalGroups' &&
functionalGroups &&
FunctionalGroup.isContractedFunctionalGroup(ci.id, functionalGroups)
) {
const action = new Action()
const selectedSgroup = sgroups.get(ci.id)
const sGroupAtoms = SGroup.getAtoms(molecule, selectedSgroup?.item)
const [firstAtom, ...atoms] = sGroupAtoms
const atomNeighbours = molecule.atomGetNeighbors(firstAtom)
const extraNeighbour = atomNeighbours?.some(
(atom) => !sGroupAtoms.includes(atom.aid)
)
if (extraNeighbour) {
action.mergeWith(fromSgroupDeletion(struct, ci.id))
action.mergeWith(fromFragmentDeletion(struct, { atoms: atoms }))
action.mergeWith(
fromAtomsAttrs(struct, firstAtom, this.atomProps, true)
)
} else {
const firstAtomPp = struct.atoms.get(firstAtom)?.a.pp
action.mergeWith(
fromFragmentDeletion(struct, {
atoms: SGroup.getAtoms(molecule, selectedSgroup?.item),
bonds: SGroup.getBonds(molecule, selectedSgroup?.item)
})
)
action.mergeWith(fromAtomAddition(struct, firstAtomPp, this.atomProps))
const {
editor,
editor: {
render: {
ctab: {
molecule: { functionalGroups }
}
}
}
this.editor.update(action)
}
const atomResult: Array<number> = []
const result: Array<number> = []
if (ci && functionalGroups.size && ci.map === 'atoms') {
const atomId = FunctionalGroup.atomsInFunctionalGroup(
} = this

editor.hover(null)
editor.selection(null)

const eventMaps = ['atoms', 'functionalGroups']
const ci = editor.findItem(event, eventMaps)

if (ci?.map === 'atoms') {
const atomId = ci.id

const fgId = FunctionalGroup.findFunctionalGroupByAtom(
functionalGroups,
ci.id
atomId
)
if (atomId !== null) atomResult.push(atomId)
}
if (atomResult.length > 0) {
for (const id of atomResult) {
const fgId = FunctionalGroup.findFunctionalGroupByAtom(
functionalGroups,
id
)
if (fgId !== null && !result.includes(fgId)) {
result.push(fgId)
}

if (fgId !== null) {
editor.event.removeFG.dispatch({ fgIds: [fgId] })
return
}
this.editor.event.removeFG.dispatch({ fgIds: result })
return
}
if (!ci) {
// ci.type == 'Canvas'
this.dragCtx = {}
} else if (ci.map === 'atoms') {
this.dragCtx = { item: ci }

this.dragCtx = {
item: ci
}
}

mousemove(event) {
const rnd = this.editor.render
const {
dragCtx,
atomProps,
editor,
editor: {
render: rnd,
render: {
ctab: reStruct,
ctab: { molecule }
}
}
} = this

if (!this.dragCtx || !this.dragCtx.item) {
this.editor.hoverIcon.show()
this.editor.hoverIcon.updatePosition()
const eventMaps = ['atoms', 'functionalGroups']
const ci = editor.findItem(event, eventMaps)

if (!dragCtx?.item || (ci?.id !== undefined && ci.id === dragCtx.item.id)) {
editor.hoverIcon.show()
editor.hoverIcon.updatePosition()
editor.hover(editor.findItem(event, eventMaps), null, event)

if (dragCtx?.action) {
const action = dragCtx.action.perform(reStruct)

delete dragCtx.action

editor.update(action, true)
}

this.editor.hover(
this.editor.findItem(event, ['atoms', 'functionalGroups']),
null,
event
)
return
} else {
this.editor.hoverIcon.hide()
}

const dragCtx = this.dragCtx
const ci = this.editor.findItem(event, ['atoms'])
editor.hoverIcon.hide()

if (ci && ci.map === 'atoms' && ci.id === dragCtx.item.id) {
// fromAtomsAttrs
this.editor.hover(this.editor.findItem(event, ['atoms']))
return
let atomId: number | undefined
if (dragCtx.item.map === 'atoms') {
atomId = dragCtx.item.id
} else if (dragCtx.item.map === 'functionalGroups') {
const sGroup = molecule.sgroups.get(dragCtx.item.id)
const attachmentAtomId = sGroup?.getAttAtomId(molecule)
atomId = attachmentAtomId
}

// fromAtomAddition
const atom = rnd.ctab.molecule.atoms.get(dragCtx.item.id)
let angle = utils.calcAngle(atom?.pp, rnd.page2obj(event))
if (!event.ctrlKey) angle = utils.fracAngle(angle, null)
const degrees = utils.degrees(angle)
this.editor.event.message.dispatch({ info: degrees + 'º' })
const newAtomPos = utils.calcNewAtomPos(
atom?.pp,
rnd.page2obj(event),
event.ctrlKey
)
if (dragCtx.action) dragCtx.action.perform(rnd.ctab)

dragCtx.action = fromBondAddition(
rnd.ctab,
this.#bondProps,
dragCtx.item.id,
Object.assign({}, this.atomProps),
undefined,
newAtomPos
)[0]
this.editor.update(dragCtx.action, true)
if (atomId !== undefined) {
const atom = molecule.atoms.get(atomId)
let angle = utils.calcAngle(atom?.pp, rnd.page2obj(event))
if (!event.ctrlKey) angle = utils.fracAngle(angle, null)
const degrees = utils.degrees(angle)
editor.event.message.dispatch({ info: degrees + 'º' })
const newAtomPos = utils.calcNewAtomPos(
atom?.pp,
rnd.page2obj(event),
event.ctrlKey
)

if (dragCtx.action) {
dragCtx.action.perform(reStruct)
}

dragCtx.action = fromBondAddition(
rnd.ctab,
this.#bondProps,
atomId,
Object.assign({}, atomProps),
undefined,
newAtomPos
)[0]

editor.update(dragCtx.action, true)
}
}

mouseup(event) {
const struct = this.editor.render.ctab
const molecule = struct.molecule
const functionalGroups = molecule.functionalGroups
const ci = this.editor.findItem(event, ['atoms', 'bonds'])
const atomResult: Array<number> = []
const result: Array<number> = []
if (ci && functionalGroups && ci.map === 'atoms') {
const atomId = FunctionalGroup.atomsInFunctionalGroup(
functionalGroups,
ci.id
)
if (atomId !== null) atomResult.push(atomId)
}
if (atomResult.length > 0) {
for (const id of atomResult) {
const fgId = FunctionalGroup.findFunctionalGroupByAtom(
functionalGroups,
id
)
if (fgId !== null && !result.includes(fgId)) {
result.push(fgId)
const {
dragCtx,
atomProps,
editor,
editor: {
render: rnd,
render: {
ctab: reStruct,
ctab: {
molecule,
molecule: { functionalGroups }
}
}
}
this.editor.event.removeFG.dispatch({ fgIds: result })
return
}
} = this

if (this.dragCtx) {
const dragCtx = this.dragCtx
const rnd = this.editor.render
const ci = editor.findItem(event, ['atoms', 'bonds', 'functionalGroups'])
const action = new Action()

this.editor.update(
dragCtx.action ||
(dragCtx.item
? fromAtomsAttrs(rnd.ctab, dragCtx.item.id, this.atomProps, true)
: fromAtomAddition(rnd.ctab, rnd.page2obj(event), this.atomProps))
if (!dragCtx.item && !ci) {
action.mergeWith(
fromAtomAddition(reStruct, rnd.page2obj(event), atomProps)
)
} else if (dragCtx.item && ci) {
if (dragCtx.item.id === ci.id) {
if (
ci.map === 'functionalGroups' &&
FunctionalGroup.isContractedFunctionalGroup(ci.id, functionalGroups)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's fun that I have the same logic in my PR :) I think we need to extract this into a separate function and reuse it.
https://github.com/epam/ketcher/pull/2580/files#diff-ee62e3d2a7eb8e9230e2d13e3cfe44e4ea9ea805a61f971355d38aab66dda856R62

) {
const sGroup = molecule.sgroups.get(ci.id)
const attachmentAtomId = sGroup?.getAttAtomId(molecule)

if (attachmentAtomId !== undefined) {
const atomsToDelete = [...SGroup.getAtoms(molecule, sGroup)].filter(
(atomId) => atomId !== attachmentAtomId
)
const bondsToDelete = [...SGroup.getBonds(molecule, sGroup)]
action.mergeWith(fromSgroupDeletion(reStruct, ci.id))
action.mergeWith(
fromFragmentDeletion(reStruct, {
atoms: atomsToDelete,
bonds: bondsToDelete
})
)
action.mergeWith(
fromAtomsAttrs(reStruct, attachmentAtomId, atomProps, true)
)
}
} else if (ci.map === 'atoms') {
const atomId = ci.id

delete this.dragCtx
if (
dragCtx.action === undefined &&
FunctionalGroup.atomsInFunctionalGroup(functionalGroups, atomId) ===
null
) {
action.mergeWith(fromAtomsAttrs(reStruct, atomId, atomProps, true))
}
}
}
}
this.editor.event.message.dispatch({

editor.event.message.dispatch({
info: false
})
this.editor.hover(
editor.hover(
this.editor.findItem(event, ['atoms', 'functionalGroups']),
null,
event
)

delete this.dragCtx

editor.update(dragCtx.action ? action.mergeWith(dragCtx.action) : action)
}
}

Expand Down