UNPKG

@eclipse-glsp/client

Version:

A sprotty-based client for GLSP

229 lines 11.2 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); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NavigationActionHandler = exports.ProcessNavigationArgumentsAction = exports.NavigateAction = void 0; /******************************************************************************** * Copyright (c) 2020-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 editor_context_service_1 = require("../../base/editor-context-service"); const navigation_target_resolver_1 = require("./navigation-target-resolver"); var NavigateAction; (function (NavigateAction) { NavigateAction.KIND = 'navigate'; function is(object) { return sprotty_1.Action.hasKind(object, NavigateAction.KIND) && (0, sprotty_1.hasStringProp)(object, 'targetTypeId'); } NavigateAction.is = is; function create(targetTypeId, options = {}) { return { kind: NavigateAction.KIND, targetTypeId, ...options }; } NavigateAction.create = create; })(NavigateAction || (exports.NavigateAction = NavigateAction = {})); var ProcessNavigationArgumentsAction; (function (ProcessNavigationArgumentsAction) { ProcessNavigationArgumentsAction.KIND = 'processNavigationArguments'; function is(object) { return sprotty_1.Action.hasKind(object, ProcessNavigationArgumentsAction.KIND) && (0, sprotty_1.hasObjectProp)(object, 'args'); } ProcessNavigationArgumentsAction.is = is; function create(args) { return { kind: ProcessNavigationArgumentsAction.KIND, args }; } ProcessNavigationArgumentsAction.create = create; })(ProcessNavigationArgumentsAction || (exports.ProcessNavigationArgumentsAction = ProcessNavigationArgumentsAction = {})); /** * Default handler for all actions that are related to the navigation. * * For a `NavigateAction` this handler triggers a `RequestNavigationTargetAction` to obtain the actual * navigation targets for the navigation type that is specified in the `NavigateAction`. * Once the navigation targets are available, it will trigger a `NavigateToTargetAction` to actually * perform the navigation. * * In other scenarios, clients may also trigger the `NavigateToTargetAction` directly, e.g. when opening * the diagram. * * Depending on the URI and arguments of the navigation target we may encounter three cases: * *(a)* the navigation target already specifies element IDs, in which case this action handler navigates * to the specified elements directly, by the selecting them and centering them in the viewport. * *(b)* the arguments of the navigation targets don't contain element IDs, but other arguments, the * navigation target needs to be resolved into actual element IDs by the `NavigationTargetResolver`. * This can for instance be useful, if the navigation deals with queries or some other more complex * logic that can't be dealt with on the client. * *(c)* the target isn't resolved by the `NavigationTargetResolver`, e.g. because the `uri` doesn't match * the URI of the current diagram. In this case, the navigation request is forwarded by dispatching * a `NavigateToExternalTargetAction`. */ let NavigationActionHandler = class NavigationActionHandler { constructor() { this.notificationTimeout = 5000; } handle(action) { if (NavigateAction.is(action)) { this.handleNavigateAction(action); } else if (sprotty_1.NavigateToTargetAction.is(action)) { this.handleNavigateToTarget(action); } else if (ProcessNavigationArgumentsAction.is(action)) { this.processNavigationArguments(action.args); } else if (sprotty_1.NavigateToExternalTargetAction.is(action)) { this.handleNavigateToExternalTarget(action); } } async handleNavigateAction(action) { try { const editorContext = this.editorContext.get(action.args); const response = await this.dispatcher.request(sprotty_1.RequestNavigationTargetsAction.create({ targetTypeId: action.targetTypeId, editorContext })); if (sprotty_1.SetNavigationTargetsAction.is(response) && response.targets && response.targets.length === 1) { if (response.targets.length > 1) { this.logger.warn(this, 'Processing of multiple targets is not supported yet. ' + 'Only the first is being processed.', response.targets); } return this.dispatcher.dispatch(sprotty_1.NavigateToTargetAction.create(response.targets[0])); } this.warnAboutFailedNavigation('No valid navigation target found'); } catch (reason) { this.logger.error(this, 'Failed to obtain navigation target', reason, action); } } async handleNavigateToTarget(action) { try { const resolvedElements = await this.resolveElements(action); if (this.containsElementIdsOrArguments(resolvedElements)) { this.navigateTo(resolvedElements); this.handleResolutionArguments(resolvedElements); return; } else { this.navigateToExternal(action.target); return; } } catch (reason) { this.logger.error(this, 'Failed to navigate', reason, action); } } resolveElements(action) { return this.resolver.resolve(action.target); } containsElementIdsOrArguments(target) { return target !== undefined && (this.containsElementIds(target.elementIds) || this.containsArguments(target.args)); } containsElementIds(elementIds) { return elementIds !== undefined && elementIds.length > 0; } containsArguments(args) { return args !== undefined && args !== undefined && Object.keys(args).length > 0; } navigateTo(target) { const elementIds = target.elementIds; if (!this.containsElementIds(elementIds)) { return; } this.dispatcher.dispatchAll([ sprotty_1.SelectAllAction.create(false), sprotty_1.SelectAction.create({ selectedElementsIDs: elementIds }), sprotty_1.CenterAction.create(elementIds) ]); } handleResolutionArguments(target) { const args = target.args; if (!this.containsArguments(args)) { return; } this.dispatcher.dispatch(ProcessNavigationArgumentsAction.create(args)); } navigateToExternal(target) { return this.dispatcher.dispatch(sprotty_1.NavigateToExternalTargetAction.create(target)); } processNavigationArguments(args) { if (args.info && args.info.toString().length > 0) { this.notify('INFO', args.info.toString()); } if (args.warning && args.warning.toString().length > 0) { this.notify('WARNING', args.warning.toString()); } if (args.error && args.error.toString().length > 0) { this.notify('ERROR', args.error.toString()); } } async handleNavigateToExternalTarget(action) { const handlers = this.actionHandlerRegistry.get(sprotty_1.NavigateToExternalTargetAction.KIND); if (handlers.length === 1) { // we are the only handler so we know nobody took care of it this.warnAboutFailedNavigation('Could not resolve or navigate to target', action.target); } } warnAboutFailedNavigation(msg, target) { const message = `${msg}` + (target ? `: '${target.uri}' (arguments: ${JSON.stringify(target.args)})` : ''); this.logger.warn(this, msg, target); this.notify('WARNING', message); } notify(severity, message) { const timeout = this.notificationTimeout; this.dispatcher.dispatchAll([sprotty_1.StatusAction.create(message, { severity, timeout }), sprotty_1.MessageAction.create(message, { severity })]); } }; exports.NavigationActionHandler = NavigationActionHandler; __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.ILogger), __metadata("design:type", Object) ], NavigationActionHandler.prototype, "logger", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IActionDispatcher), __metadata("design:type", Object) ], NavigationActionHandler.prototype, "dispatcher", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.ActionHandlerRegistryProvider), __metadata("design:type", Function) ], NavigationActionHandler.prototype, "actionHandlerRegistryProvider", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IEditorContextServiceProvider), __metadata("design:type", Function) ], NavigationActionHandler.prototype, "editorContextService", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.ActionHandlerRegistry), __metadata("design:type", sprotty_1.ActionHandlerRegistry) ], NavigationActionHandler.prototype, "actionHandlerRegistry", void 0); __decorate([ (0, inversify_1.inject)(navigation_target_resolver_1.NavigationTargetResolver), __metadata("design:type", navigation_target_resolver_1.NavigationTargetResolver) ], NavigationActionHandler.prototype, "resolver", void 0); __decorate([ (0, inversify_1.inject)(editor_context_service_1.EditorContextService), __metadata("design:type", editor_context_service_1.EditorContextService) ], NavigationActionHandler.prototype, "editorContext", void 0); exports.NavigationActionHandler = NavigationActionHandler = __decorate([ (0, inversify_1.injectable)() ], NavigationActionHandler); //# sourceMappingURL=navigation-action-handler.js.map