Skip to content
Snippets Groups Projects
Commit 7ef1d906 authored by David Sehnal's avatar David Sehnal
Browse files

mol-plugin: more UI tweaks

parent 08dbec87
No related branches found
No related tags found
No related merge requests found
...@@ -21,7 +21,7 @@ import { Camera } from 'mol-canvas3d/camera'; ...@@ -21,7 +21,7 @@ import { Camera } from 'mol-canvas3d/camera';
import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/representation'; import { StructureRepresentation3DHelpers } from 'mol-plugin/state/transforms/representation';
export const CreateJoleculeState = StateAction.build({ export const CreateJoleculeState = StateAction.build({
display: { name: 'Jolecule State' }, display: { name: 'Jolecule State Import' },
params: { id: ParamDefinition.Text('1mbo') }, params: { id: ParamDefinition.Text('1mbo') },
from: PluginStateObject.Root from: PluginStateObject.Root
})(async ({ ref, state, params }, plugin: PluginContext) => { })(async ({ ref, state, params }, plugin: PluginContext) => {
......
...@@ -25,8 +25,6 @@ export const DefaultPluginSpec: PluginSpec = { ...@@ -25,8 +25,6 @@ export const DefaultPluginSpec: PluginSpec = {
PluginSpec.Action(StateActions.Structure.CreateComplexRepresentation), PluginSpec.Action(StateActions.Structure.CreateComplexRepresentation),
PluginSpec.Action(StateActions.Structure.EnableModelCustomProps), PluginSpec.Action(StateActions.Structure.EnableModelCustomProps),
PluginSpec.Action(StateActions.Structure.TestBlob),
// Volume streaming // Volume streaming
PluginSpec.Action(InitVolumeStreaming), PluginSpec.Action(InitVolumeStreaming),
PluginSpec.Action(BoxifyVolumeStreaming), PluginSpec.Action(BoxifyVolumeStreaming),
......
...@@ -163,6 +163,7 @@ ...@@ -163,6 +163,7 @@
> span { > span {
color: $font-color; color: $font-color;
margin-left: $control-spacing;
margin-right: $control-spacing; margin-right: $control-spacing;
font-size: 85%; font-size: 85%;
display: inline-block; display: inline-block;
......
...@@ -304,24 +304,3 @@ export const StructureFromSelection = StateAction.build({ ...@@ -304,24 +304,3 @@ export const StructureFromSelection = StateAction.build({
const root = state.build().to(ref).apply(StructureSelection, { query, label: params.label }); const root = state.build().to(ref).apply(StructureSelection, { query, label: params.label });
return state.updateTree(root); 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);
});
\ No newline at end of file
...@@ -13,12 +13,12 @@ import { ParamDefinition as PD } from 'mol-util/param-definition'; ...@@ -13,12 +13,12 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
export const AnimateModelIndex = PluginStateAnimation.create({ export const AnimateModelIndex = PluginStateAnimation.create({
name: 'built-in.animate-model-index', name: 'built-in.animate-model-index',
display: { name: 'Animate Model Index' }, display: { name: 'Animate Trajectory' },
params: () => ({ params: () => ({
mode: PD.MappedStatic('palindrome', { mode: PD.MappedStatic('palindrome', {
palindrome: PD.Group({ }), palindrome: PD.Group({ }),
loop: 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']] }), }, { options: [['palindrome', 'Palindrome'], ['loop', 'Loop'], ['once', 'Once']] }),
maxFPS: PD.Numeric(15, { min: 1, max: 30, step: 1 }) maxFPS: PD.Numeric(15, { min: 1, max: 30, step: 1 })
}), }),
...@@ -42,7 +42,7 @@ export const AnimateModelIndex = PluginStateAnimation.create({ ...@@ -42,7 +42,7 @@ export const AnimateModelIndex = PluginStateAnimation.create({
const params = ctx.params; const params = ctx.params;
const palindromeDirections = animState.palindromeDirections || { }; const palindromeDirections = animState.palindromeDirections || { };
let isEnd = false; let isEnd = false, allSingles = true;
for (const m of models) { for (const m of models) {
const parent = StateSelection.findAncestorOfType(state.tree, state.cells, m.transform.ref, [PluginStateObject.Molecule.Trajectory]); const parent = StateSelection.findAncestorOfType(state.tree, state.cells, m.transform.ref, [PluginStateObject.Molecule.Trajectory]);
...@@ -51,6 +51,11 @@ export const AnimateModelIndex = PluginStateAnimation.create({ ...@@ -51,6 +51,11 @@ export const AnimateModelIndex = PluginStateAnimation.create({
update.to(m.transform.ref).update(StateTransforms.Model.ModelFromTrajectory, update.to(m.transform.ref).update(StateTransforms.Model.ModelFromTrajectory,
old => { old => {
const len = traj.data.length; const len = traj.data.length;
if (len !== 1) {
allSingles = false;
} else {
return old;
}
let dir: -1 | 1 = 1; let dir: -1 | 1 = 1;
if (params.mode.name === 'once') { if (params.mode.name === 'once') {
dir = params.mode.params.direction === 'backward' ? -1 : 1; dir = params.mode.params.direction === 'backward' ? -1 : 1;
...@@ -77,7 +82,7 @@ export const AnimateModelIndex = PluginStateAnimation.create({ ...@@ -77,7 +82,7 @@ export const AnimateModelIndex = PluginStateAnimation.create({
await PluginCommands.State.Update.dispatch(ctx.plugin, { state, tree: update, options: { doNotLogTiming: true } }); 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 } }; if (params.mode.name === 'palindrome') return { kind: 'next', state: { palindromeDirections } };
return { kind: 'next', state: {} }; return { kind: 'next', state: {} };
} }
......
...@@ -89,15 +89,15 @@ export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: bo ...@@ -89,15 +89,15 @@ export class TrajectoryViewportControls extends PluginUIComponent<{}, { show: bo
// } // }
render() { render() {
if (!this.state.show) return null;
const isAnimating = this.plugin.behaviors.state.isAnimating.value; const isAnimating = this.plugin.behaviors.state.isAnimating.value;
if (!this.state.show || (isAnimating && !this.state.label)) return null;
return <div className='msp-traj-controls'> return <div className='msp-traj-controls'>
{/* <IconButton icon={isAnimating ? 'stop' : 'play'} title={isAnimating ? 'Stop' : 'Play'} onClick={isAnimating ? this.stopAnimation : this.playAnimation} /> */} {/* <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} /> {!isAnimating && <IconButton icon='model-first' title='First Model' onClick={this.reset} disabled={isAnimating} />}
<IconButton icon='model-prev' title='Previous Model' onClick={this.prev} disabled={isAnimating} /> {!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} /> {!isAnimating && <IconButton icon='model-next' title='Next Model' onClick={this.next} disabled={isAnimating} />}
{!!this.state.label && <span>{this.state.label}</span> } {!!this.state.label && <span>{this.state.label}</span> }
</div>; </div>;
} }
...@@ -170,9 +170,18 @@ export class AnimationViewportControls extends PluginUIComponent<{}, { isEmpty: ...@@ -170,9 +170,18 @@ export class AnimationViewportControls extends PluginUIComponent<{}, { isEmpty:
state = { isEmpty: true, isExpanded: false, isUpdating: false, isAnimating: false, isPlaying: false }; state = { isEmpty: true, isExpanded: false, isUpdating: false, isAnimating: false, isPlaying: false };
componentDidMount() { componentDidMount() {
this.subscribe(this.plugin.state.snapshots.events.changed, () => this.setState({ isPlaying: this.plugin.state.snapshots.state.isPlaying })); this.subscribe(this.plugin.state.snapshots.events.changed, () => {
this.subscribe(this.plugin.behaviors.state.isUpdating, isUpdating => this.setState({ isUpdating, isEmpty: this.plugin.state.dataState.tree.transforms.size < 2 })); if (this.plugin.state.snapshots.state.isPlaying) this.setState({ isPlaying: true, isExpanded: false });
this.subscribe(this.plugin.behaviors.state.isAnimating, isAnimating => this.setState({ isAnimating })); 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 }); toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded });
stop = () => this.plugin.state.animation.stop(); stop = () => this.plugin.state.animation.stop();
......
...@@ -194,7 +194,7 @@ export class CurrentObject extends PluginUIComponent { ...@@ -194,7 +194,7 @@ export class CurrentObject extends PluginUIComponent {
return <> return <>
{(cell.status === 'ok' || cell.status === 'error') && <UpdateTransformContol state={current.state} transform={transform} /> } {(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 />}
</>; </>;
} }
} }
\ No newline at end of file
...@@ -9,7 +9,7 @@ import { PluginUIComponent } from '../base'; ...@@ -9,7 +9,7 @@ import { PluginUIComponent } from '../base';
import { ApplyActionContol } from './apply-action'; import { ApplyActionContol } from './apply-action';
import { State } from 'mol-state'; 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() { get current() {
return this.plugin.state.behavior.currentObject.value; return this.plugin.state.behavior.currentObject.value;
} }
...@@ -37,7 +37,7 @@ export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRe ...@@ -37,7 +37,7 @@ export class StateObjectActions extends PluginUIComponent<{ state: State, nodeRe
return <> return <>
{!this.props.hideHeader && <div className='msp-section-header'>{`Actions (${display})`}</div> } {!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} />)}
</>; </>;
} }
} }
\ No newline at end of file
...@@ -18,7 +18,8 @@ namespace ApplyActionContol { ...@@ -18,7 +18,8 @@ namespace ApplyActionContol {
plugin: PluginContext, plugin: PluginContext,
nodeRef: StateTransform.Ref, nodeRef: StateTransform.Ref,
state: State, state: State,
action: StateAction action: StateAction,
initiallyCollapsed?: boolean
} }
export interface ComponentState { export interface ComponentState {
...@@ -49,7 +50,7 @@ class ApplyActionContol extends TransformContolBase<ApplyActionContol.Props, App ...@@ -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)); 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) { static getDerivedStateFromProps(props: ApplyActionContol.Props, state: ApplyActionContol.ComponentState) {
if (props.nodeRef === state.ref) return null; if (props.nodeRef === state.ref) return null;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment