diff --git a/src/apps/canvas/app.ts b/src/apps/canvas/app.ts index af974f06c57097f5051fc13ab0976574fbbc4f4d..3615bbc0e4dcdbd0bb497f524821deebdecfe0f3 100644 --- a/src/apps/canvas/app.ts +++ b/src/apps/canvas/app.ts @@ -32,23 +32,46 @@ export class App { } } + setStatus(msg: string) { + + } + + private taskCount = 0 + taskCountChanged = new BehaviorSubject({ count: 0, info: '' }) + + private changeTaskCount(delta: number, info = '') { + this.taskCount += delta + this.taskCountChanged.next({ count: this.taskCount, info }) + } + + async runTask<T>(promise: Promise<T>, info: string) { + this.changeTaskCount(1, info) + let result: T + try { + result = await promise + } finally { + this.changeTaskCount(-1) + } + return result + } + async loadCif(cif: CifBlock, assemblyId?: string) { - const models = await getModelsFromMmcif(cif) - this.structureView = await StructureView(this.viewer, models, { assemblyId }) + const models = await this.runTask(getModelsFromMmcif(cif), 'Build models') + this.structureView = await this.runTask(StructureView(this, this.viewer, models, { assemblyId }), 'Init structure view') this.pdbIdLoaded.next(this.structureView) } async loadPdbIdOrUrl(idOrUrl: string, options?: { assemblyId?: string, binary?: boolean }) { if (this.structureView) this.structureView.destroy(); const url = idOrUrl.length <= 4 ? `https://files.rcsb.org/download/${idOrUrl}.cif` : idOrUrl; - const cif = await getCifFromUrl(url, options ? !!options.binary : false) + const cif = await this.runTask(getCifFromUrl(url, options ? !!options.binary : false), 'Load mmCIF from URL') this.loadCif(cif, options ? options.assemblyId : void 0) } async loadCifFile(file: File) { if (this.structureView) this.structureView.destroy(); const binary = /\.bcif$/.test(file.name); - const cif = await getCifFromFile(file, binary) + const cif = await this.runTask(getCifFromFile(file, binary), 'Load mmCIF from file') this.loadCif(cif) } } \ No newline at end of file diff --git a/src/apps/canvas/component/structure-representation.tsx b/src/apps/canvas/component/structure-representation.tsx index aee34a7e85025cecab8dd8d5cc8fe4033d9a3ab1..2cdb76e8f2b496b6850b50633ec3d3fc670f2aa5 100644 --- a/src/apps/canvas/component/structure-representation.tsx +++ b/src/apps/canvas/component/structure-representation.tsx @@ -12,8 +12,10 @@ import { Color } from 'mol-util/color'; import { Progress } from 'mol-task'; import { VisualQuality, VisualQualityNames } from 'mol-geo/geometry/geometry'; import { SizeThemeProps } from 'mol-view/theme/size'; +import { App } from '../app'; export interface StructureRepresentationComponentProps { + app: App viewer: Viewer representation: StructureRepresentation<StructureProps> } @@ -82,9 +84,9 @@ export class StructureRepresentationComponent extends React.Component<StructureR if (state.pointFilledCircle !== undefined) (props as any).pointFilledCircle = state.pointFilledCircle if (state.pointEdgeBleach !== undefined) (props as any).pointEdgeBleach = state.pointEdgeBleach - await repr.createOrUpdate(props).run( + await this.props.app.runTask(repr.createOrUpdate(props).run( progress => console.log(Progress.format(progress)) - ) + ), 'Create/update representation') this.props.viewer.add(repr) this.props.viewer.draw(true) console.log(this.props.viewer.stats) diff --git a/src/apps/canvas/component/structure-view.tsx b/src/apps/canvas/component/structure-view.tsx index d27172fe1a03e176cef4feb892862b35fadc4c92..82ca7a29d46acbbeafbc3496ffb6a31e91ae0829 100644 --- a/src/apps/canvas/component/structure-view.tsx +++ b/src/apps/canvas/component/structure-view.tsx @@ -185,6 +185,7 @@ export class StructureViewComponent extends React.Component<StructureViewCompone <StructureRepresentationComponent representation={structureRepresentations[k]} viewer={structureView.viewer} + app={structureView.app} /> </div> } else { diff --git a/src/apps/canvas/component/viewport.tsx b/src/apps/canvas/component/viewport.tsx index 6a7f3ffc62f33d638da124e62c5726f052651a65..0085461d7f307e8d3d9849eff9cfa645af1a23bd 100644 --- a/src/apps/canvas/component/viewport.tsx +++ b/src/apps/canvas/component/viewport.tsx @@ -15,8 +15,9 @@ interface ViewportProps { } interface ViewportState { - noWebGl: boolean, - info: string + noWebGl: boolean + pickingInfo: string + taskInfo: string } export class Viewport extends React.Component<ViewportProps, ViewportState> { @@ -25,7 +26,8 @@ export class Viewport extends React.Component<ViewportProps, ViewportState> { state: ViewportState = { noWebGl: false, - info: '' + pickingInfo: '', + taskInfo: '' }; handleResize() { @@ -55,11 +57,15 @@ export class Viewport extends React.Component<ViewportProps, ViewportState> { prevLoci = loci const label = labelFirst(loci) - const info = `${label}` - this.setState({ info }) + const pickingInfo = `${label}` + this.setState({ pickingInfo }) } } }) + + this.props.app.taskCountChanged.subscribe(({ count, info }) => { + this.setState({ taskInfo: count > 0 ? info : '' }) + }) } componentWillUnmount() { @@ -94,8 +100,22 @@ export class Viewport extends React.Component<ViewportProps, ViewportState> { background: 'rgba(0, 0, 0, 0.2)' }} > - {this.state.info} + {this.state.pickingInfo} </div> + { this.state.taskInfo ? + <div + style={{ + position: 'absolute', + top: 10, + right: 10, + padding: 10, + color: 'lightgrey', + background: 'rgba(0, 0, 0, 0.2)' + }} + > + {this.state.taskInfo} + </div> + : '' } </div>; } } \ No newline at end of file diff --git a/src/apps/canvas/structure-view.ts b/src/apps/canvas/structure-view.ts index ea70b750cea30a16ecb9542610fe87a8f0679951..1f0d7149f9e1448b31bc362619ad84299b2cf198 100644 --- a/src/apps/canvas/structure-view.ts +++ b/src/apps/canvas/structure-view.ts @@ -25,9 +25,11 @@ import { BehaviorSubject } from 'rxjs'; import { SpacefillRepresentation } from 'mol-geo/representation/structure/representation/spacefill'; import { DistanceRestraintRepresentation } from 'mol-geo/representation/structure/representation/distance-restraint'; import { SurfaceRepresentation } from 'mol-geo/representation/structure/representation/surface'; -// import { Progress } from 'mol-task'; +import { App } from './app'; +import { Progress } from 'mol-task'; export interface StructureView { + readonly app: App readonly viewer: Viewer readonly label: string @@ -64,11 +66,11 @@ interface StructureViewProps { -export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model>, props: StructureViewProps = {}): Promise<StructureView> { +export async function StructureView(app: App, viewer: Viewer, models: ReadonlyArray<Model>, props: StructureViewProps = {}): Promise<StructureView> { const active: { [k: string]: boolean } = { cartoon: true, point: false, - surface: true, + surface: false, ballAndStick: false, carbohydrate: false, spacefill: false, @@ -105,7 +107,7 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> if (!value) { assemblySymmetry = undefined } else { - await AssemblySymmetry.attachFromCifOrAPI(models[modelId]) + await app.runTask(AssemblySymmetry.attachFromCifOrAPI(models[modelId]), 'Load symmetry annotation') assemblySymmetry = AssemblySymmetry.get(models[modelId]) } active.symmetryAxes = value @@ -195,7 +197,7 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> } async function getStructure() { - if (model) structure = await getStructureFromModel(model, assemblyId) + if (model) structure = await app.runTask(getStructureFromModel(model, assemblyId), 'Build structure') if (model && structure) { label = `${model.label} - Assembly ${assemblyId}` } else { @@ -209,9 +211,9 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> console.log('createStructureRepr') for (const k in structureRepresentations) { if (active[k]) { - await structureRepresentations[k].createOrUpdate({ colorTheme: { name: 'element-index' } }, structure).run( - // progress => console.log(Progress.format(progress)) - ) + await app.runTask(structureRepresentations[k].createOrUpdate({}, structure).run( + progress => console.log(Progress.format(progress)) + ), 'Create/update representation') viewer.add(structureRepresentations[k]) } else { viewer.remove(structureRepresentations[k]) @@ -288,6 +290,7 @@ export async function StructureView(viewer: Viewer, models: ReadonlyArray<Model> await setModel(0, props.assemblyId, props.symmetryFeatureId) return { + app, viewer, get label() { return label },