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

Add PluginContext.mount/unmount

parent a6709acf
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,8 @@ Note that since we don't clearly distinguish between a public and private interf ...@@ -6,6 +6,8 @@ Note that since we don't clearly distinguish between a public and private interf
## [Unreleased] ## [Unreleased]
- Add `PluginContext.mount/unmount` methods; these should make it easier to reuse a plugin context with both custom and built-in UI
## [v3.22.0] - 2022-10-17 ## [v3.22.0] - 2022-10-17
- Replace `VolumeIsosurfaceParams.pickingGranularity` param with `Volume.PickingGranuality` - Replace `VolumeIsosurfaceParams.pickingGranularity` param with `Volume.PickingGranuality`
......
/** /**
* Copyright (c) 2020-2021 mol* contributors, licensed under MIT, See LICENSE file for more info. * Copyright (c) 2020-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
* *
* @author David Sehnal <david.sehnal@gmail.com> * @author David Sehnal <david.sehnal@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
...@@ -19,13 +19,14 @@ export interface ViewportCanvasParams { ...@@ -19,13 +19,14 @@ export interface ViewportCanvasParams {
parentClassName?: string, parentClassName?: string,
parentStyle?: React.CSSProperties, parentStyle?: React.CSSProperties,
// NOTE: hostClassName/hostStyle no longer in use
// TODO: remove in 4.0
hostClassName?: string, hostClassName?: string,
hostStyle?: React.CSSProperties, hostStyle?: React.CSSProperties,
} }
export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, ViewportCanvasState> { export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, ViewportCanvasState> {
private container = React.createRef<HTMLDivElement>(); private container = React.createRef<HTMLDivElement>();
private canvas = React.createRef<HTMLCanvasElement>();
state: ViewportCanvasState = { state: ViewportCanvasState = {
noWebGl: false, noWebGl: false,
...@@ -37,7 +38,7 @@ export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, View ...@@ -37,7 +38,7 @@ export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, View
}; };
componentDidMount() { componentDidMount() {
if (!this.canvas.current || !this.container.current || !this.plugin.initViewer(this.canvas.current!, this.container.current!)) { if (!this.container.current || !this.plugin.mount(this.container.current!)) {
this.setState({ noWebGl: true }); this.setState({ noWebGl: true });
return; return;
} }
...@@ -47,7 +48,7 @@ export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, View ...@@ -47,7 +48,7 @@ export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, View
componentWillUnmount() { componentWillUnmount() {
super.componentWillUnmount(); super.componentWillUnmount();
// TODO viewer cleanup this.plugin.unmount();
} }
renderMissing() { renderMissing() {
...@@ -70,10 +71,7 @@ export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, View ...@@ -70,10 +71,7 @@ export class ViewportCanvas extends PluginUIComponent<ViewportCanvasParams, View
const Logo = this.props.logo; const Logo = this.props.logo;
return <div className={this.props.parentClassName || 'msp-viewport'} style={this.props.parentStyle}> return <div className={this.props.parentClassName || 'msp-viewport'} style={this.props.parentStyle} ref={this.container}>
<div className={this.props.hostClassName || 'msp-viewport-host3d'} style={this.props.hostStyle} ref={this.container}>
<canvas ref={this.canvas} />
</div>
{(this.state.showLogo && Logo) && <Logo />} {(this.state.showLogo && Logo) && <Logo />}
</div>; </div>;
} }
......
...@@ -73,6 +73,7 @@ export class PluginContext { ...@@ -73,6 +73,7 @@ export class PluginContext {
protected subs: Subscription[] = []; protected subs: Subscription[] = [];
private disposed = false; private disposed = false;
private canvasContainer: HTMLDivElement | undefined = void 0;
private ev = RxEventHelper.create(); private ev = RxEventHelper.create();
readonly config = new PluginConfigManager(this.spec.config); // needed to init state readonly config = new PluginConfigManager(this.spec.config); // needed to init state
...@@ -186,6 +187,52 @@ export class PluginContext { ...@@ -186,6 +187,52 @@ export class PluginContext {
*/ */
readonly customState: unknown = Object.create(null); readonly customState: unknown = Object.create(null);
mount(target: HTMLElement, canvas3dContext?: Canvas3DContext) {
if (this.disposed) throw new Error('Cannot mount a disposed context');
if (!this.canvasContainer) {
const container = document.createElement('div');
Object.assign(container.style, {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0,
'-webkit-user-select': 'none',
'user-select': 'none',
'-webkit-tap-highlight-color': 'rgba(0,0,0,0)',
'-webkit-touch-callout': 'none',
'touch-action': 'manipulation',
});
let canvas = canvas3dContext?.canvas;
if (!canvas) {
canvas = document.createElement('canvas');
Object.assign(canvas.style, {
'background-image': 'linear-gradient(45deg, lightgrey 25%, transparent 25%, transparent 75%, lightgrey 75%, lightgrey), linear-gradient(45deg, lightgrey 25%, transparent 25%, transparent 75%, lightgrey 75%, lightgrey)',
'background-size': '60px 60px',
'background-position': '0 0, 30px 30px'
});
container.appendChild(canvas);
}
if (!this.initViewer(canvas, container, canvas3dContext)) {
return false;
}
this.canvasContainer = container;
}
if (this.canvasContainer.parentElement !== target) {
this.canvasContainer.parentElement?.removeChild(this.canvasContainer);
}
target.appendChild(this.canvasContainer);
this.handleResize();
return true;
}
unmount() {
this.canvasContainer?.parentElement?.removeChild(this.canvasContainer);
}
initViewer(canvas: HTMLCanvasElement, container: HTMLDivElement, canvas3dContext?: Canvas3DContext) { initViewer(canvas: HTMLCanvasElement, container: HTMLDivElement, canvas3dContext?: Canvas3DContext) {
try { try {
this.layout.setRoot(container); this.layout.setRoot(container);
...@@ -306,6 +353,9 @@ export class PluginContext { ...@@ -306,6 +353,9 @@ export class PluginContext {
objectForEach(this.managers, m => (m as any)?.dispose?.()); objectForEach(this.managers, m => (m as any)?.dispose?.());
objectForEach(this.managers.structure, m => (m as any)?.dispose?.()); objectForEach(this.managers.structure, m => (m as any)?.dispose?.());
this.unmount();
this.canvasContainer = undefined;
this.disposed = true; this.disposed = true;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment