Browse Source

mol-state & plugin: transform auto-update support

David Sehnal 6 years ago
parent
commit
96595fa874

+ 1 - 1
src/mol-plugin/skin/base/components/controls-base.scss

@@ -90,7 +90,7 @@
     -webkit-appearance: none;
     -moz-appearance: none;
     appearance: none;    
-    box-shadow: none; //  !important;
+    box-shadow: none !important;
     
     &:hover {
         color: $hover-font-color;

+ 4 - 0
src/mol-plugin/state/transforms/representation.ts

@@ -44,6 +44,10 @@ const StructureRepresentation3D = PluginStateTransform.Create<SO.Molecule.Struct
             name => PD.Group<any>(ctx.structureRepresentation.themeCtx.sizeThemeRegistry.get(name).getParams({ structure: a.data }))
         ),
     }),
+    canAutoUpdate({ oldParams, newParams }) {
+        // TODO: allow for small molecules
+        return oldParams.type.name === newParams.type.name;
+    },
     apply({ a, params }, plugin: PluginContext) {
         return Task.create('Structure Representation', async ctx => {
             const provider = plugin.structureRepresentation.registry.get(params.type.name)

+ 1 - 0
src/mol-plugin/ui/state/apply-action.tsx

@@ -44,6 +44,7 @@ class ApplyActionContol extends TransformContolBase<ApplyActionContol.Props, App
     getHeader() { return this.props.action.definition.display; }
     getHeaderFallback() { return this.props.action.id; }
     canApply() { return !this.state.error && !this.state.busy; }
+    canAutoApply() { return false; }
     applyText() { return 'Apply'; }
     isUpdate() { return false; }
 

+ 15 - 1
src/mol-plugin/ui/state/common.tsx

@@ -101,6 +101,7 @@ abstract class TransformContolBase<P, S extends TransformContolBase.ControlState
     abstract getHeader(): Transformer.Definition['display'];
     abstract getHeaderFallback(): string;
     abstract canApply(): boolean;
+    abstract canAutoApply(newParams: any): boolean;
     abstract applyText(): string;
     abstract isUpdate(): boolean;
     abstract state: S;
@@ -112,12 +113,25 @@ abstract class TransformContolBase<P, S extends TransformContolBase.ControlState
         this.apply();
     }
 
+    private autoApplyHandle: number | undefined = void 0;
+
     events: StateTransformParameters.Props['events'] = {
         onEnter: this.onEnter,
-        onChange: (params, isInitial, errors) => this.setState({ params, isInitial, error: errors && errors[0] })
+        onChange: (params, isInitial, errors) => {
+            this.setState({ params, isInitial, error: errors && errors[0] }, () => {
+                if (!isInitial && !this.state.error && this.canAutoApply(params)) {
+                    if (this.autoApplyHandle) clearTimeout(this.autoApplyHandle);
+                    this.autoApplyHandle = setTimeout(this.apply, 50) as any as number;
+                }
+            });
+        }
     }
 
     apply = async () => {
+        if (this.autoApplyHandle !== void 0) {
+            clearTimeout(this.autoApplyHandle);
+            this.autoApplyHandle = void 0;
+        }
         this.setState({ busy: true });
         try {
             await this.applyAction();

+ 12 - 0
src/mol-plugin/ui/state/update-transform.tsx

@@ -34,6 +34,18 @@ class UpdateTransformContol extends TransformContolBase<UpdateTransformContol.Pr
     applyText() { return this.canApply() ? 'Update' : 'Nothing to Update'; }
     isUpdate() { return true; }
 
+    canAutoApply(newParams: any) {
+        const autoUpdate = this.props.transform.transformer.definition.canAutoUpdate
+        if (!autoUpdate) return false;
+
+        const { state } = this.props;
+        const cell = state.cells.get(this.props.transform.ref);
+        if (!cell || !cell.sourceRef || cell.status !== 'ok') return false;
+        const parentCell = state.cells.get(cell.sourceRef)!;
+
+        return autoUpdate({ a: cell.obj!, b: parentCell.obj!, oldParams: this.props.transform.params, newParams }, this.plugin);
+    }
+
     private _getInfo = memoizeOne((t: Transform) => StateTransformParameters.infoFromTransform(this.plugin, this.props.state, this.props.transform));
 
     state: UpdateTransformContol.ComponentState = { transform: this.props.transform, error: void 0, isInitial: true, params: this.getInfo().initialValues, busy: false };

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

@@ -44,6 +44,13 @@ export namespace Transformer {
         cache: unknown
     }
 
+    export interface AutoUpdateParams<A extends StateObject = StateObject, B extends StateObject = StateObject, P extends {} = {}> {
+        a: A,
+        b: B,
+        oldParams: P,
+        newParams: P
+    }
+
     export enum UpdateResult { Unchanged, Updated, Recreate }
 
     /** Specify default control descriptors for the parameters */
@@ -68,6 +75,9 @@ export namespace Transformer {
          */
         update?(params: UpdateParams<A, B, P>, globalCtx: unknown): Task<UpdateResult> | UpdateResult,
 
+        /** Determine if the transformer can be applied automatically on UI change. Default is false. */
+        canAutoUpdate?(params: AutoUpdateParams<A, B, P>, globalCtx: unknown): boolean,
+
         params?(a: A, globalCtx: unknown): { [K in keyof P]: PD.Any },
 
         /** Test if the transform can be applied to a given node */