Bladeren bron

mol-state: Action builder

David Sehnal 6 jaren geleden
bovenliggende
commit
31a26f259f
3 gewijzigde bestanden met toevoegingen van 59 en 17 verwijderingen
  1. 13 11
      src/mol-plugin/state/actions/basic.ts
  2. 45 4
      src/mol-state/action.ts
  3. 1 2
      src/mol-util/param-definition.ts

+ 13 - 11
src/mol-plugin/state/actions/basic.ts

@@ -81,13 +81,14 @@ const DownloadStructure = StateAction.create<PluginStateObject.Root, void, Downl
     }
 });
 
-export const OpenStructure = StateAction.create<PluginStateObject.Root, void, { file: File }>({
-    from: [PluginStateObject.Root],
+export const OpenStructure = StateAction.build({
+    from: PluginStateObject.Root,
+    params: { file: PD.File({ accept: '.cif,.bcif' }) }
+})({
     display: {
         name: 'Open Structure',
         description: 'Load a structure from file and create its default Assembly and visual'
     },
-    params: () => ({ file: PD.File({ accept: '.cif,.bcif' }) }),
     apply({ params, state }) {
         const b = state.build();
         const data = b.toRoot().apply(StateTransforms.Data.ReadFile, { file: params.file, isBinary: /\.bcif$/i.test(params.file.name) });
@@ -130,8 +131,9 @@ function complexRepresentation(root: StateTreeBuilder.To<PluginStateObject.Molec
         // TODO: create spheres visual
 }
 
-export const CreateComplexRepresentation = StateAction.create<PluginStateObject.Molecule.Structure, void, {}>({
-    from: [PluginStateObject.Molecule.Structure],
+export const CreateComplexRepresentation = StateAction.build({
+    from: PluginStateObject.Molecule.Structure
+})({
     display: {
         name: 'Create Complex',
         description: 'Split the structure into Sequence/Water/Ligands/... '
@@ -143,15 +145,15 @@ export const CreateComplexRepresentation = StateAction.create<PluginStateObject.
     }
 });
 
-export const UpdateTrajectory = StateAction.create<PluginStateObject.Root, void, { action: 'advance' | 'reset', by?: number }>({
-    from: [],
+export const UpdateTrajectory = StateAction.build({
+    params: () => ({
+        action: PD.Select<'advance' | 'reset'>('advance', [['advance', 'Advance'], ['reset', 'Reset']]),
+        by: PD.makeOptional(PD.Numeric(1, { min: -1, max: 1, step: 1 }))
+    })
+})({
     display: {
         name: 'Update Trajectory'
     },
-    params: () => ({
-        action: PD.Select('advance', [['advance', 'Advance'], ['reset', 'Reset']]),
-        by: PD.Numeric(1, { min: -1, max: 1, step: 1 }, { isOptional: true })
-    }),
     apply({ params, state }) {
         const models = state.select(q => q.rootsOfType(PluginStateObject.Molecule.Model)
             .filter(c => c.transform.transformer === StateTransforms.Model.ModelFromTrajectory));

+ 45 - 4
src/mol-state/action.ts

@@ -38,8 +38,7 @@ namespace StateAction {
         params: P
     }
 
-    export interface Definition<A extends StateObject = StateObject, T = any, P extends {} = {}> {
-        readonly from: StateObject.Ctor[],
+    export interface DefinitionBase<A extends StateObject = StateObject, T = any, P extends {} = {}> {
         readonly display?: { readonly name: string, readonly description?: string },
 
         /**
@@ -47,12 +46,15 @@ namespace StateAction {
          */
         apply(params: ApplyParams<A, P>, globalCtx: unknown): T | Task<T>,
 
-        params?(a: A, globalCtx: unknown): { [K in keyof P]: PD.Any },
-
         /** Test if the transform can be applied to a given node */
         isApplicable?(a: A, globalCtx: unknown): boolean
     }
 
+    export interface Definition<A extends StateObject = StateObject, T = any, P extends {} = {}> extends DefinitionBase<A, T, P> {
+        readonly from: StateObject.Ctor[],
+        params?(a: A, globalCtx: unknown): { [K in keyof P]: PD.Any }
+    }
+
     export function create<A extends StateObject, T, P extends {} = {}>(definition: Definition<A, T, P>): StateAction<A, T, P> {
         const action: StateAction<A, T, P> = {
             create(params) { return { action, params }; },
@@ -74,4 +76,43 @@ namespace StateAction {
             }
         })
     }
+
+    export namespace Builder {
+        type ParamDefinition<P> = { [K in keyof P]-?: PD.Base<P[K]> }
+
+        export interface Type<A extends StateObject.Ctor, P extends { }> {
+            from?: A | A[],
+            params?: ParamDefinition<P> | ((a: StateObject.From<A>, globalCtx: any) => ParamDefinition<P>)
+        }
+
+        export interface Root {
+            <A extends StateObject.Ctor, P extends { }>(info: Type<A, P>): Define<StateObject.From<A>, Params<P>>
+        }
+
+        type Optionals<P> = { [K in keyof P]-?: undefined extends P[K] ? K : never }[keyof P]
+        type NonOptionals<P> = { [K in keyof P]-?: undefined extends P[K] ? never: K }[keyof P]
+        type Params<P> = Pick<P, NonOptionals<P>> & Partial<Pick<P, Optionals<P>>>
+
+        export interface Define<A extends StateObject, P> {
+            <T>(def: DefinitionBase<A, T, P>): StateAction<A, T, P>
+        }
+
+        function root(info: Type<any, any>): Define<any, any> {
+            return def => create({
+                from: info.from instanceof Array
+                    ? info.from
+                    : !!info.from ? [info.from] : [],
+                params: typeof info.params === 'object'
+                    ? () => info.params as any
+                    : !!info.params
+                    ? info.params as any
+                    : void 0,
+                ...def
+            });
+        }
+
+        export const build: Root = (info: any) => root(info);
+    }
+
+    export const build = Builder.build;
 }

+ 1 - 2
src/mol-util/param-definition.ts

@@ -15,19 +15,18 @@ export namespace ParamDefinition {
         label?: string,
         description?: string,
         isHidden?: boolean,
-        isOptional?: boolean,
     }
 
     function setInfo<T extends Info>(param: T, info?: Info): T {
         if (!info) return param;
         if (info.description) param.description = info.description;
         if (info.label) param.label = info.label;
-        if (info.isOptional) param.isOptional = info.isOptional;
         if (info.isHidden) param.isHidden = info.isHidden;
         return param;
     }
 
     export interface Base<T> extends Info {
+        isOptional?: boolean,
         defaultValue: T
     }