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';
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) => {
......
......@@ -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),
......
......@@ -163,6 +163,7 @@
> span {
color: $font-color;
margin-left: $control-spacing;
margin-right: $control-spacing;
font-size: 85%;
display: inline-block;
......
......@@ -304,24 +304,3 @@ export const StructureFromSelection = StateAction.build({
const root = state.build().to(ref).apply(StructureSelection, { query, label: params.label });
return state.updateTree(root);
});
\ No newline at end of file
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';
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: {} };
}
......
......@@ -89,15 +89,15 @@ 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} />
{!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();
......
......@@ -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 />}
</>;
}
}
\ No newline at end of file
......@@ -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} />)}
</>;
}
}
\ No newline at end of file
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment