theia-sprotty
Version:
Glue code for sprotty diagrams in a Theia IDE
121 lines (103 loc) • 5.14 kB
text/typescript
/*
* Copyright (C) 2017 TypeFox and others.
*
* Licensed under the Apache License, Version 2.0 (the "License") you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*/
import { TheiaDiagramServer } from '../sprotty/theia-diagram-server';
import { TheiaSprottyConnector } from '../sprotty/theia-sprotty-connector'
import { DiagramConfigurationRegistry } from './diagram-configuration'
import { injectable, inject } from "inversify"
import { OpenerOptions, OpenHandler, FrontendApplicationContribution, ApplicationShell } from "@theia/core/lib/browser"
import URI from "@theia/core/lib/common/uri"
import { DiagramWidget, DiagramWidgetFactory } from "./diagram-widget"
import { DiagramWidgetRegistry } from "./diagram-widget-registry"
import { Emitter, Event, SelectionService } from '@theia/core/lib/common'
import { TYPES, ModelSource, IActionDispatcher, DiagramServer } from 'sprotty/lib'
import { EditorManager } from '@theia/editor/lib/browser';
export const DiagramManagerProvider = Symbol('DiagramManagerProvider')
export type DiagramManagerProvider = () => Promise<DiagramManager>
export interface DiagramManager extends OpenHandler, FrontendApplicationContribution {
readonly diagramType: string
readonly onDiagramOpened: Event<URI>
}
export abstract class DiagramManagerImpl implements DiagramManager {
protected readonly shell: ApplicationShell
protected readonly widgetRegistry: DiagramWidgetRegistry
protected readonly selectionService: SelectionService
protected diagramConfigurationRegistry: DiagramConfigurationRegistry
protected editorManager: EditorManager
protected readonly onDiagramOpenedEmitter = new Emitter<URI>()
abstract get diagramType(): string
abstract iconClass: string
get id() {
return this.diagramType + "-diagram-opener"
}
get onDiagramOpened(): Event<URI> {
return this.onDiagramOpenedEmitter.event
}
canHandle(uri: URI, options?: OpenerOptions | undefined): number {
return 10
}
open(uri: URI, input?: OpenerOptions): Promise<DiagramWidget> {
const promiseDiagramWidget = this.getOrCreateDiagramWidget(uri)
promiseDiagramWidget.then(diagramWidget => {
window.requestAnimationFrame(() => {
this.shell.activateWidget(diagramWidget.id)
this.onDiagramOpenedEmitter.fire(uri)
})
})
return promiseDiagramWidget
}
protected async getOrCreateDiagramWidget(uri: URI): Promise<DiagramWidget> {
const widget = await this.widgetRegistry.getWidget(uri, this.diagramType)
if (widget !== undefined)
return widget
const newWidget = this.createDiagramWidget(uri)
this.addToShell(newWidget)
return Promise.resolve(newWidget)
}
protected createDiagramWidget(uri: URI): DiagramWidget {
const widgetId = this.widgetRegistry.nextId()
const svgContainerId = widgetId + '_sprotty'
const diagramConfiguration = this.diagramConfigurationRegistry.get(this.diagramType)
const diContainer = diagramConfiguration.createContainer(svgContainerId)
const modelSource = diContainer.get<ModelSource>(TYPES.ModelSource)
if (modelSource instanceof DiagramServer)
modelSource.clientId = widgetId
if (modelSource instanceof TheiaDiagramServer && this.diagramConnector)
this.diagramConnector.connect(modelSource)
const newWidget = this.diagramWidgetFactory({
id: widgetId, svgContainerId, uri, diagramType: this.diagramType, modelSource,
actionDispatcher: diContainer.get<IActionDispatcher>(TYPES.IActionDispatcher)
})
newWidget.title.closable = true
newWidget.title.label = uri.path.base
newWidget.title.icon = this.iconClass
this.widgetRegistry.addWidget(uri, this.diagramType, newWidget)
newWidget.disposed.connect(() => {
this.widgetRegistry.removeWidget(uri, this.diagramType)
if (modelSource instanceof TheiaDiagramServer && this.diagramConnector)
this.diagramConnector.disconnect(modelSource)
})
return newWidget
}
protected addToShell(widget: DiagramWidget): void {
const currentEditor = this.editorManager.currentEditor
const options: ApplicationShell.WidgetOptions = {
area: 'main'
}
if (!!currentEditor && currentEditor.editor.uri.toString(true) === widget.uri.toString(true)) {
options.ref = currentEditor
options.mode = 'split-right'
}
this.shell.addWidget(widget, options)
}
protected get diagramWidgetFactory(): DiagramWidgetFactory {
return options => new DiagramWidget(options)
}
get diagramConnector(): TheiaSprottyConnector | undefined {
return undefined
}
}