Skip to content

Commit

Permalink
#1820 – added salts and solvents merge prevention. Removed buttons fr…
Browse files Browse the repository at this point in the history
…om footer
  • Loading branch information
Nitvex committed Dec 5, 2022
1 parent f8fce33 commit 14b056e
Show file tree
Hide file tree
Showing 11 changed files with 434 additions and 1,121 deletions.
1,202 changes: 220 additions & 982 deletions example/public/templates/salts-and-solvents.sdf

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions packages/ketcher-core/src/domain/entities/sgroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,10 @@ export class SGroup {
return Vec2.diff(sgroup.pp, sgroup.bracketBox.p1)
}

static isSaltOrSolvent(molecule: Struct): boolean {
const saltsAndSolventsProvider = SaltsAndSolventsProvider.getInstance();
const saltsAndSolvents = saltsAndSolventsProvider.getSaltsAndSolventsList();
return saltsAndSolvents.some(({ name }) => name === molecule.name)
static isSaltOrSolvent(moleculeName: string): boolean {
const saltsAndSolventsProvider = SaltsAndSolventsProvider.getInstance()
const saltsAndSolvents = saltsAndSolventsProvider.getSaltsAndSolventsList()
return saltsAndSolvents.some(({ name }) => name === moleculeName)
}

static filterAtoms(atoms: any, map: any) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
import { Struct } from '../entities'
import { Struct } from '../entities'

export class SaltsAndSolventsProvider {
// eslint-disable-next-line no-use-before-define
private static instance: SaltsAndSolventsProvider
saltsAndSolventsList: Struct[]
constructor() {
this.saltsAndSolventsList = []
}

public static getInstance(): SaltsAndSolventsProvider {
if (!SaltsAndSolventsProvider.instance) {
SaltsAndSolventsProvider.instance = new SaltsAndSolventsProvider()
}
return SaltsAndSolventsProvider.instance
}

public getSaltsAndSolventsList() {
return this.saltsAndSolventsList
}

public setSaltsAndSolventsList(list: Struct[]): void {
this.saltsAndSolventsList = list
}
}

export class SaltsAndSolventsProvider {
// eslint-disable-next-line no-use-before-define
private static instance: SaltsAndSolventsProvider
saltsAndSolventsList: Struct[]
constructor() {
this.saltsAndSolventsList = []
}

public static getInstance(): SaltsAndSolventsProvider {
if (!SaltsAndSolventsProvider.instance) {
SaltsAndSolventsProvider.instance = new SaltsAndSolventsProvider()
}
return SaltsAndSolventsProvider.instance
}

public getSaltsAndSolventsList() {
return this.saltsAndSolventsList
}

public setSaltsAndSolventsList(list: Struct[]): void {
this.saltsAndSolventsList = list
}
}
47 changes: 46 additions & 1 deletion packages/ketcher-react/src/script/editor/tool/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import {
getItemsToFuse,
FunctionalGroup,
fromSimpleObjectResizing,
fromArrowResizing
fromArrowResizing,
ReStruct
} from 'ketcher-core'

import LassoHelper from './helper/lasso'
Expand Down Expand Up @@ -373,6 +374,16 @@ class SelectTool {

if (dragCtx && dragCtx.stopTapping) dragCtx.stopTapping()

const possibleSaltOrSolvent = struct.sgroups.get(actualSgroupId)
if (SGroup.isSaltOrSolvent(possibleSaltOrSolvent?.item.data.name)) {
preventSaltAndSolventsMerge(struct, dragCtx, editor)
delete this.dragCtx
if (this.#lassoHelper.running()) {
this.selectElementsOnCanvas(newSelected, editor, event)
}
return true
}

if (dragCtx && dragCtx.item) {
dragCtx.action = dragCtx.action
? fromItemsFuse(struct, dragCtx.mergeItems).mergeWith(dragCtx.action)
Expand Down Expand Up @@ -558,6 +569,20 @@ class SelectTool {

this.editor.hover(null)
}

selectElementsOnCanvas(
elements: { atoms: any[]; bonds: any[] },
editor: Editor,
event
) {
const sel =
elements.atoms.length > 0
? selMerge(this.#lassoHelper.end(), elements, false)
: this.#lassoHelper.end()
editor.selection(
!event.shiftKey ? sel : selMerge(sel, editor.selection(), false)
)
}
}

function closestToSel(ci) {
Expand Down Expand Up @@ -591,4 +616,24 @@ function uniqArray(dest, add, reversible: boolean) {
}, [])
}

/**
* Salts and Solvents are kind of special structures:
* they can not be merged with other structures and are always standalone
*/
function preventSaltAndSolventsMerge(
struct: ReStruct,
dragCtx,
editor: Editor
) {
const action = dragCtx.action
? fromItemsFuse(struct, null).mergeWith(dragCtx.action)
: fromItemsFuse(struct, null)
editor.hover(null)
editor.selection(null)
editor.update(action)
editor.event.message.dispatch({
info: false
})
}

export default SelectTool
37 changes: 25 additions & 12 deletions packages/ketcher-react/src/script/editor/tool/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import {
getItemsToFuse,
FunctionalGroup,
SGroup,
ReStruct,
Struct
} from 'ketcher-core'

import utils from '../shared/utils'
Expand Down Expand Up @@ -394,21 +396,13 @@ class TemplateTool {
let action
let pasteItems = null

if (SGroup.isSaltOrSolvent(this.template.molecule)) {
[action] = fromTemplateOnCanvas(
restruct,
this.template,
dragCtx.xy0,
0
)
this.editor.update(action)
this.editor.selection(null)
this.editor.hover(null)
return
if (SGroup.isSaltOrSolvent(this.template.molecule.name)) {
preventSaltAndSolventsMerge(restruct, this.template, dragCtx, this.editor)
return true
}

if (!dragCtx.action) {
if (!ci || SGroup.isSaltOrSolvent(this.template)) {
if (!ci) {
// ci.type == 'Canvas'
;[action, pasteItems] = fromTemplateOnCanvas(
restruct,
Expand Down Expand Up @@ -502,6 +496,25 @@ class TemplateTool {
}
}

/**
* Salts and Solvents are kind of special structures:
* they can not be merged with other structures and are always standalone
*/
function preventSaltAndSolventsMerge(
restruct: ReStruct,
template: Struct,
dragCtx,
editor: Editor
) {
const [action] = fromTemplateOnCanvas(restruct, template, dragCtx.xy0, 0)
editor.update(action)
editor.selection(null)
editor.hover(null)
editor.event.message.dispatch({
info: false
})
}

function getSign(molecule, bond, v) {
const begin = molecule.atoms.get(bond.begin).pp
const end = molecule.atoms.get(bond.end).pp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ interface TemplateLibProps {
lib: Array<Template>
selected: Template
mode: string
initialTab: number,
initialTab: number
saltsAndSolvents: (Template & { modifiedStruct: Struct })[]
}

Expand Down Expand Up @@ -120,24 +120,34 @@ const HeaderContent = () => (
</div>
)

const FooterContent = ({ data, tab }) => (
<div style={{ flexGrow: 1 }}>
<SaveButton
key="save-to-SDF"
data={data}
className={classes.saveButton}
filename={
tab === TemplateTabs.TemplateLibrary
? 'ketcher-tmpls.sdf'
: 'ketcher-fg-tmpls.sdf'
}
>
{tab === TemplateTabs.TemplateLibrary
? 'Save template library to SDF'
: 'Save functional groups to SDF'}
</SaveButton>
</div>
)
const FooterContent = ({ data, tab }) => {
const tabMapping = {
[TemplateTabs.TemplateLibrary]: {
fileName: 'ketcher-tmpls.sdf',
buttonCaption: 'Save template library to SDF'
},
[TemplateTabs.FunctionalGroupLibrary]: {
fileName: 'ketcher-fg-tmpls.sdf',
buttonCaption: 'Save functional groups to SDF'
},
[TemplateTabs.SaltsAndSolvents]: null
}
if (!tabMapping[tab]) {
return null
}
return (
<div style={{ flexGrow: 1 }}>
<SaveButton
key="save-to-SDF"
data={data}
className={classes.saveButton}
filename={tabMapping[tab].fileName}
>
{tabMapping[tab].buttonCaption}
</SaveButton>
</div>
)
}

const TemplateDialog: FC<Props> = (props) => {
const {
Expand Down Expand Up @@ -170,7 +180,9 @@ const TemplateDialog: FC<Props> = (props) => {
}, [functionalGroups, filter])

useEffect(() => {
setFilteredSaltsAndSolvents(filterFGLib(saltsAndSolvents, filter)[SALTS_AND_SOLVENTS])
setFilteredSaltsAndSolvents(
filterFGLib(saltsAndSolvents, filter)[SALTS_AND_SOLVENTS]
)
}, [saltsAndSolvents, filter])

const handleTabChange = (_, tab) => {
Expand Down Expand Up @@ -204,7 +216,7 @@ const TemplateDialog: FC<Props> = (props) => {
const serializerMapper = {
[TemplateTabs.TemplateLibrary]: templateLib,
[TemplateTabs.FunctionalGroupLibrary]: functionalGroups,
[TemplateTabs.SaltsAndSolvents]: saltsAndSolvents,
[TemplateTabs.SaltsAndSolvents]: saltsAndSolvents
}
const data = sdfSerializer.serialize(serializerMapper[tab])

Expand All @@ -214,15 +226,19 @@ const TemplateDialog: FC<Props> = (props) => {
else props.onSelect(tmpl)
}

const footerContent =
tab === TemplateTabs.SaltsAndSolvents ? null : (
<FooterContent tab={tab} data={data} />
)

return (
<Dialog
headerContent={<HeaderContent />}
footerContent={<FooterContent tab={tab} data={data} />}
footerContent={footerContent}
className={`${classes.dialog_body}`}
params={omit(['group'], rest)}
result={() => result()}
buttons={['OK']}
buttonsNameMap={{ OK: 'Add to canvas' }}
buttons={[]}
needMargin={false}
>
<div className={classes.inputContainer}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,15 @@ const TemplateTable: FC<TemplateTableProps> = (props) => {
<Icon name="delete" />
</button>
)}
{(tmpl.props.group !== 'Functional Groups' && tmpl.props.group !== 'Salts and Solvents') && (
<button
className={`${classes.button} ${classes.editButton}`}
onClick={() => onAttach!(tmpl)}
>
<Icon name="edit" />
</button>
)}
{tmpl.props.group !== 'Functional Groups' &&
tmpl.props.group !== 'Salts and Solvents' && (
<button
className={`${classes.button} ${classes.editButton}`}
onClick={() => onAttach!(tmpl)}
>
<Icon name="edit" />
</button>
)}
</div>
)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const initOptionsState = {
server: false,
templates: false,
functionalGroups: false,
saltsAndSolvents: false,
saltsAndSolvents: false
},
analyse: {
values: null,
Expand Down
Loading

0 comments on commit 14b056e

Please sign in to comment.