@eclipse-glsp/client
Advanced tools
Comparing version 0.8.0-next.2db3f72 to 0.8.0-next.32731d7
@@ -24,2 +24,3 @@ "use strict"; | ||
var command_stack_1 = require("./command-stack"); | ||
var editor_context_1 = require("./editor-context"); | ||
var update_model_command_1 = require("./model/update-model-command"); | ||
@@ -32,2 +33,3 @@ var tool_manager_action_handler_1 = require("./tool-manager/tool-manager-action-handler"); | ||
bind(types_1.GLSP_TYPES.IToolFactory).toFactory((tool_manager_action_handler_1.createToolFactory())); | ||
bind(editor_context_1.EditorContextService).toSelf().inSingletonScope(); | ||
// Model update initialization ------------------------------------ | ||
@@ -34,0 +36,0 @@ lib_1.configureCommand(context, update_model_command_1.FeedbackAwareUpdateModelCommand); |
import { Action, ActionHandlerRegistry, CommandExecutionContext, CommandReturn, IActionHandler, ILogger, SetModelAction, SModelRoot } from "sprotty/lib"; | ||
import { UpdateModelAction, UpdateModelCommand } from "sprotty/lib/features/update/update-model"; | ||
import { IFeedbackActionDispatcher } from "src/features/tool-feedback/feedback-action-dispatcher"; | ||
import { IFeedbackActionDispatcher } from "../../features/tool-feedback/feedback-action-dispatcher"; | ||
export declare class SetModelActionHandler implements IActionHandler { | ||
@@ -18,4 +18,4 @@ handle(action: Action): Action | void; | ||
protected readonly feedbackActionDispatcher: IFeedbackActionDispatcher; | ||
protected actionHandlerRegistryProvider: () => Promise<ActionHandlerRegistry>; | ||
protected modelRootListeners: SModelRootListener[]; | ||
protected actionHandlerRegistry?: ActionHandlerRegistry; | ||
constructor(action: UpdateModelAction, logger: ILogger, feedbackActionDispatcher: IFeedbackActionDispatcher, actionHandlerRegistryProvider: () => Promise<ActionHandlerRegistry>, modelRootListeners?: SModelRootListener[]); | ||
@@ -22,0 +22,0 @@ protected performUpdate(oldRoot: SModelRoot, newRoot: SModelRoot, context: CommandExecutionContext): CommandReturn; |
@@ -80,9 +80,8 @@ "use strict"; | ||
_this.feedbackActionDispatcher = feedbackActionDispatcher; | ||
_this.actionHandlerRegistryProvider = actionHandlerRegistryProvider; | ||
_this.modelRootListeners = modelRootListeners; | ||
actionHandlerRegistryProvider().then(function (registry) { return _this.actionHandlerRegistry = registry; }); | ||
return _this; | ||
} | ||
FeedbackAwareUpdateModelCommand.prototype.performUpdate = function (oldRoot, newRoot, context) { | ||
var _this = this; | ||
if (this.feedbackActionDispatcher) { | ||
if (this.feedbackActionDispatcher && this.actionHandlerRegistry) { | ||
// Create a temporary context wich defines the `newRoot` as `root` | ||
@@ -98,6 +97,4 @@ // This way we do not corrupt the redo/undo behavior of the super class | ||
}; | ||
this.actionHandlerRegistryProvider().then(function (registry) { | ||
var feedbackCommands = _this.getFeedbackCommands(registry); | ||
feedbackCommands.forEach(function (command) { return command.execute(tempContext_1); }); | ||
}); | ||
var feedbackCommands = this.getFeedbackCommands(this.actionHandlerRegistry); | ||
feedbackCommands.forEach(function (command) { return command.execute(tempContext_1); }); | ||
} | ||
@@ -104,0 +101,0 @@ this.modelRootListeners.forEach(function (listener) { return listener.modelRootChanged(newRoot); }); |
@@ -1,30 +0,13 @@ | ||
import { Action, Bounds, BoundsAware, Point, PointToPointLine, SModelElement } from "sprotty/lib"; | ||
import { Action, BoundsAware, Point, SModelElement } from "sprotty/lib"; | ||
export interface IMovementRestrictor { | ||
attemptMove(element: SModelElement, mousePoint: Point, target: SModelElement, delta: Point, result: Action[]): boolean; | ||
validate(newLocation: Point, element: SModelElement): boolean; | ||
cssClasses?: string[]; | ||
} | ||
export declare class NoCollisionMovementRestrictor { | ||
hasCollided: boolean; | ||
attemptMove(element: SModelElement, mousePoint: Point, target: SModelElement, delta: Point, result: Action[]): boolean; | ||
/** | ||
* Used to return the collision target(s) or the collision chain in case of multiple selected elements | ||
*/ | ||
getCollisionChain(target: SModelElement, element: SModelElement, delta: Point, collisionChain: SModelElement[]): SModelElement[]; | ||
/** | ||
* Returns bounds centered around the point | ||
*/ | ||
getCenteredBoundsToPointer(mousePoint: Point, bounds: Bounds): Bounds; | ||
getDistanceBetweenParallelLines(p1: Point, p2: Point, secondLine: PointToPointLine): Number; | ||
/** | ||
* Snaps the element to the target in case of a collision | ||
*/ | ||
getSnappedBounds(element: SModelElement & BoundsAware, target: SModelElement & BoundsAware): Bounds; | ||
export declare function createMovementRestrictionFeedback(element: SModelElement, movementRestrictor: IMovementRestrictor): Action[]; | ||
export declare function removeMovementRestrictionFeedback(element: SModelElement, movementRestrictor: IMovementRestrictor): Action[]; | ||
export declare class NoOverlapMovmentRestrictor implements IMovementRestrictor { | ||
validate(newLocation: Point, element: SModelElement): boolean; | ||
cssClasses: string[]; | ||
} | ||
/** | ||
* Used to check if 1D boxes (lines) overlap | ||
*/ | ||
export declare function isOverlapping1Dimension(x1: number, width1: number, x2: number, width2: number): boolean; | ||
/** | ||
* Used to check if 2 bounds are overlapping | ||
*/ | ||
export declare function isOverlappingBounds(bounds1: Bounds, bounds2: Bounds): boolean; | ||
export declare function areOverlapping(element1: SModelElement & BoundsAware, element2: SModelElement & BoundsAware): boolean; | ||
//# sourceMappingURL=movement-restrictor.d.ts.map |
@@ -26,242 +26,63 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var iterable_1 = require("sprotty/lib/utils/iterable"); | ||
var cursor_feedback_1 = require("../tool-feedback/cursor-feedback"); | ||
var viewpoint_util_1 = require("../../utils/viewpoint-util"); | ||
var css_feedback_1 = require("../tool-feedback/css-feedback"); | ||
var model_1 = require("./model"); | ||
var NoCollisionMovementRestrictor = /** @class */ (function () { | ||
function NoCollisionMovementRestrictor() { | ||
this.hasCollided = false; | ||
function createMovementRestrictionFeedback(element, movementRestrictor) { | ||
var result = []; | ||
result.push(new css_feedback_1.ModifyCSSFeedbackAction(element, movementRestrictor.cssClasses)); | ||
if (element instanceof lib_1.SParentElement) { | ||
element.children.filter(function (child) { return child instanceof model_1.SResizeHandle; }).forEach(function (child) { return result.push(new css_feedback_1.ModifyCSSFeedbackAction(child, movementRestrictor.cssClasses)); }); | ||
} | ||
/* | ||
* Attempt to perform an element move. Returns true if the move is not restricted anc can be applied successfull and false otherwise | ||
*/ | ||
NoCollisionMovementRestrictor.prototype.attemptMove = function (element, mousePoint, target, delta, result) { | ||
var _this = this; | ||
return result; | ||
} | ||
exports.createMovementRestrictionFeedback = createMovementRestrictionFeedback; | ||
function removeMovementRestrictionFeedback(element, movementRestrictor) { | ||
var result = []; | ||
result.push(new css_feedback_1.ModifyCSSFeedbackAction(element, undefined, movementRestrictor.cssClasses)); | ||
if (element instanceof lib_1.SParentElement) { | ||
element.children.filter(function (child) { return child instanceof model_1.SResizeHandle; }). | ||
forEach(function (child) { return result.push(new css_feedback_1.ModifyCSSFeedbackAction(child, undefined, movementRestrictor.cssClasses)); }); | ||
} | ||
return result; | ||
} | ||
exports.removeMovementRestrictionFeedback = removeMovementRestrictionFeedback; | ||
var NoOverlapMovmentRestrictor = /** @class */ (function () { | ||
function NoOverlapMovmentRestrictor() { | ||
this.cssClasses = ["movement-not-allowed"]; | ||
} | ||
NoOverlapMovmentRestrictor.prototype.validate = function (newLocation, element) { | ||
if (!model_1.isBoundsAwareMoveable(element)) { | ||
return false; | ||
} | ||
var mouseOverElement = false; | ||
var willOverlap = false; | ||
// Create ghost element to check possible bounds | ||
// Create ghost element at the newLocation; | ||
var ghostElement = Object.create(element); | ||
ghostElement.bounds = this.getCenteredBoundsToPointer(mousePoint, element.bounds); | ||
// Set type to Ghost to keep tracking it through elements | ||
ghostElement.bounds.x = newLocation.x - element.bounds.width / 2; | ||
ghostElement.bounds.y = newLocation.y - element.bounds.height / 2; | ||
ghostElement.type = "Ghost"; | ||
ghostElement.id = element.id; | ||
// Check collision for gost element (to see when it has passed beyond obstacle) | ||
var collisionTargetsGhost = this.getCollisionChain(target, ghostElement, delta, []) | ||
.filter(function (collidingElement) { return lib_1.isSelectable(collidingElement) && !collidingElement.selected; }); | ||
// After collision the mouse is back inside the element => change cursor back to default | ||
if (this.hasCollided && lib_1.includes(element.bounds, mousePoint)) { | ||
mouseOverElement = true; | ||
result.push(new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.DEFAULT)); | ||
} | ||
var selectedElements = target.root.index.all() | ||
.filter(function (selected) { return lib_1.isSelectable(selected) && selected.selected; }); | ||
// If the ghost element has moved beyond the obstacle move the actual element there aswell | ||
// But only if a single element is selected (multi-selection jumps are not supported) | ||
if (this.hasCollided && collisionTargetsGhost.length === 0 && iterable_1.toArray(selectedElements).length === 1) { | ||
mouseOverElement = true; | ||
result.push(new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.DEFAULT)); | ||
if (element.id === ghostElement.id) { | ||
element.bounds = ghostElement.bounds; | ||
} | ||
} | ||
// Get only the valid, non-slected collision targets to avoid in-selection collisions | ||
var collisionTargets = this.getCollisionChain(target, element, delta, []) | ||
.filter(function (collidingElement) { return lib_1.isSelectable(collidingElement) && !collidingElement.selected; }); | ||
if (collisionTargets.length > 0) { | ||
collisionTargets.forEach(function (collisionTarget) { | ||
if (lib_1.isBoundsAware(collisionTarget)) { | ||
// Only snap on first collision to avoid erratic jumps | ||
if (!_this.hasCollided) { | ||
var snappedBounds = _this.getSnappedBounds(element, collisionTarget); | ||
var snapMoves = []; | ||
snapMoves.push({ | ||
elementId: element.id, | ||
fromPosition: { | ||
x: element.position.x, | ||
y: element.position.y | ||
}, | ||
toPosition: { | ||
x: snappedBounds.x, | ||
y: snappedBounds.y | ||
} | ||
}); | ||
result.push(new lib_1.MoveAction(snapMoves, false)); | ||
} | ||
willOverlap = true; | ||
_this.hasCollided = true; | ||
result.push(new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.OVERLAP_FORBIDDEN)); | ||
} | ||
}); | ||
} | ||
if ((!willOverlap && !this.hasCollided) || | ||
(this.hasCollided && !willOverlap && mouseOverElement)) { | ||
this.hasCollided = false; | ||
return true; | ||
} | ||
return false; | ||
return !Array.from(element.root.index.all().filter(function (e) { return e.id !== ghostElement.id && e !== ghostElement.root && (e instanceof lib_1.SNode); }) | ||
.map(function (e) { return e; })).some(function (e) { return areOverlapping(e, ghostElement); }); | ||
}; | ||
/** | ||
* Used to return the collision target(s) or the collision chain in case of multiple selected elements | ||
*/ | ||
NoCollisionMovementRestrictor.prototype.getCollisionChain = function (target, element, delta, collisionChain) { | ||
var _this = this; | ||
if (model_1.isBoundsAwareMoveable(element)) { | ||
target.root.index.all() | ||
.filter(function (candidate) { return lib_1.isSelectable(candidate) && element.id !== candidate.id && collisionChain.indexOf(candidate) < 0; }) | ||
.forEach(function (candidate) { | ||
if (lib_1.isMoveable(element) && lib_1.isMoveable(candidate)) { | ||
if (lib_1.isBoundsAware(element) && lib_1.isBoundsAware(candidate)) { | ||
var futureBounds = { | ||
x: element.position.x + delta.x, | ||
y: element.position.y + delta.y, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
if (isOverlappingBounds(futureBounds, candidate.bounds) && (!isOverlappingBounds(element.bounds, candidate.bounds) || element.type === "Ghost")) { | ||
collisionChain.push(candidate); | ||
if (lib_1.isSelectable(candidate) && candidate.selected) { | ||
// Check what the selected candidate will collide with and add it to the chain | ||
collisionChain.push.apply(collisionChain, _this.getCollisionChain(target, candidate, delta, collisionChain)); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
return collisionChain; | ||
}; | ||
/** | ||
* Returns bounds centered around the point | ||
*/ | ||
NoCollisionMovementRestrictor.prototype.getCenteredBoundsToPointer = function (mousePoint, bounds) { | ||
var middleX = mousePoint.x - bounds.width / 2; | ||
var middleY = mousePoint.y - bounds.height / 2; | ||
var shiftedBounds = { x: middleX, y: middleY, width: bounds.width, height: bounds.height }; | ||
return shiftedBounds; | ||
}; | ||
// Remove this and use the one from the improved routing branch | ||
NoCollisionMovementRestrictor.prototype.getDistanceBetweenParallelLines = function (p1, p2, secondLine) { | ||
var numerator = Math.abs((secondLine.a * p1.x) + (secondLine.b * p1.y) - secondLine.c); | ||
var denominator = Math.sqrt(Math.pow(secondLine.a, 2) + Math.pow(secondLine.b, 2)); | ||
return numerator / denominator; | ||
}; | ||
/** | ||
* Snaps the element to the target in case of a collision | ||
*/ | ||
NoCollisionMovementRestrictor.prototype.getSnappedBounds = function (element, target) { | ||
var snappedBounds = element.bounds; | ||
// Build corner points | ||
var elementTopLeft = { | ||
x: element.bounds.x, | ||
y: element.bounds.y | ||
}; | ||
var elementTopRight = { | ||
x: element.bounds.x + element.bounds.width, | ||
y: element.bounds.y | ||
}; | ||
var elementBottomLeft = { | ||
x: element.bounds.x, | ||
y: element.bounds.y + element.bounds.height | ||
}; | ||
var elementBottomRight = { | ||
x: element.bounds.x + element.bounds.width, | ||
y: element.bounds.y + element.bounds.height | ||
}; | ||
var targetTopLeft = { | ||
x: target.bounds.x, | ||
y: target.bounds.y | ||
}; | ||
var targetTopRight = { | ||
x: target.bounds.x + target.bounds.width, | ||
y: target.bounds.y | ||
}; | ||
var targetBottomLeft = { | ||
x: target.bounds.x, | ||
y: target.bounds.y + target.bounds.height | ||
}; | ||
var targetBottomRight = { | ||
x: target.bounds.x + target.bounds.width, | ||
y: target.bounds.y + target.bounds.height | ||
}; | ||
// Build lines | ||
var targetTopLine = new lib_1.PointToPointLine(targetTopLeft, targetTopRight); | ||
var targetBottomLine = new lib_1.PointToPointLine(targetBottomLeft, targetBottomRight); | ||
var targetLeftLine = new lib_1.PointToPointLine(targetTopLeft, targetBottomLeft); | ||
var targetRightLine = new lib_1.PointToPointLine(targetTopRight, targetBottomRight); | ||
// Compute distances | ||
var distanceTop = this.getDistanceBetweenParallelLines(elementBottomLeft, elementBottomRight, targetTopLine); | ||
var distanceBottom = this.getDistanceBetweenParallelLines(elementTopLeft, elementTopRight, targetBottomLine); | ||
var distanceLeft = this.getDistanceBetweenParallelLines(elementTopLeft, elementBottomLeft, targetRightLine); | ||
var distanceRight = this.getDistanceBetweenParallelLines(elementTopRight, elementBottomRight, targetLeftLine); | ||
var minimumCandidates = []; | ||
// Overlap on the horizontal lines | ||
if (isOverlapping1Dimension(element.bounds.x, element.bounds.width, target.bounds.x, target.bounds.width)) { | ||
minimumCandidates.push(distanceTop.valueOf()); | ||
minimumCandidates.push(distanceBottom.valueOf()); | ||
} | ||
// Overlap on the horizontal lines | ||
if (isOverlapping1Dimension(element.bounds.y, element.bounds.height, target.bounds.y, target.bounds.height)) { | ||
minimumCandidates.push(distanceLeft.valueOf()); | ||
minimumCandidates.push(distanceRight.valueOf()); | ||
} | ||
// Get minimum distance and then snap accordingly | ||
minimumCandidates.sort(function (a, b) { return a - b; }); | ||
var minimumDistance = minimumCandidates[0]; | ||
if (minimumDistance === distanceTop) { | ||
snappedBounds = { | ||
x: element.bounds.x, | ||
y: target.bounds.y - 1 - element.bounds.height, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
if (minimumDistance === distanceBottom) { | ||
snappedBounds = { | ||
x: element.bounds.x, | ||
y: target.bounds.y + target.bounds.height + 1, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
if (minimumDistance === distanceLeft) { | ||
snappedBounds = { | ||
x: target.bounds.x + target.bounds.width + 1, | ||
y: element.bounds.y, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
if (minimumDistance === distanceRight) { | ||
snappedBounds = { | ||
x: target.bounds.x - 1 - element.bounds.width, | ||
y: element.bounds.y, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
return snappedBounds; | ||
}; | ||
NoCollisionMovementRestrictor = __decorate([ | ||
NoOverlapMovmentRestrictor = __decorate([ | ||
inversify_1.injectable() | ||
], NoCollisionMovementRestrictor); | ||
return NoCollisionMovementRestrictor; | ||
], NoOverlapMovmentRestrictor); | ||
return NoOverlapMovmentRestrictor; | ||
}()); | ||
exports.NoCollisionMovementRestrictor = NoCollisionMovementRestrictor; | ||
/** | ||
* Used to check if 1D boxes (lines) overlap | ||
*/ | ||
function isOverlapping1Dimension(x1, width1, x2, width2) { | ||
return x1 + width1 >= x2 && x2 + width2 >= x1; | ||
exports.NoOverlapMovmentRestrictor = NoOverlapMovmentRestrictor; | ||
function areOverlapping(element1, element2) { | ||
var b1 = viewpoint_util_1.toAbsoluteBounds(element1); | ||
var b2 = viewpoint_util_1.toAbsoluteBounds(element2); | ||
var r1TopLeft = b1; | ||
var r1BottomRight = { x: b1.x + b1.width, y: b1.y + b1.height }; | ||
var r2TopLeft = b2; | ||
var r2BottomRight = { x: b2.x + b2.width, y: b2.y + b2.height }; | ||
// If one rectangle is on left side of other | ||
if (r1TopLeft.x > r2BottomRight.x || r2TopLeft.x > r1BottomRight.x) | ||
return false; | ||
// If one rectangle is above other | ||
if (r1BottomRight.y < r2TopLeft.y || r2BottomRight.y < r1TopLeft.y) | ||
return false; | ||
return true; | ||
} | ||
exports.isOverlapping1Dimension = isOverlapping1Dimension; | ||
/** | ||
* Used to check if 2 bounds are overlapping | ||
*/ | ||
function isOverlappingBounds(bounds1, bounds2) { | ||
return isOverlapping1Dimension(bounds1.x, bounds1.width, bounds2.x, bounds2.width) && | ||
isOverlapping1Dimension(bounds1.y, bounds1.height, bounds2.y, bounds2.height); | ||
} | ||
exports.isOverlappingBounds = isOverlappingBounds; | ||
exports.areOverlapping = areOverlapping; | ||
//# sourceMappingURL=movement-restrictor.js.map |
import { Action, ICommandPaletteActionProvider, LabeledAction, Point, SModelElement } from "sprotty/lib"; | ||
import { EditorContextService } from "../../base/editor-context"; | ||
import { GLSPActionDispatcher } from "../request-response/glsp-action-dispatcher"; | ||
@@ -10,3 +11,3 @@ export declare namespace ServerCommandPalette { | ||
protected actionDispatcher: GLSPActionDispatcher; | ||
constructor(actionDispatcher: GLSPActionDispatcher); | ||
protected editorContext: EditorContextService; | ||
getActions(root: Readonly<SModelElement>, text: string, lastMousePosition?: Point, index?: number): Promise<LabeledAction[]>; | ||
@@ -13,0 +14,0 @@ getPaletteActionsFromResponse(action: Action): LabeledAction[]; |
@@ -11,5 +11,2 @@ "use strict"; | ||
}; | ||
var __param = (this && this.__param) || function (paramIndex, decorator) { | ||
return function (target, key) { decorator(target, key, paramIndex); } | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -33,2 +30,3 @@ /******************************************************************************** | ||
var lib_1 = require("sprotty/lib"); | ||
var editor_context_1 = require("../../base/editor-context"); | ||
var action_definitions_1 = require("../context-actions/action-definitions"); | ||
@@ -43,4 +41,3 @@ var glsp_action_dispatcher_1 = require("../request-response/glsp-action-dispatcher"); | ||
var ServerCommandPaletteActionProvider = /** @class */ (function () { | ||
function ServerCommandPaletteActionProvider(actionDispatcher) { | ||
this.actionDispatcher = actionDispatcher; | ||
function ServerCommandPaletteActionProvider() { | ||
} | ||
@@ -50,8 +47,7 @@ ServerCommandPaletteActionProvider.prototype.getActions = function (root, text, lastMousePosition, index) { | ||
var _this = this; | ||
var selectedElementIds = Array.from(root.index.all().filter(lib_1.isSelected).map(function (e) { return e.id; })); | ||
var requestAction = new action_definitions_1.RequestContextActions(selectedElementIds, lastMousePosition, (_a = {}, | ||
var requestAction = new action_definitions_1.RequestContextActions(this.editorContext.get((_a = {}, | ||
_a[action_definitions_1.ContextActions.UI_CONTROL_KEY] = ServerCommandPalette.KEY, | ||
_a[ServerCommandPalette.TEXT] = text, | ||
_a[ServerCommandPalette.INDEX] = index ? index : 0, | ||
_a)); | ||
_a))); | ||
return this.actionDispatcher.requestUntil(requestAction).then(function (response) { return _this.getPaletteActionsFromResponse(response); }); | ||
@@ -65,6 +61,12 @@ }; | ||
}; | ||
__decorate([ | ||
inversify_1.inject(lib_1.TYPES.IActionDispatcher), | ||
__metadata("design:type", glsp_action_dispatcher_1.GLSPActionDispatcher) | ||
], ServerCommandPaletteActionProvider.prototype, "actionDispatcher", void 0); | ||
__decorate([ | ||
inversify_1.inject(editor_context_1.EditorContextService), | ||
__metadata("design:type", editor_context_1.EditorContextService) | ||
], ServerCommandPaletteActionProvider.prototype, "editorContext", void 0); | ||
ServerCommandPaletteActionProvider = __decorate([ | ||
inversify_1.injectable(), | ||
__param(0, inversify_1.inject(lib_1.TYPES.IActionDispatcher)), | ||
__metadata("design:paramtypes", [glsp_action_dispatcher_1.GLSPActionDispatcher]) | ||
inversify_1.injectable() | ||
], ServerCommandPaletteActionProvider); | ||
@@ -71,0 +73,0 @@ return ServerCommandPaletteActionProvider; |
@@ -16,3 +16,4 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Action, LabeledAction, Point, RequestAction, ResponseAction } from "sprotty/lib"; | ||
import { Action, LabeledAction, RequestAction, ResponseAction } from "sprotty/lib"; | ||
import { EditorContext } from "../../base/editor-context"; | ||
export declare namespace ContextActions { | ||
@@ -22,13 +23,7 @@ const UI_CONTROL_KEY = "ui-control"; | ||
export declare class RequestContextActions implements RequestAction<SetContextActions> { | ||
readonly selectedElementIds: string[]; | ||
readonly lastMousePosition?: Point | undefined; | ||
readonly args?: { | ||
[key: string]: string | number | boolean; | ||
} | undefined; | ||
readonly editorContext: EditorContext; | ||
readonly requestId: string; | ||
static readonly KIND = "requestContextActions"; | ||
kind: string; | ||
constructor(selectedElementIds?: string[], lastMousePosition?: Point | undefined, args?: { | ||
[key: string]: string | number | boolean; | ||
} | undefined, requestId?: string); | ||
constructor(editorContext: EditorContext, requestId?: string); | ||
} | ||
@@ -35,0 +30,0 @@ export declare class SetContextActions implements ResponseAction { |
@@ -24,8 +24,5 @@ "use strict"; | ||
var RequestContextActions = /** @class */ (function () { | ||
function RequestContextActions(selectedElementIds, lastMousePosition, args, requestId) { | ||
if (selectedElementIds === void 0) { selectedElementIds = []; } | ||
function RequestContextActions(editorContext, requestId) { | ||
if (requestId === void 0) { requestId = lib_1.generateRequestId(); } | ||
this.selectedElementIds = selectedElementIds; | ||
this.lastMousePosition = lastMousePosition; | ||
this.args = args; | ||
this.editorContext = editorContext; | ||
this.requestId = requestId; | ||
@@ -32,0 +29,0 @@ this.kind = RequestContextActions.KIND; |
import { Action, IContextMenuItemProvider, LabeledAction, Point, SModelElement } from "sprotty/lib"; | ||
import { EditorContextService } from "../../base/editor-context"; | ||
import { GLSPActionDispatcher } from "../request-response/glsp-action-dispatcher"; | ||
@@ -8,3 +9,3 @@ export declare namespace ServerContextMenu { | ||
protected actionDispatcher: GLSPActionDispatcher; | ||
constructor(actionDispatcher: GLSPActionDispatcher); | ||
protected editorContext: EditorContextService; | ||
getItems(root: Readonly<SModelElement>, lastMousePosition?: Point): Promise<LabeledAction[]>; | ||
@@ -11,0 +12,0 @@ getContextActionsFromResponse(action: Action): LabeledAction[]; |
@@ -11,5 +11,2 @@ "use strict"; | ||
}; | ||
var __param = (this && this.__param) || function (paramIndex, decorator) { | ||
return function (target, key) { decorator(target, key, paramIndex); } | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -33,2 +30,3 @@ /******************************************************************************** | ||
var lib_1 = require("sprotty/lib"); | ||
var editor_context_1 = require("../../base/editor-context"); | ||
var action_definitions_1 = require("../context-actions/action-definitions"); | ||
@@ -41,4 +39,3 @@ var glsp_action_dispatcher_1 = require("../request-response/glsp-action-dispatcher"); | ||
var ServerContextMenuItemProvider = /** @class */ (function () { | ||
function ServerContextMenuItemProvider(actionDispatcher) { | ||
this.actionDispatcher = actionDispatcher; | ||
function ServerContextMenuItemProvider() { | ||
} | ||
@@ -49,4 +46,4 @@ ServerContextMenuItemProvider.prototype.getItems = function (root, lastMousePosition) { | ||
var selectedElementIds = Array.from(root.index.all().filter(lib_1.isSelected).map(function (e) { return e.id; })); | ||
var localPosition = lastMousePosition ? root.root.parentToLocal(lib_1.subtract(lastMousePosition, root.root.canvasBounds)) : undefined; | ||
var requestAction = new action_definitions_1.RequestContextActions(selectedElementIds, localPosition, (_a = {}, _a[action_definitions_1.ContextActions.UI_CONTROL_KEY] = ServerContextMenu.KEY, _a)); | ||
var context = this.editorContext.getWithSelection(selectedElementIds, (_a = {}, _a[action_definitions_1.ContextActions.UI_CONTROL_KEY] = ServerContextMenu.KEY, _a)); | ||
var requestAction = new action_definitions_1.RequestContextActions(context); | ||
return this.actionDispatcher.requestUntil(requestAction).then(function (response) { return _this.getContextActionsFromResponse(response); }); | ||
@@ -60,6 +57,12 @@ }; | ||
}; | ||
__decorate([ | ||
inversify_1.inject(lib_1.TYPES.IActionDispatcher), | ||
__metadata("design:type", glsp_action_dispatcher_1.GLSPActionDispatcher) | ||
], ServerContextMenuItemProvider.prototype, "actionDispatcher", void 0); | ||
__decorate([ | ||
inversify_1.inject(editor_context_1.EditorContextService), | ||
__metadata("design:type", editor_context_1.EditorContextService) | ||
], ServerContextMenuItemProvider.prototype, "editorContext", void 0); | ||
ServerContextMenuItemProvider = __decorate([ | ||
inversify_1.injectable(), | ||
__param(0, inversify_1.inject(lib_1.TYPES.IActionDispatcher)), | ||
__metadata("design:paramtypes", [glsp_action_dispatcher_1.GLSPActionDispatcher]) | ||
inversify_1.injectable() | ||
], ServerContextMenuItemProvider); | ||
@@ -66,0 +69,0 @@ return ServerContextMenuItemProvider; |
@@ -38,3 +38,3 @@ /******************************************************************************** | ||
newBounds: ElementAndBounds[]; | ||
readonly kind = "changeBoundsOperation"; | ||
readonly kind = "changeBounds"; | ||
constructor(newBounds: ElementAndBounds[]); | ||
@@ -49,2 +49,14 @@ } | ||
} | ||
export declare class ReconnectConnectionOperationAction implements Action { | ||
readonly connectionElementId: string; | ||
readonly sourceElementId: string; | ||
readonly targetElementId: string; | ||
readonly kind = "reconnectConnection"; | ||
constructor(connectionElementId: string, sourceElementId: string, targetElementId: string); | ||
} | ||
export declare class ChangeRoutingPointsOperation implements Action { | ||
newRoutingPoints: ElementAndRoutingPoints[]; | ||
readonly kind = "changeRoutingPoints"; | ||
constructor(newRoutingPoints: ElementAndRoutingPoints[]); | ||
} | ||
export declare class GenericOperationAction implements Action { | ||
@@ -57,2 +69,6 @@ readonly id: string; | ||
} | ||
export interface ElementAndRoutingPoints { | ||
elementId: string; | ||
newRoutingPoints?: Point[]; | ||
} | ||
//# sourceMappingURL=operation-actions.d.ts.map |
@@ -50,2 +50,20 @@ "use strict"; | ||
exports.ChangeContainerOperation = ChangeContainerOperation; | ||
var ReconnectConnectionOperationAction = /** @class */ (function () { | ||
function ReconnectConnectionOperationAction(connectionElementId, sourceElementId, targetElementId) { | ||
this.connectionElementId = connectionElementId; | ||
this.sourceElementId = sourceElementId; | ||
this.targetElementId = targetElementId; | ||
this.kind = set_operations_1.OperationKind.RECONNECT_CONNECTION; | ||
} | ||
return ReconnectConnectionOperationAction; | ||
}()); | ||
exports.ReconnectConnectionOperationAction = ReconnectConnectionOperationAction; | ||
var ChangeRoutingPointsOperation = /** @class */ (function () { | ||
function ChangeRoutingPointsOperation(newRoutingPoints) { | ||
this.newRoutingPoints = newRoutingPoints; | ||
this.kind = set_operations_1.OperationKind.CHANGE_ROUTING_POINTS; | ||
} | ||
return ChangeRoutingPointsOperation; | ||
}()); | ||
exports.ChangeRoutingPointsOperation = ChangeRoutingPointsOperation; | ||
var GenericOperationAction = /** @class */ (function () { | ||
@@ -52,0 +70,0 @@ function GenericOperationAction(id, elementId, location) { |
@@ -21,5 +21,5 @@ /******************************************************************************** | ||
const RECONNECT_CONNECTION = "reconnectConnection"; | ||
const REROUTE_CONNECTION = "rerouteConnection"; | ||
const DELETE_ELEMENT = "delete"; | ||
const CHANGE_BOUNDS = "changeBoundsOperation"; | ||
const CHANGE_ROUTING_POINTS = "changeRoutingPoints"; | ||
const DELETE_ELEMENT = "deleteElement"; | ||
const CHANGE_BOUNDS = "changeBounds"; | ||
const CHANGE_CONTAINER = "changeContainer"; | ||
@@ -26,0 +26,0 @@ const GENERIC = "generic"; |
@@ -8,5 +8,5 @@ "use strict"; | ||
OperationKind.RECONNECT_CONNECTION = "reconnectConnection"; | ||
OperationKind.REROUTE_CONNECTION = "rerouteConnection"; | ||
OperationKind.DELETE_ELEMENT = "delete"; | ||
OperationKind.CHANGE_BOUNDS = "changeBoundsOperation"; | ||
OperationKind.CHANGE_ROUTING_POINTS = "changeRoutingPoints"; | ||
OperationKind.DELETE_ELEMENT = "deleteElement"; | ||
OperationKind.CHANGE_BOUNDS = "changeBounds"; | ||
OperationKind.CHANGE_CONTAINER = "changeContainer"; | ||
@@ -13,0 +13,0 @@ OperationKind.GENERIC = "generic"; |
import { VNode } from "snabbdom/vnode"; | ||
import { Action, CommandExecutionContext, CommandReturn, MouseListener, Point, SModelElement } from "sprotty/lib"; | ||
import { IMovementRestrictor } from "../change-bounds/movement-restrictor"; | ||
import { Action, CommandExecutionContext, CommandReturn, MouseListener, MoveAction, Point, SModelElement, SModelRoot } from "sprotty/lib"; | ||
import { ChangeBoundsTool } from "../tools/change-bounds-tool"; | ||
import { FeedbackCommand } from "./model"; | ||
@@ -34,8 +34,13 @@ export declare class ShowChangeBoundsToolResizeFeedbackAction implements Action { | ||
export declare class FeedbackMoveMouseListener extends MouseListener { | ||
protected movementRestrictor?: IMovementRestrictor | undefined; | ||
protected tool: ChangeBoundsTool; | ||
hasDragged: boolean; | ||
lastDragPosition: Point | undefined; | ||
constructor(movementRestrictor?: IMovementRestrictor | undefined); | ||
startDragPosition: Point | undefined; | ||
elementId2startPos: Map<string, Point>; | ||
constructor(tool: ChangeBoundsTool); | ||
mouseDown(target: SModelElement, event: MouseEvent): Action[]; | ||
mouseMove(target: SModelElement, event: MouseEvent): Action[]; | ||
protected collectStartPositions(root: SModelRoot): void; | ||
protected getElementMoves(target: SModelElement, event: MouseEvent, isFinished: boolean): MoveAction | undefined; | ||
protected validateMove(startPostion: Point, toPosition: Point, element: SModelElement, isFinished: boolean): Point; | ||
protected snap(position: Point, element: SModelElement, isSnap: boolean): Point; | ||
mouseEnter(target: SModelElement, event: MouseEvent): Action[]; | ||
@@ -42,0 +47,0 @@ mouseUp(target: SModelElement, event: MouseEvent): Action[]; |
@@ -27,2 +27,22 @@ "use strict"; | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spread = (this && this.__spread) || function () { | ||
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -47,4 +67,4 @@ /******************************************************************************** | ||
var smodel_util_1 = require("../../utils/smodel-util"); | ||
var viewpoint_util_1 = require("../../utils/viewpoint-util"); | ||
var model_1 = require("../change-bounds/model"); | ||
var movement_restrictor_1 = require("../change-bounds/movement-restrictor"); | ||
var model_2 = require("./model"); | ||
@@ -75,3 +95,6 @@ var ShowChangeBoundsToolResizeFeedbackAction = /** @class */ (function () { | ||
var index = context.root.index; | ||
index.all().filter(model_1.isResizable).forEach(model_1.removeResizeHandles); | ||
index | ||
.all() | ||
.filter(model_1.isResizable) | ||
.forEach(model_1.removeResizeHandles); | ||
if (smodel_util_1.isNotUndefined(this.action.elementId)) { | ||
@@ -85,3 +108,3 @@ var resizeElement = index.getById(this.action.elementId); | ||
}; | ||
ShowChangeBoundsToolResizeFeedbackCommand.KIND = 'showChangeBoundsToolResizeFeedback'; | ||
ShowChangeBoundsToolResizeFeedbackCommand.KIND = "showChangeBoundsToolResizeFeedback"; | ||
ShowChangeBoundsToolResizeFeedbackCommand = __decorate([ | ||
@@ -104,6 +127,9 @@ inversify_1.injectable(), | ||
var index = context.root.index; | ||
index.all().filter(model_1.isResizable).forEach(model_1.removeResizeHandles); | ||
index | ||
.all() | ||
.filter(model_1.isResizable) | ||
.forEach(model_1.removeResizeHandles); | ||
return context.root; | ||
}; | ||
HideChangeBoundsToolResizeFeedbackCommand.KIND = 'hideChangeBoundsToolResizeFeedback'; | ||
HideChangeBoundsToolResizeFeedbackCommand.KIND = "hideChangeBoundsToolResizeFeedback"; | ||
HideChangeBoundsToolResizeFeedbackCommand = __decorate([ | ||
@@ -126,6 +152,7 @@ inversify_1.injectable(), | ||
__extends(FeedbackMoveMouseListener, _super); | ||
function FeedbackMoveMouseListener(movementRestrictor) { | ||
function FeedbackMoveMouseListener(tool) { | ||
var _this = _super.call(this) || this; | ||
_this.movementRestrictor = movementRestrictor; | ||
_this.tool = tool; | ||
_this.hasDragged = false; | ||
_this.elementId2startPos = new Map(); | ||
return _this; | ||
@@ -137,6 +164,6 @@ } | ||
if (moveable !== undefined) { | ||
this.lastDragPosition = { x: event.pageX, y: event.pageY }; | ||
this.startDragPosition = { x: event.pageX, y: event.pageY }; | ||
} | ||
else { | ||
this.lastDragPosition = undefined; | ||
this.startDragPosition = undefined; | ||
} | ||
@@ -148,26 +175,48 @@ this.hasDragged = false; | ||
FeedbackMoveMouseListener.prototype.mouseMove = function (target, event) { | ||
var _this = this; | ||
var result = []; | ||
if (event.buttons === 0) | ||
this.mouseUp(target, event); | ||
else if (this.lastDragPosition) { | ||
var viewport = lib_1.findParentByFeature(target, lib_1.isViewport); | ||
else if (this.startDragPosition) { | ||
if (this.elementId2startPos.size === 0) { | ||
this.collectStartPositions(target.root); | ||
} | ||
this.hasDragged = true; | ||
var zoom = viewport ? viewport.zoom : 1; | ||
var mousePoint_1 = viewpoint_util_1.getAbsolutePosition(target, event); | ||
var dx_1 = (event.pageX - this.lastDragPosition.x) / zoom; | ||
var dy_1 = (event.pageY - this.lastDragPosition.y) / zoom; | ||
var nodeMoves_1 = []; | ||
var isValidMove_1 = true; | ||
target.root.index.all() | ||
.filter(function (element) { return lib_1.isSelectable(element) && element.selected; }) | ||
.forEach(function (element) { | ||
if (model_1.isBoundsAwareMoveable(element)) { | ||
// If a movement restrictor is bound attemt a non restricted move | ||
if (_this.movementRestrictor) { | ||
isValidMove_1 = _this.movementRestrictor.attemptMove(element, mousePoint_1, target, { x: dx_1, y: dy_1 }, result); | ||
} | ||
} | ||
if (lib_1.isMoveable(element) && isValidMove_1) { | ||
nodeMoves_1.push({ | ||
var moveAction = this.getElementMoves(target, event, false); | ||
if (moveAction) | ||
result.push(moveAction); | ||
} | ||
return result; | ||
}; | ||
FeedbackMoveMouseListener.prototype.collectStartPositions = function (root) { | ||
var _this = this; | ||
root.index | ||
.all() | ||
.filter(function (element) { return lib_1.isSelectable(element) && element.selected; }) | ||
.forEach(function (element) { | ||
if (lib_1.isMoveable(element)) { | ||
_this.elementId2startPos.set(element.id, element.position); | ||
} | ||
}); | ||
}; | ||
FeedbackMoveMouseListener.prototype.getElementMoves = function (target, event, isFinished) { | ||
var _this = this; | ||
if (!this.startDragPosition) | ||
return undefined; | ||
var elementMoves = []; | ||
var viewport = lib_1.findParentByFeature(target, lib_1.isViewport); | ||
var zoom = viewport ? viewport.zoom : 1; | ||
var delta = { | ||
x: (event.pageX - this.startDragPosition.x) / zoom, | ||
y: (event.pageY - this.startDragPosition.y) / zoom | ||
}; | ||
this.elementId2startPos.forEach(function (startPosition, elementId) { | ||
var element = target.root.index.getById(elementId); | ||
if (element) { | ||
var toPosition = _this.snap({ | ||
x: startPosition.x + delta.x, | ||
y: startPosition.y + delta.y | ||
}, element, !event.shiftKey); | ||
if (lib_1.isMoveable(element)) { | ||
toPosition = _this.validateMove(startPosition, toPosition, element, isFinished); | ||
elementMoves.push({ | ||
elementId: element.id, | ||
@@ -178,16 +227,36 @@ fromPosition: { | ||
}, | ||
toPosition: { | ||
x: element.position.x + dx_1, | ||
y: element.position.y + dy_1 | ||
} | ||
toPosition: toPosition | ||
}); | ||
} | ||
}); | ||
this.lastDragPosition = { x: event.pageX, y: event.pageY }; | ||
if (nodeMoves_1.length > 0 && isValidMove_1) { | ||
result.push(new lib_1.MoveAction(nodeMoves_1, false)); | ||
} | ||
}); | ||
if (elementMoves.length > 0) | ||
return new lib_1.MoveAction(elementMoves, false, isFinished); | ||
else | ||
return undefined; | ||
}; | ||
FeedbackMoveMouseListener.prototype.validateMove = function (startPostion, toPosition, element, isFinished) { | ||
var newPosition = toPosition; | ||
if (this.tool.movementRestrictor) { | ||
var valid = this.tool.movementRestrictor.validate(toPosition, element); | ||
var actions = void 0; | ||
if (!valid) { | ||
actions = movement_restrictor_1.createMovementRestrictionFeedback(element, this.tool.movementRestrictor); | ||
if (isFinished) { | ||
newPosition = startPostion; | ||
} | ||
} | ||
else { | ||
actions = movement_restrictor_1.removeMovementRestrictionFeedback(element, this.tool.movementRestrictor); | ||
} | ||
this.tool.dispatchFeedback(this, actions); | ||
} | ||
return result; | ||
return newPosition; | ||
}; | ||
FeedbackMoveMouseListener.prototype.snap = function (position, element, isSnap) { | ||
if (isSnap && this.tool.snapper) | ||
return this.tool.snapper.snap(position, element); | ||
else | ||
return position; | ||
}; | ||
FeedbackMoveMouseListener.prototype.mouseEnter = function (target, event) { | ||
@@ -199,5 +268,16 @@ if (target instanceof lib_1.SModelRoot && event.buttons === 0) | ||
FeedbackMoveMouseListener.prototype.mouseUp = function (target, event) { | ||
var result = []; | ||
if (this.startDragPosition) { | ||
var moveAction = this.getElementMoves(target, event, true); | ||
if (moveAction) { | ||
result.push(moveAction); | ||
} | ||
if (this.tool.movementRestrictor) { | ||
result.push.apply(result, __spread(movement_restrictor_1.removeMovementRestrictionFeedback(target, this.tool.movementRestrictor))); | ||
} | ||
} | ||
this.hasDragged = false; | ||
this.lastDragPosition = undefined; | ||
return []; | ||
this.startDragPosition = undefined; | ||
this.elementId2startPos.clear(); | ||
return result; | ||
}; | ||
@@ -204,0 +284,0 @@ FeedbackMoveMouseListener.prototype.decorate = function (vnode, element) { |
@@ -170,3 +170,3 @@ "use strict"; | ||
var feedbackEdgeSchema = { | ||
type: 'edge', | ||
type: elementTypeId, | ||
id: feedbackEdgeId(root), | ||
@@ -173,0 +173,0 @@ sourceId: source.id, |
@@ -24,3 +24,3 @@ "use strict"; | ||
var creation_tool_feedback_1 = require("./creation-tool-feedback"); | ||
var cursor_feedback_1 = require("./cursor-feedback"); | ||
var css_feedback_1 = require("./css-feedback"); | ||
var edge_edit_tool_feedback_1 = require("./edge-edit-tool-feedback"); | ||
@@ -31,4 +31,4 @@ var feedback_action_dispatcher_1 = require("./feedback-action-dispatcher"); | ||
bind(types_1.GLSP_TYPES.IFeedbackActionDispatcher).to(feedback_action_dispatcher_1.FeedbackActionDispatcher).inSingletonScope(); | ||
lib_1.configureCommand({ bind: bind, isBound: isBound }, css_feedback_1.ModifyCssFeedbackCommand); | ||
// create node and edge tool feedback | ||
lib_1.configureCommand({ bind: bind, isBound: isBound }, cursor_feedback_1.ApplyCursorCSSFeedbackActionCommand); | ||
lib_1.configureCommand({ bind: bind, isBound: isBound }, creation_tool_feedback_1.DrawFeedbackEdgeCommand); | ||
@@ -35,0 +35,0 @@ lib_1.configureCommand({ bind: bind, isBound: isBound }, creation_tool_feedback_1.RemoveFeedbackEdgeCommand); |
@@ -1,7 +0,8 @@ | ||
import { Action, BoundsAware, Dimension, ElementAndBounds, KeyTool, ModelLayoutOptions, MouseListener, Point, SModelElement, SModelRoot, SParentElement, Tool } from "sprotty/lib"; | ||
import { SResizeHandle } from "../change-bounds/model"; | ||
import { Action, Bounds, BoundsAware, Dimension, EdgeRouterRegistry, ElementAndBounds, ISnapper, KeyTool, ModelLayoutOptions, MouseListener, Point, SModelElement, SModelRoot, SParentElement, Tool } from "sprotty/lib"; | ||
import { Resizable, SResizeHandle } from "../change-bounds/model"; | ||
import { IMovementRestrictor } from "../change-bounds/movement-restrictor"; | ||
import { IMouseTool } from "../mouse-tool/mouse-tool"; | ||
import { SelectionListener, SelectionService } from "../select/selection-service"; | ||
import { IFeedbackActionDispatcher } from "../tool-feedback/feedback-action-dispatcher"; | ||
import { IFeedbackActionDispatcher, IFeedbackEmitter } from "../tool-feedback/feedback-action-dispatcher"; | ||
import { DragAwareMouseListener } from "./drag-aware-mouse-listener"; | ||
/** | ||
@@ -25,3 +26,5 @@ * The change bounds tool has the license to move multiple elements or resize a single element by implementing the ChangeBounds operation. | ||
protected feedbackDispatcher: IFeedbackActionDispatcher; | ||
protected movementRestrictor?: IMovementRestrictor | undefined; | ||
readonly edgeRouterRegistry?: EdgeRouterRegistry | undefined; | ||
readonly snapper?: ISnapper | undefined; | ||
readonly movementRestrictor?: IMovementRestrictor | undefined; | ||
static ID: string; | ||
@@ -31,3 +34,3 @@ readonly id: string; | ||
protected changeBoundsListener: MouseListener & SelectionListener; | ||
constructor(selectionService: SelectionService, mouseTool: IMouseTool, keyTool: KeyTool, feedbackDispatcher: IFeedbackActionDispatcher, movementRestrictor?: IMovementRestrictor | undefined); | ||
constructor(selectionService: SelectionService, mouseTool: IMouseTool, keyTool: KeyTool, feedbackDispatcher: IFeedbackActionDispatcher, edgeRouterRegistry?: EdgeRouterRegistry | undefined, snapper?: ISnapper | undefined, movementRestrictor?: IMovementRestrictor | undefined); | ||
enable(): void; | ||
@@ -37,8 +40,10 @@ protected createMoveMouseListener(): MouseListener; | ||
disable(): void; | ||
dispatchFeedback(actions: Action[]): void; | ||
dispatchFeedback(feedbackEmmmiter: IFeedbackEmitter, actions: Action[]): void; | ||
} | ||
export declare class ChangeBoundsListener extends MouseListener implements SelectionListener { | ||
export declare class ChangeBoundsListener extends DragAwareMouseListener implements SelectionListener { | ||
protected tool: ChangeBoundsTool; | ||
protected lastDragPosition?: Point; | ||
protected positionDelta: Point; | ||
protected initialPositon: Point | undefined; | ||
protected initialBounds: Bounds | undefined; | ||
protected activeResizeElementId?: string; | ||
@@ -49,3 +54,3 @@ protected activeResizeHandle?: SResizeHandle; | ||
mouseMove(target: SModelElement, event: MouseEvent): Action[]; | ||
mouseUp(target: SModelElement, event: MouseEvent): Action[]; | ||
draggingMouseUp(target: SModelElement, event: MouseEvent): Action[]; | ||
selectionChanged(root: SModelRoot, selectedElements: string[]): void; | ||
@@ -59,2 +64,6 @@ protected setActiveResizeElement(target: SModelElement): boolean; | ||
protected handleElementResize(): Action[]; | ||
protected handleTopLeftResize(resizeElement: SParentElement & Resizable): Action[]; | ||
protected handleTopRightResize(resizeElement: SParentElement & Resizable): Action[]; | ||
protected handleBottomLeftResize(resizeElement: SParentElement & Resizable): Action[]; | ||
protected handleBottomRightResize(resizeElement: SParentElement & Resizable): Action[]; | ||
protected createChangeBoundsAction(element: SModelElement & BoundsAware): Action[]; | ||
@@ -64,2 +73,3 @@ protected createElementAndBounds(element: SModelElement & BoundsAware): ElementAndBounds[]; | ||
protected isValidBoundChange(element: SModelElement & BoundsAware, newPosition: Point, newSize: Dimension): boolean; | ||
protected isValidSize(element: SModelElement & BoundsAware, size: Dimension): boolean; | ||
protected minWidth(element: SModelElement & BoundsAware): number; | ||
@@ -66,0 +76,0 @@ protected minHeight(element: SModelElement & BoundsAware): number; |
@@ -38,2 +38,22 @@ "use strict"; | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
}; | ||
var __spread = (this && this.__spread) || function () { | ||
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -60,5 +80,7 @@ /******************************************************************************** | ||
var model_1 = require("../change-bounds/model"); | ||
var movement_restrictor_1 = require("../change-bounds/movement-restrictor"); | ||
var operation_actions_1 = require("../operation/operation-actions"); | ||
var selection_service_1 = require("../select/selection-service"); | ||
var change_bounds_tool_feedback_1 = require("../tool-feedback/change-bounds-tool-feedback"); | ||
var drag_aware_mouse_listener_1 = require("./drag-aware-mouse-listener"); | ||
/** | ||
@@ -78,3 +100,3 @@ * The change bounds tool has the license to move multiple elements or resize a single element by implementing the ChangeBounds operation. | ||
var ChangeBoundsTool = /** @class */ (function () { | ||
function ChangeBoundsTool(selectionService, mouseTool, keyTool, feedbackDispatcher, movementRestrictor) { | ||
function ChangeBoundsTool(selectionService, mouseTool, keyTool, feedbackDispatcher, edgeRouterRegistry, snapper, movementRestrictor) { | ||
this.selectionService = selectionService; | ||
@@ -84,2 +106,4 @@ this.mouseTool = mouseTool; | ||
this.feedbackDispatcher = feedbackDispatcher; | ||
this.edgeRouterRegistry = edgeRouterRegistry; | ||
this.snapper = snapper; | ||
this.movementRestrictor = movementRestrictor; | ||
@@ -101,3 +125,3 @@ this.id = ChangeBoundsTool_1.ID; | ||
ChangeBoundsTool.prototype.createMoveMouseListener = function () { | ||
return new change_bounds_tool_feedback_1.FeedbackMoveMouseListener(this.movementRestrictor); | ||
return new change_bounds_tool_feedback_1.FeedbackMoveMouseListener(this); | ||
}; | ||
@@ -111,6 +135,7 @@ ChangeBoundsTool.prototype.createChangeBoundsListener = function () { | ||
this.mouseTool.deregister(this.feedbackMoveMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new change_bounds_tool_feedback_1.HideChangeBoundsToolResizeFeedbackAction]); | ||
this.feedbackDispatcher.deregisterFeedback(this.feedbackMoveMouseListener, []); | ||
this.feedbackDispatcher.deregisterFeedback(this.changeBoundsListener, [new change_bounds_tool_feedback_1.HideChangeBoundsToolResizeFeedbackAction]); | ||
}; | ||
ChangeBoundsTool.prototype.dispatchFeedback = function (actions) { | ||
this.feedbackDispatcher.registerFeedback(this, actions); | ||
ChangeBoundsTool.prototype.dispatchFeedback = function (feedbackEmmmiter, actions) { | ||
this.feedbackDispatcher.registerFeedback(feedbackEmmmiter, actions); | ||
}; | ||
@@ -125,4 +150,6 @@ var ChangeBoundsTool_1; | ||
__param(3, inversify_1.inject(types_1.GLSP_TYPES.IFeedbackActionDispatcher)), | ||
__param(4, inversify_1.inject(types_1.GLSP_TYPES.IMovementRestrictor)), __param(4, inversify_1.optional()), | ||
__metadata("design:paramtypes", [selection_service_1.SelectionService, Object, lib_1.KeyTool, Object, Object]) | ||
__param(4, inversify_1.inject(lib_1.EdgeRouterRegistry)), __param(4, inversify_1.optional()), | ||
__param(5, inversify_1.inject(lib_1.TYPES.ISnapper)), __param(5, inversify_1.optional()), | ||
__param(6, inversify_1.inject(types_1.GLSP_TYPES.IMovementRestrictor)), __param(6, inversify_1.optional()), | ||
__metadata("design:paramtypes", [selection_service_1.SelectionService, Object, lib_1.KeyTool, Object, lib_1.EdgeRouterRegistry, Object, Object]) | ||
], ChangeBoundsTool); | ||
@@ -138,5 +165,7 @@ return ChangeBoundsTool; | ||
_this.positionDelta = { x: 0, y: 0 }; | ||
_this.initialPositon = undefined; | ||
return _this; | ||
} | ||
ChangeBoundsListener.prototype.mouseDown = function (target, event) { | ||
_super.prototype.mouseDown.call(this, target, event); | ||
if (event.button !== 0) { | ||
@@ -161,3 +190,4 @@ return []; | ||
ChangeBoundsListener.prototype.mouseMove = function (target, event) { | ||
if (this.updatePosition(target, event)) { | ||
_super.prototype.mouseMove.call(this, target, event); | ||
if (this.updatePosition(target, event) && this.activeResizeHandle) { | ||
// rely on the FeedbackMoveMouseListener to update the element bounds of selected elements | ||
@@ -169,3 +199,3 @@ // consider resize handles ourselves | ||
}; | ||
ChangeBoundsListener.prototype.mouseUp = function (target, event) { | ||
ChangeBoundsListener.prototype.draggingMouseUp = function (target, event) { | ||
var _this = this; | ||
@@ -187,4 +217,10 @@ if (this.lastDragPosition === undefined) { | ||
var newBounds_1 = []; | ||
var newRoutingPoints_1 = []; | ||
smodel_util_1.forEachElement(target, smodel_util_1.isNonRoutableSelectedMovableBoundsAware, function (element) { | ||
return _this.createElementAndBounds(element).forEach(function (bounds) { return newBounds_1.push(bounds); }); | ||
_this.createElementAndBounds(element).forEach(function (bounds) { return newBounds_1.push(bounds); }); | ||
// If client routing is enabled -> delegate routingpoints of connected edges to server | ||
if (_this.tool.edgeRouterRegistry && element instanceof lib_1.SConnectableElement) { | ||
element.incomingEdges.map(smodel_util_1.toElementAndRoutingPoints).forEach(function (ear) { return newRoutingPoints_1.push(ear); }); | ||
element.outgoingEdges.map(smodel_util_1.toElementAndRoutingPoints).forEach(function (ear) { return newRoutingPoints_1.push(ear); }); | ||
} | ||
}); | ||
@@ -194,2 +230,5 @@ if (newBounds_1.length > 0) { | ||
} | ||
if (newRoutingPoints_1.length > 0) { | ||
actions.push(new operation_actions_1.ChangeRoutingPointsOperation(newRoutingPoints_1)); | ||
} | ||
} | ||
@@ -232,3 +271,3 @@ this.resetPosition(); | ||
this.activeResizeElementId = moveableElement.id; | ||
this.tool.dispatchFeedback([new change_bounds_tool_feedback_1.ShowChangeBoundsToolResizeFeedbackAction(this.activeResizeElementId)]); | ||
this.tool.dispatchFeedback(this, [new change_bounds_tool_feedback_1.ShowChangeBoundsToolResizeFeedbackAction(this.activeResizeElementId)]); | ||
return true; | ||
@@ -242,3 +281,8 @@ } | ||
ChangeBoundsListener.prototype.initPosition = function (event) { | ||
this.initialPositon = { x: event.pageX, y: event.pageY }; | ||
this.lastDragPosition = { x: event.pageX, y: event.pageY }; | ||
if (this.activeResizeHandle) { | ||
var resizeElement = lib_1.findParentByFeature(this.activeResizeHandle, model_1.isResizable); | ||
this.initialBounds = { x: resizeElement.bounds.x, y: resizeElement.bounds.y, width: resizeElement.bounds.width, height: resizeElement.bounds.height }; | ||
} | ||
}; | ||
@@ -258,3 +302,3 @@ ChangeBoundsListener.prototype.updatePosition = function (target, event) { | ||
ChangeBoundsListener.prototype.reset = function () { | ||
this.tool.dispatchFeedback([new change_bounds_tool_feedback_1.HideChangeBoundsToolResizeFeedbackAction()]); | ||
this.tool.dispatchFeedback(this, [new change_bounds_tool_feedback_1.HideChangeBoundsToolResizeFeedbackAction()]); | ||
this.resetPosition(); | ||
@@ -265,2 +309,3 @@ }; | ||
this.lastDragPosition = undefined; | ||
this.initialPositon = undefined; | ||
this.positionDelta = { x: 0, y: 0 }; | ||
@@ -272,3 +317,2 @@ }; | ||
} | ||
var actions = []; | ||
var resizeElement = lib_1.findParentByFeature(this.activeResizeHandle, model_1.isResizable); | ||
@@ -278,21 +322,25 @@ if (this.isActiveResizeElement(resizeElement)) { | ||
case model_1.ResizeHandleLocation.TopLeft: | ||
this.createSetBoundsAction(resizeElement, resizeElement.bounds.x + this.positionDelta.x, resizeElement.bounds.y + this.positionDelta.y, resizeElement.bounds.width - this.positionDelta.x, resizeElement.bounds.height - this.positionDelta.y) | ||
.forEach(function (action) { return actions.push(action); }); | ||
break; | ||
return this.handleTopLeftResize(resizeElement); | ||
case model_1.ResizeHandleLocation.TopRight: | ||
this.createSetBoundsAction(resizeElement, resizeElement.bounds.x, resizeElement.bounds.y + this.positionDelta.y, resizeElement.bounds.width + this.positionDelta.x, resizeElement.bounds.height - this.positionDelta.y) | ||
.forEach(function (action) { return actions.push(action); }); | ||
break; | ||
return this.handleTopRightResize(resizeElement); | ||
case model_1.ResizeHandleLocation.BottomLeft: | ||
this.createSetBoundsAction(resizeElement, resizeElement.bounds.x + this.positionDelta.x, resizeElement.bounds.y, resizeElement.bounds.width - this.positionDelta.x, resizeElement.bounds.height + this.positionDelta.y) | ||
.forEach(function (action) { return actions.push(action); }); | ||
break; | ||
return this.handleBottomLeftResize(resizeElement); | ||
case model_1.ResizeHandleLocation.BottomRight: | ||
this.createSetBoundsAction(resizeElement, resizeElement.bounds.x, resizeElement.bounds.y, resizeElement.bounds.width + this.positionDelta.x, resizeElement.bounds.height + this.positionDelta.y) | ||
.forEach(function (action) { return actions.push(action); }); | ||
break; | ||
return this.handleBottomRightResize(resizeElement); | ||
} | ||
} | ||
return actions; | ||
return []; | ||
}; | ||
ChangeBoundsListener.prototype.handleTopLeftResize = function (resizeElement) { | ||
return this.createSetBoundsAction(resizeElement, resizeElement.bounds.x + this.positionDelta.x, resizeElement.bounds.y + this.positionDelta.y, resizeElement.bounds.width - this.positionDelta.x, resizeElement.bounds.height - this.positionDelta.y); | ||
}; | ||
ChangeBoundsListener.prototype.handleTopRightResize = function (resizeElement) { | ||
return this.createSetBoundsAction(resizeElement, resizeElement.bounds.x, resizeElement.bounds.y + this.positionDelta.y, resizeElement.bounds.width + this.positionDelta.x, resizeElement.bounds.height - this.positionDelta.y); | ||
}; | ||
ChangeBoundsListener.prototype.handleBottomLeftResize = function (resizeElement) { | ||
return this.createSetBoundsAction(resizeElement, resizeElement.bounds.x + this.positionDelta.x, resizeElement.bounds.y, resizeElement.bounds.width - this.positionDelta.x, resizeElement.bounds.height + this.positionDelta.y); | ||
}; | ||
ChangeBoundsListener.prototype.handleBottomRightResize = function (resizeElement) { | ||
return this.createSetBoundsAction(resizeElement, resizeElement.bounds.x, resizeElement.bounds.y, resizeElement.bounds.width + this.positionDelta.x, resizeElement.bounds.height + this.positionDelta.y); | ||
}; | ||
ChangeBoundsListener.prototype.createChangeBoundsAction = function (element) { | ||
@@ -302,2 +350,10 @@ if (this.isValidBoundChange(element, element.bounds, element.bounds)) { | ||
} | ||
else if (this.initialBounds) { | ||
var actions = []; | ||
if (this.tool.movementRestrictor) { | ||
actions.push.apply(actions, __spread(movement_restrictor_1.removeMovementRestrictionFeedback(element, this.tool.movementRestrictor))); | ||
} | ||
actions.push(new lib_1.SetBoundsAction([{ elementId: element.id, newPosition: this.initialBounds, newSize: this.initialBounds }])); | ||
return actions; | ||
} | ||
return []; | ||
@@ -314,10 +370,27 @@ }; | ||
var newSize = { width: width, height: height }; | ||
var result = []; | ||
if (this.isValidBoundChange(element, newPosition, newSize)) { | ||
return [new lib_1.SetBoundsAction([{ elementId: element.id, newPosition: newPosition, newSize: newSize }])]; | ||
if (this.tool.movementRestrictor) { | ||
result.push.apply(result, __spread(movement_restrictor_1.removeMovementRestrictionFeedback(element, this.tool.movementRestrictor))); | ||
} | ||
result.push(new lib_1.SetBoundsAction([{ elementId: element.id, newPosition: newPosition, newSize: newSize }])); | ||
} | ||
return []; | ||
else if (this.isValidSize(element, newSize)) { | ||
if (this.tool.movementRestrictor) { | ||
result.push.apply(result, __spread(movement_restrictor_1.createMovementRestrictionFeedback(element, this.tool.movementRestrictor))); | ||
} | ||
result.push(new lib_1.SetBoundsAction([{ elementId: element.id, newPosition: newPosition, newSize: newSize }])); | ||
} | ||
return result; | ||
}; | ||
ChangeBoundsListener.prototype.isValidBoundChange = function (element, newPosition, newSize) { | ||
return newSize.width >= this.minWidth(element) && newSize.height >= this.minHeight(element); | ||
var valid = this.isValidSize(element, newSize); | ||
if (this.tool.movementRestrictor) { | ||
return valid && this.tool.movementRestrictor.validate(newPosition, element); | ||
} | ||
return valid; | ||
}; | ||
ChangeBoundsListener.prototype.isValidSize = function (element, size) { | ||
return size.width >= this.minWidth(element) && size.height >= this.minHeight(element); | ||
}; | ||
ChangeBoundsListener.prototype.minWidth = function (element) { | ||
@@ -345,4 +418,4 @@ var layoutOptions = this.getLayoutOptions(element); | ||
return ChangeBoundsListener; | ||
}(lib_1.MouseListener)); | ||
}(drag_aware_mouse_listener_1.DragAwareMouseListener)); | ||
exports.ChangeBoundsListener = ChangeBoundsListener; | ||
//# sourceMappingURL=change-bounds-tool.js.map |
@@ -51,3 +51,3 @@ "use strict"; | ||
var creation_tool_feedback_1 = require("../tool-feedback/creation-tool-feedback"); | ||
var cursor_feedback_1 = require("../tool-feedback/cursor-feedback"); | ||
var css_feedback_1 = require("../tool-feedback/css-feedback"); | ||
var drag_aware_mouse_listener_1 = require("./drag-aware-mouse-listener"); | ||
@@ -75,7 +75,7 @@ exports.TOOL_ID_PREFIX = "tool"; | ||
this.mouseTool.register(this.creationToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.NODE_CREATION)]); | ||
this.feedbackDispatcher.registerFeedback(this, [css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.NODE_CREATION)]); | ||
}; | ||
NodeCreationTool.prototype.disable = function () { | ||
this.mouseTool.deregister(this.creationToolMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new cursor_feedback_1.ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.deregisterFeedback(this, [css_feedback_1.cursorFeedbackAction()]); | ||
}; | ||
@@ -122,4 +122,4 @@ NodeCreationTool.prototype.dispatchFeedback = function (actions) { | ||
var feedback = this.creationAllowed(this.elementTypeId) | ||
? new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.NODE_CREATION) : | ||
new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED); | ||
? css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.NODE_CREATION) : | ||
css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED); | ||
this.tool.dispatchFeedback([feedback]); | ||
@@ -159,3 +159,3 @@ } | ||
this.mouseTool.register(this.feedbackEndMovingMouseListener); | ||
this.dispatchFeedback([new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
this.dispatchFeedback([css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
}; | ||
@@ -165,3 +165,3 @@ EdgeCreationTool.prototype.disable = function () { | ||
this.mouseTool.deregister(this.feedbackEndMovingMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new creation_tool_feedback_1.RemoveFeedbackEdgeAction(), new cursor_feedback_1.ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new creation_tool_feedback_1.RemoveFeedbackEdgeAction(), css_feedback_1.cursorFeedbackAction()]); | ||
}; | ||
@@ -247,8 +247,8 @@ EdgeCreationTool.prototype.dispatchFeedback = function (actions) { | ||
if (this.allowedTarget) { | ||
var action = !this.isSourceSelected() ? new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.EDGE_CREATION_SOURCE) : | ||
new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.EDGE_CREATION_TARGET); | ||
var action = !this.isSourceSelected() ? css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.EDGE_CREATION_SOURCE) : | ||
css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.EDGE_CREATION_TARGET); | ||
return [action]; | ||
} | ||
} | ||
return [new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED)]; | ||
return [css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED)]; | ||
} | ||
@@ -255,0 +255,0 @@ return []; |
@@ -48,3 +48,3 @@ "use strict"; | ||
var operation_actions_1 = require("../operation/operation-actions"); | ||
var cursor_feedback_1 = require("../tool-feedback/cursor-feedback"); | ||
var css_feedback_1 = require("../tool-feedback/css-feedback"); | ||
/** | ||
@@ -108,7 +108,7 @@ * Deletes selected elements when hitting the `Del` key. | ||
this.mouseTool.register(this.deleteToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.ELEMENT_DELETION)]); | ||
this.feedbackDispatcher.registerFeedback(this, [css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.ELEMENT_DELETION)]); | ||
}; | ||
MouseDeleteTool.prototype.disable = function () { | ||
this.mouseTool.deregister(this.deleteToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new cursor_feedback_1.ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.registerFeedback(this, [css_feedback_1.cursorFeedbackAction()]); | ||
}; | ||
@@ -115,0 +115,0 @@ var MouseDeleteTool_1; |
@@ -26,4 +26,4 @@ /******************************************************************************** | ||
export declare class DragAwareMouseListener extends MouseListener { | ||
private isMouseDown; | ||
private isMouseDrag; | ||
private _isMouseDown; | ||
private _isMouseDrag; | ||
mouseDown(target: SModelElement, event: MouseEvent): Action[]; | ||
@@ -34,4 +34,5 @@ mouseMove(target: SModelElement, event: MouseEvent): Action[]; | ||
draggingMouseUp(element: SModelElement, event: MouseEvent): Action[]; | ||
readonly isDragging: boolean; | ||
readonly isMouseDrag: boolean; | ||
readonly isMouseDown: boolean; | ||
} | ||
//# sourceMappingURL=drag-aware-mouse-listener.d.ts.map |
@@ -44,13 +44,13 @@ "use strict"; | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
_this.isMouseDown = false; | ||
_this.isMouseDrag = false; | ||
_this._isMouseDown = false; | ||
_this._isMouseDrag = false; | ||
return _this; | ||
} | ||
DragAwareMouseListener.prototype.mouseDown = function (target, event) { | ||
this.isMouseDown = true; | ||
this._isMouseDown = true; | ||
return []; | ||
}; | ||
DragAwareMouseListener.prototype.mouseMove = function (target, event) { | ||
if (this.isMouseDown) { | ||
this.isMouseDrag = true; | ||
if (this._isMouseDown) { | ||
this._isMouseDrag = true; | ||
} | ||
@@ -60,5 +60,5 @@ return []; | ||
DragAwareMouseListener.prototype.mouseUp = function (element, event) { | ||
this.isMouseDown = false; | ||
if (this.isMouseDrag) { | ||
this.isMouseDrag = false; | ||
this._isMouseDown = false; | ||
if (this._isMouseDrag) { | ||
this._isMouseDrag = false; | ||
return this.draggingMouseUp(element, event); | ||
@@ -74,5 +74,5 @@ } | ||
}; | ||
Object.defineProperty(DragAwareMouseListener.prototype, "isDragging", { | ||
Object.defineProperty(DragAwareMouseListener.prototype, "isMouseDrag", { | ||
get: function () { | ||
return this.isMouseDrag; | ||
return this._isMouseDrag; | ||
}, | ||
@@ -82,2 +82,9 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(DragAwareMouseListener.prototype, "isMouseDown", { | ||
get: function () { | ||
return this._isMouseDown; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
return DragAwareMouseListener; | ||
@@ -84,0 +91,0 @@ }(lib_1.MouseListener)); |
@@ -78,7 +78,7 @@ "use strict"; | ||
var smodel_util_1 = require("../../utils/smodel-util"); | ||
var action_definitions_1 = require("../reconnect/action-definitions"); | ||
var operation_actions_1 = require("../operation/operation-actions"); | ||
var model_1 = require("../reconnect/model"); | ||
var selection_service_1 = require("../select/selection-service"); | ||
var creation_tool_feedback_1 = require("../tool-feedback/creation-tool-feedback"); | ||
var cursor_feedback_1 = require("../tool-feedback/cursor-feedback"); | ||
var css_feedback_1 = require("../tool-feedback/css-feedback"); | ||
var edge_edit_tool_feedback_1 = require("../tool-feedback/edge-edit-tool-feedback"); | ||
@@ -166,3 +166,3 @@ var EdgeEditTool = /** @class */ (function () { | ||
this.tool.dispatchFeedback([new edge_edit_tool_feedback_1.HideEdgeReconnectHandlesFeedbackAction(), | ||
new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.EDGE_RECONNECT), | ||
css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.EDGE_RECONNECT), | ||
new edge_edit_tool_feedback_1.DrawFeedbackEdgeSourceAction(this.edge.type, this.edge.targetId)]); | ||
@@ -173,3 +173,3 @@ this.reconnectMode = "NEW_SOURCE"; | ||
this.tool.dispatchFeedback([new edge_edit_tool_feedback_1.HideEdgeReconnectHandlesFeedbackAction(), | ||
new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.EDGE_CREATION_TARGET), | ||
css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.EDGE_CREATION_TARGET), | ||
new creation_tool_feedback_1.DrawFeedbackEdgeAction(this.edge.type, this.edge.sourceId)]); | ||
@@ -245,3 +245,3 @@ this.reconnectMode = "NEW_TARGET"; | ||
if (this.requiresReconnect(sourceId, targetId)) { | ||
result.push(new action_definitions_1.ReconnectConnectionOperationAction(this.edge.id, sourceId, targetId)); | ||
result.push(new operation_actions_1.ReconnectConnectionOperationAction(this.edge.id, sourceId, targetId)); | ||
} | ||
@@ -254,3 +254,3 @@ this.reset(); | ||
if (latestEdge && smodel_util_1.isRoutable(latestEdge)) { | ||
result.push(new action_definitions_1.RerouteConnectionOperationAction(latestEdge.id, latestEdge.routingPoints)); | ||
result.push(new operation_actions_1.ChangeRoutingPointsOperation([{ elementId: latestEdge.id, newRoutingPoints: latestEdge.routingPoints }])); | ||
this.routingHandle = undefined; | ||
@@ -269,7 +269,7 @@ } | ||
(this.reconnectMode === 'NEW_TARGET' && currentTarget.canConnect(this.edge, "target"))) { | ||
this.tool.dispatchFeedback([new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.EDGE_RECONNECT)]); | ||
this.tool.dispatchFeedback([css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.EDGE_RECONNECT)]); | ||
return []; | ||
} | ||
} | ||
this.tool.dispatchFeedback([new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
this.tool.dispatchFeedback([css_feedback_1.cursorFeedbackAction(css_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
} | ||
@@ -332,3 +332,3 @@ } | ||
result.push.apply(result, __spread([new edge_edit_tool_feedback_1.HideEdgeReconnectHandlesFeedbackAction(), | ||
new cursor_feedback_1.ApplyCursorCSSFeedbackAction(), new creation_tool_feedback_1.RemoveFeedbackEdgeAction()])); | ||
css_feedback_1.cursorFeedbackAction(), new creation_tool_feedback_1.RemoveFeedbackEdgeAction()])); | ||
this.tool.dispatchFeedback(result); | ||
@@ -335,0 +335,0 @@ }; |
@@ -19,2 +19,3 @@ /******************************************************************************** | ||
import glspContextMenuModule from "./features/context-menu/di.config"; | ||
import glspServerCopyPasteModule from "./features/copy-paste/di.config"; | ||
import glspEditLabelValidationModule from "./features/edit-label-validation/di.config"; | ||
@@ -35,6 +36,10 @@ import executeModule from "./features/execute/di.config"; | ||
export * from './base/command-stack'; | ||
export * from './base/editor-context'; | ||
export * from './features/change-bounds/model'; | ||
export * from './features/change-bounds/movement-restrictor'; | ||
export * from './features/change-bounds/snap'; | ||
export * from './features/context-actions/action-definitions'; | ||
export * from './features/context-menu/delete-element-context-menu'; | ||
export * from './features/command-palette/server-command-palette-provider'; | ||
export * from './features/copy-paste/copy-paste-handler'; | ||
export * from './features/edit-label-validation/edit-label-validator'; | ||
@@ -51,3 +56,2 @@ export * from './features/execute/execute-command'; | ||
export * from './features/rank/model'; | ||
export * from './features/reconnect/action-definitions'; | ||
export * from './features/reconnect/model'; | ||
@@ -59,3 +63,3 @@ export * from './features/request-response/glsp-action-dispatcher'; | ||
export * from './features/tool-feedback/creation-tool-feedback'; | ||
export * from './features/tool-feedback/cursor-feedback'; | ||
export * from './features/tool-feedback/css-feedback'; | ||
export * from './features/tool-feedback/edge-edit-tool-feedback'; | ||
@@ -83,3 +87,3 @@ export * from './features/tool-feedback/feedback-action-dispatcher'; | ||
export { validationModule, saveModule, executeModule, paletteModule, toolFeedbackModule, defaultGLSPModule, modelHintsModule, glspCommandPaletteModule, requestResponseModule, // | ||
glspContextMenuModule, glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule }; | ||
glspContextMenuModule, glspServerCopyPasteModule, glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -27,24 +27,26 @@ "use strict"; | ||
exports.glspContextMenuModule = di_config_3.default; | ||
var di_config_4 = require("./features/edit-label-validation/di.config"); | ||
exports.glspEditLabelValidationModule = di_config_4.default; | ||
var di_config_5 = require("./features/execute/di.config"); | ||
exports.executeModule = di_config_5.default; | ||
var di_config_6 = require("./features/hints/di.config"); | ||
exports.modelHintsModule = di_config_6.default; | ||
var di_config_7 = require("./features/layout/di.config"); | ||
exports.layoutCommandsModule = di_config_7.default; | ||
var di_config_8 = require("./features/mouse-tool/di.config"); | ||
exports.glspMouseToolModule = di_config_8.default; | ||
var di_config_9 = require("./features/request-response/di.config"); | ||
exports.requestResponseModule = di_config_9.default; | ||
var di_config_10 = require("./features/save/di.config"); | ||
exports.saveModule = di_config_10.default; | ||
var di_config_11 = require("./features/select/di.config"); | ||
exports.glspSelectModule = di_config_11.default; | ||
var di_config_12 = require("./features/tool-feedback/di.config"); | ||
exports.toolFeedbackModule = di_config_12.default; | ||
var di_config_13 = require("./features/tool-palette/di.config"); | ||
exports.paletteModule = di_config_13.default; | ||
var di_config_14 = require("./features/validation/di.config"); | ||
exports.validationModule = di_config_14.default; | ||
var di_config_4 = require("./features/copy-paste/di.config"); | ||
exports.glspServerCopyPasteModule = di_config_4.default; | ||
var di_config_5 = require("./features/edit-label-validation/di.config"); | ||
exports.glspEditLabelValidationModule = di_config_5.default; | ||
var di_config_6 = require("./features/execute/di.config"); | ||
exports.executeModule = di_config_6.default; | ||
var di_config_7 = require("./features/hints/di.config"); | ||
exports.modelHintsModule = di_config_7.default; | ||
var di_config_8 = require("./features/layout/di.config"); | ||
exports.layoutCommandsModule = di_config_8.default; | ||
var di_config_9 = require("./features/mouse-tool/di.config"); | ||
exports.glspMouseToolModule = di_config_9.default; | ||
var di_config_10 = require("./features/request-response/di.config"); | ||
exports.requestResponseModule = di_config_10.default; | ||
var di_config_11 = require("./features/save/di.config"); | ||
exports.saveModule = di_config_11.default; | ||
var di_config_12 = require("./features/select/di.config"); | ||
exports.glspSelectModule = di_config_12.default; | ||
var di_config_13 = require("./features/tool-feedback/di.config"); | ||
exports.toolFeedbackModule = di_config_13.default; | ||
var di_config_14 = require("./features/tool-palette/di.config"); | ||
exports.paletteModule = di_config_14.default; | ||
var di_config_15 = require("./features/validation/di.config"); | ||
exports.validationModule = di_config_15.default; | ||
__export(require("sprotty/lib")); | ||
@@ -54,6 +56,10 @@ __export(require("./base/model/update-model-command")); | ||
__export(require("./base/command-stack")); | ||
__export(require("./base/editor-context")); | ||
__export(require("./features/change-bounds/model")); | ||
__export(require("./features/change-bounds/movement-restrictor")); | ||
__export(require("./features/change-bounds/snap")); | ||
__export(require("./features/context-actions/action-definitions")); | ||
__export(require("./features/context-menu/delete-element-context-menu")); | ||
__export(require("./features/command-palette/server-command-palette-provider")); | ||
__export(require("./features/copy-paste/copy-paste-handler")); | ||
__export(require("./features/edit-label-validation/edit-label-validator")); | ||
@@ -70,3 +76,2 @@ __export(require("./features/execute/execute-command")); | ||
__export(require("./features/rank/model")); | ||
__export(require("./features/reconnect/action-definitions")); | ||
__export(require("./features/reconnect/model")); | ||
@@ -78,3 +83,3 @@ __export(require("./features/request-response/glsp-action-dispatcher")); | ||
__export(require("./features/tool-feedback/creation-tool-feedback")); | ||
__export(require("./features/tool-feedback/cursor-feedback")); | ||
__export(require("./features/tool-feedback/css-feedback")); | ||
__export(require("./features/tool-feedback/edge-edit-tool-feedback")); | ||
@@ -81,0 +86,0 @@ __export(require("./features/tool-feedback/feedback-action-dispatcher")); |
@@ -49,2 +49,3 @@ "use strict"; | ||
var edit_label_validator_1 = require("../features/edit-label-validation/edit-label-validator"); | ||
var copy_paste_actions_1 = require("../features/copy-paste/copy-paste-actions"); | ||
var GLSPWebsocketDiagramServer = /** @class */ (function (_super) { | ||
@@ -102,3 +103,3 @@ __extends(GLSPWebsocketDiagramServer, _super); | ||
registry.register(set_operations_1.OperationKind.RECONNECT_CONNECTION, diagramServer); | ||
registry.register(set_operations_1.OperationKind.REROUTE_CONNECTION, diagramServer); | ||
registry.register(set_operations_1.OperationKind.CHANGE_ROUTING_POINTS, diagramServer); | ||
registry.register(set_operations_1.OperationKind.CREATE_NODE, diagramServer); | ||
@@ -123,2 +124,5 @@ registry.register(set_operations_1.OperationKind.CHANGE_BOUNDS, diagramServer); | ||
registry.register(sprotty_1.ApplyLabelEditAction.KIND, diagramServer); | ||
registry.register(copy_paste_actions_1.RequestClipboardDataAction.KIND, diagramServer); | ||
registry.register(copy_paste_actions_1.PasteOperationAction.KIND, diagramServer); | ||
registry.register(copy_paste_actions_1.CutOperationAction.KIND, diagramServer); | ||
// Register an empty handler for SwitchEditMode, to avoid runtime exceptions. | ||
@@ -125,0 +129,0 @@ // We don't want to support SwitchEditMode, but sprotty still sends some corresponding |
@@ -30,3 +30,4 @@ /******************************************************************************** | ||
IContextMenuProvider: symbol; | ||
ICopyPasteHandler: symbol; | ||
}; | ||
//# sourceMappingURL=types.d.ts.map |
@@ -31,4 +31,5 @@ "use strict"; | ||
IContextMenuProviderRegistry: Symbol.for("IContextMenuProviderRegistry"), | ||
IContextMenuProvider: Symbol.for("IContextMenuProvider") | ||
IContextMenuProvider: Symbol.for("IContextMenuProvider"), | ||
ICopyPasteHandler: Symbol.for("ICopyPasteHandler") | ||
}; | ||
//# sourceMappingURL=types.js.map |
@@ -17,2 +17,3 @@ /******************************************************************************** | ||
import { BoundsAware, Selectable, SModelElement, SRoutableElement, SRoutingHandle } from "sprotty/lib"; | ||
import { ElementAndRoutingPoints } from "src/features/operation/operation-actions"; | ||
export declare function getIndex(element: SModelElement): import("sprotty").SModelIndex<SModelElement>; | ||
@@ -42,2 +43,3 @@ export declare function forEachElement<T>(element: SModelElement, predicate: (element: SModelElement) => element is SModelElement & T, runnable: (element: SModelElement & T) => void): void; | ||
}; | ||
export declare function toElementAndRoutingPoints(element: SRoutableElement): ElementAndRoutingPoints; | ||
//# sourceMappingURL=smodel-util.d.ts.map |
@@ -137,2 +137,9 @@ "use strict"; | ||
exports.toElementAndBounds = toElementAndBounds; | ||
function toElementAndRoutingPoints(element) { | ||
return { | ||
elementId: element.id, | ||
newRoutingPoints: element.routingPoints | ||
}; | ||
} | ||
exports.toElementAndRoutingPoints = toElementAndRoutingPoints; | ||
//# sourceMappingURL=smodel-util.js.map |
{ | ||
"name": "@eclipse-glsp/client", | ||
"version": "0.8.0-next.2db3f72", | ||
"version": "0.8.0-next.32731d7", | ||
"description": "A sprotty-based client for GLSP", | ||
@@ -50,5 +50,2 @@ "license": "(EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0)", | ||
}, | ||
"resolutions": { | ||
"**/sprotty": "0.8.0-next.9533a22" | ||
}, | ||
"scripts": { | ||
@@ -55,0 +52,0 @@ "prepare": "yarn run clean && yarn run build", |
@@ -7,4 +7,4 @@ # Eclipse GLSP - Client [![build-status](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fci.eclipse.org%2Fglsp%2Fjob%2Feclipse-glsp%2Fjob%2Fglsp-client%2Fjob%2Fmaster%2F)](https://ci.eclipse.org/glsp/job/eclipse-glsp/job/glsp-client/job/master) ![build-status-server](https://img.shields.io/jenkins/build?jobUrl=https://ci.eclipse.org/glsp/job/deploy-npm-glsp-client/&label=publish) | ||
For more information on building and running the web-based GLSP diagram client, see the [GLSP umbrella project](https://github.com/eclipse-glsp/glsp) and please visit the [Eclipse GLSP Website](https://www.eclipse.org/glsp). | ||
For more information, please visit the [Eclipse GLSP Umbrella repository](https://github.com/eclipse-glsp/glsp) and the [Eclipse GLSP Website](https://www.eclipse.org/glsp/). If you have questions, contact us on our [spectrum chat](https://spectrum.chat/glsp/) and have a look at our [communication and support options](https://www.eclipse.org/glsp/contact/). | ||
![alt](https://www.eclipse.org/glsp/images/diagramanimated.gif) |
@@ -24,6 +24,6 @@ /******************************************************************************** | ||
import { GLSPCommandStack } from "./command-stack"; | ||
import { EditorContextService } from "./editor-context"; | ||
import { FeedbackAwareUpdateModelCommand, SetModelActionHandler } from "./model/update-model-command"; | ||
import { createToolFactory, GLSPToolManagerActionHandler } from "./tool-manager/tool-manager-action-handler"; | ||
const defaultGLSPModule = new ContainerModule((bind, _unbind, isBound, rebind) => { | ||
@@ -34,2 +34,3 @@ const context = { bind, _unbind, isBound, rebind }; | ||
bind(GLSP_TYPES.IToolFactory).toFactory<Tool>((createToolFactory())); | ||
bind(EditorContextService).toSelf().inSingletonScope(); | ||
@@ -36,0 +37,0 @@ // Model update initialization ------------------------------------ |
@@ -32,4 +32,4 @@ /******************************************************************************** | ||
import { UpdateModelAction, UpdateModelCommand } from "sprotty/lib/features/update/update-model"; | ||
import { IFeedbackActionDispatcher } from "src/features/tool-feedback/feedback-action-dispatcher"; | ||
import { IFeedbackActionDispatcher } from "../../features/tool-feedback/feedback-action-dispatcher"; | ||
import { FeedbackCommand } from "../../features/tool-feedback/model"; | ||
@@ -64,12 +64,14 @@ import { GLSP_TYPES } from "../../types"; | ||
export class FeedbackAwareUpdateModelCommand extends UpdateModelCommand { | ||
protected actionHandlerRegistry?: ActionHandlerRegistry; | ||
constructor(@inject(TYPES.Action) action: UpdateModelAction, | ||
@inject(TYPES.ILogger) protected logger: ILogger, | ||
@inject(GLSP_TYPES.IFeedbackActionDispatcher) @optional() protected readonly feedbackActionDispatcher: IFeedbackActionDispatcher, | ||
@inject(TYPES.ActionHandlerRegistryProvider) protected actionHandlerRegistryProvider: () => Promise<ActionHandlerRegistry>, | ||
@inject(TYPES.ActionHandlerRegistryProvider) actionHandlerRegistryProvider: () => Promise<ActionHandlerRegistry>, | ||
@multiInject(GLSP_TYPES.SModelRootListener) @optional() protected modelRootListeners: SModelRootListener[] = []) { | ||
super(action); | ||
actionHandlerRegistryProvider().then(registry => this.actionHandlerRegistry = registry); | ||
} | ||
protected performUpdate(oldRoot: SModelRoot, newRoot: SModelRoot, context: CommandExecutionContext): CommandReturn { | ||
if (this.feedbackActionDispatcher) { | ||
if (this.feedbackActionDispatcher && this.actionHandlerRegistry) { | ||
// Create a temporary context wich defines the `newRoot` as `root` | ||
@@ -85,10 +87,9 @@ // This way we do not corrupt the redo/undo behavior of the super class | ||
}; | ||
this.actionHandlerRegistryProvider().then(registry => { | ||
const feedbackCommands = this.getFeedbackCommands(registry); | ||
feedbackCommands.forEach(command => command.execute(tempContext)); | ||
}); | ||
const feedbackCommands = this.getFeedbackCommands(this.actionHandlerRegistry); | ||
feedbackCommands.forEach(command => command.execute(tempContext)); | ||
} | ||
this.modelRootListeners.forEach(listener => listener.modelRootChanged(newRoot)); | ||
return super.performUpdate(oldRoot, newRoot, context); | ||
} | ||
@@ -95,0 +96,0 @@ |
@@ -17,274 +17,70 @@ /******************************************************************************** | ||
import { injectable } from "inversify"; | ||
import { | ||
Action, | ||
Bounds, | ||
BoundsAware, | ||
ElementMove, | ||
includes, | ||
isBoundsAware, | ||
isMoveable, | ||
isSelectable, | ||
MoveAction, | ||
Point, | ||
PointToPointLine, | ||
SModelElement | ||
} from "sprotty/lib"; | ||
import { FluentIterable, toArray } from "sprotty/lib/utils/iterable"; | ||
import { Action, BoundsAware, Point, SModelElement, SNode, SParentElement } from "sprotty/lib"; | ||
import { ApplyCursorCSSFeedbackAction, CursorCSS } from "../tool-feedback/cursor-feedback"; | ||
import { isBoundsAwareMoveable } from "./model"; | ||
import { toAbsoluteBounds } from "../../utils/viewpoint-util"; | ||
import { ModifyCSSFeedbackAction } from "../tool-feedback/css-feedback"; | ||
import { isBoundsAwareMoveable, SResizeHandle } from "./model"; | ||
export interface IMovementRestrictor { | ||
attemptMove(element: SModelElement, mousePoint: Point, target: SModelElement, delta: Point, result: Action[]): boolean | ||
validate(newLocation: Point, element: SModelElement): boolean; | ||
cssClasses?: string[]; | ||
} | ||
export function createMovementRestrictionFeedback(element: SModelElement, movementRestrictor: IMovementRestrictor): Action[] { | ||
const result: Action[] = []; | ||
result.push(new ModifyCSSFeedbackAction(element, movementRestrictor.cssClasses)); | ||
if (element instanceof SParentElement) { | ||
element.children.filter(child => child instanceof SResizeHandle).forEach(child => result.push(new ModifyCSSFeedbackAction(child, movementRestrictor.cssClasses))); | ||
} | ||
return result; | ||
} | ||
export function removeMovementRestrictionFeedback(element: SModelElement, movementRestrictor: IMovementRestrictor): Action[] { | ||
const result: Action[] = []; | ||
result.push(new ModifyCSSFeedbackAction(element, undefined, movementRestrictor.cssClasses)); | ||
if (element instanceof SParentElement) { | ||
element.children.filter(child => child instanceof SResizeHandle). | ||
forEach(child => result.push(new ModifyCSSFeedbackAction(child, undefined, movementRestrictor.cssClasses))); | ||
} | ||
return result; | ||
} | ||
@injectable() | ||
export class NoCollisionMovementRestrictor { | ||
hasCollided = false; | ||
/* | ||
* Attempt to perform an element move. Returns true if the move is not restricted anc can be applied successfull and false otherwise | ||
*/ | ||
attemptMove(element: SModelElement, mousePoint: Point, target: SModelElement, delta: Point, result: Action[]): boolean { | ||
export class NoOverlapMovmentRestrictor implements IMovementRestrictor { | ||
validate(newLocation: Point, element: SModelElement): boolean { | ||
if (!isBoundsAwareMoveable(element)) { | ||
return false; | ||
} | ||
let mouseOverElement: boolean = false; | ||
let willOverlap: boolean = false; | ||
// Create ghost element to check possible bounds | ||
// Create ghost element at the newLocation; | ||
const ghostElement = Object.create(element); | ||
ghostElement.bounds = this.getCenteredBoundsToPointer(mousePoint, element.bounds); | ||
// Set type to Ghost to keep tracking it through elements | ||
ghostElement.bounds.x = newLocation.x - element.bounds.width / 2; | ||
ghostElement.bounds.y = newLocation.y - element.bounds.height / 2; | ||
ghostElement.type = "Ghost"; | ||
ghostElement.id = element.id; | ||
// Check collision for gost element (to see when it has passed beyond obstacle) | ||
const collisionTargetsGhost: SModelElement[] = this.getCollisionChain(target, ghostElement, delta, []) | ||
.filter(collidingElement => isSelectable(collidingElement) && !collidingElement.selected); | ||
return !Array.from(element.root.index.all().filter(e => e.id !== ghostElement.id && e !== ghostElement.root && (e instanceof SNode)) | ||
.map(e => e as SModelElement & BoundsAware)).some(e => areOverlapping(e, ghostElement)); | ||
} | ||
// After collision the mouse is back inside the element => change cursor back to default | ||
if (this.hasCollided && includes(element.bounds, mousePoint)) { | ||
mouseOverElement = true; | ||
result.push(new ApplyCursorCSSFeedbackAction(CursorCSS.DEFAULT)); | ||
} | ||
cssClasses = ["movement-not-allowed"]; | ||
} | ||
const selectedElements: FluentIterable<SModelElement> = target.root.index.all() | ||
.filter(selected => isSelectable(selected) && selected.selected); | ||
export function areOverlapping(element1: SModelElement & BoundsAware, element2: SModelElement & BoundsAware) { | ||
const b1 = toAbsoluteBounds(element1); | ||
const b2 = toAbsoluteBounds(element2); | ||
const r1TopLeft: Point = b1; | ||
const r1BottomRight = { x: b1.x + b1.width, y: b1.y + b1.height }; | ||
const r2TopLeft: Point = b2; | ||
const r2BottomRight = { x: b2.x + b2.width, y: b2.y + b2.height }; | ||
// If the ghost element has moved beyond the obstacle move the actual element there aswell | ||
// But only if a single element is selected (multi-selection jumps are not supported) | ||
if (this.hasCollided && collisionTargetsGhost.length === 0 && toArray(selectedElements).length === 1) { | ||
mouseOverElement = true; | ||
result.push(new ApplyCursorCSSFeedbackAction(CursorCSS.DEFAULT)); | ||
// If one rectangle is on left side of other | ||
if (r1TopLeft.x > r2BottomRight.x || r2TopLeft.x > r1BottomRight.x) | ||
return false; | ||
if (element.id === ghostElement.id) { | ||
element.bounds = ghostElement.bounds; | ||
} | ||
} | ||
// Get only the valid, non-slected collision targets to avoid in-selection collisions | ||
const collisionTargets: SModelElement[] = this.getCollisionChain(target, element, delta, []) | ||
.filter(collidingElement => isSelectable(collidingElement) && !collidingElement.selected); | ||
if (collisionTargets.length > 0) { | ||
collisionTargets.forEach(collisionTarget => { | ||
if (isBoundsAware(collisionTarget)) { | ||
// Only snap on first collision to avoid erratic jumps | ||
if (!this.hasCollided) { | ||
const snappedBounds = this.getSnappedBounds(element, collisionTarget); | ||
const snapMoves: ElementMove[] = []; | ||
snapMoves.push({ | ||
elementId: element.id, | ||
fromPosition: { | ||
x: element.position.x, | ||
y: element.position.y | ||
}, | ||
toPosition: { | ||
x: snappedBounds.x, | ||
y: snappedBounds.y | ||
} | ||
}); | ||
result.push(new MoveAction(snapMoves, false)); | ||
} | ||
willOverlap = true; | ||
this.hasCollided = true; | ||
result.push(new ApplyCursorCSSFeedbackAction(CursorCSS.OVERLAP_FORBIDDEN)); | ||
} | ||
}); | ||
} | ||
if ((!willOverlap && !this.hasCollided) || | ||
(this.hasCollided && !willOverlap && mouseOverElement)) { | ||
this.hasCollided = false; | ||
return true; | ||
} | ||
// If one rectangle is above other | ||
if (r1BottomRight.y < r2TopLeft.y || r2BottomRight.y < r1TopLeft.y) | ||
return false; | ||
} | ||
/** | ||
* Used to return the collision target(s) or the collision chain in case of multiple selected elements | ||
*/ | ||
getCollisionChain(target: SModelElement, element: SModelElement, delta: Point, collisionChain: SModelElement[]): SModelElement[] { | ||
if (isBoundsAwareMoveable(element)) { | ||
target.root.index.all() | ||
.filter(candidate => isSelectable(candidate) && element.id !== candidate.id && collisionChain.indexOf(candidate) < 0) | ||
.forEach(candidate => { | ||
if (isMoveable(element) && isMoveable(candidate)) { | ||
if (isBoundsAware(element) && isBoundsAware(candidate)) { | ||
const futureBounds: Bounds = { | ||
x: element.position.x + delta.x, | ||
y: element.position.y + delta.y, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
if (isOverlappingBounds(futureBounds, candidate.bounds) && (!isOverlappingBounds(element.bounds, candidate.bounds) || element.type === "Ghost")) { | ||
collisionChain.push(candidate); | ||
if (isSelectable(candidate) && candidate.selected) { | ||
// Check what the selected candidate will collide with and add it to the chain | ||
collisionChain.push.apply(collisionChain, this.getCollisionChain(target, candidate, delta, collisionChain)); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
} | ||
return collisionChain; | ||
} | ||
return true; | ||
/** | ||
* Returns bounds centered around the point | ||
*/ | ||
getCenteredBoundsToPointer(mousePoint: Point, bounds: Bounds): Bounds { | ||
const middleX = mousePoint.x - bounds.width / 2; | ||
const middleY = mousePoint.y - bounds.height / 2; | ||
const shiftedBounds: Bounds = { x: middleX, y: middleY, width: bounds.width, height: bounds.height }; | ||
return shiftedBounds; | ||
} | ||
// Remove this and use the one from the improved routing branch | ||
getDistanceBetweenParallelLines(p1: Point, p2: Point, secondLine: PointToPointLine): Number { | ||
const numerator: number = Math.abs((secondLine.a * p1.x) + (secondLine.b * p1.y) - secondLine.c); | ||
const denominator: number = Math.sqrt(Math.pow(secondLine.a, 2) + Math.pow(secondLine.b, 2)); | ||
return numerator / denominator; | ||
} | ||
/** | ||
* Snaps the element to the target in case of a collision | ||
*/ | ||
getSnappedBounds(element: SModelElement & BoundsAware, target: SModelElement & BoundsAware): Bounds { | ||
let snappedBounds = element.bounds; | ||
// Build corner points | ||
const elementTopLeft = { | ||
x: element.bounds.x, | ||
y: element.bounds.y | ||
}; | ||
const elementTopRight = { | ||
x: element.bounds.x + element.bounds.width, | ||
y: element.bounds.y | ||
}; | ||
const elementBottomLeft = { | ||
x: element.bounds.x, | ||
y: element.bounds.y + element.bounds.height | ||
}; | ||
const elementBottomRight = { | ||
x: element.bounds.x + element.bounds.width, | ||
y: element.bounds.y + element.bounds.height | ||
}; | ||
const targetTopLeft = { | ||
x: target.bounds.x, | ||
y: target.bounds.y | ||
}; | ||
const targetTopRight = { | ||
x: target.bounds.x + target.bounds.width, | ||
y: target.bounds.y | ||
}; | ||
const targetBottomLeft = { | ||
x: target.bounds.x, | ||
y: target.bounds.y + target.bounds.height | ||
}; | ||
const targetBottomRight = { | ||
x: target.bounds.x + target.bounds.width, | ||
y: target.bounds.y + target.bounds.height | ||
}; | ||
// Build lines | ||
const targetTopLine = new PointToPointLine(targetTopLeft, targetTopRight); | ||
const targetBottomLine = new PointToPointLine(targetBottomLeft, targetBottomRight); | ||
const targetLeftLine = new PointToPointLine(targetTopLeft, targetBottomLeft); | ||
const targetRightLine = new PointToPointLine(targetTopRight, targetBottomRight); | ||
// Compute distances | ||
const distanceTop = this.getDistanceBetweenParallelLines(elementBottomLeft, elementBottomRight, targetTopLine); | ||
const distanceBottom = this.getDistanceBetweenParallelLines(elementTopLeft, elementTopRight, targetBottomLine); | ||
const distanceLeft = this.getDistanceBetweenParallelLines(elementTopLeft, elementBottomLeft, targetRightLine); | ||
const distanceRight = this.getDistanceBetweenParallelLines(elementTopRight, elementBottomRight, targetLeftLine); | ||
const minimumCandidates: number[] = []; | ||
// Overlap on the horizontal lines | ||
if (isOverlapping1Dimension(element.bounds.x, element.bounds.width, target.bounds.x, target.bounds.width)) { | ||
minimumCandidates.push(distanceTop.valueOf()); | ||
minimumCandidates.push(distanceBottom.valueOf()); | ||
} | ||
// Overlap on the horizontal lines | ||
if (isOverlapping1Dimension(element.bounds.y, element.bounds.height, target.bounds.y, target.bounds.height)) { | ||
minimumCandidates.push(distanceLeft.valueOf()); | ||
minimumCandidates.push(distanceRight.valueOf()); | ||
} | ||
// Get minimum distance and then snap accordingly | ||
minimumCandidates.sort((a, b) => a - b); | ||
const minimumDistance = minimumCandidates[0]; | ||
if (minimumDistance === distanceTop) { | ||
snappedBounds = { | ||
x: element.bounds.x, | ||
y: target.bounds.y - 1 - element.bounds.height, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
if (minimumDistance === distanceBottom) { | ||
snappedBounds = { | ||
x: element.bounds.x, | ||
y: target.bounds.y + target.bounds.height + 1, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
if (minimumDistance === distanceLeft) { | ||
snappedBounds = { | ||
x: target.bounds.x + target.bounds.width + 1, | ||
y: element.bounds.y, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
if (minimumDistance === distanceRight) { | ||
snappedBounds = { | ||
x: target.bounds.x - 1 - element.bounds.width, | ||
y: element.bounds.y, | ||
width: element.bounds.width, | ||
height: element.bounds.height | ||
}; | ||
} | ||
return snappedBounds; | ||
} | ||
} | ||
/** | ||
* Used to check if 1D boxes (lines) overlap | ||
*/ | ||
export function isOverlapping1Dimension(x1: number, width1: number, x2: number, width2: number): boolean { | ||
return x1 + width1 >= x2 && x2 + width2 >= x1; | ||
} | ||
/** | ||
* Used to check if 2 bounds are overlapping | ||
*/ | ||
export function isOverlappingBounds(bounds1: Bounds, bounds2: Bounds): boolean { | ||
return isOverlapping1Dimension(bounds1.x, bounds1.width, bounds2.x, bounds2.width) && | ||
isOverlapping1Dimension(bounds1.y, bounds1.height, bounds2.y, bounds2.height); | ||
} | ||
@@ -17,4 +17,5 @@ /******************************************************************************** | ||
import { inject, injectable } from "inversify"; | ||
import { Action, ICommandPaletteActionProvider, isSelected, LabeledAction, Point, SModelElement, TYPES } from "sprotty/lib"; | ||
import { Action, ICommandPaletteActionProvider, LabeledAction, Point, SModelElement, TYPES } from "sprotty/lib"; | ||
import { EditorContextService } from "../../base/editor-context"; | ||
import { ContextActions, isSetContextActionsAction, RequestContextActions } from "../context-actions/action-definitions"; | ||
@@ -32,11 +33,11 @@ import { GLSPActionDispatcher } from "../request-response/glsp-action-dispatcher"; | ||
constructor(@inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher) { } | ||
@inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher; | ||
@inject(EditorContextService) protected editorContext: EditorContextService; | ||
getActions(root: Readonly<SModelElement>, text: string, lastMousePosition?: Point, index?: number): Promise<LabeledAction[]> { | ||
const selectedElementIds = Array.from(root.index.all().filter(isSelected).map(e => e.id)); | ||
const requestAction = new RequestContextActions(selectedElementIds, lastMousePosition, { | ||
const requestAction = new RequestContextActions(this.editorContext.get({ | ||
[ContextActions.UI_CONTROL_KEY]: ServerCommandPalette.KEY, | ||
[ServerCommandPalette.TEXT]: text, | ||
[ServerCommandPalette.INDEX]: index ? index : 0 | ||
}); | ||
})); | ||
return this.actionDispatcher.requestUntil(requestAction).then(response => this.getPaletteActionsFromResponse(response)); | ||
@@ -43,0 +44,0 @@ } |
@@ -16,4 +16,6 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Action, generateRequestId, LabeledAction, Point, RequestAction, ResponseAction } from "sprotty/lib"; | ||
import { Action, generateRequestId, LabeledAction, RequestAction, ResponseAction } from "sprotty/lib"; | ||
import { EditorContext } from "../../base/editor-context"; | ||
export namespace ContextActions { | ||
@@ -26,6 +28,3 @@ export const UI_CONTROL_KEY = "ui-control"; | ||
kind = RequestContextActions.KIND; | ||
constructor( | ||
public readonly selectedElementIds: string[] = [], | ||
public readonly lastMousePosition?: Point, | ||
public readonly args?: { [key: string]: string | number | boolean }, | ||
constructor(public readonly editorContext: EditorContext, | ||
public readonly requestId: string = generateRequestId()) { } | ||
@@ -32,0 +31,0 @@ } |
@@ -17,13 +17,5 @@ /******************************************************************************** | ||
import { inject, injectable } from "inversify"; | ||
import { | ||
Action, | ||
IContextMenuItemProvider, | ||
isSelected, | ||
LabeledAction, | ||
Point, | ||
SModelElement, | ||
subtract, | ||
TYPES | ||
} from "sprotty/lib"; | ||
import { Action, IContextMenuItemProvider, isSelected, LabeledAction, Point, SModelElement, TYPES } from "sprotty/lib"; | ||
import { EditorContextService } from "../../base/editor-context"; | ||
import { ContextActions, isSetContextActionsAction, RequestContextActions } from "../context-actions/action-definitions"; | ||
@@ -39,8 +31,9 @@ import { GLSPActionDispatcher } from "../request-response/glsp-action-dispatcher"; | ||
constructor(@inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher) { } | ||
@inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher; | ||
@inject(EditorContextService) protected editorContext: EditorContextService; | ||
getItems(root: Readonly<SModelElement>, lastMousePosition?: Point): Promise<LabeledAction[]> { | ||
const selectedElementIds = Array.from(root.index.all().filter(isSelected).map(e => e.id)); | ||
const localPosition = lastMousePosition ? root.root.parentToLocal(subtract(lastMousePosition, root.root.canvasBounds)) : undefined; | ||
const requestAction = new RequestContextActions(selectedElementIds, localPosition, { [ContextActions.UI_CONTROL_KEY]: ServerContextMenu.KEY }); | ||
const context = this.editorContext.getWithSelection(selectedElementIds, { [ContextActions.UI_CONTROL_KEY]: ServerContextMenu.KEY }); | ||
const requestAction = new RequestContextActions(context); | ||
return this.actionDispatcher.requestUntil(requestAction).then(response => this.getContextActionsFromResponse(response)); | ||
@@ -47,0 +40,0 @@ } |
@@ -56,2 +56,15 @@ /******************************************************************************** | ||
export class ReconnectConnectionOperationAction implements Action { | ||
readonly kind = OperationKind.RECONNECT_CONNECTION; | ||
constructor(public readonly connectionElementId: string, | ||
public readonly sourceElementId: string, | ||
public readonly targetElementId: string) { } | ||
} | ||
export class ChangeRoutingPointsOperation implements Action { | ||
readonly kind = OperationKind.CHANGE_ROUTING_POINTS; | ||
constructor(public newRoutingPoints: ElementAndRoutingPoints[]) { } | ||
} | ||
export class GenericOperationAction implements Action { | ||
@@ -65,1 +78,5 @@ readonly kind = OperationKind.GENERIC; | ||
export interface ElementAndRoutingPoints { | ||
elementId: string | ||
newRoutingPoints?: Point[]; | ||
} |
@@ -22,5 +22,5 @@ /******************************************************************************** | ||
export const RECONNECT_CONNECTION = "reconnectConnection"; | ||
export const REROUTE_CONNECTION = "rerouteConnection"; | ||
export const DELETE_ELEMENT = "delete"; | ||
export const CHANGE_BOUNDS = "changeBoundsOperation"; | ||
export const CHANGE_ROUTING_POINTS = "changeRoutingPoints"; | ||
export const DELETE_ELEMENT = "deleteElement"; | ||
export const CHANGE_BOUNDS = "changeBounds"; | ||
export const CHANGE_CONTAINER = "changeContainer"; | ||
@@ -27,0 +27,0 @@ export const GENERIC = "generic"; |
@@ -36,11 +36,5 @@ /******************************************************************************** | ||
import { isNotUndefined } from "../../utils/smodel-util"; | ||
import { getAbsolutePosition } from "../../utils/viewpoint-util"; | ||
import { | ||
addResizeHandles, | ||
isBoundsAwareMoveable, | ||
isResizable, | ||
removeResizeHandles, | ||
SResizeHandle | ||
} from "../change-bounds/model"; | ||
import { IMovementRestrictor } from "../change-bounds/movement-restrictor"; | ||
import { addResizeHandles, isResizable, removeResizeHandles, SResizeHandle } from "../change-bounds/model"; | ||
import { createMovementRestrictionFeedback, removeMovementRestrictionFeedback } from "../change-bounds/movement-restrictor"; | ||
import { ChangeBoundsTool } from "../tools/change-bounds-tool"; | ||
import { FeedbackCommand } from "./model"; | ||
@@ -60,5 +54,8 @@ | ||
export class ShowChangeBoundsToolResizeFeedbackCommand extends FeedbackCommand { | ||
static readonly KIND = 'showChangeBoundsToolResizeFeedback'; | ||
static readonly KIND = "showChangeBoundsToolResizeFeedback"; | ||
constructor(@inject(TYPES.Action) protected action: ShowChangeBoundsToolResizeFeedbackAction) { | ||
constructor( | ||
@inject(TYPES.Action) | ||
protected action: ShowChangeBoundsToolResizeFeedbackAction | ||
) { | ||
super(); | ||
@@ -69,3 +66,6 @@ } | ||
const index = context.root.index; | ||
index.all().filter(isResizable).forEach(removeResizeHandles); | ||
index | ||
.all() | ||
.filter(isResizable) | ||
.forEach(removeResizeHandles); | ||
@@ -84,5 +84,8 @@ if (isNotUndefined(this.action.elementId)) { | ||
export class HideChangeBoundsToolResizeFeedbackCommand extends FeedbackCommand { | ||
static readonly KIND = 'hideChangeBoundsToolResizeFeedback'; | ||
static readonly KIND = "hideChangeBoundsToolResizeFeedback"; | ||
constructor(@inject(TYPES.Action) protected action: HideChangeBoundsToolResizeFeedbackAction) { | ||
constructor( | ||
@inject(TYPES.Action) | ||
protected action: HideChangeBoundsToolResizeFeedbackAction | ||
) { | ||
super(); | ||
@@ -93,3 +96,6 @@ } | ||
const index = context.root.index; | ||
index.all().filter(isResizable).forEach(removeResizeHandles); | ||
index | ||
.all() | ||
.filter(isResizable) | ||
.forEach(removeResizeHandles); | ||
return context.root; | ||
@@ -108,4 +114,8 @@ } | ||
hasDragged = false; | ||
lastDragPosition: Point | undefined; | ||
constructor(protected movementRestrictor?: IMovementRestrictor) { super(); } | ||
startDragPosition: Point | undefined; | ||
elementId2startPos = new Map<string, Point>(); | ||
constructor(protected tool: ChangeBoundsTool) { | ||
super(); | ||
} | ||
mouseDown(target: SModelElement, event: MouseEvent): Action[] { | ||
@@ -115,5 +125,5 @@ if (event.button === 0 && !(target instanceof SResizeHandle)) { | ||
if (moveable !== undefined) { | ||
this.lastDragPosition = { x: event.pageX, y: event.pageY }; | ||
this.startDragPosition = { x: event.pageX, y: event.pageY }; | ||
} else { | ||
this.lastDragPosition = undefined; | ||
this.startDragPosition = undefined; | ||
} | ||
@@ -127,44 +137,87 @@ this.hasDragged = false; | ||
const result: Action[] = []; | ||
if (event.buttons === 0) | ||
this.mouseUp(target, event); | ||
else if (this.lastDragPosition) { | ||
const viewport = findParentByFeature(target, isViewport); | ||
if (event.buttons === 0) this.mouseUp(target, event); | ||
else if (this.startDragPosition) { | ||
if (this.elementId2startPos.size === 0) { | ||
this.collectStartPositions(target.root); | ||
} | ||
this.hasDragged = true; | ||
const zoom = viewport ? viewport.zoom : 1; | ||
const mousePoint: Point = getAbsolutePosition(target, event); | ||
const dx = (event.pageX - this.lastDragPosition.x) / zoom; | ||
const dy = (event.pageY - this.lastDragPosition.y) / zoom; | ||
const nodeMoves: ElementMove[] = []; | ||
let isValidMove: boolean = true; | ||
const moveAction = this.getElementMoves(target, event, false); | ||
if (moveAction) result.push(moveAction); | ||
} | ||
return result; | ||
} | ||
target.root.index.all() | ||
.filter(element => isSelectable(element) && element.selected) | ||
.forEach(element => { | ||
if (isBoundsAwareMoveable(element)) { | ||
// If a movement restrictor is bound attemt a non restricted move | ||
if (this.movementRestrictor) { | ||
isValidMove = this.movementRestrictor.attemptMove(element, mousePoint, target, { x: dx, y: dy }, result); | ||
} | ||
} | ||
if (isMoveable(element) && isValidMove) { | ||
nodeMoves.push({ | ||
elementId: element.id, | ||
fromPosition: { | ||
x: element.position.x, | ||
y: element.position.y | ||
}, | ||
toPosition: { | ||
x: element.position.x + dx, | ||
y: element.position.y + dy | ||
} | ||
}); | ||
} | ||
}); | ||
this.lastDragPosition = { x: event.pageX, y: event.pageY }; | ||
if (nodeMoves.length > 0 && isValidMove) { | ||
result.push(new MoveAction(nodeMoves, false)); | ||
protected collectStartPositions(root: SModelRoot) { | ||
root.index | ||
.all() | ||
.filter(element => isSelectable(element) && element.selected) | ||
.forEach(element => { | ||
if (isMoveable(element)) { | ||
this.elementId2startPos.set(element.id, element.position); | ||
} | ||
}); | ||
} | ||
protected getElementMoves(target: SModelElement, event: MouseEvent, isFinished: boolean): MoveAction | undefined { | ||
if (!this.startDragPosition) return undefined; | ||
const elementMoves: ElementMove[] = []; | ||
const viewport = findParentByFeature(target, isViewport); | ||
const zoom = viewport ? viewport.zoom : 1; | ||
const delta = { | ||
x: (event.pageX - this.startDragPosition.x) / zoom, | ||
y: (event.pageY - this.startDragPosition.y) / zoom | ||
}; | ||
this.elementId2startPos.forEach((startPosition, elementId) => { | ||
const element = target.root.index.getById(elementId); | ||
if (element) { | ||
let toPosition = this.snap( | ||
{ | ||
x: startPosition.x + delta.x, | ||
y: startPosition.y + delta.y | ||
}, | ||
element, | ||
!event.shiftKey | ||
); | ||
if (isMoveable(element)) { | ||
toPosition = this.validateMove(startPosition, toPosition, element, isFinished); | ||
elementMoves.push({ | ||
elementId: element.id, | ||
fromPosition: { | ||
x: element.position.x, | ||
y: element.position.y | ||
}, | ||
toPosition | ||
}); | ||
} | ||
} | ||
}); | ||
if (elementMoves.length > 0) | ||
return new MoveAction(elementMoves, false, isFinished); | ||
else return undefined; | ||
} | ||
protected validateMove(startPostion: Point, toPosition: Point, element: SModelElement, isFinished: boolean) { | ||
let newPosition = toPosition; | ||
if (this.tool.movementRestrictor) { | ||
const valid = this.tool.movementRestrictor.validate(toPosition, element); | ||
let actions; | ||
if (!valid) { | ||
actions = createMovementRestrictionFeedback(element, this.tool.movementRestrictor); | ||
if (isFinished) { | ||
newPosition = startPostion; | ||
} | ||
} else { | ||
actions = removeMovementRestrictionFeedback(element, this.tool.movementRestrictor); | ||
} | ||
this.tool.dispatchFeedback(this, actions); | ||
} | ||
return result; | ||
return newPosition; | ||
} | ||
protected snap(position: Point, element: SModelElement, isSnap: boolean): Point { | ||
if (isSnap && this.tool.snapper) return this.tool.snapper.snap(position, element); | ||
else return position; | ||
} | ||
@@ -178,5 +231,17 @@ mouseEnter(target: SModelElement, event: MouseEvent): Action[] { | ||
mouseUp(target: SModelElement, event: MouseEvent): Action[] { | ||
const result: Action[] = []; | ||
if (this.startDragPosition) { | ||
const moveAction = this.getElementMoves(target, event, true); | ||
if (moveAction) { | ||
result.push(moveAction); | ||
} | ||
if (this.tool.movementRestrictor) { | ||
result.push(...removeMovementRestrictionFeedback(target, this.tool.movementRestrictor)); | ||
} | ||
} | ||
this.hasDragged = false; | ||
this.lastDragPosition = undefined; | ||
return []; | ||
this.startDragPosition = undefined; | ||
this.elementId2startPos.clear(); | ||
return result; | ||
} | ||
@@ -187,3 +252,2 @@ | ||
} | ||
} |
@@ -145,3 +145,3 @@ /******************************************************************************** | ||
const feedbackEdgeSchema = <SEdgeSchema>{ | ||
type: 'edge', | ||
type: elementTypeId, | ||
id: feedbackEdgeId(root), | ||
@@ -148,0 +148,0 @@ sourceId: source.id, |
@@ -26,3 +26,3 @@ /******************************************************************************** | ||
import { DrawFeedbackEdgeCommand, FeedbackEdgeEnd, RemoveFeedbackEdgeCommand } from "./creation-tool-feedback"; | ||
import { ApplyCursorCSSFeedbackActionCommand } from "./cursor-feedback"; | ||
import { ModifyCssFeedbackCommand } from "./css-feedback"; | ||
import { | ||
@@ -40,4 +40,5 @@ DrawFeedbackEdgeSourceCommand, | ||
configureCommand({ bind, isBound }, ModifyCssFeedbackCommand); | ||
// create node and edge tool feedback | ||
configureCommand({ bind, isBound }, ApplyCursorCSSFeedbackActionCommand); | ||
configureCommand({ bind, isBound }, DrawFeedbackEdgeCommand); | ||
@@ -44,0 +45,0 @@ configureCommand({ bind, isBound }, RemoveFeedbackEdgeCommand); |
@@ -19,6 +19,9 @@ /******************************************************************************** | ||
Action, | ||
Bounds, | ||
BoundsAware, | ||
Dimension, | ||
EdgeRouterRegistry, | ||
ElementAndBounds, | ||
findParentByFeature, | ||
ISnapper, | ||
isSelected, | ||
@@ -30,2 +33,3 @@ isViewport, | ||
Point, | ||
SConnectableElement, | ||
SetBoundsAction, | ||
@@ -35,11 +39,25 @@ SModelElement, | ||
SParentElement, | ||
Tool | ||
Tool, | ||
TYPES | ||
} from "sprotty/lib"; | ||
import { GLSP_TYPES } from "../../types"; | ||
import { forEachElement, isNonRoutableSelectedMovableBoundsAware, toElementAndBounds } from "../../utils/smodel-util"; | ||
import { isBoundsAwareMoveable, isResizable, ResizeHandleLocation, SResizeHandle } from "../change-bounds/model"; | ||
import { IMovementRestrictor } from "../change-bounds/movement-restrictor"; | ||
import { | ||
forEachElement, | ||
isNonRoutableSelectedMovableBoundsAware, | ||
toElementAndBounds, | ||
toElementAndRoutingPoints | ||
} from "../../utils/smodel-util"; | ||
import { isBoundsAwareMoveable, isResizable, Resizable, ResizeHandleLocation, SResizeHandle } from "../change-bounds/model"; | ||
import { | ||
createMovementRestrictionFeedback, | ||
IMovementRestrictor, | ||
removeMovementRestrictionFeedback | ||
} from "../change-bounds/movement-restrictor"; | ||
import { IMouseTool } from "../mouse-tool/mouse-tool"; | ||
import { ChangeBoundsOperationAction } from "../operation/operation-actions"; | ||
import { | ||
ChangeBoundsOperationAction, | ||
ChangeRoutingPointsOperation, | ||
ElementAndRoutingPoints | ||
} from "../operation/operation-actions"; | ||
import { SelectionListener, SelectionService } from "../select/selection-service"; | ||
@@ -51,3 +69,4 @@ import { | ||
} from "../tool-feedback/change-bounds-tool-feedback"; | ||
import { IFeedbackActionDispatcher } from "../tool-feedback/feedback-action-dispatcher"; | ||
import { IFeedbackActionDispatcher, IFeedbackEmitter } from "../tool-feedback/feedback-action-dispatcher"; | ||
import { DragAwareMouseListener } from "./drag-aware-mouse-listener"; | ||
@@ -79,3 +98,5 @@ /** | ||
@inject(GLSP_TYPES.IFeedbackActionDispatcher) protected feedbackDispatcher: IFeedbackActionDispatcher, | ||
@inject(GLSP_TYPES.IMovementRestrictor) @optional() protected movementRestrictor?: IMovementRestrictor) { } | ||
@inject(EdgeRouterRegistry) @optional() readonly edgeRouterRegistry?: EdgeRouterRegistry, | ||
@inject(TYPES.ISnapper) @optional() readonly snapper?: ISnapper, | ||
@inject(GLSP_TYPES.IMovementRestrictor) @optional() readonly movementRestrictor?: IMovementRestrictor) { } | ||
@@ -97,3 +118,3 @@ enable() { | ||
protected createMoveMouseListener(): MouseListener { | ||
return new FeedbackMoveMouseListener(this.movementRestrictor); | ||
return new FeedbackMoveMouseListener(this); | ||
} | ||
@@ -109,14 +130,17 @@ | ||
this.mouseTool.deregister(this.feedbackMoveMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new HideChangeBoundsToolResizeFeedbackAction]); | ||
this.feedbackDispatcher.deregisterFeedback(this.feedbackMoveMouseListener, []); | ||
this.feedbackDispatcher.deregisterFeedback(this.changeBoundsListener, [new HideChangeBoundsToolResizeFeedbackAction]); | ||
} | ||
dispatchFeedback(actions: Action[]) { | ||
this.feedbackDispatcher.registerFeedback(this, actions); | ||
dispatchFeedback(feedbackEmmmiter: IFeedbackEmitter, actions: Action[]) { | ||
this.feedbackDispatcher.registerFeedback(feedbackEmmmiter, actions); | ||
} | ||
} | ||
export class ChangeBoundsListener extends MouseListener implements SelectionListener { | ||
export class ChangeBoundsListener extends DragAwareMouseListener implements SelectionListener { | ||
// members for calculating the correct position change | ||
protected lastDragPosition?: Point; | ||
protected positionDelta: Point = { x: 0, y: 0 }; | ||
protected initialPositon: Point | undefined = undefined; | ||
protected initialBounds: Bounds | undefined; | ||
@@ -132,2 +156,3 @@ // members for resize mode | ||
mouseDown(target: SModelElement, event: MouseEvent): Action[] { | ||
super.mouseDown(target, event); | ||
if (event.button !== 0) { | ||
@@ -151,3 +176,4 @@ return []; | ||
mouseMove(target: SModelElement, event: MouseEvent): Action[] { | ||
if (this.updatePosition(target, event)) { | ||
super.mouseMove(target, event); | ||
if (this.updatePosition(target, event) && this.activeResizeHandle) { | ||
// rely on the FeedbackMoveMouseListener to update the element bounds of selected elements | ||
@@ -160,3 +186,3 @@ // consider resize handles ourselves | ||
mouseUp(target: SModelElement, event: MouseEvent): Action[] { | ||
draggingMouseUp(target: SModelElement, event: MouseEvent): Action[] { | ||
if (this.lastDragPosition === undefined) { | ||
@@ -177,7 +203,18 @@ this.resetPosition(); | ||
const newBounds: ElementAndBounds[] = []; | ||
forEachElement(target, isNonRoutableSelectedMovableBoundsAware, element => | ||
this.createElementAndBounds(element).forEach(bounds => newBounds.push(bounds))); | ||
const newRoutingPoints: ElementAndRoutingPoints[] = []; | ||
forEachElement(target, isNonRoutableSelectedMovableBoundsAware, element => { | ||
this.createElementAndBounds(element).forEach(bounds => newBounds.push(bounds)); | ||
// If client routing is enabled -> delegate routingpoints of connected edges to server | ||
if (this.tool.edgeRouterRegistry && element instanceof SConnectableElement) { | ||
element.incomingEdges.map(toElementAndRoutingPoints).forEach(ear => newRoutingPoints.push(ear)); | ||
element.outgoingEdges.map(toElementAndRoutingPoints).forEach(ear => newRoutingPoints.push(ear)); | ||
} | ||
}); | ||
if (newBounds.length > 0) { | ||
actions.push(new ChangeBoundsOperationAction(newBounds)); | ||
} | ||
if (newRoutingPoints.length > 0) { | ||
actions.push(new ChangeRoutingPointsOperation(newRoutingPoints)); | ||
} | ||
} | ||
@@ -212,3 +249,3 @@ this.resetPosition(); | ||
this.activeResizeElementId = moveableElement.id; | ||
this.tool.dispatchFeedback([new ShowChangeBoundsToolResizeFeedbackAction(this.activeResizeElementId)]); | ||
this.tool.dispatchFeedback(this, [new ShowChangeBoundsToolResizeFeedbackAction(this.activeResizeElementId)]); | ||
return true; | ||
@@ -224,3 +261,9 @@ } | ||
protected initPosition(event: MouseEvent) { | ||
this.initialPositon = { x: event.pageX, y: event.pageY }; | ||
this.lastDragPosition = { x: event.pageX, y: event.pageY }; | ||
if (this.activeResizeHandle) { | ||
const resizeElement = findParentByFeature(this.activeResizeHandle, isResizable); | ||
this.initialBounds = { x: resizeElement!.bounds.x, y: resizeElement!.bounds.y, width: resizeElement!.bounds.width, height: resizeElement!.bounds.height }; | ||
} | ||
} | ||
@@ -243,3 +286,3 @@ | ||
protected reset() { | ||
this.tool.dispatchFeedback([new HideChangeBoundsToolResizeFeedbackAction()]); | ||
this.tool.dispatchFeedback(this, [new HideChangeBoundsToolResizeFeedbackAction()]); | ||
this.resetPosition(); | ||
@@ -251,2 +294,3 @@ } | ||
this.lastDragPosition = undefined; | ||
this.initialPositon = undefined; | ||
this.positionDelta = { x: 0, y: 0 }; | ||
@@ -260,3 +304,2 @@ } | ||
const actions: Action[] = []; | ||
const resizeElement = findParentByFeature(this.activeResizeHandle, isResizable); | ||
@@ -266,41 +309,56 @@ if (this.isActiveResizeElement(resizeElement)) { | ||
case ResizeHandleLocation.TopLeft: | ||
this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x + this.positionDelta.x, | ||
resizeElement.bounds.y + this.positionDelta.y, | ||
resizeElement.bounds.width - this.positionDelta.x, | ||
resizeElement.bounds.height - this.positionDelta.y) | ||
.forEach(action => actions.push(action)); | ||
break; | ||
return this.handleTopLeftResize(resizeElement); | ||
case ResizeHandleLocation.TopRight: | ||
this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x, | ||
resizeElement.bounds.y + this.positionDelta.y, | ||
resizeElement.bounds.width + this.positionDelta.x, | ||
resizeElement.bounds.height - this.positionDelta.y) | ||
.forEach(action => actions.push(action)); | ||
break; | ||
return this.handleTopRightResize(resizeElement); | ||
case ResizeHandleLocation.BottomLeft: | ||
this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x + this.positionDelta.x, | ||
resizeElement.bounds.y, | ||
resizeElement.bounds.width - this.positionDelta.x, | ||
resizeElement.bounds.height + this.positionDelta.y) | ||
.forEach(action => actions.push(action)); | ||
break; | ||
return this.handleBottomLeftResize(resizeElement); | ||
case ResizeHandleLocation.BottomRight: | ||
this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x, | ||
resizeElement.bounds.y, | ||
resizeElement.bounds.width + this.positionDelta.x, | ||
resizeElement.bounds.height + this.positionDelta.y) | ||
.forEach(action => actions.push(action)); | ||
break; | ||
return this.handleBottomRightResize(resizeElement); | ||
} | ||
} | ||
return actions; | ||
return []; | ||
} | ||
protected handleTopLeftResize(resizeElement: SParentElement & Resizable): Action[] { | ||
return this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x + this.positionDelta.x, | ||
resizeElement.bounds.y + this.positionDelta.y, | ||
resizeElement.bounds.width - this.positionDelta.x, | ||
resizeElement.bounds.height - this.positionDelta.y); | ||
} | ||
protected handleTopRightResize(resizeElement: SParentElement & Resizable): Action[] { | ||
return this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x, | ||
resizeElement.bounds.y + this.positionDelta.y, | ||
resizeElement.bounds.width + this.positionDelta.x, | ||
resizeElement.bounds.height - this.positionDelta.y); | ||
} | ||
protected handleBottomLeftResize(resizeElement: SParentElement & Resizable): Action[] { | ||
return this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x + this.positionDelta.x, | ||
resizeElement.bounds.y, | ||
resizeElement.bounds.width - this.positionDelta.x, | ||
resizeElement.bounds.height + this.positionDelta.y); | ||
} | ||
protected handleBottomRightResize(resizeElement: SParentElement & Resizable): Action[] { | ||
return this.createSetBoundsAction(resizeElement, | ||
resizeElement.bounds.x, | ||
resizeElement.bounds.y, | ||
resizeElement.bounds.width + this.positionDelta.x, | ||
resizeElement.bounds.height + this.positionDelta.y); | ||
} | ||
protected createChangeBoundsAction(element: SModelElement & BoundsAware): Action[] { | ||
if (this.isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [new ChangeBoundsOperationAction([toElementAndBounds(element)])]; | ||
} else if (this.initialBounds) { | ||
const actions: Action[] = []; | ||
if (this.tool.movementRestrictor) { | ||
actions.push(...removeMovementRestrictionFeedback(element, this.tool.movementRestrictor)); | ||
} | ||
actions.push(new SetBoundsAction([{ elementId: element.id, newPosition: this.initialBounds, newSize: this.initialBounds }])); | ||
return actions; | ||
} | ||
@@ -320,13 +378,32 @@ return []; | ||
const newSize = { width, height }; | ||
const result: Action[] = []; | ||
if (this.isValidBoundChange(element, newPosition, newSize)) { | ||
return [new SetBoundsAction([{ elementId: element.id, newPosition, newSize }])]; | ||
if (this.tool.movementRestrictor) { | ||
result.push(...removeMovementRestrictionFeedback(element, this.tool.movementRestrictor)); | ||
} | ||
result.push(new SetBoundsAction([{ elementId: element.id, newPosition, newSize }])); | ||
} else if (this.isValidSize(element, newSize)) { | ||
if (this.tool.movementRestrictor) { | ||
result.push(...createMovementRestrictionFeedback(element, this.tool.movementRestrictor)); | ||
} | ||
result.push(new SetBoundsAction([{ elementId: element.id, newPosition, newSize }])); | ||
} | ||
return []; | ||
return result; | ||
} | ||
protected isValidBoundChange(element: SModelElement & BoundsAware, newPosition: Point, newSize: Dimension): boolean { | ||
return newSize.width >= this.minWidth(element) && newSize.height >= this.minHeight(element); | ||
const valid = this.isValidSize(element, newSize); | ||
if (this.tool.movementRestrictor) { | ||
return valid && this.tool.movementRestrictor.validate(newPosition, element); | ||
} | ||
return valid; | ||
} | ||
protected isValidSize(element: SModelElement & BoundsAware, size: Dimension) { | ||
return size.width >= this.minWidth(element) && size.height >= this.minHeight(element); | ||
} | ||
protected minWidth(element: SModelElement & BoundsAware): number { | ||
@@ -333,0 +410,0 @@ const layoutOptions = this.getLayoutOptions(element); |
@@ -42,3 +42,3 @@ /******************************************************************************** | ||
} from "../tool-feedback/creation-tool-feedback"; | ||
import { ApplyCursorCSSFeedbackAction, CursorCSS } from "../tool-feedback/cursor-feedback"; | ||
import { CursorCSS, cursorFeedbackAction } from "../tool-feedback/css-feedback"; | ||
import { IFeedbackActionDispatcher } from "../tool-feedback/feedback-action-dispatcher"; | ||
@@ -68,3 +68,3 @@ import { DragAwareMouseListener } from "./drag-aware-mouse-listener"; | ||
this.mouseTool.register(this.creationToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new ApplyCursorCSSFeedbackAction(CursorCSS.NODE_CREATION)]); | ||
this.feedbackDispatcher.registerFeedback(this, [cursorFeedbackAction(CursorCSS.NODE_CREATION)]); | ||
} | ||
@@ -74,3 +74,3 @@ | ||
this.mouseTool.deregister(this.creationToolMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.deregisterFeedback(this, [cursorFeedbackAction()]); | ||
} | ||
@@ -112,4 +112,4 @@ | ||
const feedback = this.creationAllowed(this.elementTypeId) | ||
? new ApplyCursorCSSFeedbackAction(CursorCSS.NODE_CREATION) : | ||
new ApplyCursorCSSFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED); | ||
? cursorFeedbackAction(CursorCSS.NODE_CREATION) : | ||
cursorFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED); | ||
this.tool.dispatchFeedback([feedback]); | ||
@@ -145,3 +145,3 @@ } | ||
this.mouseTool.register(this.feedbackEndMovingMouseListener); | ||
this.dispatchFeedback([new ApplyCursorCSSFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
this.dispatchFeedback([cursorFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
} | ||
@@ -152,3 +152,3 @@ | ||
this.mouseTool.deregister(this.feedbackEndMovingMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new RemoveFeedbackEdgeAction(), new ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new RemoveFeedbackEdgeAction(), cursorFeedbackAction()]); | ||
} | ||
@@ -230,8 +230,8 @@ | ||
if (this.allowedTarget) { | ||
const action = !this.isSourceSelected() ? new ApplyCursorCSSFeedbackAction(CursorCSS.EDGE_CREATION_SOURCE) : | ||
new ApplyCursorCSSFeedbackAction(CursorCSS.EDGE_CREATION_TARGET); | ||
const action = !this.isSourceSelected() ? cursorFeedbackAction(CursorCSS.EDGE_CREATION_SOURCE) : | ||
cursorFeedbackAction(CursorCSS.EDGE_CREATION_TARGET); | ||
return [action]; | ||
} | ||
} | ||
return [new ApplyCursorCSSFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]; | ||
return [cursorFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]; | ||
} | ||
@@ -238,0 +238,0 @@ return []; |
@@ -34,3 +34,3 @@ /******************************************************************************** | ||
import { DeleteElementOperationAction } from "../operation/operation-actions"; | ||
import { ApplyCursorCSSFeedbackAction, CursorCSS } from "../tool-feedback/cursor-feedback"; | ||
import { CursorCSS, cursorFeedbackAction } from "../tool-feedback/css-feedback"; | ||
import { IFeedbackActionDispatcher } from "../tool-feedback/feedback-action-dispatcher"; | ||
@@ -87,3 +87,3 @@ | ||
this.mouseTool.register(this.deleteToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new ApplyCursorCSSFeedbackAction(CursorCSS.ELEMENT_DELETION)]); | ||
this.feedbackDispatcher.registerFeedback(this, [cursorFeedbackAction(CursorCSS.ELEMENT_DELETION)]); | ||
} | ||
@@ -93,3 +93,3 @@ | ||
this.mouseTool.deregister(this.deleteToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.registerFeedback(this, [cursorFeedbackAction()]); | ||
} | ||
@@ -96,0 +96,0 @@ } |
@@ -28,7 +28,7 @@ /******************************************************************************** | ||
private isMouseDown: boolean = false; | ||
private isMouseDrag: boolean = false; | ||
private _isMouseDown: boolean = false; | ||
private _isMouseDrag: boolean = false; | ||
mouseDown(target: SModelElement, event: MouseEvent): Action[] { | ||
this.isMouseDown = true; | ||
this._isMouseDown = true; | ||
return []; | ||
@@ -38,4 +38,4 @@ } | ||
mouseMove(target: SModelElement, event: MouseEvent): Action[] { | ||
if (this.isMouseDown) { | ||
this.isMouseDrag = true; | ||
if (this._isMouseDown) { | ||
this._isMouseDrag = true; | ||
} | ||
@@ -46,5 +46,5 @@ return []; | ||
mouseUp(element: SModelElement, event: MouseEvent): Action[] { | ||
this.isMouseDown = false; | ||
if (this.isMouseDrag) { | ||
this.isMouseDrag = false; | ||
this._isMouseDown = false; | ||
if (this._isMouseDrag) { | ||
this._isMouseDrag = false; | ||
return this.draggingMouseUp(element, event); | ||
@@ -64,6 +64,10 @@ } | ||
get isDragging() { | ||
return this.isMouseDrag; | ||
get isMouseDrag() { | ||
return this._isMouseDrag; | ||
} | ||
get isMouseDown() { | ||
return this._isMouseDown; | ||
} | ||
} |
@@ -37,3 +37,3 @@ /******************************************************************************** | ||
import { IMouseTool } from "../mouse-tool/mouse-tool"; | ||
import { ReconnectConnectionOperationAction, RerouteConnectionOperationAction } from "../reconnect/action-definitions"; | ||
import { ChangeRoutingPointsOperation, ReconnectConnectionOperationAction } from "../operation/operation-actions"; | ||
import { | ||
@@ -48,3 +48,3 @@ isReconnectable, | ||
import { DrawFeedbackEdgeAction, feedbackEdgeId, RemoveFeedbackEdgeAction } from "../tool-feedback/creation-tool-feedback"; | ||
import { ApplyCursorCSSFeedbackAction, CursorCSS } from "../tool-feedback/cursor-feedback"; | ||
import { CursorCSS, cursorFeedbackAction } from "../tool-feedback/css-feedback"; | ||
import { | ||
@@ -153,3 +153,3 @@ DrawFeedbackEdgeSourceAction, | ||
this.tool.dispatchFeedback([new HideEdgeReconnectHandlesFeedbackAction(), | ||
new ApplyCursorCSSFeedbackAction(CursorCSS.EDGE_RECONNECT), | ||
cursorFeedbackAction(CursorCSS.EDGE_RECONNECT), | ||
new DrawFeedbackEdgeSourceAction(this.edge.type, this.edge.targetId)]); | ||
@@ -159,3 +159,3 @@ this.reconnectMode = "NEW_SOURCE"; | ||
this.tool.dispatchFeedback([new HideEdgeReconnectHandlesFeedbackAction(), | ||
new ApplyCursorCSSFeedbackAction(CursorCSS.EDGE_CREATION_TARGET), | ||
cursorFeedbackAction(CursorCSS.EDGE_CREATION_TARGET), | ||
new DrawFeedbackEdgeAction(this.edge.type, this.edge.sourceId)]); | ||
@@ -246,3 +246,3 @@ this.reconnectMode = "NEW_TARGET"; | ||
if (latestEdge && isRoutable(latestEdge)) { | ||
result.push(new RerouteConnectionOperationAction(latestEdge.id, latestEdge.routingPoints)); | ||
result.push(new ChangeRoutingPointsOperation([{ elementId: latestEdge.id, newRoutingPoints: latestEdge.routingPoints }])); | ||
this.routingHandle = undefined; | ||
@@ -263,7 +263,7 @@ } | ||
this.tool.dispatchFeedback([new ApplyCursorCSSFeedbackAction(CursorCSS.EDGE_RECONNECT)]); | ||
this.tool.dispatchFeedback([cursorFeedbackAction(CursorCSS.EDGE_RECONNECT)]); | ||
return []; | ||
} | ||
} | ||
this.tool.dispatchFeedback([new ApplyCursorCSSFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
this.tool.dispatchFeedback([cursorFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
} | ||
@@ -322,5 +322,5 @@ } | ||
result.push(...[new HideEdgeReconnectHandlesFeedbackAction(), | ||
new ApplyCursorCSSFeedbackAction(), new RemoveFeedbackEdgeAction()]); | ||
cursorFeedbackAction(), new RemoveFeedbackEdgeAction()]); | ||
this.tool.dispatchFeedback(result); | ||
} | ||
} |
@@ -19,2 +19,3 @@ /******************************************************************************** | ||
import glspContextMenuModule from "./features/context-menu/di.config"; | ||
import glspServerCopyPasteModule from "./features/copy-paste/di.config"; | ||
import glspEditLabelValidationModule from "./features/edit-label-validation/di.config"; | ||
@@ -37,6 +38,10 @@ import executeModule from "./features/execute/di.config"; | ||
export * from './base/command-stack'; | ||
export * from './base/editor-context'; | ||
export * from './features/change-bounds/model'; | ||
export * from './features/change-bounds/movement-restrictor'; | ||
export * from './features/change-bounds/snap'; | ||
export * from './features/context-actions/action-definitions'; | ||
export * from './features/context-menu/delete-element-context-menu'; | ||
export * from './features/command-palette/server-command-palette-provider'; | ||
export * from './features/copy-paste/copy-paste-handler'; | ||
export * from './features/edit-label-validation/edit-label-validator'; | ||
@@ -53,3 +58,2 @@ export * from './features/execute/execute-command'; | ||
export * from './features/rank/model'; | ||
export * from './features/reconnect/action-definitions'; | ||
export * from './features/reconnect/model'; | ||
@@ -61,3 +65,3 @@ export * from './features/request-response/glsp-action-dispatcher'; | ||
export * from './features/tool-feedback/creation-tool-feedback'; | ||
export * from './features/tool-feedback/cursor-feedback'; | ||
export * from './features/tool-feedback/css-feedback'; | ||
export * from './features/tool-feedback/edge-edit-tool-feedback'; | ||
@@ -87,5 +91,5 @@ export * from './features/tool-feedback/feedback-action-dispatcher'; | ||
validationModule, saveModule, executeModule, paletteModule, toolFeedbackModule, defaultGLSPModule, modelHintsModule, glspCommandPaletteModule, requestResponseModule, // | ||
glspContextMenuModule, glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule | ||
glspContextMenuModule, glspServerCopyPasteModule, glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule | ||
}; | ||
@@ -34,2 +34,3 @@ /******************************************************************************** | ||
import { ValidateLabelEditAction } from "../features/edit-label-validation/edit-label-validator"; | ||
import { RequestClipboardDataAction, PasteOperationAction, CutOperationAction } from "../features/copy-paste/copy-paste-actions"; | ||
@@ -87,3 +88,3 @@ @injectable() | ||
registry.register(OperationKind.RECONNECT_CONNECTION, diagramServer); | ||
registry.register(OperationKind.REROUTE_CONNECTION, diagramServer); | ||
registry.register(OperationKind.CHANGE_ROUTING_POINTS, diagramServer); | ||
registry.register(OperationKind.CREATE_NODE, diagramServer); | ||
@@ -108,2 +109,5 @@ registry.register(OperationKind.CHANGE_BOUNDS, diagramServer); | ||
registry.register(ApplyLabelEditAction.KIND, diagramServer); | ||
registry.register(RequestClipboardDataAction.KIND, diagramServer); | ||
registry.register(PasteOperationAction.KIND, diagramServer); | ||
registry.register(CutOperationAction.KIND, diagramServer); | ||
@@ -110,0 +114,0 @@ // Register an empty handler for SwitchEditMode, to avoid runtime exceptions. |
@@ -29,3 +29,4 @@ /******************************************************************************** | ||
IContextMenuProviderRegistry: Symbol.for("IContextMenuProviderRegistry"), | ||
IContextMenuProvider: Symbol.for("IContextMenuProvider") | ||
IContextMenuProvider: Symbol.for("IContextMenuProvider"), | ||
ICopyPasteHandler: Symbol.for("ICopyPasteHandler") | ||
}; |
@@ -26,2 +26,3 @@ /******************************************************************************** | ||
} from "sprotty/lib"; | ||
import { ElementAndRoutingPoints } from "src/features/operation/operation-actions"; | ||
@@ -115,1 +116,8 @@ | ||
} | ||
export function toElementAndRoutingPoints(element: SRoutableElement): ElementAndRoutingPoints { | ||
return { | ||
elementId: element.id, | ||
newRoutingPoints: element.routingPoints | ||
}; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 2 instances in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
1014379
371
15841
12