diff --git a/src/mol-plugin/ui/state-tree.tsx b/src/mol-plugin/ui/state-tree.tsx index 5aa91436242393360980b40cfa24b96cb2180cc8..5c56a979c7e226df685bbd70dcf26dcf46874e8d 100644 --- a/src/mol-plugin/ui/state-tree.tsx +++ b/src/mol-plugin/ui/state-tree.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import { PluginStateObject } from 'mol-plugin/state/objects'; -import { State } from 'mol-state' +import { State, StateObject } from 'mol-state' import { PluginCommands } from 'mol-plugin/command'; import { PluginComponent } from './base'; @@ -60,6 +60,8 @@ class StateTreeNode extends PluginComponent<{ nodeRef: string, state: State }, { } render() { + if (this.props.state.cells.get(this.props.nodeRef)!.obj === StateObject.Null) return null; + const cellState = this.cellState; const children = this.props.state.tree.children.get(this.props.nodeRef); diff --git a/src/mol-state/object.ts b/src/mol-state/object.ts index 97a2b9e4870dfd053303c6f6998587c799959a7c..bdbe5631533fd4915ad7bc080f43d7d329030211 100644 --- a/src/mol-state/object.ts +++ b/src/mol-state/object.ts @@ -9,7 +9,7 @@ import { Transform } from './transform'; export { StateObject, StateObjectCell } -interface StateObject<D = any, T extends StateObject.Type = { name: string, typeClass: any }> { +interface StateObject<D = any, T extends StateObject.Type = StateObject.Type<any>> { readonly id: UUID, readonly type: T, readonly data: D, @@ -39,6 +39,14 @@ namespace StateObject { } } } + + /** A special object indicating a transformer result has no value. */ + export const Null: StateObject<any, any> = { + id: UUID.create22(), + type: { name: 'Null', typeClass: 'Null' }, + data: void 0, + label: 'Null' + }; } interface StateObjectCell { diff --git a/src/mol-state/state.ts b/src/mol-state/state.ts index 1fedf85e96d96c3016ba8c8f95225240b3ea3718..d73d707efaf5280f3f4c0e385b745b8ade465f5e 100644 --- a/src/mol-state/state.ts +++ b/src/mol-state/state.ts @@ -441,6 +441,7 @@ type UpdateNodeResult = async function updateSubtree(ctx: UpdateContext, root: Ref) { setCellStatus(ctx, root, 'processing'); + let isNull = false; try { const start = now(); const update = await updateNode(ctx, root); @@ -451,10 +452,13 @@ async function updateSubtree(ctx: UpdateContext, root: Ref) { setCellStatus(ctx, root, 'ok'); ctx.results.push(update); if (update.action === 'created') { + isNull = update.obj === StateObject.Null; ctx.parent.events.log.next(LogEntry.info(`Created ${update.obj.label} in ${formatTimespan(time)}.`)); } else if (update.action === 'updated') { + isNull = update.obj === StateObject.Null; ctx.parent.events.log.next(LogEntry.info(`Updated ${update.obj.label} in ${formatTimespan(time)}.`)); } else if (update.action === 'replaced') { + isNull = update.obj === StateObject.Null; ctx.parent.events.log.next(LogEntry.info(`Updated ${update.obj.label} in ${formatTimespan(time)}.`)); } } catch (e) { @@ -464,6 +468,10 @@ async function updateSubtree(ctx: UpdateContext, root: Ref) { return; } + // Do not continue the updates if the object is null + // TODO: set the states to something "nicer"? + if (isNull) return; + const children = ctx.tree.children.get(root).values(); while (true) { const next = children.next(); @@ -497,7 +505,7 @@ async function updateNode(ctx: UpdateContext, currentRef: Ref): Promise<UpdateNo } else { const oldParams = oldTree.transforms.get(currentRef)!.params; - const updateKind = !!current.obj + const updateKind = !!current.obj && current.obj !== StateObject.Null ? await updateObject(ctx, currentRef, transform.transformer, parent, current.obj!, oldParams, transform.params) : Transformer.UpdateResult.Recreate;