object.ts 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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 { Transform } from './transform';
  8. import { ParamDefinition } from 'mol-util/param-definition';
  9. import { State } from './state';
  10. import { StateSelection } from './state/selection';
  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. }
  19. namespace StateObject {
  20. export function factory<T extends Type>() {
  21. return <D = { }>(type: T) => create<D, T>(type);
  22. }
  23. export type Type<Cls extends string = string> = { name: string, typeClass: Cls }
  24. export type Ctor<T extends StateObject = StateObject> = { new(...args: any[]): T, type: any }
  25. export type From<C extends Ctor> = C extends Ctor<infer T> ? T : never
  26. export function create<Data, T extends Type>(type: T) {
  27. return class O implements StateObject<Data, T> {
  28. static type = type;
  29. static is(obj?: StateObject): obj is O { return !!obj && type === obj.type; }
  30. id = UUID.create22();
  31. type = type;
  32. label: string;
  33. description?: string;
  34. constructor(public data: Data, props?: { label: string, description?: string }) {
  35. this.label = props && props.label || type.name;
  36. this.description = props && props.description;
  37. }
  38. }
  39. }
  40. /** A special object indicating a transformer result has no value. */
  41. export const Null: StateObject<any, any> = {
  42. id: UUID.create22(),
  43. type: { name: 'Null', typeClass: 'Null' },
  44. data: void 0,
  45. label: 'Null'
  46. };
  47. }
  48. interface StateObjectCell<T = StateObject> {
  49. transform: Transform,
  50. // Which object was used as a parent to create data in this cell
  51. sourceRef: Transform.Ref | undefined,
  52. status: StateObjectCell.Status,
  53. params: {
  54. definition: ParamDefinition.Params,
  55. values: any
  56. } | undefined;
  57. errorText?: string,
  58. obj?: T
  59. }
  60. namespace StateObjectCell {
  61. export type Status = 'ok' | 'error' | 'pending' | 'processing'
  62. export interface State {
  63. isHidden: boolean,
  64. isCollapsed: boolean
  65. }
  66. export const DefaultState: State = { isHidden: false, isCollapsed: false };
  67. export function areStatesEqual(a: State, b: State) {
  68. return a.isHidden !== b.isHidden || a.isCollapsed !== b.isCollapsed;
  69. }
  70. export function isStateChange(a: State, b?: Partial<State>) {
  71. if (!b) return false;
  72. if (typeof b.isCollapsed !== 'undefined' && a.isCollapsed !== b.isCollapsed) return true;
  73. if (typeof b.isHidden !== 'undefined' && a.isHidden !== b.isHidden) return true;
  74. return false;
  75. }
  76. }
  77. // TODO: improve the API?
  78. export class StateObjectTracker<T extends StateObject> {
  79. private query: StateSelection.Query;
  80. private version: string = '';
  81. cell: StateObjectCell | undefined;
  82. data: T['data'] | undefined;
  83. setQuery(sel: StateSelection.Selector) {
  84. this.query = StateSelection.compile(sel);
  85. }
  86. update() {
  87. const cell = this.state.select(this.query)[0];
  88. const version = cell ? cell.transform.version : void 0;
  89. const changed = this.cell !== cell || this.version !== version;
  90. this.cell = cell;
  91. this.version = version || '';
  92. this.data = cell.obj ? cell.obj.data as T : void 0 as any;
  93. return changed;
  94. }
  95. constructor(private state: State) { }
  96. }