UNPKG

@eclipse-glsp/client

Version:

A sprotty-based client for GLSP

208 lines 9.98 kB
"use strict"; 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); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeHintProvider = exports.ApplyTypeHintsCommand = exports.ApplyTypeHintsAction = void 0; /******************************************************************************** * Copyright (c) 2019-2024 EclipseSource 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 ********************************************************************************/ const sprotty_1 = require("@eclipse-glsp/sprotty"); const inversify_1 = require("inversify"); const feedback_command_1 = require("../../base/feedback/feedback-command"); const model_1 = require("../../model"); const gmodel_util_1 = require("../../utils/gmodel-util"); const model_2 = require("../change-bounds/model"); const model_3 = require("../reconnect/model"); const model_4 = require("./model"); var ApplyTypeHintsAction; (function (ApplyTypeHintsAction) { ApplyTypeHintsAction.KIND = 'applyTypeHints'; function is(object) { return sprotty_1.Action.hasKind(object, ApplyTypeHintsAction.KIND); } ApplyTypeHintsAction.is = is; function create() { return { kind: ApplyTypeHintsAction.KIND }; } ApplyTypeHintsAction.create = create; })(ApplyTypeHintsAction || (exports.ApplyTypeHintsAction = ApplyTypeHintsAction = {})); /** * Command that processes the entire model and for each model element applies its * type hints i.e. translates the type hint information into corresponding model features * and adds/removes them from the model element. */ let ApplyTypeHintsCommand = class ApplyTypeHintsCommand extends feedback_command_1.FeedbackCommand { constructor(action) { super(); this.action = action; this.rank = -10; } execute(context) { context.root.index.all().forEach(element => { if (element instanceof sprotty_1.GShapeElement || element instanceof sprotty_1.GModelRoot) { return this.applyShapeTypeHint(element); } if (element instanceof model_1.GEdge) { this.applyEdgeTypeHint(element); } }); return context.root; } applyEdgeTypeHint(element) { const hint = this.typeHintProvider.getEdgeTypeHint(element); if (hint && element.features instanceof Set) { addOrRemove(element.features, sprotty_1.deletableFeature, hint.deletable); addOrRemove(element.features, sprotty_1.editFeature, hint.routable); addOrRemove(element.features, model_3.reconnectFeature, hint.repositionable); } } applyShapeTypeHint(element) { const hint = this.typeHintProvider.getShapeTypeHint(element); if (hint && element.features instanceof Set) { addOrRemove(element.features, sprotty_1.deletableFeature, hint.deletable); addOrRemove(element.features, sprotty_1.moveFeature, hint.repositionable); addOrRemove(element.features, model_2.resizeFeature, hint.resizable); addOrRemove(element.features, model_4.reparentFeature, hint.reparentable); addOrRemove(element.features, model_4.containerFeature, true); if ((0, model_4.isContainable)(element)) { element.isContainableElement = input => this.isContainableElement(input, hint); } const fallbackCanConnect = (0, sprotty_1.isConnectable)(element) ? element.canConnect.bind(element) : undefined; addOrRemove(element.features, sprotty_1.connectableFeature, true); if ((0, sprotty_1.isConnectable)(element)) { element.canConnect = (routable, role) => this.canConnect(routable, role, element, fallbackCanConnect); } } } /** * Type hints aware wrapper function for `Connectable.canConnect`. After type hints have been applied * the `canConnect` implementation of `connectable` model elements (with a matching hint) will forward to this method. */ canConnect(routable, role, element, fallbackCanConnect) { var _a; const edgeHint = this.typeHintProvider.getEdgeTypeHint(routable.type); if (!edgeHint) { return (_a = fallbackCanConnect === null || fallbackCanConnect === void 0 ? void 0 : fallbackCanConnect(routable, role)) !== null && _a !== void 0 ? _a : false; } const validElementIds = role === 'source' ? edgeHint.sourceElementTypeIds : edgeHint.targetElementTypeIds; // If no source/target element ids are defined in the hint all elements are considered valid if (!validElementIds) { return true; } const elementType = element.type + ':'; return validElementIds.some(type => elementType.startsWith(type)); } /** * Type hints aware wrapper function for `Containable.isContainableElement`. After type hints have been applied * the `isContainableElement` implementation of `containable` model elements (with a matching hint) will forward to this method. */ isContainableElement(input, hint) { var _a, _b; const elemenType = (0, gmodel_util_1.getElementTypeId)(input) + ':'; return (_b = (_a = hint.containableElementTypeIds) === null || _a === void 0 ? void 0 : _a.some(type => elemenType.startsWith(type))) !== null && _b !== void 0 ? _b : false; } }; exports.ApplyTypeHintsCommand = ApplyTypeHintsCommand; ApplyTypeHintsCommand.KIND = ApplyTypeHintsAction.KIND; __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.ITypeHintProvider), __metadata("design:type", Object) ], ApplyTypeHintsCommand.prototype, "typeHintProvider", void 0); exports.ApplyTypeHintsCommand = ApplyTypeHintsCommand = __decorate([ (0, inversify_1.injectable)(), __param(0, (0, inversify_1.inject)(sprotty_1.TYPES.Action)), __metadata("design:paramtypes", [Object]) ], ApplyTypeHintsCommand); function addOrRemove(features, feature, add) { if (add && !features.has(feature)) { features.add(feature); } else if (!add && features.has(feature)) { features.delete(feature); } } let TypeHintProvider = class TypeHintProvider { constructor() { this.shapeHints = new Map(); this.edgeHints = new Map(); } init() { this.typeHintsFeedback = this.feedbackActionDispatcher.createEmitter(); } handle(action) { this.shapeHints.clear(); this.edgeHints.clear(); action.shapeHints.forEach(hint => this.shapeHints.set(hint.elementTypeId, hint)); action.edgeHints.forEach(hint => this.edgeHints.set(hint.elementTypeId, hint)); this.typeHintsFeedback.add(ApplyTypeHintsAction.create()).submit(); } getShapeTypeHint(input) { return this.getTypeHint(input, this.shapeHints); } getEdgeTypeHint(input) { return this.getTypeHint(input, this.edgeHints); } getTypeHint(input, hints) { const type = (0, gmodel_util_1.getElementTypeId)(input); let hint = hints.get(type); // Check subtypes if (hint === undefined) { const subtypes = type.split(':'); while (hint === undefined && subtypes.length > 0) { subtypes.pop(); hint = hints.get(subtypes.join(':')); if (hint) { // add received subtype hint to map to avoid future recomputation hints.set(type, hint); break; } } } return hint; } async postRequestModel() { const setTypeHintsAction = await this.actionDispatcher.request(sprotty_1.RequestTypeHintsAction.create()); this.handle(setTypeHintsAction); } }; exports.TypeHintProvider = TypeHintProvider; __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IFeedbackActionDispatcher), __metadata("design:type", Object) ], TypeHintProvider.prototype, "feedbackActionDispatcher", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IActionDispatcher), __metadata("design:type", Object) ], TypeHintProvider.prototype, "actionDispatcher", void 0); __decorate([ (0, inversify_1.postConstruct)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], TypeHintProvider.prototype, "init", null); exports.TypeHintProvider = TypeHintProvider = __decorate([ (0, inversify_1.injectable)() ], TypeHintProvider); //# sourceMappingURL=type-hint-provider.js.map