Skip to content
Snippets Groups Projects
Commit 545d9434 authored by dsehnal's avatar dsehnal
Browse files

Add PluginContext.initContainer/canvas3dInitialized and their usage

parent bbc43d51
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,9 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased]
- Add `PluginContext.mount/unmount` methods; these should make it easier to reuse a plugin context with both custom and built-in UI
- Add `PluginContext.initContainer/mount/unmount` methods; these should make it easier to reuse a plugin context with both custom and built-in UI
- Add `PluginContext.canvas3dInitialized`
- `createPluginUI` now resolves after the 3d canvas has been initialized.
## [v3.22.0] - 2022-10-17
......
......@@ -58,7 +58,8 @@ class Viewer {
}
static async create(elementOrId: string | HTMLElement, colors = [Color(0x992211), Color(0xDDDDDD)], showButtons = true) {
const o = { ...DefaultViewerOptions, ...{
const o = {
...DefaultViewerOptions, ...{
layoutIsExpanded: false,
layoutShowControls: false,
layoutShowRemoteState: false,
......@@ -71,7 +72,8 @@ class Viewer {
viewportShowSettings: false,
viewportShowSelectionMode: false,
viewportShowAnimation: false,
} };
}
};
const defaultSpec = DefaultPluginUISpec();
const spec: PluginUISpec = {
......@@ -135,9 +137,8 @@ class Viewer {
}
};
plugin.behaviors.canvas3d.initialized.subscribe(v => {
if (v) {
PluginCommands.Canvas3D.SetSettings(plugin, { settings: {
PluginCommands.Canvas3D.SetSettings(plugin, {
settings: {
renderer: {
...plugin.canvas3d!.props.renderer,
backgroundColor: ColorNames.white,
......@@ -146,7 +147,6 @@ class Viewer {
...plugin.canvas3d!.props.camera,
helper: { axes: { name: 'off', params: {} } }
}
} });
}
});
......
......@@ -4,16 +4,16 @@
* @author David Sehnal <david.sehnal@gmail.com>
*/
import * as ReactDOM from 'react-dom';
import { createRoot } from 'react-dom/client';
import { AlphaOrbitalsExample } from '.';
import { ParameterControls } from '../../mol-plugin-ui/controls/parameters';
import { useBehavior } from '../../mol-plugin-ui/hooks/use-behavior';
import { PluginContextContainer } from '../../mol-plugin-ui/plugin';
export function mountControls(orbitals: AlphaOrbitalsExample, parent: Element) {
ReactDOM.render(<PluginContextContainer plugin={orbitals.plugin}>
createRoot(parent).render(<PluginContextContainer plugin={orbitals.plugin}>
<Controls orbitals={orbitals} />
</PluginContextContainer>, parent);
</PluginContextContainer>);
}
function Controls({ orbitals }: { orbitals: AlphaOrbitalsExample }) {
......
......@@ -82,9 +82,6 @@ export class AlphaOrbitalsExample {
this.plugin.managers.interactivity.setProps({ granularity: 'element' });
this.plugin.behaviors.canvas3d.initialized.subscribe(init => {
if (!init) return;
if (!canComputeGrid3dOnGPU(this.plugin.canvas3d?.webgl)) {
PluginCommands.Toast.Show(this.plugin, {
title: 'Error',
......@@ -99,7 +96,6 @@ export class AlphaOrbitalsExample {
});
mountControls(this, document.getElementById('controls')!);
});
}
readonly params = new BehaviorSubject<ParamDefinition.For<Params>>({} as any);
......
......@@ -18,5 +18,10 @@ export async function createPluginUI(target: HTMLElement, spec?: PluginUISpec, o
await options.onBeforeUIRender(ctx);
}
ReactDOM.render(React.createElement(Plugin, { plugin: ctx }), target);
try {
await ctx.canvas3dInitialized;
} catch {
// Error reported in UI/console elsewhere.
}
return ctx;
}
\ No newline at end of file
......@@ -18,5 +18,10 @@ export async function createPluginUI(target: HTMLElement, spec?: PluginUISpec, o
await options.onBeforeUIRender(ctx);
}
createRoot(target).render(createElement(Plugin, { plugin: ctx }));
try {
await ctx.canvas3dInitialized;
} catch {
// Error reported in UI/console elsewhere.
}
return ctx;
}
\ No newline at end of file
......@@ -35,7 +35,7 @@ import { Representation } from '../mol-repr/representation';
import { StructureRepresentationRegistry } from '../mol-repr/structure/registry';
import { VolumeRepresentationRegistry } from '../mol-repr/volume/registry';
import { StateTransform } from '../mol-state';
import { RuntimeContext, Task } from '../mol-task';
import { RuntimeContext, Scheduler, Task } from '../mol-task';
import { ColorTheme } from '../mol-theme/color';
import { SizeTheme } from '../mol-theme/size';
import { ThemeRegistryContext } from '../mol-theme/theme';
......@@ -71,6 +71,7 @@ export class PluginContext {
};
protected subs: Subscription[] = [];
private initCanvas3dPromiseCallbacks: [res: () => void, rej: (err: any) => void] = [() => {}, () => {}];
private disposed = false;
private canvasContainer: HTMLDivElement | undefined = void 0;
......@@ -103,10 +104,15 @@ export class PluginContext {
leftPanelTabName: this.ev.behavior<LeftPanelTabName>('root')
},
canvas3d: {
// TODO: remove in 4.0?
initialized: this.canvas3dInit.pipe(filter(v => !!v), take(1))
}
} as const;
readonly canvas3dInitialized = new Promise<void>((res, rej) => {
this.initCanvas3dPromiseCallbacks = [res, rej];
});
readonly canvas3dContext: Canvas3DContext | undefined;
readonly canvas3d: Canvas3D | undefined;
readonly layout = new PluginLayout(this);
......@@ -187,10 +193,9 @@ export class PluginContext {
*/
readonly customState: unknown = Object.create(null);
mount(target: HTMLElement, canvas3dContext?: Canvas3DContext) {
if (this.disposed) throw new Error('Cannot mount a disposed context');
initContainer(canvas3dContext?: Canvas3DContext) {
if (this.canvasContainer) return true;
if (!this.canvasContainer) {
const container = document.createElement('div');
Object.assign(container.style, {
position: 'absolute',
......@@ -218,13 +223,19 @@ export class PluginContext {
return false;
}
this.canvasContainer = container;
return true;
}
if (this.canvasContainer.parentElement !== target) {
this.canvasContainer.parentElement?.removeChild(this.canvasContainer);
mount(target: HTMLElement) {
if (this.disposed) throw new Error('Cannot mount a disposed context');
if (!this.initContainer()) return false;
if (this.canvasContainer!.parentElement !== target) {
this.canvasContainer!.parentElement?.removeChild(this.canvasContainer!);
}
target.appendChild(this.canvasContainer);
target.appendChild(this.canvasContainer!);
this.handleResize();
return true;
}
......@@ -279,10 +290,12 @@ export class PluginContext {
this.handleResize();
Scheduler.setImmediate(() => this.initCanvas3dPromiseCallbacks[0]());
return true;
} catch (e) {
this.log.error('' + e);
console.error(e);
Scheduler.setImmediate(() => this.initCanvas3dPromiseCallbacks[1](e));
return false;
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment