From 564a360c8ff4c4b53e18f47ffbb9df1bfdb8b3d7 Mon Sep 17 00:00:00 2001 From: dsehnal <david.sehnal@gmail.com> Date: Sun, 19 Dec 2021 17:32:58 +0100 Subject: [PATCH] Added createPluginUI, removed createPlugin and createPluginAsync --- CHANGELOG.md | 4 ++ src/apps/docking-viewer/index.html | 12 ++--- src/apps/docking-viewer/index.ts | 21 +++++---- src/apps/viewer/embedded.html | 10 ++-- src/apps/viewer/index.html | 45 +++++++++--------- src/apps/viewer/index.ts | 18 ++++--- src/examples/alpha-orbitals/index.ts | 6 +-- src/examples/basic-wrapper/index.html | 5 +- src/examples/basic-wrapper/index.ts | 8 ++-- src/examples/lighting/index.html | 5 +- src/examples/lighting/index.ts | 52 +++++++++++---------- src/examples/proteopedia-wrapper/index.html | 7 +-- src/examples/proteopedia-wrapper/index.ts | 18 +++---- src/mol-plugin-ui/index.ts | 14 ++---- 14 files changed, 119 insertions(+), 106 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4fa1d6be..df9e74a1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,10 @@ Note that since we don't clearly distinguish between a public and private interf - pLDDT & qmean score: coloring, repr presets, molql symbol, loci labels (including avg for mutli-residue selections) - pLDDT: selection query - Warn about erroneous symmetry operator matrix (instead of throwing an error) +- Added ``createPluginUI`` to ``mol-plugin-ui`` + - Support ``onBeforeUIRender`` to make sure initial UI works with custom presets and similar features. +- [Breaking] Removed ``createPlugin`` and ``createPluginAsync`` from ``mol-plugin-ui`` + - Please use ``createPluginUI`` instead ## [v3.0.0-dev.5] - 2021-12-16 diff --git a/src/apps/docking-viewer/index.html b/src/apps/docking-viewer/index.html index 2c0d15679..a1d4a39c0 100644 --- a/src/apps/docking-viewer/index.html +++ b/src/apps/docking-viewer/index.html @@ -19,8 +19,6 @@ <div id="app"></div> <script type="text/javascript" src="./molstar.js"></script> <script type="text/javascript"> - var viewer = new DockingViewer('app', [0x33DD22, 0x1133EE], true); - function getParam(name, regex) { var r = new RegExp(name + '=' + '(' + regex + ')[&]?', 'i'); return decodeURIComponent(((window.location.search || '').match(r) || [])[1] || ''); @@ -28,10 +26,12 @@ var pdbqt = getParam('pdbqt', '[^&]+').trim(); var mol2 = getParam('mol2', '[^&]+').trim(); - viewer.loadStructuresFromUrlsAndMerge([ - { url: pdbqt, format: 'pdbqt' }, - { url: mol2, format: 'mol2' } - ]); + DockingViewer.create('app', [0x33DD22, 0x1133EE], true).then(viewer => { + viewer.loadStructuresFromUrlsAndMerge([ + { url: pdbqt, format: 'pdbqt' }, + { url: mol2, format: 'mol2' } + ]); + }); </script> </body> </html> \ No newline at end of file diff --git a/src/apps/docking-viewer/index.ts b/src/apps/docking-viewer/index.ts index 10574f79c..82e974586 100644 --- a/src/apps/docking-viewer/index.ts +++ b/src/apps/docking-viewer/index.ts @@ -8,7 +8,7 @@ import { Structure } from '../../mol-model/structure'; import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory'; import { PluginStateObject as PSO, PluginStateTransform } from '../../mol-plugin-state/objects'; -import { createPlugin } from '../../mol-plugin-ui'; +import { createPluginUI } from '../../mol-plugin-ui'; import { PluginUIContext } from '../../mol-plugin-ui/context'; import { PluginLayoutControlsDisplay } from '../../mol-plugin/layout'; import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec'; @@ -54,9 +54,10 @@ const DefaultViewerOptions = { }; class Viewer { - plugin: PluginUIContext; + constructor(public plugin: PluginUIContext) { + } - constructor(elementOrId: string | HTMLElement, colors = [Color(0x992211), Color(0xDDDDDD)], showButtons = true) { + static async create(elementOrId: string | HTMLElement, colors = [Color(0x992211), Color(0xDDDDDD)], showButtons = true) { const o = { ...DefaultViewerOptions, ...{ layoutIsExpanded: false, layoutShowControls: false, @@ -125,29 +126,31 @@ class Viewer { ? document.getElementById(elementOrId) : elementOrId; if (!element) throw new Error(`Could not get element with id '${elementOrId}'`); - this.plugin = createPlugin(element, spec); + const plugin = await createPluginUI(element, spec); - (this.plugin.customState as any) = { + (plugin.customState as any) = { colorPalette: { name: 'colors', params: { list: { colors } } } }; - this.plugin.behaviors.canvas3d.initialized.subscribe(v => { + plugin.behaviors.canvas3d.initialized.subscribe(v => { if (v) { - PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: { + PluginCommands.Canvas3D.SetSettings(plugin, { settings: { renderer: { - ...this.plugin.canvas3d!.props.renderer, + ...plugin.canvas3d!.props.renderer, backgroundColor: ColorNames.white, }, camera: { - ...this.plugin.canvas3d!.props.camera, + ...plugin.canvas3d!.props.camera, helper: { axes: { name: 'off', params: {} } } } } }); } }); + + return new Viewer(plugin); } async loadStructuresFromUrlsAndMerge(sources: { url: string, format: BuiltInTrajectoryFormat, isBinary?: boolean }[]) { diff --git a/src/apps/viewer/embedded.html b/src/apps/viewer/embedded.html index 8d1473999..adb9ecd04 100644 --- a/src/apps/viewer/embedded.html +++ b/src/apps/viewer/embedded.html @@ -20,7 +20,7 @@ <div id="app"></div> <script type="text/javascript" src="./molstar.js"></script> <script type="text/javascript"> - var viewer = new molstar.Viewer('app', { + molstar.Viewer.create('app', { layoutIsExpanded: true, layoutShowControls: false, layoutShowRemoteState: false, @@ -34,11 +34,11 @@ pdbProvider: 'rcsb', emdbProvider: 'rcsb', + }).then(() => { + viewer.loadPdb('7bv2'); + viewer.loadEmdb('EMD-30210', { detail: 6 }); + // viewer.loadAllModelsOrAssemblyFromUrl('https://cs.litemol.org/5ire/full', 'mmcif', false, { representationParams: { theme: { globalName: 'operator-name' } } }) }); - viewer.loadPdb('7bv2'); - viewer.loadEmdb('EMD-30210', { detail: 6 }); - - // viewer.loadAllModelsOrAssemblyFromUrl('https://cs.litemol.org/5ire/full', 'mmcif', false, { representationParams: { theme: { globalName: 'operator-name' } } }) </script> </body> </html> \ No newline at end of file diff --git a/src/apps/viewer/index.html b/src/apps/viewer/index.html index a29689b28..21c287ff5 100644 --- a/src/apps/viewer/index.html +++ b/src/apps/viewer/index.html @@ -56,7 +56,8 @@ var pixelScale = getParam('pixel-scale', '[^&]+').trim(); var pickScale = getParam('pick-scale', '[^&]+').trim(); var pickPadding = getParam('pick-padding', '[^&]+').trim(); - var viewer = new molstar.Viewer('app', { + + molstar.Viewer.create('app', { layoutShowControls: !hideControls, viewportShowExpand: false, collapseLeftPanel: collapseLeftPanel, @@ -68,34 +69,34 @@ pixelScale: parseFloat(pixelScale) || 1, pickScale: parseFloat(pickScale) || 0.25, pickPadding: isNaN(parseFloat(pickPadding)) ? 1 : parseFloat(pickPadding), - }); + }).then(viewer => { + var snapshotId = getParam('snapshot-id', '[^&]+').trim(); + if (snapshotId) viewer.setRemoteSnapshot(snapshotId); - var snapshotId = getParam('snapshot-id', '[^&]+').trim(); - if (snapshotId) viewer.setRemoteSnapshot(snapshotId); + var snapshotUrl = getParam('snapshot-url', '[^&]+').trim(); + var snapshotUrlType = getParam('snapshot-url-type', '[^&]+').toLowerCase().trim() || 'molj'; + if (snapshotUrl && snapshotUrlType) viewer.loadSnapshotFromUrl(snapshotUrl, snapshotUrlType); - var snapshotUrl = getParam('snapshot-url', '[^&]+').trim(); - var snapshotUrlType = getParam('snapshot-url-type', '[^&]+').toLowerCase().trim() || 'molj'; - if (snapshotUrl && snapshotUrlType) viewer.loadSnapshotFromUrl(snapshotUrl, snapshotUrlType); + var structureUrl = getParam('structure-url', '[^&]+').trim(); + var structureUrlFormat = getParam('structure-url-format', '[a-z]+').toLowerCase().trim(); + var structureUrlIsBinary = getParam('structure-url-is-binary', '[^&]+').trim() === '1'; + if (structureUrl) viewer.loadStructureFromUrl(structureUrl, structureUrlFormat, structureUrlIsBinary); - var structureUrl = getParam('structure-url', '[^&]+').trim(); - var structureUrlFormat = getParam('structure-url-format', '[a-z]+').toLowerCase().trim(); - var structureUrlIsBinary = getParam('structure-url-is-binary', '[^&]+').trim() === '1'; - if (structureUrl) viewer.loadStructureFromUrl(structureUrl, structureUrlFormat, structureUrlIsBinary); + var pdb = getParam('pdb', '[^&]+').trim(); + if (pdb) viewer.loadPdb(pdb); - var pdb = getParam('pdb', '[^&]+').trim(); - if (pdb) viewer.loadPdb(pdb); + var pdbDev = getParam('pdb-dev', '[^&]+').trim(); + if (pdbDev) viewer.loadPdbDev(pdbDev); - var pdbDev = getParam('pdb-dev', '[^&]+').trim(); - if (pdbDev) viewer.loadPdbDev(pdbDev); + var emdb = getParam('emdb', '[^&]+').trim(); + if (emdb) viewer.loadEmdb(emdb); - var emdb = getParam('emdb', '[^&]+').trim(); - if (emdb) viewer.loadEmdb(emdb); + var afdb = getParam('afdb', '[^&]+').trim(); + if (afdb) viewer.loadAlphaFoldDb(afdb); - var afdb = getParam('afdb', '[^&]+').trim(); - if (afdb) viewer.loadAlphaFoldDb(afdb); - - var modelArchive = getParam('model-archive', '[^&]+').trim(); - if (modelArchive) viewer.loadModelArchive(modelArchive); + var modelArchive = getParam('model-archive', '[^&]+').trim(); + if (modelArchive) viewer.loadModelArchive(modelArchive); + }); </script> <!-- __MOLSTAR_ANALYTICS__ --> </body> diff --git a/src/apps/viewer/index.ts b/src/apps/viewer/index.ts index 0ec98c510..9a10546d3 100644 --- a/src/apps/viewer/index.ts +++ b/src/apps/viewer/index.ts @@ -28,7 +28,7 @@ import { createVolumeRepresentationParams } from '../../mol-plugin-state/helpers import { PluginStateObject } from '../../mol-plugin-state/objects'; import { StateTransforms } from '../../mol-plugin-state/transforms'; import { TrajectoryFromModelAndCoordinates } from '../../mol-plugin-state/transforms/model'; -import { createPlugin } from '../../mol-plugin-ui'; +import { createPluginUI } from '../../mol-plugin-ui'; import { PluginUIContext } from '../../mol-plugin-ui/context'; import { DefaultPluginUISpec, PluginUISpec } from '../../mol-plugin-ui/spec'; import { PluginCommands } from '../../mol-plugin/commands'; @@ -99,9 +99,10 @@ const DefaultViewerOptions = { type ViewerOptions = typeof DefaultViewerOptions; export class Viewer { - plugin: PluginUIContext; + constructor(public plugin: PluginUIContext) { + } - constructor(elementOrId: string | HTMLElement, options: Partial<ViewerOptions> = {}) { + static async create(elementOrId: string | HTMLElement, options: Partial<ViewerOptions> = {}) { const o = { ...DefaultViewerOptions, ...options }; const defaultSpec = DefaultPluginUISpec(); @@ -162,9 +163,14 @@ export class Viewer { ? document.getElementById(elementOrId) : elementOrId; if (!element) throw new Error(`Could not get element with id '${elementOrId}'`); - this.plugin = createPlugin(element, spec); - - this.plugin.builders.structure.representation.registerPreset(ViewerAutoPreset); + const plugin = await createPluginUI(element, spec, { + onBeforeUIRender: plugin => { + // the preset needs to be added before the UI renders otherwise + // "Download Structure" wont be able to pick it up + plugin.builders.structure.representation.registerPreset(ViewerAutoPreset); + } + }); + return new Viewer(plugin); } setRemoteSnapshot(id: string) { diff --git a/src/examples/alpha-orbitals/index.ts b/src/examples/alpha-orbitals/index.ts index 231c54cbf..4ce65c3ae 100644 --- a/src/examples/alpha-orbitals/index.ts +++ b/src/examples/alpha-orbitals/index.ts @@ -11,7 +11,7 @@ import { SphericalBasisOrder } from '../../extensions/alpha-orbitals/spherical-f import { BasisAndOrbitals, CreateOrbitalDensityVolume, CreateOrbitalRepresentation3D, CreateOrbitalVolume, StaticBasisAndOrbitals } from '../../extensions/alpha-orbitals/transforms'; import { canComputeGrid3dOnGPU } from '../../mol-gl/compute/grid3d'; import { PluginStateObject } from '../../mol-plugin-state/objects'; -import { createPluginAsync } from '../../mol-plugin-ui'; +import { createPluginUI } from '../../mol-plugin-ui'; import { PluginUIContext } from '../../mol-plugin-ui/context'; import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec'; import { PluginCommands } from '../../mol-plugin/commands'; @@ -54,7 +54,7 @@ export class AlphaOrbitalsExample { async init(target: string | HTMLElement) { const defaultSpec = DefaultPluginUISpec(); - this.plugin = await createPluginAsync(typeof target === 'string' ? document.getElementById(target)! : target, { + this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, { ...defaultSpec, layout: { initial: { @@ -67,7 +67,7 @@ export class AlphaOrbitalsExample { }, canvas3d: { camera: { - helper: { axes: { name: 'off', params: { } } } + helper: { axes: { name: 'off', params: {} } } } }, config: [ diff --git a/src/examples/basic-wrapper/index.html b/src/examples/basic-wrapper/index.html index 2de1b6872..bea89d545 100644 --- a/src/examples/basic-wrapper/index.html +++ b/src/examples/basic-wrapper/index.html @@ -69,8 +69,9 @@ $('format').value = format; $('format').onchange = function (e) { format = e.target.value; } - BasicMolStarWrapper.init('app' /** or document.getElementById('app') */); - BasicMolStarWrapper.setBackground(0xffffff); + BasicMolStarWrapper.init('app' /** or document.getElementById('app') */).then(() => { + BasicMolStarWrapper.setBackground(0xffffff); + }); addControl('Load Asym Unit', () => BasicMolStarWrapper.load({ url: url, format: format })); addControl('Load Assembly', () => BasicMolStarWrapper.load({ url: url, format: format, assemblyId: assemblyId })); diff --git a/src/examples/basic-wrapper/index.ts b/src/examples/basic-wrapper/index.ts index 3ad7cb47f..0dfdd2709 100644 --- a/src/examples/basic-wrapper/index.ts +++ b/src/examples/basic-wrapper/index.ts @@ -9,7 +9,7 @@ import { EmptyLoci } from '../../mol-model/loci'; import { StructureSelection } from '../../mol-model/structure'; import { AnimateModelIndex } from '../../mol-plugin-state/animation/built-in/model-index'; import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory'; -import { createPlugin } from '../../mol-plugin-ui'; +import { createPluginUI } from '../../mol-plugin-ui'; import { PluginUIContext } from '../../mol-plugin-ui/context'; import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec'; import { PluginCommands } from '../../mol-plugin/commands'; @@ -28,8 +28,8 @@ type LoadParams = { url: string, format?: BuiltInTrajectoryFormat, isBinary?: bo class BasicWrapper { plugin: PluginUIContext; - init(target: string | HTMLElement) { - this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, { + async init(target: string | HTMLElement) { + this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, { ...DefaultPluginUISpec(), layout: { initial: { @@ -60,7 +60,7 @@ class BasicWrapper { params: { id: assemblyId } } : { name: 'model', - params: { } + params: {} }, showUnitcell: false, representationPreset: 'auto' diff --git a/src/examples/lighting/index.html b/src/examples/lighting/index.html index fc1cd43bf..2be99e14e 100644 --- a/src/examples/lighting/index.html +++ b/src/examples/lighting/index.html @@ -45,8 +45,9 @@ <div id='controls'></div> <div id="app"></div> <script> - LightingDemo.init('app') - LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3) + LightingDemo.init('app').then(() => { + LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3); + }); addHeader('Example PDB IDs'); addControl('4KTC', () => LightingDemo.load({ url: 'https://models.rcsb.org/4KTC.bcif', assemblyId: '1' }, 5, 1.3)); diff --git a/src/examples/lighting/index.ts b/src/examples/lighting/index.ts index 9537ba667..e77535882 100644 --- a/src/examples/lighting/index.ts +++ b/src/examples/lighting/index.ts @@ -6,7 +6,7 @@ import { Canvas3DProps } from '../../mol-canvas3d/canvas3d'; import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajectory'; -import { createPlugin } from '../../mol-plugin-ui'; +import { createPluginUI } from '../../mol-plugin-ui'; import { PluginUIContext } from '../../mol-plugin-ui/context'; import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec'; import { PluginCommands } from '../../mol-plugin/commands'; @@ -21,7 +21,7 @@ type _Preset = Pick<Canvas3DProps, 'multiSample' | 'postprocessing' | 'renderer' type Preset = { [K in keyof _Preset]: Partial<_Preset[K]> } const Canvas3DPresets = { - illustrative: <Preset> { + illustrative: <Preset>{ multiSample: { mode: 'temporal' as Canvas3DProps['multiSample']['mode'] }, @@ -33,25 +33,25 @@ const Canvas3DPresets = { style: { name: 'flat', params: {} } } }, - occlusion: <Preset> { + occlusion: <Preset>{ multiSample: { mode: 'temporal' as Canvas3DProps['multiSample']['mode'] }, postprocessing: { occlusion: { name: 'on', params: { samples: 32, radius: 6, bias: 1.4, blurKernelSize: 15 } }, - outline: { name: 'off', params: { } } + outline: { name: 'off', params: {} } }, renderer: { style: { name: 'matte', params: {} } } }, - standard: <Preset> { + standard: <Preset>{ multiSample: { mode: 'off' as Canvas3DProps['multiSample']['mode'] }, postprocessing: { - occlusion: { name: 'off', params: { } }, - outline: { name: 'off', params: { } } + occlusion: { name: 'off', params: {} }, + outline: { name: 'off', params: {} } }, renderer: { style: { name: 'matte', params: {} } @@ -69,8 +69,8 @@ class LightingDemo { private bias = 1.1; private preset: Canvas3DPreset = 'illustrative'; - init(target: string | HTMLElement) { - this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, { + async init(target: string | HTMLElement) { + this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, { ...DefaultPluginUISpec(), layout: { initial: { @@ -92,21 +92,23 @@ class LightingDemo { props.postprocessing.occlusion.params.radius = this.radius; props.postprocessing.occlusion.params.bias = this.bias; } - PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: { - ...props, - multiSample: { - ...this.plugin.canvas3d!.props.multiSample, - ...props.multiSample - }, - renderer: { - ...this.plugin.canvas3d!.props.renderer, - ...props.renderer - }, - postprocessing: { - ...this.plugin.canvas3d!.props.postprocessing, - ...props.postprocessing - }, - } }); + PluginCommands.Canvas3D.SetSettings(this.plugin, { + settings: { + ...props, + multiSample: { + ...this.plugin.canvas3d!.props.multiSample, + ...props.multiSample + }, + renderer: { + ...this.plugin.canvas3d!.props.renderer, + ...props.renderer + }, + postprocessing: { + ...this.plugin.canvas3d!.props.postprocessing, + ...props.postprocessing + }, + } + }); } async load({ url, format = 'mmcif', isBinary = true, assemblyId = '' }: LoadParams, radius: number, bias: number) { @@ -115,7 +117,7 @@ class LightingDemo { const data = await this.plugin.builders.data.download({ url: Asset.Url(url), isBinary }, { state: { isGhost: true } }); const trajectory = await this.plugin.builders.structure.parseTrajectory(data, format); const model = await this.plugin.builders.structure.createModel(trajectory); - const structure = await this.plugin.builders.structure.createStructure(model, assemblyId ? { name: 'assembly', params: { id: assemblyId } } : { name: 'model', params: { } }); + const structure = await this.plugin.builders.structure.createStructure(model, assemblyId ? { name: 'assembly', params: { id: assemblyId } } : { name: 'model', params: {} }); const polymer = await this.plugin.builders.structure.tryCreateComponentStatic(structure, 'polymer'); if (polymer) await this.plugin.builders.structure.representation.addRepresentation(polymer, { type: 'spacefill', color: 'illustrative' }); diff --git a/src/examples/proteopedia-wrapper/index.html b/src/examples/proteopedia-wrapper/index.html index 460ea81ef..343215bb4 100644 --- a/src/examples/proteopedia-wrapper/index.html +++ b/src/examples/proteopedia-wrapper/index.html @@ -103,10 +103,11 @@ PluginWrapper.init('app' /** or document.getElementById('app') */, { customColorList: CustomColors + }).then(() => { + PluginWrapper.setBackground(0xffffff); + loadAndSnapshot({ url: url, format: format, isBinary: isBinary, assemblyId: assemblyId, representationStyle: representationStyle }); + PluginWrapper.toggleSpin(); }); - PluginWrapper.setBackground(0xffffff); - loadAndSnapshot({ url: url, format: format, isBinary: isBinary, assemblyId: assemblyId, representationStyle: representationStyle }); - PluginWrapper.toggleSpin(); PluginWrapper.events.modelInfo.subscribe(function (info) { console.log('Model Info', info); diff --git a/src/examples/proteopedia-wrapper/index.ts b/src/examples/proteopedia-wrapper/index.ts index d43041180..f159588eb 100644 --- a/src/examples/proteopedia-wrapper/index.ts +++ b/src/examples/proteopedia-wrapper/index.ts @@ -10,7 +10,7 @@ import { AnimateModelIndex } from '../../mol-plugin-state/animation/built-in/mod import { createStructureRepresentationParams } from '../../mol-plugin-state/helpers/structure-representation-params'; import { PluginStateObject, PluginStateObject as PSO } from '../../mol-plugin-state/objects'; import { StateTransforms } from '../../mol-plugin-state/transforms'; -import { createPlugin } from '../../mol-plugin-ui'; +import { createPluginUI } from '../../mol-plugin-ui'; import { PluginUIContext } from '../../mol-plugin-ui/context'; import { DefaultPluginUISpec } from '../../mol-plugin-ui/spec'; import { CreateVolumeStreamingInfo, InitVolumeStreaming } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers'; @@ -43,10 +43,10 @@ class MolStarProteopediaWrapper { plugin: PluginUIContext; - init(target: string | HTMLElement, options?: { + async init(target: string | HTMLElement, options?: { customColorList?: number[] }) { - this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, { + this.plugin = await createPluginUI(typeof target === 'string' ? document.getElementById(target)! : target, { ...DefaultPluginUISpec(), animations: [ AnimateModelIndex @@ -95,7 +95,7 @@ class MolStarProteopediaWrapper { params: { id: assemblyId } } : { name: 'model' as const, - params: { } + params: {} } }; @@ -113,7 +113,7 @@ class MolStarProteopediaWrapper { const structure = this.getObj<PluginStateObject.Molecule.Structure>(StateElements.Assembly); if (!structure) return; - const style = _style || { }; + const style = _style || {}; const update = this.state.build(); @@ -229,7 +229,7 @@ class MolStarProteopediaWrapper { params: { id: asmId } } : { name: 'model' as const, - params: { } + params: {} } }; tree.to(StateElements.Assembly).update(StateTransforms.Model.StructureFromModel, p => ({ ...p, ...props })); @@ -269,7 +269,7 @@ class MolStarProteopediaWrapper { camera = { toggleSpin: () => this.toggleSpin(), - resetPosition: () => PluginCommands.Camera.Reset(this.plugin, { }) + resetPosition: () => PluginCommands.Camera.Reset(this.plugin, {}) }; private animateModelIndexTargetFps() { @@ -336,11 +336,11 @@ class MolStarProteopediaWrapper { reset: () => { const update = this.state.build().delete(StateElements.HetGroupFocusGroup); PluginCommands.State.Update(this.plugin, { state: this.state, tree: update }); - PluginCommands.Camera.Reset(this.plugin, { }); + PluginCommands.Camera.Reset(this.plugin, {}); }, focusFirst: async (compId: string, options?: { hideLabels: boolean, doNotLabelWaters: boolean }) => { if (!this.state.transforms.has(StateElements.Assembly)) return; - await PluginCommands.Camera.Reset(this.plugin, { }); + await PluginCommands.Camera.Reset(this.plugin, {}); const update = this.state.build(); diff --git a/src/mol-plugin-ui/index.ts b/src/mol-plugin-ui/index.ts index d7c62cc94..f890d9f8e 100644 --- a/src/mol-plugin-ui/index.ts +++ b/src/mol-plugin-ui/index.ts @@ -11,18 +11,12 @@ import { Plugin } from './plugin'; import { PluginUIContext } from './context'; import { DefaultPluginUISpec, PluginUISpec } from './spec'; -export function createPlugin(target: HTMLElement, spec?: PluginUISpec): PluginUIContext { - const ctx = new PluginUIContext(spec || DefaultPluginUISpec()); - ctx.init().then(() => { - ReactDOM.render(React.createElement(Plugin, { plugin: ctx }), target); - }); - return ctx; -} - -/** Returns the instance of the plugin after all behaviors have been initialized */ -export async function createPluginAsync(target: HTMLElement, spec?: PluginUISpec) { +export async function createPluginUI(target: HTMLElement, spec?: PluginUISpec, options?: { onBeforeUIRender?: (ctx: PluginUIContext) => (Promise<void> | void) }) { const ctx = new PluginUIContext(spec || DefaultPluginUISpec()); await ctx.init(); + if (options?.onBeforeUIRender) { + await options?.onBeforeUIRender(ctx); + } ReactDOM.render(React.createElement(Plugin, { plugin: ctx }), target); return ctx; } \ No newline at end of file -- GitLab