element.
this.attr({
'.content': {
html: content
}
});
} else {
// Content element is a
element.
// SVG elements don't have innerHTML attribute.
this.attr({
'.content': {
text: content
}
});
}
},
// Here for backwards compatibility:
setForeignObjectSize: function() {
this.updateSize.apply(this, arguments);
},
// Here for backwards compatibility:
setDivContent: function() {
this.updateContent.apply(this, arguments);
}
});
// TextBlockView implements the fallback for IE when no foreignObject exists and
// the text needs to be manually broken.
joint.shapes.basic.TextBlockView = joint.dia.ElementView.extend({
initialize: function() {
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
// Keep this for backwards compatibility:
this.noSVGForeignObjectElement = !joint.env.test('svgforeignobject');
if (!joint.env.test('svgforeignobject')) {
this.listenTo(this.model, 'change:content', function(cell) {
// avoiding pass of extra paramters
this.updateContent(cell);
});
}
},
update: function(cell, renderingOnlyAttrs) {
if (joint.env.test('svgforeignobject')) {
var model = this.model;
// Update everything but the content first.
var noTextAttrs = _.omit(renderingOnlyAttrs || model.get('attrs'), '.content');
joint.dia.ElementView.prototype.update.call(this, model, noTextAttrs);
if (!renderingOnlyAttrs || _.has(renderingOnlyAttrs, '.content')) {
// Update the content itself.
this.updateContent(model, renderingOnlyAttrs);
}
} else {
joint.dia.ElementView.prototype.update.call(this, model, renderingOnlyAttrs);
}
},
updateContent: function(cell, renderingOnlyAttrs) {
// Create copy of the text attributes
var textAttrs = _.merge({}, (renderingOnlyAttrs || cell.get('attrs'))['.content']);
textAttrs = _.omit(textAttrs, 'text');
// Break the content to fit the element size taking into account the attributes
// set on the model.
var text = joint.util.breakText(cell.get('content'), cell.get('size'), textAttrs, {
// measuring sandbox svg document
svgDocument: this.paper.svg
});
// Create a new attrs with same structure as the model attrs { text: { *textAttributes* }}
var attrs = joint.util.setByPath({}, '.content', textAttrs, '/');
// Replace text attribute with the one we just processed.
attrs['.content'].text = text;
// Update the view using renderingOnlyAttributes parameter.
joint.dia.ElementView.prototype.update.call(this, cell, attrs);
}
});
joint.routers.manhattan = (function(g, _) {
'use strict';
var config = {
// size of the step to find a route
step: 10,
// use of the perpendicular linkView option to connect center of element with first vertex
perpendicular: true,
// should be source or target not to be consider as an obstacle
excludeEnds: [], // 'source', 'target'
// should be any element with a certain type not to be consider as an obstacle
excludeTypes: ['basic.Text'],
// if number of route finding loops exceed the maximum, stops searching and returns
// fallback route
maximumLoops: 2000,
// possible starting directions from an element
startDirections: ['left', 'right', 'top', 'bottom'],
// possible ending directions to an element
endDirections: ['left', 'right', 'top', 'bottom'],
// specify directions above
directionMap: {
right: { x: 1, y: 0 },
bottom: { x: 0, y: 1 },
left: { x: -1, y: 0 },
top: { x: 0, y: -1 }
},
// maximum change of the direction
maxAllowedDirectionChange: 90,
// padding applied on the element bounding boxes
paddingBox: function() {
var step = this.step;
return {
x: -step,
y: -step,
width: 2 * step,
height: 2 * step
};
},
// an array of directions to find next points on the route
directions: function() {
var step = this.step;
return [
{ offsetX: step , offsetY: 0 , cost: step },
{ offsetX: 0 , offsetY: step , cost: step },
{ offsetX: -step , offsetY: 0 , cost: step },
{ offsetX: 0 , offsetY: -step , cost: step }
];
},
// a penalty received for direction change
penalties: function() {
return {
0: 0,
45: this.step / 2,
90: this.step / 2
};
},
// a simple route used in situations, when main routing method fails
// (exceed loops, inaccessible).
fallbackRoute: function(from, to, opts) {
// Find an orthogonal route ignoring obstacles.
var point = ((opts.previousDirAngle || 0) % 180 === 0)
? g.point(from.x, to.y)
: g.point(to.x, from.y);
return [point, to];
},
// if a function is provided, it's used to route the link while dragging an end
// i.e. function(from, to, opts) { return []; }
draggingRoute: null
};
// Map of obstacles
// Helper structure to identify whether a point lies in an obstacle.
function ObstacleMap(opt) {
this.map = {};
this.options = opt;
// tells how to divide the paper when creating the elements map
this.mapGridSize = 100;
}
ObstacleMap.prototype.build = function(graph, link) {
var opt = this.options;
// source or target element could be excluded from set of obstacles
var excludedEnds = _.chain(opt.excludeEnds)
.map(link.get, link)
.pluck('id')
.map(graph.getCell, graph).value();
// Exclude any embedded elements from the source and the target element.
var excludedAncestors = [];
var source = graph.getCell(link.get('source').id);
if (source) {
excludedAncestors = _.union(excludedAncestors, _.map(source.getAncestors(), 'id'));
};
var target = graph.getCell(link.get('target').id);
if (target) {
excludedAncestors = _.union(excludedAncestors, _.map(target.getAncestors(), 'id'));
}
// builds a map of all elements for quicker obstacle queries (i.e. is a point contained
// in any obstacle?) (a simplified grid search)
// The paper is divided to smaller cells, where each of them holds an information which
// elements belong to it. When we query whether a point is in an obstacle we don't need
// to go through all obstacles, we check only those in a particular cell.
var mapGridSize = this.mapGridSize;
_.chain(graph.getElements())
// remove source and target element if required
.difference(excludedEnds)
// remove all elements whose type is listed in excludedTypes array
.reject(function(element) {
// reject any element which is an ancestor of either source or target
return _.contains(opt.excludeTypes, element.get('type')) || _.contains(excludedAncestors, element.id);
})
// change elements (models) to their bounding boxes
.invoke('getBBox')
// expand their boxes by specific padding
.invoke('moveAndExpand', opt.paddingBox)
// build the map
.foldl(function(map, bbox) {
var origin = bbox.origin().snapToGrid(mapGridSize);
var corner = bbox.corner().snapToGrid(mapGridSize);
for (var x = origin.x; x <= corner.x; x += mapGridSize) {
for (var y = origin.y; y <= corner.y; y += mapGridSize) {
var gridKey = x + '@' + y;
map[gridKey] = map[gridKey] || [];
map[gridKey].push(bbox);
}
}
return map;
}, this.map).value();
return this;
};
ObstacleMap.prototype.isPointAccessible = function(point) {
var mapKey = point.clone().snapToGrid(this.mapGridSize).toString();
return _.every(this.map[mapKey], function(obstacle) {
return !obstacle.containsPoint(point);
});
};
// Sorted Set
// Set of items sorted by given value.
function SortedSet() {
this.items = [];
this.hash = {};
this.values = {};
this.OPEN = 1;
this.CLOSE = 2;
}
SortedSet.prototype.add = function(item, value) {
if (this.hash[item]) {
// item removal
this.items.splice(this.items.indexOf(item), 1);
} else {
this.hash[item] = this.OPEN;
}
this.values[item] = value;
var index = _.sortedIndex(this.items, item, function(i) {
return this.values[i];
}, this);
this.items.splice(index, 0, item);
};
SortedSet.prototype.remove = function(item) {
this.hash[item] = this.CLOSE;
};
SortedSet.prototype.isOpen = function(item) {
return this.hash[item] === this.OPEN;
};
SortedSet.prototype.isClose = function(item) {
return this.hash[item] === this.CLOSE;
};
SortedSet.prototype.isEmpty = function() {
return this.items.length === 0;
};
SortedSet.prototype.pop = function() {
var item = this.items.shift();
this.remove(item);
return item;
};
// reconstructs a route by concating points with their parents
function reconstructRoute(parents, point) {
var route = [];
var prevDiff = { x: 0, y: 0 };
var current = point;
var parent;
while ((parent = parents[current])) {
var diff = parent.difference(current);
if (!diff.equals(prevDiff)) {
route.unshift(current);
prevDiff = diff;
}
current = parent;
}
route.unshift(current);
return route;
}
// find points around the rectangle taking given directions in the account
function getRectPoints(bbox, directionList, opt) {
var step = opt.step;
var center = bbox.center();
var startPoints = _.chain(opt.directionMap).pick(directionList).map(function(direction) {
var x = direction.x * bbox.width / 2;
var y = direction.y * bbox.height / 2;
var point = center.clone().offset(x, y);
if (bbox.containsPoint(point)) {
point.offset(direction.x * step, direction.y * step);
}
return point.snapToGrid(step);
}).value();
return startPoints;
};
// returns a direction index from start point to end point
function getDirectionAngle(start, end, dirLen) {
var q = 360 / dirLen;
return Math.floor(g.normalizeAngle(start.theta(end) + q / 2) / q) * q;
}
function getDirectionChange(angle1, angle2) {
var dirChange = Math.abs(angle1 - angle2);
return dirChange > 180 ? 360 - dirChange : dirChange;
}
// heurestic method to determine the distance between two points
function estimateCost(from, endPoints) {
var min = Infinity;
for (var i = 0, len = endPoints.length; i < len; i++) {
var cost = from.manhattanDistance(endPoints[i]);
if (cost < min) min = cost;
};
return min;
}
// finds the route between to points/rectangles implementing A* alghoritm
function findRoute(start, end, map, opt) {
var step = opt.step;
var startPoints, endPoints;
var startCenter, endCenter;
// set of points we start pathfinding from
if (start instanceof g.rect) {
startPoints = getRectPoints(start, opt.startDirections, opt);
startCenter = start.center();
} else {
startCenter = start.clone().snapToGrid(step);
startPoints = [startCenter];
}
// set of points we want the pathfinding to finish at
if (end instanceof g.rect) {
endPoints = getRectPoints(end, opt.endDirections, opt);
endCenter = end.center();
} else {
endCenter = end.clone().snapToGrid(step);
endPoints = [endCenter];
}
// take into account only accessible end points
startPoints = _.filter(startPoints, map.isPointAccessible, map);
endPoints = _.filter(endPoints, map.isPointAccessible, map);
// Check if there is a accessible end point.
// We would have to use a fallback route otherwise.
if (startPoints.length > 0 && endPoints.length > 0) {
// The set of tentative points to be evaluated, initially containing the start points.
var openSet = new SortedSet();
// Keeps reference to a point that is immediate predecessor of given element.
var parents = {};
// Cost from start to a point along best known path.
var costs = {};
_.each(startPoints, function(point) {
var key = point.toString();
openSet.add(key, estimateCost(point, endPoints));
costs[key] = 0;
});
// directions
var dir, dirChange;
var dirs = opt.directions;
var dirLen = dirs.length;
var loopsRemain = opt.maximumLoops;
var endPointsKeys = _.invoke(endPoints, 'toString');
// main route finding loop
while (!openSet.isEmpty() && loopsRemain > 0) {
// remove current from the open list
var currentKey = openSet.pop();
var currentPoint = g.point(currentKey);
var currentDist = costs[currentKey];
var previousDirAngle = currentDirAngle;
var currentDirAngle = parents[currentKey]
? getDirectionAngle(parents[currentKey], currentPoint, dirLen)
: opt.previousDirAngle != null ? opt.previousDirAngle : getDirectionAngle(startCenter, currentPoint, dirLen);
// Check if we reached any endpoint
if (endPointsKeys.indexOf(currentKey) >= 0) {
// We don't want to allow route to enter the end point in opposite direction.
dirChange = getDirectionChange(currentDirAngle, getDirectionAngle(currentPoint, endCenter, dirLen));
if (currentPoint.equals(endCenter) || dirChange < 180) {
opt.previousDirAngle = currentDirAngle;
return reconstructRoute(parents, currentPoint);
}
}
// Go over all possible directions and find neighbors.
for (var i = 0; i < dirLen; i++) {
dir = dirs[i];
dirChange = getDirectionChange(currentDirAngle, dir.angle);
// if the direction changed rapidly don't use this point
if (dirChange > opt.maxAllowedDirectionChange) {
continue;
}
var neighborPoint = currentPoint.clone().offset(dir.offsetX, dir.offsetY);
var neighborKey = neighborPoint.toString();
// Closed points from the openSet were already evaluated.
if (openSet.isClose(neighborKey) || !map.isPointAccessible(neighborPoint)) {
continue;
}
// The current direction is ok to proccess.
var costFromStart = currentDist + dir.cost + opt.penalties[dirChange];
if (!openSet.isOpen(neighborKey) || costFromStart < costs[neighborKey]) {
// neighbor point has not been processed yet or the cost of the path
// from start is lesser than previously calcluated.
parents[neighborKey] = currentPoint;
costs[neighborKey] = costFromStart;
openSet.add(neighborKey, costFromStart + estimateCost(neighborPoint, endPoints));
};
};
loopsRemain--;
}
}
// no route found ('to' point wasn't either accessible or finding route took
// way to much calculations)
return opt.fallbackRoute(startCenter, endCenter, opt);
}
// resolve some of the options
function resolveOptions(opt) {
opt.directions = _.result(opt, 'directions');
opt.penalties = _.result(opt, 'penalties');
opt.paddingBox = _.result(opt, 'paddingBox');
_.each(opt.directions, function(direction) {
var point1 = new g.point(0, 0);
var point2 = new g.point(direction.offsetX, direction.offsetY);
var angle = g.normalizeAngle(point1.theta(point2));
direction.angle = angle;
});
}
// initiation of the route finding
function router(vertices, opt) {
resolveOptions(opt);
// enable/disable linkView perpendicular option
this.options.perpendicular = !!opt.perpendicular;
// expand boxes by specific padding
var sourceBBox = g.rect(this.sourceBBox).moveAndExpand(opt.paddingBox);
var targetBBox = g.rect(this.targetBBox).moveAndExpand(opt.paddingBox);
// pathfinding
var map = (new ObstacleMap(opt)).build(this.paper.model, this.model);
var oldVertices = _.map(vertices, g.point);
var newVertices = [];
var tailPoint = sourceBBox.center().snapToGrid(opt.step);
// find a route by concating all partial routes (routes need to go through the vertices)
// startElement -> vertex[1] -> ... -> vertex[n] -> endElement
for (var i = 0, len = oldVertices.length; i <= len; i++) {
var partialRoute = null;
var from = to || sourceBBox;
var to = oldVertices[i];
if (!to) {
to = targetBBox;
// 'to' is not a vertex. If the target is a point (i.e. it's not an element), we
// might use dragging route instead of main routing method if that is enabled.
var endingAtPoint = !this.model.get('source').id || !this.model.get('target').id;
if (endingAtPoint && _.isFunction(opt.draggingRoute)) {
// Make sure we passing points only (not rects).
var dragFrom = from instanceof g.rect ? from.center() : from;
partialRoute = opt.draggingRoute(dragFrom, to.origin(), opt);
}
}
// if partial route has not been calculated yet use the main routing method to find one
partialRoute = partialRoute || findRoute(from, to, map, opt);
var leadPoint = _.first(partialRoute);
if (leadPoint && leadPoint.equals(tailPoint)) {
// remove the first point if the previous partial route had the same point as last
partialRoute.shift();
}
tailPoint = _.last(partialRoute) || tailPoint;
Array.prototype.push.apply(newVertices, partialRoute);
};
return newVertices;
}
// public function
return function(vertices, opt, linkView) {
return router.call(linkView, vertices, _.extend({}, config, opt));
};
})(g, _);
joint.routers.metro = (function() {
if (!_.isFunction(joint.routers.manhattan)) {
throw('Metro requires the manhattan router.');
}
var config = {
// cost of a diagonal step (calculated if not defined).
diagonalCost: null,
// an array of directions to find next points on the route
directions: function() {
var step = this.step;
var diagonalCost = this.diagonalCost || Math.ceil(Math.sqrt(step * step << 1));
return [
{ offsetX: step , offsetY: 0 , cost: step },
{ offsetX: step , offsetY: step , cost: diagonalCost },
{ offsetX: 0 , offsetY: step , cost: step },
{ offsetX: -step , offsetY: step , cost: diagonalCost },
{ offsetX: -step , offsetY: 0 , cost: step },
{ offsetX: -step , offsetY: -step , cost: diagonalCost },
{ offsetX: 0 , offsetY: -step , cost: step },
{ offsetX: step , offsetY: -step , cost: diagonalCost }
];
},
maxAllowedDirectionChange: 45,
// a simple route used in situations, when main routing method fails
// (exceed loops, inaccessible).
fallbackRoute: function(from, to, opts) {
// Find a route which breaks by 45 degrees ignoring all obstacles.
var theta = from.theta(to);
var a = { x: to.x, y: from.y };
var b = { x: from.x, y: to.y };
if (theta % 180 > 90) {
var t = a;
a = b;
b = t;
}
var p1 = (theta % 90) < 45 ? a : b;
var l1 = g.line(from, p1);
var alpha = 90 * Math.ceil(theta / 90);
var p2 = g.point.fromPolar(l1.squaredLength(), g.toRad(alpha + 135), p1);
var l2 = g.line(to, p2);
var point = l1.intersection(l2);
return point ? [point.round(), to] : [to];
}
};
// public function
return function(vertices, opts, linkView) {
return joint.routers.manhattan(vertices, _.extend({}, config, opts), linkView);
};
})();
// Does not make any changes to vertices.
// Returns the arguments that are passed to it, unchanged.
joint.routers.normal = function(vertices, opt, linkView) {
return vertices;
};
// Routes the link always to/from a certain side
//
// Arguments:
// padding ... gap between the element and the first vertex. :: Default 40.
// side ... 'left' | 'right' | 'top' | 'bottom' :: Default 'bottom'.
//
joint.routers.oneSide = function(vertices, opt, linkView) {
var side = opt.side || 'bottom';
var padding = opt.padding || 40;
// LinkView contains cached source an target bboxes.
// Note that those are Geometry rectangle objects.
var sourceBBox = linkView.sourceBBox;
var targetBBox = linkView.targetBBox;
var sourcePoint = sourceBBox.center();
var targetPoint = targetBBox.center();
var coordinate, coordinateValue, dimension, direction;
switch (side) {
case 'bottom':
direction = 1;
coordinate = 'y';
dimension = 'height';
break;
case 'top':
direction = -1;
coordinate = 'y';
dimension = 'height';
break;
case 'left':
direction = -1;
coordinate = 'x';
dimension = 'width';
break;
case 'right':
direction = 1;
coordinate = 'x';
dimension = 'width';
break;
default:
throw new Error('Router: invalid side');
}
// move the points from the center of the element to outside of it.
sourcePoint[coordinate] += direction * (sourceBBox[dimension] / 2 + padding);
targetPoint[coordinate] += direction * (targetBBox[dimension] / 2 + padding);
// make link orthogonal (at least the first and last vertex).
if (direction * (sourcePoint[coordinate] - targetPoint[coordinate]) > 0) {
targetPoint[coordinate] = sourcePoint[coordinate];
} else {
sourcePoint[coordinate] = targetPoint[coordinate];
}
return [sourcePoint].concat(vertices, targetPoint);
};
joint.routers.orthogonal = (function() {
// bearing -> opposite bearing
var opposite = {
N: 'S',
S: 'N',
E: 'W',
W: 'E'
};
// bearing -> radians
var radians = {
N: -Math.PI / 2 * 3,
S: -Math.PI / 2,
E: 0,
W: Math.PI
};
// HELPERS //
// simple bearing method (calculates only orthogonal cardinals)
function bearing(from, to) {
if (from.x == to.x) return from.y > to.y ? 'N' : 'S';
if (from.y == to.y) return from.x > to.x ? 'W' : 'E';
return null;
}
// returns either width or height of a bbox based on the given bearing
function boxSize(bbox, brng) {
return bbox[brng == 'W' || brng == 'E' ? 'width' : 'height'];
}
// expands a box by specific value
function expand(bbox, val) {
return g.rect(bbox).moveAndExpand({ x: -val, y: -val, width: 2 * val, height: 2 * val });
}
// transform point to a rect
function pointBox(p) {
return g.rect(p.x, p.y, 0, 0);
}
// returns a minimal rect which covers the given boxes
function boundary(bbox1, bbox2) {
var x1 = Math.min(bbox1.x, bbox2.x);
var y1 = Math.min(bbox1.y, bbox2.y);
var x2 = Math.max(bbox1.x + bbox1.width, bbox2.x + bbox2.width);
var y2 = Math.max(bbox1.y + bbox1.height, bbox2.y + bbox2.height);
return g.rect(x1, y1, x2 - x1, y2 - y1);
}
// returns a point `p` where lines p,p1 and p,p2 are perpendicular and p is not contained
// in the given box
function freeJoin(p1, p2, bbox) {
var p = g.point(p1.x, p2.y);
if (bbox.containsPoint(p)) p = g.point(p2.x, p1.y);
// kept for reference
// if (bbox.containsPoint(p)) p = null;
return p;
}
// PARTIAL ROUTERS //
function vertexVertex(from, to, brng) {
var p1 = g.point(from.x, to.y);
var p2 = g.point(to.x, from.y);
var d1 = bearing(from, p1);
var d2 = bearing(from, p2);
var xBrng = opposite[brng];
var p = (d1 == brng || (d1 != xBrng && (d2 == xBrng || d2 != brng))) ? p1 : p2;
return { points: [p], direction: bearing(p, to) };
}
function elementVertex(from, to, fromBBox) {
var p = freeJoin(from, to, fromBBox);
return { points: [p], direction: bearing(p, to) };
}
function vertexElement(from, to, toBBox, brng) {
var route = {};
var pts = [g.point(from.x, to.y), g.point(to.x, from.y)];
var freePts = _.filter(pts, function(pt) { return !toBBox.containsPoint(pt); });
var freeBrngPts = _.filter(freePts, function(pt) { return bearing(pt, from) != brng; });
var p;
if (freeBrngPts.length > 0) {
// try to pick a point which bears the same direction as the previous segment
p = _.filter(freeBrngPts, function(pt) { return bearing(from, pt) == brng; }).pop();
p = p || freeBrngPts[0];
route.points = [p];
route.direction = bearing(p, to);
} else {
// Here we found only points which are either contained in the element or they would create
// a link segment going in opposite direction from the previous one.
// We take the point inside element and move it outside the element in the direction the
// route is going. Now we can join this point with the current end (using freeJoin).
p = _.difference(pts, freePts)[0];
var p2 = g.point(to).move(p, -boxSize(toBBox, brng) / 2);
var p1 = freeJoin(p2, from, toBBox);
route.points = [p1, p2];
route.direction = bearing(p2, to);
}
return route;
}
function elementElement(from, to, fromBBox, toBBox) {
var route = elementVertex(to, from, toBBox);
var p1 = route.points[0];
if (fromBBox.containsPoint(p1)) {
route = elementVertex(from, to, fromBBox);
var p2 = route.points[0];
if (toBBox.containsPoint(p2)) {
var fromBorder = g.point(from).move(p2, -boxSize(fromBBox, bearing(from, p2)) / 2);
var toBorder = g.point(to).move(p1, -boxSize(toBBox, bearing(to, p1)) / 2);
var mid = g.line(fromBorder, toBorder).midpoint();
var startRoute = elementVertex(from, mid, fromBBox);
var endRoute = vertexVertex(mid, to, startRoute.direction);
route.points = [startRoute.points[0], endRoute.points[0]];
route.direction = endRoute.direction;
}
}
return route;
}
// Finds route for situations where one of end is inside the other.
// Typically the route is conduct outside the outer element first and
// let go back to the inner element.
function insideElement(from, to, fromBBox, toBBox, brng) {
var route = {};
var bndry = expand(boundary(fromBBox, toBBox), 1);
// start from the point which is closer to the boundary
var reversed = bndry.center().distance(to) > bndry.center().distance(from);
var start = reversed ? to : from;
var end = reversed ? from : to;
var p1, p2, p3;
if (brng) {
// Points on circle with radius equals 'W + H` are always outside the rectangle
// with width W and height H if the center of that circle is the center of that rectangle.
p1 = g.point.fromPolar(bndry.width + bndry.height, radians[brng], start);
p1 = bndry.pointNearestToPoint(p1).move(p1, -1);
} else {
p1 = bndry.pointNearestToPoint(start).move(start, 1);
}
p2 = freeJoin(p1, end, bndry);
if (p1.round().equals(p2.round())) {
p2 = g.point.fromPolar(bndry.width + bndry.height, g.toRad(p1.theta(start)) + Math.PI / 2, end);
p2 = bndry.pointNearestToPoint(p2).move(end, 1).round();
p3 = freeJoin(p1, p2, bndry);
route.points = reversed ? [p2, p3, p1] : [p1, p3, p2];
} else {
route.points = reversed ? [p2, p1] : [p1, p2];
}
route.direction = reversed ? bearing(p1, to) : bearing(p2, to);
return route;
}
// MAIN ROUTER //
// Return points that one needs to draw a connection through in order to have a orthogonal link
// routing from source to target going through `vertices`.
function findOrthogonalRoute(vertices, opt, linkView) {
var padding = opt.elementPadding || 20;
var orthogonalVertices = [];
var sourceBBox = expand(linkView.sourceBBox, padding);
var targetBBox = expand(linkView.targetBBox, padding);
vertices = _.map(vertices, g.point);
vertices.unshift(sourceBBox.center());
vertices.push(targetBBox.center());
var brng;
for (var i = 0, max = vertices.length - 1; i < max; i++) {
var route = null;
var from = vertices[i];
var to = vertices[i + 1];
var isOrthogonal = !!bearing(from, to);
if (i == 0) {
if (i + 1 == max) { // route source -> target
// Expand one of elements by 1px so we detect also situations when they
// are positioned one next other with no gap between.
if (sourceBBox.intersect(expand(targetBBox, 1))) {
route = insideElement(from, to, sourceBBox, targetBBox);
} else if (!isOrthogonal) {
route = elementElement(from, to, sourceBBox, targetBBox);
}
} else { // route source -> vertex
if (sourceBBox.containsPoint(to)) {
route = insideElement(from, to, sourceBBox, expand(pointBox(to), padding));
} else if (!isOrthogonal) {
route = elementVertex(from, to, sourceBBox);
}
}
} else if (i + 1 == max) { // route vertex -> target
var orthogonalLoop = isOrthogonal && bearing(to, from) == brng;
if (targetBBox.containsPoint(from) || orthogonalLoop) {
route = insideElement(from, to, expand(pointBox(from), padding), targetBBox, brng);
} else if (!isOrthogonal) {
route = vertexElement(from, to, targetBBox, brng);
}
} else if (!isOrthogonal) { // route vertex -> vertex
route = vertexVertex(from, to, brng);
}
if (route) {
Array.prototype.push.apply(orthogonalVertices, route.points);
brng = route.direction;
} else {
// orthogonal route and not looped
brng = bearing(from, to);
}
if (i + 1 < max) {
orthogonalVertices.push(to);
}
}
return orthogonalVertices;
};
return findOrthogonalRoute;
})();
joint.connectors.normal = function(sourcePoint, targetPoint, vertices) {
// Construct the `d` attribute of the `` element.
var d = ['M', sourcePoint.x, sourcePoint.y];
_.each(vertices, function(vertex) {
d.push(vertex.x, vertex.y);
});
d.push(targetPoint.x, targetPoint.y);
return d.join(' ');
};
joint.connectors.rounded = function(sourcePoint, targetPoint, vertices, opts) {
opts = opts || {};
var offset = opts.radius || 10;
var c1, c2, d1, d2, prev, next;
// Construct the `d` attribute of the `` element.
var d = ['M', sourcePoint.x, sourcePoint.y];
_.each(vertices, function(vertex, index) {
// the closest vertices
prev = vertices[index - 1] || sourcePoint;
next = vertices[index + 1] || targetPoint;
// a half distance to the closest vertex
d1 = d2 || g.point(vertex).distance(prev) / 2;
d2 = g.point(vertex).distance(next) / 2;
// control points
c1 = g.point(vertex).move(prev, -Math.min(offset, d1)).round();
c2 = g.point(vertex).move(next, -Math.min(offset, d2)).round();
d.push(c1.x, c1.y, 'S', vertex.x, vertex.y, c2.x, c2.y, 'L');
});
d.push(targetPoint.x, targetPoint.y);
return d.join(' ');
};
joint.connectors.smooth = function(sourcePoint, targetPoint, vertices) {
var d;
if (vertices.length) {
d = g.bezier.curveThroughPoints([sourcePoint].concat(vertices).concat([targetPoint]));
} else {
// if we have no vertices use a default cubic bezier curve, cubic bezier requires
// two control points. The two control points are both defined with X as mid way
// between the source and target points. SourceControlPoint Y is equal to sourcePoint Y
// and targetControlPointY being equal to targetPointY. Handle situation were
// sourcePointX is greater or less then targetPointX.
var controlPointX = (sourcePoint.x < targetPoint.x)
? targetPoint.x - ((targetPoint.x - sourcePoint.x) / 2)
: sourcePoint.x - ((sourcePoint.x - targetPoint.x) / 2);
d = [
'M', sourcePoint.x, sourcePoint.y,
'C', controlPointX, sourcePoint.y, controlPointX, targetPoint.y,
targetPoint.x, targetPoint.y
];
}
return d.join(' ');
};
joint.connectors.jumpover = (function(_, g) {
// default size of jump if not specified in options
var JUMP_SIZE = 5;
// available jump types
var JUMP_TYPES = ['arc', 'gap', 'cubic'];
// takes care of math. error for case when jump is too close to end of line
var CLOSE_PROXIMITY_PADDING = 1;
// list of connector types not to jump over.
var IGNORED_CONNECTORS = ['smooth'];
/**
* Transform start/end and vertices into series of lines
* @param {g.point} sourcePoint start point
* @param {g.point} targetPoint end point
* @param {g.point[]} vertices optional list of vertices
* @return {g.line[]} [description]
*/
function createLines(sourcePoint, targetPoint, vertices) {
// make a flattened array of all points
var points = [].concat(sourcePoint, vertices, targetPoint);
return points.reduce(function(resultLines, point, idx) {
// if there is a next point, make a line with it
var nextPoint = points[idx + 1];
if (nextPoint != null) {
resultLines[idx] = g.line(point, nextPoint);
}
return resultLines;
}, []);
}
function setupUpdating(jumpOverLinkView) {
var updateList = jumpOverLinkView.paper._jumpOverUpdateList;
// first time setup for this paper
if (updateList == null) {
updateList = jumpOverLinkView.paper._jumpOverUpdateList = [];
jumpOverLinkView.paper.on('cell:pointerup', updateJumpOver);
jumpOverLinkView.paper.model.on('reset', function() {
updateList = [];
});
}
// add this link to a list so it can be updated when some other link is updated
if (updateList.indexOf(jumpOverLinkView) < 0) {
updateList.push(jumpOverLinkView);
// watch for change of connector type or removal of link itself
// to remove the link from a list of jump over connectors
jumpOverLinkView.listenToOnce(jumpOverLinkView.model, 'change:connector remove', function() {
updateList.splice(updateList.indexOf(jumpOverLinkView), 1);
});
}
}
/**
* Handler for a batch:stop event to force
* update of all registered links with jump over connector
* @param {object} batchEvent optional object with info about batch
*/
function updateJumpOver() {
var updateList = this._jumpOverUpdateList;
for (var i = 0; i < updateList.length; i++) {
updateList[i].update();
}
}
/**
* Utility function to collect all intersection poinst of a single
* line against group of other lines.
* @param {g.line} line where to find points
* @param {g.line[]} crossCheckLines lines to cross
* @return {g.point[]} list of intersection points
*/
function findLineIntersections(line, crossCheckLines) {
return _(crossCheckLines).map(function(crossCheckLine) {
return line.intersection(crossCheckLine);
}).compact().value();
}
/**
* Sorting function for list of points by their distance.
* @param {g.point} p1 first point
* @param {g.point} p2 second point
* @return {number} squared distance between points
*/
function sortPoints(p1, p2) {
return g.line(p1, p2).squaredLength();
}
/**
* Split input line into multiple based on intersection points.
* @param {g.line} line input line to split
* @param {g.point[]} intersections poinst where to split the line
* @param {number} jumpSize the size of jump arc (length empty spot on a line)
* @return {g.line[]} list of lines being split
*/
function createJumps(line, intersections, jumpSize) {
return intersections.reduce(function(resultLines, point, idx) {
// skipping points that were merged with the previous line
// to make bigger arc over multiple lines that are close to each other
if (point.skip === true) {
return resultLines;
}
// always grab the last line from buffer and modify it
var lastLine = resultLines.pop() || line;
// calculate start and end of jump by moving by a given size of jump
var jumpStart = g.point(point).move(lastLine.start, -(jumpSize));
var jumpEnd = g.point(point).move(lastLine.start, +(jumpSize));
// now try to look at the next intersection point
var nextPoint = intersections[idx + 1];
if (nextPoint != null) {
var distance = jumpEnd.distance(nextPoint);
if (distance <= jumpSize) {
// next point is close enough, move the jump end by this
// difference and mark the next point to be skipped
jumpEnd = nextPoint.move(lastLine.start, distance);
nextPoint.skip = true;
}
} else {
// this block is inside of `else` as an optimization so the distance is
// not calculated when we know there are no other intersection points
var endDistance = jumpStart.distance(lastLine.end);
// if the end is too close to possible jump, draw remaining line instead of a jump
if (endDistance < jumpSize * 2 + CLOSE_PROXIMITY_PADDING) {
resultLines.push(lastLine);
return resultLines;
}
}
var startDistance = jumpEnd.distance(lastLine.start);
if (startDistance < jumpSize * 2 + CLOSE_PROXIMITY_PADDING) {
// if the start of line is too close to jump, draw that line instead of a jump
resultLines.push(lastLine);
return resultLines;
}
// finally create a jump line
var jumpLine = g.line(jumpStart, jumpEnd);
// it's just simple line but with a `isJump` property
jumpLine.isJump = true;
resultLines.push(
g.line(lastLine.start, jumpStart),
jumpLine,
g.line(jumpEnd, lastLine.end)
);
return resultLines;
}, []);
}
/**
* Assemble `D` attribute of a SVG path by iterating given lines.
* @param {g.line[]} lines source lines to use
* @param {number} jumpSize the size of jump arc (length empty spot on a line)
* @return {string}
*/
function buildPath(lines, jumpSize, jumpType) {
// first move to the start of a first line
var start = ['M', lines[0].start.x, lines[0].start.y];
// make a paths from lines
var paths = _(lines).map(function(line) {
if (line.isJump) {
var diff;
if (jumpType === 'arc') {
diff = line.start.difference(line.end);
// determine rotation of arc based on difference between points
var xAxisRotate = Number(diff.x < 0 && diff.y < 0);
// for a jump line we create an arc instead
return ['A', jumpSize, jumpSize, 0, 0, xAxisRotate, line.end.x, line.end.y];
} else if (jumpType === 'gap') {
return ['M', line.end.x, line.end.y];
} else if (jumpType === 'cubic') {
diff = line.start.difference(line.end);
var angle = line.start.theta(line.end);
var xOffset = jumpSize * 0.6;
var yOffset = jumpSize * 1.35;
// determine rotation of curve based on difference between points
if (diff.x < 0 && diff.y < 0) {
yOffset *= -1;
}
var controlStartPoint = g.point(line.start.x + xOffset, line.start.y + yOffset).rotate(line.start, angle);
var controlEndPoint = g.point(line.end.x - xOffset, line.end.y + yOffset).rotate(line.end, angle);
// create a cubic bezier curve
return ['C', controlStartPoint.x, controlStartPoint.y, controlEndPoint.x, controlEndPoint.y, line.end.x, line.end.y];
}
}
return ['L', line.end.x, line.end.y];
}).flatten().value();
return [].concat(start, paths).join(' ');
}
/**
* Actual connector function that will be run on every update.
* @param {g.point} sourcePoint start point of this link
* @param {g.point} targetPoint end point of this link
* @param {g.point[]} vertices of this link
* @param {object} opts options
* @property {number} size optional size of a jump arc
* @return {string} created `D` attribute of SVG path
*/
return function(sourcePoint, targetPoint, vertices, opts) { // eslint-disable-line max-params
setupUpdating(this);
var jumpSize = opts.size || JUMP_SIZE;
var jumpType = opts.jump && ('' + opts.jump).toLowerCase();
var ignoreConnectors = opts.ignoreConnectors || IGNORED_CONNECTORS;
// grab the first jump type as a default if specified one is invalid
if (JUMP_TYPES.indexOf(jumpType) === -1) {
jumpType = JUMP_TYPES[0];
}
var paper = this.paper;
var graph = paper.model;
var allLinks = graph.getLinks();
// there is just one link, draw it directly
if (allLinks.length === 1) {
return buildPath(
createLines(sourcePoint, targetPoint, vertices),
jumpSize, jumpType
);
}
var thisModel = this.model;
var thisIndex = allLinks.indexOf(thisModel);
var defaultConnector = paper.options.defaultConnector || {};
// not all links are meant to be jumped over.
var links = allLinks.filter(function(link, idx) {
var connector = link.get('connector') || defaultConnector;
// avoid jumping over links with connector type listed in `ignored connectors`.
if (_.contains(ignoreConnectors, connector.name)) {
return false;
}
// filter out links that are above this one and have the same connector type
// otherwise there would double hoops for each intersection
if (idx > thisIndex) {
return connector.name !== 'jumpover';
}
return true;
});
// find views for all links
var linkViews = links.map(function(link) {
return paper.findViewByModel(link);
});
// create lines for this link
var thisLines = createLines(
sourcePoint,
targetPoint,
vertices
);
// create lines for all other links
var linkLines = linkViews.map(function(linkView) {
if (linkView == null) {
return [];
}
if (linkView === this) {
return thisLines;
}
return createLines(
linkView.sourcePoint,
linkView.targetPoint,
linkView.route
);
}, this);
// transform lines for this link by splitting with jump lines at
// points of intersection with other links
var jumpingLines = thisLines.reduce(function(resultLines, thisLine) {
// iterate all links and grab the intersections with this line
// these are then sorted by distance so the line can be split more easily
var intersections = _(links).map(function(link, i) {
// don't intersection with itself
if (link === thisModel) {
return null;
}
return findLineIntersections(thisLine, linkLines[i]);
}).flatten().compact().sortBy(_.partial(sortPoints, thisLine.start)).value();
if (intersections.length > 0) {
// split the line based on found intersection points
resultLines.push.apply(resultLines, createJumps(thisLine, intersections, jumpSize));
} else {
// without any intersection the line goes uninterrupted
resultLines.push(thisLine);
}
return resultLines;
}, []);
return buildPath(jumpingLines, jumpSize, jumpType);
};
}(_, g));
joint.highlighters.addClass = {
className: 'highlighted',
highlight: function(cellView, magnetEl, opt) {
var className = opt.className || this.className;
V(magnetEl).addClass(className);
},
unhighlight: function(cellView, magnetEl, opt) {
var className = opt.className || this.className;
V(magnetEl).removeClass(className);
}
};
joint.highlighters.opacity = {
highlight: function(cellView, magnetEl, opt) {
V(magnetEl).addClass('joint-highlight-opacity');
},
unhighlight: function(cellView, magnetEl, opt) {
V(magnetEl).removeClass('joint-highlight-opacity');
}
};
joint.highlighters.stroke = {
defaultOptions: {
padding: 3,
rx: 0,
ry: 0
},
_views: {},
highlight: function(cellView, magnetEl, opt) {
// Only highlight once.
if (this._views[magnetEl.id]) return;
opt = _.defaults(opt || {}, this.defaultOptions);
var magnetVel = V(magnetEl);
var magnetBBox = magnetVel.bbox(true/* without transforms */);
try {
var pathData = magnetVel.convertToPathData();
} catch (error) {
// Failed to get path data from magnet element.
// Draw a rectangle around the entire cell view instead.
pathData = V.rectToPath(_.extend({}, opt, magnetBBox));
}
var highlightVel = V('path').attr({
d: pathData,
'class': 'joint-highlight-stroke',
'pointer-events': 'none'
});
highlightVel.transform(cellView.el.getCTM().inverse());
highlightVel.transform(magnetEl.getCTM());
var padding = opt.padding;
if (padding) {
// Add padding to the highlight element.
var cx = magnetBBox.x + (magnetBBox.width / 2);
var cy = magnetBBox.y + (magnetBBox.height / 2);
var sx = (magnetBBox.width + padding) / magnetBBox.width;
var sy = (magnetBBox.height + padding) / magnetBBox.height;
highlightVel.transform({
a: sx,
b: 0,
c: 0,
d: sy,
e: cx - sx * cx,
f: cy - sy * cy
});
}
// This will handle the joint-theme-* class name for us.
var highlightView = this._views[magnetEl.id] = new joint.mvc.View({
// This is necessary because we're passing in a vectorizer element (not jQuery).
el: highlightVel.node,
$el: highlightVel
});
// Remove the highlight view when the cell is removed from the graph.
highlightView.listenTo(cellView.model, 'remove', highlightView.remove);
cellView.vel.append(highlightVel);
},
unhighlight: function(cellView, magnetEl, opt) {
opt = _.defaults(opt || {}, this.defaultOptions);
if (this._views[magnetEl.id]) {
this._views[magnetEl.id].remove();
this._views[magnetEl.id] = null;
}
}
};
// JointJS library.
// (c) 2011-2013 client IO
joint.shapes.erd = {};
joint.shapes.erd.Entity = joint.dia.Element.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'erd.Entity',
size: { width: 150, height: 60 },
attrs: {
'.outer': {
fill: '#2ECC71', stroke: '#27AE60', 'stroke-width': 2,
points: '100,0 100,60 0,60 0,0'
},
'.inner': {
fill: '#2ECC71', stroke: '#27AE60', 'stroke-width': 2,
points: '95,5 95,55 5,55 5,5',
display: 'none'
},
text: {
text: 'Entity',
'font-family': 'Arial', 'font-size': 14,
ref: '.outer', 'ref-x': .5, 'ref-y': .5,
'x-alignment': 'middle', 'y-alignment': 'middle'
}
}
}, joint.dia.Element.prototype.defaults)
});
joint.shapes.erd.WeakEntity = joint.shapes.erd.Entity.extend({
defaults: joint.util.deepSupplement({
type: 'erd.WeakEntity',
attrs: {
'.inner' : { display: 'auto' },
text: { text: 'Weak Entity' }
}
}, joint.shapes.erd.Entity.prototype.defaults)
});
joint.shapes.erd.Relationship = joint.dia.Element.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'erd.Relationship',
size: { width: 80, height: 80 },
attrs: {
'.outer': {
fill: '#3498DB', stroke: '#2980B9', 'stroke-width': 2,
points: '40,0 80,40 40,80 0,40'
},
'.inner': {
fill: '#3498DB', stroke: '#2980B9', 'stroke-width': 2,
points: '40,5 75,40 40,75 5,40',
display: 'none'
},
text: {
text: 'Relationship',
'font-family': 'Arial', 'font-size': 12,
ref: '.', 'ref-x': .5, 'ref-y': .5,
'x-alignment': 'middle', 'y-alignment': 'middle'
}
}
}, joint.dia.Element.prototype.defaults)
});
joint.shapes.erd.IdentifyingRelationship = joint.shapes.erd.Relationship.extend({
defaults: joint.util.deepSupplement({
type: 'erd.IdentifyingRelationship',
attrs: {
'.inner': { display: 'auto' },
text: { text: 'Identifying' }
}
}, joint.shapes.erd.Relationship.prototype.defaults)
});
joint.shapes.erd.Attribute = joint.dia.Element.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'erd.Attribute',
size: { width: 100, height: 50 },
attrs: {
'ellipse': {
transform: 'translate(50, 25)'
},
'.outer': {
stroke: '#D35400', 'stroke-width': 2,
cx: 0, cy: 0, rx: 50, ry: 25,
fill: '#E67E22'
},
'.inner': {
stroke: '#D35400', 'stroke-width': 2,
cx: 0, cy: 0, rx: 45, ry: 20,
fill: '#E67E22', display: 'none'
},
text: {
'font-family': 'Arial', 'font-size': 14,
ref: '.', 'ref-x': .5, 'ref-y': .5,
'x-alignment': 'middle', 'y-alignment': 'middle'
}
}
}, joint.dia.Element.prototype.defaults)
});
joint.shapes.erd.Multivalued = joint.shapes.erd.Attribute.extend({
defaults: joint.util.deepSupplement({
type: 'erd.Multivalued',
attrs: {
'.inner': { display: 'block' },
text: { text: 'multivalued' }
}
}, joint.shapes.erd.Attribute.prototype.defaults)
});
joint.shapes.erd.Derived = joint.shapes.erd.Attribute.extend({
defaults: joint.util.deepSupplement({
type: 'erd.Derived',
attrs: {
'.outer': { 'stroke-dasharray': '3,5' },
text: { text: 'derived' }
}
}, joint.shapes.erd.Attribute.prototype.defaults)
});
joint.shapes.erd.Key = joint.shapes.erd.Attribute.extend({
defaults: joint.util.deepSupplement({
type: 'erd.Key',
attrs: {
ellipse: { 'stroke-width': 4 },
text: { text: 'key', 'font-weight': '800', 'text-decoration': 'underline' }
}
}, joint.shapes.erd.Attribute.prototype.defaults)
});
joint.shapes.erd.Normal = joint.shapes.erd.Attribute.extend({
defaults: joint.util.deepSupplement({
type: 'erd.Normal',
attrs: { text: { text: 'Normal' }}
}, joint.shapes.erd.Attribute.prototype.defaults)
});
joint.shapes.erd.ISA = joint.dia.Element.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'erd.ISA',
size: { width: 100, height: 50 },
attrs: {
polygon: {
points: '0,0 50,50 100,0',
fill: '#F1C40F', stroke: '#F39C12', 'stroke-width': 2
},
text: {
text: 'ISA', 'font-size': 18,
ref: 'polygon', 'ref-x': .5, 'ref-y': .3,
'x-alignment': 'middle', 'y-alignment': 'middle'
}
}
}, joint.dia.Element.prototype.defaults)
});
joint.shapes.erd.Line = joint.dia.Link.extend({
defaults: { type: 'erd.Line' },
cardinality: function(value) {
this.set('labels', [{ position: -20, attrs: { text: { dy: -8, text: value }}}]);
}
});
joint.shapes.fsa = {};
joint.shapes.fsa.State = joint.shapes.basic.Circle.extend({
defaults: joint.util.deepSupplement({
type: 'fsa.State',
attrs: {
circle: { 'stroke-width': 3 },
text: { 'font-weight': '800' }
}
}, joint.shapes.basic.Circle.prototype.defaults)
});
joint.shapes.fsa.StartState = joint.dia.Element.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'fsa.StartState',
size: { width: 20, height: 20 },
attrs: {
circle: {
transform: 'translate(10, 10)',
r: 10,
fill: '#000000'
}
}
}, joint.dia.Element.prototype.defaults)
});
joint.shapes.fsa.EndState = joint.dia.Element.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'fsa.EndState',
size: { width: 20, height: 20 },
attrs: {
'.outer': {
transform: 'translate(10, 10)',
r: 10,
fill: '#ffffff',
stroke: '#000000'
},
'.inner': {
transform: 'translate(10, 10)',
r: 6,
fill: '#000000'
}
}
}, joint.dia.Element.prototype.defaults)
});
joint.shapes.fsa.Arrow = joint.dia.Link.extend({
defaults: joint.util.deepSupplement({
type: 'fsa.Arrow',
attrs: { '.marker-target': { d: 'M 10 0 L 0 5 L 10 10 z' }},
smooth: true
}, joint.dia.Link.prototype.defaults)
});
// JointJS library.
// (c) 2011-2013 client IO
joint.shapes.org = {};
joint.shapes.org.Member = joint.dia.Element.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'org.Member',
size: { width: 180, height: 70 },
attrs: {
rect: { width: 170, height: 60 },
'.card': {
fill: '#FFFFFF', stroke: '#000000', 'stroke-width': 2,
'pointer-events': 'visiblePainted', rx: 10, ry: 10
},
image: {
width: 48, height: 48,
ref: '.card', 'ref-x': 10, 'ref-y': 5
},
'.rank': {
'text-decoration': 'underline',
ref: '.card', 'ref-x': 0.9, 'ref-y': 0.2,
'font-family': 'Courier New', 'font-size': 14,
'text-anchor': 'end'
},
'.name': {
'font-weight': '800',
ref: '.card', 'ref-x': 0.9, 'ref-y': 0.6,
'font-family': 'Courier New', 'font-size': 14,
'text-anchor': 'end'
}
}
}, joint.dia.Element.prototype.defaults)
});
joint.shapes.org.Arrow = joint.dia.Link.extend({
defaults: {
type: 'org.Arrow',
source: { selector: '.card' }, target: { selector: '.card' },
attrs: { '.connection': { stroke: '#585858', 'stroke-width': 3 }},
z: -1
}
});
// JointJS library.
// (c) 2011-2013 client IO
joint.shapes.chess = {};
joint.shapes.chess.KingWhite = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.KingWhite',
size: { width: 42, height: 38 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.KingBlack = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.KingBlack',
size: { width: 42, height: 38 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.QueenWhite = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.QueenWhite',
size: { width: 42, height: 38 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.QueenBlack = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.QueenBlack',
size: { width: 42, height: 38 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.RookWhite = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.RookWhite',
size: { width: 32, height: 34 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.RookBlack = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.RookBlack',
size: { width: 32, height: 34 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.BishopWhite = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.BishopWhite',
size: { width: 38, height: 38 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.BishopBlack = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.BishopBlack',
size: { width: 38, height: 38 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.KnightWhite = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.KnightWhite',
size: { width: 38, height: 37 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.KnightBlack = joint.shapes.basic.Generic.extend({
markup: ' ',
defaults: joint.util.deepSupplement({
type: 'chess.KnightBlack',
size: { width: 38, height: 37 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.PawnWhite = joint.shapes.basic.Generic.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'chess.PawnWhite',
size: { width: 28, height: 33 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.chess.PawnBlack = joint.shapes.basic.Generic.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'chess.PawnBlack',
size: { width: 28, height: 33 }
}, joint.shapes.basic.Generic.prototype.defaults)
});
// JointJS library.
// (c) 2011-2013 client IO
joint.shapes.pn = {};
joint.shapes.pn.Place = joint.shapes.basic.Generic.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'pn.Place',
size: { width: 50, height: 50 },
attrs: {
'.root': {
r: 25,
fill: '#ffffff',
stroke: '#000000',
transform: 'translate(25, 25)'
},
'.label': {
'text-anchor': 'middle',
'ref-x': .5,
'ref-y': -20,
ref: '.root',
fill: '#000000',
'font-size': 12
},
'.tokens > circle': {
fill: '#000000',
r: 5
},
'.tokens.one > circle': { transform: 'translate(25, 25)' },
'.tokens.two > circle:nth-child(1)': { transform: 'translate(19, 25)' },
'.tokens.two > circle:nth-child(2)': { transform: 'translate(31, 25)' },
'.tokens.three > circle:nth-child(1)': { transform: 'translate(18, 29)' },
'.tokens.three > circle:nth-child(2)': { transform: 'translate(25, 19)' },
'.tokens.three > circle:nth-child(3)': { transform: 'translate(32, 29)' },
'.tokens.alot > text': {
transform: 'translate(25, 18)',
'text-anchor': 'middle',
fill: '#000000'
}
}
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.pn.PlaceView = joint.dia.ElementView.extend({
initialize: function() {
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.model.on('change:tokens', function() {
this.renderTokens();
this.update();
}, this);
},
render: function() {
joint.dia.ElementView.prototype.render.apply(this, arguments);
this.renderTokens();
this.update();
},
renderTokens: function() {
var $tokens = this.$('.tokens').empty();
$tokens[0].className.baseVal = 'tokens';
var tokens = this.model.get('tokens');
if (!tokens) return;
switch (tokens) {
case 1:
$tokens[0].className.baseVal += ' one';
$tokens.append(V('').node);
break;
case 2:
$tokens[0].className.baseVal += ' two';
$tokens.append(V('').node, V('').node);
break;
case 3:
$tokens[0].className.baseVal += ' three';
$tokens.append(V('').node, V('').node, V('').node);
break;
default:
$tokens[0].className.baseVal += ' alot';
$tokens.append(V('').text(tokens + '' ).node);
break;
}
}
});
joint.shapes.pn.Transition = joint.shapes.basic.Generic.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'pn.Transition',
size: { width: 12, height: 50 },
attrs: {
'rect': {
width: 12,
height: 50,
fill: '#000000',
stroke: '#000000'
},
'.label': {
'text-anchor': 'middle',
'ref-x': .5,
'ref-y': -20,
ref: 'rect',
fill: '#000000',
'font-size': 12
}
}
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.pn.Link = joint.dia.Link.extend({
defaults: joint.util.deepSupplement({
type: 'pn.Link',
attrs: { '.marker-target': { d: 'M 10 0 L 0 5 L 10 10 z' }}
}, joint.dia.Link.prototype.defaults)
});
// JointJS library.
// (c) 2011-2013 client IO
joint.shapes.devs = {};
joint.shapes.devs.Model = joint.shapes.basic.Generic.extend(_.extend({}, joint.shapes.basic.PortsModelInterface, {
markup: '',
portMarkup: '',
defaults: joint.util.deepSupplement({
type: 'devs.Model',
size: { width: 1, height: 1 },
inPorts: [],
outPorts: [],
attrs: {
'.': { magnet: false },
'.body': {
width: 150, height: 250,
stroke: '#000000'
},
'.port-body': {
r: 10,
magnet: true,
stroke: '#000000'
},
text: {
'pointer-events': 'none'
},
'.label': { text: 'Model', 'ref-x': .5, 'ref-y': 10, ref: '.body', 'text-anchor': 'middle', fill: '#000000' },
'.inPorts .port-label': { x:-15, dy: 4, 'text-anchor': 'end', fill: '#000000' },
'.outPorts .port-label':{ x: 15, dy: 4, fill: '#000000' }
}
}, joint.shapes.basic.Generic.prototype.defaults),
getPortAttrs: function(portName, index, total, selector, type) {
var attrs = {};
var portClass = 'port' + index;
var portSelector = selector + '>.' + portClass;
var portLabelSelector = portSelector + '>.port-label';
var portBodySelector = portSelector + '>.port-body';
attrs[portLabelSelector] = { text: portName };
attrs[portBodySelector] = { port: { id: portName || _.uniqueId(type) , type: type } };
attrs[portSelector] = { ref: '.body', 'ref-y': (index + 0.5) * (1 / total) };
if (selector === '.outPorts') { attrs[portSelector]['ref-dx'] = 0; }
return attrs;
}
}));
joint.shapes.devs.Atomic = joint.shapes.devs.Model.extend({
defaults: joint.util.deepSupplement({
type: 'devs.Atomic',
size: { width: 80, height: 80 },
attrs: {
'.body': { fill: 'salmon' },
'.label': { text: 'Atomic' },
'.inPorts .port-body': { fill: 'PaleGreen' },
'.outPorts .port-body': { fill: 'Tomato' }
}
}, joint.shapes.devs.Model.prototype.defaults)
});
joint.shapes.devs.Coupled = joint.shapes.devs.Model.extend({
defaults: joint.util.deepSupplement({
type: 'devs.Coupled',
size: { width: 200, height: 300 },
attrs: {
'.body': { fill: 'seaGreen' },
'.label': { text: 'Coupled' },
'.inPorts .port-body': { fill: 'PaleGreen' },
'.outPorts .port-body': { fill: 'Tomato' }
}
}, joint.shapes.devs.Model.prototype.defaults)
});
joint.shapes.devs.Link = joint.dia.Link.extend({
defaults: {
type: 'devs.Link',
attrs: { '.connection' : { 'stroke-width' : 2 }}
}
});
joint.shapes.devs.ModelView = joint.dia.ElementView.extend(joint.shapes.basic.PortsViewInterface);
joint.shapes.devs.AtomicView = joint.shapes.devs.ModelView;
joint.shapes.devs.CoupledView = joint.shapes.devs.ModelView;
joint.shapes.uml = {};
joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
markup: [
'',
'',
'',
'',
'',
''
].join(''),
defaults: joint.util.deepSupplement({
type: 'uml.Class',
attrs: {
rect: { 'width': 200 },
'.uml-class-name-rect': { 'stroke': 'black', 'stroke-width': 2, 'fill': '#3498db' },
'.uml-class-attrs-rect': { 'stroke': 'black', 'stroke-width': 2, 'fill': '#2980b9' },
'.uml-class-methods-rect': { 'stroke': 'black', 'stroke-width': 2, 'fill': '#2980b9' },
'.uml-class-name-text': {
'ref': '.uml-class-name-rect', 'ref-y': .5, 'ref-x': .5, 'text-anchor': 'middle', 'y-alignment': 'middle', 'font-weight': 'bold',
'fill': 'black', 'font-size': 12, 'font-family': 'Times New Roman'
},
'.uml-class-attrs-text': {
'ref': '.uml-class-attrs-rect', 'ref-y': 5, 'ref-x': 5,
'fill': 'black', 'font-size': 12, 'font-family': 'Times New Roman'
},
'.uml-class-methods-text': {
'ref': '.uml-class-methods-rect', 'ref-y': 5, 'ref-x': 5,
'fill': 'black', 'font-size': 12, 'font-family': 'Times New Roman'
}
},
name: [],
attributes: [],
methods: []
}, joint.shapes.basic.Generic.prototype.defaults),
initialize: function() {
this.on('change:name change:attributes change:methods', function() {
this.updateRectangles();
this.trigger('uml-update');
}, this);
this.updateRectangles();
joint.shapes.basic.Generic.prototype.initialize.apply(this, arguments);
},
getClassName: function() {
return this.get('name');
},
updateRectangles: function() {
var attrs = this.get('attrs');
var rects = [
{ type: 'name', text: this.getClassName() },
{ type: 'attrs', text: this.get('attributes') },
{ type: 'methods', text: this.get('methods') }
];
var offsetY = 0;
_.each(rects, function(rect) {
var lines = _.isArray(rect.text) ? rect.text : [rect.text];
var rectHeight = lines.length * 20 + 20;
attrs['.uml-class-' + rect.type + '-text'].text = lines.join('\n');
attrs['.uml-class-' + rect.type + '-rect'].height = rectHeight;
attrs['.uml-class-' + rect.type + '-rect'].transform = 'translate(0,' + offsetY + ')';
offsetY += rectHeight;
});
}
});
joint.shapes.uml.ClassView = joint.dia.ElementView.extend({
initialize: function() {
joint.dia.ElementView.prototype.initialize.apply(this, arguments);
this.listenTo(this.model, 'uml-update', function() {
this.update();
this.resize();
});
}
});
joint.shapes.uml.Abstract = joint.shapes.uml.Class.extend({
defaults: joint.util.deepSupplement({
type: 'uml.Abstract',
attrs: {
'.uml-class-name-rect': { fill : '#e74c3c' },
'.uml-class-attrs-rect': { fill : '#c0392b' },
'.uml-class-methods-rect': { fill : '#c0392b' }
}
}, joint.shapes.uml.Class.prototype.defaults),
getClassName: function() {
return ['<>', this.get('name')];
}
});
joint.shapes.uml.AbstractView = joint.shapes.uml.ClassView;
joint.shapes.uml.Interface = joint.shapes.uml.Class.extend({
defaults: joint.util.deepSupplement({
type: 'uml.Interface',
attrs: {
'.uml-class-name-rect': { fill : '#f1c40f' },
'.uml-class-attrs-rect': { fill : '#f39c12' },
'.uml-class-methods-rect': { fill : '#f39c12' }
}
}, joint.shapes.uml.Class.prototype.defaults),
getClassName: function() {
return ['<>', this.get('name')];
}
});
joint.shapes.uml.InterfaceView = joint.shapes.uml.ClassView;
joint.shapes.uml.Generalization = joint.dia.Link.extend({
defaults: {
type: 'uml.Generalization',
attrs: { '.marker-target': { d: 'M 20 0 L 0 10 L 20 20 z', fill: 'white' }}
}
});
joint.shapes.uml.Implementation = joint.dia.Link.extend({
defaults: {
type: 'uml.Implementation',
attrs: {
'.marker-target': { d: 'M 20 0 L 0 10 L 20 20 z', fill: 'white' },
'.connection': { 'stroke-dasharray': '3,3' }
}
}
});
joint.shapes.uml.Aggregation = joint.dia.Link.extend({
defaults: {
type: 'uml.Aggregation',
attrs: { '.marker-target': { d: 'M 40 10 L 20 20 L 0 10 L 20 0 z', fill: 'white' }}
}
});
joint.shapes.uml.Composition = joint.dia.Link.extend({
defaults: {
type: 'uml.Composition',
attrs: { '.marker-target': { d: 'M 40 10 L 20 20 L 0 10 L 20 0 z', fill: 'black' }}
}
});
joint.shapes.uml.Association = joint.dia.Link.extend({
defaults: { type: 'uml.Association' }
});
// Statechart
joint.shapes.uml.State = joint.shapes.basic.Generic.extend({
markup: [
'',
'',
'',
'',
'',
'',
'',
''
].join(''),
defaults: joint.util.deepSupplement({
type: 'uml.State',
attrs: {
'.uml-state-body': {
'width': 200, 'height': 200, 'rx': 10, 'ry': 10,
'fill': '#ecf0f1', 'stroke': '#bdc3c7', 'stroke-width': 3
},
'.uml-state-separator': {
'stroke': '#bdc3c7', 'stroke-width': 2
},
'.uml-state-name': {
'ref': '.uml-state-body', 'ref-x': .5, 'ref-y': 5, 'text-anchor': 'middle',
'fill': '#000000', 'font-family': 'Courier New', 'font-size': 14
},
'.uml-state-events': {
'ref': '.uml-state-separator', 'ref-x': 5, 'ref-y': 5,
'fill': '#000000', 'font-family': 'Courier New', 'font-size': 14
}
},
name: 'State',
events: []
}, joint.shapes.basic.Generic.prototype.defaults),
initialize: function() {
this.on({
'change:name': this.updateName,
'change:events': this.updateEvents,
'change:size': this.updatePath
}, this);
this.updateName();
this.updateEvents();
this.updatePath();
joint.shapes.basic.Generic.prototype.initialize.apply(this, arguments);
},
updateName: function() {
this.attr('.uml-state-name/text', this.get('name'));
},
updateEvents: function() {
this.attr('.uml-state-events/text', this.get('events').join('\n'));
},
updatePath: function() {
var d = 'M 0 20 L ' + this.get('size').width + ' 20';
// We are using `silent: true` here because updatePath() is meant to be called
// on resize and there's no need to to update the element twice (`change:size`
// triggers also an update).
this.attr('.uml-state-separator/d', d, { silent: true });
}
});
joint.shapes.uml.StartState = joint.shapes.basic.Circle.extend({
defaults: joint.util.deepSupplement({
type: 'uml.StartState',
attrs: { circle: { 'fill': '#34495e', 'stroke': '#2c3e50', 'stroke-width': 2, 'rx': 1 }}
}, joint.shapes.basic.Circle.prototype.defaults)
});
joint.shapes.uml.EndState = joint.shapes.basic.Generic.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'uml.EndState',
size: { width: 20, height: 20 },
attrs: {
'circle.outer': {
transform: 'translate(10, 10)',
r: 10,
fill: '#ffffff',
stroke: '#2c3e50'
},
'circle.inner': {
transform: 'translate(10, 10)',
r: 6,
fill: '#34495e'
}
}
}, joint.shapes.basic.Generic.prototype.defaults)
});
joint.shapes.uml.Transition = joint.dia.Link.extend({
defaults: {
type: 'uml.Transition',
attrs: {
'.marker-target': { d: 'M 10 0 L 0 5 L 10 10 z', fill: '#34495e', stroke: '#2c3e50' },
'.connection': { stroke: '#2c3e50' }
}
}
});
// JointJS library.
// (c) 2011-2013 client IO
joint.shapes.logic = {};
joint.shapes.logic.Gate = joint.shapes.basic.Generic.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Gate',
size: { width: 80, height: 40 },
attrs: {
'.': { magnet: false },
'.body': { width: 100, height: 50 },
circle: { r: 7, stroke: 'black', fill: 'transparent', 'stroke-width': 2 }
}
}, joint.shapes.basic.Generic.prototype.defaults),
operation: function() { return true; }
});
joint.shapes.logic.IO = joint.shapes.logic.Gate.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'logic.IO',
size: { width: 60, height: 30 },
attrs: {
'.body': { fill: 'white', stroke: 'black', 'stroke-width': 2 },
'.wire': { ref: '.body', 'ref-y': .5, stroke: 'black' },
text: {
fill: 'black',
ref: '.body', 'ref-x': .5, 'ref-y': .5, 'y-alignment': 'middle',
'text-anchor': 'middle',
'font-weight': 'bold',
'font-variant': 'small-caps',
'text-transform': 'capitalize',
'font-size': '14px'
}
}
}, joint.shapes.logic.Gate.prototype.defaults)
});
joint.shapes.logic.Input = joint.shapes.logic.IO.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Input',
attrs: {
'.wire': { 'ref-dx': 0, d: 'M 0 0 L 23 0' },
circle: { ref: '.body', 'ref-dx': 30, 'ref-y': 0.5, magnet: true, 'class': 'output', port: 'out' },
text: { text: 'input' }
}
}, joint.shapes.logic.IO.prototype.defaults)
});
joint.shapes.logic.Output = joint.shapes.logic.IO.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Output',
attrs: {
'.wire': { 'ref-x': 0, d: 'M 0 0 L -23 0' },
circle: { ref: '.body', 'ref-x': -30, 'ref-y': 0.5, magnet: 'passive', 'class': 'input', port: 'in' },
text: { text: 'output' }
}
}, joint.shapes.logic.IO.prototype.defaults)
});
joint.shapes.logic.Gate11 = joint.shapes.logic.Gate.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'logic.Gate11',
attrs: {
'.input': { ref: '.body', 'ref-x': -2, 'ref-y': 0.5, magnet: 'passive', port: 'in' },
'.output': { ref: '.body', 'ref-dx': 2, 'ref-y': 0.5, magnet: true, port: 'out' }
}
}, joint.shapes.logic.Gate.prototype.defaults)
});
joint.shapes.logic.Gate21 = joint.shapes.logic.Gate.extend({
markup: '',
defaults: joint.util.deepSupplement({
type: 'logic.Gate21',
attrs: {
'.input1': { ref: '.body', 'ref-x': -2, 'ref-y': 0.3, magnet: 'passive', port: 'in1' },
'.input2': { ref: '.body', 'ref-x': -2, 'ref-y': 0.7, magnet: 'passive', port: 'in2' },
'.output': { ref: '.body', 'ref-dx': 2, 'ref-y': 0.5, magnet: true, port: 'out' }
}
}, joint.shapes.logic.Gate.prototype.defaults)
});
joint.shapes.logic.Repeater = joint.shapes.logic.Gate11.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Repeater',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9Ik5PVCBBTlNJLnN2ZyIKICAgaW5rc2NhcGU6b3V0cHV0X2V4dGVuc2lvbj0ib3JnLmlua3NjYXBlLm91dHB1dC5zdmcuaW5rc2NhcGUiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0Ij4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAxNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSI1MCA6IDE1IDogMSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIyNSA6IDEwIDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI3MTQiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMC41IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEgOiAwLjUgOiAxIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjAuNSA6IDAuMzMzMzMzMzMgOiAxIgogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgwNiIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgxOSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIzNzIuMDQ3MjQgOiAzNTAuNzg3MzkgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNzQ0LjA5NDQ4IDogNTI2LjE4MTA5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MjYuMTgxMDkgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjc3NyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSI3NSA6IDQwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjE1MCA6IDYwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA2MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUzMjc1IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjUwIDogMzMuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEwMCA6IDUwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmU1NTMzIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjMyIDogMjEuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjY0IDogMzIgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDMyIDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI1NTciCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMjUgOiAxNi42NjY2NjcgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNTAgOiAyNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMjUgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICA8L2RlZnM+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJiYXNlIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxLjAiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnpvb209IjgiCiAgICAgaW5rc2NhcGU6Y3g9Ijg0LjY4NTM1MiIKICAgICBpbmtzY2FwZTpjeT0iMTUuMjg4NjI4IgogICAgIGlua3NjYXBlOmRvY3VtZW50LXVuaXRzPSJweCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJsYXllcjEiCiAgICAgc2hvd2dyaWQ9InRydWUiCiAgICAgaW5rc2NhcGU6Z3JpZC1iYm94PSJ0cnVlIgogICAgIGlua3NjYXBlOmdyaWQtcG9pbnRzPSJ0cnVlIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwMDAwIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTM5OSIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI4NzQiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjMzIgogICAgIGlua3NjYXBlOndpbmRvdy15PSIwIgogICAgIGlua3NjYXBlOnNuYXAtYmJveD0idHJ1ZSI+CiAgICA8aW5rc2NhcGU6Z3JpZAogICAgICAgaWQ9IkdyaWRGcm9tUHJlMDQ2U2V0dGluZ3MiCiAgICAgICB0eXBlPSJ4eWdyaWQiCiAgICAgICBvcmlnaW54PSIwcHgiCiAgICAgICBvcmlnaW55PSIwcHgiCiAgICAgICBzcGFjaW5neD0iMXB4IgogICAgICAgc3BhY2luZ3k9IjFweCIKICAgICAgIGNvbG9yPSIjMDAwMGZmIgogICAgICAgZW1wY29sb3I9IiMwMDAwZmYiCiAgICAgICBvcGFjaXR5PSIwLjIiCiAgICAgICBlbXBvcGFjaXR5PSIwLjQiCiAgICAgICBlbXBzcGFjaW5nPSI1IgogICAgICAgdmlzaWJsZT0idHJ1ZSIKICAgICAgIGVuYWJsZWQ9InRydWUiIC8+CiAgPC9zb2RpcG9kaTpuYW1lZHZpZXc+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhNyI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGcKICAgICBpbmtzY2FwZTpsYWJlbD0iTGF5ZXIgMSIKICAgICBpbmtzY2FwZTpncm91cG1vZGU9ImxheWVyIgogICAgIGlkPSJsYXllcjEiPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjEuOTk5OTk5ODg7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gNzIuMTU2OTEsMjUgTCA5NSwyNSIKICAgICAgIGlkPSJwYXRoMzA1OSIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2MiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MjtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSAyOS4wNDM0NzgsMjUgTCA1LjA0MzQ3ODEsMjUiCiAgICAgICBpZD0icGF0aDMwNjEiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWpvaW46bWl0ZXI7bWFya2VyOm5vbmU7c3Ryb2tlLW9wYWNpdHk6MTt2aXNpYmlsaXR5OnZpc2libGU7ZGlzcGxheTppbmxpbmU7b3ZlcmZsb3c6dmlzaWJsZTtlbmFibGUtYmFja2dyb3VuZDphY2N1bXVsYXRlIgogICAgICAgZD0iTSAyOC45Njg3NSwyLjU5Mzc1IEwgMjguOTY4NzUsNSBMIDI4Ljk2ODc1LDQ1IEwgMjguOTY4NzUsNDcuNDA2MjUgTCAzMS4xMjUsNDYuMzQzNzUgTCA3Mi4xNTYyNSwyNi4zNDM3NSBMIDcyLjE1NjI1LDIzLjY1NjI1IEwgMzEuMTI1LDMuNjU2MjUgTCAyOC45Njg3NSwyLjU5Mzc1IHogTSAzMS45Njg3NSw3LjQwNjI1IEwgNjguMDkzNzUsMjUgTCAzMS45Njg3NSw0Mi41OTM3NSBMIDMxLjk2ODc1LDcuNDA2MjUgeiIKICAgICAgIGlkPSJwYXRoMjYzOCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NjY2NjY2NjY2NjYyIgLz4KICA8L2c+Cjwvc3ZnPgo=' }}
}, joint.shapes.logic.Gate11.prototype.defaults),
operation: function(input) {
return input;
}
});
joint.shapes.logic.Not = joint.shapes.logic.Gate11.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Not',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9Ik5PVCBBTlNJLnN2ZyIKICAgaW5rc2NhcGU6b3V0cHV0X2V4dGVuc2lvbj0ib3JnLmlua3NjYXBlLm91dHB1dC5zdmcuaW5rc2NhcGUiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0Ij4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAxNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSI1MCA6IDE1IDogMSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIyNSA6IDEwIDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI3MTQiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMC41IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEgOiAwLjUgOiAxIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjAuNSA6IDAuMzMzMzMzMzMgOiAxIgogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgwNiIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgxOSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIzNzIuMDQ3MjQgOiAzNTAuNzg3MzkgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNzQ0LjA5NDQ4IDogNTI2LjE4MTA5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MjYuMTgxMDkgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjc3NyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSI3NSA6IDQwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjE1MCA6IDYwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA2MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUzMjc1IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjUwIDogMzMuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEwMCA6IDUwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmU1NTMzIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjMyIDogMjEuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjY0IDogMzIgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDMyIDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI1NTciCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMjUgOiAxNi42NjY2NjcgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNTAgOiAyNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMjUgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICA8L2RlZnM+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJiYXNlIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxLjAiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnpvb209IjgiCiAgICAgaW5rc2NhcGU6Y3g9Ijg0LjY4NTM1MiIKICAgICBpbmtzY2FwZTpjeT0iMTUuMjg4NjI4IgogICAgIGlua3NjYXBlOmRvY3VtZW50LXVuaXRzPSJweCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJsYXllcjEiCiAgICAgc2hvd2dyaWQ9InRydWUiCiAgICAgaW5rc2NhcGU6Z3JpZC1iYm94PSJ0cnVlIgogICAgIGlua3NjYXBlOmdyaWQtcG9pbnRzPSJ0cnVlIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwMDAwIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTM5OSIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI4NzQiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjMzIgogICAgIGlua3NjYXBlOndpbmRvdy15PSIwIgogICAgIGlua3NjYXBlOnNuYXAtYmJveD0idHJ1ZSI+CiAgICA8aW5rc2NhcGU6Z3JpZAogICAgICAgaWQ9IkdyaWRGcm9tUHJlMDQ2U2V0dGluZ3MiCiAgICAgICB0eXBlPSJ4eWdyaWQiCiAgICAgICBvcmlnaW54PSIwcHgiCiAgICAgICBvcmlnaW55PSIwcHgiCiAgICAgICBzcGFjaW5neD0iMXB4IgogICAgICAgc3BhY2luZ3k9IjFweCIKICAgICAgIGNvbG9yPSIjMDAwMGZmIgogICAgICAgZW1wY29sb3I9IiMwMDAwZmYiCiAgICAgICBvcGFjaXR5PSIwLjIiCiAgICAgICBlbXBvcGFjaXR5PSIwLjQiCiAgICAgICBlbXBzcGFjaW5nPSI1IgogICAgICAgdmlzaWJsZT0idHJ1ZSIKICAgICAgIGVuYWJsZWQ9InRydWUiIC8+CiAgPC9zb2RpcG9kaTpuYW1lZHZpZXc+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhNyI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGcKICAgICBpbmtzY2FwZTpsYWJlbD0iTGF5ZXIgMSIKICAgICBpbmtzY2FwZTpncm91cG1vZGU9ImxheWVyIgogICAgIGlkPSJsYXllcjEiPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjEuOTk5OTk5ODg7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gNzkuMTU2OTEsMjUgTCA5NSwyNSIKICAgICAgIGlkPSJwYXRoMzA1OSIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2MiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MjtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSAyOS4wNDM0NzgsMjUgTCA1LjA0MzQ3ODEsMjUiCiAgICAgICBpZD0icGF0aDMwNjEiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWpvaW46bWl0ZXI7bWFya2VyOm5vbmU7c3Ryb2tlLW9wYWNpdHk6MTt2aXNpYmlsaXR5OnZpc2libGU7ZGlzcGxheTppbmxpbmU7b3ZlcmZsb3c6dmlzaWJsZTtlbmFibGUtYmFja2dyb3VuZDphY2N1bXVsYXRlIgogICAgICAgZD0iTSAyOC45Njg3NSwyLjU5Mzc1IEwgMjguOTY4NzUsNSBMIDI4Ljk2ODc1LDQ1IEwgMjguOTY4NzUsNDcuNDA2MjUgTCAzMS4xMjUsNDYuMzQzNzUgTCA3Mi4xNTYyNSwyNi4zNDM3NSBMIDcyLjE1NjI1LDIzLjY1NjI1IEwgMzEuMTI1LDMuNjU2MjUgTCAyOC45Njg3NSwyLjU5Mzc1IHogTSAzMS45Njg3NSw3LjQwNjI1IEwgNjguMDkzNzUsMjUgTCAzMS45Njg3NSw0Mi41OTM3NSBMIDMxLjk2ODc1LDcuNDA2MjUgeiIKICAgICAgIGlkPSJwYXRoMjYzOCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NjY2NjY2NjY2NjYyIgLz4KICAgIDxwYXRoCiAgICAgICBzb2RpcG9kaTp0eXBlPSJhcmMiCiAgICAgICBzdHlsZT0iZmlsbDpub25lO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDozO3N0cm9rZS1saW5lam9pbjptaXRlcjttYXJrZXI6bm9uZTtzdHJva2Utb3BhY2l0eToxO3Zpc2liaWxpdHk6dmlzaWJsZTtkaXNwbGF5OmlubGluZTtvdmVyZmxvdzp2aXNpYmxlO2VuYWJsZS1iYWNrZ3JvdW5kOmFjY3VtdWxhdGUiCiAgICAgICBpZD0icGF0aDI2NzEiCiAgICAgICBzb2RpcG9kaTpjeD0iNzYiCiAgICAgICBzb2RpcG9kaTpjeT0iMjUiCiAgICAgICBzb2RpcG9kaTpyeD0iNCIKICAgICAgIHNvZGlwb2RpOnJ5PSI0IgogICAgICAgZD0iTSA4MCwyNSBBIDQsNCAwIDEgMSA3MiwyNSBBIDQsNCAwIDEgMSA4MCwyNSB6IgogICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTEsMCkiIC8+CiAgPC9nPgo8L3N2Zz4K' }}
}, joint.shapes.logic.Gate11.prototype.defaults),
operation: function(input) {
return !input;
}
});
joint.shapes.logic.Or = joint.shapes.logic.Gate21.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Or',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9Ik9SIEFOU0kuc3ZnIgogICBpbmtzY2FwZTpvdXRwdXRfZXh0ZW5zaW9uPSJvcmcuaW5rc2NhcGUub3V0cHV0LnN2Zy5pbmtzY2FwZSI+CiAgPGRlZnMKICAgICBpZD0iZGVmczQiPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDE1IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9IjUwIDogMTUgOiAxIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjI1IDogMTAgOiAxIgogICAgICAgaWQ9InBlcnNwZWN0aXZlMjcxNCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAwLjUgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfej0iMSA6IDAuNSA6IDEiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMC41IDogMC4zMzMzMzMzMyA6IDEiCiAgICAgICBpZD0icGVyc3BlY3RpdmUyODA2IiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUyODE5IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjM3Mi4wNDcyNCA6IDM1MC43ODczOSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSI3NDQuMDk0NDggOiA1MjYuMTgxMDkgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDUyNi4xODEwOSA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUyNzc3IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49Ijc1IDogNDAgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iMTUwIDogNjAgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDYwIDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTMyNzUiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iNTAgOiAzMy4zMzMzMzMgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iMTAwIDogNTAgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDUwIDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTU1MzMiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMzIgOiAyMS4zMzMzMzMgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNjQgOiAzMiA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMzIgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjU1NyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIyNSA6IDE2LjY2NjY2NyA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSI1MCA6IDI1IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAyNSA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogIDwvZGVmcz4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaWQ9ImJhc2UiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IgogICAgIGJvcmRlcm9wYWNpdHk9IjEuMCIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6em9vbT0iNCIKICAgICBpbmtzY2FwZTpjeD0iMTEzLjAwMDM5IgogICAgIGlua3NjYXBlOmN5PSIxMi44OTM3MzEiCiAgICAgaW5rc2NhcGU6ZG9jdW1lbnQtdW5pdHM9InB4IgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9ImcyNTYwIgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTpncmlkLWJib3g9InRydWUiCiAgICAgaW5rc2NhcGU6Z3JpZC1wb2ludHM9InRydWUiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAwMDAiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxMzk5IgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9Ijg3NCIKICAgICBpbmtzY2FwZTp3aW5kb3cteD0iMzciCiAgICAgaW5rc2NhcGU6d2luZG93LXk9Ii00IgogICAgIGlua3NjYXBlOnNuYXAtYmJveD0idHJ1ZSI+CiAgICA8aW5rc2NhcGU6Z3JpZAogICAgICAgaWQ9IkdyaWRGcm9tUHJlMDQ2U2V0dGluZ3MiCiAgICAgICB0eXBlPSJ4eWdyaWQiCiAgICAgICBvcmlnaW54PSIwcHgiCiAgICAgICBvcmlnaW55PSIwcHgiCiAgICAgICBzcGFjaW5neD0iMXB4IgogICAgICAgc3BhY2luZ3k9IjFweCIKICAgICAgIGNvbG9yPSIjMDAwMGZmIgogICAgICAgZW1wY29sb3I9IiMwMDAwZmYiCiAgICAgICBvcGFjaXR5PSIwLjIiCiAgICAgICBlbXBvcGFjaXR5PSIwLjQiCiAgICAgICBlbXBzcGFjaW5nPSI1IgogICAgICAgdmlzaWJsZT0idHJ1ZSIKICAgICAgIGVuYWJsZWQ9InRydWUiIC8+CiAgPC9zb2RpcG9kaTpuYW1lZHZpZXc+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhNyI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGcKICAgICBpbmtzY2FwZTpsYWJlbD0iTGF5ZXIgMSIKICAgICBpbmtzY2FwZTpncm91cG1vZGU9ImxheWVyIgogICAgIGlkPSJsYXllcjEiPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Im0gNzAsMjUgYyAyMCwwIDI1LDAgMjUsMCIKICAgICAgIGlkPSJwYXRoMzA1OSIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2MiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MjtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSAzMSwxNSA1LDE1IgogICAgICAgaWQ9InBhdGgzMDYxIiAvPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjEuOTk5OTk5ODg7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gMzIsMzUgNSwzNSIKICAgICAgIGlkPSJwYXRoMzk0NCIgLz4KICAgIDxnCiAgICAgICBpZD0iZzI1NjAiCiAgICAgICBpbmtzY2FwZTpsYWJlbD0iTGF5ZXIgMSIKICAgICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2LjUsLTM5LjUpIj4KICAgICAgPHBhdGgKICAgICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6ZXZlbm9kZDtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgICBkPSJNIC0yLjQwNjI1LDQ0LjUgTCAtMC40MDYyNSw0Ni45Mzc1IEMgLTAuNDA2MjUsNDYuOTM3NSA1LjI1LDUzLjkzNzU0OSA1LjI1LDY0LjUgQyA1LjI1LDc1LjA2MjQ1MSAtMC40MDYyNSw4Mi4wNjI1IC0wLjQwNjI1LDgyLjA2MjUgTCAtMi40MDYyNSw4NC41IEwgMC43NSw4NC41IEwgMTQuNzUsODQuNSBDIDE3LjE1ODA3Niw4NC41MDAwMDEgMjIuNDM5Njk5LDg0LjUyNDUxNCAyOC4zNzUsODIuMDkzNzUgQyAzNC4zMTAzMDEsNzkuNjYyOTg2IDQwLjkxMTUzNiw3NC43NTA0ODQgNDYuMDYyNSw2NS4yMTg3NSBMIDQ0Ljc1LDY0LjUgTCA0Ni4wNjI1LDYzLjc4MTI1IEMgMzUuNzU5Mzg3LDQ0LjcxNTU5IDE5LjUwNjU3NCw0NC41IDE0Ljc1LDQ0LjUgTCAwLjc1LDQ0LjUgTCAtMi40MDYyNSw0NC41IHogTSAzLjQ2ODc1LDQ3LjUgTCAxNC43NSw0Ny41IEMgMTkuNDM0MTczLDQ3LjUgMzMuMDM2ODUsNDcuMzY5NzkzIDQyLjcxODc1LDY0LjUgQyAzNy45NTE5NjQsNzIuOTI5MDc1IDMyLjE5NzQ2OSw3Ny4xODM5MSAyNyw3OS4zMTI1IEMgMjEuNjM5MzM5LDgxLjUwNzkyNCAxNy4xNTgwNzUsODEuNTAwMDAxIDE0Ljc1LDgxLjUgTCAzLjUsODEuNSBDIDUuMzczNTg4NCw3OC4zOTE1NjYgOC4yNSw3Mi40NTA2NSA4LjI1LDY0LjUgQyA4LjI1LDU2LjUyNjY0NiA1LjM0MTQ2ODYsNTAuNTk5ODE1IDMuNDY4NzUsNDcuNSB6IgogICAgICAgICBpZD0icGF0aDQ5NzMiCiAgICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NzY2NjY3NjY2NjY2NjY2NzY2NzYyIgLz4KICAgIDwvZz4KICA8L2c+Cjwvc3ZnPgo=' }}
}, joint.shapes.logic.Gate21.prototype.defaults),
operation: function(input1, input2) {
return input1 || input2;
}
});
joint.shapes.logic.And = joint.shapes.logic.Gate21.extend({
defaults: joint.util.deepSupplement({
type: 'logic.And',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9IkFORCBBTlNJLnN2ZyIKICAgaW5rc2NhcGU6b3V0cHV0X2V4dGVuc2lvbj0ib3JnLmlua3NjYXBlLm91dHB1dC5zdmcuaW5rc2NhcGUiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0Ij4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAxNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSI1MCA6IDE1IDogMSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIyNSA6IDEwIDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI3MTQiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMC41IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEgOiAwLjUgOiAxIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjAuNSA6IDAuMzMzMzMzMzMgOiAxIgogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgwNiIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgxOSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIzNzIuMDQ3MjQgOiAzNTAuNzg3MzkgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNzQ0LjA5NDQ4IDogNTI2LjE4MTA5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MjYuMTgxMDkgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjc3NyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSI3NSA6IDQwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjE1MCA6IDYwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA2MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUzMjc1IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjUwIDogMzMuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEwMCA6IDUwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmU1NTMzIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjMyIDogMjEuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjY0IDogMzIgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDMyIDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgPC9kZWZzPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0iYmFzZSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMS4wIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp6b29tPSI4IgogICAgIGlua3NjYXBlOmN4PSI1Ni42OTgzNDgiCiAgICAgaW5rc2NhcGU6Y3k9IjI1LjMyNjg5OSIKICAgICBpbmtzY2FwZTpkb2N1bWVudC11bml0cz0icHgiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ibGF5ZXIxIgogICAgIHNob3dncmlkPSJ0cnVlIgogICAgIGlua3NjYXBlOmdyaWQtYmJveD0idHJ1ZSIKICAgICBpbmtzY2FwZTpncmlkLXBvaW50cz0idHJ1ZSIKICAgICBncmlkdG9sZXJhbmNlPSIxMDAwMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjEzOTkiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iODc0IgogICAgIGlua3NjYXBlOndpbmRvdy14PSIzMyIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMCIKICAgICBpbmtzY2FwZTpzbmFwLWJib3g9InRydWUiPgogICAgPGlua3NjYXBlOmdyaWQKICAgICAgIGlkPSJHcmlkRnJvbVByZTA0NlNldHRpbmdzIgogICAgICAgdHlwZT0ieHlncmlkIgogICAgICAgb3JpZ2lueD0iMHB4IgogICAgICAgb3JpZ2lueT0iMHB4IgogICAgICAgc3BhY2luZ3g9IjFweCIKICAgICAgIHNwYWNpbmd5PSIxcHgiCiAgICAgICBjb2xvcj0iIzAwMDBmZiIKICAgICAgIGVtcGNvbG9yPSIjMDAwMGZmIgogICAgICAgb3BhY2l0eT0iMC4yIgogICAgICAgZW1wb3BhY2l0eT0iMC40IgogICAgICAgZW1wc3BhY2luZz0iNSIKICAgICAgIHZpc2libGU9InRydWUiCiAgICAgICBlbmFibGVkPSJ0cnVlIiAvPgogIDwvc29kaXBvZGk6bmFtZWR2aWV3PgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTciPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0ibGF5ZXIxIj4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJtIDcwLDI1IGMgMjAsMCAyNSwwIDI1LDAiCiAgICAgICBpZD0icGF0aDMwNTkiCiAgICAgICBzb2RpcG9kaTpub2RldHlwZXM9ImNjIiAvPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gMzEsMTUgNSwxNSIKICAgICAgIGlkPSJwYXRoMzA2MSIgLz4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoxLjk5OTk5OTg4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJNIDMyLDM1IDUsMzUiCiAgICAgICBpZD0icGF0aDM5NDQiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZvbnQtc2l6ZTptZWRpdW07Zm9udC1zdHlsZTpub3JtYWw7Zm9udC12YXJpYW50Om5vcm1hbDtmb250LXdlaWdodDpub3JtYWw7Zm9udC1zdHJldGNoOm5vcm1hbDt0ZXh0LWluZGVudDowO3RleHQtYWxpZ246c3RhcnQ7dGV4dC1kZWNvcmF0aW9uOm5vbmU7bGluZS1oZWlnaHQ6bm9ybWFsO2xldHRlci1zcGFjaW5nOm5vcm1hbDt3b3JkLXNwYWNpbmc6bm9ybWFsO3RleHQtdHJhbnNmb3JtOm5vbmU7ZGlyZWN0aW9uOmx0cjtibG9jay1wcm9ncmVzc2lvbjp0Yjt3cml0aW5nLW1vZGU6bHItdGI7dGV4dC1hbmNob3I6c3RhcnQ7ZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lO3N0cm9rZS13aWR0aDozO21hcmtlcjpub25lO3Zpc2liaWxpdHk6dmlzaWJsZTtkaXNwbGF5OmlubGluZTtvdmVyZmxvdzp2aXNpYmxlO2VuYWJsZS1iYWNrZ3JvdW5kOmFjY3VtdWxhdGU7Zm9udC1mYW1pbHk6Qml0c3RyZWFtIFZlcmEgU2FuczstaW5rc2NhcGUtZm9udC1zcGVjaWZpY2F0aW9uOkJpdHN0cmVhbSBWZXJhIFNhbnMiCiAgICAgICBkPSJNIDMwLDUgTCAzMCw2LjQyODU3MTQgTCAzMCw0My41NzE0MjkgTCAzMCw0NSBMIDMxLjQyODU3MSw0NSBMIDUwLjQ3NjE5LDQ1IEMgNjEuNzQ0MDk4LDQ1IDcwLjQ3NjE5LDM1Ljk5OTk1NSA3MC40NzYxOSwyNSBDIDcwLjQ3NjE5LDE0LjAwMDA0NSA2MS43NDQwOTksNS4wMDAwMDAyIDUwLjQ3NjE5LDUgQyA1MC40NzYxOSw1IDUwLjQ3NjE5LDUgMzEuNDI4NTcxLDUgTCAzMCw1IHogTSAzMi44NTcxNDMsNy44NTcxNDI5IEMgNDAuODM0MjY0LDcuODU3MTQyOSA0NS45MTgzNjgsNy44NTcxNDI5IDQ4LjA5NTIzOCw3Ljg1NzE0MjkgQyA0OS4yODU3MTQsNy44NTcxNDI5IDQ5Ljg4MDk1Miw3Ljg1NzE0MjkgNTAuMTc4NTcxLDcuODU3MTQyOSBDIDUwLjMyNzM4MSw3Ljg1NzE0MjkgNTAuNDA5MjI3LDcuODU3MTQyOSA1MC40NDY0MjksNy44NTcxNDI5IEMgNTAuNDY1MDI5LDcuODU3MTQyOSA1MC40NzE1NDMsNy44NTcxNDI5IDUwLjQ3NjE5LDcuODU3MTQyOSBDIDYwLjIzNjg1Myw3Ljg1NzE0MyA2Ny4xNDI4NTcsMTUuNDk3MDk4IDY3LjE0Mjg1NywyNSBDIDY3LjE0Mjg1NywzNC41MDI5MDIgNTkuNzYwNjYyLDQyLjE0Mjg1NyA1MCw0Mi4xNDI4NTcgTCAzMi44NTcxNDMsNDIuMTQyODU3IEwgMzIuODU3MTQzLDcuODU3MTQyOSB6IgogICAgICAgaWQ9InBhdGgyODg0IgogICAgICAgc29kaXBvZGk6bm9kZXR5cGVzPSJjY2NjY2NzY2NjY3Nzc3NzY2NjIiAvPgogIDwvZz4KPC9zdmc+Cg==' }}
}, joint.shapes.logic.Gate21.prototype.defaults),
operation: function(input1, input2) {
return input1 && input2;
}
});
joint.shapes.logic.Nor = joint.shapes.logic.Gate21.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Nor',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9Ik5PUiBBTlNJLnN2ZyIKICAgaW5rc2NhcGU6b3V0cHV0X2V4dGVuc2lvbj0ib3JnLmlua3NjYXBlLm91dHB1dC5zdmcuaW5rc2NhcGUiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0Ij4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAxNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSI1MCA6IDE1IDogMSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIyNSA6IDEwIDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI3MTQiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMC41IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEgOiAwLjUgOiAxIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjAuNSA6IDAuMzMzMzMzMzMgOiAxIgogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgwNiIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgxOSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIzNzIuMDQ3MjQgOiAzNTAuNzg3MzkgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNzQ0LjA5NDQ4IDogNTI2LjE4MTA5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MjYuMTgxMDkgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjc3NyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSI3NSA6IDQwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjE1MCA6IDYwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA2MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUzMjc1IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjUwIDogMzMuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEwMCA6IDUwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmU1NTMzIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjMyIDogMjEuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjY0IDogMzIgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDMyIDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI1NTciCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMjUgOiAxNi42NjY2NjcgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNTAgOiAyNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMjUgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICA8L2RlZnM+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJiYXNlIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxLjAiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnpvb209IjEiCiAgICAgaW5rc2NhcGU6Y3g9Ijc4LjY3NzY0NCIKICAgICBpbmtzY2FwZTpjeT0iMjIuMTAyMzQ0IgogICAgIGlua3NjYXBlOmRvY3VtZW50LXVuaXRzPSJweCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJsYXllcjEiCiAgICAgc2hvd2dyaWQ9InRydWUiCiAgICAgaW5rc2NhcGU6Z3JpZC1iYm94PSJ0cnVlIgogICAgIGlua3NjYXBlOmdyaWQtcG9pbnRzPSJ0cnVlIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwMDAwIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTM5OSIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI4NzQiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjM3IgogICAgIGlua3NjYXBlOndpbmRvdy15PSItNCIKICAgICBpbmtzY2FwZTpzbmFwLWJib3g9InRydWUiPgogICAgPGlua3NjYXBlOmdyaWQKICAgICAgIGlkPSJHcmlkRnJvbVByZTA0NlNldHRpbmdzIgogICAgICAgdHlwZT0ieHlncmlkIgogICAgICAgb3JpZ2lueD0iMHB4IgogICAgICAgb3JpZ2lueT0iMHB4IgogICAgICAgc3BhY2luZ3g9IjFweCIKICAgICAgIHNwYWNpbmd5PSIxcHgiCiAgICAgICBjb2xvcj0iIzAwMDBmZiIKICAgICAgIGVtcGNvbG9yPSIjMDAwMGZmIgogICAgICAgb3BhY2l0eT0iMC4yIgogICAgICAgZW1wb3BhY2l0eT0iMC40IgogICAgICAgZW1wc3BhY2luZz0iNSIKICAgICAgIHZpc2libGU9InRydWUiCiAgICAgICBlbmFibGVkPSJ0cnVlIiAvPgogIDwvc29kaXBvZGk6bmFtZWR2aWV3PgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTciPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0ibGF5ZXIxIj4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJNIDc5LDI1IEMgOTksMjUgOTUsMjUgOTUsMjUiCiAgICAgICBpZD0icGF0aDMwNTkiCiAgICAgICBzb2RpcG9kaTpub2RldHlwZXM9ImNjIiAvPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gMzEsMTUgNSwxNSIKICAgICAgIGlkPSJwYXRoMzA2MSIgLz4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoxLjk5OTk5OTg4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJNIDMyLDM1IDUsMzUiCiAgICAgICBpZD0icGF0aDM5NDQiIC8+CiAgICA8ZwogICAgICAgaWQ9ImcyNTYwIgogICAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNi41LC0zOS41KSI+CiAgICAgIDxwYXRoCiAgICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjM7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgICAgZD0iTSAtMi40MDYyNSw0NC41IEwgLTAuNDA2MjUsNDYuOTM3NSBDIC0wLjQwNjI1LDQ2LjkzNzUgNS4yNSw1My45Mzc1NDkgNS4yNSw2NC41IEMgNS4yNSw3NS4wNjI0NTEgLTAuNDA2MjUsODIuMDYyNSAtMC40MDYyNSw4Mi4wNjI1IEwgLTIuNDA2MjUsODQuNSBMIDAuNzUsODQuNSBMIDE0Ljc1LDg0LjUgQyAxNy4xNTgwNzYsODQuNTAwMDAxIDIyLjQzOTY5OSw4NC41MjQ1MTQgMjguMzc1LDgyLjA5Mzc1IEMgMzQuMzEwMzAxLDc5LjY2Mjk4NiA0MC45MTE1MzYsNzQuNzUwNDg0IDQ2LjA2MjUsNjUuMjE4NzUgTCA0NC43NSw2NC41IEwgNDYuMDYyNSw2My43ODEyNSBDIDM1Ljc1OTM4Nyw0NC43MTU1OSAxOS41MDY1NzQsNDQuNSAxNC43NSw0NC41IEwgMC43NSw0NC41IEwgLTIuNDA2MjUsNDQuNSB6IE0gMy40Njg3NSw0Ny41IEwgMTQuNzUsNDcuNSBDIDE5LjQzNDE3Myw0Ny41IDMzLjAzNjg1LDQ3LjM2OTc5MyA0Mi43MTg3NSw2NC41IEMgMzcuOTUxOTY0LDcyLjkyOTA3NSAzMi4xOTc0NjksNzcuMTgzOTEgMjcsNzkuMzEyNSBDIDIxLjYzOTMzOSw4MS41MDc5MjQgMTcuMTU4MDc1LDgxLjUwMDAwMSAxNC43NSw4MS41IEwgMy41LDgxLjUgQyA1LjM3MzU4ODQsNzguMzkxNTY2IDguMjUsNzIuNDUwNjUgOC4yNSw2NC41IEMgOC4yNSw1Ni41MjY2NDYgNS4zNDE0Njg2LDUwLjU5OTgxNSAzLjQ2ODc1LDQ3LjUgeiIKICAgICAgICAgaWQ9InBhdGg0OTczIgogICAgICAgICBzb2RpcG9kaTpub2RldHlwZXM9ImNjc2NjY2NzY2NjY2NjY2Njc2Njc2MiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIHNvZGlwb2RpOnR5cGU9ImFyYyIKICAgICAgICAgc3R5bGU9ImZpbGw6bm9uZTtmaWxsLW9wYWNpdHk6MTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWpvaW46bWl0ZXI7bWFya2VyOm5vbmU7c3Ryb2tlLW9wYWNpdHk6MTt2aXNpYmlsaXR5OnZpc2libGU7ZGlzcGxheTppbmxpbmU7b3ZlcmZsb3c6dmlzaWJsZTtlbmFibGUtYmFja2dyb3VuZDphY2N1bXVsYXRlIgogICAgICAgICBpZD0icGF0aDI2MDQiCiAgICAgICAgIHNvZGlwb2RpOmN4PSI3NSIKICAgICAgICAgc29kaXBvZGk6Y3k9IjI1IgogICAgICAgICBzb2RpcG9kaTpyeD0iNCIKICAgICAgICAgc29kaXBvZGk6cnk9IjQiCiAgICAgICAgIGQ9Ik0gNzksMjUgQSA0LDQgMCAxIDEgNzEsMjUgQSA0LDQgMCAxIDEgNzksMjUgeiIKICAgICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTI2LjUsMzkuNSkiIC8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K' }}
}, joint.shapes.logic.Gate21.prototype.defaults),
operation: function(input1, input2) {
return !(input1 || input2);
}
});
joint.shapes.logic.Nand = joint.shapes.logic.Gate21.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Nand',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9Ik5BTkQgQU5TSS5zdmciCiAgIGlua3NjYXBlOm91dHB1dF9leHRlbnNpb249Im9yZy5pbmtzY2FwZS5vdXRwdXQuc3ZnLmlua3NjYXBlIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzNCI+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMTUgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfej0iNTAgOiAxNSA6IDEiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMjUgOiAxMCA6IDEiCiAgICAgICBpZD0icGVyc3BlY3RpdmUyNzE0IiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDAuNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSIxIDogMC41IDogMSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIwLjUgOiAwLjMzMzMzMzMzIDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI4MDYiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI4MTkiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMzcyLjA0NzI0IDogMzUwLjc4NzM5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9Ijc0NC4wOTQ0OCA6IDUyNi4xODEwOSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNTI2LjE4MTA5IDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI3NzciCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iNzUgOiA0MCA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSIxNTAgOiA2MCA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNjAgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMzI3NSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSI1MCA6IDMzLjMzMzMzMyA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSIxMDAgOiA1MCA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNTAgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlNTUzMyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIzMiA6IDIxLjMzMzMzMyA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSI2NCA6IDMyIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAzMiA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogIDwvZGVmcz4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgaWQ9ImJhc2UiCiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IgogICAgIGJvcmRlcm9wYWNpdHk9IjEuMCIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6em9vbT0iMTYiCiAgICAgaW5rc2NhcGU6Y3g9Ijc4LjI4MzMwNyIKICAgICBpbmtzY2FwZTpjeT0iMTYuNDQyODQzIgogICAgIGlua3NjYXBlOmRvY3VtZW50LXVuaXRzPSJweCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJsYXllcjEiCiAgICAgc2hvd2dyaWQ9InRydWUiCiAgICAgaW5rc2NhcGU6Z3JpZC1iYm94PSJ0cnVlIgogICAgIGlua3NjYXBlOmdyaWQtcG9pbnRzPSJ0cnVlIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwMDAwIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTM5OSIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI4NzQiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjMzIgogICAgIGlua3NjYXBlOndpbmRvdy15PSIwIgogICAgIGlua3NjYXBlOnNuYXAtYmJveD0idHJ1ZSI+CiAgICA8aW5rc2NhcGU6Z3JpZAogICAgICAgaWQ9IkdyaWRGcm9tUHJlMDQ2U2V0dGluZ3MiCiAgICAgICB0eXBlPSJ4eWdyaWQiCiAgICAgICBvcmlnaW54PSIwcHgiCiAgICAgICBvcmlnaW55PSIwcHgiCiAgICAgICBzcGFjaW5neD0iMXB4IgogICAgICAgc3BhY2luZ3k9IjFweCIKICAgICAgIGNvbG9yPSIjMDAwMGZmIgogICAgICAgZW1wY29sb3I9IiMwMDAwZmYiCiAgICAgICBvcGFjaXR5PSIwLjIiCiAgICAgICBlbXBvcGFjaXR5PSIwLjQiCiAgICAgICBlbXBzcGFjaW5nPSI1IgogICAgICAgdmlzaWJsZT0idHJ1ZSIKICAgICAgIGVuYWJsZWQ9InRydWUiIC8+CiAgPC9zb2RpcG9kaTpuYW1lZHZpZXc+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhNyI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPGcKICAgICBpbmtzY2FwZTpsYWJlbD0iTGF5ZXIgMSIKICAgICBpbmtzY2FwZTpncm91cG1vZGU9ImxheWVyIgogICAgIGlkPSJsYXllcjEiPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gNzksMjUgQyA5MS44LDI1IDk1LDI1IDk1LDI1IgogICAgICAgaWQ9InBhdGgzMDU5IgogICAgICAgc29kaXBvZGk6bm9kZXR5cGVzPSJjYyIgLz4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJNIDMxLDE1IDUsMTUiCiAgICAgICBpZD0icGF0aDMwNjEiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MS45OTk5OTk4ODtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSAzMiwzNSA1LDM1IgogICAgICAgaWQ9InBhdGgzOTQ0IiAvPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmb250LXNpemU6bWVkaXVtO2ZvbnQtc3R5bGU6bm9ybWFsO2ZvbnQtdmFyaWFudDpub3JtYWw7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtc3RyZXRjaDpub3JtYWw7dGV4dC1pbmRlbnQ6MDt0ZXh0LWFsaWduOnN0YXJ0O3RleHQtZGVjb3JhdGlvbjpub25lO2xpbmUtaGVpZ2h0Om5vcm1hbDtsZXR0ZXItc3BhY2luZzpub3JtYWw7d29yZC1zcGFjaW5nOm5vcm1hbDt0ZXh0LXRyYW5zZm9ybTpub25lO2RpcmVjdGlvbjpsdHI7YmxvY2stcHJvZ3Jlc3Npb246dGI7d3JpdGluZy1tb2RlOmxyLXRiO3RleHQtYW5jaG9yOnN0YXJ0O2ZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MzttYXJrZXI6bm9uZTt2aXNpYmlsaXR5OnZpc2libGU7ZGlzcGxheTppbmxpbmU7b3ZlcmZsb3c6dmlzaWJsZTtlbmFibGUtYmFja2dyb3VuZDphY2N1bXVsYXRlO2ZvbnQtZmFtaWx5OkJpdHN0cmVhbSBWZXJhIFNhbnM7LWlua3NjYXBlLWZvbnQtc3BlY2lmaWNhdGlvbjpCaXRzdHJlYW0gVmVyYSBTYW5zIgogICAgICAgZD0iTSAzMCw1IEwgMzAsNi40Mjg1NzE0IEwgMzAsNDMuNTcxNDI5IEwgMzAsNDUgTCAzMS40Mjg1NzEsNDUgTCA1MC40NzYxOSw0NSBDIDYxLjc0NDA5OCw0NSA3MC40NzYxOSwzNS45OTk5NTUgNzAuNDc2MTksMjUgQyA3MC40NzYxOSwxNC4wMDAwNDUgNjEuNzQ0MDk5LDUuMDAwMDAwMiA1MC40NzYxOSw1IEMgNTAuNDc2MTksNSA1MC40NzYxOSw1IDMxLjQyODU3MSw1IEwgMzAsNSB6IE0gMzIuODU3MTQzLDcuODU3MTQyOSBDIDQwLjgzNDI2NCw3Ljg1NzE0MjkgNDUuOTE4MzY4LDcuODU3MTQyOSA0OC4wOTUyMzgsNy44NTcxNDI5IEMgNDkuMjg1NzE0LDcuODU3MTQyOSA0OS44ODA5NTIsNy44NTcxNDI5IDUwLjE3ODU3MSw3Ljg1NzE0MjkgQyA1MC4zMjczODEsNy44NTcxNDI5IDUwLjQwOTIyNyw3Ljg1NzE0MjkgNTAuNDQ2NDI5LDcuODU3MTQyOSBDIDUwLjQ2NTAyOSw3Ljg1NzE0MjkgNTAuNDcxNTQzLDcuODU3MTQyOSA1MC40NzYxOSw3Ljg1NzE0MjkgQyA2MC4yMzY4NTMsNy44NTcxNDMgNjcuMTQyODU3LDE1LjQ5NzA5OCA2Ny4xNDI4NTcsMjUgQyA2Ny4xNDI4NTcsMzQuNTAyOTAyIDU5Ljc2MDY2Miw0Mi4xNDI4NTcgNTAsNDIuMTQyODU3IEwgMzIuODU3MTQzLDQyLjE0Mjg1NyBMIDMyLjg1NzE0Myw3Ljg1NzE0MjkgeiIKICAgICAgIGlkPSJwYXRoMjg4NCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NjY2Njc2NjY2Nzc3Nzc2NjYyIgLz4KICAgIDxwYXRoCiAgICAgICBzb2RpcG9kaTp0eXBlPSJhcmMiCiAgICAgICBzdHlsZT0iZmlsbDpub25lO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDozO3N0cm9rZS1saW5lam9pbjptaXRlcjttYXJrZXI6bm9uZTtzdHJva2Utb3BhY2l0eToxO3Zpc2liaWxpdHk6dmlzaWJsZTtkaXNwbGF5OmlubGluZTtvdmVyZmxvdzp2aXNpYmxlO2VuYWJsZS1iYWNrZ3JvdW5kOmFjY3VtdWxhdGUiCiAgICAgICBpZD0icGF0aDQwMDgiCiAgICAgICBzb2RpcG9kaTpjeD0iNzUiCiAgICAgICBzb2RpcG9kaTpjeT0iMjUiCiAgICAgICBzb2RpcG9kaTpyeD0iNCIKICAgICAgIHNvZGlwb2RpOnJ5PSI0IgogICAgICAgZD0iTSA3OSwyNSBBIDQsNCAwIDEgMSA3MSwyNSBBIDQsNCAwIDEgMSA3OSwyNSB6IiAvPgogIDwvZz4KPC9zdmc+Cg==' }}
}, joint.shapes.logic.Gate21.prototype.defaults),
operation: function(input1, input2) {
return !(input1 && input2);
}
});
joint.shapes.logic.Xor = joint.shapes.logic.Gate21.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Xor',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9IlhPUiBBTlNJLnN2ZyIKICAgaW5rc2NhcGU6b3V0cHV0X2V4dGVuc2lvbj0ib3JnLmlua3NjYXBlLm91dHB1dC5zdmcuaW5rc2NhcGUiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0Ij4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAxNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSI1MCA6IDE1IDogMSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIyNSA6IDEwIDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI3MTQiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMC41IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEgOiAwLjUgOiAxIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjAuNSA6IDAuMzMzMzMzMzMgOiAxIgogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgwNiIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjgxOSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIzNzIuMDQ3MjQgOiAzNTAuNzg3MzkgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNzQ0LjA5NDQ4IDogNTI2LjE4MTA5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MjYuMTgxMDkgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMjc3NyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSI3NSA6IDQwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjE1MCA6IDYwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA2MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUzMjc1IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjUwIDogMzMuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjEwMCA6IDUwIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiA1MCA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmU1NTMzIgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjMyIDogMjEuMzMzMzMzIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjY0IDogMzIgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDMyIDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI1NTciCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMjUgOiAxNi42NjY2NjcgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfej0iNTAgOiAyNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMjUgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICA8L2RlZnM+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIGlkPSJiYXNlIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxLjAiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAuMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnpvb209IjUuNjU2ODU0MiIKICAgICBpbmtzY2FwZTpjeD0iMjUuOTM4MTE2IgogICAgIGlua3NjYXBlOmN5PSIxNy4yMzAwNSIKICAgICBpbmtzY2FwZTpkb2N1bWVudC11bml0cz0icHgiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ibGF5ZXIxIgogICAgIHNob3dncmlkPSJ0cnVlIgogICAgIGlua3NjYXBlOmdyaWQtYmJveD0idHJ1ZSIKICAgICBpbmtzY2FwZTpncmlkLXBvaW50cz0idHJ1ZSIKICAgICBncmlkdG9sZXJhbmNlPSIxMDAwMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjEzOTkiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iODc0IgogICAgIGlua3NjYXBlOndpbmRvdy14PSIzMyIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMCIKICAgICBpbmtzY2FwZTpzbmFwLWJib3g9InRydWUiPgogICAgPGlua3NjYXBlOmdyaWQKICAgICAgIGlkPSJHcmlkRnJvbVByZTA0NlNldHRpbmdzIgogICAgICAgdHlwZT0ieHlncmlkIgogICAgICAgb3JpZ2lueD0iMHB4IgogICAgICAgb3JpZ2lueT0iMHB4IgogICAgICAgc3BhY2luZ3g9IjFweCIKICAgICAgIHNwYWNpbmd5PSIxcHgiCiAgICAgICBjb2xvcj0iIzAwMDBmZiIKICAgICAgIGVtcGNvbG9yPSIjMDAwMGZmIgogICAgICAgb3BhY2l0eT0iMC4yIgogICAgICAgZW1wb3BhY2l0eT0iMC40IgogICAgICAgZW1wc3BhY2luZz0iNSIKICAgICAgIHZpc2libGU9InRydWUiCiAgICAgICBlbmFibGVkPSJ0cnVlIiAvPgogIDwvc29kaXBvZGk6bmFtZWR2aWV3PgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTciPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0ibGF5ZXIxIj4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJtIDcwLDI1IGMgMjAsMCAyNSwwIDI1LDAiCiAgICAgICBpZD0icGF0aDMwNTkiCiAgICAgICBzb2RpcG9kaTpub2RldHlwZXM9ImNjIiAvPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjEuOTk5OTk5ODg7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gMzAuMzg1NzE3LDE1IEwgNC45OTk5OTk4LDE1IgogICAgICAgaWQ9InBhdGgzMDYxIiAvPgogICAgPHBhdGgKICAgICAgIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjEuOTk5OTk5NzY7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgIGQ9Ik0gMzEuMzYyMDkxLDM1IEwgNC45OTk5OTk4LDM1IgogICAgICAgaWQ9InBhdGgzOTQ0IiAvPgogICAgPGcKICAgICAgIGlkPSJnMjU2MCIKICAgICAgIGlua3NjYXBlOmxhYmVsPSJMYXllciAxIgogICAgICAgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjYuNSwtMzkuNSkiPgogICAgICA8cGF0aAogICAgICAgICBpZD0icGF0aDM1MTYiCiAgICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjM7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgICAgZD0iTSAtMi4yNSw4MS41MDAwMDUgQyAtMy44NDczNzQsODQuMTQ0NDA1IC00LjUsODQuNTAwMDA1IC00LjUsODQuNTAwMDA1IEwgLTguMTU2MjUsODQuNTAwMDA1IEwgLTYuMTU2MjUsODIuMDYyNTA1IEMgLTYuMTU2MjUsODIuMDYyNTA1IC0wLjUsNzUuMDYyNDUxIC0wLjUsNjQuNSBDIC0wLjUsNTMuOTM3NTQ5IC02LjE1NjI1LDQ2LjkzNzUgLTYuMTU2MjUsNDYuOTM3NSBMIC04LjE1NjI1LDQ0LjUgTCAtNC41LDQ0LjUgQyAtMy43MTg3NSw0NS40Mzc1IC0zLjA3ODEyNSw0Ni4xNTYyNSAtMi4yODEyNSw0Ny41IEMgLTAuNDA4NTMxLDUwLjU5OTgxNSAyLjUsNTYuNTI2NjQ2IDIuNSw2NC41IEMgMi41LDcyLjQ1MDY1IC0wLjM5NjY5Nyw3OC4zNzk0MjUgLTIuMjUsODEuNTAwMDA1IHoiCiAgICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NjY3NjY2Njc2MiIC8+CiAgICAgIDxwYXRoCiAgICAgICAgIHN0eWxlPSJmaWxsOiMwMDAwMDA7ZmlsbC1vcGFjaXR5OjE7ZmlsbC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlOm5vbmU7c3Ryb2tlLXdpZHRoOjM7c3Ryb2tlLWxpbmVjYXA6YnV0dDtzdHJva2UtbGluZWpvaW46bWl0ZXI7c3Ryb2tlLW9wYWNpdHk6MSIKICAgICAgICAgZD0iTSAtMi40MDYyNSw0NC41IEwgLTAuNDA2MjUsNDYuOTM3NSBDIC0wLjQwNjI1LDQ2LjkzNzUgNS4yNSw1My45Mzc1NDkgNS4yNSw2NC41IEMgNS4yNSw3NS4wNjI0NTEgLTAuNDA2MjUsODIuMDYyNSAtMC40MDYyNSw4Mi4wNjI1IEwgLTIuNDA2MjUsODQuNSBMIDAuNzUsODQuNSBMIDE0Ljc1LDg0LjUgQyAxNy4xNTgwNzYsODQuNTAwMDAxIDIyLjQzOTY5OSw4NC41MjQ1MTQgMjguMzc1LDgyLjA5Mzc1IEMgMzQuMzEwMzAxLDc5LjY2Mjk4NiA0MC45MTE1MzYsNzQuNzUwNDg0IDQ2LjA2MjUsNjUuMjE4NzUgTCA0NC43NSw2NC41IEwgNDYuMDYyNSw2My43ODEyNSBDIDM1Ljc1OTM4Nyw0NC43MTU1OSAxOS41MDY1NzQsNDQuNSAxNC43NSw0NC41IEwgMC43NSw0NC41IEwgLTIuNDA2MjUsNDQuNSB6IE0gMy40Njg3NSw0Ny41IEwgMTQuNzUsNDcuNSBDIDE5LjQzNDE3Myw0Ny41IDMzLjAzNjg1LDQ3LjM2OTc5MyA0Mi43MTg3NSw2NC41IEMgMzcuOTUxOTY0LDcyLjkyOTA3NSAzMi4xOTc0NjksNzcuMTgzOTEgMjcsNzkuMzEyNSBDIDIxLjYzOTMzOSw4MS41MDc5MjQgMTcuMTU4MDc1LDgxLjUwMDAwMSAxNC43NSw4MS41IEwgMy41LDgxLjUgQyA1LjM3MzU4ODQsNzguMzkxNTY2IDguMjUsNzIuNDUwNjUgOC4yNSw2NC41IEMgOC4yNSw1Ni41MjY2NDYgNS4zNDE0Njg2LDUwLjU5OTgxNSAzLjQ2ODc1LDQ3LjUgeiIKICAgICAgICAgaWQ9InBhdGg0OTczIgogICAgICAgICBzb2RpcG9kaTpub2RldHlwZXM9ImNjc2NjY2NzY2NjY2NjY2Njc2Njc2MiIC8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K' }}
}, joint.shapes.logic.Gate21.prototype.defaults),
operation: function(input1, input2) {
return (!input1 || input2) && (input1 || !input2);
}
});
joint.shapes.logic.Xnor = joint.shapes.logic.Gate21.extend({
defaults: joint.util.deepSupplement({
type: 'logic.Xnor',
attrs: { image: { 'xlink:href': 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHdpZHRoPSIxMDAiCiAgIGhlaWdodD0iNTAiCiAgIGlkPSJzdmcyIgogICBzb2RpcG9kaTp2ZXJzaW9uPSIwLjMyIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjQ2IgogICB2ZXJzaW9uPSIxLjAiCiAgIHNvZGlwb2RpOmRvY25hbWU9IlhOT1IgQU5TSS5zdmciCiAgIGlua3NjYXBlOm91dHB1dF9leHRlbnNpb249Im9yZy5pbmtzY2FwZS5vdXRwdXQuc3ZnLmlua3NjYXBlIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzNCI+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogMTUgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfej0iNTAgOiAxNSA6IDEiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMjUgOiAxMCA6IDEiCiAgICAgICBpZD0icGVyc3BlY3RpdmUyNzE0IiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDAuNSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF96PSIxIDogMC41IDogMSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIwLjUgOiAwLjMzMzMzMzMzIDogMSIKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI4MDYiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI4MTkiCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iMzcyLjA0NzI0IDogMzUwLjc4NzM5IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9Ijc0NC4wOTQ0OCA6IDUyNi4xODEwOSA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNTI2LjE4MTA5IDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgICA8aW5rc2NhcGU6cGVyc3BlY3RpdmUKICAgICAgIGlkPSJwZXJzcGVjdGl2ZTI3NzciCiAgICAgICBpbmtzY2FwZTpwZXJzcDNkLW9yaWdpbj0iNzUgOiA0MCA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSIxNTAgOiA2MCA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNjAgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlMzI3NSIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSI1MCA6IDMzLjMzMzMzMyA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSIxMDAgOiA1MCA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF95PSIwIDogMTAwMCA6IDAiCiAgICAgICBpbmtzY2FwZTp2cF94PSIwIDogNTAgOiAxIgogICAgICAgc29kaXBvZGk6dHlwZT0iaW5rc2NhcGU6cGVyc3AzZCIgLz4KICAgIDxpbmtzY2FwZTpwZXJzcGVjdGl2ZQogICAgICAgaWQ9InBlcnNwZWN0aXZlNTUzMyIKICAgICAgIGlua3NjYXBlOnBlcnNwM2Qtb3JpZ2luPSIzMiA6IDIxLjMzMzMzMyA6IDEiCiAgICAgICBpbmtzY2FwZTp2cF96PSI2NCA6IDMyIDogMSIKICAgICAgIGlua3NjYXBlOnZwX3k9IjAgOiAxMDAwIDogMCIKICAgICAgIGlua3NjYXBlOnZwX3g9IjAgOiAzMiA6IDEiCiAgICAgICBzb2RpcG9kaTp0eXBlPSJpbmtzY2FwZTpwZXJzcDNkIiAvPgogICAgPGlua3NjYXBlOnBlcnNwZWN0aXZlCiAgICAgICBpZD0icGVyc3BlY3RpdmUyNTU3IgogICAgICAgaW5rc2NhcGU6cGVyc3AzZC1vcmlnaW49IjI1IDogMTYuNjY2NjY3IDogMSIKICAgICAgIGlua3NjYXBlOnZwX3o9IjUwIDogMjUgOiAxIgogICAgICAgaW5rc2NhcGU6dnBfeT0iMCA6IDEwMDAgOiAwIgogICAgICAgaW5rc2NhcGU6dnBfeD0iMCA6IDI1IDogMSIKICAgICAgIHNvZGlwb2RpOnR5cGU9Imlua3NjYXBlOnBlcnNwM2QiIC8+CiAgPC9kZWZzPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0iYmFzZSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMS4wIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp6b29tPSI0IgogICAgIGlua3NjYXBlOmN4PSI5NS43MjM2NiIKICAgICBpbmtzY2FwZTpjeT0iLTI2Ljc3NTAyMyIKICAgICBpbmtzY2FwZTpkb2N1bWVudC11bml0cz0icHgiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ibGF5ZXIxIgogICAgIHNob3dncmlkPSJ0cnVlIgogICAgIGlua3NjYXBlOmdyaWQtYmJveD0idHJ1ZSIKICAgICBpbmtzY2FwZTpncmlkLXBvaW50cz0idHJ1ZSIKICAgICBncmlkdG9sZXJhbmNlPSIxMDAwMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9IjEzOTkiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iODc0IgogICAgIGlua3NjYXBlOndpbmRvdy14PSIzMyIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMCIKICAgICBpbmtzY2FwZTpzbmFwLWJib3g9InRydWUiPgogICAgPGlua3NjYXBlOmdyaWQKICAgICAgIGlkPSJHcmlkRnJvbVByZTA0NlNldHRpbmdzIgogICAgICAgdHlwZT0ieHlncmlkIgogICAgICAgb3JpZ2lueD0iMHB4IgogICAgICAgb3JpZ2lueT0iMHB4IgogICAgICAgc3BhY2luZ3g9IjFweCIKICAgICAgIHNwYWNpbmd5PSIxcHgiCiAgICAgICBjb2xvcj0iIzAwMDBmZiIKICAgICAgIGVtcGNvbG9yPSIjMDAwMGZmIgogICAgICAgb3BhY2l0eT0iMC4yIgogICAgICAgZW1wb3BhY2l0eT0iMC40IgogICAgICAgZW1wc3BhY2luZz0iNSIKICAgICAgIHZpc2libGU9InRydWUiCiAgICAgICBlbmFibGVkPSJ0cnVlIiAvPgogIDwvc29kaXBvZGk6bmFtZWR2aWV3PgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTciPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0ibGF5ZXIxIj4KICAgIDxwYXRoCiAgICAgICBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyLjAwMDAwMDI0O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiCiAgICAgICBkPSJNIDc4LjMzMzMzMiwyNSBDIDkxLjY2NjY2NiwyNSA5NSwyNSA5NSwyNSIKICAgICAgIGlkPSJwYXRoMzA1OSIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2MiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MS45OTk5OTk4ODtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSAzMC4zODU3MTcsMTUgTCA0Ljk5OTk5OTgsMTUiCiAgICAgICBpZD0icGF0aDMwNjEiIC8+CiAgICA8cGF0aAogICAgICAgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MS45OTk5OTk3NjtzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgZD0iTSAzMS4zNjIwOTEsMzUgTCA0Ljk5OTk5OTgsMzUiCiAgICAgICBpZD0icGF0aDM5NDQiIC8+CiAgICA8ZwogICAgICAgaWQ9ImcyNTYwIgogICAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgICB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNi41LC0zOS41KSI+CiAgICAgIDxwYXRoCiAgICAgICAgIGlkPSJwYXRoMzUxNiIKICAgICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6ZXZlbm9kZDtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgICBkPSJNIC0yLjI1LDgxLjUwMDAwNSBDIC0zLjg0NzM3NCw4NC4xNDQ0MDUgLTQuNSw4NC41MDAwMDUgLTQuNSw4NC41MDAwMDUgTCAtOC4xNTYyNSw4NC41MDAwMDUgTCAtNi4xNTYyNSw4Mi4wNjI1MDUgQyAtNi4xNTYyNSw4Mi4wNjI1MDUgLTAuNSw3NS4wNjI0NTEgLTAuNSw2NC41IEMgLTAuNSw1My45Mzc1NDkgLTYuMTU2MjUsNDYuOTM3NSAtNi4xNTYyNSw0Ni45Mzc1IEwgLTguMTU2MjUsNDQuNSBMIC00LjUsNDQuNSBDIC0zLjcxODc1LDQ1LjQzNzUgLTMuMDc4MTI1LDQ2LjE1NjI1IC0yLjI4MTI1LDQ3LjUgQyAtMC40MDg1MzEsNTAuNTk5ODE1IDIuNSw1Ni41MjY2NDYgMi41LDY0LjUgQyAyLjUsNzIuNDUwNjUgLTAuMzk2Njk3LDc4LjM3OTQyNSAtMi4yNSw4MS41MDAwMDUgeiIKICAgICAgICAgc29kaXBvZGk6bm9kZXR5cGVzPSJjY2Njc2NjY2NzYyIgLz4KICAgICAgPHBhdGgKICAgICAgICAgc3R5bGU9ImZpbGw6IzAwMDAwMDtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6ZXZlbm9kZDtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MztzdHJva2UtbGluZWNhcDpidXR0O3N0cm9rZS1saW5lam9pbjptaXRlcjtzdHJva2Utb3BhY2l0eToxIgogICAgICAgICBkPSJNIC0yLjQwNjI1LDQ0LjUgTCAtMC40MDYyNSw0Ni45Mzc1IEMgLTAuNDA2MjUsNDYuOTM3NSA1LjI1LDUzLjkzNzU0OSA1LjI1LDY0LjUgQyA1LjI1LDc1LjA2MjQ1MSAtMC40MDYyNSw4Mi4wNjI1IC0wLjQwNjI1LDgyLjA2MjUgTCAtMi40MDYyNSw4NC41IEwgMC43NSw4NC41IEwgMTQuNzUsODQuNSBDIDE3LjE1ODA3Niw4NC41MDAwMDEgMjIuNDM5Njk5LDg0LjUyNDUxNCAyOC4zNzUsODIuMDkzNzUgQyAzNC4zMTAzMDEsNzkuNjYyOTg2IDQwLjkxMTUzNiw3NC43NTA0ODQgNDYuMDYyNSw2NS4yMTg3NSBMIDQ0Ljc1LDY0LjUgTCA0Ni4wNjI1LDYzLjc4MTI1IEMgMzUuNzU5Mzg3LDQ0LjcxNTU5IDE5LjUwNjU3NCw0NC41IDE0Ljc1LDQ0LjUgTCAwLjc1LDQ0LjUgTCAtMi40MDYyNSw0NC41IHogTSAzLjQ2ODc1LDQ3LjUgTCAxNC43NSw0Ny41IEMgMTkuNDM0MTczLDQ3LjUgMzMuMDM2ODUsNDcuMzY5NzkzIDQyLjcxODc1LDY0LjUgQyAzNy45NTE5NjQsNzIuOTI5MDc1IDMyLjE5NzQ2OSw3Ny4xODM5MSAyNyw3OS4zMTI1IEMgMjEuNjM5MzM5LDgxLjUwNzkyNCAxNy4xNTgwNzUsODEuNTAwMDAxIDE0Ljc1LDgxLjUgTCAzLjUsODEuNSBDIDUuMzczNTg4NCw3OC4zOTE1NjYgOC4yNSw3Mi40NTA2NSA4LjI1LDY0LjUgQyA4LjI1LDU2LjUyNjY0NiA1LjM0MTQ2ODYsNTAuNTk5ODE1IDMuNDY4NzUsNDcuNSB6IgogICAgICAgICBpZD0icGF0aDQ5NzMiCiAgICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0iY2NzY2NjY3NjY2NjY2NjY2NzY2NzYyIgLz4KICAgIDwvZz4KICAgIDxwYXRoCiAgICAgICBzb2RpcG9kaTp0eXBlPSJhcmMiCiAgICAgICBzdHlsZT0iZmlsbDpub25lO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDozO3N0cm9rZS1saW5lam9pbjptaXRlcjttYXJrZXI6bm9uZTtzdHJva2Utb3BhY2l0eToxO3Zpc2liaWxpdHk6dmlzaWJsZTtkaXNwbGF5OmlubGluZTtvdmVyZmxvdzp2aXNpYmxlO2VuYWJsZS1iYWNrZ3JvdW5kOmFjY3VtdWxhdGUiCiAgICAgICBpZD0icGF0aDM1NTEiCiAgICAgICBzb2RpcG9kaTpjeD0iNzUiCiAgICAgICBzb2RpcG9kaTpjeT0iMjUiCiAgICAgICBzb2RpcG9kaTpyeD0iNCIKICAgICAgIHNvZGlwb2RpOnJ5PSI0IgogICAgICAgZD0iTSA3OSwyNSBBIDQsNCAwIDEgMSA3MSwyNSBBIDQsNCAwIDEgMSA3OSwyNSB6IiAvPgogIDwvZz4KPC9zdmc+Cg==' }}
}, joint.shapes.logic.Gate21.prototype.defaults),
operation: function(input1, input2) {
return (!input1 || !input2) && (input1 || input2);
}
});
joint.shapes.logic.Wire = joint.dia.Link.extend({
arrowheadMarkup: [
'',
'',
''
].join(''),
vertexMarkup: [
'',
'',
'',
'',
'',
'Remove vertex.',
'',
'',
''
].join(''),
defaults: joint.util.deepSupplement({
type: 'logic.Wire',
attrs: {
'.connection': { 'stroke-width': 2 },
'.marker-vertex': { r: 7 }
},
router: { name: 'orthogonal' },
connector: { name: 'rounded', args: { radius: 10 }}
}, joint.dia.Link.prototype.defaults)
});
if (typeof exports === 'object') {
var graphlib = require('graphlib');
var dagre = require('dagre');
}
// In the browser, these variables are set to undefined because of JavaScript hoisting.
// In that case, should grab them from the window object.
graphlib = graphlib || (typeof window !== 'undefined' && window.graphlib);
dagre = dagre || (typeof window !== 'undefined' && window.dagre);
joint.layout.DirectedGraph = {
layout: function(graphOrCells, opt) {
var graph;
if (graphOrCells instanceof joint.dia.Graph) {
graph = graphOrCells;
} else {
graph = (new joint.dia.Graph()).resetCells(graphOrCells);
}
// This is not needed anymore.
graphOrCells = null;
opt = _.defaults(opt || {}, {
resizeClusters: true,
clusterPadding: 10
});
// create a graphlib.Graph that represents the joint.dia.Graph
var glGraph = graph.toGraphLib({
directed: true,
// We are about to use edge naming feature.
multigraph: true,
// We are able to layout graphs with embeds.
compound: true,
setNodeLabel: function(element) {
return {
width: element.get('size').width,
height: element.get('size').height,
rank: element.get('rank')
};
},
setEdgeLabel: function(link) {
return {
minLen: link.get('minLen') || 1
};
},
setEdgeName: function(link) {
// Graphlib edges have no ids. We use edge name property
// to store and retrieve ids instead.
return link.id;
}
});
var glLabel = {};
// Dagre layout accepts options as lower case.
// Direction for rank nodes. Can be TB, BT, LR, or RL
if (opt.rankDir) glLabel.rankdir = opt.rankDir;
// Alignment for rank nodes. Can be UL, UR, DL, or DR
if (opt.align) glLabel.align = opt.align;
// Number of pixels that separate nodes horizontally in the layout.
if (opt.nodeSep) glLabel.nodesep = opt.nodeSep;
// Number of pixels that separate edges horizontally in the layout.
if (opt.edgeSep) glLabel.edgesep = opt.edgeSep;
// Number of pixels between each rank in the layout.
if (opt.rankSep) glLabel.ranksep = opt.rankSep;
// Number of pixels to use as a margin around the left and right of the graph.
if (opt.marginX) glLabel.marginx = opt.marginX;
// Number of pixels to use as a margin around the top and bottom of the graph.
if (opt.marginY) glLabel.marginy = opt.marginY;
// Set the option object for the graph label.
glGraph.setGraph(glLabel);
// Executes the layout.
dagre.layout(glGraph, { debugTiming: !!opt.debugTiming });
// Wrap all graph changes into a batch.
graph.startBatch('layout');
// Update the graph.
graph.fromGraphLib(glGraph, {
importNode: function(v, gl) {
var element = this.getCell(v);
var glNode = gl.node(v);
if (opt.setPosition) {
opt.setPosition(element, glNode);
} else {
element.set('position', {
x: glNode.x - glNode.width / 2,
y: glNode.y - glNode.height / 2
});
}
},
importEdge: function(edgeObj, gl) {
var link = this.getCell(edgeObj.name);
var glEdge = gl.edge(edgeObj);
var points = glEdge.points || [];
if (opt.setLinkVertices) {
if (opt.setVertices) {
opt.setVertices(link, points);
} else {
// Remove the first and last point from points array.
// Those are source/target element connection points
// ie. they lies on the edge of connected elements.
link.set('vertices', points.slice(1, points.length - 1));
}
}
}
});
if (opt.resizeClusters) {
// Resize and reposition cluster elements (parents of other elements)
// to fit their children.
// 1. filter clusters only
// 2. map id on cells
// 3. sort cells by their depth (the deepest first)
// 4. resize cell to fit their direct children only.
_.chain(glGraph.nodes())
.filter(function(v) { return glGraph.children(v).length > 0; })
.map(graph.getCell, graph)
.sortBy(function(cluster) { return -cluster.getAncestors().length; })
.invoke('fitEmbeds', { padding: opt.clusterPadding })
.value();
}
graph.stopBatch('layout');
// Return an object with height and width of the graph.
return glGraph.graph();
},
fromGraphLib: function(glGraph, opt) {
opt = opt || {};
var importNode = opt.importNode || _.noop;
var importEdge = opt.importEdge || _.noop;
var graph = this instanceof joint.dia.Graph ? this : new joint.dia.Graph;
// Import all nodes.
glGraph.nodes().forEach(function(node) {
importNode.call(graph, node, glGraph, graph, opt);
});
// Import all edges.
glGraph.edges().forEach(function(edge) {
importEdge.call(graph, edge, glGraph, graph, opt);
});
return graph;
},
// Create new graphlib graph from existing JointJS graph.
toGraphLib: function(graph, opt) {
opt = opt || {};
var glGraphType = _.pick(opt, 'directed', 'compound', 'multigraph');
var glGraph = new graphlib.Graph(glGraphType);
var setNodeLabel = opt.setNodeLabel || _.noop;
var setEdgeLabel = opt.setEdgeLabel || _.noop;
var setEdgeName = opt.setEdgeName || _.noop;
graph.get('cells').each(function(cell) {
if (cell.isLink()) {
var source = cell.get('source');
var target = cell.get('target');
// Links that end at a point are ignored.
if (!source.id || !target.id) return;
// Note that if we are creating a multigraph we can name the edges. If
// we try to name edges on a non-multigraph an exception is thrown.
glGraph.setEdge(source.id, target.id, setEdgeLabel(cell), setEdgeName(cell));
} else {
glGraph.setNode(cell.id, setNodeLabel(cell));
// For the compound graphs we have to take embeds into account.
if (glGraph.isCompound() && cell.has('parent')) {
glGraph.setParent(cell.id, cell.get('parent'));
}
}
});
return glGraph;
}
};
joint.dia.Graph.prototype.toGraphLib = function(opt) {
return joint.layout.DirectedGraph.toGraphLib(this, opt);
};
joint.dia.Graph.prototype.fromGraphLib = function(glGraph, opt) {
return joint.layout.DirectedGraph.fromGraphLib.call(this, glGraph, opt);
};
joint.g = g;
joint.V = joint.Vectorizer = V;
return joint;
}));