1st version parsing for class diagrams, parsing draft completed, starting rendering work

This commit is contained in:
knsv
2015-10-29 07:49:08 +01:00
parent a694f61003
commit 01ddfea478
19 changed files with 1334 additions and 1041 deletions

View File

@@ -3,7 +3,7 @@ import * as Logger from '../../logger';
var log = new Logger.Log();
var relations = [];
var classes = {};
let classes = new Map();
// Functions to be run after graph rendering
var funs = [];
@@ -16,21 +16,28 @@ var funs = [];
*/
exports.addClass = function (id) {
console.log('Adding: '+id);
if(typeof classes.id === 'undefined'){
classes[id] = {
if(typeof classes.get(id) === 'undefined'){
classes.set(id, {
id:id,
methods:[]
};
});
}
};
exports.clear = function () {
relations = [];
classes = {};
classes.clear();
};
module.exports.getClass = function (id) {
return classes[id];
return classes.get(id);
};
module.exports.getClasses = function (id) {
return classes;
};
module.exports.getRelations = function (id) {
return relations;
};
exports.addRelation = function (relation) {
@@ -38,24 +45,6 @@ exports.addRelation = function (relation) {
exports.addClass(relation.id1);
exports.addClass(relation.id2);
//var id1, id2, type1, type2, relationTitle1, relationTitle2, title,label;
//id1=tuple.id1;
//id2=tuple.id2;
//type1=tuple.type1;
//type2=tuple.type2;
//relationTitle1=tuple.relationTitle1;
//relationTitle2=tuple.relationTitle1;
//
//log.debug('Got edge', start, end);
//var edge = {
// id1: id1,
// id2: id2,
// type1: type1,
// type2: type2,
// relationTitle1:relationTitle1,
// relationTitle2:relationTitle2,
// title:title
//};
relations.push(relation);
};

View File

@@ -3,10 +3,11 @@
*/
describe('class diagram, ', function () {
describe('when parsing an info graph it', function () {
var ex, cd;
var cd, cDDb;
beforeEach(function () {
cd = require('./parser/classDiagram').parser;
cd.yy = require('./classDb');
cDDb = require('./classDb');
cd.yy = cDDb;
});
it('should handle relation definitions', function () {
@@ -106,20 +107,108 @@ class User {
});
describe('when fetchiing data an classDiagram graph it', function () {
var ex, cd;
describe('when fetching data from an classDiagram graph it', function () {
var cd, cDDb;
beforeEach(function () {
cd = require('./parser/classDiagram').parser;
cd.yy = require('./classDb');
cDDb = require('./classDb');
cd.yy = cDDb;
cd.yy.clear();
});
it('should handle relation definitions', function () {
it('should handle relation definitions EXTENSION', function () {
var str = `classDiagram
Class01 <|-- Class02`;
Class01 <|-- Class02`;
cd.parse(str);
var relations = cd.yy.getRelations();
expect(cd.yy.getClass('Class01').id).toBe('Class01');
expect(cd.yy.getClass('Class02').id).toBe('Class02');
expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION);
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
});
it('should handle relation definitions AGGREGATION and dotted line', function () {
var str = `classDiagram
Class01 o.. Class02`;
cd.parse(str);
var relations = cd.yy.getRelations();
expect(cd.yy.getClass('Class01').id).toBe('Class01');
expect(cd.yy.getClass('Class02').id).toBe('Class02');
expect(relations[0].relation.type1).toBe(cDDb.relationType.AGGREGATION);
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE);
});
it('should handle relation definitions COMPOSITION on both sides', function () {
var str = `classDiagram
Class01 *--* Class02`;
cd.parse(str);
var relations = cd.yy.getRelations();
expect(cd.yy.getClass('Class01').id).toBe('Class01');
expect(cd.yy.getClass('Class02').id).toBe('Class02');
expect(relations[0].relation.type1).toBe(cDDb.relationType.COMPOSITION);
expect(relations[0].relation.type2).toBe(cDDb.relationType.COMPOSITION);
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
});
it('should handle relation definitions no types', function () {
var str = `classDiagram
Class01 -- Class02`;
cd.parse(str);
var relations = cd.yy.getRelations();
expect(cd.yy.getClass('Class01').id).toBe('Class01');
expect(cd.yy.getClass('Class02').id).toBe('Class02');
expect(relations[0].relation.type1).toBe('none');
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
});
it('should handle relation definitions with type only on right side', function () {
var str = `classDiagram
Class01 --|> Class02`;
cd.parse(str);
var relations = cd.yy.getRelations();
expect(cd.yy.getClass('Class01').id).toBe('Class01');
expect(cd.yy.getClass('Class02').id).toBe('Class02');
expect(relations[0].relation.type1).toBe('none');
expect(relations[0].relation.type2).toBe(cDDb.relationType.EXTENSION);
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
});
it('should handle multiple classes and relation definitions', function () {
var str = `classDiagram
Class01 <|-- Class02
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 -- Class10`;
cd.parse(str);
var relations = cd.yy.getRelations();
expect(cd.yy.getClass('Class01').id).toBe('Class01');
expect(cd.yy.getClass('Class10').id).toBe('Class10');
expect(relations.length).toBe(5);
expect(relations[0].relation.type1).toBe(cDDb.relationType.EXTENSION);
expect(relations[0].relation.type2).toBe('none');
expect(relations[0].relation.lineType).toBe(cDDb.lineType.LINE);
expect(relations[3].relation.type1).toBe('none');
expect(relations[3].relation.type2).toBe('none');
expect(relations[3].relation.lineType).toBe(cDDb.lineType.DOTTED_LINE);
});
});
});

View File

@@ -3,7 +3,8 @@
*/
var cd = require('./parser/classDiagram').parser;
sq.yy = require('./classDb');
var cDDb = require('./classDb');
cd.yy = cDDb;
var d3 = require('../../d3');
import * as Logger from '../../logger';
var log = new Logger.Log();
@@ -21,43 +22,49 @@ var conf = {
* @param pos The position if the actor in the liost of actors
* @param description The text in the box
*/
var drawClass = function(elem, startx, verticalPos, msg){
var rect = svgDraw.getNoteRect();
rect.x = startx;
rect.y = verticalPos;
rect.width = conf.width;
rect.class = 'note';
var drawClass = function(elem, classDef){
//var rect = svgDraw.getNoteRect();
//rect.x = startx;
//rect.y = verticalPos;
//rect.width = conf.width;
//rect.class = 'note';
//
//var g = elem.append('g');
//var rectElem = svgDraw.drawRect(g, rect);
//
//var textObj = svgDraw.getTextObj();
//textObj.x = startx-4;
//textObj.y = verticalPos-13;
//textObj.textMargin = conf.noteMargin;
//textObj.dy = '1em';
//textObj.text = msg.message;
//textObj.class = 'noteText';
//
//var textElem = svgDraw.drawText(g,textObj, conf.width-conf.noteMargin);
//
//var textHeight = textElem[0][0].getBBox().height;
//if(textHeight > conf.width){
// textElem.remove();
// g = elem.append('g');
//
// //textObj.x = textObj.x - conf.width;
// //textElem = svgDraw.drawText(g,textObj, 2*conf.noteMargin);
// textElem = svgDraw.drawText(g,textObj, 2*conf.width-conf.noteMargin);
// textHeight = textElem[0][0].getBBox().height;
// rectElem.attr('width',2*conf.width);
// exports.bounds.insert(startx, verticalPos, startx + 2*conf.width, verticalPos + 2*conf.noteMargin + textHeight);
//}else{
// exports.bounds.insert(startx, verticalPos, startx + conf.width, verticalPos + 2*conf.noteMargin + textHeight);
//}
//
//rectElem.attr('height',textHeight+ 2*conf.noteMargin);
//exports.bounds.bumpVerticalPos(textHeight+ 2*conf.noteMargin);
var g = elem.append('g');
var rectElem = svgDraw.drawRect(g, rect);
var textElem = g.append('text') // text label for the x axis
.style('text-anchor', 'middle')
.attr('class', 'classText')
.text(classDef.id);
var textObj = svgDraw.getTextObj();
textObj.x = startx-4;
textObj.y = verticalPos-13;
textObj.textMargin = conf.noteMargin;
textObj.dy = '1em';
textObj.text = msg.message;
textObj.class = 'noteText';
var textElem = svgDraw.drawText(g,textObj, conf.width-conf.noteMargin);
var textHeight = textElem[0][0].getBBox().height;
if(textHeight > conf.width){
textElem.remove();
g = elem.append('g');
//textObj.x = textObj.x - conf.width;
//textElem = svgDraw.drawText(g,textObj, 2*conf.noteMargin);
textElem = svgDraw.drawText(g,textObj, 2*conf.width-conf.noteMargin);
textHeight = textElem[0][0].getBBox().height;
rectElem.attr('width',2*conf.width);
exports.bounds.insert(startx, verticalPos, startx + 2*conf.width, verticalPos + 2*conf.noteMargin + textHeight);
}else{
exports.bounds.insert(startx, verticalPos, startx + conf.width, verticalPos + 2*conf.noteMargin + textHeight);
}
rectElem.attr('height',textHeight+ 2*conf.noteMargin);
exports.bounds.bumpVerticalPos(textHeight+ 2*conf.noteMargin);
};
@@ -76,16 +83,31 @@ module.exports.setConf = function(cnf){
*/
module.exports.draw = function (text, id) {
cd.yy.clear();
cd.parse(text+'\n');
cd.parse(text);
var width = box.stopx-box.startx+2*conf.diagramMarginX;
if(conf.useMaxWidth) {
diagram.attr('height', '100%');
diagram.attr('width', '100%');
diagram.attr('style', 'max-width:' + (width) + 'px;');
}else{
diagram.attr('height',height);
diagram.attr('width', width );
//// Fetch the default direction, use TD if none was found
var diagram = d3.select('#'+id);
var svg = diagram.append('svg');
let classes = cDDb.getClasses();
for(let classDef of classes.values()){
drawClass(svg, classDef)
}
diagram.attr('viewBox', (box.startx-conf.diagramMarginX) + ' -' +conf.diagramMarginY + ' ' + width + ' ' + height);
//
//
//
//
//
//if(conf.useMaxWidth) {
// diagram.attr('height', '100%');
// diagram.attr('width', '100%');
// diagram.attr('style', 'max-width:' + (width) + 'px;');
//}else{
// diagram.attr('height',height);
// diagram.attr('width', width );
//}
//diagram.attr('viewBox', (box.startx-conf.diagramMarginX) + ' -' +conf.diagramMarginY + ' ' + width + ' ' + height);
};

View File

@@ -0,0 +1,113 @@
//var proxyquire = require('proxyquire');
//var newD3;
///**
// * Created by knut on 14-11-18.
// */
//
//var d3 = {
// select:function(){
// return new newD3();
// },
// selectAll:function(){
// return new newD3();
// }
//};
//var classRenderer = proxyquire('./classRenderer', { '../../d3': d3 });
var testDom = require('testdom')('<html><body><div id="tst"></div></body></html>');
var classRenderer = require('./classRenderer');
var parser = require('./parser/classDiagram').parser;
fdescribe('class diagram, ', function () {
describe('when rendering a classDiagram',function() {
var conf;
beforeEach(function () {
////parser.yy = require('./classDb');
////parser.yy.clear();
////parseError = function(err, hash) {
//// log.debug('Syntax error:' + err);
//// log.debug(hash);
////};
////sq.yy.parseError = parseError;
//
//newD3 = function() {
// var o = {
// append: function () {
// return newD3();
// },
// attr: function () {
// return this;
// },
// style: function () {
// return this;
// },
// text: function () {
// return this;
// },
// 0:{
// 0: {
// getBBox: function () {
// return {
// height: 10,
// width: 20
// };
// }
// }
//
// }
// };
//
// return o;
//};
//
//conf = {
// diagramMarginX:50,
// diagramMarginY:10,
// actorMargin:50,
// width:150,
// // Height of actor boxes
// height:65,
// boxMargin:10,
// messageMargin:40,
// boxTextMargin:15,
// noteMargin:25,
// mirrorActors:true,
// // Depending on css styling this might need adjustment
// // Prolongs the edge of the diagram downwards
// bottomMarginAdj:1
//};
//classRenderer.setConf(conf);
// ... add whatever browser globals your tests might need ...
//}
Object.defineProperties(window.HTMLElement.prototype, {
getBBox :{
get : function() {return {x:10,y:10,width:100,height:100}; }
},
offsetLeft: {
get: function() { return parseFloat(window.getComputedStyle(this).marginLeft) || 0; }
},
offsetTop: {
get: function() { return parseFloat(window.getComputedStyle(this).marginTop) || 0; }
},
offsetHeight: {
get: function() { return parseFloat(window.getComputedStyle(this).height) || 0; }
},
offsetWidth: {
get: function() { return parseFloat(window.getComputedStyle(this).width) || 0; }
}
});
});
it('it should handle one actor', function () {
var str = `classDiagram
Class01 --|> Class02`;
classRenderer.draw(str,'tst');
console.log(document.body.innerHTML);
});
});
});

View File

@@ -168,7 +168,7 @@ relationStatement
;
relation
: relationType lineType relationType { $$={type1:$1,type2:$2,lineType:$3}; }
: relationType lineType relationType { $$={type1:$1,type2:$3,lineType:$2}; }
| lineType relationType { $$={type1:'none',type2:$2,lineType:$1}; }
| relationType lineType { $$={type1:$1,type2:'none',lineType:$2}; }
| lineType { $$={type1:'none',type2:'none',lineType:$1}; }

View File

@@ -123,7 +123,7 @@ case 22:
this.$ = {id1:$$[$0-4], id2:$$[$0], relation:$$[$0-2], relationTitle1:$$[$0-3], relationTitle2:$$[$0-1]}
break;
case 23:
this.$={type1:$$[$0-2],type2:$$[$0-1],lineType:$$[$0]};
this.$={type1:$$[$0-2],type2:$$[$0],lineType:$$[$0-1]};
break;
case 24:
this.$={type1:'none',type2:$$[$0],lineType:$$[$0-1]};