From 3dd1af3b384018c645821ecf6d182cb7a9f9c81e Mon Sep 17 00:00:00 2001
From: Alexander Rose <alex.rose@rcsb.org>
Date: Thu, 15 Nov 2018 09:50:28 -0800
Subject: [PATCH] wip, param label tweaks

---
 src/apps/canvas/component/viewport.tsx        |  1 +
 src/mol-app/component/parameter/boolean.tsx   |  3 ++-
 src/mol-app/component/parameter/color.tsx     |  3 ++-
 .../component/parameter/multi-select.tsx      |  5 ++--
 src/mol-app/component/parameter/number.tsx    |  3 ++-
 src/mol-app/component/parameter/select.tsx    |  3 ++-
 src/mol-app/component/parameter/text.tsx      |  3 ++-
 src/mol-app/component/parameters.tsx          | 24 ++++++++++++-------
 src/mol-plugin/ui/controls/parameters.tsx     | 24 ++++++++++++-------
 src/mol-util/param-definition.ts              | 12 +---------
 10 files changed, 45 insertions(+), 36 deletions(-)

diff --git a/src/apps/canvas/component/viewport.tsx b/src/apps/canvas/component/viewport.tsx
index 35c108815..ee2350261 100644
--- a/src/apps/canvas/component/viewport.tsx
+++ b/src/apps/canvas/component/viewport.tsx
@@ -158,6 +158,7 @@ export class Viewport extends React.Component<ViewportProps, ViewportState> {
                     </select>
                 </div>
                 <ColorParamComponent
+                    label={BackgroundColorParam.label || ''}
                     param={BackgroundColorParam}
                     value={this.state.backgroundColor}
                     onChange={value => {
diff --git a/src/mol-app/component/parameter/boolean.tsx b/src/mol-app/component/parameter/boolean.tsx
index 11f4f0bd1..c8eff666f 100644
--- a/src/mol-app/component/parameter/boolean.tsx
+++ b/src/mol-app/component/parameter/boolean.tsx
@@ -8,6 +8,7 @@ import * as React from 'react'
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 
 export interface BooleanParamComponentProps {
+    label: string
     param: PD.Boolean
     value: boolean
     onChange(v: boolean): void
@@ -29,7 +30,7 @@ export class BooleanParamComponent extends React.Component<BooleanParamComponent
 
     render() {
         return <div>
-            <span>{this.props.param.label} </span>
+            <span>{this.props.label} </span>
             <button onClick={e => this.onChange(!this.state.value) }>
                 {this.state.value ? 'Off' : 'On'}
             </button>
diff --git a/src/mol-app/component/parameter/color.tsx b/src/mol-app/component/parameter/color.tsx
index 496254a49..a5c08374c 100644
--- a/src/mol-app/component/parameter/color.tsx
+++ b/src/mol-app/component/parameter/color.tsx
@@ -10,6 +10,7 @@ import { ColorNames } from 'mol-util/color/tables';
 import { Color } from 'mol-util/color';
 
 export interface ColorParamComponentProps {
+    label: string
     param: PD.Color
     value: Color
     onChange(v: Color): void
@@ -31,7 +32,7 @@ export class ColorParamComponent extends React.Component<ColorParamComponentProp
 
     render() {
         return <div>
-            <span>{this.props.param.label} </span>
+            <span>{this.props.label} </span>
             <select value={this.state.value} onChange={e => this.onChange(Color(parseInt(e.target.value))) }>
                 {Object.keys(ColorNames).map(name => {
                     return <option key={name} value={(ColorNames as { [k: string]: Color})[name]}>{name}</option>
diff --git a/src/mol-app/component/parameter/multi-select.tsx b/src/mol-app/component/parameter/multi-select.tsx
index 26b3a767c..6db9c0c41 100644
--- a/src/mol-app/component/parameter/multi-select.tsx
+++ b/src/mol-app/component/parameter/multi-select.tsx
@@ -8,6 +8,7 @@ import * as React from 'react'
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 
 export interface MultiSelectParamComponentProps<T extends string> {
+    label: string
     param: PD.MultiSelect<T>
     value: T[]
     onChange(v: T[]): void
@@ -29,10 +30,10 @@ export class MultiSelectParamComponent<T extends string> extends React.Component
 
     render() {
         return <div>
-            <span>{this.props.param.label} </span>
+            <span>{this.props.label} </span>
             <select multiple value={this.state.value} onChange={e => {
                 const value = Array.from(e.target.options).filter(option => option.selected).map(option => option.value)
-                this.onChange(value as T[]) 
+                this.onChange(value as T[])
             }}>
                 {this.props.param.options.map(v => {
                     const [value, label] = v
diff --git a/src/mol-app/component/parameter/number.tsx b/src/mol-app/component/parameter/number.tsx
index 3ee613df7..f8509b18c 100644
--- a/src/mol-app/component/parameter/number.tsx
+++ b/src/mol-app/component/parameter/number.tsx
@@ -8,6 +8,7 @@ import * as React from 'react'
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 
 export interface NumberParamComponentProps {
+    label: string
     param: PD.Numeric
     value: number
     onChange(v: number): void
@@ -30,7 +31,7 @@ export class NumberParamComponent extends React.Component<NumberParamComponentPr
 
     render() {
         return <div>
-            <span>{this.props.param.label} </span>
+            <span>{this.props.label} </span>
             <input type='range'
                 value={this.state.value}
                 min={this.props.param.min}
diff --git a/src/mol-app/component/parameter/select.tsx b/src/mol-app/component/parameter/select.tsx
index 0af63a6c4..9a2ab105e 100644
--- a/src/mol-app/component/parameter/select.tsx
+++ b/src/mol-app/component/parameter/select.tsx
@@ -8,6 +8,7 @@ import * as React from 'react'
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 
 export interface SelectParamComponentProps<T extends string> {
+    label: string
     param: PD.Select<T>
     value: T
     onChange(v: T): void
@@ -29,7 +30,7 @@ export class SelectParamComponent<T extends string> extends React.Component<Sele
 
     render() {
         return <div>
-            <span>{this.props.param.label} </span>
+            <span>{this.props.label} </span>
             <select value={this.state.value} onChange={e => this.onChange(e.target.value as T) }>
                 {this.props.param.options.map(v => {
                     const [value, label] = v
diff --git a/src/mol-app/component/parameter/text.tsx b/src/mol-app/component/parameter/text.tsx
index aa00d7cb1..d07252794 100644
--- a/src/mol-app/component/parameter/text.tsx
+++ b/src/mol-app/component/parameter/text.tsx
@@ -8,6 +8,7 @@ import * as React from 'react'
 import { ParamDefinition as PD } from 'mol-util/param-definition';
 
 export interface TextParamComponentProps {
+    label: string
     param: PD.Text
     value: string
     onChange(v: string): void
@@ -29,7 +30,7 @@ export class TextParamComponent extends React.Component<TextParamComponentProps,
 
     render() {
         return <div>
-            <span>{this.props.param.label} </span>
+            <span>{this.props.label} </span>
             <input type='text'
                 value={this.state.value}
                 onChange={e => this.onChange(e.currentTarget.value)}
diff --git a/src/mol-app/component/parameters.tsx b/src/mol-app/component/parameters.tsx
index e493dd358..b719707ff 100644
--- a/src/mol-app/component/parameters.tsx
+++ b/src/mol-app/component/parameters.tsx
@@ -12,6 +12,7 @@ import { SelectParamComponent } from './parameter/select';
 import { MultiSelectParamComponent } from './parameter/multi-select';
 import { TextParamComponent } from './parameter/text';
 import { ColorParamComponent } from './parameter/color';
+import { camelCaseToWords } from 'mol-util/string';
 
 interface ParametersProps<P extends PD.Params> {
     params: P
@@ -21,24 +22,28 @@ interface ParametersProps<P extends PD.Params> {
 
 type ParametersState = {}
 
-function getParamComponent<P extends PD.Any>(p: PD.Any, value: P['defaultValue'], onChange: (v: P['defaultValue']) => void) {
-    switch (p.type) {
+function getParamComponent<P extends PD.Any>(label: string, param: PD.Any, value: P['defaultValue'], onChange: (v: P['defaultValue']) => void) {
+    switch (param.type) {
         case 'boolean':
-            return <BooleanParamComponent param={p} value={value} onChange={onChange} />
+            return <BooleanParamComponent label={label} param={param} value={value} onChange={onChange} />
         case 'number':
-            return <NumberParamComponent param={p} value={value} onChange={onChange} />
+            return <NumberParamComponent label={label} param={param} value={value} onChange={onChange} />
         case 'select':
-            return <SelectParamComponent param={p} value={value} onChange={onChange} />
+            return <SelectParamComponent label={label} param={param} value={value} onChange={onChange} />
         case 'multi-select':
-            return <MultiSelectParamComponent param={p} value={value} onChange={onChange} />
+            return <MultiSelectParamComponent label={label} param={param} value={value} onChange={onChange} />
         case 'text':
-            return <TextParamComponent param={p} value={value} onChange={onChange} />
+            return <TextParamComponent label={label} param={param} value={value} onChange={onChange} />
         case 'color':
-            return <ColorParamComponent param={p} value={value} onChange={onChange} />
+            return <ColorParamComponent label={label} param={param} value={value} onChange={onChange} />
     }
     return ''
 }
 
+function getLabel(name: string, param: PD.Base<any>) {
+    return param.label === undefined ? camelCaseToWords(name) : param.label
+}
+
 export class ParametersComponent<P extends PD.Params> extends React.Component<ParametersProps<P>, ParametersState> {
     onChange(k: string, value: any) {
         this.props.onChange(k, value)
@@ -49,8 +54,9 @@ export class ParametersComponent<P extends PD.Params> extends React.Component<Pa
             { Object.keys(this.props.params).map(k => {
                 const param = this.props.params[k]
                 const value = this.props.values[k]
+                const label = getLabel(k, param)
                 return <div key={k}>
-                    {getParamComponent(param, value, v => this.onChange(k, v))}
+                    {getParamComponent(label, param, value, v => this.onChange(k, v))}
                 </div>
             })}
         </div>;
diff --git a/src/mol-plugin/ui/controls/parameters.tsx b/src/mol-plugin/ui/controls/parameters.tsx
index 2ac820fcc..d8f21ed32 100644
--- a/src/mol-plugin/ui/controls/parameters.tsx
+++ b/src/mol-plugin/ui/controls/parameters.tsx
@@ -7,6 +7,7 @@
 
 import * as React from 'react'
 import { ParamDefinition as PD } from 'mol-util/param-definition';
+import { camelCaseToWords } from 'mol-util/string';
 
 export interface ParameterControlsProps<P extends PD.Params = PD.Params> {
     params: P,
@@ -57,6 +58,10 @@ export type ParamOnChange = (params: { param: PD.Base<any>, name: string, value:
 type ValueControlProps<P extends PD.Base<any> = PD.Base<any>> = { value: any, param: P, isEnabled?: boolean, onChange: (v: any) => void, onEnter?: () => void }
 type ValueControl = React.ComponentClass<ValueControlProps<any>>
 
+function getLabel(name: string, param: PD.Base<any>) {
+    return param.label === undefined ? camelCaseToWords(name) : param.label
+}
+
 export class ParamWrapper extends React.PureComponent<ParamWrapperProps> {
     onChange = (value: any) => {
         this.props.onChange({ param: this.props.param, name: this.props.name, value });
@@ -64,7 +69,7 @@ export class ParamWrapper extends React.PureComponent<ParamWrapperProps> {
 
     render() {
         return <div style={{ padding: '0 3px', borderBottom: '1px solid #ccc' }}>
-            <div style={{ lineHeight: '20px', float: 'left' }} title={this.props.param.description}>{this.props.param.label}</div>
+            <div style={{ lineHeight: '20px', float: 'left' }} title={this.props.param.description}>{getLabel(this.props.name, this.props.param)}</div>
             <div style={{ float: 'left', marginLeft: '5px' }}>
                 <this.props.control value={this.props.value} param={this.props.param} onChange={this.onChange} onEnter={this.props.onEnter} isEnabled={this.props.isEnabled} />
             </div>
@@ -140,16 +145,17 @@ export class SelectControl extends React.PureComponent<ValueControlProps<PD.Sele
 
 
 export class MultiSelectControl extends React.PureComponent<ValueControlProps<PD.MultiSelect<any>>> {
-    // onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
-    //     this.setState({ value: e.target.value });
-    //     this.props.onChange(e.target.value);
-    // }
+    onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
+        const value = Array.from(e.target.options).filter(option => option.selected).map(option => option.value);
+        this.setState({ value });
+        this.props.onChange(value);
+    }
 
     render() {
-        return <span>multiselect TODO</span>;
-        // return <select value={this.props.value || ''} onChange={this.onChange}>
-        //     {this.props.param.options.map(([value, label]) => <option key={label} value={value}>{label}</option>)}
-        // </select>;
+        // return <span>multiselect TODO</span>;
+        return <select multiple value={this.props.value || ''} onChange={this.onChange}>
+            {this.props.param.options.map(([value, label]) => <option key={label} value={value}>{label}</option>)}
+        </select>;
     }
 }
 
diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts
index 3b36bbd2a..c3faf8ca6 100644
--- a/src/mol-util/param-definition.ts
+++ b/src/mol-util/param-definition.ts
@@ -8,7 +8,6 @@
 import { Color as ColorData } from './color';
 import { shallowClone } from 'mol-util';
 import { Vec2 } from 'mol-math/linear-algebra';
-import { camelCaseToWords } from './string';
 
 export namespace ParamDefinition {
     export interface Info {
@@ -101,7 +100,7 @@ export namespace ParamDefinition {
         params: Params
     }
     export function Group<P extends Params>(params: P, info: Info = {}): Group<Values<P>> {
-        return { type: 'group', defaultValue: getDefaultValues(params) as any, params };
+        return { type: 'group', defaultValue: getDefaultValues(params) as any, params, ...info };
     }
 
     export interface Mapped<T> extends Base<{ name: string, params: T }> {
@@ -136,15 +135,6 @@ export namespace ParamDefinition {
         return d as Values<T>
     }
 
-    export function getLabels<T extends Params>(params: T) {
-        const d: { [k: string]: string } = {}
-        Object.keys(params).forEach(k => {
-            const label = params[k].label
-            d[k] = label === undefined ? camelCaseToWords(k) : label
-        })
-        return d as { [k in keyof T]: string }
-    }
-
     export function clone<P extends Params>(params: P): P {
         return shallowClone(params)
     }
-- 
GitLab