From b50270ab9d3c7e76616a9bd45baef60729d2499c Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 30 Mar 2023 18:21:24 +0300 Subject: [PATCH 1/3] =?UTF-8?q?#2419=20=E2=80=93=20After=20pressing=20Calc?= =?UTF-8?q?ulate=20CIP,=20an=20abbreviation=20appears=20under=20mouse=20cu?= =?UTF-8?q?rsor=20(#2426)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ketcher-react/src/script/editor/Editor.ts | 2 +- packages/ketcher-react/src/script/editor/HoverIcon.ts | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/ketcher-react/src/script/editor/Editor.ts b/packages/ketcher-react/src/script/editor/Editor.ts index 7472774112..cb9fc42a71 100644 --- a/packages/ketcher-react/src/script/editor/Editor.ts +++ b/packages/ketcher-react/src/script/editor/Editor.ts @@ -220,7 +220,7 @@ class Editor implements KetcherEditor { const isAtomToolChosen = name === 'atom' if (!isAtomToolChosen) { - this.hoverIcon.hide() + this.hoverIcon.hide(true) } if (!tool || tool.isNotActiveTool) { diff --git a/packages/ketcher-react/src/script/editor/HoverIcon.ts b/packages/ketcher-react/src/script/editor/HoverIcon.ts index 56c5b4ae69..4087adbb94 100644 --- a/packages/ketcher-react/src/script/editor/HoverIcon.ts +++ b/packages/ketcher-react/src/script/editor/HoverIcon.ts @@ -69,7 +69,7 @@ export class HoverIcon { } onMouseLeave(event: MouseEvent) { - if (!this.isOverLoader(event)) { + if (!this.isOverLoader(event) && this.isShown) { this.shouldBeShownWhenMouseBack = true this.hide() } @@ -86,9 +86,13 @@ export class HoverIcon { this.shouldBeShownWhenMouseBack = false } - hide() { + hide(restShouldBeShownWhenMouseBack?: boolean) { this.element.hide() this.isShown = false + + if (restShouldBeShownWhenMouseBack) { + this.shouldBeShownWhenMouseBack = false + } } initialize(): { @@ -115,8 +119,7 @@ export class HoverIcon { this.element = icon.element this._fill = icon.fill this._label = icon.label - this.isShown = true this.shouldBeShownWhenMouseBack = false - this.updatePosition() + this.hide() } } From e4d8673cdea8d359709b7f16454334e5d7b38707 Mon Sep 17 00:00:00 2001 From: konstantinzharich Date: Thu, 6 Apr 2023 09:21:58 +0200 Subject: [PATCH 2/3] #2425 - changed logic of the mouse down (add async await) (#2444) - created getter isModeFunctionalGroup - created separate method showRemoveAbbreviationPopup to trigger popup - created constants Co-authored-by: Konstantin Zharich --- packages/ketcher-react/src/constants.ts | 4 + .../src/script/editor/tool/template.ts | 74 ++++++++++++++----- .../src/script/ui/action/functionalGroups.ts | 3 +- .../script/ui/state/functionalGroups/index.ts | 3 +- .../script/ui/state/saltsAndSolvents/index.ts | 3 +- 5 files changed, 64 insertions(+), 23 deletions(-) diff --git a/packages/ketcher-react/src/constants.ts b/packages/ketcher-react/src/constants.ts index 38ff054622..02b997bbc4 100644 --- a/packages/ketcher-react/src/constants.ts +++ b/packages/ketcher-react/src/constants.ts @@ -17,3 +17,7 @@ export const KETCHER_INIT_EVENT_NAME = 'ketcher-init' export const KETCHER_SAVED_SETTINGS_KEY = 'ketcher_editor_saved_settings' + +export const MODES = { + FG: 'fg' +} diff --git a/packages/ketcher-react/src/script/editor/tool/template.ts b/packages/ketcher-react/src/script/editor/tool/template.ts index c6fa1f969c..bdbb26701c 100644 --- a/packages/ketcher-react/src/script/editor/tool/template.ts +++ b/packages/ketcher-react/src/script/editor/tool/template.ts @@ -34,6 +34,7 @@ import { import utils from '../shared/utils' import Editor from '../Editor' import { getGroupIdsFromItemArrays } from './helper/getGroupIdsFromItems' +import { MODES } from 'ketcher-react/src/constants' type MergeItems = Record> | null @@ -77,7 +78,7 @@ class TemplateTool { } const bond = frag.bonds.get(this.template.bid) - if (bond && this.mode !== 'fg') { + if (bond && !this.isModeFunctionalGroup) { // template location sign against attachment bond this.template.sign = getSign(frag, bond, this.template.xy0) this.findItems.push('bonds') @@ -94,7 +95,21 @@ class TemplateTool { editor.hoverIcon.updatePosition() } - mousedown(event) { + showRemoveAbbreviationPopup(): Promise { + return this.editor.event.removeFG + .dispatch({ fgIds: this.targetGroupsIds }) + .then(() => { + // case when we remove abbreviation group, click on benzene ring and try to add it + this.targetGroupsIds.length = 0 + return Promise.resolve() + }) + } + + get isModeFunctionalGroup() { + return this.mode === MODES.FG + } + + async mousedown(event) { const closestItem = this.editor.findItem(event, [ 'atoms', 'bonds', @@ -111,6 +126,7 @@ class TemplateTool { }) if ( + // if point is functional group and it is not expanded closestItem?.map === 'functionalGroups' && FunctionalGroup.isContractedFunctionalGroup( closestItem.id, @@ -121,6 +137,18 @@ class TemplateTool { } } + const isTargetExpanded = struct.functionalGroups.get( + this.targetGroupsIds[0] + )?.isExpanded + const isTargetAtomOrBond = + this.targetGroupsIds.length && !this.isModeFunctionalGroup + + if (isTargetAtomOrBond || isTargetExpanded) { + await this.showRemoveAbbreviationPopup() + + return + } + this.editor.hover(null) this.dragCtx = { @@ -137,7 +165,7 @@ class TemplateTool { return } - if (ci.map === 'bonds' && this.mode !== 'fg') { + if (ci.map === 'bonds' && !this.isModeFunctionalGroup) { // calculate fragment center const xy0 = new Vec2() const bond = struct.bonds.get(ci.id) @@ -205,7 +233,7 @@ class TemplateTool { const struct = this.editor.render.ctab.molecule /* moving when attached to bond */ - if (ci && ci.map === 'bonds' && this.mode !== 'fg') { + if (ci && ci.map === 'bonds' && !this.isModeFunctionalGroup) { const bond = struct.bonds.get(ci.id) let sign = getSign(struct, bond, eventPos) @@ -251,8 +279,9 @@ class TemplateTool { targetPos = atom?.pp if (targetPos) { - extraBond = - this.mode === 'fg' ? true : Vec2.dist(targetPos, eventPos) > 1 + extraBond = this.isModeFunctionalGroup + ? true + : Vec2.dist(targetPos, eventPos) > 1 } } } @@ -320,7 +349,7 @@ class TemplateTool { this.editor.update(dragCtx.action, true) - if (this.mode !== 'fg') { + if (!this.isModeFunctionalGroup) { dragCtx.mergeItems = getItemsToFuse(this.editor, pasteItems) this.editor.hover(getHoverToFuse(dragCtx.mergeItems)) } @@ -334,11 +363,6 @@ class TemplateTool { mouseup(event) { const dragCtx = this.dragCtx - if (this.targetGroupsIds.length && this.mode !== 'fg') { - this.editor.event.removeFG.dispatch({ fgIds: this.targetGroupsIds }) - return - } - if (!dragCtx) { return true } @@ -351,7 +375,12 @@ class TemplateTool { const functionalGroups = struct.functionalGroups /* after moving around bond */ - if (dragCtx.action && ci && ci.map === 'bonds' && this.mode !== 'fg') { + if ( + dragCtx.action && + ci && + ci.map === 'bonds' && + !this.isModeFunctionalGroup + ) { dragCtx.action.perform(restruct) // revert drag action const promise = fromTemplateOnBondAction( @@ -386,7 +415,7 @@ class TemplateTool { } else if ( ci?.map === 'functionalGroups' && FunctionalGroup.isContractedFunctionalGroup(ci.id, functionalGroups) && - this.mode === 'fg' && + this.isModeFunctionalGroup && this.targetGroupsIds.length ) { functionalGroupRemoveAction = new Action() @@ -449,7 +478,7 @@ class TemplateTool { action = functionalGroupRemoveAction.mergeWith(action) } dragCtx.action = action - } else if (ci.map === 'bonds' && this.mode !== 'fg') { + } else if (ci.map === 'bonds' && !this.isModeFunctionalGroup) { const promise = fromTemplateOnBondAction( restruct, this.template, @@ -460,7 +489,7 @@ class TemplateTool { ) as Promise promise.then(([action, pasteItems]) => { - if (this.mode !== 'fg') { + if (!this.isModeFunctionalGroup) { const mergeItems = getItemsToFuse(this.editor, pasteItems) action = fromItemsFuse(restruct, mergeItems).mergeWith(action) this.editor.update(action) @@ -473,7 +502,7 @@ class TemplateTool { this.editor.selection(null) - if (!dragCtx.mergeItems && pasteItems && this.mode !== 'fg') { + if (!dragCtx.mergeItems && pasteItems && !this.isModeFunctionalGroup) { dragCtx.mergeItems = getItemsToFuse(this.editor, pasteItems) } dragCtx.action = dragCtx.action @@ -516,9 +545,14 @@ function addSaltsAndSolventsOnCanvasWithoutMerge( } function getTemplateMode(tmpl) { - if (tmpl.mode) return tmpl.mode - if (['Functional Groups', 'Salts and Solvents'].includes(tmpl.props?.group)) - return 'fg' + if (tmpl.mode) { + return tmpl.mode + } + + if (['Functional Groups', 'Salts and Solvents'].includes(tmpl.props?.group)) { + return MODES.FG + } + return null } diff --git a/packages/ketcher-react/src/script/ui/action/functionalGroups.ts b/packages/ketcher-react/src/script/ui/action/functionalGroups.ts index 8e3ac76d91..afc07aa585 100644 --- a/packages/ketcher-react/src/script/ui/action/functionalGroups.ts +++ b/packages/ketcher-react/src/script/ui/action/functionalGroups.ts @@ -15,6 +15,7 @@ ***************************************************************************/ import isHidden from './isHidden' +import { MODES } from 'ketcher-react/src/constants' const functionalGroupsLib = { 'functional-groups': { @@ -22,7 +23,7 @@ const functionalGroupsLib = { // TODO Update HELP about current tools title: 'Functional Groups', action: { dialog: 'templates', prop: { tab: 1 } }, - selected: (editor) => editor._tool.mode === 'fg', + selected: (editor) => editor._tool.mode === MODES.FG, disabled: (_, __, options) => { return !options.app.functionalGroups }, diff --git a/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts b/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts index 8cbd13d9ef..8b81af0db9 100644 --- a/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts +++ b/packages/ketcher-react/src/script/ui/state/functionalGroups/index.ts @@ -25,6 +25,7 @@ import { import templatesRawData from '../../../../templates/fg.sdf' import { memoizedDebounce } from '../../utils' import { TOOLTIP_DELAY } from '../../../editor/utils/functionalGroupsTooltip' +import { MODES } from 'ketcher-react/src/constants' interface FGState { lib: [] @@ -35,7 +36,7 @@ interface FGState { const initialState: FGState = { lib: [], functionalGroupInfo: null, - mode: 'fg' + mode: MODES.FG } const functionalGroupsReducer = ( diff --git a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts index e31aead0b5..5e71abfce0 100644 --- a/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts +++ b/packages/ketcher-react/src/script/ui/state/saltsAndSolvents/index.ts @@ -25,6 +25,7 @@ import { } from 'ketcher-core' import { RenderStruct } from '../../utils' import templatesRawData from '../../../../templates/salts-and-solvents.sdf' +import { MODES } from 'ketcher-react/src/constants' interface SaltsAndSolventsState { lib: [] @@ -33,7 +34,7 @@ interface SaltsAndSolventsState { const initialState: SaltsAndSolventsState = { lib: [], - mode: 'fg' + mode: MODES.FG } const saltsAndSolventsReducer = ( From d5c02f89118ef9bcfed5947cf271e31963ce0f3d Mon Sep 17 00:00:00 2001 From: Nikita Date: Thu, 6 Apr 2023 12:54:38 +0300 Subject: [PATCH 3/3] =?UTF-8?q?#2446=20=E2=80=93=20Structures=20are=20draw?= =?UTF-8?q?n=20outside=20the=20viewbox,=20when=20changing=20rendering=20op?= =?UTF-8?q?tions=20(#2448)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ketcher-react/src/script/editor/Editor.ts | 2 +- .../ketcher-react/src/script/editor/utils/canvasExtension.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ketcher-react/src/script/editor/Editor.ts b/packages/ketcher-react/src/script/editor/Editor.ts index cb9fc42a71..77ad3a4e44 100644 --- a/packages/ketcher-react/src/script/editor/Editor.ts +++ b/packages/ketcher-react/src/script/editor/Editor.ts @@ -285,7 +285,7 @@ class Editor implements KetcherEditor { this.render.clientArea, Object.assign({ scale: SCALE }, value) ) - this.render.setMolecule(struct) // TODO: reuse this.struct here? + this.struct(struct) this.render.setZoom(zoom) this.render.update() return this.render.options diff --git a/packages/ketcher-react/src/script/editor/utils/canvasExtension.ts b/packages/ketcher-react/src/script/editor/utils/canvasExtension.ts index 44bebcc0f1..c6a541bc67 100644 --- a/packages/ketcher-react/src/script/editor/utils/canvasExtension.ts +++ b/packages/ketcher-react/src/script/editor/utils/canvasExtension.ts @@ -1,5 +1,4 @@ import { Vec2 } from 'ketcher-core' -import _ from 'lodash' const edgeOffset = 150