UNPKG

@kieler/klighd-core

Version:

Core KLighD diagram visualization with Sprotty

323 lines 16.9 kB
"use strict"; /* * KIELER - Kiel Integrated Environment for Layout Eclipse RichClient * * http://rtsys.informatik.uni-kiel.de/kieler * * Copyright 2021-2024 by * + Kiel University * + Department of Computer Science * + Real-Time and Embedded Systems Group * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 */ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var KlighdDiagramServer_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.KlighdDiagramServer = void 0; const file_saver_1 = require("file-saver"); const actions_1 = require("@kieler/klighd-interactive/lib/actions"); const actions_2 = require("@kieler/klighd-interactive/lib/layered/actions"); const actions_3 = require("@kieler/klighd-interactive/lib/rect-packing/actions"); const actions_4 = require("@kieler/klighd-interactive/lib/tree/actions"); const inversify_1 = require("inversify"); const sprotty_1 = require("sprotty"); const sprotty_protocol_1 = require("sprotty-protocol"); const actions_5 = require("./actions/actions"); const bookmark_1 = require("./bookmarks/bookmark"); const bookmark_registry_1 = require("./bookmarks/bookmark-registry"); const di_symbols_1 = require("./di.symbols"); const actions_6 = require("./diagram-pieces/actions"); const diagram_piece_request_manager_1 = require("./diagram-pieces/diagram-piece-request-manager"); const hover_1 = require("./hover/hover"); const popup_provider_1 = require("./hover/popup-provider"); const render_options_registry_1 = require("./options/render-options-registry"); const preferences_registry_1 = require("./preferences-registry"); const services_1 = require("./services"); const actions_7 = require("./syntheses/actions"); const update_depthmap_model_1 = require("./update/update-depthmap-model"); /** * This class extends {@link DiagramServerProxy} to handle different `klighd-core` specific * actions and forward them to the server is required. */ let KlighdDiagramServer = KlighdDiagramServer_1 = class KlighdDiagramServer extends sprotty_1.DiagramServerProxy { constructor(connection) { super(); this.childrenToRequestQueue = new diagram_piece_request_manager_1.GridDiagramPieceRequestManager(); this._connection = connection; connection.onMessageReceived(this.messageReceived.bind(this)); } sendMessage(message) { this._connection.sendMessage(message); } messageReceived(message) { super.messageReceived(message); const wasDiagramModelUpdated = message.action.kind === sprotty_1.SetModelCommand.KIND || message.action.kind === sprotty_protocol_1.UpdateModelAction.KIND; if (wasDiagramModelUpdated) { this.actionDispatcher.dispatch(update_depthmap_model_1.UpdateDepthMapModelAction.create()); if (this.preferencesRegistry.getValue(preferences_registry_1.IncrementalDiagramGeneratorOption)) { // After model is received request first piece. // TODO: Here some state aware process should handle requesting pieces // This needs to be initialized here, probably also do this stuff // with commands // get root diagram piece this.childrenToRequestQueue.reset(); this.actionDispatcher.dispatch(actions_6.RequestDiagramPieceAction.create((0, sprotty_protocol_1.generateRequestId)(), '$root')); } if (this.bookmarkRegistry && this.bookmarkRegistry.initialBookmark) { this.actionDispatcher.dispatch(bookmark_1.GoToBookmarkAction.create(this.bookmarkRegistry.initialBookmark)); } else if (this.renderOptionsRegistry && this.renderOptionsRegistry.getValue(render_options_registry_1.ResizeToFit)) { this.actionDispatcher.dispatch(actions_5.KlighdFitToScreenAction.create(true)); } } else if (message.action.kind === actions_6.SetDiagramPieceAction.KIND) { // add any children of the requested piece as stubs into queue if (message.action.diagramPiece.children !== undefined) { const children = message.action.diagramPiece.children; children.forEach((element) => { // FIXME: not all types of children should be added here, edges for example are already // complete as they can't have any own children this.childrenToRequestQueue.enqueue(message.action.diagramPiece.id, element); }); } if (this.childrenToRequestQueue.front() !== undefined) { // get viewport this.actionDispatcher.dispatch(sprotty_protocol_1.GetViewportAction.create()); } } } handleLocally(action) { // In contract to the name, this should return true, if the actions should be // sent to the server. Don't know what the Sprotty folks where thinking when they named it... switch (action.kind) { case actions_5.PerformActionAction.KIND: return true; case actions_1.RefreshDiagramAction.KIND: return true; case actions_5.RefreshLayoutAction.KIND: return true; case actions_6.RequestDiagramPieceAction.KIND: return true; case actions_7.SetSynthesisAction.KIND: return true; case actions_5.KlighdExportSvgAction.KIND: return this.handleExportSvgAction(action); default: // Do nothing. } return super.handleLocally(action); } handleExportSvgAction(action) { const blob = new Blob([action.svg], { type: 'text/plain;charset=utf-8' }); const fileName = action.uri.split('/').pop(); let name = 'diagram'; if (fileName) { // Get file name ; [name] = fileName.split('.'); } (0, file_saver_1.saveAs)(blob, `${name}.svg`); return false; } initialize(registry) { super.initialize(registry); // Register the KLighD specific new actions. registry.register(sprotty_protocol_1.BringToFrontAction.KIND, this); registry.register(actions_5.CheckImagesAction.KIND, this); registry.register(actions_5.CheckedImagesAction.KIND, this); registry.register(actions_2.DeleteLayerConstraintAction.KIND, this); registry.register(actions_2.DeletePositionConstraintAction.KIND, this); registry.register(actions_2.DeleteStaticConstraintAction.KIND, this); registry.register(actions_2.DeleteRelativeConstraintsAction.KIND, this); registry.register(actions_2.DeleteInLayerPredecessorOfConstraintAction.KIND, this); registry.register(actions_2.DeleteInLayerSuccessorOfConstraintAction.KIND, this); registry.register(actions_5.PerformActionAction.KIND, this); registry.register(actions_3.RectPackSetPositionConstraintAction.KIND, this); registry.register(actions_3.RectPackDeletePositionConstraintAction.KIND, this); registry.register(actions_1.RefreshDiagramAction.KIND, this); registry.register(actions_5.RefreshLayoutAction.KIND, this); registry.register(sprotty_protocol_1.RequestPopupModelAction.KIND, this); registry.register(actions_6.RequestDiagramPieceAction.KIND, this); registry.register(actions_3.SetAspectRatioAction.KIND, this); registry.register(actions_2.SetLayerConstraintAction.KIND, this); registry.register(actions_2.SetPositionConstraintAction.KIND, this); registry.register(actions_2.SetStaticConstraintAction.KIND, this); registry.register(actions_2.SetInLayerPredecessorOfConstraintAction.KIND, this); registry.register(actions_2.SetInLayerSuccessorOfConstraintAction.KIND, this); registry.register(actions_7.SetSynthesisAction.KIND, this); registry.register(actions_5.StoreImagesAction.KIND, this); registry.register(sprotty_1.SwitchEditModeAction.KIND, this); registry.register(sprotty_protocol_1.SelectAction.KIND, this); registry.register(actions_6.SetDiagramPieceAction.KIND, this); registry.register(actions_4.TreeSetPositionConstraintAction.KIND, this); registry.register(sprotty_protocol_1.ViewportResult.KIND, this); } handle(action) { if (action.kind === sprotty_protocol_1.BringToFrontAction.KIND || action.kind === sprotty_1.SwitchEditModeAction.KIND) { // Actions that should be ignored and not further handled by this diagram server return; } if (action.kind === actions_5.CheckImagesAction.KIND) { this.handleCheckImages(action); } else if (action.kind === actions_5.StoreImagesAction.KIND) { this.handleStoreImages(action); } else if (action.kind === sprotty_protocol_1.RequestPopupModelAction.KIND) { // Handle RequestPopupModelAction if they are modified RequestKlighdPopupModelAction. // Other PopupModel requests are simply ignored. if (hover_1.RequestKlighdPopupModelAction.isThisAction(action)) this.handleRequestKlighdPopupModel(action); } else if (action.kind === actions_6.RequestDiagramPieceAction.KIND) { this.handleRequestDiagramPiece(action); } else if (action.kind === sprotty_protocol_1.ViewportResult.KIND) { this.handleViewportResult(action); } else { super.handle(action); } } handleCheckImages(action) { // check in local storage, if these images are already stored. If not, send back a request for those images. const notCached = []; for (const image of action.images) { const id = KlighdDiagramServer_1.imageToSessionStorageString(image.bundleName, image.imagePath); // "URI" as bundle name implies that the image path is a URI that should be resolved locally. if (!this.sessionStorage.getItem(id) && image.bundleName !== 'URI') { notCached.push({ k: image.bundleName, v: image.imagePath }); } } this.actionDispatcher.dispatch(actions_5.CheckedImagesAction.create(notCached)); } handleStoreImages(action) { // Put the new images in session storage. for (const imagePair of action.images) { const imageIdentifier = imagePair.k; const id = KlighdDiagramServer_1.imageToSessionStorageString(imageIdentifier.k, imageIdentifier.v); const imageString = imagePair.v; this.sessionStorage.setItem(id, imageString); } } /** * Converts the representation of the image data into a single string for identification in sessionStorage. * * @param bundleName The bundle name of the image. * @param imagePath The image path of the image. */ static imageToSessionStorageString(bundleName, imagePath) { return `${bundleName}:${imagePath}`; } /** * Handles Popup Requests because the action requires the currentRoot, * which is stored as a protected property in the super class. */ handleRequestKlighdPopupModel(action) { const element = (0, sprotty_protocol_1.findElement)(this.currentRoot, action.elementId); if (element) { const model = this.popupModelProvider.getPopupModel(action, element); if (model) { this.actionDispatcher.dispatch(sprotty_protocol_1.SetPopupModelAction.create(model)); } } return false; } // Super class behavior, except taking the needsClientLayout preference into account instead of the client option. handleRequestModel(action) { const needsClientLayout = !!this.preferencesRegistry.getValue(preferences_registry_1.ClientLayoutOption); const needsServerLayout = !needsClientLayout; const newOptions = Object.assign({ needsClientLayout, needsServerLayout }, action.options); const newAction = Object.assign(Object.assign({}, action), { options: newOptions }); this.forwardToServer(newAction); return false; } // Behavior adapted from the super class and modified to the behavior of the DiagramServer to allow this proxy to the Java diagram server to still be able to perform the layout locally. handleComputedBounds(action) { if (!this.preferencesRegistry.getValue(preferences_registry_1.ClientLayoutOption)) { return false; } const root = this.currentRoot; this.computedBoundsApplicator.apply(root, action); this.doSubmitModel(root, root.type === this.lastSubmittedModelType, action); return false; } // Behavior taken from the DiagramServer to allow this proxy to the Java diagram server to still be able to perform the layout locally. async doSubmitModel(newRoot, update, cause) { if (this.layoutEngine) { newRoot = await this.layoutEngine.layout(newRoot); } const modelType = newRoot.type; if (cause && cause.kind === sprotty_protocol_1.RequestModelAction.KIND) { const { requestId } = cause; const response = sprotty_protocol_1.SetModelAction.create(newRoot, requestId); this.actionDispatcher.dispatch(response); } else if (update && modelType === this.lastSubmittedModelType) { this.actionDispatcher.dispatch(sprotty_protocol_1.UpdateModelAction.create(newRoot)); } else { this.actionDispatcher.dispatch(sprotty_protocol_1.SetModelAction.create(newRoot)); } this.lastSubmittedModelType = modelType; } handleRequestDiagramPiece(action) { this.forwardToServer(action); } handleViewportResult(action) { this.childrenToRequestQueue.setViewport(action); const child = this.childrenToRequestQueue.dequeue(); this.actionDispatcher.dispatch(actions_6.RequestDiagramPieceAction.create((0, sprotty_protocol_1.generateRequestId)(), child.id)); } }; exports.KlighdDiagramServer = KlighdDiagramServer; __decorate([ (0, inversify_1.inject)(services_1.ServiceTypes.SessionStorage), __metadata("design:type", Object) ], KlighdDiagramServer.prototype, "sessionStorage", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IPopupModelProvider), __metadata("design:type", popup_provider_1.PopupModelProvider) ], KlighdDiagramServer.prototype, "popupModelProvider", void 0); __decorate([ (0, inversify_1.inject)(di_symbols_1.DISymbol.PreferencesRegistry), __metadata("design:type", preferences_registry_1.PreferencesRegistry) ], KlighdDiagramServer.prototype, "preferencesRegistry", void 0); __decorate([ (0, inversify_1.inject)(di_symbols_1.DISymbol.RenderOptionsRegistry), (0, inversify_1.optional)(), __metadata("design:type", render_options_registry_1.RenderOptionsRegistry) ], KlighdDiagramServer.prototype, "renderOptionsRegistry", void 0); __decorate([ (0, inversify_1.inject)(di_symbols_1.DISymbol.BookmarkRegistry), (0, inversify_1.optional)(), __metadata("design:type", bookmark_registry_1.BookmarkRegistry) ], KlighdDiagramServer.prototype, "bookmarkRegistry", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IModelLayoutEngine), (0, inversify_1.optional)(), __metadata("design:type", Object) ], KlighdDiagramServer.prototype, "layoutEngine", void 0); exports.KlighdDiagramServer = KlighdDiagramServer = KlighdDiagramServer_1 = __decorate([ (0, inversify_1.injectable)(), __param(0, (0, inversify_1.inject)(services_1.ServiceTypes.Connection)), __metadata("design:paramtypes", [Object]) ], KlighdDiagramServer); //# sourceMappingURL=diagram-server.js.map