From 517de96d01da7ece156dcc6ced6075d065b6f54d Mon Sep 17 00:00:00 2001 From: Alexander Rose <alex.rose@rcsb.org> Date: Wed, 28 Nov 2018 16:20:42 -0800 Subject: [PATCH] theme registry refactoring, added .isApplicable method --- src/mol-app/component/color-theme.tsx | 2 +- src/mol-geo/geometry/color-data.ts | 2 +- src/mol-geo/geometry/size-data.ts | 2 +- .../rcsb/themes/assembly-symmetry-cluster.ts | 3 +- .../pdbe/structure-quality-report.ts | 6 +- .../custom-props/rcsb/assembly-symmetry.ts | 3 - src/mol-plugin/context.ts | 2 +- .../state/transforms/representation.ts | 18 +++--- src/mol-theme/color.ts | 56 +++-------------- src/mol-theme/color/carbohydrate-symbol.ts | 3 +- src/mol-theme/color/chain-id.ts | 3 +- src/mol-theme/color/cross-link.ts | 3 +- src/mol-theme/color/element-index.ts | 3 +- src/mol-theme/color/element-symbol.ts | 3 +- src/mol-theme/color/molecule-type.ts | 3 +- src/mol-theme/color/polymer-id.ts | 3 +- src/mol-theme/color/polymer-index.ts | 3 +- src/mol-theme/color/residue-name.ts | 3 +- src/mol-theme/color/secondary-structure.ts | 3 +- src/mol-theme/color/sequence-id.ts | 3 +- src/mol-theme/color/shape-group.ts | 3 +- src/mol-theme/color/uniform.ts | 3 +- src/mol-theme/color/unit-index.ts | 3 +- src/mol-theme/size.ts | 56 +++-------------- src/mol-theme/size/physical.ts | 3 +- src/mol-theme/size/uniform.ts | 3 +- src/mol-theme/theme.ts | 61 ++++++++++++++++++- 27 files changed, 126 insertions(+), 133 deletions(-) diff --git a/src/mol-app/component/color-theme.tsx b/src/mol-app/component/color-theme.tsx index e546c25bd..bf3c58078 100644 --- a/src/mol-app/component/color-theme.tsx +++ b/src/mol-app/component/color-theme.tsx @@ -9,7 +9,7 @@ import { ColorTheme } from 'mol-theme/color'; import { Color } from 'mol-util/color'; export interface ColorThemeComponentProps { - colorTheme: ColorTheme + colorTheme: ColorTheme<any> } export interface ColorThemeComponentState { diff --git a/src/mol-geo/geometry/color-data.ts b/src/mol-geo/geometry/color-data.ts index 43c2bd310..1f4fb376a 100644 --- a/src/mol-geo/geometry/color-data.ts +++ b/src/mol-geo/geometry/color-data.ts @@ -22,7 +22,7 @@ export type ColorData = { dColorType: ValueCell<string>, } -export function createColors(locationIt: LocationIterator, colorTheme: ColorTheme, colorData?: ColorData): ColorData { +export function createColors(locationIt: LocationIterator, colorTheme: ColorTheme<any>, colorData?: ColorData): ColorData { switch (getGranularity(locationIt, colorTheme.granularity)) { case 'uniform': return createUniformColor(locationIt, colorTheme.color, colorData) case 'group': return createGroupColor(locationIt, colorTheme.color, colorData) diff --git a/src/mol-geo/geometry/size-data.ts b/src/mol-geo/geometry/size-data.ts index a1651cc4b..6cb0e8b75 100644 --- a/src/mol-geo/geometry/size-data.ts +++ b/src/mol-geo/geometry/size-data.ts @@ -21,7 +21,7 @@ export type SizeData = { dSizeType: ValueCell<string>, } -export function createSizes(locationIt: LocationIterator, sizeTheme: SizeTheme, sizeData?: SizeData): SizeData { +export function createSizes(locationIt: LocationIterator, sizeTheme: SizeTheme<any>, sizeData?: SizeData): SizeData { switch (getGranularity(locationIt, sizeTheme.granularity)) { case 'uniform': return createUniformSize(locationIt, sizeTheme.size, sizeData) case 'group': return createGroupSize(locationIt, sizeTheme.size, sizeData) 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 7bfbff51a..d739f926c 100644 --- a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts +++ b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts @@ -113,5 +113,6 @@ export const AssemblySymmetryClusterColorThemeProvider: ColorTheme.Provider<Asse label: 'RCSB Assembly Symmetry Cluster', factory: AssemblySymmetryClusterColorTheme, getParams: getAssemblySymmetryClusterColorThemeParams, - defaultValues: PD.getDefaultValues(AssemblySymmetryClusterColorThemeParams) + defaultValues: PD.getDefaultValues(AssemblySymmetryClusterColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.models[0].customProperties.has(AssemblySymmetry.Descriptor) } \ No newline at end of file diff --git a/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts b/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts index 948edad6c..61a09e969 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts @@ -12,6 +12,7 @@ import { StructureElement } from 'mol-model/structure'; import { CustomPropertyRegistry } from 'mol-plugin/util/custom-prop-registry'; import { ParamDefinition as PD } from 'mol-util/param-definition'; import { PluginBehavior } from '../../../behavior'; +import { ThemeDataContext } from 'mol-theme/theme'; export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: boolean }>({ name: 'pdbe-structure-quality-report-prop', @@ -34,13 +35,12 @@ export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: bo this.ctx.customModelProperties.register(this.provider); this.ctx.lociLabels.addProvider(labelPDBeValidation); - // TODO: support filtering of themes based on the input structure - // in this case, it would check structure.models[0].customProperties.has(StructureQualityReport.Descriptor) this.ctx.structureRepresentation.themeCtx.colorThemeRegistry.add('pdbe-structure-quality-report', { label: 'PDBe Structure Quality Report', factory: StructureQualityReportColorTheme, getParams: () => ({}), - defaultValues: {} + defaultValues: {}, + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.models[0].customProperties.has(StructureQualityReport.Descriptor) }) } diff --git a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts index e7c7ce4f5..5fac25309 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts @@ -31,9 +31,6 @@ export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean register(): void { this.ctx.customModelProperties.register(this.provider); this.ctx.lociLabels.addProvider(labelAssemblySymmetryAxes); - - // TODO: support filtering of themes and representations based on the input structure - // in this case, it would check structure.models[0].customProperties.has(AssemblySymmetry.Descriptor) this.ctx.structureRepresentation.themeCtx.colorThemeRegistry.add('rcsb-assembly-symmetry-cluster', AssemblySymmetryClusterColorThemeProvider) this.ctx.structureRepresentation.registry.add('rcsb-assembly-symmetry-axes', AssemblySymmetryAxesRepresentationProvider) } diff --git a/src/mol-plugin/context.ts b/src/mol-plugin/context.ts index 588fc0dc6..069805cb0 100644 --- a/src/mol-plugin/context.ts +++ b/src/mol-plugin/context.ts @@ -73,7 +73,7 @@ export class PluginContext { readonly structureRepresentation = { registry: new StructureRepresentationRegistry(), - themeCtx: { colorThemeRegistry: new ColorTheme.Registry(), sizeThemeRegistry: new SizeTheme.Registry() } as ThemeRegistryContext + themeCtx: { colorThemeRegistry: ColorTheme.createRegistry(), sizeThemeRegistry: SizeTheme.createRegistry() } as ThemeRegistryContext } readonly customModelProperties = new CustomPropertyRegistry(); diff --git a/src/mol-plugin/state/transforms/representation.ts b/src/mol-plugin/state/transforms/representation.ts index 443148667..942816e5e 100644 --- a/src/mol-plugin/state/transforms/representation.ts +++ b/src/mol-plugin/state/transforms/representation.ts @@ -50,21 +50,23 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ from: SO.Molecule.Structure, to: SO.Molecule.Representation3D, params: (a, ctx: PluginContext) => { - const type = ctx.structureRepresentation.registry.get(ctx.structureRepresentation.registry.default.name); + const { registry, themeCtx } = ctx.structureRepresentation + const type = registry.get(registry.default.name); + const dataCtx = { structure: a.data } return ({ type: PD.Mapped<any>( - ctx.structureRepresentation.registry.default.name, - ctx.structureRepresentation.registry.types, - name => PD.Group<any>(ctx.structureRepresentation.registry.get(name).getParams(ctx.structureRepresentation.themeCtx, a.data))), + registry.default.name, + registry.types, + name => PD.Group<any>(registry.get(name).getParams(themeCtx, a.data))), colorTheme: PD.Mapped<any>( type.defaultColorTheme, - ctx.structureRepresentation.themeCtx.colorThemeRegistry.types, - name => PD.Group<any>(ctx.structureRepresentation.themeCtx.colorThemeRegistry.get(name).getParams({ structure: a.data })) + themeCtx.colorThemeRegistry.getApplicableTypes(dataCtx), + name => PD.Group<any>(themeCtx.colorThemeRegistry.get(name).getParams(dataCtx)) ), sizeTheme: PD.Mapped<any>( type.defaultSizeTheme, - ctx.structureRepresentation.themeCtx.sizeThemeRegistry.types, - name => PD.Group<any>(ctx.structureRepresentation.themeCtx.sizeThemeRegistry.get(name).getParams({ structure: a.data })) + themeCtx.sizeThemeRegistry.types, + name => PD.Group<any>(themeCtx.sizeThemeRegistry.get(name).getParams(dataCtx)) ) }) } diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts index 75bbc2eee..ba17219d3 100644 --- a/src/mol-theme/color.ts +++ b/src/mol-theme/color.ts @@ -11,7 +11,7 @@ import { CarbohydrateSymbolColorThemeProvider } from './color/carbohydrate-symbo import { UniformColorThemeProvider } from './color/uniform'; import { deepEqual } from 'mol-util'; import { ParamDefinition as PD } from 'mol-util/param-definition'; -import { ThemeDataContext } from './theme'; +import { ThemeDataContext, ThemeRegistry, ThemeProvider } from './theme'; import { ChainIdColorThemeProvider } from './color/chain-id'; import { CrossLinkColorThemeProvider } from './color/cross-link'; import { ElementIndexColorThemeProvider } from './color/element-index'; @@ -32,7 +32,7 @@ export type LocationColor = (location: Location, isSecondary: boolean) => Color export type ColorThemeProps = { [k: string]: any } export { ColorTheme } -interface ColorTheme<P extends PD.Params = {}> { +interface ColorTheme<P extends PD.Params> { readonly factory: ColorTheme.Factory<P> readonly granularity: ColorType readonly color: LocationColor @@ -47,56 +47,16 @@ namespace ColorTheme { const EmptyColor = Color(0xCCCCCC) export const Empty: ColorTheme<{}> = { factory: EmptyFactory, granularity: 'uniform', color: () => EmptyColor, props: {} } - export function areEqual(themeA: ColorTheme, themeB: ColorTheme) { + export function areEqual(themeA: ColorTheme<any>, themeB: ColorTheme<any>) { return themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props) } - export interface Provider<P extends PD.Params> { - readonly label: string - readonly factory: (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P> - readonly getParams: (ctx: ThemeDataContext) => P - readonly defaultValues: PD.Values<P> - } - export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {} } - - export class Registry { - private _list: { name: string, provider: Provider<any> }[] = [] - private _map = new Map<string, Provider<any>>() - - get default() { return this._list[0]; } - get types(): [string, string][] { - return this._list.map(e => [e.name, e.provider.label] as [string, string]); - } - - constructor() { - Object.keys(BuiltInColorThemes).forEach(name => { - const p = (BuiltInColorThemes as { [k: string]: Provider<any> })[name] - this.add(name, p) - }) - } - - add<P extends PD.Params>(name: string, provider: Provider<P>) { - this._list.push({ name, provider }) - this._map.set(name, provider) - } - - remove(name: string) { - this._list.splice(this._list.findIndex(e => e.name === name)) - this._map.delete(name) - } - - get<P extends PD.Params>(name: string): Provider<P> { - return this._map.get(name) || EmptyProvider as unknown as Provider<P> - } - - create(name: string, ctx: ThemeDataContext, props = {}) { - const provider = this.get(name) - return provider.factory(ctx, { ...PD.getDefaultValues(provider.getParams(ctx)), ...props }) - } + export interface Provider<P extends PD.Params> extends ThemeProvider<ColorTheme<P>, P> { } + export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } - get list() { - return this._list - } + export type Registry = ThemeRegistry<ColorTheme<any>> + export function createRegistry() { + return new ThemeRegistry(BuiltInColorThemes as { [k: string]: Provider<any> }, EmptyProvider) } } diff --git a/src/mol-theme/color/carbohydrate-symbol.ts b/src/mol-theme/color/carbohydrate-symbol.ts index 550c8f35d..72c7382c1 100644 --- a/src/mol-theme/color/carbohydrate-symbol.ts +++ b/src/mol-theme/color/carbohydrate-symbol.ts @@ -78,5 +78,6 @@ export const CarbohydrateSymbolColorThemeProvider: ColorTheme.Provider<Carbohydr label: 'Carbohydrate Symbol', factory: CarbohydrateSymbolColorTheme, getParams: getCarbohydrateSymbolColorThemeParams, - defaultValues: PD.getDefaultValues(CarbohydrateSymbolColorThemeParams) + defaultValues: PD.getDefaultValues(CarbohydrateSymbolColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts index eb37bf31c..c89d06002 100644 --- a/src/mol-theme/color/chain-id.ts +++ b/src/mol-theme/color/chain-id.ts @@ -95,5 +95,6 @@ export const ChainIdColorThemeProvider: ColorTheme.Provider<ChainIdColorThemePar label: 'Chain Id', factory: ChainIdColorTheme, getParams: getChainIdColorThemeParams, - defaultValues: PD.getDefaultValues(ChainIdColorThemeParams) + defaultValues: PD.getDefaultValues(ChainIdColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/cross-link.ts b/src/mol-theme/color/cross-link.ts index bfe6cc0ac..d3cdf4b80 100644 --- a/src/mol-theme/color/cross-link.ts +++ b/src/mol-theme/color/cross-link.ts @@ -72,5 +72,6 @@ export const CrossLinkColorThemeProvider: ColorTheme.Provider<CrossLinkColorThem label: 'Cross Link', factory: CrossLinkColorTheme, getParams: getCrossLinkColorThemeParams, - defaultValues: PD.getDefaultValues(CrossLinkColorThemeParams) + defaultValues: PD.getDefaultValues(CrossLinkColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts index c650f6c99..3636026ab 100644 --- a/src/mol-theme/color/element-index.ts +++ b/src/mol-theme/color/element-index.ts @@ -72,5 +72,6 @@ export const ElementIndexColorThemeProvider: ColorTheme.Provider<ElementIndexCol label: 'Element Index', factory: ElementIndexColorTheme, getParams: getElementIndexColorThemeParams, - defaultValues: PD.getDefaultValues(ElementIndexColorThemeParams) + defaultValues: PD.getDefaultValues(ElementIndexColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/element-symbol.ts b/src/mol-theme/color/element-symbol.ts index bc15c9f23..28055bab2 100644 --- a/src/mol-theme/color/element-symbol.ts +++ b/src/mol-theme/color/element-symbol.ts @@ -64,5 +64,6 @@ export const ElementSymbolColorThemeProvider: ColorTheme.Provider<ElementSymbolC label: 'Element Symbol', factory: ElementSymbolColorTheme, getParams: getElementSymbolColorThemeParams, - defaultValues: PD.getDefaultValues(ElementSymbolColorThemeParams) + defaultValues: PD.getDefaultValues(ElementSymbolColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/molecule-type.ts b/src/mol-theme/color/molecule-type.ts index b91c557af..ad643930c 100644 --- a/src/mol-theme/color/molecule-type.ts +++ b/src/mol-theme/color/molecule-type.ts @@ -73,5 +73,6 @@ export const MoleculeTypeColorThemeProvider: ColorTheme.Provider<MoleculeTypeCol label: 'Molecule Type', factory: MoleculeTypeColorTheme, getParams: getMoleculeTypeColorThemeParams, - defaultValues: PD.getDefaultValues(MoleculeTypeColorThemeParams) + defaultValues: PD.getDefaultValues(MoleculeTypeColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/polymer-id.ts b/src/mol-theme/color/polymer-id.ts index 41b92030a..87c1c75ae 100644 --- a/src/mol-theme/color/polymer-id.ts +++ b/src/mol-theme/color/polymer-id.ts @@ -102,5 +102,6 @@ export const PolymerIdColorThemeProvider: ColorTheme.Provider<PolymerIdColorThem label: 'Polymer Id', factory: PolymerIdColorTheme, getParams: getPolymerIdColorThemeParams, - defaultValues: PD.getDefaultValues(PolymerIdColorThemeParams) + defaultValues: PD.getDefaultValues(PolymerIdColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts index a51257fc8..d13fe8d17 100644 --- a/src/mol-theme/color/polymer-index.ts +++ b/src/mol-theme/color/polymer-index.ts @@ -70,5 +70,6 @@ export const PolymerIndexColorThemeProvider: ColorTheme.Provider<PolymerIndexCol label: 'Polymer Index', factory: PolymerIndexColorTheme, getParams: getPolymerIndexColorThemeParams, - defaultValues: PD.getDefaultValues(PolymerIndexColorThemeParams) + defaultValues: PD.getDefaultValues(PolymerIndexColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/residue-name.ts b/src/mol-theme/color/residue-name.ts index 682ae8a4b..999bf2a9b 100644 --- a/src/mol-theme/color/residue-name.ts +++ b/src/mol-theme/color/residue-name.ts @@ -129,5 +129,6 @@ export const ResidueNameColorThemeProvider: ColorTheme.Provider<ResidueNameColor label: 'Residue Name', factory: ResidueNameColorTheme, getParams: getResidueNameColorThemeParams, - defaultValues: PD.getDefaultValues(ResidueNameColorThemeParams) + defaultValues: PD.getDefaultValues(ResidueNameColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/secondary-structure.ts b/src/mol-theme/color/secondary-structure.ts index 6f2d094fe..384c5fb0b 100644 --- a/src/mol-theme/color/secondary-structure.ts +++ b/src/mol-theme/color/secondary-structure.ts @@ -96,5 +96,6 @@ export const SecondaryStructureColorThemeProvider: ColorTheme.Provider<Secondary label: 'Secondary Structure', factory: SecondaryStructureColorTheme, getParams: getSecondaryStructureColorThemeParams, - defaultValues: PD.getDefaultValues(SecondaryStructureColorThemeParams) + defaultValues: PD.getDefaultValues(SecondaryStructureColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/sequence-id.ts b/src/mol-theme/color/sequence-id.ts index cb8e49ffa..b0dd084b6 100644 --- a/src/mol-theme/color/sequence-id.ts +++ b/src/mol-theme/color/sequence-id.ts @@ -103,5 +103,6 @@ export const SequenceIdColorThemeProvider: ColorTheme.Provider<SequenceIdColorTh label: 'Sequence Id', factory: SequenceIdColorTheme, getParams: getSequenceIdColorThemeParams, - defaultValues: PD.getDefaultValues(SequenceIdColorThemeParams) + defaultValues: PD.getDefaultValues(SequenceIdColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/color/shape-group.ts b/src/mol-theme/color/shape-group.ts index b6cbba700..66c51e853 100644 --- a/src/mol-theme/color/shape-group.ts +++ b/src/mol-theme/color/shape-group.ts @@ -39,5 +39,6 @@ export const ShapeGroupColorThemeProvider: ColorTheme.Provider<ShapeGroupColorTh label: 'Shape Group', factory: ShapeGroupColorTheme, getParams: getShapeGroupColorThemeParams, - defaultValues: PD.getDefaultValues(ShapeGroupColorThemeParams) + defaultValues: PD.getDefaultValues(ShapeGroupColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.shape } \ No newline at end of file diff --git a/src/mol-theme/color/uniform.ts b/src/mol-theme/color/uniform.ts index 8c702a998..c18b62c9a 100644 --- a/src/mol-theme/color/uniform.ts +++ b/src/mol-theme/color/uniform.ts @@ -38,5 +38,6 @@ export const UniformColorThemeProvider: ColorTheme.Provider<UniformColorThemePar label: 'Uniform', factory: UniformColorTheme, getParams: getUniformColorThemeParams, - defaultValues: PD.getDefaultValues(UniformColorThemeParams) + defaultValues: PD.getDefaultValues(UniformColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => true } \ No newline at end of file diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts index 4f9d14883..ac25d5113 100644 --- a/src/mol-theme/color/unit-index.ts +++ b/src/mol-theme/color/unit-index.ts @@ -61,5 +61,6 @@ export const UnitIndexColorThemeProvider: ColorTheme.Provider<UnitIndexColorThem label: 'Unit Index', factory: UnitIndexColorTheme, getParams: getUnitIndexColorThemeParams, - defaultValues: PD.getDefaultValues(UnitIndexColorThemeParams) + defaultValues: PD.getDefaultValues(UnitIndexColorThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/size.ts b/src/mol-theme/size.ts index 16179eb0d..11dd21588 100644 --- a/src/mol-theme/size.ts +++ b/src/mol-theme/size.ts @@ -7,12 +7,12 @@ import { SizeType, LocationSize } from 'mol-geo/geometry/size-data'; import { UniformSizeThemeProvider } from './size/uniform'; import { ParamDefinition as PD } from 'mol-util/param-definition'; -import { ThemeDataContext } from 'mol-theme/theme'; +import { ThemeDataContext, ThemeRegistry, ThemeProvider } from 'mol-theme/theme'; import { PhysicalSizeThemeProvider } from './size/physical'; import { deepEqual } from 'mol-util'; export { SizeTheme } -interface SizeTheme<P extends PD.Params = {}> { +interface SizeTheme<P extends PD.Params> { readonly factory: SizeTheme.Factory<P> readonly granularity: SizeType readonly size: LocationSize @@ -25,56 +25,16 @@ namespace SizeTheme { export const EmptyFactory = () => Empty export const Empty: SizeTheme<{}> = { factory: EmptyFactory, granularity: 'uniform', size: () => 1, props: {} } - export function areEqual(themeA: SizeTheme, themeB: SizeTheme) { + export function areEqual(themeA: SizeTheme<any>, themeB: SizeTheme<any>) { return themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props) } - export interface Provider<P extends PD.Params> { - readonly label: string - readonly factory: Factory<P> - readonly getParams: (ctx: ThemeDataContext) => P - readonly defaultValues: PD.Values<P> - } - export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {} } - - export class Registry { - private _list: { name: string, provider: Provider<any> }[] = [] - private _map = new Map<string, Provider<any>>() - - get default() { return this._list[0]; } - get types(): [string, string][] { - return this._list.map(e => [e.name, e.provider.label] as [string, string]); - } - - constructor() { - Object.keys(BuiltInSizeThemes).forEach(name => { - const p = (BuiltInSizeThemes as { [k: string]: Provider<any> })[name] - this.add(name, p) - }) - } - - add<P extends PD.Params>(name: string, provider: Provider<P>) { - this._list.push({ name, provider }) - this._map.set(name, provider) - } - - remove(name: string) { - this._list.splice(this._list.findIndex(e => e.name === name)) - this._map.delete(name) - } - - get<P extends PD.Params>(name: string): Provider<P> { - return this._map.get(name) || EmptyProvider as unknown as Provider<P> - } - - create(name: string, ctx: ThemeDataContext, props = {}) { - const provider = this.get(name) - return provider.factory(ctx, { ...PD.getDefaultValues(provider.getParams(ctx)), ...props }) - } + export interface Provider<P extends PD.Params> extends ThemeProvider<SizeTheme<P>, P> { } + export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } - get list() { - return this._list - } + export type Registry = ThemeRegistry<SizeTheme<any>> + export function createRegistry() { + return new ThemeRegistry(BuiltInSizeThemes as { [k: string]: Provider<any> }, EmptyProvider) } } diff --git a/src/mol-theme/size/physical.ts b/src/mol-theme/size/physical.ts index b856912c4..3d141c045 100644 --- a/src/mol-theme/size/physical.ts +++ b/src/mol-theme/size/physical.ts @@ -60,5 +60,6 @@ export const PhysicalSizeThemeProvider: SizeTheme.Provider<PhysicalSizeThemePara label: 'Physical', factory: PhysicalSizeTheme, getParams: getPhysicalSizeThemeParams, - defaultValues: PD.getDefaultValues(PhysicalSizeThemeParams) + defaultValues: PD.getDefaultValues(PhysicalSizeThemeParams), + isApplicable: (ctx: ThemeDataContext) => !!ctx.structure } \ No newline at end of file diff --git a/src/mol-theme/size/uniform.ts b/src/mol-theme/size/uniform.ts index 3d91d0c35..69c7fd832 100644 --- a/src/mol-theme/size/uniform.ts +++ b/src/mol-theme/size/uniform.ts @@ -34,5 +34,6 @@ export const UniformSizeThemeProvider: SizeTheme.Provider<UniformSizeThemeParams label: 'Uniform', factory: UniformSizeTheme, getParams: getUniformSizeThemeParams, - defaultValues: PD.getDefaultValues(UniformSizeThemeParams) + defaultValues: PD.getDefaultValues(UniformSizeThemeParams), + isApplicable: (ctx: ThemeDataContext) => true } \ No newline at end of file diff --git a/src/mol-theme/theme.ts b/src/mol-theme/theme.ts index ad2222c38..7808942b8 100644 --- a/src/mol-theme/theme.ts +++ b/src/mol-theme/theme.ts @@ -9,6 +9,7 @@ import { SizeTheme } from './size'; import { Structure } from 'mol-model/structure'; import { VolumeData } from 'mol-model/volume'; import { ParamDefinition as PD } from 'mol-util/param-definition'; +import { Shape } from 'mol-model/shape'; export interface ThemeRegistryContext { colorThemeRegistry: ColorTheme.Registry @@ -19,11 +20,12 @@ export interface ThemeDataContext { [k: string]: any structure?: Structure volume?: VolumeData + shape?: Shape } export interface Theme { - color: ColorTheme - size: SizeTheme + color: ColorTheme<any> + size: SizeTheme<any> // label: LabelTheme // TODO } @@ -43,4 +45,59 @@ export function createTheme(ctx: ThemeRegistryContext, data: ThemeDataContext, p export function createEmptyTheme(): Theme { return { color: ColorTheme.Empty, size: SizeTheme.Empty } +} + +// + +export interface ThemeProvider<T extends ColorTheme<P> | SizeTheme<P>, P extends PD.Params> { + readonly label: string + readonly factory: (ctx: ThemeDataContext, props: PD.Values<P>) => T + readonly getParams: (ctx: ThemeDataContext) => P + readonly defaultValues: PD.Values<P> + readonly isApplicable: (ctx: ThemeDataContext) => boolean +} + +function getTypes(list: { name: string, provider: ThemeProvider<any, any> }[]) { + return list.map(e => [e.name, e.provider.label] as [string, string]); +} + +export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { + private _list: { name: string, provider: ThemeProvider<T, any> }[] = [] + private _map = new Map<string, ThemeProvider<T, any>>() + + get default() { return this._list[0]; } + get list() { return this._list } + get types(): [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])) + } + + add<P extends PD.Params>(name: string, provider: ThemeProvider<T, P>) { + this._list.push({ name, provider }) + this._map.set(name, provider) + } + + remove(name: string) { + this._list.splice(this._list.findIndex(e => e.name === name)) + this._map.delete(name) + console.log('removed', name, this._list, this._map) + } + + get<P extends PD.Params>(name: string): ThemeProvider<T, P> { + return this._map.get(name) || this.emptyProvider + } + + create(name: string, ctx: ThemeDataContext, props = {}) { + const provider = this.get(name) + return provider.factory(ctx, { ...PD.getDefaultValues(provider.getParams(ctx)), ...props }) + } + + getApplicableList(ctx: ThemeDataContext) { + return this._list.filter(e => e.provider.isApplicable(ctx)); + } + + getApplicableTypes(ctx: ThemeDataContext) { + return getTypes(this.getApplicableList(ctx)) + } } \ No newline at end of file -- GitLab