processmaker-builder
Version:
The gulp task runner for ProcessMaker building
522 lines (479 loc) • 19.5 kB
JavaScript
var PMConnectHandler = function (options) {
PMUI.draw.Handler.call(this, options);
/**
* Category of this resize handler
* @type {"resizable"/"nonresizable"}
*/
this.category = null;
/**
* Denotes whether the resize handle is visible or not.
* @property boolean
*/
this.visible = false;
/**
* JSON used to create an instance of the class Style used when the object is resizable.
* @property {Object}
*/
this.resizableStyle = null;
/**
* JSON used to create an instance of the class Style used when the object is not resizable.
* @property {Object}
*/
this.nonResizableStyle = null;
this.relativeShape = null;
// set defaults
PMConnectHandler.prototype.init.call(this, options);
};
PMConnectHandler.prototype = new PMUI.draw.Handler();
/**
* The type of each instance of this class.
* @property {String}
*/
PMConnectHandler.prototype.type = "PMConnectHandler";
/**
* Instance initializer which uses options to extend the config options to initialize the instance
* @param {Object} options The object that contains the config
* @private
*/
PMConnectHandler.prototype.init = function (options) {
var defaults = {
width: 10,
height: 10,
parent: null,
orientation: null,
representation: null,
resizableStyle: {},
nonResizableStyle: {},
zOrder: 2
};
// extend recursively the defaultOptions with the given options
$.extend(true, defaults, options);
// add default zIndex to this handler
if (defaults.resizableStyle.cssProperties) {
defaults.resizableStyle.cssProperties.zIndex = defaults.zOrder;
}
if (defaults.nonResizableStyle.cssProperties) {
defaults.nonResizableStyle.cssProperties.zIndex = defaults.zOrder;
}
this.setParent(defaults.parent)
.setWidth(defaults.width)
.setHeight(defaults.height)
.setOrientation(defaults.orientation)
.setRepresentation(defaults.representation)
.setResizableStyle(defaults.resizableStyle)
.setNonResizableStyle(defaults.nonResizableStyle);
};
/**
* Sets the parent of this handler
* @param {PMUI.draw.Shape} newParent
* @chainable
*/
PMConnectHandler.prototype.setParent = function (newParent) {
this.parent = newParent;
return this;
};
/**
* Gets the parent of this handler.
* @return {PMUI.draw.Shape}
*/
PMConnectHandler.prototype.getParent = function () {
return this.parent;
};
/**
* Paints this resize handler by calling it's parent's `paint` and setting
* the visibility of this resize handler
* @chainable
*/
PMConnectHandler.prototype.paint = function () {
if (!this.html) {
throw new Error("paint(): This handler has no html");
}
// this line paints the representation (by default a rectangle)
PMUI.draw.Handler.prototype.paint.call(this);
this.setVisible(this.visible);
return this;
};
/**
* Sets the category of the resizeHandler (also adds the needed class to
* make the element resizable)
* @param newCategory
* @chainable
*/
PMConnectHandler.prototype.setCategory = function (newCategory) {
if (typeof newCategory === "string") {
this.category = newCategory;
}
this.style.addClasses([newCategory]);
return this;
};
/**
* Sets the resizable style of this shape by creating an instance of the class Style
* @param {Object} style
* @chainable
*/
PMConnectHandler.prototype.setResizableStyle = function (style) {
this.resizableStyle = new PMUI.util.Style({
belongsTo: this,
cssProperties: style.cssProperties,
cssClasses: style.cssClasses
});
return this;
};
/**
* Sets the non resizable style for this shape by creating an instance of the class Style
* @param {Object} style
* @chainable
*/
PMConnectHandler.prototype.setNonResizableStyle = function (style) {
this.nonResizableStyle = new PMUI.util.Style({
belongsTo: this,
cssProperties: style.cssProperties,
cssClasses: style.cssClasses
});
return this;
};
PMConnectHandler.prototype.attachListeners = function () {
var $handler = $('.dragConnectHandler');
$handler.mousedown(this.onMouseDown(this));
if (this.relativeShape) {
dragOptions = {
revert: true,
helper: "clone",
cursorAt: false,
revertDuration: 0,
grid: [1, 1],
start: this.onDragStart(this.relativeShape),
stop: this.onDragEnd(this.relativeShape),
drag: this.onDrag(this.relativeShape),
refreshPositions: true,
cursor: "pointer"
};
$(this.html).draggable(dragOptions);
}
return this;
};
PMConnectHandler.prototype.attachDrop = function () {
dropOptions = {
accept: '.dragConnectHandler, .pmui-oval',
hoverClass: "ui-state-hover",
drop: this.onDrop(this.relativeShape, this),
over: this.onDropOver(this.relativeShape, this)
};
$('.dropConnectHandler').droppable(dropOptions);
};
PMConnectHandler.prototype.onMouseDown = function (customShape) {
return function (e, ui) {
e.preventDefault();
e.stopPropagation();
}
};
PMConnectHandler.prototype.onMouseOver = function (customShape) {
return function (e, ui) {
e.preventDefault();
e.stopPropagation();
}
};
PMConnectHandler.prototype.onMouseOut = function (customShape) {
return function (e, ui) {
e.preventDefault();
e.stopPropagation();
PMUI.getActiveCanvas.isMouseOverHelper = false;
if (PMUI.getActiveCanvas.hightLightShape) {
PMUI.getActiveCanvas.hideDragConnectHandlers();
}
}
};
PMConnectHandler.prototype.onDragStart = function (customShape) {
return function (e, ui) {
if (!customShape.canvas.currentConnection) {
customShape.canvas.isDraggingConnectHandler = true;
var canvas = customShape.canvas,
currentLabel = canvas.currentLabel,
realPoint = canvas.relativePoint(e),
startPortX = e.pageX - customShape.getAbsoluteX(),
startPortY = e.pageY - customShape.getAbsoluteY();
// empty the current selection so that the segment created by the
// helper is always on top
customShape.canvas.emptyCurrentSelection();
if (currentLabel) {
currentLabel.loseFocus();
$(currentLabel.textField).focusout();
}
if (customShape.family !== "CustomShape") {
return false;
}
customShape.setOldX(customShape.getX());
customShape.setOldY(customShape.getY());
customShape.startConnectionPoint.x = customShape.canvas.zoomFactor * realPoint.x;
customShape.startConnectionPoint.y = customShape.canvas.zoomFactor * realPoint.y - canvas.getY();
} else {
customShape.canvas.currentConnection.disconnect();
}
return true;
};
};
PMConnectHandler.prototype.onDragEnd = function (customShape) {
return function (e, ui) {
if (customShape.canvas.connectionSegment) {
$(customShape.canvas.connectionSegment.getHTML()).remove();
customShape.canvas.currentConnection.connect()
.updateIncomingAndOutgoingConnections('create');
}
};
};
PMConnectHandler.prototype.onDrag = function (customShape) {
var sourceShape,
destinyShape,
startPoint;
return function (e, ui) {
var connections;
if (customShape.canvas.currentConnection) {
canvas = customShape.canvas;
endPoint = new PMUI.util.Point();
if (canvas.connectionSegment) {
$(canvas.connectionSegment.getHTML()).remove();
}
endPoint.x = e.pageX - canvas.getX() + canvas.getLeftScroll() - canvas.getAbsoluteX();
endPoint.y = e.pageY - canvas.getY() + canvas.getTopScroll() - canvas.getAbsoluteY();
//make connection segment
otherPort = customShape.connection.srcPort.getPoint(false)
.equals(customShape.getPoint(false)) ? customShape.connection.destPort :
customShape.connection.srcPort;
//remove related shapes
sourceShape = customShape.connection.srcPort.getParent();
destinyShape = customShape.connection.destPort.getParent();
connections = PMFlow.getConnections(sourceShape, destinyShape, false);
if (sourceShape && connections.length) {
// as we are invoking PMFlow.getConnections() with false as third parameter the result can have
// at most 1 element, that's why we use the index 0 in the arrays below.
sourceShape.removeOutgoingConnection(connections[0]);
destinyShape.removeIncomingConnection(connections[0]);
}
connections = PMFlow.getConnections(destinyShape, sourceShape, false);
if (destinyShape && connections.length) {
// as we are invoking PMFlow.getConnections() with false as third parameter the result can have
// at most 1 element, that's why we use the index 0 in the arrays below.
destinyShape.removeOutgoingConnection(connections[0]);
sourceShape.removeIncomingConnection(connections[0]);
}
startPoint = otherPort.getPoint(false);
startPoint.x = startPoint.x - canvas.getAbsoluteX();
startPoint.y = startPoint.y - canvas.getAbsoluteY();
canvas.connectionSegment = new PMUI.draw.Segment({
startPoint: startPoint,
endPoint: endPoint,
parent: canvas
});
canvas.connectionSegment.createHTML();
canvas.connectionSegment.paint();
} else {
customShape.canvas.isDraggingConnectHandler = true;
var canvas = customShape.getCanvas(),
endPoint = new PMUI.util.Point(),
realPoint = canvas.relativePoint(e);
if (canvas.connectionSegment) {
//remove the connection segment in order to create another one
$(canvas.connectionSegment.getHTML()).remove();
}
//Determine the point where the mouse currently is
endPoint.x = realPoint.x * customShape.canvas.zoomFactor - canvas.getX();
endPoint.y = realPoint.y * customShape.canvas.zoomFactor - canvas.getY();
//creates a new segment from where the helper was created to the
// currently mouse location
canvas.connectionSegment = new PMUI.draw.Segment({
startPoint: customShape.startConnectionPoint,
endPoint: endPoint,
parent: canvas,
zOrder: PMUI.util.Style.MAX_ZINDEX * 2
});
//We make the connection segment point to helper in order to get
// information when the drop occurs
canvas.connectionSegment.pointsTo = customShape;
//create HTML and paint
//canvas.connectionSegment.createHTML();
canvas.connectionSegment.paint();
}
};
};
PMConnectHandler.prototype.onClick = function (obj) {
return function (e, ui) {
alert('clicked');
};
};
/**
* Drag enter hook for this drop behavior, marks that a shape is over a
* droppable element
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMConnectHandler.prototype.onDropOver = function (shape, handler) {
return function (e, ui) {
};
};
/**
* Drag leave hook for this drop behavior, marks that a shape has left a
* droppable element
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMConnectHandler.prototype.onDropOut = function (shape, handler) {
return function (e, ui) {
shape.entered = false;
handler.style.addClasses(['pmConnnectHandler']);
};
};
/**
* On drop handler for this drop behavior, creates a connection between the
* droppable element and the dropped element, or move ports among those shapes
* @param {PMUI.draw.Shape} shape
* @return {Function}
*/
PMConnectHandler.prototype.onDrop = function (shape, handler) {
return function (e, ui) {
var connection,
sourceShape,
canvas = shape.getCanvas(),
id = ui.draggable.attr('id'),
targetShape,
originalType,
currLeft,
currTop,
startPoint,
sourcePort,
endPort,
endPortXCoord,
endPortYCoord,
port,
command,
validationResult;
if (!shape.canvas.currentConnection) {
shape.entered = false;
//if its the helper then we need to create two ports and draw a
// connection
//we get the points and the corresponding shapes involved
startPoint = shape.canvas.connectionSegment.startPoint;
sourceShape = shape.canvas.connectionSegment.pointsTo;
//determine the points where the helper was created
if (sourceShape.parent && sourceShape.parent.id === shape.id) {
return true;
}
validationResult = PMDesigner.connectValidator.isValid(sourceShape, shape);
if (!validationResult.result) {
//show invalid message
PMDesigner.msgFlash(validationResult.msg, document.body, 'info', 3000, 5);
return false;
}
sourceShape.setPosition(sourceShape.oldX, sourceShape.oldY);
startPoint.x -= sourceShape.absoluteX - shape.canvas.getAbsoluteX();
startPoint.y -= sourceShape.absoluteY - shape.canvas.getAbsoluteY();
//create the ports
sourcePort = new PMUI.draw.Port({
width: 10,
height: 10
});
endPort = new PMUI.draw.Port({
width: 10,
height: 10
});
//determine the position where the helper was dropped
endPortXCoord = ui.offset.left - shape.canvas.getX() -
shape.getAbsoluteX() + shape.canvas.getLeftScroll();
endPortYCoord = ui.offset.top - shape.canvas.getY() -
shape.getAbsoluteY() + shape.canvas.getTopScroll();
// add ports to the corresponding shapes
// addPort() determines the position of the ports
sourceShape.addPort(sourcePort, startPoint.x, startPoint.y);
shape.addPort(endPort, endPortXCoord, endPortYCoord,
false, sourcePort);
//add ports to the canvas array for regularShapes
//shape.canvas.regularShapes.insert(sourcePort).insert(endPort);
//create the connection
connection = new PMFlow({
srcPort: sourcePort,
destPort: endPort,
segmentColor: new PMUI.util.Color(0, 0, 0),
name: " ",
canvas: shape.canvas,
segmentStyle: shape.connectionType.segmentStyle,
flo_type: shape.connectionType.type
});
connection.setSrcDecorator(new PMUI.draw.ConnectionDecorator({
width: 11,
height: 11,
canvas: canvas,
decoratorPrefix: (typeof shape.connectionType.srcDecorator !== 'undefined'
&& shape.connectionType.srcDecorator !== null) ?
shape.connectionType.srcDecorator : "mafe-decorator",
decoratorType: "source",
parent: connection
}));
connection.setDestDecorator(new PMUI.draw.ConnectionDecorator({
width: 11,
height: 11,
canvas: canvas,
decoratorPrefix: (typeof shape.connectionType.destDecorator !== 'undefined'
&& shape.connectionType.destDecorator !== null) ?
shape.connectionType.destDecorator : "mafe-decorator",
decoratorType: "target",
parent: connection
}));
connection.canvas.commandStack.add(new PMUI.command.CommandConnect(connection));
//connect the two ports
connection.connect();
connection.setSegmentMoveHandlers();
//add the connection to the canvas, that means insert its html to
// the DOM and adding it to the connections array
canvas.addConnection(connection);
// Filling PMFlow fields
connection.setTargetShape(endPort.parent);
connection.setOriginShape(sourcePort.parent);
// now that the connection was drawn try to create the intersections
connection.checkAndCreateIntersectionsWithAll();
//attaching port listeners
sourcePort.attachListeners(sourcePort);
endPort.attachListeners(endPort);
// finally trigger createEvent
canvas.triggerCreateEvent(connection, []);
} else {
connection = shape.canvas.currentConnection;
if (shape.canvas.dragConnectHandlers.get(0).id === id) {
port = shape.canvas.dragConnectHandlers.get(0).relativeShape;
targetShape = shape.canvas.dragConnectHandlers.get(1).relativeShape.parent;
sourceShape = shape;
} else if (shape.canvas.dragConnectHandlers.get(1).id === id) {
port = shape.canvas.dragConnectHandlers.get(1).relativeShape;
sourceShape = shape.canvas.dragConnectHandlers.get(0).relativeShape.parent;
targetShape = shape;
} else {
port = null;
}
originalType = connection.flo_type;
validationResult = PMDesigner.connectValidator.isValid(sourceShape, targetShape, connection);
if (!validationResult.result) {
//show invalid message
PMDesigner.msgFlash(validationResult.msg, document.body, 'info', 3000, 5);
return false;
}
if (originalType !== 'DEFAULT' && originalType !== targetShape.connectionType.type) {
PMDesigner.msgFlash('Invalid connection type'.translate(), document.body, 'info', 3000, 5);
targetShape.connectionType.type = originalType;
return false;
}
command = new PMCommandReconnect(port, {
shape: shape,
x: ui.offset.left - shape.canvas.getX() - shape.getAbsoluteX() + shape.canvas.getLeftScroll(),
y: ui.offset.top - shape.canvas.getY() - shape.getAbsoluteY() + shape.canvas.getTopScroll()
});
canvas.commandStack.add(command);
command.execute();
canvas.currentConnection = connection;
canvas.triggerPortChangeEvent(port);
$(canvas.connectionSegment.getHTML()).remove();
canvas.connectionSegment = null;
connection.showPortsAndHandlers();
canvas.isDraggingConnectHandler = false;
canvas.hideDropConnectHandlers();
}
return false;
};
};