object.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { UUID } from 'mol-util';
  7. import { StateTransform } from './transform';
  8. import { ParamDefinition } from 'mol-util/param-definition';
  9. import { State } from './state';
  10. import { StateSelection, StateTransformer } from 'mol-state';
  11. export { StateObject, StateObjectCell }
  12. interface StateObject<D = any, T extends StateObject.Type = StateObject.Type<any>> {
  13. readonly id: UUID,
  14. readonly type: T,
  15. readonly data: D,
  16. readonly label: string,
  17. readonly description?: string,
  18. // assigned by reconciler to be StateTransform.props.tag
  19. readonly tag?: string
  20. }
  21. namespace StateObject {
  22. export function factory<T extends Type>() {
  23. return <D = { }>(type: T) => create<D, T>(type);
  24. }
  25. export type Type<Cls extends string = string> = { name: string, typeClass: Cls }
  26. export type Ctor<T extends StateObject = StateObject> = { new(...args: any[]): T, type: any }
  27. export type From<C extends Ctor> = C extends Ctor<infer T> ? T : never
  28. export function create<Data, T extends Type>(type: T) {
  29. return class O implements StateObject<Data, T> {
  30. static type = type;
  31. static is(obj?: StateObject): obj is O { return !!obj && type === obj.type; }
  32. id = UUID.create22();
  33. type = type;
  34. label: string;
  35. description?: string;
  36. constructor(public data: Data, props?: { label: string, description?: string }) {
  37. this.label = props && props.label || type.name;
  38. this.description = props && props.description;
  39. }
  40. }
  41. }
  42. /** A special object indicating a transformer result has no value. */
  43. export const Null: StateObject<any, any> = {
  44. id: UUID.create22(),
  45. type: { name: 'Null', typeClass: 'Null' },
  46. data: void 0,
  47. label: 'Null'
  48. };
  49. }
  50. interface StateObjectCell<T extends StateObject = StateObject, F extends StateTransform<StateTransformer<any, T, any>> = StateTransform<StateTransformer<any, T, any>>> {
  51. transform: F,
  52. // Which object was used as a parent to create data in this cell
  53. sourceRef: StateTransform.Ref | undefined,
  54. status: StateObjectCell.Status,
  55. params: {
  56. definition: ParamDefinition.Params,
  57. values: any
  58. } | undefined;
  59. errorText?: string,
  60. obj?: T,
  61. cache: unknown | undefined
  62. }
  63. namespace StateObjectCell {
  64. export type Status = 'ok' | 'error' | 'pending' | 'processing'
  65. export type Obj<C extends StateObjectCell> = C extends StateObjectCell<infer T> ? T : never
  66. export type Transform<C extends StateObjectCell> = C extends StateObjectCell<any, infer T> ? T : never
  67. export interface State {
  68. isHidden: boolean,
  69. isCollapsed: boolean
  70. }
  71. export const DefaultState: State = { isHidden: false, isCollapsed: false };
  72. export function areStatesEqual(a: State, b: State) {
  73. return a.isHidden !== b.isHidden || a.isCollapsed !== b.isCollapsed;
  74. }
  75. export function isStateChange(a: State, b?: Partial<State>) {
  76. if (!b) return false;
  77. if (typeof b.isCollapsed !== 'undefined' && a.isCollapsed !== b.isCollapsed) return true;
  78. if (typeof b.isHidden !== 'undefined' && a.isHidden !== b.isHidden) return true;
  79. return false;
  80. }
  81. }
  82. // TODO: improve the API?
  83. export class StateObjectTracker<T extends StateObject> {
  84. private query: StateSelection.Query;
  85. private version: string = '';
  86. cell: StateObjectCell | undefined;
  87. data: T['data'] | undefined;
  88. setQuery(sel: StateSelection.Selector) {
  89. this.query = StateSelection.compile(sel);
  90. }
  91. update() {
  92. const cell = this.state.select(this.query)[0];
  93. const version = cell ? cell.transform.version : void 0;
  94. const changed = this.cell !== cell || this.version !== version;
  95. this.cell = cell;
  96. this.version = version || '';
  97. this.data = cell && cell.obj ? cell.obj.data as T : void 0 as any;
  98. return changed;
  99. }
  100. constructor(private state: State) { }
  101. }