Bladeren bron

mol-plugin: more UI tweaks

David Sehnal 6 jaren geleden
bovenliggende
commit
7ef1d906f1

+ 1 - 1
src/apps/viewer/extensions/jolecule.ts

@@ -21,7 +21,7 @@ import { Camera } from 'mol-canvas3d/camera';
 import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/representation';
 
 export const CreateJoleculeState = StateAction.build({
-    display: { name: 'Jolecule State' },
+    display: { name: 'Jolecule State Import' },
     params: { id: ParamDefinition.Text('1mbo') },
     from: PluginStateObject.Root
 })(async ({ ref, state, params }, plugin: PluginContext) => {

+ 0 - 2
src/mol-plugin/index.ts

@@ -25,8 +25,6 @@ export const DefaultPluginSpec: PluginSpec = {
         PluginSpec.Action(StateActions.Structure.CreateComplexRepresentation),
         PluginSpec.Action(StateActions.Structure.EnableModelCustomProps),
 
-        PluginSpec.Action(StateActions.Structure.TestBlob),
-
         // Volume streaming
         PluginSpec.Action(InitVolumeStreaming),
         PluginSpec.Action(BoxifyVolumeStreaming),

+ 1 - 0
src/mol-plugin/skin/base/components/temp.scss

@@ -163,6 +163,7 @@
 
         > span {
             color: $font-color;
+            margin-left: $control-spacing;
             margin-right: $control-spacing;
             font-size: 85%;
             display: inline-block;

+ 0 - 21
src/mol-plugin/state/actions/structure.ts

@@ -303,25 +303,4 @@ export const StructureFromSelection = StateAction.build({
     const query = StructureElement.Loci.toScriptExpression(sel);
     const root = state.build().to(ref).apply(StructureSelection, { query, label: params.label });
     return state.updateTree(root);
-});
-
-
-export const TestBlob = StateAction.build({
-    display: { name: 'Test Blob' },
-    from: PluginStateObject.Root
-})(({ ref, state }, ctx: PluginContext) => {
-
-    const ids = '5B6V,5B6W,5H2H,5H2I,5H2J,5B6X,5H2K,5H2L,5H2M,5B6Y,5H2N,5H2O,5H2P,5B6Z'.split(',').map(u => u.toLowerCase());
-
-    const root = state.build().to(ref)
-        .apply(StateTransforms.Data.DownloadBlob, {
-            sources: ids.map(id => ({ id, url: `https://webchem.ncbr.muni.cz/ModelServer/static/bcif/${id}`, isBinary: true })),
-            maxConcurrency: 4
-        }).apply(StateTransforms.Data.ParseBlob, {
-            formats: ids.map(id => ({ id, format: 'cif' as 'cif' }))
-        })
-        .apply(StateTransforms.Model.TrajectoryFromBlob)
-        .apply(StateTransforms.Model.ModelFromTrajectory, { modelIndex: 0 });
-    createStructureTree(ctx, root, false);
-    return state.updateTree(root);
 });

+ 9 - 4
src/mol-plugin/state/animation/built-in.ts

@@ -13,12 +13,12 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
 
 export const AnimateModelIndex = PluginStateAnimation.create({
     name: 'built-in.animate-model-index',
-    display: { name: 'Animate Model Index' },
+    display: { name: 'Animate Trajectory' },
     params: () => ({
         mode: PD.MappedStatic('palindrome', {
             palindrome: PD.Group({ }),
             loop: PD.Group({ }),
-            once: PD.Group({ direction: PD.Select('palindrome', [['forward', 'Forward'], ['backward', 'Backward']]) }, { isFlat: true })
+            once: PD.Group({ direction: PD.Select('forward', [['forward', 'Forward'], ['backward', 'Backward']]) }, { isFlat: true })
         }, { options: [['palindrome', 'Palindrome'], ['loop', 'Loop'], ['once', 'Once']] }),
         maxFPS: PD.Numeric(15, { min: 1, max: 30, step: 1 })
     }),
@@ -42,7 +42,7 @@ export const AnimateModelIndex = PluginStateAnimation.create({
 
         const params = ctx.params;
         const palindromeDirections = animState.palindromeDirections || { };
-        let isEnd = false;
+        let isEnd = false, allSingles = true;
 
         for (const m of models) {
             const parent = StateSelection.findAncestorOfType(state.tree, state.cells, m.transform.ref, [PluginStateObject.Molecule.Trajectory]);
@@ -51,6 +51,11 @@ export const AnimateModelIndex = PluginStateAnimation.create({
             update.to(m.transform.ref).update(StateTransforms.Model.ModelFromTrajectory,
                 old => {
                     const len = traj.data.length;
+                    if (len !== 1) {
+                        allSingles = false;
+                    } else {
+                        return old;
+                    }
                     let dir: -1 | 1 = 1;
                     if (params.mode.name === 'once') {
                         dir = params.mode.params.direction === 'backward' ? -1 : 1;
@@ -77,7 +82,7 @@ export const AnimateModelIndex = PluginStateAnimation.create({
 
         await PluginCommands.State.Update.dispatch(ctx.plugin, { state, tree: update, options: { doNotLogTiming: true } });
 
-        if (params.mode.name === 'once' && isEnd) return { kind: 'finished' };
+        if (allSingles || (params.mode.name === 'once' && isEnd)) return { kind: 'finished' };
         if (params.mode.name === 'palindrome') return { kind: 'next', state: { palindromeDirections } };
         return { kind: 'next', state: {} };
     }

+ 18 - 9
src/mol-plugin/ui/controls.tsx

@@ -89,16 +89,16 @@ export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: bo
     // }
 
     render() {
-        if (!this.state.show) return null;
-
         const isAnimating = this.plugin.behaviors.state.isAnimating.value;
 
+        if (!this.state.show || (isAnimating && !this.state.label)) return null;
+
         return <div className='msp-traj-controls'>
             {/* <IconButton icon={isAnimating ? 'stop' : 'play'} title={isAnimating ? 'Stop' : 'Play'} onClick={isAnimating ? this.stopAnimation : this.playAnimation} /> */}
-            <IconButton icon='model-first' title='First Model' onClick={this.reset} disabled={isAnimating} />
-            <IconButton icon='model-prev' title='Previous Model' onClick={this.prev} disabled={isAnimating} />
-            <IconButton icon='model-next' title='Next Model' onClick={this.next} disabled={isAnimating} />
-            { !!this.state.label && <span>{this.state.label}</span> }
+            {!isAnimating && <IconButton icon='model-first' title='First Model' onClick={this.reset} disabled={isAnimating} />}
+            {!isAnimating && <IconButton icon='model-prev' title='Previous Model' onClick={this.prev} disabled={isAnimating} />}
+            {!isAnimating && <IconButton icon='model-next' title='Next Model' onClick={this.next} disabled={isAnimating} />}
+            {!!this.state.label && <span>{this.state.label}</span> }
         </div>;
     }
 }
@@ -170,9 +170,18 @@ export class AnimationViewportControls extends PluginUIComponent<{}, { isEmpty:
     state = { isEmpty: true, isExpanded: false, isUpdating: false, isAnimating: false, isPlaying: false };
 
     componentDidMount() {
-        this.subscribe(this.plugin.state.snapshots.events.changed, () => this.setState({ isPlaying: this.plugin.state.snapshots.state.isPlaying }));
-        this.subscribe(this.plugin.behaviors.state.isUpdating, isUpdating => this.setState({ isUpdating, isEmpty: this.plugin.state.dataState.tree.transforms.size < 2 }));
-        this.subscribe(this.plugin.behaviors.state.isAnimating, isAnimating => this.setState({ isAnimating }));
+        this.subscribe(this.plugin.state.snapshots.events.changed, () => {
+            if (this.plugin.state.snapshots.state.isPlaying) this.setState({ isPlaying: true, isExpanded: false });
+            else this.setState({ isPlaying: false });
+        });
+        this.subscribe(this.plugin.behaviors.state.isUpdating, isUpdating => {
+            if (isUpdating) this.setState({ isUpdating: true, isExpanded: false, isEmpty: this.plugin.state.dataState.tree.transforms.size < 2 });
+            else this.setState({ isUpdating: false, isEmpty: this.plugin.state.dataState.tree.transforms.size < 2 });
+        });
+        this.subscribe(this.plugin.behaviors.state.isAnimating, isAnimating => {
+            if (isAnimating) this.setState({ isAnimating: true, isExpanded: false });
+            else this.setState({ isAnimating: false });
+        });
     }
     toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded });
     stop = () => this.plugin.state.animation.stop();

+ 1 - 1
src/mol-plugin/ui/plugin.tsx

@@ -194,7 +194,7 @@ export class CurrentObject extends PluginUIComponent {
 
         return <>
             {(cell.status === 'ok' || cell.status === 'error') && <UpdateTransformContol state={current.state} transform={transform} /> }
-            {cell.status === 'ok' && <StateObjectActions state={current.state} nodeRef={ref} />}
+            {cell.status === 'ok' && <StateObjectActions state={current.state} nodeRef={ref} initiallyColapsed />}
         </>;
     }
 }

+ 2 - 2
src/mol-plugin/ui/state/actions.tsx

@@ -9,7 +9,7 @@ import { PluginUIComponent } from '../base';
 import { ApplyActionContol } from './apply-action';
 import { State } from 'mol-state';
 
-export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRef: string, hideHeader?: boolean }> {
+export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRef: string, hideHeader?: boolean, initiallyColapsed?: boolean }> {
     get current() {
         return this.plugin.state.behavior.currentObject.value;
     }
@@ -37,7 +37,7 @@ export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRe
 
         return <>
             {!this.props.hideHeader && <div className='msp-section-header'>{`Actions (${display})`}</div> }
-            {actions.map((act, i) => <ApplyActionContol plugin={this.plugin} key={`${act.id}`} state={state} action={act} nodeRef={ref} />)}
+            {actions.map((act, i) => <ApplyActionContol plugin={this.plugin} key={`${act.id}`} state={state} action={act} nodeRef={ref} initiallyCollapsed={this.props.initiallyColapsed} />)}
         </>;
     }
 }

+ 3 - 2
src/mol-plugin/ui/state/apply-action.tsx

@@ -18,7 +18,8 @@ namespace ApplyActionContol {
         plugin: PluginContext,
         nodeRef: StateTransform.Ref,
         state: State,
-        action: StateAction
+        action: StateAction,
+        initiallyCollapsed?: boolean
     }
 
     export interface ComponentState {
@@ -49,7 +50,7 @@ class ApplyActionContol extends TransformContolBase<ApplyActionContol.Props, App
 
     private _getInfo = memoizeLatest((t: StateTransform.Ref, v: string) => StateTransformParameters.infoFromAction(this.plugin, this.props.state, this.props.action, this.props.nodeRef));
 
-    state = { ref: this.props.nodeRef, version: this.props.state.transforms.get(this.props.nodeRef).version, error: void 0, isInitial: true, params: this.getInfo().initialValues, busy: false };
+    state = { ref: this.props.nodeRef, version: this.props.state.transforms.get(this.props.nodeRef).version, error: void 0, isInitial: true, params: this.getInfo().initialValues, busy: false, isCollapsed: this.props.initiallyCollapsed };
 
     static getDerivedStateFromProps(props: ApplyActionContol.Props, state: ApplyActionContol.ComponentState) {
         if (props.nodeRef === state.ref) return null;