Support sequenceDiagram "over" notes

This commit is contained in:
Richard Gibson 2015-11-06 02:42:03 -05:00
parent 76130bc485
commit 26ebbf82ee
4 changed files with 93 additions and 21 deletions

View File

@ -103,8 +103,16 @@ statement
;
note_statement
: 'note' placement actor text2 {$$=[$3,{type:'addNote', placement:$2, actor:$3.actor, text:$4}];}
| 'note' 'over' spaceList actor_pair actor
: 'note' placement actor text2
{
$$ = [$3, {type:'addNote', placement:$2, actor:$3.actor, text:$4}];}
| 'note' 'over' actor_pair text2
{
// Coerce actor_pair into a [to, from, ...] array
$2 = [].concat($3, $3).slice(0, 2);
$2[0] = $2[0].actor;
$2[1] = $2[1].actor;
$$ = [$3, {type:'addNote', placement:yy.PLACEMENT.OVER, actor:$2.slice(0, 2), text:$4}];}
;
spaceList
@ -112,8 +120,8 @@ spaceList
| SPACE
;
actor_pair
: actor { $$ = $1; }
| actor ',' actor { $$ = [$1, $3]; }
: actor ',' actor { $$ = [$1, $3]; }
| actor { $$ = $1; }
;
placement

View File

@ -77,8 +77,11 @@ exports.PLACEMENT = {
exports.addNote = function (actor, placement, message){
var note = {actor:actor, placement: placement, message:message};
// Coerce actor into a [to, from, ...] array
var actors = [].concat(actor, actor);
notes.push(note);
messages.push({from:actor, to:actor, message:message, type:exports.LINETYPE.NOTE, placement: placement});
messages.push({from:actors[0], to:actors[1], message:message, type:exports.LINETYPE.NOTE, placement: placement});
};
@ -132,4 +135,4 @@ exports.apply = function(param){
break;
}
}
};
};

View File

@ -231,6 +231,31 @@ describe('when parsing a sequenceDiagram',function() {
expect(messages[0].from).toBe('Alice');
expect(messages[2].from).toBe('John');
});
it('it should handle notes over a single actor', function () {
var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' +
'Note over Bob: Bob thinks\n';
sq.parse(str);
var messages = sq.yy.getMessages();
expect(messages[1].from).toBe('Bob');
expect(messages[1].to).toBe('Bob');
});
it('it should handle notes over multiple actors', function () {
var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n' +
'Note over Alice,Bob: confusion\n' +
'Note over Bob,Alice: resolution\n';
sq.parse(str);
var messages = sq.yy.getMessages();
expect(messages[1].from).toBe('Alice');
expect(messages[1].to).toBe('Bob');
expect(messages[2].from).toBe('Bob');
expect(messages[2].to).toBe('Alice');
});
it('it should handle loop statements a sequenceDiagram', function () {
var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n\n' +
@ -623,7 +648,23 @@ describe('when rendering a sequenceDiagram',function() {
expect(bounds.stopy ).toBe(conf.height);
});
it('it should handle one actor and a note', function () {
it('it should handle one actor and a centered note', function () {
sd.bounds.init();
var str = 'sequenceDiagram\n' +
'participant Alice\n' +
'Note over Alice: Alice thinks\n';
sq.parse(str);
sd.draw(str,'tst');
var bounds = sd.bounds.getBounds();
expect(bounds.startx).toBe(0);
expect(bounds.starty).toBe(0);
expect(bounds.stopx ).toBe( conf.width);
// 10 comes from mock of text height
expect(bounds.stopy ).toBe( conf.height + conf.boxMargin + 2*conf.noteMargin +10);
});
it('it should handle one actor and a note to the left', function () {
sd.bounds.init();
var str = 'sequenceDiagram\n' +
'participant Alice\n' +
@ -668,7 +709,22 @@ describe('when rendering a sequenceDiagram',function() {
expect(bounds.starty).toBe(0);
expect(bounds.stopx ).toBe(conf.width*2 + conf.actorMargin);
expect(bounds.stopy ).toBe(0 + conf.messageMargin + conf.height);
});
it('it should handle two actors and two centered shared notes', function () {
sd.bounds.init();
var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n'+
'Note over Alice,Bob: Looks\n' +
'Note over Bob,Alice: Looks back\n';
sq.parse(str);
sd.draw(str,'tst');
var bounds = sd.bounds.getBounds();
expect(bounds.startx).toBe(0);
expect(bounds.starty).toBe(0);
expect(bounds.stopx ).toBe(conf.width*2 + conf.actorMargin);
expect(bounds.stopy ).toBe( conf.height + conf.messageMargin + 2*(conf.boxMargin + 2*conf.noteMargin + 10));
});
it('it should draw two actors and two messages', function () {
sd.bounds.init();

View File

@ -129,11 +129,11 @@ exports.bounds = {
* @param pos The position if the actor in the liost of actors
* @param description The text in the box
*/
var drawNote = function(elem, startx, verticalPos, msg){
var drawNote = function(elem, startx, verticalPos, msg, forceWidth){
var rect = svgDraw.getNoteRect();
rect.x = startx;
rect.y = verticalPos;
rect.width = conf.width;
rect.width = forceWidth || conf.width;
rect.class = 'note';
var g = elem.append('g');
@ -147,21 +147,19 @@ var drawNote = function(elem, startx, verticalPos, msg){
textObj.text = msg.message;
textObj.class = 'noteText';
var textElem = svgDraw.drawText(g,textObj, conf.width-conf.noteMargin);
var textElem = svgDraw.drawText(g,textObj, rect.width-conf.noteMargin);
var textHeight = textElem[0][0].getBBox().height;
if(textHeight > conf.width){
if(!forceWidth && 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);
textElem = svgDraw.drawText(g,textObj, 2*rect.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);
rectElem.attr('width',2*rect.width);
exports.bounds.insert(startx, verticalPos, startx + 2*rect.width, verticalPos + 2*conf.noteMargin + textHeight);
}else{
exports.bounds.insert(startx, verticalPos, startx + conf.width, verticalPos + 2*conf.noteMargin + textHeight);
exports.bounds.insert(startx, verticalPos, startx + rect.width, verticalPos + 2*conf.noteMargin + textHeight);
}
rectElem.attr('height',textHeight+ 2*conf.noteMargin);
@ -290,6 +288,7 @@ module.exports.draw = function (text, id) {
var startx;
var stopx;
var forceWidth;
// Fetch data from the parsing
var actors = sq.yy.getActors();
@ -312,13 +311,19 @@ module.exports.draw = function (text, id) {
startx = actors[msg.from].x;
stopx = actors[msg.to].x;
if(msg.placement !== 0){
// Right of
if(msg.placement === sq.yy.PLACEMENT.RIGHTOF){
drawNote(diagram, startx + (conf.width + conf.actorMargin)/2, exports.bounds.getVerticalPos(), msg);
}else{
// Left of
}else if(msg.placement === sq.yy.PLACEMENT.LEFTOF){
drawNote(diagram, startx - (conf.width + conf.actorMargin)/2, exports.bounds.getVerticalPos(), msg);
}else if(msg.to === msg.from) {
// Single-actor over
drawNote(diagram, startx, exports.bounds.getVerticalPos(), msg);
}else{
// Multi-actor over
forceWidth = Math.abs(startx - stopx) + conf.actorMargin;
drawNote(diagram, (startx + stopx + conf.width - forceWidth)/2, exports.bounds.getVerticalPos(), msg,
forceWidth);
}
break;
case sq.yy.LINETYPE.LOOP_START: