diff --git a/src/apps/basic-wrapper/index.ts b/src/apps/basic-wrapper/index.ts index f030ff31181b3c406ea3aaf2c77337d0fb23af0c..eda1d52beaadca16798fcec89eee0d30e47ed5c7 100644 --- a/src/apps/basic-wrapper/index.ts +++ b/src/apps/basic-wrapper/index.ts @@ -26,9 +26,11 @@ class BasicWrapper { init(target: string | HTMLElement) { this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, { ...DefaultPluginSpec, - initialLayout: { - isExpanded: false, - showControls: false + layout: { + initial: { + isExpanded: false, + showControls: false + } } }); diff --git a/src/apps/viewer/index.ts b/src/apps/viewer/index.ts index 1309526f08231a055e4b1bbe07ab835678b5db97..947f1be45eedcbdac2a0b5c8a131ba086ce57345 100644 --- a/src/apps/viewer/index.ts +++ b/src/apps/viewer/index.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> */ @@ -10,8 +10,10 @@ require('mol-plugin/skin/light.scss') createPlugin(document.getElementById('app')!, { ...DefaultPluginSpec, - initialLayout: { - isExpanded: true, - showControls: true + layout: { + initial: { + isExpanded: true, + showControls: true + } } }); \ No newline at end of file diff --git a/src/examples/proteopedia-wrapper/index.ts b/src/examples/proteopedia-wrapper/index.ts index 962e5642fab1caf6e3edad9a8c1ff464e31fe04c..335e2a48b0c201ed3e553e1b73902b6850d114c2 100644 --- a/src/examples/proteopedia-wrapper/index.ts +++ b/src/examples/proteopedia-wrapper/index.ts @@ -17,6 +17,7 @@ import { StateBuilder, StateObject } from 'mol-state'; import { EvolutionaryConservation } from './annotation'; import { LoadParams, SupportedFormats, RepresentationStyle, ModelInfo } from './helpers'; import { RxEventHelper } from 'mol-util/rx-event-helper'; +import { ControlsWrapper } from './ui/controls'; require('mol-plugin/skin/light.scss') class MolStarProteopediaWrapper { @@ -33,9 +34,14 @@ class MolStarProteopediaWrapper { init(target: string | HTMLElement) { this.plugin = createPlugin(typeof target === 'string' ? document.getElementById(target)! : target, { ...DefaultPluginSpec, - initialLayout: { - isExpanded: false, - showControls: false + layout: { + initial: { + isExpanded: false, + showControls: false + }, + controls: { + right: ControlsWrapper + } } }); diff --git a/src/examples/proteopedia-wrapper/ui/controls.tsx b/src/examples/proteopedia-wrapper/ui/controls.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d2a79e61b59b5df991b610381e77c7d9e4fe8ecc --- /dev/null +++ b/src/examples/proteopedia-wrapper/ui/controls.tsx @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +import * as React from 'react'; +import { PluginUIComponent } from 'mol-plugin/ui/base'; +import { CurrentObject } from 'mol-plugin/ui/plugin'; +import { AnimationControls } from 'mol-plugin/ui/state/animation'; +import { CameraSnapshots } from 'mol-plugin/ui/camera'; + +export class ControlsWrapper extends PluginUIComponent { + render() { + return <div className='msp-scrollable-container msp-right-controls'> + <CurrentObject /> + <AnimationControls /> + <CameraSnapshots /> + </div>; + } +} \ No newline at end of file diff --git a/src/mol-plugin/context.ts b/src/mol-plugin/context.ts index d592a2ef37742a39bdc79c15dfaf0ba1804dbdde..43d7ea16a5e6fe6fd62340ee342f598f73e62b5b 100644 --- a/src/mol-plugin/context.ts +++ b/src/mol-plugin/context.ts @@ -99,7 +99,7 @@ export class PluginContext { initViewer(canvas: HTMLCanvasElement, container: HTMLDivElement) { try { this.layout.setRoot(container); - if (this.spec.initialLayout) this.layout.setProps(this.spec.initialLayout); + if (this.spec.layout && this.spec.layout.initial) this.layout.setProps(this.spec.layout.initial); (this.canvas3d as Canvas3D) = Canvas3D.create(canvas, container); PluginCommands.Canvas3D.SetSettings.dispatch(this, { settings: { backgroundColor: Color(0xFCFBF9) } }); this.canvas3d.animate(); diff --git a/src/mol-plugin/layout.ts b/src/mol-plugin/layout.ts index 63b8f19be005def858b246ed5d7e31317289b9e4..715a84be5cd68db524c193d3add84564c831636b 100644 --- a/src/mol-plugin/layout.ts +++ b/src/mol-plugin/layout.ts @@ -176,7 +176,7 @@ export class PluginLayout extends PluginComponent<PluginLayoutStateProps> { } constructor(private context: PluginContext) { - super({ ...PD.getDefaultValues(PluginLayoutStateParams), ...context.spec.initialLayout }); + super({ ...PD.getDefaultValues(PluginLayoutStateParams), ...(context.spec.layout && context.spec.layout.initial) }); PluginCommands.Layout.Update.subscribe(context, e => this.updateProps(e.state)); diff --git a/src/mol-plugin/spec.ts b/src/mol-plugin/spec.ts index 2bfb64ecabb86f3b97d3fbdf0a748c65cd0bfa7f..3a9611eb8d91f954dc718e7c177affaddbde2b48 100644 --- a/src/mol-plugin/spec.ts +++ b/src/mol-plugin/spec.ts @@ -16,7 +16,14 @@ interface PluginSpec { behaviors: PluginSpec.Behavior[], animations?: PluginStateAnimation[], customParamEditors?: [StateAction | StateTransformer, StateTransformParameters.Class][], - initialLayout?: PluginLayoutStateProps + layout?: { + initial?: PluginLayoutStateProps, + controls?: { + left?: React.ComponentClass | 'none', + right?: React.ComponentClass | 'none', + bottom?: React.ComponentClass | 'none' + } + } } namespace PluginSpec { @@ -38,4 +45,10 @@ namespace PluginSpec { export function Behavior<T extends StateTransformer>(transformer: T, defaultParams?: StateTransformer.Params<T>): Behavior { return { transformer, defaultParams }; } + + export interface LayoutControls { + left?: React.ComponentClass | 'none', + right?: React.ComponentClass | 'none', + bottom?: React.ComponentClass | 'none' + } } \ No newline at end of file diff --git a/src/mol-plugin/ui/plugin.tsx b/src/mol-plugin/ui/plugin.tsx index 27c4304a2f9fd5b9246c5e80da8a89cad0a01c3b..1a2b0615822f95389d9175161478dd34bce634d0 100644 --- a/src/mol-plugin/ui/plugin.tsx +++ b/src/mol-plugin/ui/plugin.tsx @@ -43,35 +43,44 @@ class Layout extends PluginUIComponent { this.subscribe(this.plugin.layout.events.updated, () => this.forceUpdate()); } - region(kind: 'left' | 'right' | 'bottom' | 'main', element: JSX.Element) { + region(kind: 'left' | 'right' | 'bottom' | 'main', Element: React.ComponentClass) { return <div className={`msp-layout-region msp-layout-${kind}`}> <div className='msp-layout-static'> - {element} + <Element /> </div> </div>; } render() { const layout = this.plugin.layout.state; + const spec = this.plugin.spec.layout && this.plugin.spec.layout.controls; + return <div className='msp-plugin'> <div className={`msp-plugin-content ${layout.isExpanded ? 'msp-layout-expanded' : 'msp-layout-standard msp-layout-standard-outside'}`}> <div className={layout.showControls ? 'msp-layout-hide-top' : 'msp-layout-hide-top msp-layout-hide-right msp-layout-hide-bottom msp-layout-hide-left'}> - {this.region('main', <ViewportWrapper />)} - {layout.showControls && this.region('left', <State />)} - {layout.showControls && this.region('right', <div className='msp-scrollable-container msp-right-controls'> - <CurrentObject /> - <AnimationControls /> - <CameraSnapshots /> - <StateSnapshots /> - </div>)} - {layout.showControls && this.region('bottom', <Log />)} + {this.region('main', ViewportWrapper)} + {layout.showControls && spec && spec.left !== 'none' && this.region('left', (spec && spec.left) || State)} + {layout.showControls && spec && spec.right !== 'none' && this.region('right', (spec && spec.right) || ControlsWrapper)} + {layout.showControls && spec && spec.bottom !== 'none' && this.region('bottom', (spec && spec.bottom) || Log)} </div> </div> </div>; } } -export class ViewportWrapper extends PluginUIComponent { + +export class ControlsWrapper extends PluginUIComponent { + render() { + return <div className='msp-scrollable-container msp-right-controls'> + <CurrentObject /> + <AnimationControls /> + <CameraSnapshots /> + <StateSnapshots /> + </div>; + } +} + +export class ViewportWrapper extends PluginUIComponent { render() { return <> <Viewport />