/** * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal */ import { UUID } from 'mol-util'; import { Transform } from './transform'; import { ParamDefinition } from 'mol-util/param-definition'; import { State } from './state'; import { StateSelection } from './state/selection'; export { StateObject, StateObjectCell } interface StateObject> { readonly id: UUID, readonly type: T, readonly data: D, readonly label: string, readonly description?: string, } namespace StateObject { export function factory() { return (type: T) => create(type); } export type Type = { name: string, typeClass: Cls } export type Ctor = { new(...args: any[]): T, type: any } export type From = C extends Ctor ? T : never export function create(type: T) { return class O implements StateObject { static type = type; static is(obj?: StateObject): obj is O { return !!obj && type === obj.type; } id = UUID.create22(); type = type; label: string; description?: string; constructor(public data: Data, props?: { label: string, description?: string }) { this.label = props && props.label || type.name; this.description = props && props.description; } } } /** A special object indicating a transformer result has no value. */ export const Null: StateObject = { id: UUID.create22(), type: { name: 'Null', typeClass: 'Null' }, data: void 0, label: 'Null' }; } interface StateObjectCell { transform: Transform, // Which object was used as a parent to create data in this cell sourceRef: Transform.Ref | undefined, status: StateObjectCell.Status, params: { definition: ParamDefinition.Params, values: any } | undefined; errorText?: string, obj?: T } namespace StateObjectCell { export type Status = 'ok' | 'error' | 'pending' | 'processing' export interface State { isHidden: boolean, isCollapsed: boolean } export const DefaultState: State = { isHidden: false, isCollapsed: false }; export function areStatesEqual(a: State, b: State) { return a.isHidden !== b.isHidden || a.isCollapsed !== b.isCollapsed; } export function isStateChange(a: State, b?: Partial) { if (!b) return false; if (typeof b.isCollapsed !== 'undefined' && a.isCollapsed !== b.isCollapsed) return true; if (typeof b.isHidden !== 'undefined' && a.isHidden !== b.isHidden) return true; return false; } } // TODO: improve the API? export class StateObjectTracker { private query: StateSelection.Query; private version: string = ''; cell: StateObjectCell | undefined; data: T['data'] | undefined; setQuery(sel: StateSelection.Selector) { this.query = StateSelection.compile(sel); } update() { const cell = this.state.select(this.query)[0]; const version = cell ? cell.transform.version : void 0; const changed = this.cell !== cell || this.version !== version; this.cell = cell; this.version = version || ''; this.data = cell.obj ? cell.obj.data as T : void 0 as any; return changed; } constructor(private state: State) { } }