Skip to content

Commit

Permalink
#4878 - Replace selected monomer on canvas with monomer from library …
Browse files Browse the repository at this point in the history
…in sequence mode

- added ketcher-standalone builds for indigo without render module
- added structService reinitialization
  • Loading branch information
rrodionov91 committed Aug 3, 2024
1 parent 9a0f30c commit a2137b8
Show file tree
Hide file tree
Showing 19 changed files with 339 additions and 59 deletions.
4 changes: 4 additions & 0 deletions example/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ export default defineConfig({
find: 'web-worker:./indigoWorker',
replacement: './indigoWorker?worker',
},
{
find: '_indigo-ketcher-import-alias_',
replacement: 'indigo-ketcher',
},
],
},
customLogger: logger,
Expand Down
67 changes: 63 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 19 additions & 14 deletions packages/ketcher-core/src/application/ketcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ const allowedApiSettings = {

export class Ketcher {
logging: LogSettings;
#structService: StructService;
structService: StructService;
#formatterFactory: FormatterFactory;
#editor: Editor;
#indigo: Indigo;
_indigo: Indigo;
#eventBus: EventEmitter;

get editor(): Editor {
Expand All @@ -79,9 +79,9 @@ export class Ketcher {
assert(formatterFactory != null);

this.#editor = editor;
this.#structService = structService;
this.structService = structService;
this.#formatterFactory = formatterFactory;
this.#indigo = new Indigo(this.#structService);
this._indigo = new Indigo(this.structService);
this.#eventBus = new EventEmitter();
this.logging = {
enabled: false,
Expand All @@ -95,7 +95,7 @@ export class Ketcher {
}

get indigo() {
return this.#indigo;
return this._indigo;
}

// TEMP.: getting only dearomatize-on-load setting
Expand Down Expand Up @@ -300,7 +300,7 @@ export class Ketcher {
this.#editor.struct(),
);

return this.#structService.getInChIKey(struct);
return this.structService.getInChIKey(struct);
}

containsReaction(): boolean {
Expand Down Expand Up @@ -354,11 +354,11 @@ export class Ketcher {

if (window.isPolymerEditorTurnedOn) {
deleteAllEntitiesOnCanvas();
await parseAndAddMacromoleculesOnCanvas(structStr, this.#structService);
await parseAndAddMacromoleculesOnCanvas(structStr, this.structService);
} else {
const struct: Struct = await prepareStructToRender(
structStr,
this.#structService,
this.structService,
this,
);

Expand All @@ -375,7 +375,7 @@ export class Ketcher {
assert(typeof helmStr === 'string');
const struct: Struct = await prepareStructToRender(
helmStr,
this.#structService,
this.structService,
this,
);
struct.rescale();
Expand All @@ -393,11 +393,11 @@ export class Ketcher {
assert(typeof structStr === 'string');

if (window.isPolymerEditorTurnedOn) {
await parseAndAddMacromoleculesOnCanvas(structStr, this.#structService);
await parseAndAddMacromoleculesOnCanvas(structStr, this.structService);
} else {
const struct: Struct = await prepareStructToRender(
structStr,
this.#structService,
this.structService,
this,
);

Expand All @@ -413,7 +413,7 @@ export class Ketcher {
}

runAsyncAction<void>(async () => {
const struct = await this.#indigo.layout(this.#editor.struct());
const struct = await this._indigo.layout(this.#editor.struct());
const ketSerializer = new KetSerializer();
this.setMolecule(ketSerializer.serialize(struct));
}, this.eventBus);
Expand Down Expand Up @@ -458,7 +458,7 @@ export class Ketcher {
if (window.isPolymerEditorTurnedOn) {
throw new Error('Recognize is not available in macro mode');
}
return this.#indigo.recognize(image, { version });
return this._indigo.recognize(image, { version });
}

async generateImage(
Expand All @@ -481,7 +481,7 @@ export class Ketcher {
options.outputFormat = 'png';
}

const base64 = await this.#structService.generateImageAsBase64(
const base64 = await this.structService.generateImageAsBase64(
data,
options,
);
Expand All @@ -494,4 +494,9 @@ export class Ketcher {
const blob = new Blob([byteArray], { type: meta });
return blob;
}

public reinitializeIndigo(structService: StructService) {
this.structService = structService;
this._indigo = new Indigo(structService);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,5 @@ export interface StructService {
data: ExplicitHydrogensData,
options?: StructServiceOptions,
) => Promise<ExplicitHydrogensResult>;
destroy?: () => void;
}
34 changes: 25 additions & 9 deletions packages/ketcher-react/src/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ import init, { Config } from './script';
import { useEffect, useRef } from 'react';
import { createRoot, Root } from 'react-dom/client';

import { Ketcher } from 'ketcher-core';
import { Ketcher, StructService } from 'ketcher-core';
import classes from './Editor.module.less';
import clsx from 'clsx';
import { useResizeObserver } from './hooks';
import {
ketcherInitEventName,
KETCHER_ROOT_NODE_CLASS_NAME,
} from './constants';
import { KetcherBuilder } from './script/builders';

const mediaSizes = {
smallWidth: 1040,
Expand All @@ -47,13 +48,24 @@ function Editor(props: EditorProps) {
const initPromiseRef = useRef<ReturnType<typeof init> | null>(null);
const appRootRef = useRef<Root | null>(null);
const cleanupRef = useRef<(() => unknown) | null>(null);
const ketcherBuilderRef = useRef<KetcherBuilder | null>(null);
// eslint-disable-next-line @typescript-eslint/no-empty-function
const setServerRef = useRef<(structService: StructService) => void>(() => {});
const structServiceProvider = props.structServiceProvider;

const rootElRef = useRef<HTMLDivElement>(null);

const { height, width } = useResizeObserver<HTMLDivElement>({
ref: rootElRef,
});

useEffect(() => {
ketcherBuilderRef.current?.reinitializeApi(
props.structServiceProvider,
setServerRef.current,
);
}, [structServiceProvider]);

const initKetcher = () => {
appRootRef.current = createRoot(rootElRef.current as HTMLDivElement);

Expand All @@ -63,15 +75,19 @@ function Editor(props: EditorProps) {
appRoot: appRootRef.current,
});

initPromiseRef.current?.then(({ ketcher, ketcherId, cleanup }) => {
cleanupRef.current = cleanup;
initPromiseRef.current?.then(
({ ketcher, ketcherId, cleanup, builder, setServer }) => {
cleanupRef.current = cleanup;
ketcherBuilderRef.current = builder;
setServerRef.current = setServer;

if (typeof props.onInit === 'function' && ketcher) {
props.onInit(ketcher);
const ketcherInitEvent = new Event(ketcherInitEventName(ketcherId));
window.dispatchEvent(ketcherInitEvent);
}
});
if (typeof props.onInit === 'function' && ketcher) {
props.onInit(ketcher);
const ketcherInitEvent = new Event(ketcherInitEventName(ketcherId));
window.dispatchEvent(ketcherInitEvent);
}
},
);
};
useEffect(() => {
if (initPromiseRef.current === null) {
Expand Down
3 changes: 3 additions & 0 deletions packages/ketcher-react/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ export const KETCHER_ROOT_NODE_CSS_SELECTOR = `.${KETCHER_ROOT_NODE_CLASS_NAME}`

export const EditorClassName = 'Ketcher-polymer-editor-root';
export const KETCHER_MACROMOLECULES_ROOT_NODE_SELECTOR = `.${EditorClassName}`;
export const STRUCT_SERVICE_NO_RENDER_INITIALIZED_EVENT =
'struct-service-no-render-initialized';
export const STRUCT_SERVICE_INITIALIZED_EVENT = 'struct-service-initialized';
1 change: 1 addition & 0 deletions packages/ketcher-react/src/script/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function createApi(
getInChIKey: structService.getInChIKey.bind(structService),
toggleExplicitHydrogens:
structService.toggleExplicitHydrogens.bind(structService),
destroy: structService.destroy?.bind(structService),
});
}

Expand Down
Loading

0 comments on commit a2137b8

Please sign in to comment.