Browse Source

StateTransformer.dispose
- use in StructureRepresentation3D to release custom props

David Sehnal 5 years ago
parent
commit
b6112a914f

+ 1 - 1
src/mol-model-props/common/custom-element-property.ts

@@ -107,7 +107,7 @@ namespace CustomElementProperty {
             isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && !!modelProperty.get(ctx.structure.models[0]).value,
             ensureCustomProperties: {
                 attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? modelProperty.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(),
-                detach: (_, data: ThemeDataContext) => data.structure && data.structure.models[0].customProperties.reference(modelProperty.descriptor, false)
+                detach: (data: ThemeDataContext) => data.structure && data.structure.models[0].customProperties.reference(modelProperty.descriptor, false)
             }
         }
     }

+ 1 - 1
src/mol-model-props/computed/representations/interactions.ts

@@ -48,6 +48,6 @@ export const InteractionsRepresentationProvider = StructureRepresentationProvide
     isApplicable: (structure: Structure) => structure.elementCount > 0,
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, structure: Structure) => InteractionsProvider.attach(ctx, structure, void 0, true),
-        detach: (_, data) => InteractionsProvider.ref(data, false)
+        detach: (data) => InteractionsProvider.ref(data, false)
     }
 })

+ 1 - 1
src/mol-model-props/computed/themes/accessible-surface-area.ts

@@ -73,6 +73,6 @@ export const AccessibleSurfaceAreaColorThemeProvider: ColorTheme.Provider<Access
     isApplicable: (ctx: ThemeDataContext) => !!ctx.structure,
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? AccessibleSurfaceAreaProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.customPropertyDescriptors.reference(AccessibleSurfaceAreaProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(AccessibleSurfaceAreaProvider.descriptor, false)
     }
 }

+ 1 - 1
src/mol-model-props/computed/themes/interaction-type.ts

@@ -116,6 +116,6 @@ export const InteractionTypeColorThemeProvider: ColorTheme.Provider<InteractionT
     isApplicable: (ctx: ThemeDataContext) => !!ctx.structure,
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? InteractionsProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.customPropertyDescriptors.reference(InteractionsProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(InteractionsProvider.descriptor, false)
     }
 }

+ 1 - 1
src/mol-model-props/integrative/cross-link-restraint/color.ts

@@ -70,6 +70,6 @@ export const CrossLinkColorThemeProvider: ColorTheme.Provider<CrossLinkColorThem
     isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && CrossLinkRestraint.isApplicable(ctx.structure),
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? CrossLinkRestraintProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.customPropertyDescriptors.reference(CrossLinkRestraintProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(CrossLinkRestraintProvider.descriptor, false)
     }
 }

+ 1 - 1
src/mol-model-props/integrative/cross-link-restraint/representation.ts

@@ -144,6 +144,6 @@ export const CrossLinkRestraintRepresentationProvider = StructureRepresentationP
     isApplicable: (structure: Structure) => CrossLinkRestraint.isApplicable(structure),
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, structure: Structure) => CrossLinkRestraintProvider.attach(ctx, structure, void 0, true),
-        detach: (_, data) => CrossLinkRestraintProvider.ref(data, false)
+        detach: (data) => CrossLinkRestraintProvider.ref(data, false)
     }
 })

+ 1 - 1
src/mol-model-props/pdbe/themes/structure-quality-report.ts

@@ -105,6 +105,6 @@ export const StructureQualityReportColorThemeProvider: ColorTheme.Provider<Param
     isApplicable: (ctx: ThemeDataContext) => StructureQualityReport.isApplicable(ctx.structure?.models[0]),
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? StructureQualityReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.models[0].customProperties.reference(StructureQualityReportProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.models[0].customProperties.reference(StructureQualityReportProvider.descriptor, false)
     }
 }

+ 1 - 1
src/mol-model-props/rcsb/representations/validation-report-clashes.ts

@@ -289,6 +289,6 @@ export const ClashesRepresentationProvider = StructureRepresentationProvider({
     isApplicable: (structure: Structure) => structure.elementCount > 0,
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, structure: Structure) => ClashesProvider.attach(ctx, structure, void 0, true),
-        detach: (_, data) => ClashesProvider.ref(data, false)
+        detach: (data) => ClashesProvider.ref(data, false)
     }
 })

+ 1 - 1
src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts

@@ -99,6 +99,6 @@ export const AssemblySymmetryClusterColorThemeProvider: ColorTheme.Provider<Asse
     isApplicable: (ctx: ThemeDataContext) => AssemblySymmetry.isApplicable(ctx.structure),
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? AssemblySymmetryProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.customPropertyDescriptors.reference(AssemblySymmetryProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(AssemblySymmetryProvider.descriptor, false)
     }
 }

