From 2da3df6e4d2271ddaef3fa71474ebdbe18168904 Mon Sep 17 00:00:00 2001 From: David Sehnal <david.sehnal@gmail.com> Date: Thu, 27 Feb 2020 16:17:23 +0100 Subject: [PATCH] ParamDefinition.Select grouping & used in theme definitions --- src/apps/state-docs/pd-to-md.ts | 2 +- src/examples/proteopedia-wrapper/coloring.ts | 1 + .../common/custom-element-property.ts | 1 + .../themes/accessible-surface-area.ts | 1 + .../computed/themes/interaction-type.ts | 1 + .../integrative/cross-link-restraint/color.ts | 1 + .../pdbe/themes/structure-quality-report.ts | 1 + .../rcsb/themes/assembly-symmetry-cluster.ts | 1 + .../rcsb/themes/density-fit.ts | 1 + .../rcsb/themes/geometry-quality.ts | 1 + .../rcsb/themes/random-coil-index.ts | 1 + src/mol-plugin-ui/controls/action-menu.tsx | 61 ++++++++++++++++++- src/mol-plugin-ui/controls/parameters.tsx | 20 ++---- src/mol-theme/color.ts | 9 ++- src/mol-theme/color/carbohydrate-symbol.ts | 3 +- src/mol-theme/color/chain-id.ts | 1 + src/mol-theme/color/element-index.ts | 1 + src/mol-theme/color/element-symbol.ts | 1 + src/mol-theme/color/entity-source.ts | 1 + src/mol-theme/color/hydrophobicity.ts | 1 + src/mol-theme/color/illustrative.ts | 1 + src/mol-theme/color/model-index.ts | 1 + src/mol-theme/color/molecule-type.ts | 1 + src/mol-theme/color/occupancy.ts | 1 + src/mol-theme/color/operator-hkl.ts | 1 + src/mol-theme/color/operator-name.ts | 1 + src/mol-theme/color/polymer-id.ts | 1 + src/mol-theme/color/polymer-index.ts | 1 + src/mol-theme/color/residue-name.ts | 1 + src/mol-theme/color/secondary-structure.ts | 1 + src/mol-theme/color/sequence-id.ts | 1 + src/mol-theme/color/shape-group.ts | 1 + src/mol-theme/color/uncertainty.ts | 1 + src/mol-theme/color/uniform.ts | 1 + src/mol-theme/color/unit-index.ts | 1 + src/mol-theme/size.ts | 2 +- src/mol-theme/size/physical.ts | 1 + src/mol-theme/size/shape-group.ts | 1 + src/mol-theme/size/uncertainty.ts | 1 + src/mol-theme/size/uniform.ts | 1 + src/mol-theme/theme.ts | 17 +++++- src/mol-util/param-definition.ts | 8 +-- 42 files changed, 129 insertions(+), 27 deletions(-) diff --git a/src/apps/state-docs/pd-to-md.ts b/src/apps/state-docs/pd-to-md.ts index f0df30519..a55d372a0 100644 --- a/src/apps/state-docs/pd-to-md.ts +++ b/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])[]) { +function oToS(options: readonly (readonly [string, string] | [string, string, string])[]) { return options.map(o => `'${o[0]}'`).join(', '); } diff --git a/src/examples/proteopedia-wrapper/coloring.ts b/src/examples/proteopedia-wrapper/coloring.ts index 0f7bc4b3a..3b2549636 100644 --- a/src/examples/proteopedia-wrapper/coloring.ts +++ b/src/examples/proteopedia-wrapper/coloring.ts @@ -96,6 +96,7 @@ export function createProteopediaCustomTheme(colors: number[]) { const ProteopediaCustomColorThemeProvider: ColorTheme.Provider<ProteopediaCustomColorThemeParams> = { label: 'Proteopedia Custom', + category: 'Custom', factory: ProteopediaCustomColorTheme, getParams: getChainIdColorThemeParams, defaultValues: PD.getDefaultValues(ProteopediaCustomColorThemeParams), diff --git a/src/mol-model-props/common/custom-element-property.ts b/src/mol-model-props/common/custom-element-property.ts index 3dea414a9..4684a20e4 100644 --- a/src/mol-model-props/common/custom-element-property.ts +++ b/src/mol-model-props/common/custom-element-property.ts @@ -99,6 +99,7 @@ namespace CustomElementProperty { return { label: modelProperty.label, + category: 'Custom', factory: Coloring, getParams: () => ({}), defaultValues: {}, diff --git a/src/mol-model-props/computed/themes/accessible-surface-area.ts b/src/mol-model-props/computed/themes/accessible-surface-area.ts index fe2a60134..3218bc0b5 100644 --- a/src/mol-model-props/computed/themes/accessible-surface-area.ts +++ b/src/mol-model-props/computed/themes/accessible-surface-area.ts @@ -68,6 +68,7 @@ export function AccessibleSurfaceAreaColorTheme(ctx: ThemeDataContext, props: PD export const AccessibleSurfaceAreaColorThemeProvider: ColorTheme.Provider<AccessibleSurfaceAreaColorThemeParams> = { label: 'Accessible Surface Area', + category: ColorTheme.Category.Computed, factory: AccessibleSurfaceAreaColorTheme, getParams: getAccessibleSurfaceAreaColorThemeParams, defaultValues: PD.getDefaultValues(AccessibleSurfaceAreaColorThemeParams), diff --git a/src/mol-model-props/computed/themes/interaction-type.ts b/src/mol-model-props/computed/themes/interaction-type.ts index d6ede61af..f816d2b41 100644 --- a/src/mol-model-props/computed/themes/interaction-type.ts +++ b/src/mol-model-props/computed/themes/interaction-type.ts @@ -108,6 +108,7 @@ export function InteractionTypeColorTheme(ctx: ThemeDataContext, props: PD.Value export const InteractionTypeColorThemeProvider: ColorTheme.Provider<InteractionTypeColorThemeParams> = { label: 'Interaction Type', + category: ColorTheme.Category.Computed, factory: InteractionTypeColorTheme, getParams: getInteractionTypeColorThemeParams, defaultValues: PD.getDefaultValues(InteractionTypeColorThemeParams), diff --git a/src/mol-model-props/integrative/cross-link-restraint/color.ts b/src/mol-model-props/integrative/cross-link-restraint/color.ts index 4000f4371..3ba49d73d 100644 --- a/src/mol-model-props/integrative/cross-link-restraint/color.ts +++ b/src/mol-model-props/integrative/cross-link-restraint/color.ts @@ -63,6 +63,7 @@ export function CrossLinkColorTheme(ctx: ThemeDataContext, props: PD.Values<Cros export const CrossLinkColorThemeProvider: ColorTheme.Provider<CrossLinkColorThemeParams> = { label: 'Cross Link', + category: ColorTheme.Category.Advanced, factory: CrossLinkColorTheme, getParams: getCrossLinkColorThemeParams, defaultValues: PD.getDefaultValues(CrossLinkColorThemeParams), 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 e3296bab9..a4b23e9eb 100644 --- a/src/mol-model-props/pdbe/themes/structure-quality-report.ts +++ b/src/mol-model-props/pdbe/themes/structure-quality-report.ts @@ -79,6 +79,7 @@ export function StructureQualityReportColorTheme(ctx: ThemeDataContext, props: P export const StructureQualityReportColorThemeProvider: ColorTheme.Provider<Params> = { label: 'PDBe Structure Quality Report', + category: 'PDBe', factory: StructureQualityReportColorTheme, getParams: ctx => { const issueTypes = StructureQualityReport.getIssueTypes(ctx.structure); 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 b8e1d2f7c..cbab8e1e4 100644 --- a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts +++ b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts @@ -93,6 +93,7 @@ export function AssemblySymmetryClusterColorTheme(ctx: ThemeDataContext, props: export const AssemblySymmetryClusterColorThemeProvider: ColorTheme.Provider<AssemblySymmetryClusterColorThemeParams> = { label: 'RCSB Assembly Symmetry Cluster', + category: 'RCSB', factory: AssemblySymmetryClusterColorTheme, getParams: getAssemblySymmetryClusterColorThemeParams, defaultValues: PD.getDefaultValues(AssemblySymmetryClusterColorThemeParams), diff --git a/src/mol-model-props/rcsb/themes/density-fit.ts b/src/mol-model-props/rcsb/themes/density-fit.ts index 9bc3d3d0f..319c3c602 100644 --- a/src/mol-model-props/rcsb/themes/density-fit.ts +++ b/src/mol-model-props/rcsb/themes/density-fit.ts @@ -62,6 +62,7 @@ export function DensityFitColorTheme(ctx: ThemeDataContext, props: {}): ColorThe export const DensityFitColorThemeProvider: ColorTheme.Provider<{}> = { label: 'RCSB Density Fit', + category: 'RCSB', factory: DensityFitColorTheme, getParams: () => ({}), defaultValues: PD.getDefaultValues({}), diff --git a/src/mol-model-props/rcsb/themes/geometry-quality.ts b/src/mol-model-props/rcsb/themes/geometry-quality.ts index 1f39b8de4..ca6d54e35 100644 --- a/src/mol-model-props/rcsb/themes/geometry-quality.ts +++ b/src/mol-model-props/rcsb/themes/geometry-quality.ts @@ -102,6 +102,7 @@ export function GeometryQualityColorTheme(ctx: ThemeDataContext, props: PD.Value export const GeometryQualityColorThemeProvider: ColorTheme.Provider<GeometricQualityColorThemeParams> = { label: 'RCSB Geometry Quality', + category: 'RCSB', factory: GeometryQualityColorTheme, getParams: getGeometricQualityColorThemeParams, defaultValues: PD.getDefaultValues(getGeometricQualityColorThemeParams({})), diff --git a/src/mol-model-props/rcsb/themes/random-coil-index.ts b/src/mol-model-props/rcsb/themes/random-coil-index.ts index 596aa2055..c8a7e90f2 100644 --- a/src/mol-model-props/rcsb/themes/random-coil-index.ts +++ b/src/mol-model-props/rcsb/themes/random-coil-index.ts @@ -53,6 +53,7 @@ export function RandomCoilIndexColorTheme(ctx: ThemeDataContext, props: {}): Col export const RandomCoilIndexColorThemeProvider: ColorTheme.Provider<{}> = { label: 'RCSB Random Coil Index', + category: 'RCSB', factory: RandomCoilIndexColorTheme, getParams: () => ({}), defaultValues: PD.getDefaultValues({}), diff --git a/src/mol-plugin-ui/controls/action-menu.tsx b/src/mol-plugin-ui/controls/action-menu.tsx index 0d67b8c80..bc223a0de 100644 --- a/src/mol-plugin-ui/controls/action-menu.tsx +++ b/src/mol-plugin-ui/controls/action-menu.tsx @@ -7,6 +7,7 @@ import * as React from 'react' import { Icon } from './common'; import { Subscription, BehaviorSubject, Observable } from 'rxjs'; +import { ParamDefinition } from '../../mol-util/param-definition'; export class ActionMenu { private _command: BehaviorSubject<ActionMenu.Command>; @@ -139,16 +140,29 @@ export namespace ActionMenu { } } - class Section extends React.PureComponent<{ menu: ActionMenu, header?: string, items: Spec, onSelect: OnSelect, current: Item | undefined }, { isExpanded: boolean }> { - state = { isExpanded: false } + type SectionProps = { menu: ActionMenu, header?: string, items: Spec, onSelect: OnSelect, current: Item | undefined } + type SectionState = { items: Spec, current: Item | undefined, isExpanded: boolean } + + class Section extends React.PureComponent<SectionProps, SectionState> { + state = { + items: this.props.items, + current: this.props.current, + isExpanded: !!this.props.current && !!findCurrent(this.props.items, this.props.current.value) + } toggleExpanded = (e: React.MouseEvent<HTMLButtonElement>) => { this.setState({ isExpanded: !this.state.isExpanded }); e.currentTarget.blur(); } + 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 && !!findCurrent(props.items, props.current.value) } + } + render() { const { header, items, onSelect, current, menu } = this.props; + if (typeof items === 'string') return null; if (isItem(items)) return <Action menu={menu} item={items} onSelect={onSelect} current={current} /> return <div> @@ -196,4 +210,47 @@ export namespace ActionMenu { if (value) return { name, icon: iconOrValue, value }; return { name, value: iconOrValue }; } + + function createSpecFromSelectParamSimple(param: ParamDefinition.Select<any>) { + const spec: Item[] = []; + for (const [v, l] of param.options) { + spec.push(ActionMenu.Item(l, v)); + } + return spec as Spec; + } + + function createSpecFromSelectParamCategories(param: ParamDefinition.Select<any>) { + const cats = new Map<string, (Item | string)[]>(); + const spec: (Item | (Item | string)[] | string)[] = []; + for (const [v, l, c] of param.options) { + if (!!c) { + let cat = cats.get(c); + if (!cat) { + cat = [c]; + cats.set(c, cat); + spec.push(cat); + } + cat.push(ActionMenu.Item(l, v)); + } else { + spec.push(ActionMenu.Item(l, v)); + } + } + return spec as Spec; + } + + export function createSpecFromSelectParam(param: ParamDefinition.Select<any>) { + for (const o of param.options) { + if (!!o[2]) return createSpecFromSelectParamCategories(param); + } + return createSpecFromSelectParamSimple(param); + } + + export function findCurrent(spec: Spec, value: any): Item | undefined { + if (typeof spec === 'string') return; + if (isItem(spec)) return spec.value === value ? spec : void 0; + for (const s of spec) { + const found = findCurrent(s, value); + if (found) return found; + } + } } \ 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 f52c546cc..2576f59e7 100644 --- a/src/mol-plugin-ui/controls/parameters.tsx +++ b/src/mol-plugin-ui/controls/parameters.tsx @@ -8,7 +8,7 @@ import { Vec2, Vec3 } from '../../mol-math/linear-algebra'; import { Color } from '../../mol-util/color'; import { ColorListName, getColorListFromName } from '../../mol-util/color/lists'; -import { memoize1 } from '../../mol-util/memoize'; +import { memoize1, memoizeLatest } from '../../mol-util/memoize'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { camelCaseToWords } from '../../mol-util/string'; import * as React from 'react'; @@ -328,22 +328,14 @@ export class SelectControl extends SimpleParam<PD.Select<string | number>> { this.update(value); } + items = memoizeLatest((param: PD.Select<any>) => ActionMenu.createSpecFromSelectParam(param)); + renderControl() { - const isInvalid = this.props.value !== void 0 && !this.props.param.options.some(e => e[0] === this.props.value); - const items: ActionMenu.Item[] = []; - let current: ActionMenu.Item | undefined = void 0; - if (isInvalid) { - current = ActionMenu.Item(`[Invalid] ${this.props.value}`, this.props.value); - items.push(current); - } - for (const [value, label] of this.props.param.options) { - const item = ActionMenu.Item(label, value); - items.push(item); - if (value === this.props.value) current = item; - } + const items = this.items(this.props.param); + const current = ActionMenu.findCurrent(items, this.props.value); return <ActionMenu.Toggle menu={this.menu} disabled={this.props.isDisabled} - onSelect={this.onSelect} items={items as ActionMenu.Spec} label={current?.name} + onSelect={this.onSelect} items={items as ActionMenu.Spec} label={current?.name || `[Invalid] ${this.props.value}`} current={current} />; } diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts index 67537bb8f..6efcc7691 100644 --- a/src/mol-theme/color.ts +++ b/src/mol-theme/color.ts @@ -46,6 +46,13 @@ interface ColorTheme<P extends PD.Params> { readonly legend?: Readonly<ScaleLegend | TableLegend> } namespace ColorTheme { + export const enum Category { + Basic = 'Basic', + Advanced = 'Advanced', + Computed = 'Computed', + Misc = 'Miscellaneous' + } + export type Props = { [k: string]: any } export type Factory<P extends PD.Params> = (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P> export const EmptyFactory = () => Empty @@ -62,7 +69,7 @@ namespace ColorTheme { } export interface Provider<P extends PD.Params> extends ThemeProvider<ColorTheme<P>, P> { } - export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } + export const EmptyProvider: Provider<{}> = { label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } export type Registry = ThemeRegistry<ColorTheme<any>> export function createRegistry() { diff --git a/src/mol-theme/color/carbohydrate-symbol.ts b/src/mol-theme/color/carbohydrate-symbol.ts index f29d10170..853e7cf9c 100644 --- a/src/mol-theme/color/carbohydrate-symbol.ts +++ b/src/mol-theme/color/carbohydrate-symbol.ts @@ -61,7 +61,8 @@ export function CarbohydrateSymbolColorTheme(ctx: ThemeDataContext, props: PD.Va } export const CarbohydrateSymbolColorThemeProvider: ColorTheme.Provider<CarbohydrateSymbolColorThemeParams> = { - label: 'Carbohydrate Symbol', + label: 'Carbohydrate Symbol', + category: ColorTheme.Category.Advanced, factory: CarbohydrateSymbolColorTheme, getParams: getCarbohydrateSymbolColorThemeParams, defaultValues: PD.getDefaultValues(CarbohydrateSymbolColorThemeParams), diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts index 16c072ff4..d9ae75cb9 100644 --- a/src/mol-theme/color/chain-id.ts +++ b/src/mol-theme/color/chain-id.ts @@ -119,6 +119,7 @@ export function ChainIdColorTheme(ctx: ThemeDataContext, props: PD.Values<ChainI export const ChainIdColorThemeProvider: ColorTheme.Provider<ChainIdColorThemeParams> = { label: 'Chain Id', + category: ColorTheme.Category.Basic, factory: ChainIdColorTheme, getParams: getChainIdColorThemeParams, defaultValues: PD.getDefaultValues(ChainIdColorThemeParams), diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts index be94f3376..d2e13588b 100644 --- a/src/mol-theme/color/element-index.ts +++ b/src/mol-theme/color/element-index.ts @@ -73,6 +73,7 @@ export function ElementIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<E export const ElementIndexColorThemeProvider: ColorTheme.Provider<ElementIndexColorThemeParams> = { label: 'Element Index', + category: ColorTheme.Category.Basic, factory: ElementIndexColorTheme, getParams: getElementIndexColorThemeParams, defaultValues: PD.getDefaultValues(ElementIndexColorThemeParams), diff --git a/src/mol-theme/color/element-symbol.ts b/src/mol-theme/color/element-symbol.ts index 6f2f8881f..8c559ff64 100644 --- a/src/mol-theme/color/element-symbol.ts +++ b/src/mol-theme/color/element-symbol.ts @@ -69,6 +69,7 @@ export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values< export const ElementSymbolColorThemeProvider: ColorTheme.Provider<ElementSymbolColorThemeParams> = { label: 'Element Symbol', + category: ColorTheme.Category.Basic, factory: ElementSymbolColorTheme, getParams: getElementSymbolColorThemeParams, defaultValues: PD.getDefaultValues(ElementSymbolColorThemeParams), diff --git a/src/mol-theme/color/entity-source.ts b/src/mol-theme/color/entity-source.ts index a8ac312bf..e8b4e71bc 100644 --- a/src/mol-theme/color/entity-source.ts +++ b/src/mol-theme/color/entity-source.ts @@ -175,6 +175,7 @@ export function EntitySourceColorTheme(ctx: ThemeDataContext, props: PD.Values<E export const EntitySourceColorThemeProvider: ColorTheme.Provider<EntitySourceColorThemeParams> = { label: 'Entity Source', + category: ColorTheme.Category.Advanced, factory: EntitySourceColorTheme, getParams: getEntitySourceColorThemeParams, defaultValues: PD.getDefaultValues(EntitySourceColorThemeParams), diff --git a/src/mol-theme/color/hydrophobicity.ts b/src/mol-theme/color/hydrophobicity.ts index 47f3b94e4..e49e3f25c 100644 --- a/src/mol-theme/color/hydrophobicity.ts +++ b/src/mol-theme/color/hydrophobicity.ts @@ -94,6 +94,7 @@ export function HydrophobicityColorTheme(ctx: ThemeDataContext, props: PD.Values export const HydrophobicityColorThemeProvider: ColorTheme.Provider<HydrophobicityColorThemeParams> = { label: 'Hydrophobicity', + category: ColorTheme.Category.Advanced, factory: HydrophobicityColorTheme, getParams: getHydrophobicityColorThemeParams, defaultValues: PD.getDefaultValues(HydrophobicityColorThemeParams), diff --git a/src/mol-theme/color/illustrative.ts b/src/mol-theme/color/illustrative.ts index 6025f1eed..9b86d8b97 100644 --- a/src/mol-theme/color/illustrative.ts +++ b/src/mol-theme/color/illustrative.ts @@ -76,6 +76,7 @@ export function IllustrativeColorTheme(ctx: ThemeDataContext, props: PD.Values<I export const IllustrativeColorThemeProvider: ColorTheme.Provider<IllustrativeColorThemeParams> = { label: 'Illustrative', + category: ColorTheme.Category.Misc, factory: IllustrativeColorTheme, getParams: getIllustrativeColorThemeParams, defaultValues: PD.getDefaultValues(IllustrativeColorThemeParams), diff --git a/src/mol-theme/color/model-index.ts b/src/mol-theme/color/model-index.ts index fd98c44f7..f7cc54bf7 100644 --- a/src/mol-theme/color/model-index.ts +++ b/src/mol-theme/color/model-index.ts @@ -61,6 +61,7 @@ export function ModelIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<Mod export const ModelIndexColorThemeProvider: ColorTheme.Provider<ModelIndexColorThemeParams> = { label: 'Model Index', + category: ColorTheme.Category.Basic, factory: ModelIndexColorTheme, getParams: getModelIndexColorThemeParams, defaultValues: PD.getDefaultValues(ModelIndexColorThemeParams), diff --git a/src/mol-theme/color/molecule-type.ts b/src/mol-theme/color/molecule-type.ts index 49f891381..668f8ccfe 100644 --- a/src/mol-theme/color/molecule-type.ts +++ b/src/mol-theme/color/molecule-type.ts @@ -78,6 +78,7 @@ export function MoleculeTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<M export const MoleculeTypeColorThemeProvider: ColorTheme.Provider<MoleculeTypeColorThemeParams> = { label: 'Molecule Type', + category: ColorTheme.Category.Advanced, factory: MoleculeTypeColorTheme, getParams: getMoleculeTypeColorThemeParams, defaultValues: PD.getDefaultValues(MoleculeTypeColorThemeParams), diff --git a/src/mol-theme/color/occupancy.ts b/src/mol-theme/color/occupancy.ts index cf609f010..7cfa1c458 100644 --- a/src/mol-theme/color/occupancy.ts +++ b/src/mol-theme/color/occupancy.ts @@ -60,6 +60,7 @@ export function OccupancyColorTheme(ctx: ThemeDataContext, props: PD.Values<Occu export const OccupancyColorThemeProvider: ColorTheme.Provider<OccupancyColorThemeParams> = { label: 'Occupancy', + category: ColorTheme.Category.Advanced, factory: OccupancyColorTheme, getParams: getOccupancyColorThemeParams, defaultValues: PD.getDefaultValues(OccupancyColorThemeParams), diff --git a/src/mol-theme/color/operator-hkl.ts b/src/mol-theme/color/operator-hkl.ts index 2469356ea..d08c29033 100644 --- a/src/mol-theme/color/operator-hkl.ts +++ b/src/mol-theme/color/operator-hkl.ts @@ -119,6 +119,7 @@ export function OperatorHklColorTheme(ctx: ThemeDataContext, props: PD.Values<Op export const OperatorHklColorThemeProvider: ColorTheme.Provider<OperatorHklColorThemeParams> = { label: 'Operator HKL', + category: ColorTheme.Category.Advanced, factory: OperatorHklColorTheme, getParams: getOperatorHklColorThemeParams, defaultValues: PD.getDefaultValues(OperatorHklColorThemeParams), diff --git a/src/mol-theme/color/operator-name.ts b/src/mol-theme/color/operator-name.ts index 16d48b147..61b4e95c4 100644 --- a/src/mol-theme/color/operator-name.ts +++ b/src/mol-theme/color/operator-name.ts @@ -85,6 +85,7 @@ export function OperatorNameColorTheme(ctx: ThemeDataContext, props: PD.Values<O export const OperatorNameColorThemeProvider: ColorTheme.Provider<OperatorNameColorThemeParams> = { label: 'Operator Name', + category: ColorTheme.Category.Advanced, factory: OperatorNameColorTheme, getParams: getOperatorNameColorThemeParams, defaultValues: PD.getDefaultValues(OperatorNameColorThemeParams), diff --git a/src/mol-theme/color/polymer-id.ts b/src/mol-theme/color/polymer-id.ts index 46955e905..3e796d3d9 100644 --- a/src/mol-theme/color/polymer-id.ts +++ b/src/mol-theme/color/polymer-id.ts @@ -128,6 +128,7 @@ export function PolymerIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Poly export const PolymerIdColorThemeProvider: ColorTheme.Provider<PolymerIdColorThemeParams> = { label: 'Polymer Id', + category: ColorTheme.Category.Basic, factory: PolymerIdColorTheme, getParams: getPolymerIdColorThemeParams, defaultValues: PD.getDefaultValues(PolymerIdColorThemeParams), diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts index 02bfa5b44..ef37ce818 100644 --- a/src/mol-theme/color/polymer-index.ts +++ b/src/mol-theme/color/polymer-index.ts @@ -88,6 +88,7 @@ export function PolymerIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<P export const PolymerIndexColorThemeProvider: ColorTheme.Provider<PolymerIndexColorThemeParams> = { label: 'Polymer Index', + category: ColorTheme.Category.Advanced, factory: PolymerIndexColorTheme, getParams: getPolymerIndexColorThemeParams, defaultValues: PD.getDefaultValues(PolymerIndexColorThemeParams), diff --git a/src/mol-theme/color/residue-name.ts b/src/mol-theme/color/residue-name.ts index 175518740..72259d10f 100644 --- a/src/mol-theme/color/residue-name.ts +++ b/src/mol-theme/color/residue-name.ts @@ -130,6 +130,7 @@ export function ResidueNameColorTheme(ctx: ThemeDataContext, props: PD.Values<Re export const ResidueNameColorThemeProvider: ColorTheme.Provider<ResidueNameColorThemeParams> = { label: 'Residue Name', + category: ColorTheme.Category.Basic, factory: ResidueNameColorTheme, getParams: getResidueNameColorThemeParams, defaultValues: PD.getDefaultValues(ResidueNameColorThemeParams), diff --git a/src/mol-theme/color/secondary-structure.ts b/src/mol-theme/color/secondary-structure.ts index 9eef3bb1c..6afa2dc1b 100644 --- a/src/mol-theme/color/secondary-structure.ts +++ b/src/mol-theme/color/secondary-structure.ts @@ -113,6 +113,7 @@ export function SecondaryStructureColorTheme(ctx: ThemeDataContext, props: PD.Va export const SecondaryStructureColorThemeProvider: ColorTheme.Provider<SecondaryStructureColorThemeParams> = { label: 'Secondary Structure', + category: ColorTheme.Category.Basic, factory: SecondaryStructureColorTheme, getParams: getSecondaryStructureColorThemeParams, defaultValues: PD.getDefaultValues(SecondaryStructureColorThemeParams), diff --git a/src/mol-theme/color/sequence-id.ts b/src/mol-theme/color/sequence-id.ts index 66457c0b5..90f5038ec 100644 --- a/src/mol-theme/color/sequence-id.ts +++ b/src/mol-theme/color/sequence-id.ts @@ -101,6 +101,7 @@ export function SequenceIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Seq export const SequenceIdColorThemeProvider: ColorTheme.Provider<SequenceIdColorThemeParams> = { label: 'Sequence Id', + category: ColorTheme.Category.Basic, factory: SequenceIdColorTheme, getParams: getSequenceIdColorThemeParams, defaultValues: PD.getDefaultValues(SequenceIdColorThemeParams), diff --git a/src/mol-theme/color/shape-group.ts b/src/mol-theme/color/shape-group.ts index 1c3166faf..d5b5ba87e 100644 --- a/src/mol-theme/color/shape-group.ts +++ b/src/mol-theme/color/shape-group.ts @@ -37,6 +37,7 @@ export function ShapeGroupColorTheme(ctx: ThemeDataContext, props: PD.Values<Sha export const ShapeGroupColorThemeProvider: ColorTheme.Provider<ShapeGroupColorThemeParams> = { label: 'Shape Group', + category: ColorTheme.Category.Advanced, factory: ShapeGroupColorTheme, getParams: getShapeGroupColorThemeParams, defaultValues: PD.getDefaultValues(ShapeGroupColorThemeParams), diff --git a/src/mol-theme/color/uncertainty.ts b/src/mol-theme/color/uncertainty.ts index d7511cb05..7e87f0127 100644 --- a/src/mol-theme/color/uncertainty.ts +++ b/src/mol-theme/color/uncertainty.ts @@ -64,6 +64,7 @@ export function UncertaintyColorTheme(ctx: ThemeDataContext, props: PD.Values<Un export const UncertaintyColorThemeProvider: ColorTheme.Provider<UncertaintyColorThemeParams> = { label: 'Uncertainty/Disorder', + category: ColorTheme.Category.Advanced, factory: UncertaintyColorTheme, getParams: getUncertaintyColorThemeParams, defaultValues: PD.getDefaultValues(UncertaintyColorThemeParams), diff --git a/src/mol-theme/color/uniform.ts b/src/mol-theme/color/uniform.ts index 6bc0e8bdc..e018b914d 100644 --- a/src/mol-theme/color/uniform.ts +++ b/src/mol-theme/color/uniform.ts @@ -37,6 +37,7 @@ export function UniformColorTheme(ctx: ThemeDataContext, props: PD.Values<Unifor export const UniformColorThemeProvider: ColorTheme.Provider<UniformColorThemeParams> = { label: 'Uniform', + category: ColorTheme.Category.Basic, factory: UniformColorTheme, getParams: getUniformColorThemeParams, defaultValues: PD.getDefaultValues(UniformColorThemeParams), diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts index bb6bb9c5b..bcd5e7314 100644 --- a/src/mol-theme/color/unit-index.ts +++ b/src/mol-theme/color/unit-index.ts @@ -73,6 +73,7 @@ export function UnitIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<Unit export const UnitIndexColorThemeProvider: ColorTheme.Provider<UnitIndexColorThemeParams> = { label: 'Unit Index', + category: ColorTheme.Category.Advanced, factory: UnitIndexColorTheme, getParams: getUnitIndexColorThemeParams, defaultValues: PD.getDefaultValues(UnitIndexColorThemeParams), diff --git a/src/mol-theme/size.ts b/src/mol-theme/size.ts index 71c79b8d2..2283474f7 100644 --- a/src/mol-theme/size.ts +++ b/src/mol-theme/size.ts @@ -32,7 +32,7 @@ namespace SizeTheme { } export interface Provider<P extends PD.Params> extends ThemeProvider<SizeTheme<P>, P> { } - export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } + export const EmptyProvider: Provider<{}> = { label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } export type Registry = ThemeRegistry<SizeTheme<any>> export function createRegistry() { diff --git a/src/mol-theme/size/physical.ts b/src/mol-theme/size/physical.ts index 4456ad209..8622967d1 100644 --- a/src/mol-theme/size/physical.ts +++ b/src/mol-theme/size/physical.ts @@ -58,6 +58,7 @@ export function PhysicalSizeTheme(ctx: ThemeDataContext, props: PD.Values<Physic export const PhysicalSizeThemeProvider: SizeTheme.Provider<PhysicalSizeThemeParams> = { label: 'Physical', + category: '', factory: PhysicalSizeTheme, getParams: getPhysicalSizeThemeParams, defaultValues: PD.getDefaultValues(PhysicalSizeThemeParams), diff --git a/src/mol-theme/size/shape-group.ts b/src/mol-theme/size/shape-group.ts index 2e2f867d5..b7eaa993f 100644 --- a/src/mol-theme/size/shape-group.ts +++ b/src/mol-theme/size/shape-group.ts @@ -36,6 +36,7 @@ export function ShapeGroupSizeTheme(ctx: ThemeDataContext, props: PD.Values<Shap export const ShapeGroupSizeThemeProvider: SizeTheme.Provider<ShapeGroupSizeThemeParams> = { label: 'Shape Group', + category: '', factory: ShapeGroupSizeTheme, getParams: getShapeGroupSizeThemeParams, defaultValues: PD.getDefaultValues(ShapeGroupSizeThemeParams), diff --git a/src/mol-theme/size/uncertainty.ts b/src/mol-theme/size/uncertainty.ts index 5f9da065b..bbeec0777 100644 --- a/src/mol-theme/size/uncertainty.ts +++ b/src/mol-theme/size/uncertainty.ts @@ -54,6 +54,7 @@ export function UncertaintySizeTheme(ctx: ThemeDataContext, props: PD.Values<Unc export const UncertaintySizeThemeProvider: SizeTheme.Provider<UncertaintySizeThemeParams> = { label: 'Uncertainty/Disorder', + category: '', factory: UncertaintySizeTheme, getParams: getUncertaintySizeThemeParams, defaultValues: PD.getDefaultValues(UncertaintySizeThemeParams), diff --git a/src/mol-theme/size/uniform.ts b/src/mol-theme/size/uniform.ts index 4d82bef10..32b271874 100644 --- a/src/mol-theme/size/uniform.ts +++ b/src/mol-theme/size/uniform.ts @@ -32,6 +32,7 @@ export function UniformSizeTheme(ctx: ThemeDataContext, props: PD.Values<Uniform export const UniformSizeThemeProvider: SizeTheme.Provider<UniformSizeThemeParams> = { label: 'Uniform', + category: '', factory: UniformSizeTheme, getParams: getUniformSizeThemeParams, defaultValues: PD.getDefaultValues(UniformSizeThemeParams), diff --git a/src/mol-theme/theme.ts b/src/mol-theme/theme.ts index ce5350a5a..d654af18e 100644 --- a/src/mol-theme/theme.ts +++ b/src/mol-theme/theme.ts @@ -60,7 +60,8 @@ namespace Theme { // export interface ThemeProvider<T extends ColorTheme<P> | SizeTheme<P>, P extends PD.Params> { - readonly label: string + readonly label: string + readonly category: string readonly factory: (ctx: ThemeDataContext, props: PD.Values<P>) => T readonly getParams: (ctx: ThemeDataContext) => P readonly defaultValues: PD.Values<P> @@ -69,7 +70,7 @@ export interface ThemeProvider<T extends ColorTheme<P> | SizeTheme<P>, P extends } function getTypes(list: { name: string, provider: ThemeProvider<any, any> }[]) { - return list.map(e => [e.name, e.provider.label] as [string, string]); + return list.map(e => [e.name, e.provider.label, e.provider.category] as [string, string, string]); } export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { @@ -79,16 +80,26 @@ export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { get default() { return this._list[0] } get list() { return this._list } - get types(): [string, string][] { return getTypes(this._list) } + get types(): [string, string, string][] { return getTypes(this._list) } constructor(builtInThemes: { [k: string]: ThemeProvider<T, any> }, private emptyProvider: ThemeProvider<T, any>) { Object.keys(builtInThemes).forEach(name => this.add(name, builtInThemes[name])) } + private sort() { + this._list.sort((a, b) => { + if (a.provider.category === b.provider.category) { + return a.provider.label < b.provider.label ? -1 : a.provider.label > b.provider.label ? 1 : 0; + } + return a.provider.category < b.provider.label ? -1 : 1; + }); + } + add<P extends PD.Params>(name: string, provider: ThemeProvider<T, P>) { this._list.push({ name, provider }) this._map.set(name, provider) this._name.set(provider, name) + this.sort(); } remove(name: string) { diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts index b2ccbedce..064528cf1 100644 --- a/src/mol-util/param-definition.ts +++ b/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])[] + options: readonly (readonly [T, string] | [T, string, string])[] } - export function Select<T extends string | number>(defaultValue: T, options: readonly (readonly [T, string])[], info?: Info): Select<T> { + export function Select<T extends string | number>(defaultValue: T, options: readonly (readonly [T, string] | [T, string, string])[], info?: Info): Select<T> { return setInfo<Select<T>>({ type: 'select', defaultValue: checkDefaultKey(defaultValue, options), options }, info) } @@ -201,7 +201,7 @@ export namespace ParamDefinition { select: Select<string>, map(name: string): Any } - export function Mapped<T>(defaultKey: string, names: [string, string][], map: (name: string) => Any, info?: Info): Mapped<NamedParams<T>> { + export function Mapped<T>(defaultKey: string, names: ([string, string] | [string, string, string])[], map: (name: string) => Any, info?: Info): Mapped<NamedParams<T>> { const name = checkDefaultKey(defaultKey, names); return setInfo<Mapped<NamedParams<T>>>({ type: 'mapped', @@ -406,7 +406,7 @@ export namespace ParamDefinition { return ret; } - function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string])[]) { + function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string] | [T, string, string])[]) { for (const o of options) { if (o[0] === k) return k; } -- GitLab