From 0365f883dde3f23e43750d0a847872f918ef3b36 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Thu, 12 Mar 2020 14:04:42 +0100 Subject: [PATCH] mol-plugin: customuze UI layout in viewport params --- src/mol-plugin-ui/plugin.tsx | 7 +- .../viewport/simple-settings.tsx | 84 ++++++++++++------- src/mol-plugin/layout.ts | 19 +++-- 3 files changed, 71 insertions(+), 39 deletions(-) diff --git a/src/mol-plugin-ui/plugin.tsx b/src/mol-plugin-ui/plugin.tsx index cc571085c..e5f3a25af 100644 --- a/src/mol-plugin-ui/plugin.tsx +++ b/src/mol-plugin-ui/plugin.tsx @@ -69,7 +69,7 @@ class Layout extends PluginUIComponent { const controls = (this.plugin.spec.layout && this.plugin.spec.layout.controls) || { }; const classList: string[] = [] - if (controls.top === 'none' || !layout.showControls) { + if (controls.top === 'none' || !layout.showControls || layout.regionState.top === 'hidden') { classList.push('msp-layout-hide-top') } @@ -79,10 +79,11 @@ class Layout extends PluginUIComponent { classList.push('msp-layout-collapse-left') } - if (controls.right === 'none' || !layout.showControls) { + if (controls.right === 'none' || !layout.showControls || layout.regionState.right === 'hidden') { classList.push('msp-layout-hide-right') } - if (controls.bottom === 'none' || !layout.showControls) { + + if (controls.bottom === 'none' || !layout.showControls || layout.regionState.bottom === 'hidden') { classList.push('msp-layout-hide-bottom') } diff --git a/src/mol-plugin-ui/viewport/simple-settings.tsx b/src/mol-plugin-ui/viewport/simple-settings.tsx index e25a9e30c..2cdc23609 100644 --- a/src/mol-plugin-ui/viewport/simple-settings.tsx +++ b/src/mol-plugin-ui/viewport/simple-settings.tsx @@ -6,7 +6,7 @@ */ import * as React from 'react'; -import { Canvas3DParams } from '../../mol-canvas3d/canvas3d'; +import { Canvas3DParams, Canvas3DProps } from '../../mol-canvas3d/canvas3d'; import { PluginCommands } from '../../mol-plugin/commands'; import { ColorNames } from '../../mol-util/color/names'; import { ParameterMappingControl } from '../controls/parameters'; @@ -15,6 +15,9 @@ import { PluginUIComponent } from '../base'; import { Color } from '../../mol-util/color'; import { ParamMapping } from '../../mol-util/param-mapping'; import { PluginContext } from '../../mol-plugin/context'; +import { Mutable } from '../../mol-util/type-helpers'; +import { produce } from 'immer'; +import { StateTransform } from '../../mol-state'; export class SimpleSettingsControl extends PluginUIComponent { componentDidMount() { @@ -28,6 +31,7 @@ export class SimpleSettingsControl extends PluginUIComponent { } const SimpleSettingsParams = { + layout: PD.MultiSelect<'sequence' | 'log' | 'left'>([], [['sequence', 'Sequence'], ['log', 'Log'], ['left', 'Left Panel']] as const), spin: Canvas3DParams.trackball.params.spin, camera: Canvas3DParams.cameraMode, background: PD.MappedStatic('opaque', { @@ -44,9 +48,17 @@ const SimpleSettingsParams = { type SimpleSettingsParams = typeof SimpleSettingsParams const SimpleSettingsMapping = ParamMapping({ params: SimpleSettingsParams, - target(ctx: PluginContext) { return ctx.canvas3d?.props!; } })({ - values(t, ctx) { - const renderer = t.renderer; + target(ctx: PluginContext) { + const layout: SimpleSettingsParams['layout']['defaultValue'] = []; + if (ctx.layout.state.regionState.top !== 'hidden') layout.push('sequence'); + if (ctx.layout.state.regionState.bottom !== 'hidden') layout.push('log'); + if (ctx.layout.state.regionState.left !== 'hidden') layout.push('left'); + return { canvas: ctx.canvas3d?.props!, layout }; + } +})({ + values(props, ctx) { + const { canvas } = props; + const renderer = canvas.renderer; let renderStyle: SimpleSettingsParams['renderStyle']['defaultValue'] = 'custom' as any; if (renderer) { @@ -64,39 +76,55 @@ const SimpleSettingsMapping = ParamMapping({ } return { - spin: !!t.trackball.spin, - camera: t.cameraMode, - background: (renderer.backgroundColor === ColorNames.white && t.transparentBackground) + layout: props.layout, + spin: !!canvas.trackball.spin, + camera: canvas.cameraMode, + background: (renderer.backgroundColor === ColorNames.white && canvas.transparentBackground) ? { name: 'transparent', params: { } } : { name: 'opaque', params: { color: renderer.backgroundColor } }, renderStyle, - occlusion: t.postprocessing.occlusionEnable, - outline: t.postprocessing.outlineEnable, - fog: ctx.canvas3d ? t.cameraFog > 1 : false, - clipFar: t.cameraClipFar + occlusion: canvas.postprocessing.occlusionEnable, + outline: canvas.postprocessing.outlineEnable, + fog: ctx.canvas3d ? canvas.cameraFog > 1 : false, + clipFar: canvas.cameraClipFar }; }, - update(s, t) { - t.trackball.spin = s.spin; - t.cameraMode = s.camera; - t.transparentBackground = s.background.name === 'transparent'; - t.renderer.backgroundColor = s.background.name === 'transparent' ? ColorNames.white : s.background.params.color; + update(s, props) { + const canvas = props.canvas as Mutable<Canvas3DProps>; + canvas.trackball.spin = s.spin; + canvas.cameraMode = s.camera; + canvas.transparentBackground = s.background.name === 'transparent'; + canvas.renderer.backgroundColor = s.background.name === 'transparent' ? ColorNames.white : s.background.params.color; switch (s.renderStyle) { - case 'flat': Object.assign(t.renderer, { lightIntensity: 0, ambientIntensity: 1, roughness: 0.4, metalness: 0 }); break; - case 'matte': Object.assign(t.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 1, metalness: 0 }); break; - case 'glossy': Object.assign(t.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 0.4, metalness: 0 }); break; - case 'metallic': Object.assign(t.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 0.6, metalness: 0.4 }); break; + case 'flat': Object.assign(canvas.renderer, { lightIntensity: 0, ambientIntensity: 1, roughness: 0.4, metalness: 0 }); break; + case 'matte': Object.assign(canvas.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 1, metalness: 0 }); break; + case 'glossy': Object.assign(canvas.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 0.4, metalness: 0 }); break; + case 'metallic': Object.assign(canvas.renderer, { lightIntensity: 0.6, ambientIntensity: 0.4, roughness: 0.6, metalness: 0.4 }); break; } - t.postprocessing.occlusionEnable = s.occlusion; + canvas.postprocessing.occlusionEnable = s.occlusion; if (s.occlusion) { - t.postprocessing.occlusionBias = 0.5; - t.postprocessing.occlusionRadius = 64; + canvas.postprocessing.occlusionBias = 0.5; + canvas.postprocessing.occlusionRadius = 64; } - t.postprocessing.outlineEnable = s.outline; - t.cameraFog = s.fog ? 50 : 0; - t.cameraClipFar = s.clipFar; + canvas.postprocessing.outlineEnable = s.outline; + canvas.cameraFog = s.fog ? 50 : 0; + canvas.cameraClipFar = s.clipFar; + + props.layout = s.layout; }, - apply(settings, ctx) { - return PluginCommands.Canvas3D.SetSettings(ctx, { settings }); + async apply(props, ctx) { + await PluginCommands.Canvas3D.SetSettings(ctx, { settings: props.canvas }); + + const hideLeft = props.layout.indexOf('left') < 0; + const state = produce(ctx.layout.state, s => { + s.regionState.top = props.layout.indexOf('sequence') >= 0 ? 'full' : 'hidden'; + s.regionState.bottom = props.layout.indexOf('log') >= 0 ? 'full' : 'hidden'; + s.regionState.left = hideLeft ? 'hidden' : ctx.behaviors.layout.leftPanelTabName.value === 'none' ? 'collapsed' : 'full'; + }); + await PluginCommands.Layout.Update(ctx, { state }); + + if (hideLeft) { + PluginCommands.State.SetCurrentObject(ctx, { state: ctx.state.dataState, ref: StateTransform.RootRef }); + } } }) \ No newline at end of file diff --git a/src/mol-plugin/layout.ts b/src/mol-plugin/layout.ts index 570e8f76f..019fa2540 100644 --- a/src/mol-plugin/layout.ts +++ b/src/mol-plugin/layout.ts @@ -11,20 +11,23 @@ import { PluginContext } from './context'; import { PluginCommands } from './commands'; const regionStateOptions = [ - ['full', 'Full'] as const, - ['collapsed', 'Collapsed'] as const, - ['hidden', 'Hidden'] as const, -]; + ['full', 'Full'], + ['collapsed', 'Collapsed'], + ['hidden', 'Hidden'], +] as const; +const simpleRegionStateOptions = [ + ['full', 'Full'], + ['hidden', 'Hidden'], +] as const; export type PluginLayoutControlsDisplay = 'outside' | 'portrait' | 'landscape' | 'reactive' export const PluginLayoutStateParams = { isExpanded: PD.Boolean(false), showControls: PD.Boolean(true), regionState: PD.Group({ left: PD.Select('full', regionStateOptions), - // TODO: support other region states - // right: PD.Select('full', regionStateOptions), - // top: PD.Select('full', regionStateOptions), - // bottom: PD.Select('full', regionStateOptions), + top: PD.Select('full', simpleRegionStateOptions), + right: PD.Select('full', simpleRegionStateOptions), + bottom: PD.Select('full', simpleRegionStateOptions), }), controlsDisplay: PD.Value<PluginLayoutControlsDisplay>('outside', { isHidden: true }) } -- GitLab