+ 1 - 1
src/mol-model-props/rcsb/themes/density-fit.ts

@@ -70,6 +70,6 @@ export const DensityFitColorThemeProvider: ColorTheme.Provider<{}, ValidationRep
     isApplicable: (ctx: ThemeDataContext) => ValidationReport.isApplicable(ctx.structure?.models[0]),
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? ValidationReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false)
     }
 }

+ 1 - 1
src/mol-model-props/rcsb/themes/geometry-quality.ts

@@ -110,6 +110,6 @@ export const GeometryQualityColorThemeProvider: ColorTheme.Provider<GeometricQua
     isApplicable: (ctx: ThemeDataContext) => ValidationReport.isApplicable(ctx.structure?.models[0]),
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? ValidationReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false)
     }
 }

+ 1 - 1
src/mol-model-props/rcsb/themes/random-coil-index.ts

@@ -61,6 +61,6 @@ export const RandomCoilIndexColorThemeProvider: ColorTheme.Provider<{}, Validati
     isApplicable: (ctx: ThemeDataContext) => ValidationReport.isApplicable(ctx.structure?.models[0]),
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? ValidationReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false)
+        detach: (data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false)
     }
 }

+ 15 - 7
src/mol-plugin-state/transforms/representation.ts

@@ -136,18 +136,19 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({
 
             // TODO set initial state, repr.setState({})
             await repr.createOrUpdate(props, a.data).runInContext(ctx);
-            return new SO.Molecule.Structure.Representation3D({ repr, source: a } , { label: provider.label });
+            return new SO.Molecule.Structure.Representation3D({ repr, source: a }, { label: provider.label });
         });
     },
     update({ a, b, oldParams, newParams, cache }, plugin: PluginContext) {
         return Task.create('Structure Representation', async ctx => {
             const oldProvider = plugin.representation.structure.registry.get(oldParams.type.name);
-            const propertyCtx = { runtime: ctx, fetch: plugin.fetch }
-            if (oldProvider.ensureCustomProperties) oldProvider.ensureCustomProperties.detach(propertyCtx, a.data);
-            Theme.releaseDependencies(propertyCtx, plugin.representation.structure.themes, { structure: a.data }, oldParams);
+            if (oldProvider.ensureCustomProperties) oldProvider.ensureCustomProperties.detach(a.data);
+            Theme.releaseDependencies(plugin.representation.structure.themes, { structure: a.data }, oldParams);
 
             if (newParams.type.name !== oldParams.type.name) return StateTransformer.UpdateResult.Recreate;
+
             const provider = plugin.representation.structure.registry.get(newParams.type.name)
+            const propertyCtx = { runtime: ctx, fetch: plugin.fetch }
             if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data)
             const props = { ...b.data.repr.props, ...newParams.type.params }
             await Theme.ensureDependencies(propertyCtx, plugin.representation.structure.themes, { structure: a.data }, newParams)
@@ -164,6 +165,14 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({
             return StateTransformer.UpdateResult.Updated;
         });
     },
+    dispose({ b, params }, plugin: PluginContext) {
+        if (!b || !params) return;
+
+        const structure = b.data.source.data;
+        const provider = plugin.representation.structure.registry.get(params.type.name);
+        if (provider.ensureCustomProperties) provider.ensureCustomProperties.detach(structure);
+        Theme.releaseDependencies(plugin.representation.structure.themes, { structure }, params);
+    },
     interpolate(src, tar, t) {
         if (src.colorTheme.name !== 'uniform' || tar.colorTheme.name !== 'uniform') {
             return t <= 0.5 ? src : tar;
@@ -475,7 +484,7 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({
                 type: PD.Mapped<any>(
                     registry.default.name,
                     registry.types,
-                    name => PD.Group<any>(registry.get(name).getParams(themeCtx, VolumeData.One ))),
+                    name => PD.Group<any>(registry.get(name).getParams(themeCtx, VolumeData.One))),
                 colorTheme: PD.Mapped<any>(
                     type.defaultColorTheme.name,
                     themeCtx.colorThemeRegistry.types,
@@ -530,8 +539,7 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({
             if (newParams.type.name !== oldParams.type.name) {
                 const oldProvider = plugin.representation.volume.registry.get(oldParams.type.name);
                 if (oldProvider.ensureCustomProperties) {
-                    const propertyCtx = { runtime: ctx, fetch: plugin.fetch }
-                    oldProvider.ensureCustomProperties.detach(propertyCtx, a.data)
+                    oldProvider.ensureCustomProperties.detach(a.data)
                 }
                 return StateTransformer.UpdateResult.Recreate;
             }

+ 1 - 1
src/mol-repr/representation.ts

@@ -51,7 +51,7 @@ export interface RepresentationProvider<D = any, P extends PD.Params = any, S ex
     readonly isApplicable: (data: D) => boolean
     readonly ensureCustomProperties?: {
         attach: (ctx: CustomProperty.Context, data: D) => Promise<void>,
-        detach: (ctx: CustomProperty.Context, data: D) => void
+        detach: (data: D) => void
     }
 }
 

+ 1 - 1
src/mol-repr/structure/representation/cartoon.ts

@@ -67,6 +67,6 @@ export const CartoonRepresentationProvider = StructureRepresentationProvider({
     isApplicable: (structure: Structure) => structure.polymerResidueCount > 0,
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, structure: Structure) => SecondaryStructureProvider.attach(ctx, structure, void 0, true),
-        detach: (_, data) => SecondaryStructureProvider.ref(data, false)
+        detach: (data) => SecondaryStructureProvider.ref(data, false)
     }
 })

+ 5 - 0
src/mol-state/state.ts

@@ -442,6 +442,11 @@ async function update(ctx: UpdateContext) {
             ctx.parent.setCurrent(newCurrent);
         }
 
+        for (let i = deletes.length - 1; i >= 0; i--) {
+            const cell = ctx.cells.get(deletes[i]);
+            cell?.transform.transformer.definition.dispose?.({ b: cell.obj, params: cell.transform.params, cache: cell.cache }, ctx.parent.globalContext);
+        }
+
         for (const d of deletes) {
             const cell = ctx.cells.get(d);
             if (cell) unlinkCell(cell);

+ 9 - 0
src/mol-state/transformer.ts

@@ -66,6 +66,12 @@ namespace Transformer {
         newParams: P
     }
 
+    export interface DisposeParams<B extends StateObject = StateObject, P extends {} = {}> {
+        b: B | undefined,
+        params: P | undefined,
+        cache: unknown
+    }
+
     export enum UpdateResult { Unchanged, Updated, Recreate, Null }
 
     /** Specify default control descriptors for the parameters */
@@ -97,6 +103,9 @@ namespace Transformer {
         /** Parameter interpolation */
         interpolate?(src: P, target: P, t: number, globalCtx: unknown): P
 
+        /** Cleanup resources */
+        dispose?(params: DisposeParams<B, P>, globalCtx: unknown): void
+
         /** Custom conversion to and from JSON */
         readonly customSerialization?: { toJSON(params: P, obj?: B): any, fromJSON(data: any): P }
     }

+ 2 - 2
src/mol-theme/color/secondary-structure.ts

@@ -121,6 +121,6 @@ export const SecondaryStructureColorThemeProvider: ColorTheme.Provider<Secondary
     isApplicable: (ctx: ThemeDataContext) => !!ctx.structure,
     ensureCustomProperties: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? SecondaryStructureProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(),
-        detach: (_, data) => data.structure && data.structure.customPropertyDescriptors.reference(SecondaryStructureProvider.descriptor, false)
-    }    
+        detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(SecondaryStructureProvider.descriptor, false)
+    }
 }

+ 4 - 4
src/mol-theme/theme.ts

@@ -57,9 +57,9 @@ namespace Theme {
         await theme.sizeThemeRegistry.get(props.sizeTheme.name).ensureCustomProperties?.attach(ctx, data)
     }
 
-    export function releaseDependencies(ctx: CustomProperty.Context, theme: ThemeRegistryContext, data: ThemeDataContext, props: Props) {
-        theme.colorThemeRegistry.get(props.colorTheme.name).ensureCustomProperties?.detach(ctx, data)
-        theme.sizeThemeRegistry.get(props.sizeTheme.name).ensureCustomProperties?.detach(ctx, data)
+    export function releaseDependencies(theme: ThemeRegistryContext, data: ThemeDataContext, props: Props) {
+        theme.colorThemeRegistry.get(props.colorTheme.name).ensureCustomProperties?.detach(data)
+        theme.sizeThemeRegistry.get(props.sizeTheme.name).ensureCustomProperties?.detach(data)
     }
 }
 
@@ -75,7 +75,7 @@ export interface ThemeProvider<T extends ColorTheme<P> | SizeTheme<P>, P extends
     readonly isApplicable: (ctx: ThemeDataContext) => boolean
     readonly ensureCustomProperties?: {
         attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => Promise<void>,
-        detach: (ctx: CustomProperty.Context, data: ThemeDataContext) => void
+        detach: (data: ThemeDataContext) => void
     }
 }