@eclipse-glsp/client
Version:
A sprotty-based client for GLSP
235 lines • 11.1 kB
JavaScript
"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 EdgeCreationTool_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EdgeCreationToolMouseListener = exports.EdgeCreationTool = 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 tool_1 = require("../../../base/tool-manager/tool");
const model_1 = require("../../../model");
const grid_1 = require("../../grid/grid");
const base_tools_1 = require("../base-tools");
const dangling_edge_feedback_1 = require("./dangling-edge-feedback");
const edge_creation_tool_feedback_1 = require("./edge-creation-tool-feedback");
/**
* Tool to create connections in a Diagram, by selecting a source and target node.
*/
let EdgeCreationTool = EdgeCreationTool_1 = class EdgeCreationTool extends base_tools_1.BaseCreationTool {
constructor() {
super(...arguments);
this.isTriggerAction = sprotty_1.TriggerEdgeCreationAction.is;
}
get id() {
return EdgeCreationTool_1.ID;
}
doEnable() {
this.toolFeedback();
this.creationListener();
this.trackFeedbackEdge();
}
toolFeedback() {
const toolFeedback = this.createFeedbackEmitter()
.add((0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED), (0, css_feedback_1.cursorFeedbackAction)())
.submit();
this.toDisposeOnDisable.push(toolFeedback);
}
creationListener() {
const creationListener = new EdgeCreationToolMouseListener(this.triggerAction, this.actionDispatcher, this.typeHintProvider, this, this.grid ? this.grid.x / 2 : undefined);
this.toDisposeOnDisable.push(creationListener, this.mouseTool.registerListener(creationListener));
}
trackFeedbackEdge() {
const mouseMovingFeedback = new edge_creation_tool_feedback_1.FeedbackEdgeEndMovingMouseListener(this.anchorRegistry, this.feedbackDispatcher);
this.toDisposeOnDisable.push(mouseMovingFeedback, this.mouseTool.registerListener(mouseMovingFeedback));
}
};
exports.EdgeCreationTool = EdgeCreationTool;
EdgeCreationTool.ID = 'tool_create_edge';
__decorate([
(0, inversify_1.inject)(sprotty_1.AnchorComputerRegistry),
__metadata("design:type", sprotty_1.AnchorComputerRegistry)
], EdgeCreationTool.prototype, "anchorRegistry", void 0);
__decorate([
(0, inversify_1.inject)(sprotty_1.TYPES.ITypeHintProvider),
__metadata("design:type", Object)
], EdgeCreationTool.prototype, "typeHintProvider", void 0);
__decorate([
(0, inversify_1.optional)(),
(0, inversify_1.inject)(sprotty_1.TYPES.Grid),
__metadata("design:type", Object)
], EdgeCreationTool.prototype, "grid", void 0);
exports.EdgeCreationTool = EdgeCreationTool = EdgeCreationTool_1 = __decorate([
(0, inversify_1.injectable)()
], EdgeCreationTool);
class EdgeCreationToolMouseListener extends drag_aware_mouse_listener_1.DragAwareMouseListener {
constructor(triggerAction, actionDispatcher, typeHintProvider, tool, dragSensitivity) {
super(dragSensitivity);
this.triggerAction = triggerAction;
this.actionDispatcher = actionDispatcher;
this.typeHintProvider = typeHintProvider;
this.tool = tool;
this.dragSensitivity = dragSensitivity;
this.allowedTarget = false;
this.pendingDynamicCheck = false;
this.proxyEdge = new model_1.GEdge();
this.proxyEdge.type = triggerAction.elementTypeId;
this.cursorFeedback = tool.createFeedbackEmitter();
this.feedbackEdgeFeedback = tool.createFeedbackEmitter();
}
nonDraggingMouseUp(element, event) {
const result = [];
if (event.button === 0) {
if (!this.isSourceSelected()) {
if (this.currentTarget && this.allowedTarget) {
this.source = this.currentTarget.id;
this.feedbackEdgeFeedback
.add(dangling_edge_feedback_1.DrawFeedbackEdgeAction.create({ elementTypeId: this.triggerAction.elementTypeId, sourceId: this.source }), dangling_edge_feedback_1.RemoveFeedbackEdgeAction.create())
.submit();
}
}
else if (this.currentTarget && this.allowedTarget) {
this.target = this.currentTarget.id;
}
if (this.source && this.target) {
result.push(this.getCreateOperation(element, event, this.source, this.target));
if (!this.isContinuousMode(element, event)) {
result.push(tool_1.EnableDefaultToolsAction.create());
}
else {
this.dispose();
}
}
}
else if (event.button === 2) {
this.dispose();
result.push(tool_1.EnableDefaultToolsAction.create());
}
return result;
}
/**
* Determines wether the tool should run in continuous mode (also called stamp mode) or not.
* If continuous mode is enabled, the tool will stay after a successful creation.
* The user can then create more elements of the same type without having to re-trigger the tool.
* By default, continuous mode is enabled if the user holds the CTRL key.
* @param element the current model element
* @param event
*/
isContinuousMode(element, event) {
return (0, sprotty_1.isCtrlOrCmd)(event);
}
getCreateOperation(element, event, sourceElementId, targetElementId) {
return sprotty_1.CreateEdgeOperation.create({
elementTypeId: this.triggerAction.elementTypeId,
sourceElementId,
targetElementId,
args: this.getCreateEdgeOperationArgs(element, event)
});
}
getCreateEdgeOperationArgs(ctx, event) {
return { ...this.triggerAction.args };
}
isSourceSelected() {
return this.source !== undefined;
}
isTargetSelected() {
return this.target !== undefined;
}
mouseOver(target, event) {
const newCurrentTarget = (0, sprotty_1.findParentByFeature)(target, sprotty_1.isConnectable);
if (newCurrentTarget !== this.currentTarget) {
this.pendingDynamicCheck = false;
this.currentTarget = newCurrentTarget;
if (this.currentTarget) {
if (!this.isSourceSelected()) {
this.allowedTarget = this.canConnect(newCurrentTarget, 'source');
}
else if (!this.isTargetSelected()) {
this.allowedTarget = this.canConnect(newCurrentTarget, 'target');
}
if (this.pendingDynamicCheck) {
return [(0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.EDGE_CHECK_PENDING)];
}
}
else {
this.allowedTarget = false;
}
return [this.updateEdgeFeedback()];
}
return [];
}
updateEdgeFeedback() {
if (this.allowedTarget) {
const action = !this.isSourceSelected()
? (0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.EDGE_CREATION_SOURCE)
: (0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.EDGE_CREATION_TARGET);
return action;
}
return (0, css_feedback_1.cursorFeedbackAction)(css_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED);
}
canConnect(element, role) {
var _a;
if (!element || !(0, sprotty_1.isConnectable)(element) || !element.canConnect(this.proxyEdge, role)) {
return false;
}
if (!this.isDynamic(this.proxyEdge.type)) {
return true;
}
const sourceElement = (_a = this.source) !== null && _a !== void 0 ? _a : element;
const targetElement = this.source ? element : undefined;
this.pendingDynamicCheck = true;
// Request server edge check
this.actionDispatcher
.request(sprotty_1.RequestCheckEdgeAction.create({ sourceElement, targetElement, edgeType: this.proxyEdge.type }))
.then(result => {
if (this.pendingDynamicCheck) {
this.allowedTarget = result.isValid;
this.actionDispatcher.dispatch(this.updateEdgeFeedback());
this.pendingDynamicCheck = false;
}
})
.catch(err => console.error('Dynamic edge check failed with: ', err));
// Temporarily mark the target as invalid while we wait for the server response,
// so a fast-clicking user doesn't get a chance to create the edge in the meantime.
return false;
}
isDynamic(edgeTypeId) {
var _a;
const typeHint = this.typeHintProvider.getEdgeTypeHint(edgeTypeId);
return (_a = typeHint === null || typeHint === void 0 ? void 0 : typeHint.dynamic) !== null && _a !== void 0 ? _a : false;
}
dispose() {
this.source = undefined;
this.target = undefined;
this.currentTarget = undefined;
this.allowedTarget = false;
this.feedbackEdgeFeedback.dispose();
this.cursorFeedback.dispose();
super.dispose();
}
}
exports.EdgeCreationToolMouseListener = EdgeCreationToolMouseListener;
//# sourceMappingURL=edge-creation-tool.js.map