@eclipse-glsp/client
Advanced tools
Comparing version 0.8.0-next.ca58207 to 0.8.0-next.db93ed9
@@ -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 { | ||
handle(action: Action): Action | void; | ||
handledActionKinds: string[]; | ||
} | ||
@@ -19,4 +18,4 @@ export declare function isSetModelAction(action: Action): action is SetModelAction; | ||
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[]); | ||
@@ -23,0 +22,0 @@ protected performUpdate(oldRoot: SModelRoot, newRoot: SModelRoot, context: CommandExecutionContext): CommandReturn; |
@@ -52,3 +52,2 @@ "use strict"; | ||
function SetModelActionHandler() { | ||
this.handledActionKinds = [lib_1.SetModelCommand.KIND]; | ||
} | ||
@@ -82,9 +81,8 @@ SetModelActionHandler.prototype.handle = function (action) { | ||
_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` | ||
@@ -100,6 +98,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); }); | ||
} | ||
@@ -106,0 +102,0 @@ this.modelRootListeners.forEach(function (listener) { return listener.modelRootChanged(newRoot); }); |
@@ -16,4 +16,7 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { BoundsAware, Hoverable, Locateable, SChildElement, Selectable, SModelElement, SNode, SParentElement } from "sprotty/lib"; | ||
import { NodeEditConfig } from "../../base/edit-config/edit-config"; | ||
import { BoundsAware, Hoverable, Locateable, SChildElement, Selectable, SModelElement, SParentElement } from "sprotty/lib"; | ||
export declare const resizeFeature: unique symbol; | ||
export interface Resizable extends BoundsAware, Selectable { | ||
} | ||
export declare function isResizable(element: SModelElement): element is SParentElement & Resizable; | ||
export declare enum ResizeHandleLocation { | ||
@@ -25,3 +28,2 @@ TopLeft = "top-left", | ||
} | ||
export declare function isResizeable(element: SModelElement): element is SNode & SParentElement & BoundsAware & Selectable & NodeEditConfig; | ||
export declare function isBoundsAwareMoveable(element: SModelElement): element is SModelElement & Locateable & BoundsAware; | ||
@@ -28,0 +30,0 @@ export declare class SResizeHandle extends SChildElement implements Hoverable { |
@@ -32,3 +32,7 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var edit_config_1 = require("../../base/edit-config/edit-config"); | ||
exports.resizeFeature = Symbol("resizeFeature"); | ||
function isResizable(element) { | ||
return lib_1.isBoundsAware(element) && lib_1.isSelectable(element) && element instanceof lib_1.SParentElement && element.hasFeature(exports.resizeFeature); | ||
} | ||
exports.isResizable = isResizable; | ||
var ResizeHandleLocation; | ||
@@ -41,6 +45,2 @@ (function (ResizeHandleLocation) { | ||
})(ResizeHandleLocation = exports.ResizeHandleLocation || (exports.ResizeHandleLocation = {})); | ||
function isResizeable(element) { | ||
return edit_config_1.isConfigurableNode(element) && element.resizable && lib_1.isBoundsAware(element) && lib_1.isSelectable(element) && element instanceof lib_1.SParentElement; | ||
} | ||
exports.isResizeable = isResizeable; | ||
function isBoundsAwareMoveable(element) { | ||
@@ -47,0 +47,0 @@ return lib_1.isMoveable(element) && lib_1.isBoundsAware(element); |
@@ -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 |
@@ -21,9 +21,7 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var action_provider_1 = require("./action-provider"); | ||
var glspCommandPaletteModule = new inversify_1.ContainerModule(function (bind, unbind, isBound, rebind) { | ||
bind(lib_1.TYPES.ICommandPaletteActionProvider).to(action_provider_1.NavigationCommandPaletteActionProvider); | ||
bind(action_provider_1.ServerCommandPaletteActionProvider).toSelf().inSingletonScope(); | ||
bind(lib_1.TYPES.ICommandPaletteActionProvider).to(action_provider_1.ServerCommandPaletteActionProvider); | ||
var server_command_palette_provider_1 = require("./server-command-palette-provider"); | ||
var glspCommandPaletteModule = new inversify_1.ContainerModule(function (bind) { | ||
bind(lib_1.TYPES.ICommandPaletteActionProvider).to(server_command_palette_provider_1.ServerCommandPaletteActionProvider); | ||
}); | ||
exports.default = glspCommandPaletteModule; | ||
//# sourceMappingURL=di.config.js.map |
@@ -1,19 +0,21 @@ | ||
import { Action, EditableLabel, EditLabelValidationResult, IEditLabelValidationDecorator, IEditLabelValidator, SModelElement } from "sprotty"; | ||
import { RequestResponseSupport } from "../request-response/support"; | ||
export declare class ValidateLabelEditAction implements Action { | ||
import { Action, EditableLabel, EditLabelValidationResult, IEditLabelValidationDecorator, IEditLabelValidator, RequestAction, ResponseAction, SModelElement } from "sprotty"; | ||
import { GLSPActionDispatcher } from "../request-response/glsp-action-dispatcher"; | ||
export declare class ValidateLabelEditAction implements RequestAction<SetLabelEditValidationResultAction> { | ||
readonly value: string; | ||
readonly labelId: string; | ||
readonly requestId: string; | ||
static readonly KIND = "validateLabelEdit"; | ||
kind: string; | ||
constructor(value: string, labelId: string); | ||
constructor(value: string, labelId: string, requestId?: string); | ||
} | ||
export declare class SetLabelEditValidationResultAction implements Action { | ||
export declare class SetLabelEditValidationResultAction implements ResponseAction { | ||
readonly result: EditLabelValidationResult; | ||
readonly responseId: string; | ||
static readonly KIND = "setLabelEditValidationResult"; | ||
kind: string; | ||
constructor(result: EditLabelValidationResult); | ||
constructor(result: EditLabelValidationResult, responseId?: string); | ||
} | ||
export declare function isSetLabelEditValidationResultAction(action: Action): action is SetLabelEditValidationResultAction; | ||
export declare class ServerEditLabelValidator implements IEditLabelValidator { | ||
protected requestResponseSupport: RequestResponseSupport; | ||
protected actionDispatcher: GLSPActionDispatcher; | ||
validate(value: string, label: EditableLabel & SModelElement): Promise<EditLabelValidationResult>; | ||
@@ -20,0 +22,0 @@ getValidationResultFromResponse(action: Action): EditLabelValidationResult; |
@@ -28,8 +28,10 @@ "use strict"; | ||
var inversify_1 = require("inversify"); | ||
var types_1 = require("../../types"); | ||
var support_1 = require("../request-response/support"); | ||
var sprotty_1 = require("sprotty"); | ||
var glsp_action_dispatcher_1 = require("../request-response/glsp-action-dispatcher"); | ||
var ValidateLabelEditAction = /** @class */ (function () { | ||
function ValidateLabelEditAction(value, labelId) { | ||
function ValidateLabelEditAction(value, labelId, requestId) { | ||
if (requestId === void 0) { requestId = sprotty_1.generateRequestId(); } | ||
this.value = value; | ||
this.labelId = labelId; | ||
this.requestId = requestId; | ||
this.kind = ValidateLabelEditAction.KIND; | ||
@@ -42,4 +44,6 @@ } | ||
var SetLabelEditValidationResultAction = /** @class */ (function () { | ||
function SetLabelEditValidationResultAction(result) { | ||
function SetLabelEditValidationResultAction(result, responseId) { | ||
if (responseId === void 0) { responseId = ''; } | ||
this.result = result; | ||
this.responseId = responseId; | ||
this.kind = SetLabelEditValidationResultAction.KIND; | ||
@@ -60,4 +64,5 @@ } | ||
ServerEditLabelValidator.prototype.validate = function (value, label) { | ||
var _this = this; | ||
var action = new ValidateLabelEditAction(value, label.id); | ||
return this.requestResponseSupport.dispatchRequest(action, this.getValidationResultFromResponse); | ||
return this.actionDispatcher.requestUntil(action).then(function (response) { return _this.getValidationResultFromResponse(response); }); | ||
}; | ||
@@ -71,5 +76,5 @@ ServerEditLabelValidator.prototype.getValidationResultFromResponse = function (action) { | ||
__decorate([ | ||
inversify_1.inject(types_1.GLSP_TYPES.RequestResponseSupport), | ||
__metadata("design:type", support_1.RequestResponseSupport) | ||
], ServerEditLabelValidator.prototype, "requestResponseSupport", void 0); | ||
inversify_1.inject(sprotty_1.TYPES.IActionDispatcher), | ||
__metadata("design:type", glsp_action_dispatcher_1.GLSPActionDispatcher) | ||
], ServerEditLabelValidator.prototype, "actionDispatcher", void 0); | ||
ServerEditLabelValidator = __decorate([ | ||
@@ -76,0 +81,0 @@ inversify_1.injectable() |
@@ -21,11 +21,11 @@ "use strict"; | ||
var types_1 = require("../../types"); | ||
var action_definition_1 = require("./action-definition"); | ||
var type_hints_action_initializer_1 = require("./type-hints-action-initializer"); | ||
var request_type_hints_action_1 = require("./request-type-hints-action"); | ||
var type_hints_1 = require("./type-hints"); | ||
var modelHintsModule = new inversify_1.ContainerModule(function (bind, _unbind, isBound) { | ||
bind(type_hints_action_initializer_1.TypeHintsEditConfigProvider).toSelf().inSingletonScope(); | ||
lib_1.configureActionHandler({ bind: bind, isBound: isBound }, action_definition_1.SetTypeHintsAction.KIND, type_hints_action_initializer_1.TypeHintsEditConfigProvider); | ||
bind(types_1.GLSP_TYPES.IEditConfigProvider).toService(type_hints_action_initializer_1.TypeHintsEditConfigProvider); | ||
lib_1.configureCommand({ bind: bind, isBound: isBound }, type_hints_action_initializer_1.ApplyEditConfigCommand); | ||
bind(type_hints_1.TypeHintProvider).toSelf().inSingletonScope(); | ||
bind(types_1.GLSP_TYPES.ITypeHintProvider).toService(type_hints_1.TypeHintProvider); | ||
lib_1.configureActionHandler({ bind: bind, isBound: isBound }, request_type_hints_action_1.SetTypeHintsAction.KIND, type_hints_1.TypeHintProvider); | ||
lib_1.configureCommand({ bind: bind, isBound: isBound }, type_hints_1.ApplyTypeHintsCommand); | ||
}); | ||
exports.default = modelHintsModule; | ||
//# sourceMappingURL=di.config.js.map |
@@ -53,5 +53,5 @@ import { Action, Command, CommandExecutionContext, CommandReturn, Dimension, ElementAndBounds, ElementMove, IActionDispatcher, KeyListener, Point, SModelElement } from "sprotty"; | ||
export declare namespace Select { | ||
function all(elements: SelectableBoundsAware[]): SelectableBoundsAware[]; | ||
function first(elements: SelectableBoundsAware[]): SelectableBoundsAware[]; | ||
function last(elements: SelectableBoundsAware[]): SelectableBoundsAware[]; | ||
function all(elements: SelectableBoundsAware[]): (SModelElement & import("sprotty").BoundsAware & import("sprotty").Selectable)[]; | ||
function first(elements: SelectableBoundsAware[]): (SModelElement & import("sprotty").BoundsAware & import("sprotty").Selectable)[]; | ||
function last(elements: SelectableBoundsAware[]): (SModelElement & import("sprotty").BoundsAware & import("sprotty").Selectable)[]; | ||
} | ||
@@ -58,0 +58,0 @@ export declare class AlignElementsAction implements Action { |
@@ -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"; |
@@ -16,6 +16,8 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { RoutingHandleKind, SModelElement, SRoutableElement, SRoutingHandle } from "sprotty/lib"; | ||
export declare function isRoutable<T extends SModelElement>(element: T): element is T & SRoutableElement; | ||
import { RoutingHandleKind, SModelElement, SModelExtension, SRoutableElement, SRoutingHandle } from "sprotty/lib"; | ||
export declare const reconnectFeature: unique symbol; | ||
export interface Reconnectable extends SModelExtension { | ||
} | ||
export declare function isReconnectable(element: SModelElement): element is SRoutableElement & Reconnectable; | ||
export declare function isReconnectHandle(element: SModelElement | undefined): element is SReconnectHandle; | ||
export declare function isRoutingHandle(element: SModelElement | undefined): element is SRoutingHandle; | ||
export declare function addReconnectHandles(element: SRoutableElement): void; | ||
@@ -22,0 +24,0 @@ export declare function removeReconnectHandles(element: SRoutableElement): void; |
@@ -32,7 +32,8 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
exports.reconnectFeature = Symbol("reconnectFeature"); | ||
function isReconnectable(element) { | ||
return element instanceof lib_1.SRoutableElement && element.hasFeature(exports.reconnectFeature); | ||
} | ||
exports.isReconnectable = isReconnectable; | ||
var ROUTING_HANDLE_SOURCE_INDEX = -2; | ||
function isRoutable(element) { | ||
return element instanceof lib_1.SRoutableElement && element.routingPoints !== undefined; | ||
} | ||
exports.isRoutable = isRoutable; | ||
function isReconnectHandle(element) { | ||
@@ -42,6 +43,2 @@ return element !== undefined && element instanceof SReconnectHandle; | ||
exports.isReconnectHandle = isReconnectHandle; | ||
function isRoutingHandle(element) { | ||
return element !== undefined && element instanceof lib_1.SRoutingHandle; | ||
} | ||
exports.isRoutingHandle = isRoutingHandle; | ||
function addReconnectHandles(element) { | ||
@@ -48,0 +45,0 @@ removeReconnectHandles(element); |
@@ -20,10 +20,7 @@ "use strict"; | ||
var sprotty_1 = require("sprotty"); | ||
var types_1 = require("../../types"); | ||
var support_1 = require("./support"); | ||
var glsp_action_dispatcher_1 = require("./glsp-action-dispatcher"); | ||
var requestResponseModule = new inversify_1.ContainerModule(function (bind, unbind, isBound, rebind) { | ||
bind(support_1.RequestResponseSupport).toSelf().inSingletonScope(); | ||
bind(types_1.GLSP_TYPES.RequestResponseSupport).toService(support_1.RequestResponseSupport); | ||
bind(sprotty_1.TYPES.IActionHandlerInitializer).toService(support_1.RequestResponseSupport); | ||
rebind(sprotty_1.TYPES.IActionDispatcher).to(glsp_action_dispatcher_1.GLSPActionDispatcher).inSingletonScope(); | ||
}); | ||
exports.default = requestResponseModule; | ||
//# sourceMappingURL=di.config.js.map |
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,6 +95,9 @@ var ShowChangeBoundsToolResizeFeedbackAction = /** @class */ (function () { | ||
var index = context.root.index; | ||
index.all().filter(model_1.isResizeable).forEach(model_1.removeResizeHandles); | ||
index | ||
.all() | ||
.filter(model_1.isResizable) | ||
.forEach(model_1.removeResizeHandles); | ||
if (smodel_util_1.isNotUndefined(this.action.elementId)) { | ||
var resizeElement = index.getById(this.action.elementId); | ||
if (smodel_util_1.isNotUndefined(resizeElement) && model_1.isResizeable(resizeElement)) { | ||
if (smodel_util_1.isNotUndefined(resizeElement) && model_1.isResizable(resizeElement)) { | ||
model_1.addResizeHandles(resizeElement); | ||
@@ -85,3 +108,3 @@ } | ||
}; | ||
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.isResizeable).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,16 +152,17 @@ 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; | ||
} | ||
FeedbackMoveMouseListener.prototype.mouseDown = function (target, event) { | ||
if (event.button === 0) { | ||
if (event.button === 0 && !(target instanceof model_1.SResizeHandle)) { | ||
var moveable = lib_1.findParentByFeature(target, lib_1.isMoveable); | ||
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; | ||
} | ||
@@ -147,26 +174,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, | ||
@@ -177,16 +226,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) { | ||
@@ -198,5 +267,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; | ||
}; | ||
@@ -203,0 +283,0 @@ FeedbackMoveMouseListener.prototype.decorate = function (vnode, element) { |
@@ -6,4 +6,5 @@ import { Action, AnchorComputerRegistry, CommandExecutionContext, CommandReturn, MouseListener, SDanglingAnchor, SModelElement, SModelRoot, SRoutableElement } from "sprotty/lib"; | ||
readonly sourceId: string; | ||
readonly routerKind?: string | undefined; | ||
kind: string; | ||
constructor(elementTypeId: string, sourceId: string); | ||
constructor(elementTypeId: string, sourceId: string, routerKind?: string | undefined); | ||
} | ||
@@ -10,0 +11,0 @@ export declare class DrawFeedbackEdgeCommand extends FeedbackCommand { |
@@ -45,9 +45,10 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var smodel_util_1 = require("../../utils/smodel-util"); | ||
var viewpoint_util_1 = require("../../utils/viewpoint-util"); | ||
var model_1 = require("../reconnect/model"); | ||
var model_2 = require("./model"); | ||
var model_1 = require("./model"); | ||
var DrawFeedbackEdgeAction = /** @class */ (function () { | ||
function DrawFeedbackEdgeAction(elementTypeId, sourceId) { | ||
function DrawFeedbackEdgeAction(elementTypeId, sourceId, routerKind) { | ||
this.elementTypeId = elementTypeId; | ||
this.sourceId = sourceId; | ||
this.routerKind = routerKind; | ||
this.kind = DrawFeedbackEdgeCommand.KIND; | ||
@@ -66,3 +67,3 @@ } | ||
DrawFeedbackEdgeCommand.prototype.execute = function (context) { | ||
drawFeedbackEdge(context, this.action.sourceId, this.action.elementTypeId); | ||
drawFeedbackEdge(context, this.action.sourceId, this.action.elementTypeId, this.action.routerKind); | ||
return context.root; | ||
@@ -77,3 +78,3 @@ }; | ||
return DrawFeedbackEdgeCommand; | ||
}(model_2.FeedbackCommand)); | ||
}(model_1.FeedbackCommand)); | ||
exports.DrawFeedbackEdgeCommand = DrawFeedbackEdgeCommand; | ||
@@ -101,3 +102,3 @@ var RemoveFeedbackEdgeAction = /** @class */ (function () { | ||
return RemoveFeedbackEdgeCommand; | ||
}(model_2.FeedbackCommand)); | ||
}(model_1.FeedbackCommand)); | ||
exports.RemoveFeedbackEdgeCommand = RemoveFeedbackEdgeCommand; | ||
@@ -159,3 +160,3 @@ var FeedbackEdgeEnd = /** @class */ (function (_super) { | ||
exports.feedbackEdgeEndId = feedbackEdgeEndId; | ||
function drawFeedbackEdge(context, sourceId, elementTypeId) { | ||
function drawFeedbackEdge(context, sourceId, elementTypeId, routerKind) { | ||
var root = context.root; | ||
@@ -172,12 +173,14 @@ var sourceChild = root.index.getById(sourceId); | ||
edgeEnd.id = feedbackEdgeEndId(root); | ||
edgeEnd.position = { x: source.bounds.x, y: source.bounds.y }; | ||
edgeEnd.position = viewpoint_util_1.toAbsolutePosition(source); | ||
var feedbackEdgeSchema = { | ||
type: 'edge', | ||
type: elementTypeId, | ||
id: feedbackEdgeId(root), | ||
sourceId: source.id, | ||
targetId: edgeEnd.id, | ||
cssClasses: ["feedback-edge"], | ||
routerKind: routerKind, | ||
opacity: 0.3 | ||
}; | ||
var feedbackEdge = context.modelFactory.createElement(feedbackEdgeSchema); | ||
if (model_1.isRoutable(feedbackEdge)) { | ||
if (smodel_util_1.isRoutable(feedbackEdge)) { | ||
edgeEnd.feedbackEdge = feedbackEdge; | ||
@@ -184,0 +187,0 @@ root.add(edgeEnd); |
@@ -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); |
@@ -77,6 +77,6 @@ "use strict"; | ||
var index = context.root.index; | ||
index.all().filter(model_1.isRoutable).forEach(model_1.removeReconnectHandles); | ||
index.all().filter(smodel_util_1.isRoutable).forEach(model_1.removeReconnectHandles); | ||
if (smodel_util_1.isNotUndefined(this.action.elementId)) { | ||
var routableElement = index.getById(this.action.elementId); | ||
if (smodel_util_1.isNotUndefined(routableElement) && model_1.isRoutable(routableElement)) { | ||
if (smodel_util_1.isNotUndefined(routableElement) && smodel_util_1.isRoutable(routableElement)) { | ||
model_1.addReconnectHandles(routableElement); | ||
@@ -105,3 +105,3 @@ } | ||
var index = context.root.index; | ||
index.all().filter(model_1.isRoutable).forEach(model_1.removeReconnectHandles); | ||
index.all().filter(smodel_util_1.isRoutable).forEach(model_1.removeReconnectHandles); | ||
return context.root; | ||
@@ -233,3 +233,3 @@ }; | ||
if (event.button === 0) { | ||
var routingHandle = lib_1.findParentByFeature(target, model_1.isRoutingHandle); | ||
var routingHandle = lib_1.findParentByFeature(target, smodel_util_1.isRoutingHandle); | ||
if (routingHandle !== undefined) { | ||
@@ -259,5 +259,5 @@ result.push(new SwitchRoutingModeAction([target.id], [])); | ||
target.root.index.all() | ||
.filter(function (element) { return smodel_util_1.isSelected(element); }) | ||
.filter(function (element) { return lib_1.isSelected(element); }) | ||
.forEach(function (element) { | ||
if (model_1.isRoutingHandle(element)) { | ||
if (smodel_util_1.isRoutingHandle(element)) { | ||
var point = _this.getHandlePosition(element); | ||
@@ -285,3 +285,3 @@ if (point !== undefined) { | ||
var parent_1 = handle.parent; | ||
if (!model_1.isRoutable(parent_1)) | ||
if (!smodel_util_1.isRoutable(parent_1)) | ||
return undefined; | ||
@@ -334,3 +334,3 @@ var router = this.edgeRouterRegistry.get(parent_1.routerKind); | ||
var feedbackEdge = context.modelFactory.createElement(feedbackEdgeSchema); | ||
if (model_1.isRoutable(feedbackEdge)) { | ||
if (smodel_util_1.isRoutable(feedbackEdge)) { | ||
edgeEnd.feedbackEdge = feedbackEdge; | ||
@@ -337,0 +337,0 @@ root.add(edgeEnd); |
@@ -1,19 +0,4 @@ | ||
/******************************************************************************** | ||
* Copyright (c) 2019 EclipseSource and others. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the Eclipse | ||
* Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
* with the GNU Classpath Exception which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
********************************************************************************/ | ||
import { VNode } from "snabbdom/vnode"; | ||
import { IView, Point, RenderingContext, SModelElement } from "sprotty/lib"; | ||
import { SResizeHandle } from '../change-bounds/model'; | ||
import { SResizeHandle } from "../change-bounds/model"; | ||
/** | ||
@@ -20,0 +5,0 @@ * This view is used for the invisible end of the feedback edge. |
"use strict"; | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); | ||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; | ||
return c > 3 && r && Object.defineProperty(target, key, r), r; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/******************************************************************************** | ||
@@ -17,14 +24,7 @@ * Copyright (c) 2019 EclipseSource and others. | ||
********************************************************************************/ | ||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | ||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); | ||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; | ||
return c > 3 && r && Object.defineProperty(target, key, r), r; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** @jsx svg */ | ||
var inversify_1 = require("inversify"); | ||
var snabbdom_jsx_1 = require("snabbdom-jsx"); | ||
var snabbdom = require("snabbdom-jsx"); | ||
var lib_1 = require("sprotty/lib"); | ||
var model_1 = require("../change-bounds/model"); | ||
var JSX = { createElement: snabbdom.svg }; | ||
/** | ||
@@ -39,3 +39,3 @@ * This view is used for the invisible end of the feedback edge. | ||
var position = model.position || lib_1.ORIGIN_POINT; | ||
return snabbdom_jsx_1.svg("g", { x: position.x, y: position.y }); | ||
return JSX.createElement("g", { x: position.x, y: position.y }); | ||
}; | ||
@@ -54,3 +54,3 @@ FeedbackEdgeEndView = __decorate([ | ||
if (position !== undefined) { | ||
var node = snabbdom_jsx_1.svg("circle", { "class-sprotty-resize-handle": true, "class-mouseover": handle.hoverFeedback, cx: position.x, cy: position.y, r: this.getRadius() }); | ||
var node = JSX.createElement("circle", { "class-sprotty-resize-handle": true, "class-mouseover": handle.hoverFeedback, cx: position.x, cy: position.y, r: this.getRadius() }); | ||
lib_1.setAttr(node, 'data-kind', handle.location); | ||
@@ -60,7 +60,7 @@ return node; | ||
// Fallback: Create an empty group | ||
return snabbdom_jsx_1.svg("g", null); | ||
return JSX.createElement("g", null); | ||
}; | ||
SResizeHandleView.prototype.getPosition = function (handle) { | ||
var parent = handle.parent; | ||
if (model_1.isResizeable(parent)) { | ||
if (model_1.isResizable(parent)) { | ||
if (handle.location === model_1.ResizeHandleLocation.TopLeft) { | ||
@@ -67,0 +67,0 @@ return { x: 0, y: 0 }; |
@@ -1,8 +0,8 @@ | ||
import { Action, BoundsAware, KeyTool, 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 { FeedbackMoveMouseListener } 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"; | ||
/** | ||
@@ -26,25 +26,31 @@ * 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; | ||
readonly id: string; | ||
protected feedbackMoveMouseListener: FeedbackMoveMouseListener; | ||
protected changeBoundsListener: ChangeBoundsListener; | ||
constructor(selectionService: SelectionService, mouseTool: IMouseTool, keyTool: KeyTool, feedbackDispatcher: IFeedbackActionDispatcher, movementRestrictor?: IMovementRestrictor | undefined); | ||
protected feedbackMoveMouseListener: MouseListener; | ||
protected changeBoundsListener: MouseListener & SelectionListener; | ||
constructor(selectionService: SelectionService, mouseTool: IMouseTool, keyTool: KeyTool, feedbackDispatcher: IFeedbackActionDispatcher, edgeRouterRegistry?: EdgeRouterRegistry | undefined, snapper?: ISnapper | undefined, movementRestrictor?: IMovementRestrictor | undefined); | ||
enable(): void; | ||
protected createMoveMouseListener(): MouseListener; | ||
protected createChangeBoundsListener(): MouseListener & SelectionListener; | ||
disable(): void; | ||
dispatchFeedback(actions: Action[]): void; | ||
dispatchFeedback(feedbackEmmmiter: IFeedbackEmitter, actions: Action[]): void; | ||
} | ||
declare class ChangeBoundsListener extends MouseListener implements SelectionListener { | ||
export declare class ChangeBoundsListener extends DragAwareMouseListener implements SelectionListener { | ||
protected tool: ChangeBoundsTool; | ||
protected lastDragPosition: Point | undefined; | ||
protected lastDragPosition?: Point; | ||
protected positionDelta: Point; | ||
protected activeResizeElementId: string | undefined; | ||
protected activeResizeHandle: SResizeHandle | undefined; | ||
protected initialPositon: Point | undefined; | ||
protected initialBounds: Bounds | undefined; | ||
protected activeResizeElementId?: string; | ||
protected activeResizeHandle?: SResizeHandle; | ||
constructor(tool: ChangeBoundsTool); | ||
mouseDown(target: SModelElement, event: MouseEvent): Action[]; | ||
mouseMove(target: SModelElement, event: MouseEvent): Action[]; | ||
mouseUp(target: SModelElement, event: MouseEvent): Action[]; | ||
draggingMouseUp(target: SModelElement, event: MouseEvent): Action[]; | ||
selectionChanged(root: SModelRoot, selectedElements: string[]): void; | ||
protected setActiveResizeElement(target: SModelElement): boolean; | ||
protected isActiveResizeElement(element: SModelElement | undefined): element is SParentElement & BoundsAware; | ||
protected isActiveResizeElement(element?: SModelElement): element is SParentElement & BoundsAware; | ||
protected initPosition(event: MouseEvent): void; | ||
@@ -54,6 +60,16 @@ protected updatePosition(target: SModelElement, event: MouseEvent): boolean; | ||
protected resetPosition(): void; | ||
protected hasPositionDelta(): 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[]; | ||
protected createElementAndBounds(element: SModelElement & BoundsAware): ElementAndBounds[]; | ||
protected createSetBoundsAction(element: SModelElement & BoundsAware, x: number, y: number, width: number, height: number): Action[]; | ||
protected isValidBoundChange(element: SModelElement & BoundsAware, newPosition: Point, newSize: Dimension): boolean; | ||
protected isValidSize(element: SModelElement & BoundsAware, size: Dimension): boolean; | ||
protected minWidth(element: SModelElement & BoundsAware): number; | ||
protected minHeight(element: SModelElement & BoundsAware): number; | ||
protected getLayoutOptions(element: SModelElement): ModelLayoutOptions | undefined; | ||
} | ||
export {}; | ||
//# sourceMappingURL=change-bounds-tool.d.ts.map |
@@ -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; | ||
@@ -91,10 +115,17 @@ this.id = ChangeBoundsTool_1.ID; | ||
// install feedback move mouse listener for client-side move updates | ||
this.feedbackMoveMouseListener = new change_bounds_tool_feedback_1.FeedbackMoveMouseListener(this.movementRestrictor); | ||
this.feedbackMoveMouseListener = this.createMoveMouseListener(); | ||
this.mouseTool.register(this.feedbackMoveMouseListener); | ||
// instlal change bounds listener for client-side resize updates and server-side updates | ||
this.changeBoundsListener = new ChangeBoundsListener(this); | ||
// install change bounds listener for client-side resize updates and server-side updates | ||
this.changeBoundsListener = this.createChangeBoundsListener(); | ||
this.mouseTool.register(this.changeBoundsListener); | ||
this.selectionService.register(this.changeBoundsListener); | ||
// register feedback | ||
this.feedbackDispatcher.registerFeedback(this, [new change_bounds_tool_feedback_1.ShowChangeBoundsToolResizeFeedbackAction]); | ||
}; | ||
ChangeBoundsTool.prototype.createMoveMouseListener = function () { | ||
return new change_bounds_tool_feedback_1.FeedbackMoveMouseListener(this); | ||
}; | ||
ChangeBoundsTool.prototype.createChangeBoundsListener = function () { | ||
return new ChangeBoundsListener(this); | ||
}; | ||
ChangeBoundsTool.prototype.disable = function () { | ||
@@ -104,6 +135,7 @@ this.mouseTool.deregister(this.changeBoundsListener); | ||
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); | ||
}; | ||
@@ -118,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); | ||
@@ -130,8 +164,4 @@ return ChangeBoundsTool; | ||
_this.tool = tool; | ||
// members for calculating the correct position change | ||
_this.lastDragPosition = undefined; | ||
_this.positionDelta = { x: 0, y: 0 }; | ||
// members for resize mode | ||
_this.activeResizeElementId = undefined; | ||
_this.activeResizeHandle = undefined; | ||
_this.initialPositon = undefined; | ||
return _this; | ||
@@ -141,22 +171,23 @@ } | ||
_super.prototype.mouseDown.call(this, target, event); | ||
var actions = []; | ||
if (event.button === 0) { | ||
// check if we have a resize handle (only single-selection) | ||
if (this.activeResizeElementId && target instanceof model_1.SResizeHandle) { | ||
this.activeResizeHandle = target; | ||
} | ||
else { | ||
this.setActiveResizeElement(target); | ||
} | ||
if (this.activeResizeElementId) { | ||
this.initPosition(event); | ||
} | ||
else { | ||
this.reset(); | ||
} | ||
if (event.button !== 0) { | ||
return []; | ||
} | ||
return actions; | ||
// check if we have a resize handle (only single-selection) | ||
if (this.activeResizeElementId && target instanceof model_1.SResizeHandle) { | ||
this.activeResizeHandle = target; | ||
} | ||
else { | ||
this.setActiveResizeElement(target); | ||
} | ||
if (this.activeResizeElementId) { | ||
this.initPosition(event); | ||
} | ||
else { | ||
this.reset(); | ||
} | ||
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 | ||
@@ -168,22 +199,27 @@ // consider resize handles ourselves | ||
}; | ||
ChangeBoundsListener.prototype.mouseUp = function (target, event) { | ||
_super.prototype.mouseUp.call(this, target, event); | ||
if (!this.hasPositionDelta()) { | ||
ChangeBoundsListener.prototype.draggingMouseUp = function (target, event) { | ||
var _this = this; | ||
if (this.lastDragPosition === undefined) { | ||
this.resetPosition(); | ||
return []; | ||
} | ||
// no further bound changing, simply send the latest data to the server using a single change bounds action for all relevant elements | ||
var actions = []; | ||
if (this.activeResizeHandle) { | ||
// An action. Resize, not move. | ||
var resizeElement = lib_1.findParentByFeature(this.activeResizeHandle, model_1.isResizeable); | ||
// Resize, not move | ||
var resizeElement = lib_1.findParentByFeature(this.activeResizeHandle, model_1.isResizable); | ||
if (this.isActiveResizeElement(resizeElement)) { | ||
createChangeBoundsAction(resizeElement).forEach(function (action) { return actions.push(action); }); | ||
this.createChangeBoundsAction(resizeElement).forEach(function (action) { return actions.push(action); }); | ||
} | ||
} | ||
else { | ||
// Bounds... Change Bounds. | ||
// Move | ||
var newBounds_1 = []; | ||
smodel_util_1.forEachElement(target, smodel_util_1.isNonRoutableSelectedBoundsAware, function (element) { | ||
return createElementAndBounds(element).forEach(function (bounds) { return newBounds_1.push(bounds); }); | ||
var newRoutingPoints_1 = []; | ||
smodel_util_1.forEachElement(target, smodel_util_1.isNonRoutableSelectedMovableBoundsAware, function (element) { | ||
_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); }); | ||
} | ||
}); | ||
@@ -193,2 +229,5 @@ if (newBounds_1.length > 0) { | ||
} | ||
if (newRoutingPoints_1.length > 0) { | ||
actions.push(new operation_actions_1.ChangeRoutingPointsOperation(newRoutingPoints_1)); | ||
} | ||
} | ||
@@ -201,3 +240,3 @@ this.resetPosition(); | ||
if (this.activeResizeElementId) { | ||
if (selectedElements.indexOf(this.activeResizeElementId) > -1) { | ||
if (selectedElements.includes(this.activeResizeElementId)) { | ||
// our active element is still selected, nothing to do | ||
@@ -229,6 +268,6 @@ return; | ||
var moveableElement = lib_1.findParentByFeature(target, model_1.isBoundsAwareMoveable); | ||
if (smodel_util_1.isSelected(moveableElement)) { | ||
if (lib_1.isSelected(moveableElement)) { | ||
// only allow one element to have the element resize handles | ||
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,7 +309,5 @@ }; | ||
this.lastDragPosition = undefined; | ||
this.initialPositon = undefined; | ||
this.positionDelta = { x: 0, y: 0 }; | ||
}; | ||
ChangeBoundsListener.prototype.hasPositionDelta = function () { | ||
return this.positionDelta.x !== 0 || this.positionDelta.y !== 0; | ||
}; | ||
ChangeBoundsListener.prototype.handleElementResize = function () { | ||
@@ -275,59 +317,101 @@ if (!this.activeResizeHandle) { | ||
} | ||
var actions = []; | ||
var resizeElement = lib_1.findParentByFeature(this.activeResizeHandle, model_1.isResizeable); | ||
var resizeElement = lib_1.findParentByFeature(this.activeResizeHandle, model_1.isResizable); | ||
if (this.isActiveResizeElement(resizeElement)) { | ||
switch (this.activeResizeHandle.location) { | ||
case model_1.ResizeHandleLocation.TopLeft: | ||
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: | ||
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: | ||
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: | ||
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) { | ||
if (this.isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [new operation_actions_1.ChangeBoundsOperationAction([smodel_util_1.toElementAndBounds(element)])]; | ||
} | ||
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 []; | ||
}; | ||
ChangeBoundsListener.prototype.createElementAndBounds = function (element) { | ||
if (this.isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [smodel_util_1.toElementAndBounds(element)]; | ||
} | ||
return []; | ||
}; | ||
ChangeBoundsListener.prototype.createSetBoundsAction = function (element, x, y, width, height) { | ||
var newPosition = { x: x, y: y }; | ||
var newSize = { width: width, height: height }; | ||
var result = []; | ||
if (this.isValidBoundChange(element, newPosition, 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 }])); | ||
} | ||
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) { | ||
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) { | ||
var layoutOptions = this.getLayoutOptions(element); | ||
if (layoutOptions !== undefined && typeof layoutOptions.minWidth === 'number') { | ||
return layoutOptions.minWidth; | ||
} | ||
return 1; | ||
}; | ||
ChangeBoundsListener.prototype.minHeight = function (element) { | ||
var layoutOptions = this.getLayoutOptions(element); | ||
if (layoutOptions !== undefined && typeof layoutOptions.minHeight === 'number') { | ||
return layoutOptions.minHeight; | ||
} | ||
return 1; | ||
}; | ||
ChangeBoundsListener.prototype.getLayoutOptions = function (element) { | ||
var layoutOptions = element.layoutOptions; | ||
if (layoutOptions !== undefined) { | ||
return layoutOptions; | ||
} | ||
return undefined; | ||
}; | ||
return ChangeBoundsListener; | ||
}(lib_1.MouseListener)); | ||
function createChangeBoundsAction(element) { | ||
if (isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [new operation_actions_1.ChangeBoundsOperationAction([smodel_util_1.toElementAndBounds(element)])]; | ||
} | ||
return []; | ||
} | ||
function createElementAndBounds(element) { | ||
if (isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [smodel_util_1.toElementAndBounds(element)]; | ||
} | ||
return []; | ||
} | ||
function createSetBoundsAction(element, x, y, width, height) { | ||
var newPosition = { x: x, y: y }; | ||
var newSize = { width: width, height: height }; | ||
if (isValidBoundChange(element, newPosition, newSize)) { | ||
return [new lib_1.SetBoundsAction([{ elementId: element.id, newPosition: newPosition, newSize: newSize }])]; | ||
} | ||
return []; | ||
} | ||
function isValidBoundChange(element, newPosition, newSize) { | ||
return newSize.width >= minWidth(element) && newSize.height >= minHeight(element); | ||
} | ||
function minWidth(element) { | ||
// currently there are no element-specific constraints | ||
return 1; | ||
} | ||
function minHeight(element) { | ||
// currently there are no element-specific constraints | ||
return 1; | ||
} | ||
}(drag_aware_mouse_listener_1.DragAwareMouseListener)); | ||
exports.ChangeBoundsListener = ChangeBoundsListener; | ||
//# sourceMappingURL=change-bounds-tool.js.map |
@@ -1,4 +0,5 @@ | ||
import { Action, AnchorComputerRegistry, SModelElement, Tool } from "sprotty/lib"; | ||
import { EdgeEditConfig, IEditConfigProvider } from "../../base/edit-config/edit-config"; | ||
import { Action, AnchorComputerRegistry, SEdge, SModelElement, Tool } from "sprotty/lib"; | ||
import { TypeAware } from "../../base/tool-manager/tool-manager-action-handler"; | ||
import { Containable } from "../hints/model"; | ||
import { ITypeHintProvider } from "../hints/type-hints"; | ||
import { IMouseTool } from "../mouse-tool/mouse-tool"; | ||
@@ -24,5 +25,5 @@ import { FeedbackEdgeEndMovingMouseListener } from "../tool-feedback/creation-tool-feedback"; | ||
protected tool: NodeCreationTool; | ||
protected container?: SModelElement; | ||
protected container?: SModelElement & Containable; | ||
constructor(elementTypeId: string, tool: NodeCreationTool); | ||
protected creationAllowed(target: SModelElement): boolean | SModelElement; | ||
protected creationAllowed(elementTypeId: string): boolean | undefined; | ||
nonDraggingMouseUp(target: SModelElement, event: MouseEvent): Action[]; | ||
@@ -38,7 +39,7 @@ mouseOver(target: SModelElement, event: MouseEvent): Action[]; | ||
protected anchorRegistry: AnchorComputerRegistry; | ||
readonly editConfigProvider: IEditConfigProvider; | ||
readonly typeHintProvider: ITypeHintProvider; | ||
elementTypeId: string; | ||
protected creationToolMouseListener: EdgeCreationToolMouseListener; | ||
protected feedbackEndMovingMouseListener: FeedbackEdgeEndMovingMouseListener; | ||
constructor(mouseTool: IMouseTool, feedbackDispatcher: IFeedbackActionDispatcher, anchorRegistry: AnchorComputerRegistry, editConfigProvider: IEditConfigProvider); | ||
constructor(mouseTool: IMouseTool, feedbackDispatcher: IFeedbackActionDispatcher, anchorRegistry: AnchorComputerRegistry, typeHintProvider: ITypeHintProvider); | ||
readonly id: string; | ||
@@ -56,3 +57,3 @@ enable(): void; | ||
protected allowedTarget: boolean; | ||
protected edgeEditConfig?: EdgeEditConfig; | ||
protected proxyEdge: SEdge; | ||
constructor(elementTypeId: string, tool: EdgeCreationTool); | ||
@@ -59,0 +60,0 @@ protected reinitialize(): void; |
@@ -45,9 +45,9 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var edit_config_1 = require("../../base/edit-config/edit-config"); | ||
var types_1 = require("../../types"); | ||
var viewpoint_util_1 = require("../../utils/viewpoint-util"); | ||
var model_1 = require("../hints/model"); | ||
var operation_actions_1 = require("../operation/operation-actions"); | ||
var set_operations_1 = require("../operation/set-operations"); | ||
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()]); | ||
}; | ||
@@ -102,8 +102,8 @@ NodeCreationTool.prototype.dispatchFeedback = function (actions) { | ||
} | ||
NodeCreationToolMouseListener.prototype.creationAllowed = function (target) { | ||
return this.container || target instanceof lib_1.SModelRoot; | ||
NodeCreationToolMouseListener.prototype.creationAllowed = function (elementTypeId) { | ||
return this.container && this.container.isContainableElement(elementTypeId); | ||
}; | ||
NodeCreationToolMouseListener.prototype.nonDraggingMouseUp = function (target, event) { | ||
var result = []; | ||
if (this.creationAllowed(target)) { | ||
if (this.creationAllowed(this.elementTypeId)) { | ||
var containerId = this.container ? this.container.id : undefined; | ||
@@ -119,9 +119,8 @@ var location_1 = viewpoint_util_1.getAbsolutePosition(target, event); | ||
NodeCreationToolMouseListener.prototype.mouseOver = function (target, event) { | ||
var _this = this; | ||
var currentContainer = lib_1.findParent(target, function (e) { return edit_config_1.containmentAllowed(e, _this.elementTypeId); }); | ||
var currentContainer = lib_1.findParentByFeature(target, model_1.isContainable); | ||
if (!this.container || currentContainer !== this.container) { | ||
this.container = currentContainer; | ||
var feedback = this.creationAllowed(target) | ||
? new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.NODE_CREATION) : | ||
new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.OPERATION_NOT_ALLOWED); | ||
var feedback = this.creationAllowed(this.elementTypeId) | ||
? 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]); | ||
@@ -142,7 +141,7 @@ } | ||
var EdgeCreationTool = /** @class */ (function () { | ||
function EdgeCreationTool(mouseTool, feedbackDispatcher, anchorRegistry, editConfigProvider) { | ||
function EdgeCreationTool(mouseTool, feedbackDispatcher, anchorRegistry, typeHintProvider) { | ||
this.mouseTool = mouseTool; | ||
this.feedbackDispatcher = feedbackDispatcher; | ||
this.anchorRegistry = anchorRegistry; | ||
this.editConfigProvider = editConfigProvider; | ||
this.typeHintProvider = typeHintProvider; | ||
this.elementTypeId = "unknown"; | ||
@@ -162,3 +161,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)]); | ||
}; | ||
@@ -168,3 +167,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()]); | ||
}; | ||
@@ -179,3 +178,3 @@ EdgeCreationTool.prototype.dispatchFeedback = function (actions) { | ||
__param(2, inversify_1.inject(lib_1.AnchorComputerRegistry)), | ||
__param(3, inversify_1.inject(types_1.GLSP_TYPES.IEditConfigProvider)), | ||
__param(3, inversify_1.inject(types_1.GLSP_TYPES.ITypeHintProvider)), | ||
__metadata("design:paramtypes", [Object, Object, lib_1.AnchorComputerRegistry, Object]) | ||
@@ -193,6 +192,4 @@ ], EdgeCreationTool); | ||
_this.allowedTarget = false; | ||
var config = tool.editConfigProvider.getEditConfig(_this.elementTypeId); | ||
if (config && config.configType === edit_config_1.edgeEditConfig) { | ||
_this.edgeEditConfig = config; | ||
} | ||
_this.proxyEdge = new lib_1.SEdge(); | ||
_this.proxyEdge.type = elementTypeId; | ||
return _this; | ||
@@ -254,8 +251,8 @@ } | ||
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)]; | ||
} | ||
@@ -265,6 +262,6 @@ return []; | ||
EdgeCreationToolMouseListener.prototype.isAllowedSource = function (element) { | ||
return element !== undefined && this.edgeEditConfig ? this.edgeEditConfig.isAllowedSource(element) : false; | ||
return element !== undefined && lib_1.isConnectable(element) && element.canConnect(this.proxyEdge, "source"); | ||
}; | ||
EdgeCreationToolMouseListener.prototype.isAllowedTarget = function (element) { | ||
return element !== undefined && this.edgeEditConfig ? this.edgeEditConfig.isAllowedTarget(element) : false; | ||
return element !== undefined && lib_1.isConnectable(element) && element.canConnect(this.proxyEdge, "target"); | ||
}; | ||
@@ -271,0 +268,0 @@ EdgeCreationToolMouseListener = __decorate([ |
@@ -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"); | ||
/** | ||
@@ -83,3 +83,3 @@ * Deletes selected elements when hitting the `Del` key. | ||
if (keyboard_1.matchesKeystroke(event, 'Delete')) { | ||
var deleteElementIds = Array.from(element.root.index.all().filter(function (e) { return lib_1.isSelectable(e) && e.selected; }) | ||
var deleteElementIds = Array.from(element.root.index.all().filter(function (e) { return lib_1.isDeletable(e) && lib_1.isSelectable(e) && e.selected; }) | ||
.filter(function (e) { return e.id !== e.root.id; }).map(function (e) { return e.id; })); | ||
@@ -109,7 +109,7 @@ return [new operation_actions_1.DeleteElementOperationAction(deleteElementIds)]; | ||
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()]); | ||
}; | ||
@@ -133,3 +133,3 @@ var MouseDeleteTool_1; | ||
DeleteToolMouseListener.prototype.mouseUp = function (target, event) { | ||
if (target instanceof lib_1.SModelRoot) { | ||
if (!lib_1.isDeletable(target)) { | ||
return []; | ||
@@ -136,0 +136,0 @@ } |
@@ -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)); |
@@ -76,10 +76,9 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var edit_config_1 = require("../../base/edit-config/edit-config"); | ||
var types_1 = require("../../types"); | ||
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"); | ||
@@ -142,3 +141,3 @@ var EdgeEditTool = /** @class */ (function () { | ||
ReconnectEdgeListener.prototype.isValidEdge = function (edge) { | ||
return edge !== undefined && edge.id !== creation_tool_feedback_1.feedbackEdgeId(edge.root) && smodel_util_1.isSelected(edge); | ||
return edge !== undefined && edge.id !== creation_tool_feedback_1.feedbackEdgeId(edge.root) && lib_1.isSelected(edge); | ||
}; | ||
@@ -152,6 +151,13 @@ ReconnectEdgeListener.prototype.setEdgeSelected = function (edge) { | ||
// note: order is important here as we want the reconnect handles to cover the routing handles | ||
this.tool.dispatchFeedback([new edge_edit_tool_feedback_1.SwitchRoutingModeAction([this.edge.id], []), new edge_edit_tool_feedback_1.ShowEdgeReconnectHandlesFeedbackAction(this.edge.id)]); | ||
var feedbackActions = []; | ||
if (lib_1.canEditRouting(edge)) { | ||
feedbackActions.push(new edge_edit_tool_feedback_1.SwitchRoutingModeAction([this.edge.id], [])); | ||
} | ||
if (model_1.isReconnectable(edge)) { | ||
feedbackActions.push(new edge_edit_tool_feedback_1.ShowEdgeReconnectHandlesFeedbackAction(this.edge.id)); | ||
} | ||
this.tool.dispatchFeedback(feedbackActions); | ||
}; | ||
ReconnectEdgeListener.prototype.isEdgeSelected = function () { | ||
return this.edge !== undefined && smodel_util_1.isSelected(this.edge); | ||
return this.edge !== undefined && lib_1.isSelected(this.edge); | ||
}; | ||
@@ -162,3 +168,3 @@ ReconnectEdgeListener.prototype.setReconnectHandleSelected = function (edge, reconnectHandle) { | ||
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)]); | ||
@@ -169,3 +175,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)]); | ||
@@ -204,4 +210,4 @@ this.reconnectMode = "NEW_TARGET"; | ||
var reconnectHandle = lib_1.findParentByFeature(target, model_1.isReconnectHandle); | ||
var routingHandle = !reconnectHandle ? lib_1.findParentByFeature(target, model_1.isRoutingHandle) : undefined; | ||
var edge = lib_1.findParentByFeature(target, model_1.isRoutable); | ||
var routingHandle = !reconnectHandle ? lib_1.findParentByFeature(target, smodel_util_1.isRoutingHandle) : undefined; | ||
var edge = lib_1.findParentByFeature(target, smodel_util_1.isRoutable); | ||
if (this.isEdgeSelected() && edge && reconnectHandle) { | ||
@@ -242,3 +248,3 @@ // PHASE 2 Reconnect: Select reconnect handle on selected edge | ||
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)); | ||
} | ||
@@ -250,4 +256,4 @@ this.reset(); | ||
var latestEdge = target.index.getById(this.edge.id); | ||
if (latestEdge && model_1.isRoutable(latestEdge)) { | ||
result.push(new action_definitions_1.RerouteConnectionOperationAction(latestEdge.id, latestEdge.routingPoints)); | ||
if (latestEdge && smodel_util_1.isRoutable(latestEdge)) { | ||
result.push(new operation_actions_1.ChangeRoutingPointsOperation([{ elementId: latestEdge.id, newRoutingPoints: latestEdge.routingPoints }])); | ||
this.routingHandle = undefined; | ||
@@ -263,10 +269,10 @@ } | ||
this.setNewConnectable(currentTarget); | ||
if (currentTarget && edit_config_1.isConfigurableEdge(this.edge)) { | ||
if ((this.reconnectMode === 'NEW_SOURCE' && this.edge.isAllowedSource(currentTarget.type)) || | ||
(this.reconnectMode === 'NEW_TARGET' && this.edge.isAllowedTarget(currentTarget.type))) { | ||
this.tool.dispatchFeedback([new cursor_feedback_1.ApplyCursorCSSFeedbackAction(cursor_feedback_1.CursorCSS.EDGE_RECONNECT)]); | ||
if (currentTarget) { | ||
if ((this.reconnectMode === 'NEW_SOURCE' && currentTarget.canConnect(this.edge, "source")) || | ||
(this.reconnectMode === 'NEW_TARGET' && currentTarget.canConnect(this.edge, "target"))) { | ||
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)]); | ||
} | ||
@@ -293,3 +299,3 @@ } | ||
if (element) { | ||
var edge = lib_1.findParentByFeature(element, model_1.isRoutable); | ||
var edge = lib_1.findParentByFeature(element, smodel_util_1.isRoutable); | ||
if (this.isValidEdge(edge)) { | ||
@@ -330,3 +336,3 @@ // PHASE 1: Select edge | ||
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); | ||
@@ -333,0 +339,0 @@ }; |
@@ -18,2 +18,4 @@ /******************************************************************************** | ||
import glspCommandPaletteModule from "./features/command-palette/di.config"; | ||
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"; | ||
@@ -31,24 +33,35 @@ import executeModule from "./features/execute/di.config"; | ||
export * from 'sprotty/lib'; | ||
export * from './base/edit-config/edit-config'; | ||
export * from './model-source/websocket-diagram-server'; | ||
export * from './base/model/update-model-command'; | ||
export * from './base/tool-manager/tool-manager-action-handler'; | ||
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/command-palette/action-definitions'; | ||
export * from './features/command-palette/action-provider'; | ||
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'; | ||
export * from './features/execute/execute-command'; | ||
export * from './features/execute/model'; | ||
export * from './features/hints/action-definition'; | ||
export * from './features/hints/type-hints-action-initializer'; | ||
export * from './features/mouse-tool/di.config'; | ||
export * from './features/hints/request-type-hints-action'; | ||
export * from './features/hints/type-hints'; | ||
export * from './features/hints/model'; | ||
export * from './features/layout/layout-commands'; | ||
export * from './features/mouse-tool/mouse-tool'; | ||
export * from './features/operation/operation-actions'; | ||
export * from './features/operation/set-operations'; | ||
export * from './features/request-response/action-definitions'; | ||
export * from './features/request-response/support'; | ||
export * from './features/rank/model'; | ||
export * from './features/reconnect/model'; | ||
export * from './features/request-response/glsp-action-dispatcher'; | ||
export * from './features/save/model'; | ||
export * from './features/save/save'; | ||
export * from './features/select/di.config'; | ||
export * from './features/tool-feedback/change-bounds-tool-feedback'; | ||
export * from './features/tool-feedback/creation-tool-feedback'; | ||
export * from './features/tool-feedback/css-feedback'; | ||
export * from './features/tool-feedback/edge-edit-tool-feedback'; | ||
export * from './features/tool-feedback/feedback-action-dispatcher'; | ||
export * from './features/tool-feedback/model'; | ||
export * from './features/tool-feedback/model'; | ||
export * from './features/tool-palette/tool-palette'; | ||
@@ -59,5 +72,6 @@ export * from './features/tools/change-bounds-tool'; | ||
export * from './features/tools/delete-tool'; | ||
export * from './features/tools/drag-aware-mouse-listener'; | ||
export * from './features/tools/edge-edit-tool'; | ||
export * from './features/undo-redo/model'; | ||
export * from './features/validation/validate'; | ||
export * from './features/layout/layout-commands'; | ||
export * from './lib/model'; | ||
@@ -69,5 +83,6 @@ export * from './types'; | ||
export * from './utils/viewpoint-util'; | ||
export * from './model-source/websocket-diagram-server'; | ||
export * from "./model-source/glsp-server-status"; | ||
export { validationModule, saveModule, executeModule, paletteModule, toolFeedbackModule, defaultGLSPModule, modelHintsModule, glspCommandPaletteModule, requestResponseModule, // | ||
glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule }; | ||
glspContextMenuModule, glspServerCopyPasteModule, glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule }; | ||
//# sourceMappingURL=index.d.ts.map |
@@ -25,47 +25,62 @@ "use strict"; | ||
exports.glspCommandPaletteModule = di_config_2.default; | ||
var di_config_3 = require("./features/edit-label-validation/di.config"); | ||
exports.glspEditLabelValidationModule = di_config_3.default; | ||
var di_config_4 = require("./features/execute/di.config"); | ||
exports.executeModule = di_config_4.default; | ||
var di_config_5 = require("./features/hints/di.config"); | ||
exports.modelHintsModule = di_config_5.default; | ||
var di_config_6 = require("./features/layout/di.config"); | ||
exports.layoutCommandsModule = di_config_6.default; | ||
var di_config_7 = require("./features/mouse-tool/di.config"); | ||
exports.glspMouseToolModule = di_config_7.default; | ||
var di_config_8 = require("./features/request-response/di.config"); | ||
exports.requestResponseModule = di_config_8.default; | ||
var di_config_9 = require("./features/save/di.config"); | ||
exports.saveModule = di_config_9.default; | ||
var di_config_10 = require("./features/select/di.config"); | ||
exports.glspSelectModule = di_config_10.default; | ||
var di_config_11 = require("./features/tool-feedback/di.config"); | ||
exports.toolFeedbackModule = di_config_11.default; | ||
var di_config_12 = require("./features/tool-palette/di.config"); | ||
exports.paletteModule = di_config_12.default; | ||
var di_config_13 = require("./features/validation/di.config"); | ||
exports.validationModule = di_config_13.default; | ||
var di_config_3 = require("./features/context-menu/di.config"); | ||
exports.glspContextMenuModule = di_config_3.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")); | ||
__export(require("./base/edit-config/edit-config")); | ||
__export(require("./model-source/websocket-diagram-server")); | ||
__export(require("./base/model/update-model-command")); | ||
__export(require("./base/tool-manager/tool-manager-action-handler")); | ||
__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/command-palette/action-definitions")); | ||
__export(require("./features/command-palette/action-provider")); | ||
__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")); | ||
__export(require("./features/execute/execute-command")); | ||
__export(require("./features/execute/model")); | ||
__export(require("./features/hints/action-definition")); | ||
__export(require("./features/hints/type-hints-action-initializer")); | ||
__export(require("./features/mouse-tool/di.config")); | ||
__export(require("./features/hints/request-type-hints-action")); | ||
__export(require("./features/hints/type-hints")); | ||
__export(require("./features/hints/model")); | ||
__export(require("./features/layout/layout-commands")); | ||
__export(require("./features/mouse-tool/mouse-tool")); | ||
__export(require("./features/operation/operation-actions")); | ||
__export(require("./features/operation/set-operations")); | ||
__export(require("./features/request-response/action-definitions")); | ||
__export(require("./features/request-response/support")); | ||
__export(require("./features/rank/model")); | ||
__export(require("./features/reconnect/model")); | ||
__export(require("./features/request-response/glsp-action-dispatcher")); | ||
__export(require("./features/save/model")); | ||
__export(require("./features/save/save")); | ||
__export(require("./features/select/di.config")); | ||
__export(require("./features/tool-feedback/change-bounds-tool-feedback")); | ||
__export(require("./features/tool-feedback/creation-tool-feedback")); | ||
__export(require("./features/tool-feedback/css-feedback")); | ||
__export(require("./features/tool-feedback/edge-edit-tool-feedback")); | ||
__export(require("./features/tool-feedback/feedback-action-dispatcher")); | ||
__export(require("./features/tool-feedback/model")); | ||
__export(require("./features/tool-feedback/model")); | ||
__export(require("./features/tool-palette/tool-palette")); | ||
@@ -76,5 +91,6 @@ __export(require("./features/tools/change-bounds-tool")); | ||
__export(require("./features/tools/delete-tool")); | ||
__export(require("./features/tools/drag-aware-mouse-listener")); | ||
__export(require("./features/tools/edge-edit-tool")); | ||
__export(require("./features/undo-redo/model")); | ||
__export(require("./features/validation/validate")); | ||
__export(require("./features/layout/layout-commands")); | ||
__export(require("./lib/model")); | ||
@@ -86,3 +102,4 @@ __export(require("./types")); | ||
__export(require("./utils/viewpoint-util")); | ||
__export(require("./model-source/websocket-diagram-server")); | ||
__export(require("./model-source/glsp-server-status")); | ||
//# sourceMappingURL=index.js.map |
@@ -16,8 +16,10 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { SGraph } from "sprotty/lib"; | ||
import { SGraph, SModelElement, SModelElementSchema } from "sprotty/lib"; | ||
import { Containable } from "../features/hints/model"; | ||
import { Saveable } from "../features/save/model"; | ||
export declare class GLSPGraph extends SGraph implements Saveable { | ||
export declare class GLSPGraph extends SGraph implements Saveable, Containable { | ||
static readonly DEFAULT_FEATURES: symbol[]; | ||
dirty: boolean; | ||
hasFeature(feature: symbol): boolean; | ||
isContainableElement(input: string | SModelElement | SModelElementSchema): boolean; | ||
} | ||
//# sourceMappingURL=model.d.ts.map |
@@ -32,11 +32,15 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var model_1 = require("../features/save/model"); | ||
var model_1 = require("../features/hints/model"); | ||
var model_2 = require("../features/save/model"); | ||
var GLSPGraph = /** @class */ (function (_super) { | ||
__extends(GLSPGraph, _super); | ||
function GLSPGraph() { | ||
return _super !== null && _super.apply(this, arguments) || this; | ||
var _this = _super !== null && _super.apply(this, arguments) || this; | ||
_this.dirty = false; | ||
return _this; | ||
} | ||
GLSPGraph.prototype.hasFeature = function (feature) { | ||
return feature === model_1.saveFeature || _super.prototype.hasFeature.call(this, feature); | ||
GLSPGraph.prototype.isContainableElement = function (input) { | ||
return true; | ||
}; | ||
GLSPGraph.DEFAULT_FEATURES = [lib_1.viewportFeature, lib_1.exportFeature, model_2.saveFeature, model_1.containerFeature]; | ||
return GLSPGraph; | ||
@@ -43,0 +47,0 @@ }(lib_1.SGraph)); |
@@ -41,10 +41,11 @@ "use strict"; | ||
var vscode_ws_jsonrpc_1 = require("vscode-ws-jsonrpc"); | ||
var action_definitions_1 = require("../features/command-palette/action-definitions"); | ||
var action_definitions_1 = require("../features/context-actions/action-definitions"); | ||
var execute_command_1 = require("../features/execute/execute-command"); | ||
var action_definition_1 = require("../features/hints/action-definition"); | ||
var request_type_hints_action_1 = require("../features/hints/request-type-hints-action"); | ||
var set_operations_1 = require("../features/operation/set-operations"); | ||
var action_definitions_2 = require("../features/request-response/action-definitions"); | ||
var save_1 = require("../features/save/save"); | ||
var model_1 = require("../features/undo-redo/model"); | ||
var validate_1 = require("../features/validation/validate"); | ||
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); | ||
@@ -108,3 +109,3 @@ registry.register(set_operations_1.OperationKind.CHANGE_BOUNDS, diagramServer); | ||
registry.register(execute_command_1.ExecuteServerCommandAction.KIND, diagramServer); | ||
registry.register(action_definition_1.RequestTypeHintsAction.KIND, diagramServer); | ||
registry.register(request_type_hints_action_1.RequestTypeHintsAction.KIND, diagramServer); | ||
registry.register(sprotty_1.ComputedBoundsAction.KIND, diagramServer); | ||
@@ -119,7 +120,10 @@ registry.register(sprotty_1.RequestBoundsCommand.KIND, diagramServer); | ||
registry.register(sprotty_1.ExportSvgAction.KIND, diagramServer); | ||
registry.register(action_definitions_1.RequestCommandPaletteActions.KIND, diagramServer); | ||
registry.register(action_definitions_2.IdentifiableRequestAction.KIND, diagramServer); | ||
registry.register(action_definitions_1.RequestContextActions.KIND, diagramServer); | ||
registry.register(edit_label_validator_1.ValidateLabelEditAction.KIND, diagramServer); | ||
registry.register(validate_1.RequestMarkersAction.KIND, diagramServer); | ||
registry.register(sprotty_1.LayoutAction.KIND, 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. | ||
@@ -126,0 +130,0 @@ // We don't want to support SwitchEditMode, but sprotty still sends some corresponding |
@@ -20,5 +20,4 @@ /******************************************************************************** | ||
IToolFactory: symbol; | ||
IEditConfigProvider: symbol; | ||
ITypeHintProvider: symbol; | ||
IMovementRestrictor: symbol; | ||
RequestResponseSupport: symbol; | ||
SelectionService: symbol; | ||
@@ -28,3 +27,8 @@ SelectionListener: symbol; | ||
MouseTool: symbol; | ||
IContextMenuService: symbol; | ||
IContextMenuServiceProvider: symbol; | ||
IContextMenuProviderRegistry: symbol; | ||
IContextMenuProvider: symbol; | ||
ICopyPasteHandler: symbol; | ||
}; | ||
//# sourceMappingURL=types.d.ts.map |
@@ -22,10 +22,14 @@ "use strict"; | ||
IToolFactory: Symbol.for("Factory<Tool>"), | ||
IEditConfigProvider: Symbol.for("IEditConfigProvider"), | ||
ITypeHintProvider: Symbol.for("ITypeHintProvider"), | ||
IMovementRestrictor: Symbol.for("IMovmementRestrictor"), | ||
RequestResponseSupport: Symbol.for("RequestResponseSupport"), | ||
SelectionService: Symbol.for("SelectionService"), | ||
SelectionListener: Symbol.for("SelectionListener"), | ||
SModelRootListener: Symbol.for("SModelRootListener"), | ||
MouseTool: Symbol.for("MouseTool") | ||
MouseTool: Symbol.for("MouseTool"), | ||
IContextMenuService: Symbol.for("IContextMenuService"), | ||
IContextMenuServiceProvider: Symbol.for("IContextMenuServiceProvider"), | ||
IContextMenuProviderRegistry: Symbol.for("IContextMenuProviderRegistry"), | ||
IContextMenuProvider: Symbol.for("IContextMenuProvider"), | ||
ICopyPasteHandler: Symbol.for("ICopyPasteHandler") | ||
}; | ||
//# sourceMappingURL=types.js.map |
@@ -16,5 +16,4 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
export declare function contains<T>(array: T[], value: T): boolean; | ||
export declare function remove<T>(array: T[], value: T): boolean; | ||
export declare function distinctAdd<T>(array: T[], value: T): boolean; | ||
//# sourceMappingURL=array-utils.d.ts.map |
@@ -18,8 +18,2 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function contains(array, value) { | ||
if (value === undefined) | ||
return false; | ||
return array.indexOf(value) >= 0; | ||
} | ||
exports.contains = contains; | ||
function remove(array, value) { | ||
@@ -35,3 +29,3 @@ var index = array.indexOf(value); | ||
function distinctAdd(array, value) { | ||
if (!contains(array, value)) { | ||
if (!array.includes(value)) { | ||
array.push(value); | ||
@@ -38,0 +32,0 @@ return true; |
@@ -16,4 +16,4 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { BoundsAware, Selectable, SModelElement, SParentElement } from "sprotty/lib"; | ||
import { NodeEditConfig } from "../base/edit-config/edit-config"; | ||
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>; | ||
@@ -24,8 +24,9 @@ export declare function forEachElement<T>(element: SModelElement, predicate: (element: SModelElement) => element is SModelElement & T, runnable: (element: SModelElement & T) => void): void; | ||
export declare function getSelectedElementCount(element: SModelElement): number; | ||
export declare function isSelected(element: SModelElement | undefined): element is SModelElement & Selectable; | ||
export declare function isNotUndefined<T>(element: T | undefined): element is T; | ||
export declare function addCssClasses(root: SModelElement, cssClasses: string[]): void; | ||
export declare function removeCssClasses(root: SModelElement, cssClasses: string[]): void; | ||
export declare function isContainmentAllowed(element: SModelElement, containableElementTypeId: string): element is SParentElement & NodeEditConfig; | ||
export declare function isNonRoutableSelectedMovableBoundsAware(element: SModelElement): element is SelectableBoundsAware; | ||
export declare function isNonRoutableSelectedBoundsAware(element: SModelElement): element is SelectableBoundsAware; | ||
export declare function isRoutable<T extends SModelElement>(element: T): element is T & SRoutableElement; | ||
export declare function isRoutingHandle(element: SModelElement | undefined): element is SRoutingHandle; | ||
export declare type SelectableBoundsAware = SModelElement & BoundsAware & Selectable; | ||
@@ -43,2 +44,3 @@ export declare function toElementAndBounds(element: SModelElement & BoundsAware): { | ||
}; | ||
export declare function toElementAndRoutingPoints(element: SRoutableElement): ElementAndRoutingPoints; | ||
//# sourceMappingURL=smodel-util.d.ts.map |
@@ -30,4 +30,2 @@ "use strict"; | ||
var lib_1 = require("sprotty/lib"); | ||
var edit_config_1 = require("../base/edit-config/edit-config"); | ||
var model_1 = require("../features/reconnect/model"); | ||
function getIndex(element) { | ||
@@ -56,3 +54,3 @@ return element.root.index; | ||
getIndex(element).all() | ||
.filter(isSelected) | ||
.filter(lib_1.isSelected) | ||
.forEach(function (e) { return selected = selected + 1; }); | ||
@@ -62,6 +60,2 @@ return selected; | ||
exports.getSelectedElementCount = getSelectedElementCount; | ||
function isSelected(element) { | ||
return isNotUndefined(element) && lib_1.isSelectable(element) && element.selected; | ||
} | ||
exports.isSelected = isSelected; | ||
function isNotUndefined(element) { | ||
@@ -116,10 +110,18 @@ return element !== undefined; | ||
exports.removeCssClasses = removeCssClasses; | ||
function isContainmentAllowed(element, containableElementTypeId) { | ||
return edit_config_1.isConfigurableNode(element) && element.isContainableElement(containableElementTypeId); | ||
function isNonRoutableSelectedMovableBoundsAware(element) { | ||
return isNonRoutableSelectedBoundsAware(element) && lib_1.isMoveable(element); | ||
} | ||
exports.isContainmentAllowed = isContainmentAllowed; | ||
exports.isNonRoutableSelectedMovableBoundsAware = isNonRoutableSelectedMovableBoundsAware; | ||
function isNonRoutableSelectedBoundsAware(element) { | ||
return lib_1.isBoundsAware(element) && isSelected(element) && !model_1.isRoutable(element); | ||
return lib_1.isBoundsAware(element) && lib_1.isSelected(element) && !isRoutable(element); | ||
} | ||
exports.isNonRoutableSelectedBoundsAware = isNonRoutableSelectedBoundsAware; | ||
function isRoutable(element) { | ||
return element instanceof lib_1.SRoutableElement && element.routingPoints !== undefined; | ||
} | ||
exports.isRoutable = isRoutable; | ||
function isRoutingHandle(element) { | ||
return element !== undefined && element instanceof lib_1.SRoutingHandle; | ||
} | ||
exports.isRoutingHandle = isRoutingHandle; | ||
function toElementAndBounds(element) { | ||
@@ -139,2 +141,9 @@ return { | ||
exports.toElementAndBounds = toElementAndBounds; | ||
function toElementAndRoutingPoints(element) { | ||
return { | ||
elementId: element.id, | ||
newRoutingPoints: element.routingPoints | ||
}; | ||
} | ||
exports.toElementAndRoutingPoints = toElementAndRoutingPoints; | ||
//# sourceMappingURL=smodel-util.js.map |
@@ -16,4 +16,3 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Point } from "sprotty/lib"; | ||
import { SModelElement } from "sprotty/lib"; | ||
import { Bounds, BoundsAware, Dimension, Point, SModelElement } from "sprotty/lib"; | ||
/** | ||
@@ -33,2 +32,23 @@ * Return the position corresponding to this mouse event (Browser coordinates) | ||
export declare function getAbsolutePosition(target: SModelElement, mouseEvent: MouseEvent): Point; | ||
/** | ||
* Translates the bounds of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
export declare function toAbsoluteBounds(element: SModelElement & BoundsAware): Bounds; | ||
/** | ||
* Translates the position of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
export declare function toAbsolutePosition(target: SModelElement & BoundsAware): Point; | ||
/** | ||
* Translates the size of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
export declare function toAbsoluteSize(target: SModelElement & BoundsAware): Dimension; | ||
//# sourceMappingURL=viewpoint-util.d.ts.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/******************************************************************************** | ||
* Copyright (c) 2019 EclipseSource and others. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the Eclipse | ||
* Public License v. 2.0 are satisfied: GNU General Public License, version 2 | ||
* with the GNU Classpath Exception which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
********************************************************************************/ | ||
var lib_1 = require("sprotty/lib"); | ||
var lib_2 = require("sprotty/lib"); | ||
/** | ||
@@ -23,3 +37,3 @@ * Return the position corresponding to this mouse event (Browser coordinates) | ||
yPos -= canvasBounds.y; | ||
var viewport = lib_1.findParentByFeature(target, lib_2.isViewport); | ||
var viewport = lib_1.findParentByFeature(target, lib_1.isViewport); | ||
var zoom = viewport ? viewport.zoom : 1; | ||
@@ -40,2 +54,37 @@ if (viewport) { | ||
exports.getAbsolutePosition = getAbsolutePosition; | ||
/** | ||
* Translates the bounds of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
function toAbsoluteBounds(element) { | ||
var location = lib_1.isAlignable(element) ? element.alignment : lib_1.ORIGIN_POINT; | ||
var x = location.x; | ||
var y = location.y; | ||
var width = element.bounds.width; | ||
var height = element.bounds.height; | ||
return lib_1.translateBounds({ x: x, y: y, width: width, height: height }, element, element.root); | ||
} | ||
exports.toAbsoluteBounds = toAbsoluteBounds; | ||
/** | ||
* Translates the position of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
function toAbsolutePosition(target) { | ||
return toAbsoluteBounds(target); | ||
} | ||
exports.toAbsolutePosition = toAbsolutePosition; | ||
/** | ||
* Translates the size of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
function toAbsoluteSize(target) { | ||
return toAbsoluteBounds(target); | ||
} | ||
exports.toAbsoluteSize = toAbsoluteSize; | ||
//# sourceMappingURL=viewpoint-util.js.map |
{ | ||
"name": "@eclipse-glsp/client", | ||
"version": "0.8.0-next.ca58207", | ||
"version": "0.8.0-next.db93ed9", | ||
"description": "A sprotty-based client for GLSP", | ||
@@ -36,5 +36,13 @@ "license": "(EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0)", | ||
"devDependencies": { | ||
"@types/chai": "4.1.3", | ||
"@types/mocha": "^5.2.7", | ||
"@types/node": "10.14.18", | ||
"@types/uuid": "3.4.5", | ||
"chai": "^4.2.0", | ||
"jenkins-mocha": "^8.0.0", | ||
"mocha": "^6.2.0", | ||
"reflect-metadata": "^0.1.13", | ||
"rimraf": "^2.6.1", | ||
"semver": "6.3.0", | ||
"ts-node": "^8.3.0", | ||
"tslint": "^5.5.0", | ||
@@ -49,2 +57,3 @@ "typescript": "3.6.4" | ||
"watch": "tsc -w", | ||
"test": "jenkins-mocha --opts ./configs/mocha.opts \"./src/**/*.spec.?(ts|tsx)\"", | ||
"publish:latest": "yarn publish --tag latest", | ||
@@ -51,0 +60,0 @@ "publish:next": "yarn publish --new-version \"$(semver $npm_package_version -i minor)-next.$(git rev-parse --short HEAD)\" --tag next" |
@@ -1,3 +0,9 @@ | ||
# Eclipse GLSP - Client | ||
# 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) | ||
This package contains a client for the [Graphical Language Server Protocol (GLSP)](https://github.com/eclipse-glsp/glsp) based on [Eclipse Sprotty](https://github.com/eclipse/sprotty). | ||
A web-based diagram client framework for the [Graphical Language Server Protocol (GLSP)](https://github.com/eclipse-glsp/glsp) based on [Eclipse Sprotty](https://github.com/eclipse/sprotty). | ||
This project is built with `yarn` and is available from npm via [@eclipse-glsp/client](https://www.npmjs.com/package/@eclipse-glsp/client). | ||
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"; | ||
@@ -47,4 +47,2 @@ import { GLSP_TYPES } from "../../types"; | ||
} | ||
handledActionKinds = [SetModelCommand.KIND]; | ||
} | ||
@@ -67,12 +65,14 @@ | ||
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` | ||
@@ -88,10 +88,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); | ||
} | ||
@@ -98,0 +97,0 @@ |
@@ -27,8 +27,14 @@ /******************************************************************************** | ||
SModelElement, | ||
SNode, | ||
SParentElement | ||
} from "sprotty/lib"; | ||
import { isConfigurableNode, NodeEditConfig } from "../../base/edit-config/edit-config"; | ||
export const resizeFeature = Symbol("resizeFeature"); | ||
export interface Resizable extends BoundsAware, Selectable { | ||
} | ||
export function isResizable(element: SModelElement): element is SParentElement & Resizable { | ||
return isBoundsAware(element) && isSelectable(element) && element instanceof SParentElement && element.hasFeature(resizeFeature); | ||
} | ||
export enum ResizeHandleLocation { | ||
@@ -41,6 +47,2 @@ TopLeft = "top-left", | ||
export function isResizeable(element: SModelElement): element is SNode & SParentElement & BoundsAware & Selectable & NodeEditConfig { | ||
return isConfigurableNode(element) && element.resizable && isBoundsAware(element) && isSelectable(element) && element instanceof SParentElement; | ||
} | ||
export function isBoundsAwareMoveable(element: SModelElement): element is SModelElement & Locateable & BoundsAware { | ||
@@ -47,0 +49,0 @@ return isMoveable(element) && isBoundsAware(element); |
@@ -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); | ||
} | ||
@@ -21,7 +21,5 @@ /******************************************************************************** | ||
import { NavigationCommandPaletteActionProvider, ServerCommandPaletteActionProvider } from "./action-provider"; | ||
import { ServerCommandPaletteActionProvider } from "./server-command-palette-provider"; | ||
const glspCommandPaletteModule = new ContainerModule((bind, unbind, isBound, rebind) => { | ||
bind(TYPES.ICommandPaletteActionProvider).to(NavigationCommandPaletteActionProvider); | ||
bind(ServerCommandPaletteActionProvider).toSelf().inSingletonScope(); | ||
const glspCommandPaletteModule = new ContainerModule((bind) => { | ||
bind(TYPES.ICommandPaletteActionProvider).to(ServerCommandPaletteActionProvider); | ||
@@ -28,0 +26,0 @@ }); |
@@ -21,21 +21,29 @@ /******************************************************************************** | ||
EditLabelValidationResult, | ||
generateRequestId, | ||
IEditLabelValidationDecorator, | ||
IEditLabelValidator, | ||
RequestAction, | ||
ResponseAction, | ||
Severity, | ||
SModelElement | ||
SModelElement, | ||
TYPES | ||
} from "sprotty"; | ||
import { GLSP_TYPES } from "../../types"; | ||
import { RequestResponseSupport } from "../request-response/support"; | ||
import { GLSPActionDispatcher } from "../request-response/glsp-action-dispatcher"; | ||
export class ValidateLabelEditAction implements Action { | ||
export class ValidateLabelEditAction implements RequestAction<SetLabelEditValidationResultAction> { | ||
static readonly KIND = "validateLabelEdit"; | ||
kind = ValidateLabelEditAction.KIND; | ||
constructor(public readonly value: string, public readonly labelId: string) { } | ||
constructor( | ||
public readonly value: string, | ||
public readonly labelId: string, | ||
public readonly requestId: string = generateRequestId()) { } | ||
} | ||
export class SetLabelEditValidationResultAction implements Action { | ||
export class SetLabelEditValidationResultAction implements ResponseAction { | ||
static readonly KIND = "setLabelEditValidationResult"; | ||
kind = SetLabelEditValidationResultAction.KIND; | ||
constructor(public readonly result: EditLabelValidationResult) { } | ||
constructor( | ||
public readonly result: EditLabelValidationResult, | ||
public readonly responseId: string = '') { } | ||
} | ||
@@ -51,7 +59,7 @@ | ||
@inject(GLSP_TYPES.RequestResponseSupport) protected requestResponseSupport: RequestResponseSupport; | ||
@inject(TYPES.IActionDispatcher) protected actionDispatcher: GLSPActionDispatcher; | ||
validate(value: string, label: EditableLabel & SModelElement): Promise<EditLabelValidationResult> { | ||
const action = new ValidateLabelEditAction(value, label.id); | ||
return this.requestResponseSupport.dispatchRequest(action, this.getValidationResultFromResponse); | ||
return this.actionDispatcher.requestUntil(action).then(response => this.getValidationResultFromResponse(response)); | ||
} | ||
@@ -58,0 +66,0 @@ |
@@ -20,12 +20,12 @@ /******************************************************************************** | ||
import { GLSP_TYPES } from "../../types"; | ||
import { SetTypeHintsAction } from "./action-definition"; | ||
import { ApplyEditConfigCommand, TypeHintsEditConfigProvider } from "./type-hints-action-initializer"; | ||
import { SetTypeHintsAction } from "./request-type-hints-action"; | ||
import { ApplyTypeHintsCommand, TypeHintProvider } from "./type-hints"; | ||
const modelHintsModule = new ContainerModule((bind, _unbind, isBound) => { | ||
bind(TypeHintsEditConfigProvider).toSelf().inSingletonScope(); | ||
configureActionHandler({ bind, isBound }, SetTypeHintsAction.KIND, TypeHintsEditConfigProvider); | ||
bind(GLSP_TYPES.IEditConfigProvider).toService(TypeHintsEditConfigProvider); | ||
configureCommand({ bind, isBound }, ApplyEditConfigCommand); | ||
bind(TypeHintProvider).toSelf().inSingletonScope(); | ||
bind(GLSP_TYPES.ITypeHintProvider).toService(TypeHintProvider); | ||
configureActionHandler({ bind, isBound }, SetTypeHintsAction.KIND, TypeHintProvider); | ||
configureCommand({ bind, isBound }, ApplyTypeHintsCommand); | ||
}); | ||
export default modelHintsModule; |
@@ -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"; |
@@ -22,2 +22,3 @@ /******************************************************************************** | ||
SModelElement, | ||
SModelExtension, | ||
SRoutableElement, | ||
@@ -27,8 +28,12 @@ SRoutingHandle | ||
const ROUTING_HANDLE_SOURCE_INDEX: number = -2; | ||
export const reconnectFeature = Symbol("reconnectFeature"); | ||
export interface Reconnectable extends SModelExtension { | ||
} | ||
export function isRoutable<T extends SModelElement>(element: T): element is T & SRoutableElement { | ||
return element instanceof SRoutableElement && (element as any).routingPoints !== undefined; | ||
export function isReconnectable(element: SModelElement): element is SRoutableElement & Reconnectable { | ||
return element instanceof SRoutableElement && element.hasFeature(reconnectFeature); | ||
} | ||
const ROUTING_HANDLE_SOURCE_INDEX: number = -2; | ||
export function isReconnectHandle(element: SModelElement | undefined): element is SReconnectHandle { | ||
@@ -38,5 +43,2 @@ return element !== undefined && element instanceof SReconnectHandle; | ||
export function isRoutingHandle(element: SModelElement | undefined): element is SRoutingHandle { | ||
return element !== undefined && element instanceof SRoutingHandle; | ||
} | ||
@@ -43,0 +45,0 @@ export function addReconnectHandles(element: SRoutableElement) { |
@@ -19,12 +19,8 @@ /******************************************************************************** | ||
import { GLSP_TYPES } from "../../types"; | ||
import { RequestResponseSupport } from "./support"; | ||
import { GLSPActionDispatcher } from "./glsp-action-dispatcher"; | ||
const requestResponseModule = new ContainerModule((bind, unbind, isBound, rebind) => { | ||
bind(RequestResponseSupport).toSelf().inSingletonScope(); | ||
bind(GLSP_TYPES.RequestResponseSupport).toService(RequestResponseSupport); | ||
bind(TYPES.IActionHandlerInitializer).toService(RequestResponseSupport); | ||
rebind(TYPES.IActionDispatcher).to(GLSPActionDispatcher).inSingletonScope(); | ||
}); | ||
export default requestResponseModule; |
@@ -36,5 +36,5 @@ /******************************************************************************** | ||
import { isNotUndefined } from "../../utils/smodel-util"; | ||
import { getAbsolutePosition } from "../../utils/viewpoint-util"; | ||
import { addResizeHandles, isBoundsAwareMoveable, isResizeable, removeResizeHandles } 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"; | ||
@@ -54,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(); | ||
@@ -63,7 +66,10 @@ } | ||
const index = context.root.index; | ||
index.all().filter(isResizeable).forEach(removeResizeHandles); | ||
index | ||
.all() | ||
.filter(isResizable) | ||
.forEach(removeResizeHandles); | ||
if (isNotUndefined(this.action.elementId)) { | ||
const resizeElement = index.getById(this.action.elementId); | ||
if (isNotUndefined(resizeElement) && isResizeable(resizeElement)) { | ||
if (isNotUndefined(resizeElement) && isResizable(resizeElement)) { | ||
addResizeHandles(resizeElement); | ||
@@ -78,5 +84,8 @@ } | ||
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(); | ||
@@ -87,3 +96,6 @@ } | ||
const index = context.root.index; | ||
index.all().filter(isResizeable).forEach(removeResizeHandles); | ||
index | ||
.all() | ||
.filter(isResizable) | ||
.forEach(removeResizeHandles); | ||
return context.root; | ||
@@ -102,11 +114,15 @@ } | ||
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[] { | ||
if (event.button === 0) { | ||
if (event.button === 0 && !(target instanceof SResizeHandle)) { | ||
const moveable = findParentByFeature(target, isMoveable); | ||
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; | ||
} | ||
@@ -118,48 +134,89 @@ this.hasDragged = false; | ||
mouseMove(target: SModelElement, event: MouseEvent): Action[] { | ||
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; | ||
} | ||
@@ -173,5 +230,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; | ||
} | ||
@@ -182,4 +251,2 @@ | ||
} | ||
} |
@@ -34,2 +34,3 @@ /******************************************************************************** | ||
SDanglingAnchor, | ||
SEdgeSchema, | ||
SModelElement, | ||
@@ -41,13 +42,11 @@ SModelRoot, | ||
import { getAbsolutePosition } from "../../utils/viewpoint-util"; | ||
import { isRoutable } from "../reconnect/model"; | ||
import { isRoutable } from "../../utils/smodel-util"; | ||
import { getAbsolutePosition, toAbsolutePosition } from "../../utils/viewpoint-util"; | ||
import { FeedbackCommand } from "./model"; | ||
export class DrawFeedbackEdgeAction implements Action { | ||
kind = DrawFeedbackEdgeCommand.KIND; | ||
constructor(readonly elementTypeId: string, readonly sourceId: string) { } | ||
constructor(readonly elementTypeId: string, readonly sourceId: string, readonly routerKind?: string) { } | ||
} | ||
@injectable() | ||
@@ -62,3 +61,3 @@ export class DrawFeedbackEdgeCommand extends FeedbackCommand { | ||
execute(context: CommandExecutionContext): CommandReturn { | ||
drawFeedbackEdge(context, this.action.sourceId, this.action.elementTypeId); | ||
drawFeedbackEdge(context, this.action.sourceId, this.action.elementTypeId, this.action.routerKind); | ||
return context.root; | ||
@@ -132,3 +131,3 @@ } | ||
function drawFeedbackEdge(context: CommandExecutionContext, sourceId: string, elementTypeId: string) { | ||
function drawFeedbackEdge(context: CommandExecutionContext, sourceId: string, elementTypeId: string, routerKind?: string) { | ||
const root = context.root; | ||
@@ -147,9 +146,11 @@ const sourceChild = root.index.getById(sourceId); | ||
edgeEnd.id = feedbackEdgeEndId(root); | ||
edgeEnd.position = { x: source.bounds.x, y: source.bounds.y }; | ||
edgeEnd.position = toAbsolutePosition(source); | ||
const feedbackEdgeSchema = { | ||
type: 'edge', | ||
const feedbackEdgeSchema = <SEdgeSchema>{ | ||
type: elementTypeId, | ||
id: feedbackEdgeId(root), | ||
sourceId: source.id, | ||
targetId: edgeEnd.id, | ||
cssClasses: ["feedback-edge"], | ||
routerKind, | ||
opacity: 0.3 | ||
@@ -156,0 +157,0 @@ }; |
@@ -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); |
@@ -31,2 +31,3 @@ /******************************************************************************** | ||
isConnectable, | ||
isSelected, | ||
isViewport, | ||
@@ -46,5 +47,5 @@ MouseListener, | ||
import { isNotUndefined, isSelected } from "../../utils/smodel-util"; | ||
import { isNotUndefined, isRoutable, isRoutingHandle } from "../../utils/smodel-util"; | ||
import { getAbsolutePosition } from "../../utils/viewpoint-util"; | ||
import { addReconnectHandles, isRoutable, isRoutingHandle, removeReconnectHandles } from "../reconnect/model"; | ||
import { addReconnectHandles, removeReconnectHandles } from "../reconnect/model"; | ||
import { | ||
@@ -186,3 +187,2 @@ FeedbackEdgeEnd, | ||
export class FeedbackEdgeRouteMovingMouseListener extends MouseListener { | ||
@@ -189,0 +189,0 @@ hasDragged = false; |
@@ -19,10 +19,16 @@ /******************************************************************************** | ||
Action, | ||
Bounds, | ||
BoundsAware, | ||
Dimension, | ||
EdgeRouterRegistry, | ||
ElementAndBounds, | ||
findParentByFeature, | ||
ISnapper, | ||
isSelected, | ||
isViewport, | ||
KeyTool, | ||
ModelLayoutOptions, | ||
MouseListener, | ||
Point, | ||
SConnectableElement, | ||
SetBoundsAction, | ||
@@ -32,11 +38,25 @@ SModelElement, | ||
SParentElement, | ||
Tool | ||
Tool, | ||
TYPES | ||
} from "sprotty/lib"; | ||
import { GLSP_TYPES } from "../../types"; | ||
import { forEachElement, isNonRoutableSelectedBoundsAware, isSelected, toElementAndBounds } from "../../utils/smodel-util"; | ||
import { isBoundsAwareMoveable, isResizeable, 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"; | ||
@@ -48,3 +68,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"; | ||
@@ -69,4 +90,4 @@ /** | ||
protected feedbackMoveMouseListener: FeedbackMoveMouseListener; | ||
protected changeBoundsListener: ChangeBoundsListener; | ||
protected feedbackMoveMouseListener: MouseListener; | ||
protected changeBoundsListener: MouseListener & SelectionListener; | ||
@@ -77,16 +98,28 @@ constructor(@inject(GLSP_TYPES.SelectionService) protected selectionService: SelectionService, | ||
@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) { } | ||
enable() { | ||
// install feedback move mouse listener for client-side move updates | ||
this.feedbackMoveMouseListener = new FeedbackMoveMouseListener(this.movementRestrictor); | ||
this.feedbackMoveMouseListener = this.createMoveMouseListener(); | ||
this.mouseTool.register(this.feedbackMoveMouseListener); | ||
// instlal change bounds listener for client-side resize updates and server-side updates | ||
this.changeBoundsListener = new ChangeBoundsListener(this); | ||
// install change bounds listener for client-side resize updates and server-side updates | ||
this.changeBoundsListener = this.createChangeBoundsListener(); | ||
this.mouseTool.register(this.changeBoundsListener); | ||
this.selectionService.register(this.changeBoundsListener); | ||
// register feedback | ||
this.feedbackDispatcher.registerFeedback(this, [new ShowChangeBoundsToolResizeFeedbackAction]); | ||
} | ||
protected createMoveMouseListener(): MouseListener { | ||
return new FeedbackMoveMouseListener(this); | ||
} | ||
protected createChangeBoundsListener(): MouseListener & SelectionListener { | ||
return new ChangeBoundsListener(this); | ||
} | ||
disable() { | ||
@@ -96,18 +129,21 @@ this.mouseTool.deregister(this.changeBoundsListener); | ||
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); | ||
} | ||
} | ||
class ChangeBoundsListener extends MouseListener implements SelectionListener { | ||
export class ChangeBoundsListener extends DragAwareMouseListener implements SelectionListener { | ||
// members for calculating the correct position change | ||
protected lastDragPosition: Point | undefined = undefined; | ||
protected lastDragPosition?: Point; | ||
protected positionDelta: Point = { x: 0, y: 0 }; | ||
protected initialPositon: Point | undefined = undefined; | ||
protected initialBounds: Bounds | undefined; | ||
// members for resize mode | ||
protected activeResizeElementId: string | undefined = undefined; | ||
protected activeResizeHandle: SResizeHandle | undefined = undefined; | ||
protected activeResizeElementId?: string; | ||
protected activeResizeHandle?: SResizeHandle; | ||
@@ -120,21 +156,22 @@ constructor(protected tool: ChangeBoundsTool) { | ||
super.mouseDown(target, event); | ||
const actions: Action[] = []; | ||
if (event.button === 0) { | ||
// check if we have a resize handle (only single-selection) | ||
if (this.activeResizeElementId && target instanceof SResizeHandle) { | ||
this.activeResizeHandle = target; | ||
} else { | ||
this.setActiveResizeElement(target); | ||
} | ||
if (this.activeResizeElementId) { | ||
this.initPosition(event); | ||
} else { | ||
this.reset(); | ||
} | ||
if (event.button !== 0) { | ||
return []; | ||
} | ||
return actions; | ||
// check if we have a resize handle (only single-selection) | ||
if (this.activeResizeElementId && target instanceof SResizeHandle) { | ||
this.activeResizeHandle = target; | ||
} else { | ||
this.setActiveResizeElement(target); | ||
} | ||
if (this.activeResizeElementId) { | ||
this.initPosition(event); | ||
} else { | ||
this.reset(); | ||
} | ||
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 | ||
@@ -147,5 +184,4 @@ // consider resize handles ourselves | ||
mouseUp(target: SModelElement, event: MouseEvent): Action[] { | ||
super.mouseUp(target, event); | ||
if (!this.hasPositionDelta()) { | ||
draggingMouseUp(target: SModelElement, event: MouseEvent): Action[] { | ||
if (this.lastDragPosition === undefined) { | ||
this.resetPosition(); | ||
@@ -155,18 +191,28 @@ return []; | ||
// no further bound changing, simply send the latest data to the server using a single change bounds action for all relevant elements | ||
const actions: Action[] = []; | ||
if (this.activeResizeHandle) { | ||
// An action. Resize, not move. | ||
const resizeElement = findParentByFeature(this.activeResizeHandle, isResizeable); | ||
// Resize, not move | ||
const resizeElement = findParentByFeature(this.activeResizeHandle, isResizable); | ||
if (this.isActiveResizeElement(resizeElement)) { | ||
createChangeBoundsAction(resizeElement).forEach(action => actions.push(action)); | ||
this.createChangeBoundsAction(resizeElement).forEach(action => actions.push(action)); | ||
} | ||
} else { | ||
// Bounds... Change Bounds. | ||
// Move | ||
const newBounds: ElementAndBounds[] = []; | ||
forEachElement(target, isNonRoutableSelectedBoundsAware, element => | ||
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)); | ||
} | ||
} | ||
@@ -179,3 +225,3 @@ this.resetPosition(); | ||
if (this.activeResizeElementId) { | ||
if (selectedElements.indexOf(this.activeResizeElementId) > -1) { | ||
if (selectedElements.includes(this.activeResizeElementId)) { | ||
// our active element is still selected, nothing to do | ||
@@ -202,3 +248,3 @@ return; | ||
this.activeResizeElementId = moveableElement.id; | ||
this.tool.dispatchFeedback([new ShowChangeBoundsToolResizeFeedbackAction(this.activeResizeElementId)]); | ||
this.tool.dispatchFeedback(this, [new ShowChangeBoundsToolResizeFeedbackAction(this.activeResizeElementId)]); | ||
return true; | ||
@@ -209,3 +255,3 @@ } | ||
protected isActiveResizeElement(element: SModelElement | undefined): element is SParentElement & BoundsAware { | ||
protected isActiveResizeElement(element?: SModelElement): element is SParentElement & BoundsAware { | ||
return element !== undefined && element.id === this.activeResizeElementId; | ||
@@ -215,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 }; | ||
} | ||
} | ||
@@ -234,3 +286,3 @@ | ||
protected reset() { | ||
this.tool.dispatchFeedback([new HideChangeBoundsToolResizeFeedbackAction()]); | ||
this.tool.dispatchFeedback(this, [new HideChangeBoundsToolResizeFeedbackAction()]); | ||
this.resetPosition(); | ||
@@ -242,9 +294,6 @@ } | ||
this.lastDragPosition = undefined; | ||
this.initialPositon = undefined; | ||
this.positionDelta = { x: 0, y: 0 }; | ||
} | ||
protected hasPositionDelta(): boolean { | ||
return this.positionDelta.x !== 0 || this.positionDelta.y !== 0; | ||
} | ||
protected handleElementResize(): Action[] { | ||
@@ -255,82 +304,127 @@ if (!this.activeResizeHandle) { | ||
const actions: Action[] = []; | ||
const resizeElement = findParentByFeature(this.activeResizeHandle, isResizeable); | ||
const resizeElement = findParentByFeature(this.activeResizeHandle, isResizable); | ||
if (this.isActiveResizeElement(resizeElement)) { | ||
switch (this.activeResizeHandle.location) { | ||
case ResizeHandleLocation.TopLeft: | ||
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: | ||
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: | ||
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: | ||
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 []; | ||
} | ||
} | ||
function createChangeBoundsAction(element: SModelElement & BoundsAware): Action[] { | ||
if (isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [new ChangeBoundsOperationAction([toElementAndBounds(element)])]; | ||
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); | ||
} | ||
return []; | ||
} | ||
function createElementAndBounds(element: SModelElement & BoundsAware): ElementAndBounds[] { | ||
if (isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [toElementAndBounds(element)]; | ||
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); | ||
} | ||
return []; | ||
} | ||
function createSetBoundsAction(element: SModelElement & BoundsAware, x: number, y: number, width: number, height: number): Action[] { | ||
const newPosition = { x, y }; | ||
const newSize = { width, height }; | ||
if (isValidBoundChange(element, newPosition, newSize)) { | ||
return [new SetBoundsAction([{ elementId: element.id, newPosition, newSize }])]; | ||
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); | ||
} | ||
return []; | ||
} | ||
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; | ||
} | ||
return []; | ||
} | ||
function isValidBoundChange(element: SModelElement & BoundsAware, newPosition: Point, newSize: Dimension): boolean { | ||
return newSize.width >= minWidth(element) && newSize.height >= minHeight(element); | ||
} | ||
protected createElementAndBounds(element: SModelElement & BoundsAware): ElementAndBounds[] { | ||
if (this.isValidBoundChange(element, element.bounds, element.bounds)) { | ||
return [toElementAndBounds(element)]; | ||
} | ||
return []; | ||
} | ||
function minWidth(element: SModelElement & BoundsAware): number { | ||
// currently there are no element-specific constraints | ||
return 1; | ||
} | ||
protected createSetBoundsAction(element: SModelElement & BoundsAware, x: number, y: number, width: number, height: number): Action[] { | ||
const newPosition = { x, y }; | ||
const newSize = { width, height }; | ||
const result: Action[] = []; | ||
if (this.isValidBoundChange(element, newPosition, newSize)) { | ||
if (this.tool.movementRestrictor) { | ||
result.push(...removeMovementRestrictionFeedback(element, this.tool.movementRestrictor)); | ||
} | ||
function minHeight(element: SModelElement & BoundsAware): number { | ||
// currently there are no element-specific constraints | ||
return 1; | ||
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 result; | ||
} | ||
protected isValidBoundChange(element: SModelElement & BoundsAware, newPosition: Point, newSize: Dimension): boolean { | ||
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 { | ||
const layoutOptions = this.getLayoutOptions(element); | ||
if (layoutOptions !== undefined && typeof layoutOptions.minWidth === 'number') { | ||
return layoutOptions.minWidth; | ||
} | ||
return 1; | ||
} | ||
protected minHeight(element: SModelElement & BoundsAware): number { | ||
const layoutOptions = this.getLayoutOptions(element); | ||
if (layoutOptions !== undefined && typeof layoutOptions.minHeight === 'number') { | ||
return layoutOptions.minHeight; | ||
} | ||
return 1; | ||
} | ||
protected getLayoutOptions(element: SModelElement): ModelLayoutOptions | undefined { | ||
const layoutOptions = (element as any).layoutOptions; | ||
if (layoutOptions !== undefined) { | ||
return layoutOptions as ModelLayoutOptions; | ||
} | ||
return undefined; | ||
} | ||
} | ||
@@ -21,15 +21,15 @@ /******************************************************************************** | ||
EnableDefaultToolsAction, | ||
findParent, | ||
findParentByFeature, | ||
isConnectable, | ||
isCtrlOrCmd, | ||
SEdge, | ||
SModelElement, | ||
SModelRoot, | ||
Tool | ||
} from "sprotty/lib"; | ||
import { containmentAllowed, EdgeEditConfig, edgeEditConfig, IEditConfigProvider } from "../../base/edit-config/edit-config"; | ||
import { TypeAware } from "../../base/tool-manager/tool-manager-action-handler"; | ||
import { GLSP_TYPES } from "../../types"; | ||
import { getAbsolutePosition } from "../../utils/viewpoint-util"; | ||
import { Containable, isContainable } from "../hints/model"; | ||
import { ITypeHintProvider } from "../hints/type-hints"; | ||
import { IMouseTool } from "../mouse-tool/mouse-tool"; | ||
@@ -43,7 +43,6 @@ import { CreateConnectionOperationAction, CreateNodeOperationAction } from "../operation/operation-actions"; | ||
} 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"; | ||
import { DragAwareMouseListener } from "./drag-aware-mouse-listener"; | ||
export const TOOL_ID_PREFIX = "tool"; | ||
@@ -70,3 +69,3 @@ | ||
this.mouseTool.register(this.creationToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new ApplyCursorCSSFeedbackAction(CursorCSS.NODE_CREATION)]); | ||
this.feedbackDispatcher.registerFeedback(this, [cursorFeedbackAction(CursorCSS.NODE_CREATION)]); | ||
} | ||
@@ -76,3 +75,3 @@ | ||
this.mouseTool.deregister(this.creationToolMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.deregisterFeedback(this, [cursorFeedbackAction()]); | ||
} | ||
@@ -87,3 +86,3 @@ | ||
export class NodeCreationToolMouseListener extends DragAwareMouseListener { | ||
protected container?: SModelElement; | ||
protected container?: SModelElement & Containable; | ||
constructor(protected elementTypeId: string, protected tool: NodeCreationTool) { | ||
@@ -93,4 +92,4 @@ super(); | ||
protected creationAllowed(target: SModelElement) { | ||
return this.container || target instanceof SModelRoot; | ||
protected creationAllowed(elementTypeId: string) { | ||
return this.container && this.container.isContainableElement(elementTypeId); | ||
} | ||
@@ -100,3 +99,3 @@ | ||
const result: Action[] = []; | ||
if (this.creationAllowed(target)) { | ||
if (this.creationAllowed(this.elementTypeId)) { | ||
const containerId = this.container ? this.container.id : undefined; | ||
@@ -113,8 +112,8 @@ const location = getAbsolutePosition(target, event); | ||
mouseOver(target: SModelElement, event: MouseEvent): Action[] { | ||
const currentContainer = findParent(target, e => containmentAllowed(e, this.elementTypeId)); | ||
const currentContainer = findParentByFeature(target, isContainable); | ||
if (!this.container || currentContainer !== this.container) { | ||
this.container = currentContainer; | ||
const feedback = this.creationAllowed(target) | ||
? new ApplyCursorCSSFeedbackAction(CursorCSS.NODE_CREATION) : | ||
new ApplyCursorCSSFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED); | ||
const feedback = this.creationAllowed(this.elementTypeId) | ||
? cursorFeedbackAction(CursorCSS.NODE_CREATION) : | ||
cursorFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED); | ||
this.tool.dispatchFeedback([feedback]); | ||
@@ -139,3 +138,3 @@ } | ||
@inject(AnchorComputerRegistry) protected anchorRegistry: AnchorComputerRegistry, | ||
@inject(GLSP_TYPES.IEditConfigProvider) public readonly editConfigProvider: IEditConfigProvider) { } | ||
@inject(GLSP_TYPES.ITypeHintProvider) public readonly typeHintProvider: ITypeHintProvider) { } | ||
@@ -151,3 +150,3 @@ get id() { | ||
this.mouseTool.register(this.feedbackEndMovingMouseListener); | ||
this.dispatchFeedback([new ApplyCursorCSSFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
this.dispatchFeedback([cursorFeedbackAction(CursorCSS.OPERATION_NOT_ALLOWED)]); | ||
} | ||
@@ -158,3 +157,3 @@ | ||
this.mouseTool.deregister(this.feedbackEndMovingMouseListener); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new RemoveFeedbackEdgeAction(), new ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.deregisterFeedback(this, [new RemoveFeedbackEdgeAction(), cursorFeedbackAction()]); | ||
} | ||
@@ -174,10 +173,7 @@ | ||
protected allowedTarget: boolean = false; | ||
protected edgeEditConfig?: EdgeEditConfig; | ||
protected proxyEdge: SEdge; | ||
constructor(protected elementTypeId: string, protected tool: EdgeCreationTool) { | ||
super(); | ||
const config = tool.editConfigProvider.getEditConfig(this.elementTypeId); | ||
if (config && config.configType === edgeEditConfig) { | ||
this.edgeEditConfig = config as EdgeEditConfig; | ||
} | ||
this.proxyEdge = new SEdge(); | ||
this.proxyEdge.type = elementTypeId; | ||
} | ||
@@ -240,8 +236,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)]; | ||
} | ||
@@ -252,8 +248,9 @@ return []; | ||
protected isAllowedSource(element: SModelElement | undefined): boolean { | ||
return element !== undefined && this.edgeEditConfig ? this.edgeEditConfig.isAllowedSource(element) : false; | ||
return element !== undefined && isConnectable(element) && element.canConnect(this.proxyEdge, "source"); | ||
} | ||
protected isAllowedTarget(element: SModelElement | undefined): boolean { | ||
return element !== undefined && this.edgeEditConfig ? this.edgeEditConfig.isAllowedTarget(element) : false; | ||
return element !== undefined && isConnectable(element) && element.canConnect(this.proxyEdge, "target"); | ||
} | ||
} |
@@ -21,2 +21,3 @@ /******************************************************************************** | ||
isCtrlOrCmd, | ||
isDeletable, | ||
isSelectable, | ||
@@ -27,3 +28,2 @@ KeyListener, | ||
SModelElement, | ||
SModelRoot, | ||
Tool | ||
@@ -36,3 +36,3 @@ } from "sprotty/lib"; | ||
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"; | ||
@@ -65,3 +65,3 @@ | ||
if (matchesKeystroke(event, 'Delete')) { | ||
const deleteElementIds = Array.from(element.root.index.all().filter(e => isSelectable(e) && e.selected) | ||
const deleteElementIds = Array.from(element.root.index.all().filter(e => isDeletable(e) && isSelectable(e) && e.selected) | ||
.filter(e => e.id !== e.root.id).map(e => e.id)); | ||
@@ -90,3 +90,3 @@ return [new DeleteElementOperationAction(deleteElementIds)]; | ||
this.mouseTool.register(this.deleteToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new ApplyCursorCSSFeedbackAction(CursorCSS.ELEMENT_DELETION)]); | ||
this.feedbackDispatcher.registerFeedback(this, [cursorFeedbackAction(CursorCSS.ELEMENT_DELETION)]); | ||
} | ||
@@ -96,6 +96,4 @@ | ||
this.mouseTool.deregister(this.deleteToolMouseListener); | ||
this.feedbackDispatcher.registerFeedback(this, [new ApplyCursorCSSFeedbackAction()]); | ||
this.feedbackDispatcher.registerFeedback(this, [cursorFeedbackAction()]); | ||
} | ||
} | ||
@@ -106,3 +104,3 @@ | ||
mouseUp(target: SModelElement, event: MouseEvent): Action[] { | ||
if (target instanceof SModelRoot) { | ||
if (!isDeletable(target)) { | ||
return []; | ||
@@ -109,0 +107,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; | ||
} | ||
} |
@@ -20,2 +20,3 @@ /******************************************************************************** | ||
AnchorComputerRegistry, | ||
canEditRouting, | ||
Connectable, | ||
@@ -25,2 +26,3 @@ EdgeRouterRegistry, | ||
isConnectable, | ||
isSelected, | ||
MouseListener, | ||
@@ -34,11 +36,9 @@ SModelElement, | ||
import { isConfigurableEdge } from "../../base/edit-config/edit-config"; | ||
import { GLSP_TYPES } from "../../types"; | ||
import { isSelected } from "../../utils/smodel-util"; | ||
import { isRoutable, isRoutingHandle } from "../../utils/smodel-util"; | ||
import { IMouseTool } from "../mouse-tool/mouse-tool"; | ||
import { ReconnectConnectionOperationAction, RerouteConnectionOperationAction } from "../reconnect/action-definitions"; | ||
import { ChangeRoutingPointsOperation, ReconnectConnectionOperationAction } from "../operation/operation-actions"; | ||
import { | ||
isReconnectable, | ||
isReconnectHandle, | ||
isRoutable, | ||
isRoutingHandle, | ||
isSourceRoutingHandle, | ||
@@ -50,3 +50,3 @@ isTargetRoutingHandle, | ||
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 { | ||
@@ -137,3 +137,10 @@ DrawFeedbackEdgeSourceAction, | ||
// note: order is important here as we want the reconnect handles to cover the routing handles | ||
this.tool.dispatchFeedback([new SwitchRoutingModeAction([this.edge.id], []), new ShowEdgeReconnectHandlesFeedbackAction(this.edge.id)]); | ||
const feedbackActions = []; | ||
if (canEditRouting(edge)) { | ||
feedbackActions.push(new SwitchRoutingModeAction([this.edge.id], [])); | ||
} | ||
if (isReconnectable(edge)) { | ||
feedbackActions.push(new ShowEdgeReconnectHandlesFeedbackAction(this.edge.id)); | ||
} | ||
this.tool.dispatchFeedback(feedbackActions); | ||
} | ||
@@ -149,3 +156,3 @@ | ||
this.tool.dispatchFeedback([new HideEdgeReconnectHandlesFeedbackAction(), | ||
new ApplyCursorCSSFeedbackAction(CursorCSS.EDGE_RECONNECT), | ||
cursorFeedbackAction(CursorCSS.EDGE_RECONNECT), | ||
new DrawFeedbackEdgeSourceAction(this.edge.type, this.edge.targetId)]); | ||
@@ -155,3 +162,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)]); | ||
@@ -242,3 +249,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; | ||
@@ -255,11 +262,11 @@ } | ||
this.setNewConnectable(currentTarget); | ||
if (currentTarget && isConfigurableEdge(this.edge)) { | ||
if ((this.reconnectMode === 'NEW_SOURCE' && this.edge.isAllowedSource(currentTarget.type)) || | ||
(this.reconnectMode === 'NEW_TARGET' && this.edge.isAllowedTarget(currentTarget.type))) { | ||
if (currentTarget) { | ||
if ((this.reconnectMode === 'NEW_SOURCE' && currentTarget.canConnect(this.edge, "source")) || | ||
(this.reconnectMode === 'NEW_TARGET' && currentTarget.canConnect(this.edge, "target"))) { | ||
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)]); | ||
} | ||
@@ -318,5 +325,5 @@ } | ||
result.push(...[new HideEdgeReconnectHandlesFeedbackAction(), | ||
new ApplyCursorCSSFeedbackAction(), new RemoveFeedbackEdgeAction()]); | ||
cursorFeedbackAction(), new RemoveFeedbackEdgeAction()]); | ||
this.tool.dispatchFeedback(result); | ||
} | ||
} |
@@ -18,2 +18,4 @@ /******************************************************************************** | ||
import glspCommandPaletteModule from "./features/command-palette/di.config"; | ||
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"; | ||
@@ -32,24 +34,36 @@ import executeModule from "./features/execute/di.config"; | ||
export * from 'sprotty/lib'; | ||
export * from './base/edit-config/edit-config'; | ||
export * from './model-source/websocket-diagram-server'; | ||
export * from './base/model/update-model-command'; | ||
export * from './base/tool-manager/tool-manager-action-handler'; | ||
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/command-palette/action-definitions'; | ||
export * from './features/command-palette/action-provider'; | ||
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'; | ||
export * from './features/execute/execute-command'; | ||
export * from './features/execute/model'; | ||
export * from './features/hints/action-definition'; | ||
export * from './features/hints/type-hints-action-initializer'; | ||
export * from './features/mouse-tool/di.config'; | ||
export * from './features/hints/request-type-hints-action'; | ||
export * from './features/hints/type-hints'; | ||
export * from './features/hints/model'; | ||
export * from './features/layout/layout-commands'; | ||
export * from './features/mouse-tool/mouse-tool'; | ||
export * from './features/operation/operation-actions'; | ||
export * from './features/operation/set-operations'; | ||
export * from './features/request-response/action-definitions'; | ||
export * from './features/request-response/support'; | ||
export * from './features/rank/model'; | ||
export * from './features/reconnect/model'; | ||
export * from './features/request-response/glsp-action-dispatcher'; | ||
export * from './features/save/model'; | ||
export * from './features/save/save'; | ||
export * from './features/select/di.config'; | ||
export * from './features/tool-feedback/change-bounds-tool-feedback'; | ||
export * from './features/tool-feedback/creation-tool-feedback'; | ||
export * from './features/tool-feedback/css-feedback'; | ||
export * from './features/tool-feedback/edge-edit-tool-feedback'; | ||
export * from './features/tool-feedback/feedback-action-dispatcher'; | ||
export * from './features/tool-feedback/model'; | ||
export * from './features/tool-feedback/model'; | ||
export * from './features/tool-palette/tool-palette'; | ||
@@ -60,5 +74,7 @@ export * from './features/tools/change-bounds-tool'; | ||
export * from './features/tools/delete-tool'; | ||
export * from './features/tools/drag-aware-mouse-listener'; | ||
export * from './features/tools/edge-edit-tool'; | ||
export * from './features/undo-redo/model'; | ||
export * from './features/validation/validate'; | ||
export * from './features/layout/layout-commands'; | ||
export * from './lib/model'; | ||
@@ -70,9 +86,9 @@ export * from './types'; | ||
export * from './utils/viewpoint-util'; | ||
export * from './model-source/websocket-diagram-server'; | ||
export * from "./model-source/glsp-server-status"; | ||
export { | ||
validationModule, saveModule, executeModule, paletteModule, toolFeedbackModule, defaultGLSPModule, modelHintsModule, glspCommandPaletteModule, requestResponseModule, // | ||
glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule | ||
glspContextMenuModule, glspServerCopyPasteModule, glspSelectModule, glspMouseToolModule, layoutCommandsModule, glspEditLabelValidationModule | ||
}; | ||
@@ -16,12 +16,13 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { SGraph } from "sprotty/lib"; | ||
import { exportFeature, SGraph, SModelElement, SModelElementSchema, viewportFeature } from "sprotty/lib"; | ||
import { Containable, containerFeature } from "../features/hints/model"; | ||
import { Saveable, saveFeature } from "../features/save/model"; | ||
export class GLSPGraph extends SGraph implements Saveable { | ||
dirty: boolean; | ||
hasFeature(feature: symbol) { | ||
return feature === saveFeature || super.hasFeature(feature); | ||
export class GLSPGraph extends SGraph implements Saveable, Containable { | ||
static readonly DEFAULT_FEATURES = [viewportFeature, exportFeature, saveFeature, containerFeature]; | ||
dirty: boolean = false; | ||
isContainableElement(input: string | SModelElement | SModelElementSchema): boolean { | ||
return true; | ||
} | ||
} |
@@ -26,10 +26,11 @@ /******************************************************************************** | ||
import { NotificationType } from "vscode-ws-jsonrpc"; | ||
import { RequestCommandPaletteActions } from "../features/command-palette/action-definitions"; | ||
import { RequestContextActions } from "../features/context-actions/action-definitions"; | ||
import { ExecuteServerCommandAction } from "../features/execute/execute-command"; | ||
import { RequestTypeHintsAction } from "../features/hints/action-definition"; | ||
import { RequestTypeHintsAction } from "../features/hints/request-type-hints-action"; | ||
import { OperationKind, RequestOperationsAction } from "../features/operation/set-operations"; | ||
import { IdentifiableRequestAction } from "../features/request-response/action-definitions"; | ||
import { SaveModelAction } from "../features/save/save"; | ||
import { GlspRedoAction, GlspUndoAction } from "../features/undo-redo/model"; | ||
import { RequestMarkersAction } from "../features/validation/validate"; | ||
import { ValidateLabelEditAction } from "../features/edit-label-validation/edit-label-validator"; | ||
import { RequestClipboardDataAction, PasteOperationAction, CutOperationAction } from "../features/copy-paste/copy-paste-actions"; | ||
@@ -50,3 +51,2 @@ @injectable() | ||
}); | ||
} | ||
@@ -89,3 +89,3 @@ | ||
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); | ||
@@ -105,7 +105,10 @@ registry.register(OperationKind.CHANGE_BOUNDS, diagramServer); | ||
registry.register(ExportSvgAction.KIND, diagramServer); | ||
registry.register(RequestCommandPaletteActions.KIND, diagramServer); | ||
registry.register(IdentifiableRequestAction.KIND, diagramServer); | ||
registry.register(RequestContextActions.KIND, diagramServer); | ||
registry.register(ValidateLabelEditAction.KIND, diagramServer); | ||
registry.register(RequestMarkersAction.KIND, diagramServer); | ||
registry.register(LayoutAction.KIND, diagramServer); | ||
registry.register(ApplyLabelEditAction.KIND, diagramServer); | ||
registry.register(RequestClipboardDataAction.KIND, diagramServer); | ||
registry.register(PasteOperationAction.KIND, diagramServer); | ||
registry.register(CutOperationAction.KIND, diagramServer); | ||
@@ -112,0 +115,0 @@ // Register an empty handler for SwitchEditMode, to avoid runtime exceptions. |
@@ -20,9 +20,13 @@ /******************************************************************************** | ||
IToolFactory: Symbol.for("Factory<Tool>"), | ||
IEditConfigProvider: Symbol.for("IEditConfigProvider"), | ||
ITypeHintProvider: Symbol.for("ITypeHintProvider"), | ||
IMovementRestrictor: Symbol.for("IMovmementRestrictor"), | ||
RequestResponseSupport: Symbol.for("RequestResponseSupport"), | ||
SelectionService: Symbol.for("SelectionService"), | ||
SelectionListener: Symbol.for("SelectionListener"), | ||
SModelRootListener: Symbol.for("SModelRootListener"), | ||
MouseTool: Symbol.for("MouseTool") | ||
MouseTool: Symbol.for("MouseTool"), | ||
IContextMenuService: Symbol.for("IContextMenuService"), | ||
IContextMenuServiceProvider: Symbol.for("IContextMenuServiceProvider"), | ||
IContextMenuProviderRegistry: Symbol.for("IContextMenuProviderRegistry"), | ||
IContextMenuProvider: Symbol.for("IContextMenuProvider"), | ||
ICopyPasteHandler: Symbol.for("ICopyPasteHandler") | ||
}; |
@@ -17,7 +17,2 @@ /******************************************************************************** | ||
export function contains<T>(array: T[], value: T): boolean { | ||
if (value === undefined) return false; | ||
return array.indexOf(value) >= 0; | ||
} | ||
export function remove<T>(array: T[], value: T): boolean { | ||
@@ -33,3 +28,3 @@ const index = array.indexOf(value); | ||
export function distinctAdd<T>(array: T[], value: T): boolean { | ||
if (!contains(array, value)) { | ||
if (!array.includes(value)) { | ||
array.push(value); | ||
@@ -36,0 +31,0 @@ return true; |
@@ -16,6 +16,14 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { BoundsAware, isBoundsAware, isSelectable, Selectable, SModelElement, SParentElement } from "sprotty/lib"; | ||
import { | ||
BoundsAware, | ||
isBoundsAware, | ||
isMoveable, | ||
isSelected, | ||
Selectable, | ||
SModelElement, | ||
SRoutableElement, | ||
SRoutingHandle | ||
} from "sprotty/lib"; | ||
import { ElementAndRoutingPoints } from "src/features/operation/operation-actions"; | ||
import { isConfigurableNode, NodeEditConfig } from "../base/edit-config/edit-config"; | ||
import { isRoutable } from "../features/reconnect/model"; | ||
@@ -50,6 +58,2 @@ export function getIndex(element: SModelElement) { | ||
export function isSelected(element: SModelElement | undefined): element is SModelElement & Selectable { | ||
return isNotUndefined(element) && isSelectable(element) && element.selected; | ||
} | ||
export function isNotUndefined<T>(element: T | undefined): element is T { | ||
@@ -82,5 +86,4 @@ return element !== undefined; | ||
export function isContainmentAllowed(element: SModelElement, containableElementTypeId: string) | ||
: element is SParentElement & NodeEditConfig { | ||
return isConfigurableNode(element) && element.isContainableElement(containableElementTypeId); | ||
export function isNonRoutableSelectedMovableBoundsAware(element: SModelElement): element is SelectableBoundsAware { | ||
return isNonRoutableSelectedBoundsAware(element) && isMoveable(element); | ||
} | ||
@@ -92,2 +95,10 @@ | ||
export function isRoutable<T extends SModelElement>(element: T): element is T & SRoutableElement { | ||
return element instanceof SRoutableElement && (element as any).routingPoints !== undefined; | ||
} | ||
export function isRoutingHandle(element: SModelElement | undefined): element is SRoutingHandle { | ||
return element !== undefined && element instanceof SRoutingHandle; | ||
} | ||
export type SelectableBoundsAware = SModelElement & BoundsAware & Selectable; | ||
@@ -108,1 +119,8 @@ | ||
} | ||
export function toElementAndRoutingPoints(element: SRoutableElement): ElementAndRoutingPoints { | ||
return { | ||
elementId: element.id, | ||
newRoutingPoints: element.routingPoints | ||
}; | ||
} |
@@ -16,9 +16,16 @@ /******************************************************************************** | ||
********************************************************************************/ | ||
import { Point } from "sprotty/lib"; | ||
import { SModelElement } from "sprotty/lib"; | ||
import { Viewport } from "sprotty/lib"; | ||
import { | ||
Bounds, | ||
BoundsAware, | ||
Dimension, | ||
findParentByFeature, | ||
isAlignable, | ||
isViewport, | ||
ORIGIN_POINT, | ||
Point, | ||
SModelElement, | ||
translateBounds, | ||
Viewport | ||
} from "sprotty/lib"; | ||
import { findParentByFeature } from "sprotty/lib"; | ||
import { isViewport } from "sprotty/lib"; | ||
/** | ||
@@ -60,1 +67,36 @@ * Return the position corresponding to this mouse event (Browser coordinates) | ||
} | ||
/** | ||
* Translates the bounds of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
export function toAbsoluteBounds(element: SModelElement & BoundsAware): Bounds { | ||
const location = isAlignable(element) ? element.alignment : ORIGIN_POINT; | ||
const x = location.x; | ||
const y = location.y; | ||
const width = element.bounds.width; | ||
const height = element.bounds.height; | ||
return translateBounds({ x, y, width, height }, element, element.root); | ||
} | ||
/** | ||
* Translates the position of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
export function toAbsolutePosition(target: SModelElement & BoundsAware): Point { | ||
return toAbsoluteBounds(target); | ||
} | ||
/** | ||
* Translates the size of the diagram element (local coordinates) into the diagram coordinates system | ||
* (i.e. relative to the Diagram's 0;0 point) | ||
* | ||
* @param target A bounds-aware element from the diagram | ||
*/ | ||
export function toAbsoluteSize(target: SModelElement & BoundsAware): Dimension { | ||
return toAbsoluteBounds(target); | ||
} |
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
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
10
13
12