Преглед изворни кода

mol-plugin-ui: ActionMenu helpers

David Sehnal пре 5 година
родитељ
комит
d735dcdc3e

+ 1 - 1
src/apps/state-docs/pd-to-md.ts

@@ -39,7 +39,7 @@ function paramInfo(param: PD.Any, offset: number): string {
     }
 }
 
-function oToS(options: readonly (readonly [string, string] | [string, string, string])[]) {
+function oToS(options: readonly (readonly [string, string] | readonly [string, string, string])[]) {
     return options.map(o => `'${o[0]}'`).join(', ');
 }
 

+ 27 - 26
src/mol-plugin-ui/controls/action-menu.tsx

@@ -41,23 +41,24 @@ export namespace ActionMenu {
         return { label, value: iconOrValue };
     }
 
-    function createSpecFromSelectParamSimple(param: ParamDefinition.Select<any>) {
-        const items: Item[] = [];
-        for (const [v, l] of param.options) {
-            items.push(ActionMenu.Item(l, v));
-        }
-        return items as Items;
-    }
+    export function createItems<T>(xs: ArrayLike<T>, options?: { label?: (t: T) => string, value?: (t: T) => any, category?: (t: T) => string | undefined }) {
+        const { label, value, category } = options || { };
+        let cats: Map<string, (ActionMenu.Item | string)[]> | undefined = void 0;
+        const items: (ActionMenu.Item | (ActionMenu.Item | string)[] | string)[] = [];
+        for (let i = 0; i < xs.length; i++) {
+            const x = xs[i];
+
+            const catName = category?.(x);
+            const l = label ? label(x) : '' + x;
+            const v = value ? value(x) : x;
 
-    function createSpecFromSelectParamCategories(param: ParamDefinition.Select<any>) {
-        const cats = new Map<string, (Item | string)[]>();
-        const items: (Item | (Item | string)[] | string)[] = [];
-        for (const [v, l, c] of param.options) {
-            if (!!c) {
-                let cat = cats.get(c);
+            if (!!catName) {
+                if (!cats) cats = new Map<string, (ActionMenu.Item | string)[]>();
+
+                let cat = cats.get(catName);
                 if (!cat) {
-                    cat = [c];
-                    cats.set(c, cat);
+                    cat = [catName];
+                    cats.set(catName, cat);
                     items.push(cat);
                 }
                 cat.push(ActionMenu.Item(l, v));
@@ -65,21 +66,21 @@ export namespace ActionMenu {
                 items.push(ActionMenu.Item(l, v));
             }
         }
-        return items as Items;
+        return items as ActionMenu.Items;
     }
+    
+    type Opt = ParamDefinition.Select<any>['options'][0];
+    const _selectOptions = { value: (o: Opt) => o[0], label: (o: Opt) => o[1], category: (o: Opt) => o[2] };
 
-    export function createSpecFromSelectParam(param: ParamDefinition.Select<any>) {
-        for (const o of param.options) {
-            if (!!o[2]) return createSpecFromSelectParamCategories(param);
-        }
-        return createSpecFromSelectParamSimple(param);
+    export function createItemsFromSelectParam(param: ParamDefinition.Select<any>) {
+        return createItems(param.options, _selectOptions);
     }
 
-    export function findCurrent(items: Items, value: any): Item | undefined {
+    export function findItem(items: Items, value: any): Item | undefined {
         if (typeof items === 'string') return;
         if (isItem(items)) return items.value === value ? items : void 0;
         for (const s of items) {
-            const found = findCurrent(s, value);
+            const found = findItem(s, value);
             if (found) return found;
         }
     }
@@ -101,7 +102,7 @@ class Section extends React.PureComponent<SectionProps, SectionState> {
     state = {
         items: this.props.items,
         current: this.props.current,
-        isExpanded: !!this.props.current && !!ActionMenu.findCurrent(this.props.items, this.props.current.value)
+        isExpanded: !!this.props.current && !!ActionMenu.findItem(this.props.items, this.props.current.value)
     }
 
     toggleExpanded = (e: React.MouseEvent<HTMLButtonElement>) => {
@@ -111,7 +112,7 @@ class Section extends React.PureComponent<SectionProps, SectionState> {
 
     static getDerivedStateFromProps(props: SectionProps, state: SectionState) {
         if (props.items === state.items && props.current === state.current) return null;
-        return { items: props.items, current: props.current, isExpanded: props.current && !!ActionMenu.findCurrent(props.items, props.current.value) }
+        return { items: props.items, current: props.current, isExpanded: props.current && !!ActionMenu.findItem(props.items, props.current.value) }
     }
 
     render() {
@@ -120,7 +121,7 @@ class Section extends React.PureComponent<SectionProps, SectionState> {
         if (typeof items === 'string') return null;
         if (isItem(items)) return <Action item={items} onSelect={onSelect} current={current} />
 
-        const hasCurrent = header && current && !!ActionMenu.findCurrent(items, current.value)
+        const hasCurrent = header && current && !!ActionMenu.findItem(items, current.value)
 
         return <div>
             {header && <div className='msp-control-group-header' style={{ marginTop: '1px' }}>

+ 6 - 5
src/mol-plugin-ui/controls/parameters.tsx

@@ -345,16 +345,17 @@ export class SelectControl extends React.PureComponent<ParamProps<PD.Select<stri
 
     toggle = () => this.setState({ showOptions: !this.state.showOptions });
 
-    items = memoizeLatest((param: PD.Select<any>) => ActionMenu.createSpecFromSelectParam(param));
+    items = memoizeLatest((param: PD.Select<any>) => ActionMenu.createItemsFromSelectParam(param));
 
     renderControl() {
         const items = this.items(this.props.param);
-        const current = this.props.value !== undefined ? ActionMenu.findCurrent(items, this.props.value) : void 0;
+        const current = this.props.value !== undefined ? ActionMenu.findItem(items, this.props.value) : void 0;
         const label = current
             ? current.label
             : typeof this.props.value === 'undefined'
-                ? `${ActionMenu.getFirstItem(items)?.label || ''} [Default]`
-                : `[Invalid] ${this.props.value}`
+            ? `${ActionMenu.getFirstItem(items)?.label || ''} [Default]`
+            : `[Invalid] ${this.props.value}`;
+        
         return <ToggleButton disabled={this.props.isDisabled} style={{ textAlign: 'left', overflow: 'hidden', textOverflow: 'ellipsis' }}
             label={label} title={label as string} toggle={this.toggle} isSelected={this.state.showOptions} />;
     }
@@ -363,7 +364,7 @@ export class SelectControl extends React.PureComponent<ParamProps<PD.Select<stri
         if (!this.state.showOptions) return null;
 
         const items = this.items(this.props.param);
-        const current = ActionMenu.findCurrent(items, this.props.value);
+        const current = ActionMenu.findItem(items, this.props.value);
 
         return <ActionMenu items={items} current={current} onSelect={this.onSelect} />;
     }

+ 4 - 20
src/mol-plugin-ui/structure/selection.tsx

@@ -17,26 +17,10 @@ import { StructureElement } from '../../mol-model/structure';
 import { ActionMenu } from '../controls/action-menu';
 import { ToggleButton } from '../controls/common';
 
-function createDefaultQueries() {
-    const cats = new Map<string, (ActionMenu.Item | string)[]>();
-    const items: (ActionMenu.Item | (ActionMenu.Item | string)[] | string)[] = [];
-    for (const q of StructureSelectionQueryList) {
-        if (!!q.category) {
-            let cat = cats.get(q.category);
-            if (!cat) {
-                cat = [q.category];
-                cats.set(q.category, cat);
-                items.push(cat);
-            }
-            cat.push(ActionMenu.Item(q.label, q));
-        } else {
-            items.push(ActionMenu.Item(q.label, q));
-        }
-    }
-    return items as ActionMenu.Items;
-}
-
-export const DefaultQueries = createDefaultQueries()
+export const DefaultQueries = ActionMenu.createItems(StructureSelectionQueryList, {
+    label: q => q.label,
+    category: q => q.category
+});
 
 const StructureSelectionParams = {
     granularity: Interactivity.Params.granularity,

+ 3 - 3
src/mol-util/param-definition.ts

@@ -65,9 +65,9 @@ export namespace ParamDefinition {
     export interface Select<T extends string | number> extends Base<T> {
         type: 'select'
         /** array of (value, label) tuples */
-        options: readonly (readonly [T, string] | [T, string, string])[]
+        options: readonly (readonly [T, string] | readonly [T, string, string])[]
     }
-    export function Select<T extends string | number>(defaultValue: T, options: readonly (readonly [T, string] | [T, string, string])[], info?: Info): Select<T> {
+    export function Select<T extends string | number>(defaultValue: T, options: readonly (readonly [T, string] | readonly [T, string, string])[], info?: Info): Select<T> {
         return setInfo<Select<T>>({ type: 'select', defaultValue: checkDefaultKey(defaultValue, options), options }, info)
     }
 
@@ -406,7 +406,7 @@ export namespace ParamDefinition {
         return ret;
     }
 
-    function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string] | [T, string, string])[]) {
+    function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string] | readonly [T, string, string])[]) {
         for (const o of options) {
             if (o[0] === k) return k;
         }