diff --git a/src/mol-app/component/color-theme.tsx b/src/mol-app/component/color-theme.tsx deleted file mode 100644 index a98f423fe3f590df91363083f7c24b8dad7b65cb..0000000000000000000000000000000000000000 --- a/src/mol-app/component/color-theme.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. - * - * @author Alexander Rose <alexander.rose@weirdbyte.de> - */ - -import * as React from 'react' -import { ColorTheme } from '../../mol-theme/color'; -import { Color } from '../../mol-util/color'; - -export interface ColorThemeComponentProps { - colorTheme: ColorTheme<any> -} - -export interface ColorThemeComponentState { - -} - -export class ColorThemeComponent extends React.Component<ColorThemeComponentProps, ColorThemeComponentState> { - state = { - - } - - render() { - const ct = this.props.colorTheme - return <div> - <span>Color Theme Info </span> - - {ct.description ? <div><i>{ct.description}</i></div> : ''} - { - ct.legend && ct.legend.kind === 'scale-legend' - ? <div - style={{ - width: '100%', - height: '30px', - background: `linear-gradient(to right, ${ct.legend.colors.map(c => Color.toStyle(c)).join(', ')})` - }} - > - <span style={{float: 'left', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.minLabel}</span> - <span style={{float: 'right', padding: '6px', color: 'white', fontWeight: 'bold', backgroundColor: 'rgba(0, 0, 0, 0.2)'}}>{ct.legend.maxLabel}</span> - </div> - : ct.legend && ct.legend.kind === 'table-legend' - ? <div> - {ct.legend.table.map((value, i) => { - const [name, color] = value - return <div key={i} style={{minWidth: '60px', marginRight: '5px', display: 'inline-block'}}> - <div style={{width: '30px', height: '20px', backgroundColor: Color.toStyle(color), display: 'inline-block'}}></div> - {name} - </div> - })} - </div> - : '' - } - </div>; - } -} \ No newline at end of file diff --git a/src/mol-model-props/common/custom-element-property.ts b/src/mol-model-props/common/custom-element-property.ts index 96e1725aea6b878e92d8a4e3f93e6021c8bd5995..e8c94d90516c4176479ce59f20d9442085282ba3 100644 --- a/src/mol-model-props/common/custom-element-property.ts +++ b/src/mol-model-props/common/custom-element-property.ts @@ -12,7 +12,7 @@ import { Task } from '../../mol-task'; import { ThemeDataContext, ThemeProvider } from '../../mol-theme/theme'; import { ColorTheme, LocationColor } from '../../mol-theme/color'; import { Color } from '../../mol-util/color'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend } from '../../mol-util/legend'; import { Loci } from '../../mol-model/loci'; import { OrderedSet } from '../../mol-data/int'; diff --git a/src/mol-model-props/pdbe/themes/structure-quality-report.ts b/src/mol-model-props/pdbe/themes/structure-quality-report.ts index f71be143439fd657a5134a812736e792d078b345..e7b474229291ee82cd4d86f3bfa2ba680cf8dc5e 100644 --- a/src/mol-model-props/pdbe/themes/structure-quality-report.ts +++ b/src/mol-model-props/pdbe/themes/structure-quality-report.ts @@ -10,7 +10,7 @@ import { StructureElement } from '../../../mol-model/structure'; import { ColorTheme, LocationColor } from '../../../mol-theme/color'; import { ThemeDataContext } from '../../../mol-theme/theme'; import { Color } from '../../../mol-util/color'; -import { TableLegend } from '../../../mol-util/color/lists'; +import { TableLegend } from '../../../mol-util/legend'; const ValidationColors = [ Color.fromRgb(170, 170, 170), // not applicable diff --git a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts index 565a01dc44936762ef0634c1a1b4afaf3150ba20..50215e718df8b8fe29a44b5f1b38d580378ccf21 100644 --- a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts +++ b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts @@ -12,10 +12,9 @@ import { AssemblySymmetry } from '../assembly-symmetry'; import { Color } from '../../../mol-util/color'; import { Unit, StructureElement, StructureProperties } from '../../../mol-model/structure'; import { Location } from '../../../mol-model/location'; -import { ScaleLegend } from '../../../mol-util/color/scale'; +import { ScaleLegend, TableLegend } from '../../../mol-util/legend'; import { getSymmetrySelectParam } from '../util'; import { getPalette, getPaletteParams } from '../../../mol-util/color/palette'; -import { TableLegend } from '../../../mol-util/color/lists'; const DefaultColor = Color(0xCCCCCC) diff --git a/src/mol-plugin/skin/base/components/controls.scss b/src/mol-plugin/skin/base/components/controls.scss index 5d40894a68651f05f19b55e03ec93e0ff64c08b7..367d6e783f7b7e05eb86eb949b5a82ea599898bf 100644 --- a/src/mol-plugin/skin/base/components/controls.scss +++ b/src/mol-plugin/skin/base/components/controls.scss @@ -302,5 +302,64 @@ > div { line-height: $row-height; text-align: center; + color: color-lower-contrast($font-color, 15%); + } +} + +.msp-help span { + display: none; +} + +.msp-help:hover span { + display: inline-block; + background: linear-gradient($default-background, change-color($default-background, $alpha: 0.5)); +} + +.msp-help-text { + height: auto !important; + + > div { + padding: ($control-spacing / 2) $control-spacing; + text-align: left; + color: color-lower-contrast($font-color, 15%); + } +} + +.msp-help-description { + font-style: italic; +} + +.msp-help-legend { + padding-top: $control-spacing; +} + +.msp-scale-legend { + > div { + width: 100%; + height: $control-spacing * 3; + + > span { + padding: $control-spacing / 2; + color: white; + font-weight: bold; + background-color: rgba(0, 0, 0, 0.2); + } + } +} + +.msp-table-legend { + > div { + // min-width: 60px; + margin-right: $control-spacing / 2; + display: inline-flex; + + .msp-table-legend-color { + width: $control-spacing * 3; + height: $control-spacing * 2; + } + + .msp-table-legend-text { + margin: 0 ($control-spacing / 2); + } } } \ No newline at end of file diff --git a/src/mol-plugin/skin/base/icons.scss b/src/mol-plugin/skin/base/icons.scss index 7c642ee711538fcf36bd3a881feb6d163d119e6f..49162eda4eb043fc06bee6c41b35a9f767c3afa0 100644 --- a/src/mol-plugin/skin/base/icons.scss +++ b/src/mol-plugin/skin/base/icons.scss @@ -4,45 +4,45 @@ font-style: normal; font-weight: normal; speak: none; - + display: inline-block; text-decoration: inherit; width: 1em; margin-right: .2em; text-align: center; /* opacity: .8; */ - + /* For safety - reset parent styles, that can break glyph codes*/ font-variant: normal; text-transform: none; - + /* fix buttons height, for twitter bootstrap */ line-height: 1em; - + /* Animation center compensation - margins should be symmetric */ /* remove if not needed */ margin-left: .2em; - + /* you can be more comfortable with increased icons size */ /* font-size: 120%; */ - + /* Font smoothing. That was taken from TWBS */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - + /* Uncomment for 3D effect */ /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ } -.msp-icon-expand-layout:before { +.msp-icon-expand-layout:before { content: "\e84a"; } -.msp-icon-plus:before { +.msp-icon-plus:before { content: "\e816"; } -.msp-icon-minus:before { +.msp-icon-minus:before { content: "\e819"; } @@ -50,19 +50,19 @@ content: "\e891"; } -.msp-icon-ok:before { +.msp-icon-ok:before { content: "\e812"; } -.msp-icon-back:before { +.msp-icon-back:before { content: "\e820"; } -.msp-icon-cross:before { +.msp-icon-cross:before { content: "\e868"; } -.msp-icon-off:before { +.msp-icon-off:before { content: "\e813"; } @@ -70,23 +70,23 @@ content: "\e885"; } -.msp-icon-collapse:before { +.msp-icon-collapse:before { content: "\e883"; } -.msp-icon-visual-visibility:before { +.msp-icon-visual-visibility:before { content: "\e826"; } -.msp-icon-abort:before { +.msp-icon-abort:before { content: "\e814"; } -.msp-icon-focus-on-visual:before { +.msp-icon-focus-on-visual:before { content: "\e8a3"; } -.msp-icon-settings:before { +.msp-icon-settings:before { content: "\e855"; } @@ -106,6 +106,10 @@ content: '\e81c' } +.msp-icon-help-circle:before { + content: '\e81d'; +} + .msp-icon-info:before { content: '\e81e' } @@ -126,18 +130,10 @@ content: '\e875' } -.msp-icon-screenshot:before { +.msp-icon-screenshot:before { content: "\e80f"; } -.msp-icon-help:before { - content: "\e81c"; -} - -.msp-icon-help-circle:before { - content: "\e81d"; -} - .msp-icon-model-prev:before { content: "\e884"; } diff --git a/src/mol-plugin/state/transforms/representation.ts b/src/mol-plugin/state/transforms/representation.ts index 5e993e95f558cd92084045e86a5b55b292b6ae79..4ba293a3ebbd06942a793b6b5b36fda206684e40 100644 --- a/src/mol-plugin/state/transforms/representation.ts +++ b/src/mol-plugin/state/transforms/representation.ts @@ -135,6 +135,15 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ const type = registry.get(registry.default.name); if (!a) { + const colorThemeInfo = { + help: (value: { name: string, params: {} }) => { + const { name, params } = value + const p = themeCtx.colorThemeRegistry.get(name) + const ct = p.factory({}, params) + return { description: ct.description, legend: ct.legend } + } + } + return { type: PD.Mapped<any>( registry.default.name, @@ -143,7 +152,8 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ colorTheme: PD.Mapped<any>( type.defaultColorTheme, themeCtx.colorThemeRegistry.types, - name => PD.Group<any>(themeCtx.colorThemeRegistry.get(name).getParams({ structure: Structure.Empty })) + name => PD.Group<any>(themeCtx.colorThemeRegistry.get(name).getParams({ structure: Structure.Empty })), + colorThemeInfo ), sizeTheme: PD.Mapped<any>( type.defaultSizeTheme, @@ -154,6 +164,15 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ } const dataCtx = { structure: a.data } + const colorThemeInfo = { + help: (value: { name: string, params: {} }) => { + const { name, params } = value + const p = themeCtx.colorThemeRegistry.get(name) + const ct = p.factory(dataCtx, params) + return { description: ct.description, legend: ct.legend } + } + } + return ({ type: PD.Mapped<any>( registry.default.name, @@ -162,7 +181,8 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ colorTheme: PD.Mapped<any>( type.defaultColorTheme, themeCtx.colorThemeRegistry.getApplicableTypes(dataCtx), - name => PD.Group<any>(themeCtx.colorThemeRegistry.get(name).getParams(dataCtx)) + name => PD.Group<any>(themeCtx.colorThemeRegistry.get(name).getParams(dataCtx)), + colorThemeInfo ), sizeTheme: PD.Mapped<any>( type.defaultSizeTheme, diff --git a/src/mol-plugin/ui/controls/legend.tsx b/src/mol-plugin/ui/controls/legend.tsx new file mode 100644 index 0000000000000000000000000000000000000000..93463cef9668aba9bc5932f28e23620305449efb --- /dev/null +++ b/src/mol-plugin/ui/controls/legend.tsx @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Color } from '../../../mol-util/color'; +import * as React from 'react'; +import { _Props, _State } from '../base'; +import { Legend as LegendData, ScaleLegend as ScaleLegendData, TableLegend as TableLegendData } from '../../../mol-util/legend'; + +export type LegendProps<L extends LegendData> = { legend: L } +export type Legend = React.ComponentClass<LegendProps<any>> + +export function legendFor(legend: LegendData): Legend | undefined { + switch (legend.kind) { + case 'scale-legend': return ScaleLegend + case 'table-legend': return TableLegend + default: + const _: never = legend; + console.warn(`${_} has no associated UI component`); + return void 0; + } +} + +export class ScaleLegend extends React.PureComponent<LegendProps<ScaleLegendData>> { + render() { + const { legend } = this.props + const colors = legend.colors.map(c => Color.toStyle(c)).join(', ') + return <div className='msp-scale-legend'> + <div style={{ background: `linear-gradient(to right, ${colors})` }}> + <span style={{float: 'left'}}>{legend.minLabel}</span> + <span style={{float: 'right'}}>{legend.maxLabel}</span> + </div> + </div> + } +} + +export class TableLegend extends React.PureComponent<LegendProps<TableLegendData>> { + render() { + const { legend } = this.props + return <div className='msp-table-legend'> + {legend.table.map((value, i) => { + const [name, color] = value + return <div key={i}> + <div className='msp-table-legend-color' style={{backgroundColor: Color.toStyle(color)}}></div> + <div className='msp-table-legend-text'>{name}</div> + </div> + })} + </div> + } +} \ No newline at end of file diff --git a/src/mol-plugin/ui/controls/parameters.tsx b/src/mol-plugin/ui/controls/parameters.tsx index fb373164cee802fa78321cbea798dd1ea168b029..58ffcae56db8367902441b597df5b21cf7047558 100644 --- a/src/mol-plugin/ui/controls/parameters.tsx +++ b/src/mol-plugin/ui/controls/parameters.tsx @@ -17,6 +17,8 @@ import LineGraphComponent from './line-graph/line-graph-component'; import { Slider, Slider2 } from './slider'; import { NumericInput, IconButton, ControlGroup } from './common'; import { _Props, _State } from '../base'; +import { legendFor } from './legend'; +import { Legend as LegendData } from '../../../mol-util/legend'; export interface ParameterControlsProps<P extends PD.Params = PD.Params> { params: P, @@ -73,13 +75,34 @@ function controlFor(param: PD.Any): ParamControl | undefined { } } -// type ParamWrapperProps = { name: string, value: any, param: PD.Base<any>, onChange: ParamOnChange, control: ValueControl, onEnter?: () => void, isEnabled?: boolean } +export class ParamHelp<L extends LegendData> extends React.PureComponent<{ legend?: L, description?: string }> { + render() { + const { legend, description } = this.props + const Legend = legend && legendFor(legend) + + return <div className='msp-control-row msp-help-text'> + <div> + <div className='msp-help-description'><span className={`msp-icon msp-icon-help-circle`} />{description}</div> + <div className='msp-help-legend'>{Legend && <Legend legend={legend} />}</div> + </div> + </div> + } +} export type ParamOnChange = (params: { param: PD.Base<any>, name: string, value: any }) => void -export interface ParamProps<P extends PD.Base<any> = PD.Base<any>> { name: string, value: P['defaultValue'], param: P, isDisabled?: boolean, onChange: ParamOnChange, onEnter?: () => void } +export interface ParamProps<P extends PD.Base<any> = PD.Base<any>> { + name: string, + value: P['defaultValue'], + param: P, + isDisabled?: boolean, + onChange: ParamOnChange, + onEnter?: () => void +} export type ParamControl = React.ComponentClass<ParamProps<any>> -export abstract class SimpleParam<P extends PD.Any> extends React.PureComponent<ParamProps<P>> { +export abstract class SimpleParam<P extends PD.Any> extends React.PureComponent<ParamProps<P>, { isExpanded: boolean }> { + state = { isExpanded: false }; + protected update(value: P['defaultValue']) { this.props.onChange({ param: this.props.param, name: this.props.name, value }); } @@ -93,14 +116,33 @@ export abstract class SimpleParam<P extends PD.Any> extends React.PureComponent< return className.join(' ') } + toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded }); + render() { const label = this.props.param.label || camelCaseToWords(this.props.name); - return <div className={this.className}> - <span title={this.props.param.description}>{label}</span> - <div> - {this.renderControl()} + const help = this.props.param.help + ? this.props.param.help(this.props.value) + : { description: this.props.param.description, legend: this.props.param.legend } + const hasHelp = help.description || help.legend + return <> + <div className={this.className}> + <span title={this.props.param.description}> + {label} + {hasHelp && + <button className='msp-help msp-btn-link msp-btn-icon msp-conrol-group-expander' onClick={this.toggleExpanded} title={`${this.state.isExpanded ? 'Hide' : 'Show'} help`} + style={{ background: 'transparent', textAlign: 'left', padding: '0' }}> + <span className={`msp-icon msp-icon-help-circle`} /> + </button> + } + </span> + <div> + {this.renderControl()} + </div> </div> - </div>; + {hasHelp && this.state.isExpanded && <div className='msp-control-offset'> + <ParamHelp legend={help.legend} description={help.description} /> + </div>} + </>; } } @@ -526,16 +568,24 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> const label = this.props.param.label || camelCaseToWords(this.props.name); const Mapped = controlFor(param); - const select = <SelectControl param={this.props.param.select} + const help = this.props.param.help + const select = help + ? { + ...this.props.param.select, + help: (name: any) => help({ name, params: this.getValues(name) }) + } + : this.props.param.select + + const Select = <SelectControl param={select} isDisabled={this.props.isDisabled} onChange={this.onChangeName} onEnter={this.props.onEnter} name={label} value={value.name} /> if (!Mapped) { - return select; + return Select; } return <> - {select} + {Select} <Mapped param={param} value={value.params} name={`${label} Properties`} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> </> } diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts index 18edc8457a92f6972cf8f77cdbf78060bda91c18..0b7cf68dc79c7a859aacd33ab327907c2c34d113 100644 --- a/src/mol-theme/color.ts +++ b/src/mol-theme/color.ts @@ -24,8 +24,7 @@ import { SecondaryStructureColorThemeProvider } from './color/secondary-structur import { SequenceIdColorThemeProvider } from './color/sequence-id'; import { ShapeGroupColorThemeProvider } from './color/shape-group'; import { UnitIndexColorThemeProvider } from './color/unit-index'; -import { ScaleLegend } from '../mol-util/color/scale'; -import { TableLegend } from '../mol-util/color/lists'; +import { ScaleLegend, TableLegend } from '../mol-util/legend'; import { UncertaintyColorThemeProvider } from './color/uncertainty'; import { EntitySourceColorThemeProvider } from './color/entity-source'; import { IllustrativeColorThemeProvider } from './color/illustrative'; diff --git a/src/mol-theme/color/carbohydrate-symbol.ts b/src/mol-theme/color/carbohydrate-symbol.ts index 6f338108a6161ed12bb2cdfc87ee5448e35ee59f..2a56f21d3a6415f3b07e709b547db1837d37824e 100644 --- a/src/mol-theme/color/carbohydrate-symbol.ts +++ b/src/mol-theme/color/carbohydrate-symbol.ts @@ -1,5 +1,5 @@ /** - * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> */ @@ -11,7 +11,7 @@ import { ColorTheme, LocationColor } from '../color'; import { Color } from '../../mol-util/color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../theme'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend } from '../../mol-util/legend'; const DefaultColor = Color(0xCCCCCC) const Description = 'Assigns colors according to the Symbol Nomenclature for Glycans (SNFG).' diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts index e03b204091dd055508feca7cad06082e26c71732..e7188bedb41210eb565990d7962e663747d48c0c 100644 --- a/src/mol-theme/color/chain-id.ts +++ b/src/mol-theme/color/chain-id.ts @@ -10,9 +10,8 @@ import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../../mol-theme/theme'; -import { ScaleLegend } from '../../mol-util/color/scale'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend, ScaleLegend } from '../../mol-util/legend'; import { Segmentation } from '../../mol-data/int'; const DefaultColor = Color(0xFAFAFA) diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts index 66146728d08feaf9a3929004a553e165a33b6ea5..990068c8177b1584826d66c988b2cce31f6fe7c8 100644 --- a/src/mol-theme/color/element-index.ts +++ b/src/mol-theme/color/element-index.ts @@ -12,8 +12,7 @@ import { ColorTheme, LocationColor } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../../mol-theme/theme'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; -import { TableLegend } from '../../mol-util/color/lists'; -import { ScaleLegend } from '../../mol-util/color/scale'; +import { TableLegend, ScaleLegend } from '../../mol-util/legend'; const DefaultColor = Color(0xCCCCCC) const Description = 'Gives every element (atom or coarse sphere/gaussian) a unique color based on the position (index) of the element in the list of elements in the structure.' diff --git a/src/mol-theme/color/element-symbol.ts b/src/mol-theme/color/element-symbol.ts index 46ca5dd74ff05741f44c7a7237be70b7c8289a05..27e0c117ce15a267db3b69fed2eb4180c0ff5ed6 100644 --- a/src/mol-theme/color/element-symbol.ts +++ b/src/mol-theme/color/element-symbol.ts @@ -11,7 +11,7 @@ import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../theme'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend } from '../../mol-util/legend'; import { getAdjustedColorMap } from '../../mol-util/color/color'; // from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF) diff --git a/src/mol-theme/color/entity-source.ts b/src/mol-theme/color/entity-source.ts index ac8ebd3c86d4e8d81d6578e5021c6032626ebc86..92b4d60ee6aef963eaffbe3e8c836268f58cfdf2 100644 --- a/src/mol-theme/color/entity-source.ts +++ b/src/mol-theme/color/entity-source.ts @@ -10,11 +10,10 @@ import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../../mol-theme/theme'; -import { ScaleLegend } from '../../mol-util/color/scale'; import { Table, Column } from '../../mol-data/db'; import { mmCIF_Schema } from '../../mol-io/reader/cif/schema/mmcif'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend, ScaleLegend } from '../../mol-util/legend'; const DefaultColor = Color(0xFAFAFA) const Description = 'Gives ranges of a polymer chain a color based on the entity source it originates from. Genes get the same color per entity.' diff --git a/src/mol-theme/color/model-index.ts b/src/mol-theme/color/model-index.ts index faf151815d4110dacb2502b15188ca26694dd7cd..39d398c8824e5531321e4f5fd578a10b792e0ea6 100644 --- a/src/mol-theme/color/model-index.ts +++ b/src/mol-theme/color/model-index.ts @@ -10,9 +10,8 @@ import { StructureElement, Link } from '../../mol-model/structure'; import { ColorTheme, LocationColor } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../../mol-theme/theme'; -import { ScaleLegend } from '../../mol-util/color/scale'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend, ScaleLegend } from '../../mol-util/legend'; const DefaultColor = Color(0xCCCCCC) const Description = 'Gives every model a unique color based on the position (index) of the model in the list of models in the structure.' diff --git a/src/mol-theme/color/molecule-type.ts b/src/mol-theme/color/molecule-type.ts index 7bc5eca8637e557c33eab3033ddb984ba02ec988..a1c808c3b488201d970540f4dc6153b1908ee928 100644 --- a/src/mol-theme/color/molecule-type.ts +++ b/src/mol-theme/color/molecule-type.ts @@ -12,7 +12,7 @@ import { MoleculeType } from '../../mol-model/structure/model/types'; import { getElementMoleculeType } from '../../mol-model/structure/util'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../theme'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend } from '../../mol-util/legend'; import { getAdjustedColorMap } from '../../mol-util/color/color'; export const MoleculeTypeColors = ColorMap({ diff --git a/src/mol-theme/color/polymer-id.ts b/src/mol-theme/color/polymer-id.ts index 3910089d83cc8e80665627d1a0b21fd888ddc707..5df2bc59983be4f5a6117b0a4b9e33f625acb308 100644 --- a/src/mol-theme/color/polymer-id.ts +++ b/src/mol-theme/color/polymer-id.ts @@ -12,8 +12,7 @@ import { ColorTheme, LocationColor } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../../mol-theme/theme'; import { getPalette, getPaletteParams } from '../../mol-util/color/palette'; -import { ScaleLegend } from '../../mol-util/color/scale'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend, ScaleLegend } from '../../mol-util/legend'; import { Segmentation } from '../../mol-data/int'; const DefaultColor = Color(0xFAFAFA) diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts index 1dc4d59fcca5fedd5d361c3444fee59a09107587..2233487402935173084c68fcfc5dc90c9ddd9f01 100644 --- a/src/mol-theme/color/polymer-index.ts +++ b/src/mol-theme/color/polymer-index.ts @@ -10,8 +10,7 @@ import { StructureElement, Link, Structure } from '../../mol-model/structure'; import { ColorTheme, LocationColor } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../../mol-theme/theme'; -import { ScaleLegend } from '../../mol-util/color/scale'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend, ScaleLegend } from '../../mol-util/legend'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; const DefaultColor = Color(0xCCCCCC) diff --git a/src/mol-theme/color/residue-name.ts b/src/mol-theme/color/residue-name.ts index 06151d63dae8a5f7521d9c3e37699ec1cbaf0771..c2e98072409845f197ef2f377f0d079e0c67bd38 100644 --- a/src/mol-theme/color/residue-name.ts +++ b/src/mol-theme/color/residue-name.ts @@ -10,7 +10,7 @@ import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../theme'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend } from '../../mol-util/legend'; import { getAdjustedColorMap } from '../../mol-util/color/color'; // protein colors from Jmol http://jmol.sourceforge.net/jscolors/ diff --git a/src/mol-theme/color/secondary-structure.ts b/src/mol-theme/color/secondary-structure.ts index afa12534c3464d0e36b0e1f49e61d731f18177ee..006a3dbaab484afa41cabae8874626019029f6b0 100644 --- a/src/mol-theme/color/secondary-structure.ts +++ b/src/mol-theme/color/secondary-structure.ts @@ -12,7 +12,7 @@ import { SecondaryStructureType, MoleculeType } from '../../mol-model/structure/ import { getElementMoleculeType } from '../../mol-model/structure/util'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../theme'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend } from '../../mol-util/legend'; import { ComputedSecondaryStructure } from '../../mol-model-props/computed/secondary-structure'; import { getAdjustedColorMap } from '../../mol-util/color/color'; diff --git a/src/mol-theme/color/uniform.ts b/src/mol-theme/color/uniform.ts index 4fdb7c2d427129cd9d1be257650a49037e67a14b..6bc0e8bdc70be6be9be3c061eb5c7936ab8d270d 100644 --- a/src/mol-theme/color/uniform.ts +++ b/src/mol-theme/color/uniform.ts @@ -8,7 +8,7 @@ import { ColorTheme } from '../color'; import { Color } from '../../mol-util/color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../theme'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend } from '../../mol-util/legend'; import { defaults } from '../../mol-util'; const DefaultColor = Color(0xCCCCCC) diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts index a57d648762fe13559b8526e850c978eb3a3cd172..c1f42c49ff897b64d5bee1c1adc5dbf4ad812d52 100644 --- a/src/mol-theme/color/unit-index.ts +++ b/src/mol-theme/color/unit-index.ts @@ -10,9 +10,8 @@ import { StructureElement, Link } from '../../mol-model/structure'; import { ColorTheme, LocationColor } from '../color'; import { ParamDefinition as PD } from '../../mol-util/param-definition' import { ThemeDataContext } from '../../mol-theme/theme'; -import { ScaleLegend } from '../../mol-util/color/scale'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; -import { TableLegend } from '../../mol-util/color/lists'; +import { TableLegend, ScaleLegend } from '../../mol-util/legend'; const DefaultColor = Color(0xCCCCCC) const Description = 'Gives every unit (single chain or collection of single elements) a unique color based on the position (index) of the unit in the list of units in the structure.' diff --git a/src/mol-util/color/lists.ts b/src/mol-util/color/lists.ts index 531f92ff0af159a0515d5194defd49b03c6085fd..e0ade6d6ffd10d24e3058fbf94c4d544e9a8d069 100644 --- a/src/mol-util/color/lists.ts +++ b/src/mol-util/color/lists.ts @@ -4,15 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Color, ColorList } from './color'; - -export interface TableLegend { - kind: 'table-legend' - table: [ string, Color ][] -} -export function TableLegend(table: [ string, Color ][]): TableLegend { - return { kind: 'table-legend', table } -} +import { ColorList } from './color'; export const ColorLists = { /** diff --git a/src/mol-util/color/palette.ts b/src/mol-util/color/palette.ts index e0791f8f9c105b86681b5b8150db3dfdc55ccd9b..d05fa5aa52033fc00da71c8920af0f06844a2484 100644 --- a/src/mol-util/color/palette.ts +++ b/src/mol-util/color/palette.ts @@ -6,9 +6,10 @@ import { ParamDefinition as PD } from '../param-definition' import { DistinctColorsParams, distinctColors } from './distinct'; -import { ScaleLegend, ColorScale } from './scale'; +import { ColorScale } from './scale'; import { Color } from '.'; -import { TableLegend, ColorListName, ColorListOptionsScale, ColorListOptionsSet, getColorListFromName } from './lists'; +import { ColorListName, ColorListOptionsScale, ColorListOptionsSet, getColorListFromName } from './lists'; +import { TableLegend, ScaleLegend } from '../legend'; type PaletteType = 'generate' | 'scale' | 'set' @@ -71,6 +72,7 @@ export function getPalette(count: number, props: PaletteProps) { colors = distinctColors(count, props.palette.params) } const colorsLength = colors.length + legend = TableLegend(colors.map((c, i) => [`${i + 1}`, c])) color = (i: number) => colors[i % colorsLength] } diff --git a/src/mol-util/color/scale.ts b/src/mol-util/color/scale.ts index 31b33f774487522593ba480d83a8949b3105de99..9745506ae6e6278337d174602869d14857261ccf 100644 --- a/src/mol-util/color/scale.ts +++ b/src/mol-util/color/scale.ts @@ -8,16 +8,7 @@ import { Color } from './color' import { getColorListFromName, ColorListName } from './lists' import { defaults } from '../../mol-util'; import { NumberArray } from '../../mol-util/type-helpers'; - -export interface ScaleLegend { - kind: 'scale-legend' - minLabel: string, - maxLabel: string, - colors: Color[] -} -export function ScaleLegend(minLabel: string, maxLabel: string, colors: Color[]): ScaleLegend { - return { kind: 'scale-legend', minLabel, maxLabel, colors } -} +import { ScaleLegend } from '../legend'; export interface ColorScale { /** Returns hex color for given value */ diff --git a/src/mol-util/legend.ts b/src/mol-util/legend.ts new file mode 100644 index 0000000000000000000000000000000000000000..4079fa8c3e7e8bc5511c1d189179538fbbd4c094 --- /dev/null +++ b/src/mol-util/legend.ts @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author Alexander Rose <alexander.rose@weirdbyte.de> + */ + +import { Color } from './color'; + +export type Legend = TableLegend | ScaleLegend + +export interface TableLegend { + kind: 'table-legend' + table: [ string, Color ][] +} +export function TableLegend(table: [ string, Color ][]): TableLegend { + return { kind: 'table-legend', table } +} + +export interface ScaleLegend { + kind: 'scale-legend' + minLabel: string, + maxLabel: string, + colors: Color[] +} +export function ScaleLegend(minLabel: string, maxLabel: string, colors: Color[]): ScaleLegend { + return { kind: 'scale-legend', minLabel, maxLabel, colors } +} \ No newline at end of file diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts index 51792e49b8e3dac2721e22fdbdcaec6ffe1f9ac0..486acb15ef0fb99e2fcbd995395f595f29637e09 100644 --- a/src/mol-util/param-definition.ts +++ b/src/mol-util/param-definition.ts @@ -10,25 +10,32 @@ import { shallowEqual } from './index'; import { Vec2 as Vec2Data, Vec3 as Vec3Data } from '../mol-math/linear-algebra'; import { deepClone } from './object'; import { Script as ScriptData } from '../mol-script/script'; +import { Legend } from './legend'; export namespace ParamDefinition { export interface Info { label?: string, description?: string, + legend?: Legend, fieldLabels?: { [name: string]: string }, isHidden?: boolean, shortLabel?: boolean, twoColumns?: boolean, + + help?: (value: any) => { description?: string, legend?: Legend } } function setInfo<T extends Info>(param: T, info?: Info): T { if (!info) return param; if (info.label) param.label = info.label; if (info.description) param.description = info.description; + if (info.legend) param.legend = info.legend; if (info.fieldLabels) param.fieldLabels = info.fieldLabels; if (info.isHidden) param.isHidden = info.isHidden; if (info.shortLabel) param.shortLabel = info.shortLabel; if (info.twoColumns) param.twoColumns = info.twoColumns; + + if (info.help) param.help = info.help; return param; } diff --git a/src/mol-util/type-helpers.ts b/src/mol-util/type-helpers.ts index a6e5f3c4206311ab97ceea6d6ff591c68577830d..22e9b6ae51afe0c1832ccafc3d2db7ef09f09e85 100644 --- a/src/mol-util/type-helpers.ts +++ b/src/mol-util/type-helpers.ts @@ -5,9 +5,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export type Mutable<T> = { - -readonly [P in keyof T]: T[P] -} +export type Mutable<T> = { -readonly [P in keyof T]: T[P] } +export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>> + export type TypedIntArray = Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array export type TypedFloatArray = Float32Array | Float64Array