Skip to content

Commit

Permalink
#2078 – Center molecules after layout
Browse files Browse the repository at this point in the history
  • Loading branch information
Nitvex committed Jul 18, 2023
1 parent ad26c41 commit 8f65ff7
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 36 deletions.
35 changes: 35 additions & 0 deletions ketcher-autotests/tests/Indigo-Tools/Layout/layout.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Page, test } from '@playwright/test';
import {
selectTopPanelButton,
TopPanelButton,
takeEditorScreenshot,
openFile,
pressButton,
waitForLoad,
getCoordinatesOfTheMiddleOfTheScreen,
} from '@utils';

async function openFileWithShift(filename: string, page: Page) {
await selectTopPanelButton(TopPanelButton.Open, page);
await openFile(filename, page);
await waitForLoad(page, async () => {
await pressButton(page, 'Add to Canvas');
});
const { x, y } = await getCoordinatesOfTheMiddleOfTheScreen(page);
const shift = 150;
await page.mouse.click(x + shift, y + shift);
}

test.describe('Indigo Tools - Layout', () => {
test.beforeEach(async ({ page }) => {
await page.goto('');
});

test('Center molecule after layout', async ({ page }) => {
// Related Github issue: https://github.com/epam/ketcher/issues/2078
const anyStructure = 'benzene-rings.mol';
await openFileWithShift(anyStructure, page);
await selectTopPanelButton(TopPanelButton.Layout, page);
await takeEditorScreenshot(page);
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions ketcher-autotests/tests/test-data/benzene-rings.mol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
null
Ketcher 7172314 12D 1 1.00000 0.00000 0

18 20 0 0 0 0 0 0 0 0999 V2000
20.5750 -8.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.7090 -10.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.7090 -9.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
20.5750 -10.6000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
21.4410 -9.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
21.4410 -10.1000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.8679 -7.8929 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
18.1961 -7.4466 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
18.9014 -8.1523 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
18.4545 -6.4796 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
20.1273 -6.9220 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.4156 -6.2194 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
20.1227 -5.5123 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
18.8981 -4.2900 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.1560 -5.2537 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.6054 -3.5817 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
20.8329 -4.8013 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
20.5678 -3.8369 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
3 1 2 0 0 0
4 2 2 0 0 0
1 5 1 0 0 0
2 3 1 0 0 0
5 6 2 0 0 0
6 4 1 0 0 0
1 7 1 0 0 0
9 7 2 0 0 0
10 8 2 0 0 0
7 11 1 0 0 0
8 9 1 0 0 0
11 12 2 0 0 0
12 10 1 0 0 0
12 13 1 0 0 0
15 13 2 0 0 0
16 14 2 0 0 0
13 17 1 0 0 0
14 15 1 0 0 0
17 18 2 0 0 0
18 16 1 0 0 0
M END
59 changes: 23 additions & 36 deletions packages/ketcher-react/src/script/editor/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
fromDescriptorsAlign,
fromMultipleMove,
fromNewCanvas,
ReStruct,
} from 'ketcher-core';
import {
DOMSubscription,
Expand All @@ -47,6 +46,11 @@ import {
ToolConstructorInterface,
ToolEventHandlerName,
} from './tool/Tool';
import {
getSelectionMap,
getStructCenter,
recoordinate,
} from './utils/structLayout';

const SCALE = 40;
const HISTORY_SIZE = 32; // put me to options
Expand Down Expand Up @@ -83,7 +87,7 @@ const highlightTargets = [

function selectStereoFlagsIfNecessary(
atoms: any,
expAtoms: number[]
expAtoms: number[],
): number[] {
const atomsOfFragments = {};
atoms.forEach((atom, atomId) => {
Expand Down Expand Up @@ -157,8 +161,8 @@ class Editor implements KetcherEditor {
{
scale: SCALE,
},
options
)
options,
),
);

this._selection = null; // eslint-disable-line
Expand Down Expand Up @@ -304,7 +308,7 @@ class Editor implements KetcherEditor {

this.render = new Render(
this.render.clientArea,
Object.assign({ scale: SCALE }, value)
Object.assign({ scale: SCALE }, value),
);
this.struct(struct);
this.render.setZoom(zoom);
Expand Down Expand Up @@ -332,15 +336,15 @@ class Editor implements KetcherEditor {
const structure = this.render.ctab;
const { scale, offset } = this.render.options;
const structCenter = getStructCenter(structure);
const canvasCenter = this.render.sz.scaled(1 / scale).scaled(0.5);
const { width, height } = this.render.clientArea.getBoundingClientRect();
const canvasCenterVector = new Vec2(width, height);
const canvasCenter = this.render.view2obj(canvasCenterVector).scaled(0.5);
const shiftFactor = 0.4;
const shiftVector = canvasCenter
.sub(structCenter)
.sub(offset.scaled(1 / scale));
.sub(offset.scaled(shiftFactor / scale));

const structureToMove = Object.keys(ReStruct.maps).reduce((result, map) => {
result[map] = Array.from(structure[map].keys());
return result;
}, {});
const structureToMove = getSelectionMap(structure);

const action = fromMultipleMove(structure, structureToMove, shiftVector);
this.update(action, true);
Expand All @@ -365,7 +369,7 @@ class Editor implements KetcherEditor {
this.zoom(
newZoomValue < MIN_ZOOM_VALUE
? MIN_ZOOM_VALUE
: Number(newZoomValue.toFixed(2))
: Number(newZoomValue.toFixed(2)),
);
}
}
Expand Down Expand Up @@ -406,12 +410,12 @@ class Editor implements KetcherEditor {
}
const stereoFlags = selectStereoFlagsIfNecessary(
this.struct().atoms,
this.explicitSelected().atoms
this.explicitSelected().atoms,
);
if (stereoFlags.length !== 0) {
this._selection && this._selection.enhancedFlags
? (this._selection.enhancedFlags = Array.from(
new Set([...this._selection.enhancedFlags, ...stereoFlags])
new Set([...this._selection.enhancedFlags, ...stereoFlags]),
))
: (res.enhancedFlags = stereoFlags);
}
Expand Down Expand Up @@ -455,7 +459,7 @@ class Editor implements KetcherEditor {
update(
action: Action | true,
ignoreHistory?: boolean,
options = { resizeCanvas: true }
options = { resizeCanvas: true },
) {
setFunctionalGroupsTooltip({
editor: this,
Expand Down Expand Up @@ -616,7 +620,7 @@ class Editor implements KetcherEditor {
true,
null,
new Pile(selection.simpleObjects),
new Pile(selection.texts)
new Pile(selection.texts),
);

// Copy by its own as Struct.clone doesn't support
Expand Down Expand Up @@ -655,7 +659,7 @@ function resetSelectionOnCanvasClick(
editor: Editor,
eventName: string,
clientArea: HTMLElement,
event
event,
) {
if (
eventName === 'mouseup' &&
Expand Down Expand Up @@ -687,7 +691,7 @@ function useToolIfNeeded(
editor: Editor,
eventHandlerName: ToolEventHandlerName,
clientArea: HTMLElement,
event
event,
) {
const editorTool = editor.tool();
if (!editorTool) {
Expand Down Expand Up @@ -787,7 +791,7 @@ function domEventSetup(editor: Editor, clientArea: HTMLElement) {
editor,
toolEventHandler,
clientArea,
event
event,
);
if (isToolUsed) {
return true;
Expand All @@ -800,23 +804,6 @@ function domEventSetup(editor: Editor, clientArea: HTMLElement) {
});
}

function recoordinate(editor: Editor, rp?: Vec2 /* , vp */) {
// rp is a point in scaled coordinates, which will be positioned
// vp is the point where the reference point should now be (in view coordinates)
// or the center if not set
console.assert(rp, 'Reference point not specified');
if (rp) {
editor.render.setScrollOffset(rp.x, rp.y);
} else {
editor.render.setScrollOffset(0, 0);
}
}

function getStructCenter(ReStruct, selection?) {
const bb = ReStruct.getVBoxObj(selection || {});
return Vec2.lc2(bb.p0, 0.5, bb.p1, 0.5);
}

export { Editor };
export default Editor;

Expand Down
1 change: 1 addition & 0 deletions packages/ketcher-react/src/script/editor/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@

export * from './customOnChangeHandler';
export * from './elementOffset';
export * from './structLayout';
23 changes: 23 additions & 0 deletions packages/ketcher-react/src/script/editor/utils/structLayout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Editor, ReStruct, Vec2 } from 'ketcher-core';

export function getSelectionMap(structure: ReStruct) {
return Object.keys(ReStruct.maps).reduce((result, map) => {
result[map] = Array.from(structure[map].keys());
return result;
}, {});
}

export function getStructCenter(ReStruct, selection?) {
const bb = ReStruct.getVBoxObj(selection || {});
return Vec2.lc2(bb.p0, 0.5, bb.p1, 0.5);
}

export function recoordinate(editor: Editor, rp?: Vec2) {
// rp is a point in scaled coordinates, which will be positioned
console.assert(rp, 'Reference point not specified');
if (rp) {
editor.render.setScrollOffset(rp.x, rp.y);
} else {
editor.render.setScrollOffset(0, 0);
}
}

0 comments on commit 8f65ff7

Please sign in to comment.