sprotty
Version:
A next-gen framework for graphical views
200 lines • 8.62 kB
JavaScript
"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