UNPKG

sprotty

Version:

A next-gen framework for graphical views

200 lines 8.62 kB
"use strict"; /******************************************************************************** * Copyright (c) 2017-2021 TypeFox and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the Eclipse * Public License v. 2.0 are satisfied: GNU General Public License, version 2 * with the GNU Classpath Exception which is available at * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-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); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DiagramServerProxy = exports.ServerStatusAction = void 0; const file_saver_1 = require("file-saver"); const inversify_1 = require("inversify"); const actions_1 = require("sprotty-protocol/lib/actions"); const set_model_1 = require("../base/features/set-model"); const types_1 = require("../base/types"); const bounds_manipulation_1 = require("../features/bounds/bounds-manipulation"); const update_model_1 = require("../features/update/update-model"); const model_source_1 = require("./model-source"); /** * Sent by the external server when to signal a state change. */ class ServerStatusAction { constructor() { this.kind = ServerStatusAction.KIND; } } exports.ServerStatusAction = ServerStatusAction; ServerStatusAction.KIND = 'serverStatus'; const receivedFromServerProperty = '__receivedFromServer'; /** * A ModelSource that communicates with an external model provider, e.g. * a model editor. * * This class defines which actions are sent to and received from the * external model source. */ let DiagramServerProxy = class DiagramServerProxy extends model_source_1.ModelSource { constructor() { super(...arguments); this.currentRoot = { type: 'NONE', id: 'ROOT' }; } get model() { return this.currentRoot; } initialize(registry) { super.initialize(registry); // Register actions to be sent to the remote server registry.register(actions_1.ComputedBoundsAction.KIND, this); registry.register(bounds_manipulation_1.RequestBoundsCommand.KIND, this); registry.register(actions_1.RequestPopupModelAction.KIND, this); registry.register(actions_1.CollapseExpandAction.KIND, this); registry.register(actions_1.CollapseExpandAllAction.KIND, this); registry.register(actions_1.OpenAction.KIND, this); registry.register(ServerStatusAction.KIND, this); if (!this.clientId) { this.clientId = this.viewerOptions.baseDiv; } } handle(action) { const forwardToServer = this.handleLocally(action); if (forwardToServer) { this.forwardToServer(action); } } forwardToServer(action) { const message = { clientId: this.clientId, action: action }; this.logger.log(this, 'sending', message); this.sendMessage(message); } /** * Called when a message is received from the remote diagram server. */ messageReceived(data) { const object = typeof (data) === 'string' ? JSON.parse(data) : data; if ((0, actions_1.isActionMessage)(object) && object.action) { if (!object.clientId || object.clientId === this.clientId) { object.action[receivedFromServerProperty] = true; this.logger.log(this, 'receiving', object); this.actionDispatcher.dispatch(object.action).then(() => { this.storeNewModel(object.action); }); } } else { this.logger.error(this, 'received data is not an action message', object); } } /** * Check whether the given action should be handled locally. Returns true if the action should * still be sent to the server, and false if it's only handled locally. */ handleLocally(action) { this.storeNewModel(action); switch (action.kind) { case actions_1.ComputedBoundsAction.KIND: return this.handleComputedBounds(action); case actions_1.RequestModelAction.KIND: return this.handleRequestModel(action); case bounds_manipulation_1.RequestBoundsCommand.KIND: return false; case actions_1.ExportSvgAction.KIND: return this.handleExportSvgAction(action); case ServerStatusAction.KIND: return this.handleServerStateAction(action); } return !action[receivedFromServerProperty]; } /** * Put the new model contained in the given action into the model storage, if there is any. */ storeNewModel(action) { if (action.kind === set_model_1.SetModelCommand.KIND || action.kind === update_model_1.UpdateModelCommand.KIND || action.kind === bounds_manipulation_1.RequestBoundsCommand.KIND) { const newRoot = action.newRoot; if (newRoot) { this.currentRoot = newRoot; if (action.kind === set_model_1.SetModelCommand.KIND || action.kind === update_model_1.UpdateModelCommand.KIND) { this.lastSubmittedModelType = newRoot.type; } } } } handleRequestModel(action) { const newOptions = Object.assign({ needsClientLayout: this.viewerOptions.needsClientLayout, needsServerLayout: this.viewerOptions.needsServerLayout }, action.options); const newAction = Object.assign(Object.assign({}, action), { options: newOptions }); this.forwardToServer(newAction); return false; } /** * If the server requires to compute a layout, the computed bounds are forwarded. Otherwise they * are applied to the current model locally and a model update is triggered. */ handleComputedBounds(action) { if (this.viewerOptions.needsServerLayout) { return true; } else { const root = this.currentRoot; this.computedBoundsApplicator.apply(root, action); if (root.type === this.lastSubmittedModelType) { this.actionDispatcher.dispatch(actions_1.UpdateModelAction.create(root)); } else { this.actionDispatcher.dispatch(actions_1.SetModelAction.create(root)); } this.lastSubmittedModelType = root.type; return false; } } handleExportSvgAction(action) { const blob = new Blob([action.svg], { type: 'text/plain;charset=utf-8' }); (0, file_saver_1.saveAs)(blob, 'diagram.svg'); return false; } handleServerStateAction(action) { return false; } commitModel(newRoot) { const previousRoot = this.currentRoot; this.currentRoot = newRoot; return previousRoot; } }; exports.DiagramServerProxy = DiagramServerProxy; __decorate([ (0, inversify_1.inject)(types_1.TYPES.ILogger), __metadata("design:type", Object) ], DiagramServerProxy.prototype, "logger", void 0); __decorate([ (0, inversify_1.inject)(model_source_1.ComputedBoundsApplicator), __metadata("design:type", model_source_1.ComputedBoundsApplicator) ], DiagramServerProxy.prototype, "computedBoundsApplicator", void 0); exports.DiagramServerProxy = DiagramServerProxy = __decorate([ (0, inversify_1.injectable)() ], DiagramServerProxy); //# sourceMappingURL=diagram-server.js.map