UNPKG

@eclipse-glsp/client

Version:

A sprotty-based client for GLSP

262 lines 13.9 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 EdgeEditTool_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.EdgeEditListener = exports.EdgeEditTool = 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 drag_aware_mouse_listener_1 = require("../../../base/drag-aware-mouse-listener"); const css_feedback_1 = require("../../../base/feedback/css-feedback"); const selection_service_1 = require("../../../base/selection-service"); const gmodel_util_1 = require("../../../utils/gmodel-util"); const model_1 = require("../../reconnect/model"); const base_tools_1 = require("../base-tools"); const dangling_edge_feedback_1 = require("../edge-creation/dangling-edge-feedback"); const edge_edit_tool_feedback_1 = require("./edge-edit-tool-feedback"); let EdgeEditTool = EdgeEditTool_1 = class EdgeEditTool extends base_tools_1.BaseEditTool { get id() { return EdgeEditTool_1.ID; } enable() { this.edgeEditListener = new EdgeEditListener(this); // install feedback move mouse listener for client-side move updates this.feedbackEdgeSourceMovingListener = new edge_edit_tool_feedback_1.FeedbackEdgeSourceMovingMouseListener(this.anchorRegistry, this.feedbackDispatcher); this.feedbackEdgeTargetMovingListener = new edge_edit_tool_feedback_1.FeedbackEdgeTargetMovingMouseListener(this.anchorRegistry, this.feedbackDispatcher); this.feedbackMovingListener = new edge_edit_tool_feedback_1.FeedbackEdgeRouteMovingMouseListener(this.changeBoundsManager, this.edgeRouterRegistry); this.toDisposeOnDisable.push(this.edgeEditListener, this.mouseTool.registerListener(this.edgeEditListener), this.feedbackEdgeSourceMovingListener, this.feedbackEdgeTargetMovingListener, this.feedbackMovingListener, this.selectionService.addListener(this.edgeEditListener)); } registerFeedbackListeners() { this.mouseTool.register(this.feedbackMovingListener); this.mouseTool.register(this.feedbackEdgeSourceMovingListener); this.mouseTool.register(this.feedbackEdgeTargetMovingListener); } deregisterFeedbackListeners() { this.feedbackEdgeSourceMovingListener.dispose(); this.feedbackEdgeTargetMovingListener.dispose(); this.mouseTool.deregister(this.feedbackEdgeSourceMovingListener); this.mouseTool.deregister(this.feedbackEdgeTargetMovingListener); this.mouseTool.deregister(this.feedbackMovingListener); } }; exports.EdgeEditTool = EdgeEditTool; EdgeEditTool.ID = 'glsp.edge-edit-tool'; __decorate([ (0, inversify_1.inject)(selection_service_1.SelectionService), __metadata("design:type", selection_service_1.SelectionService) ], EdgeEditTool.prototype, "selectionService", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.AnchorComputerRegistry), __metadata("design:type", sprotty_1.AnchorComputerRegistry) ], EdgeEditTool.prototype, "anchorRegistry", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.EdgeRouterRegistry), (0, inversify_1.optional)(), __metadata("design:type", sprotty_1.EdgeRouterRegistry) ], EdgeEditTool.prototype, "edgeRouterRegistry", void 0); __decorate([ (0, inversify_1.inject)(sprotty_1.TYPES.IChangeBoundsManager), __metadata("design:type", Object) ], EdgeEditTool.prototype, "changeBoundsManager", void 0); exports.EdgeEditTool = EdgeEditTool = EdgeEditTool_1 = __decorate([ (0, inversify_1.injectable)() ], EdgeEditTool); class EdgeEditListener extends drag_aware_mouse_listener_1.DragAwareMouseListener { constructor(tool) { super(); this.tool = tool; this.cursorFeedback = this.tool.createFeedbackEmitter(); this.editFeedback = this.tool.createFeedbackEmitter(); } isValidEdge(edge) { return edge !== undefined && edge.id !== (0, dangling_edge_feedback_1.feedbackEdgeId)(edge.root) && (0, sprotty_1.isSelected)(edge); } setEdgeSelected(edge) { this.edge = edge; // note: order is important here as we want the reconnect handles to cover the routing handles if ((0, sprotty_1.canEditRouting)(edge)) { this.editFeedback.add(edge_edit_tool_feedback_1.SwitchRoutingModeAction.create({ elementsToActivate: [this.edge.id] }), edge_edit_tool_feedback_1.SwitchRoutingModeAction.create({ elementsToDeactivate: [this.edge.id] })); } if ((0, model_1.isReconnectable)(edge)) { this.editFeedback.add(edge_edit_tool_feedback_1.ShowEdgeReconnectHandlesFeedbackAction.create(this.edge.id), edge_edit_tool_feedback_1.HideEdgeReconnectHandlesFeedbackAction.create()); } this.editFeedback.submit(); } isEdgeSelected() { return this.edge !== undefined && (0, sprotty_1.isSelected)(this.edge); } setReconnectHandleSelected(edge, reconnectHandle) { if (this.edge && this.edge.target && this.edge.source) { this.editFeedback.dispose(); if ((0, model_1.isSourceRoutingHandle)(edge, reconnectHandle)) { this.editFeedback .add((0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.EDGE_RECONNECT), (0, css_feedback_1.cursorFeedbackAction)()) .add(edge_edit_tool_feedback_1.DrawFeedbackEdgeSourceAction.create({ elementTypeId: this.edge.type, targetId: this.edge.targetId }), dangling_edge_feedback_1.RemoveFeedbackEdgeAction.create()) .submit(); this.reconnectMode = 'NEW_SOURCE'; } else if ((0, model_1.isTargetRoutingHandle)(edge, reconnectHandle)) { this.editFeedback .add((0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.EDGE_CREATION_TARGET), (0, css_feedback_1.cursorFeedbackAction)()) .add(dangling_edge_feedback_1.DrawFeedbackEdgeAction.create({ elementTypeId: this.edge.type, sourceId: this.edge.sourceId }), dangling_edge_feedback_1.RemoveFeedbackEdgeAction.create()) .submit(); this.reconnectMode = 'NEW_TARGET'; } } } isReconnecting() { return this.reconnectMode !== undefined; } isReconnectingNewSource() { return this.reconnectMode === 'NEW_SOURCE'; } setRoutingHandleSelected(edge, routingHandle) { if (this.edge && this.edge.target && this.edge.source) { this.routingHandle = routingHandle; } } requiresReconnect(sourceId, targetId) { return this.edge !== undefined && (this.edge.sourceId !== sourceId || this.edge.targetId !== targetId); } setNewConnectable(connectable) { this.newConnectable = connectable; } isReadyToReconnect() { return this.edge && this.isReconnecting() && this.newConnectable !== undefined; } isReadyToReroute() { return this.routingHandle !== undefined; } mouseDown(target, event) { const result = super.mouseDown(target, event); if (event.button === 0) { const reconnectHandle = (0, sprotty_1.findParentByFeature)(target, model_1.isReconnectHandle); const routingHandle = !reconnectHandle ? (0, sprotty_1.findParentByFeature)(target, gmodel_util_1.isRoutingHandle) : undefined; const edge = (0, sprotty_1.findParentByFeature)(target, gmodel_util_1.isRoutable); if (this.isEdgeSelected() && edge && reconnectHandle) { // PHASE 2 Reconnect: Select reconnect handle on selected edge this.setReconnectHandleSelected(edge, reconnectHandle); } else if (this.isEdgeSelected() && edge && routingHandle) { // PHASE 2 Reroute: Select routing handle on selected edge this.setRoutingHandleSelected(edge, routingHandle); } else if (this.isValidEdge(edge)) { // PHASE 1: Select edge this.dispose(); this.tool.registerFeedbackListeners(); this.setEdgeSelected(edge); } } else if (event.button === 2) { this.dispose(); } return result; } draggingMouseMove(target, event) { // reset any selected connectables when we are dragging, maybe the user is just panning this.setNewConnectable(undefined); return super.draggingMouseMove(target, event); } mouseUp(target, event) { const result = super.mouseUp(target, event); if (!this.isReadyToReconnect() && !this.isReadyToReroute()) { return result; } if (this.edge && this.newConnectable) { const sourceElementId = this.isReconnectingNewSource() ? this.newConnectable.id : this.edge.sourceId; const targetElementId = this.isReconnectingNewSource() ? this.edge.targetId : this.newConnectable.id; if (this.requiresReconnect(sourceElementId, targetElementId)) { result.push(sprotty_1.ReconnectEdgeOperation.create({ edgeElementId: this.edge.id, sourceElementId, targetElementId })); } this.dispose(); } else if (this.edge && this.routingHandle) { // we need to re-retrieve the edge as it might have changed due to a server update since we do not reset the state between // reroute actions const latestEdge = target.index.getById(this.edge.id); if (latestEdge && (0, gmodel_util_1.isRoutable)(latestEdge)) { const newRoutingPoints = (0, gmodel_util_1.calcElementAndRoutingPoints)(latestEdge, this.tool.edgeRouterRegistry); result.push(sprotty_1.ChangeRoutingPointsOperation.create([newRoutingPoints])); this.routingHandle = undefined; } } return result; } mouseOver(target, _event) { if (this.edge && this.isReconnecting()) { const currentTarget = (0, sprotty_1.findParentByFeature)(target, sprotty_1.isConnectable); if (!this.newConnectable || currentTarget !== this.newConnectable) { this.setNewConnectable(currentTarget); if (currentTarget) { if ((this.reconnectMode === 'NEW_SOURCE' && currentTarget.canConnect(this.edge, 'source')) || (this.reconnectMode === 'NEW_TARGET' && currentTarget.canConnect(this.edge, 'target'))) { this.cursorFeedback.add((0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.EDGE_RECONNECT), (0, css_feedback_1.cursorFeedbackAction)()).submit(); return []; } } this.cursorFeedback.add((0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED), (0, css_feedback_1.cursorFeedbackAction)()).submit(); } } return []; } selectionChanged(root, selectedElements) { if (this.edge) { if (selectedElements.indexOf(this.edge.id) > -1) { // our active edge is still selected, nothing to do return; } if (this.isReconnecting()) { // we are reconnecting, so we may have clicked on a potential target return; } // try to find some other selected element and mark that active for (const elementId of selectedElements.reverse()) { const element = root.index.getById(elementId); if (element) { const edge = (0, sprotty_1.findParentByFeature)(element, gmodel_util_1.isRoutable); if (this.isValidEdge(edge)) { // PHASE 1: Select edge this.setEdgeSelected(edge); return; } } } this.dispose(); } } dispose() { this.edge = undefined; this.reconnectMode = undefined; this.newConnectable = undefined; this.routingHandle = undefined; this.cursorFeedback.dispose(); this.editFeedback.dispose(); this.tool.deregisterFeedbackListeners(); super.dispose(); } } exports.EdgeEditListener = EdgeEditListener; //# sourceMappingURL=edge-edit-tool.js.map