Skip to content

Commit

Permalink
#2276 Click & drag an 'Atom' on FG, Salts and Solvents, FG connected …
Browse files Browse the repository at this point in the history
…with Atom forms many atoms (#2577)

* #2276 - atom tool mousedown, mousemove and mouseup events refactored

* #2276 - revert bond action if the user hovers over the original target

* #2276 - click and drag action on salt or solvent does not create a bond with atom

* #2276 - atom tool click action on salt or solvent fixed

---------

Co-authored-by: Dmitrii Vasilev <dmitrii.vasilev@clarivate.com>
  • Loading branch information
VasilevDO and Dmitrii Vasilev authored May 16, 2023
1 parent 1c0ce0e commit d399ad2
Showing 1 changed file with 165 additions and 135 deletions.
300 changes: 165 additions & 135 deletions packages/ketcher-react/src/script/editor/tool/atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,174 +67,204 @@ 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,
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 }

const ciFunctionalGroupName =
ci?.map === 'functionalGroups'
? molecule.sgroups.get(ci?.id)?.data.name
: undefined
const isSaltOrSolvent = ciFunctionalGroupName
? SGroup.isSaltOrSolvent(ciFunctionalGroupName)
: false

this.dragCtx = {
item: ci,
isSaltOrSolvent
}
}

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 ||
dragCtx?.isSaltOrSolvent ||
(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 || dragCtx?.isSaltOrSolvent) && !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)
) {
const sGroup = molecule.sgroups.get(ci.id)
const attachmentAtomId = sGroup?.getAttAtomId(molecule)

delete this.dragCtx
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

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

0 comments on commit d399ad2

Please sign in to comment.