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_statement
: 'note' placement actor text2 {$$=[$3,{type:'addNote', placement:$2, actor:$3.actor, text:$4}];} : 'note' placement actor text2
| 'note' 'over' spaceList actor_pair actor {
$$ = [$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 spaceList
@ -112,8 +120,8 @@ spaceList
| SPACE | SPACE
; ;
actor_pair actor_pair
: actor { $$ = $1; } : actor ',' actor { $$ = [$1, $3]; }
| actor ',' actor { $$ = [$1, $3]; } | actor { $$ = $1; }
; ;
placement placement

View File

@ -77,8 +77,11 @@ exports.PLACEMENT = {
exports.addNote = function (actor, placement, message){ exports.addNote = function (actor, placement, message){
var note = {actor:actor, placement: placement, message:message}; var note = {actor:actor, placement: placement, message:message};
// Coerce actor into a [to, from, ...] array
var actors = [].concat(actor, actor);
notes.push(note); 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; break;
} }
} }
}; };

View File

@ -231,6 +231,31 @@ describe('when parsing a sequenceDiagram',function() {
expect(messages[0].from).toBe('Alice'); expect(messages[0].from).toBe('Alice');
expect(messages[2].from).toBe('John'); 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 () { it('it should handle loop statements a sequenceDiagram', function () {
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'Alice->Bob: Hello Bob, how are you?\n\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); 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(); sd.bounds.init();
var str = 'sequenceDiagram\n' + var str = 'sequenceDiagram\n' +
'participant Alice\n' + 'participant Alice\n' +
@ -668,7 +709,22 @@ describe('when rendering a sequenceDiagram',function() {
expect(bounds.starty).toBe(0); expect(bounds.starty).toBe(0);
expect(bounds.stopx ).toBe(conf.width*2 + conf.actorMargin); expect(bounds.stopx ).toBe(conf.width*2 + conf.actorMargin);
expect(bounds.stopy ).toBe(0 + conf.messageMargin + conf.height); 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 () { it('it should draw two actors and two messages', function () {
sd.bounds.init(); sd.bounds.init();

View File

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