diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts index 3b43345da9f478baad3915fe9528470f4820863f..fb96eee073b6de2fdac2b40dfd7c6a5844f2fa39 100644 --- a/src/mol-util/param-definition.ts +++ b/src/mol-util/param-definition.ts @@ -6,7 +6,7 @@ */ import { Color as ColorData } from './color'; -import { shallowClone, shallowEqual } from 'mol-util'; +import { shallowEqual } from 'mol-util'; import { Vec2 } from 'mol-math/linear-algebra'; import { deepClone } from './object'; @@ -16,6 +16,13 @@ export namespace ParamDefinition { description?: string } + 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; + return param; + } + export interface Base<T> extends Info { defaultValue: T } @@ -23,8 +30,8 @@ export namespace ParamDefinition { export interface Value<T> extends Base<T> { type: 'value' } - export function Value<T>(defaultValue: T, info: Info = {}): Value<T> { - return { type: 'value', defaultValue, ...info } + export function Value<T>(defaultValue: T, info?: Info): Value<T> { + return setInfo<Value<T>>({ type: 'value', defaultValue }, info); } export interface Select<T extends string> extends Base<T> { @@ -32,8 +39,8 @@ export namespace ParamDefinition { /** array of (value, label) tuples */ options: [T, string][] } - export function Select<T extends string>(defaultValue: T, options: [T, string][], info: Info = {}): Select<T> { - return { type: 'select', defaultValue, options, ...info } + export function Select<T extends string>(defaultValue: T, options: [T, string][], info?: Info): Select<T> { + return setInfo<Select<T>>({ type: 'select', defaultValue, options }, info) } export interface MultiSelect<E extends string, T = E[]> extends Base<T> { @@ -41,29 +48,29 @@ export namespace ParamDefinition { /** array of (value, label) tuples */ options: [E, string][] } - export function MultiSelect<E extends string, T = E[]>(defaultValue: T, options: [E, string][], info: Info = {}): MultiSelect<E, T> { - return { type: 'multi-select', defaultValue, options, ...info } + export function MultiSelect<E extends string, T = E[]>(defaultValue: T, options: [E, string][], info?: Info): MultiSelect<E, T> { + return setInfo<MultiSelect<E, T>>({ type: 'multi-select', defaultValue, options }, info) } export interface Boolean extends Base<boolean> { type: 'boolean' } - export function Boolean(defaultValue: boolean, info: Info = {}): Boolean { - return { type: 'boolean', defaultValue, ...info } + export function Boolean(defaultValue: boolean, info?: Info): Boolean { + return setInfo<Boolean>({ type: 'boolean', defaultValue }, info) } export interface Text extends Base<string> { type: 'text' } - export function Text(defaultValue: string = '', info: Info = {}): Text { - return { type: 'text', defaultValue, ...info } + export function Text(defaultValue: string = '', info?: Info): Text { + return setInfo<Text>({ type: 'text', defaultValue }, info) } export interface Color extends Base<ColorData> { type: 'color' } - export function Color(defaultValue: ColorData, info: Info = {}): Color { - return { type: 'color', defaultValue, ...info } + export function Color(defaultValue: ColorData, info?: Info): Color { + return setInfo<Color>({ type: 'color', defaultValue }, info) } export interface Numeric extends Base<number> { @@ -78,30 +85,37 @@ export namespace ParamDefinition { */ step?: number } - export function Numeric(defaultValue: number, range: { min?: number, max?: number, step?: number } = {}, info: Info = {}): Numeric { - return { type: 'number', defaultValue, ...range, ...info } + export function Numeric(defaultValue: number, range?: { min?: number, max?: number, step?: number }, info?: Info): Numeric { + return setInfo<Numeric>(setRange({ type: 'number', defaultValue }, range), info) + } + function setRange(p: Numeric, range?: { min?: number, max?: number, step?: number }) { + if (!range) return p; + if (typeof range.min !== 'undefined') p.min = range.min; + if (typeof range.max !== 'undefined') p.max = range.max; + if (typeof range.step !== 'undefined') p.step = range.step; + return p; } export interface Interval extends Base<[number, number]> { type: 'interval' } - export function Interval(defaultValue: [number, number], info: Info = {}): Interval { - return { type: 'interval', defaultValue, ...info } + export function Interval(defaultValue: [number, number], info?: Info): Interval { + return setInfo<Interval>({ type: 'interval', defaultValue }, info) } export interface LineGraph extends Base<Vec2[]> { type: 'line-graph' } - export function LineGraph(defaultValue: Vec2[], info: Info = {}): LineGraph { - return { type: 'line-graph', defaultValue, ...info } + export function LineGraph(defaultValue: Vec2[], info?: Info): LineGraph { + return setInfo<LineGraph>({ type: 'line-graph', defaultValue }, info) } export interface Group<T> extends Base<T> { type: 'group', params: Params } - export function Group<P extends Params>(params: P, info: Info = {}): Group<Values<P>> { - return { type: 'group', defaultValue: getDefaultValues(params) as any, params, ...info }; + export function Group<P extends Params>(params: P, info?: Info): Group<Values<P>> { + return setInfo<Group<Values<P>>>({ type: 'group', defaultValue: getDefaultValues(params) as any, params }, info); } export interface NamedParams<T = any> { name: string, params: T } @@ -110,25 +124,24 @@ export namespace ParamDefinition { select: Select<string>, map(name: string): Any } - export function Mapped<T>(defaultKey: string, names: [string, string][], map: Mapped<T>['map'], info: Info = {}): Mapped<T> { - return { + export function Mapped<T>(defaultKey: string, names: [string, string][], map: Mapped<T>['map'], info?: Info): Mapped<T> { + return setInfo<Mapped<T>>({ type: 'mapped', defaultValue: { name: defaultKey, params: map(defaultKey).defaultValue as any }, select: Select<string>(defaultKey, names, info), - map - }; + map }, info); } - export interface Converted<T, C> extends Base<C> { + export interface Converted<T, C> extends Base<T> { type: 'converted', - param: Base<C>, + convertedControl: Any, /** converts from prop value to display value */ fromValue(v: T): C, /** converts from display value to prop value */ toValue(v: C): T } - export function Converted<T, C>(param: Base<C>, fromValue: Converted<T, C>['fromValue'], toValue: Converted<T, C>['toValue']): Converted<T, C> { - return { type: 'converted', param, defaultValue: param.defaultValue, fromValue, toValue, label: param.label, description: param.description }; + export function Converted<T, C extends Any>(defaultValue: T, convertedControl: C, fromValue: (v: T) => C, toValue: (v: C) => T, info?: Info): Converted<T, C> { + return setInfo<Converted<T, C>>({ type: 'converted', defaultValue, convertedControl, fromValue, toValue }, info); } export type Any = Value<any> | Select<any> | MultiSelect<any> | Boolean | Text | Color | Numeric | Interval | LineGraph | Group<any> | Mapped<any> | Converted<any, any>