Просмотр исходного кода

mol-plugin: customuze UI layout in viewport params

David Sehnal 5 лет назад
Родитель
Сommit
0365f883dd

+ 4 - 3
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')
         }
 

+ 56 - 28
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 });
+        }
     }
 })

+ 11 - 8
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 })
 }