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

mol-state & volume streaming updates

- error cells are no longer considered valid update roots
- volume streaming now better handles initialization errors
parent e3e7fa30
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,7 @@
*/
import * as React from 'react';
import { InitVolumeStreaming, CreateVolumeStreamingInfo } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers';
import { InitVolumeStreaming } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers';
import { CollapsableControls, CollapsableState } from '../base';
import { ApplyActionControl } from '../state/apply-action';
import { UpdateTransformControl } from '../state/update-transform';
......@@ -14,7 +14,8 @@ import { BindingsHelp } from '../viewport/help';
import { ExpandGroup } from '../controls/common';
import { StructureHierarchyManager } from '../../mol-plugin-state/manager/structure/hierarchy';
import { FocusLoci } from '../../mol-plugin/behavior/dynamic/representation';
import { StateSelection } from '../../mol-state';
import { StateSelection, StateTransform } from '../../mol-state';
import { VolumeStreaming } from '../../mol-plugin/behavior/dynamic/volume-streaming/behavior';
interface VolumeStreamingControlState extends CollapsableState {
isBusy: boolean
......@@ -39,6 +40,9 @@ export class VolumeStreamingControls extends CollapsableControls<{}, VolumeStrea
description: StructureHierarchyManager.getSelectedStructuresDescription(this.plugin)
})
});
this.subscribe(this.plugin.events.state.cell.stateUpdated, e => {
if (StateTransform.hasTag(e.cell.transform, VolumeStreaming.RootTag)) this.forceUpdate();
});
this.subscribe(this.plugin.behaviors.state.isBusy, v => {
this.setState({ isBusy: v })
});
......@@ -58,9 +62,11 @@ export class VolumeStreamingControls extends CollapsableControls<{}, VolumeStrea
renderEnable() {
const pivot = this.pivot;
const errored = this.plugin.state.data.select(StateSelection.Generators.ofTransformerWithError(CreateVolumeStreamingInfo, pivot.cell.transform.ref))[0];
const simpleApply = errored
? { header: 'Error enabling', icon: 'alert' as const, title: errored.errorText }
const root = StateSelection.findTagInSubtree(this.pivot.cell.parent.tree, this.pivot.cell.transform.ref, VolumeStreaming.RootTag);
const rootCell = root && this.pivot.cell.parent.cells.get(root);
const simpleApply = rootCell && rootCell.status === 'error'
? { header: 'Error enabling', icon: 'alert' as const, title: rootCell.errorText }
: { header: 'Enable', icon: 'check' as const, title: 'Enable' }
return <ApplyActionControl state={pivot.cell.parent} action={InitVolumeStreaming} initiallyCollapsed={true} nodeRef={pivot.cell.transform.ref} simpleApply={simpleApply} />;
......
......@@ -27,6 +27,7 @@ import { EmptyLoci, Loci, isEmptyLoci } from '../../../../mol-model/loci';
export class VolumeStreaming extends PluginStateObject.CreateBehavior<VolumeStreaming.Behavior>({ name: 'Volume Streaming' }) { }
export namespace VolumeStreaming {
export const RootTag = 'volume-streaming-info'
export interface ChannelParams {
isoValue: VolumeIsoValue,
......
......@@ -94,12 +94,21 @@ export const InitVolumeStreaming = StateAction.build({
}
const infoTree = state.build().to(ref)
.apply(CreateVolumeStreamingInfo, {
.applyOrUpdateTagged(VolumeStreaming.RootTag, CreateVolumeStreamingInfo, {
serverUrl: params.options.serverUrl,
entries
});
const infoObj = await state.updateTree(infoTree).runInContext(taskCtx);
await plugin.updateDataState(infoTree);
const info = infoTree.selector;
if (!info.isOk) return;
// clear the children in case there were errors
const children = state.tree.children.get(info.ref);
if (children?.size > 0) await plugin.managers.structure.hierarchy.remove(children?.toArray());
const infoObj = info.cell!.obj!;
const behTree = state.build().to(infoTree.ref).apply(CreateVolumeStreamingBehavior,
PD.getDefaultValues(VolumeStreaming.createParams({ data: infoObj.data, defaultView: params.defaultView, channelParams: params.options.channelParams })),
......
......@@ -171,6 +171,7 @@ class State {
}
private inTransaction = false;
private inTransactionError = false;
/** Apply series of updates to the state. If any of them fail, revert to the original state. */
transaction(edits: () => Promise<void> | void, options?: { canUndo?: string | boolean }) {
......@@ -183,12 +184,12 @@ class State {
let restored = false;
try {
if (!isNested) this.behaviors.isUpdating.next(true);
this.inTransaction = true;
this.inTransactionError = false;
await edits();
let hasError = false;
this.cells.forEach(c => hasError = hasError || c.state === 'error');
if (hasError) {
if (this.inTransactionError) {
restored = true;
await this.updateTree(snapshot).runInContext(ctx);
}
......@@ -198,7 +199,10 @@ class State {
await this.updateTree(snapshot).runInContext(ctx);
this.events.log.error(e);
}
if (isNested) throw e;
if (isNested) {
this.inTransactionError = true;
throw e;
}
} finally {
if (!isNested) {
this.inTransaction = false;
......@@ -240,6 +244,8 @@ class State {
: await this._updateTree(taskCtx, params);
reverted = this.reverted;
if (ret.ctx.hadError) this.inTransactionError = true;
return ret.cell;
} finally {
this.updateQueue.handled(params);
......@@ -537,7 +543,7 @@ function findUpdateRoots(cells: Map<StateTransform.Ref, StateObjectCell>, tree:
function findUpdateRootsVisitor(n: StateTransform, _: any, s: { roots: Ref[], cells: Map<Ref, StateObjectCell> }) {
const cell = s.cells.get(n.ref);
if (!cell || cell.transform.version !== n.version || cell.status === 'error') {
s.roots.push(n.ref);
if (cell?.status !== 'error') s.roots.push(n.ref);
return false;
}
// nothing below a Null object can be an update root
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment