diagram.lib.diagram.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of common-base Show documentation
Show all versions of common-base Show documentation
DSL based modeling framework - facilities common base
var graph;
function queryParameter(parameterName) {
let query = window.location.search.substring(1);
let parms = query.split('&');
for (let i = 0; i < parms.length; i++) {
let pos = parms[i].indexOf('=');
if (pos > 0 && parameterName == parms[i].substring(0, pos)) {
return parms[i].substring(pos + 1).replace(/%22/g, '');
}
}
return undefined;
}
function collectBases(currentObject, all, hierarchyObjects) {
let currentBase = currentObject.extends;
if (currentBase !== undefined) {
for (let object of all) {
if (object.name === currentBase) {
hierarchyObjects.push(object);
collectBases(object, all, hierarchyObjects);
return;
}
}
}
}
function draw(graph, parent, layout) {
let data = createDiagramData();
let objVertexes = {};
/* objects */
//layout.roots = [];
let objMap = {};
let allObjects = data.content;
for (let object of allObjects) {
objMap[object.name] = object;
}
// create Object map (not vertex map)
let focusedObject;
let hierarchyObjects;
let focused = queryParameter('focused');
if (focused !== undefined) {
for (let object of allObjects) {
if (object.name == focused) {
focusedObject = object;
hierarchyObjects = [];
hierarchyObjects.push(object);
collectBases(focusedObject, allObjects, hierarchyObjects);
}
}
} else {
hierarchyObjects = allObjects;
}
let relationEdges = [];
for (let object of hierarchyObjects) {
let vObj = objVertexes[object.name];
if (vObj === undefined) {
drawObject(graph, parent, object, objMap, objVertexes, 'object', 'title', relationEdges, focusedObject !== undefined, false);
}
if (object.extends === undefined) {
//layout.roots.push(vObj);
}
}
if (focusedObject !== undefined) {
layout.execute(parent);
for (let relationEdge of relationEdges) {
let edge = graph.insertEdge(parent, null, '', relationEdge.from, relationEdge.to, relationEdge.style);
edge.edge = mxEdgeStyle.OrthConnector;
}
let parallelEdgeLayout = new mxParallelEdgeLayout(graph);
parallelEdgeLayout.execute(parent);
} else {
// Executes the layout
layout.execute(parent);
}
}
function drawObject(graph, parent, object, objMap, objVertexes, objStyle, titleStyle, relationEdges, withAssociations, isOther) {
let isInPackage = objMap[object.name] !== undefined;
if (isOther) {
objStyle = 'otherObject';
titleStyle = 'otherTitle';
}
if (!isInPackage) {
objStyle = 'exObject';
titleStyle = 'exTitle';
}
let maxWidth = 80;
let fieldInfos = [];
if (object.fields !== undefined) {
for (let field of object.fields) {
let fieldInfo = {};
if (field.cardinality !== undefined) {
if (field.cardinality === '*') {
fieldInfo.namePart = field.name + '*'
} else {
fieldInfo.namePart = field.name + '[' + field.cardinality + ']'
}
} else {
fieldInfo.namePart = field.name;
}
if (field.type !== undefined) {
fieldInfo.typePart = field.type;
} else if (field.composition !== undefined) {
fieldInfo.typePart = field.composition;
fieldInfo.association = true;
} else if (field.aggregation !== undefined) {
fieldInfo.typePart = field.aggregation;
fieldInfo.association = true;
fieldInfo.reference = true;
}
if (withAssociations || fieldInfo.association !== true) {
fieldInfo.namePart = fieldInfo.namePart + ':';
} else {
//fieldInfo.namePart = fieldInfo.namePart+' \u2192';
}
fieldInfo.nameWidth = mxUtils.getSizeForString(fieldInfo.namePart).width;
fieldInfo.typeWidth = mxUtils.getSizeForString(fieldInfo.typePart).width;
let totalWidth = 80;
if (!withAssociations && fieldInfo.association === true) {
fieldInfo.nameWidth = fieldInfo.nameWidth + 5;
totalWidth = fieldInfo.nameWidth + fieldInfo.typeWidth + 37;
} else {
totalWidth = fieldInfo.nameWidth + fieldInfo.typeWidth + 17;
}
fieldInfos.push(fieldInfo);
//let rect = mxUtils.getSizeForString(fieldInfo.label);
if (maxWidth < totalWidth) {
maxWidth = totalWidth;
}
}
}
let objWidth = maxWidth;
let doc = mxUtils.createXmlDocument();
let classNode = doc.createElement('x')
classNode.setAttribute('label', '');
classNode.setAttribute('isClass', 'true');
let vObj = graph.insertVertex(parent, null, classNode, null, null, objWidth, 35 + fieldInfos.length * 22 + 10, objStyle);
let childVertexes = [];
let titleNode = doc.createElement(object.name);
titleNode.setAttribute('label', object.name);
if (isInPackage) {
titleNode.setAttribute('queryParameter', object.name);
}
let vTitle = graph.insertVertex(vObj, null, null, 0, 0, objWidth + 5, 30, titleStyle);
let vTitleText = graph.insertVertex(vTitle, null, titleNode, (objWidth+5)/2, 15, 0, 0, titleStyle);
childVertexes.push(vTitle);
vTitle.geometry.offset = new mxPoint(0, 10);
vTitle.geometry.relative = true;
if (object.fields !== undefined) {
let i = 0;
for (let fieldInfo of fieldInfos) {
let y = 35 + i * 20 + 7;
let vField = graph.insertVertex(vObj, null, null, null, null, objWidth, 22, 'property');
vField.geometry.offset = new mxPoint(5, 35 + i * 20 + 7);
vField.geometry.height = 20;
vField.geometry.relative = true;
let vNamePart = graph.insertVertex(vField, null, fieldInfo.namePart, 0, 0, fieldInfo.nameWidth, 20, 'propertyDetail');
// vNamePart.geometry.offset = new mxPoint(0, 0);
// vNamePart.geometry.relative = true;
childVertexes.push(vNamePart);
let typeBegin = fieldInfo.nameWidth + 7;
if (!withAssociations && fieldInfo.association === true) {
typeBegin = typeBegin + 20;
}
let typeNode = doc.createElement(fieldInfo.typePart);
typeNode.setAttribute('label', fieldInfo.typePart);
if (!withAssociations && fieldInfo.association === true) {
typeNode.setAttribute('queryParameter', fieldInfo.typePart);
}
let vTypePart = graph.insertVertex(vField, null, typeNode, typeBegin, 0, objWidth - typeBegin, 20, 'propertyDetail');
// vTypePart.geometry.offset = new mxPoint(50, 0);
// vTypePart.geometry.relative = true;
childVertexes.push(vTypePart);
if (!withAssociations && fieldInfo.association === true) {
if (fieldInfo.reference === true) {
let vArrow = graph.insertEdge(vObj, null, '', vNamePart, vTypePart, 'reference');
childVertexes.push(vArrow);
} else {
let vArrow = graph.insertEdge(vObj, null, '', vNamePart, vTypePart, 'containment');
childVertexes.push(vArrow);
}
//let vArrow = graph.insertEdge(vObj, null, '', null, null,'reference');
// vArrow.geometry.spacing=10;
// vArrow.geometry.setTerminalPoint(new mxPoint(fieldInfo.nameWidth+5, y), true);
// vArrow.geometry.setTerminalPoint(new mxPoint(typeBegin+0, y ), false);
// vArrow.geometry.relative = true;
}
childVertexes.push(vField);
i++;
}
}
vObj.geometry.size = new mxPoint(100, 200);
graph.groupCells(vObj, 0, childVertexes);
objVertexes[object.name] = vObj;
drawBaseObject(graph, parent, object, vObj, objMap, objVertexes, relationEdges, withAssociations, isOther);
if (withAssociations && object.fields !== undefined) {
drawRelatedObjects(graph, parent, object, vObj, objMap, objVertexes, relationEdges, withAssociations, isOther);
}
return vObj
}
function drawBaseObject(graph, parent, object, vObj, objMap, objVertexes, relationEdges, withAssociations, isOther) {
if (object.extends !== undefined) {
let vBase = objVertexes[object.extends];
if (vBase === undefined) {
let extObj = objMap[object.extends];
if (extObj === undefined) {
extObj = {};
extObj.name = object.extends;
}
vBase = drawObject(graph, parent, extObj, objMap, objVertexes, 'object', 'title', relationEdges, withAssociations, isOther);
}
if (vObj !== undefined && vBase !== undefined) {
if (isOther) {
graph.insertEdge(parent, null, '', vBase, vObj, 'otherSpecialize');
} else {
graph.insertEdge(parent, null, '', vBase, vObj, 'specialize');
}
}
}
}
function drawRelatedObjects(graph, parent, object, vObj, objMap, objVertexes, relationEdges, withAssociations, isOther) {
let relatedObjects = new Set();
let index = 0;
for (let field of object.fields) {
index = index + 1;
let type = field.composition;
if (type === undefined) {
type = field.aggregation;
}
if (type !== undefined) {
let vType = objVertexes[type];
if (vType === undefined) {
let otherObject = objMap[type];
if (otherObject !== undefined) {
vType = drawObject(graph, parent, otherObject, objMap, objVertexes, 'otherObject', 'otherTitle', relationEdges, true, true);
}
}
if (vType !== undefined) {
let relationInfo = {};
relationInfo.vType = vType;
relationInfo.index = index;
relationInfo.reference = field.aggregation !== undefined;
relationInfo.isOther = isOther;
relatedObjects.add(relationInfo);
}
}
}
for (let relationInfo of relatedObjects) {
let offset = 21 + relationInfo.index * 20;
let v11 = graph.insertVertex(vObj, null, '', 1, 0, 0, 0);
v11.geometry.offset = new mxPoint(0, offset);
v11.geometry.relative = true;
let relationStyle = 'composition';
if (relationInfo.reference == true) {
relationStyle = 'aggregation';
}
if (isOther) {
relationStyle = 'other_' + relationStyle;
}
let relationEdge = {};
relationEdge.from = v11;
relationEdge.to = relationInfo.vType;
relationEdge.style = relationStyle;
relationEdges.push(relationEdge);
}
}
function main(container) {
// Checks if browser is supported
if (!mxClient.isBrowserSupported()) {
// Displays an error message if the browser is
// not supported.
mxUtils.error('Browser is not supported!', 200, false);
} else {
// Disables the built-in context menu
mxEvent.disableContextMenu(container);
mxConstants.VERTEX_SELECTION_COLOR = '#00ff00';
mxConstants.VERTEX_SELECTION_STROKEWIDTH = 2;
mxConstants.VERTEX_SELECTION_DASHED = false;
mxGraph.prototype.isHtmlLabel = function (cell) {
return this.isHtmlLabels();
};
mxGraph.prototype.addListener(mxEvent.CLICK, function (sender, evt) {
let cell = evt.getProperty("cell");
if (cell !== undefined) {
let queryParameter = cell.getAttribute("queryParameter");
if (queryParameter !== undefined) {
let currentLocation = window.location;
let locationPath = location.protocol + '//' + location.host + location.pathname;
let newLocation = locationPath + '?focused=' + queryParameter;
window.location.href = newLocation;
evt.consume();
}
}
});
mxGraph.prototype.getCursorForCell = function (cell) {
if (cell !== undefined &&
cell.getAttribute("queryParameter") != undefined) {
return 'pointer';
}
};
let getCellContainer = function (cell) {
let parentCell = cell.parent;
if (parentCell != null) {
if (parentCell.getAttribute("isClass") !== undefined) {
return parentCell;
} else {
return getCellContainer(parentCell);
}
}
return null;
};
/**
* Redirects start drag to parent.
*/
let graphHandlerGetInitialCellForEvent = mxGraphHandler.prototype.getInitialCellForEvent;
mxGraphHandler.prototype.getInitialCellForEvent = function (me) {
let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments);
let container = getCellContainer(cell);
if (container != null) {
cell = container;
}
return cell;
};
// Creates the graph inside the given container
let graph = new mxGraph(container);
graph.foldingEnabled = false;
//graph.recursiveResize = true;
let hasQueryParameter = function (cell) {
return cell != null &&
cell.getAttribute("queryParameter") != undefined;
};
function updateStyle(state, hover) {
if (hover) {
state.style[mxConstants.STYLE_FONTCOLOR] = '#529aba';
}
}
/* Update cell style on mouseover */
graph.addMouseListener(
{
currentState: null,
previousStyle: null,
mouseDown: function (sender, me) {
if (this.currentState != null) {
this.dragLeave(me.getEvent(), this.currentState);
this.currentState = null;
}
},
mouseMove: function (sender, me) {
if (this.currentState != null && me.getState() == this.currentState) {
return;
}
let tmp = graph.view.getState(me.getCell());
// Ignores everything but vertices with query parameter
if (graph.isMouseDown || (tmp != null && (!
graph.getModel().isVertex(tmp.cell) || !hasQueryParameter(tmp.cell)))) {
tmp = null;
}
if (tmp != this.currentState) {
if (this.currentState != null) {
this.dragLeave(me.getEvent(), this.currentState);
}
this.currentState = tmp;
if (this.currentState != null) {
this.dragEnter(me.getEvent(), this.currentState);
}
}
},
mouseUp: function (sender, me) {
},
dragEnter: function (evt, state) {
if (state != null) {
this.previousStyle = state.style;
state.style = mxUtils.clone(state.style);
updateStyle(state, true);
state.shape.apply(state);
state.shape.redraw();
if (state.text != null) {
state.text.apply(state);
state.text.redraw();
}
}
},
dragLeave: function (evt, state) {
if (state != null) {
state.style = this.previousStyle;
updateStyle(state, false);
state.shape.apply(state);
state.shape.redraw();
if (state.text != null) {
state.text.apply(state);
state.text.redraw();
}
}
}
});
graph.isPart = function (cell) {
return getCellContainer(cell) != null;
};
graph.convertValueToString = function (cell) {
let label = cell.getAttribute('label');
if (label !== undefined) {
return label;
}
return cell.value;
};
graph.selectCellForEvent = function (cell, evt) {
let container = getCellContainer(cell);
if (container != null) {
cell = container;
}
mxGraph.prototype.selectCellForEvent.apply(this, arguments);
};
// Prevent moving certain cells
graph.isCellMovable = function (cell) {
return cell.getAttribute("isClass") !== undefined;
};
graph.border = 80;
graph.getView().translate = new mxPoint(graph.border / 2, graph.border / 2);
// Adds rubberband selection
new mxRubberband(graph);
// Changes the default vertex style in-place
var style = graph.getStylesheet().getDefaultVertexStyle();
style[mxConstants.STYLE_PERIMETER_SPACING] = 6;
// style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
// style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(81,108,180)';
style[mxConstants.STYLE_RESIZABLE] = 0;
// style[mxConstants.STYLE_ROUNDED] = true;
//style[mxConstants.STYLE_SHADOW] = true;
style[mxConstants.STYLE_FILLCOLOR] = 'none';
style[mxConstants.STYLE_FOLDABLE] = 0;
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 2;
graph.getStylesheet().putCellStyle('object', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_STROKECOLOR] = '#717171';
graph.getStylesheet().putCellStyle('exObject', style);
style = [];
style[mxConstants.STYLE_STROKEWIDTH] = 2;
style[mxConstants.STYLE_STROKECOLOR] = '#8c8c8c';
graph.getStylesheet().putCellStyle('otherObject', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
graph.getStylesheet().putCellStyle('title', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
//style[mxConstants.STYLE_FONTCOLOR] = '#808a99';
graph.getStylesheet().putCellStyle('exTitle', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKECOLOR] = '#8c8c8c';
graph.getStylesheet().putCellStyle('otherTitle', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
style[mxConstants.STYLE_STROKEWIDTH] = 0;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_ALIGN] = 'left';
style[mxConstants.STYLE_PERIMETER_SPACING] = 1;
graph.getStylesheet().putCellStyle('property', style);
style = [];
style[mxConstants.STYLE_FONTCOLOR] = '#575757';
//style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_STROKE_OPACITY] = 0;
style[mxConstants.STYLE_ALIGN] = 'left';
style[mxConstants.STYLE_PERIMETER_SPACING] = 1;
//style[mxConstants.STYLE_STROKECOLOR] = 'rgb(81,108,180)';
//style[mxConstants.STYLE_SPACING] = 0;
graph.getStylesheet().putCellStyle('propertyDetail', style);
/* Edge styles */
style = graph.getStylesheet().getDefaultEdgeStyle();
style[mxConstants.STYLE_STROKECOLOR] = 'rgb(81,108,180)';
style[mxConstants.STYLE_ROUNDED] = true;
style = [];
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = -5;
style[mxConstants.STYLE_STARTFILL] = 0;
style[mxConstants.STYLE_STARTSIZE] = 9;
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_BLOCK;
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
graph.getStylesheet().putCellStyle('specialize', style);
style = [];
style[mxConstants.STYLE_STROKE_OPACITY] = 100;
style[mxConstants.STYLE_STROKEWIDTH] = 1;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = -5;
style[mxConstants.STYLE_STARTFILL] = 0;
style[mxConstants.STYLE_STARTSIZE] = 9;
style[mxConstants.STYLE_ROUNDED] = true;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_BLOCK;
style[mxConstants.STYLE_ENDARROW] = mxConstants.NONE;
style[mxConstants.STYLE_STROKECOLOR] = '#8c8c8c';
graph.getStylesheet().putCellStyle('otherSpecialize', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
style[mxConstants.STYLE_STARTFILL] = 0;
style[mxConstants.STYLE_STARTSIZE] = 4;
style[mxConstants.STYLE_ENDSIZE] = 3;
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 2;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_DIAMOND;
graph.getStylesheet().putCellStyle('reference', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
style[mxConstants.STYLE_STARTFILL] = 1;
style[mxConstants.STYLE_STARTSIZE] = 4;
style[mxConstants.STYLE_ENDSIZE] = 3;
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 2;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_STARTARROW] = mxConstants.NONE;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_DIAMOND;
graph.getStylesheet().putCellStyle('containment', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
style[mxConstants.STYLE_STARTFILL] = 0;
style[mxConstants.STYLE_STARTSIZE] = 7;
style[mxConstants.STYLE_ENDSIZE] = 6;
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = -7;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_DIAMOND;
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;
graph.getStylesheet().putCellStyle('aggregation', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
style[mxConstants.STYLE_STARTSIZE] = 7;
style[mxConstants.STYLE_ENDSIZE] = 6;
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = -7;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_DIAMOND;
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;
graph.getStylesheet().putCellStyle('composition', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
style[mxConstants.STYLE_STARTFILL] = 0;
style[mxConstants.STYLE_STARTSIZE] = 7;
style[mxConstants.STYLE_ENDSIZE] = 6;
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = -7;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_DIAMOND;
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;
style[mxConstants.STYLE_STROKECOLOR] = '#8c8c8c';
graph.getStylesheet().putCellStyle('other_aggregation', style);
style = [];
style[mxConstants.STYLE_ENDARROW] = mxConstants.ARROW_CLASSIC;
style[mxConstants.STYLE_STARTSIZE] = 7;
style[mxConstants.STYLE_ENDSIZE] = 6;
//style[mxConstants.STYLE_PERIMETER_SPACING] = 3;
style[mxConstants.STYLE_TARGET_PERIMETER_SPACING] = 0;
style[mxConstants.STYLE_SOURCE_PERIMETER_SPACING] = -7;
style[mxConstants.STYLE_STARTARROW] = mxConstants.ARROW_DIAMOND;
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.EntityRelation;
style[mxConstants.STYLE_STROKECOLOR] = '#8c8c8c';
graph.getStylesheet().putCellStyle('other_composition', style);
/* Layout algorithm */
//let layout = new mxCompactTreeLayout(graph);
let layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_NORTH);
layout.edgeStyle = 4;
layout.intraCellSpacing = 100;
layout.interHierarchySpacing = 100;
let parent = graph.getDefaultParent();
graph.border = 30;
// Load cells and layouts the graph
graph.getModel().beginUpdate();
try {
// draw the diagram
draw(graph, parent, layout);
} finally {
// Updates the display
graph.getModel().endUpdate();
}
if (mxClient.IS_QUIRKS) {
document.body.style.overflow = 'hidden';
new mxDivResizer(container);
}
}
}