color.ts 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { Color } from 'mol-util/color';
  7. import { Location } from 'mol-model/location';
  8. import { ColorType } from 'mol-geo/geometry/color-data';
  9. import { CarbohydrateSymbolColorThemeProvider } from './color/carbohydrate-symbol';
  10. import { UniformColorThemeProvider } from './color/uniform';
  11. import { deepEqual } from 'mol-util';
  12. import { ParamDefinition as PD } from 'mol-util/param-definition';
  13. import { ThemeDataContext } from './theme';
  14. import { ChainIdColorThemeProvider } from './color/chain-id';
  15. import { CrossLinkColorThemeProvider } from './color/cross-link';
  16. import { ElementIndexColorThemeProvider } from './color/element-index';
  17. import { ElementSymbolColorThemeProvider } from './color/element-symbol';
  18. import { MoleculeTypeColorThemeProvider } from './color/molecule-type';
  19. import { PolymerIdColorThemeProvider } from './color/polymer-id';
  20. import { PolymerIndexColorThemeProvider } from './color/polymer-index';
  21. import { ResidueNameColorThemeProvider } from './color/residue-name';
  22. import { SecondaryStructureColorThemeProvider } from './color/secondary-structure';
  23. import { SequenceIdColorThemeProvider } from './color/sequence-id';
  24. import { ShapeGroupColorThemeProvider } from './color/shape-group';
  25. import { UnitIndexColorThemeProvider } from './color/unit-index';
  26. import { ScaleLegend } from 'mol-util/color/scale';
  27. import { TableLegend } from 'mol-util/color/tables';
  28. export type LocationColor = (location: Location, isSecondary: boolean) => Color
  29. export type ColorThemeProps = { [k: string]: any }
  30. export { ColorTheme }
  31. interface ColorTheme<P extends PD.Params = {}> {
  32. readonly factory: ColorTheme.Factory<P>
  33. readonly granularity: ColorType
  34. readonly color: LocationColor
  35. readonly props: Readonly<PD.Values<P>>
  36. readonly description?: string
  37. readonly legend?: Readonly<ScaleLegend | TableLegend>
  38. }
  39. namespace ColorTheme {
  40. export type Props = { [k: string]: any }
  41. export type Factory<P extends PD.Params> = (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P>
  42. export const EmptyFactory = () => Empty
  43. const EmptyColor = Color(0xCCCCCC)
  44. export const Empty: ColorTheme<{}> = { factory: EmptyFactory, granularity: 'uniform', color: () => EmptyColor, props: {} }
  45. export function areEqual(themeA: ColorTheme, themeB: ColorTheme) {
  46. return themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props)
  47. }
  48. export interface Provider<P extends PD.Params> {
  49. readonly label: string
  50. readonly factory: (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P>
  51. readonly getParams: (ctx: ThemeDataContext) => P
  52. readonly defaultValues: PD.Values<P>
  53. }
  54. export const EmptyProvider: Provider<{}> = { label: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {} }
  55. export class Registry {
  56. private _list: { name: string, provider: Provider<any> }[] = []
  57. private _map = new Map<string, Provider<any>>()
  58. get default() { return this._list[0]; }
  59. get types(): [string, string][] {
  60. return this._list.map(e => [e.name, e.provider.label] as [string, string]);
  61. }
  62. constructor() {
  63. Object.keys(BuiltInColorThemes).forEach(name => {
  64. const p = (BuiltInColorThemes as { [k: string]: Provider<any> })[name]
  65. this.add(name, p)
  66. })
  67. }
  68. add<P extends PD.Params>(name: string, provider: Provider<P>) {
  69. this._list.push({ name, provider })
  70. this._map.set(name, provider)
  71. }
  72. remove(name: string) {
  73. this._list.splice(this._list.findIndex(e => e.name === name))
  74. this._map.delete(name)
  75. }
  76. get<P extends PD.Params>(name: string): Provider<P> {
  77. return this._map.get(name) || EmptyProvider as unknown as Provider<P>
  78. }
  79. create(id: string, ctx: ThemeDataContext, props = {}) {
  80. const provider = this.get(id)
  81. return provider ? provider.factory(ctx, { ...PD.getDefaultValues(provider.getParams(ctx)), ...props }) : Empty
  82. }
  83. get list() {
  84. return this._list
  85. }
  86. }
  87. }
  88. export const BuiltInColorThemes = {
  89. 'carbohydrate-symbol': CarbohydrateSymbolColorThemeProvider,
  90. 'chain-id': ChainIdColorThemeProvider,
  91. 'cross-link': CrossLinkColorThemeProvider,
  92. 'element-index': ElementIndexColorThemeProvider,
  93. 'element-symbol': ElementSymbolColorThemeProvider,
  94. 'molecule-type': MoleculeTypeColorThemeProvider,
  95. 'polymer-id': PolymerIdColorThemeProvider,
  96. 'polymer-index': PolymerIndexColorThemeProvider,
  97. 'residue-name': ResidueNameColorThemeProvider,
  98. 'secondary-structure': SecondaryStructureColorThemeProvider,
  99. 'sequence-id': SequenceIdColorThemeProvider,
  100. 'shape-group': ShapeGroupColorThemeProvider,
  101. 'unit-index': UnitIndexColorThemeProvider,
  102. 'uniform': UniformColorThemeProvider,
  103. }