Add support for unbordered text content, add convenience for placing notes/text on left/right of entire diagram

This commit is contained in:
David Evans 2017-10-28 18:30:01 +01:00
parent 912c9dbb64
commit cd949d6f38
8 changed files with 79 additions and 6 deletions

View File

@ -75,6 +75,8 @@ note over Foo, Bar: "Foo and Bar
on multiple lines" on multiple lines"
note between Foo, Bar: Link note between Foo, Bar: Link
text right: 'Comments\nOver here!'
state over Foo: Foo is ponderous state over Foo: Foo is ponderous
``` ```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -11,6 +11,12 @@ define(['core/ArrayUtilities'], (array) => {
const LOCKED_AGENT = new AgentState(false, true); const LOCKED_AGENT = new AgentState(false, true);
const DEFAULT_AGENT = new AgentState(false); const DEFAULT_AGENT = new AgentState(false);
const NOTE_DEFAULT_AGENTS = {
'note over': ['[', ']'],
'note left': ['['],
'note right': [']'],
};
return class Generator { return class Generator {
constructor() { constructor() {
this.agentStates = new Map(); this.agentStates = new Map();
@ -24,6 +30,9 @@ define(['core/ArrayUtilities'], (array) => {
this.stageHandlers = { this.stageHandlers = {
'mark': this.handleMark.bind(this), 'mark': this.handleMark.bind(this),
'async': this.handleAsync.bind(this), 'async': this.handleAsync.bind(this),
'note over': this.handleNote.bind(this),
'note left': this.handleNote.bind(this),
'note right': this.handleNote.bind(this),
'agent define': this.handleAgentDefine.bind(this), 'agent define': this.handleAgentDefine.bind(this),
'agent begin': this.handleAgentBegin.bind(this), 'agent begin': this.handleAgentBegin.bind(this),
'agent end': this.handleAgentEnd.bind(this), 'agent end': this.handleAgentEnd.bind(this),
@ -131,6 +140,16 @@ define(['core/ArrayUtilities'], (array) => {
this.currentSection.stages.push(stage); this.currentSection.stages.push(stage);
} }
handleNote(stage) {
if(stage.agents.length === 0) {
this.handleUnknownStage(Object.assign({}, stage, {
agents: NOTE_DEFAULT_AGENTS[stage.type] || [],
}));
} else {
this.handleUnknownStage(stage);
}
}
handleAgentDefine({agents}) { handleAgentDefine({agents}) {
array.mergeSets(this.currentNest.agents, agents); array.mergeSets(this.currentNest.agents, agents);
array.mergeSets(this.agents, agents); array.mergeSets(this.agents, agents);

View File

@ -481,6 +481,21 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
]})).toThrow(); ]})).toThrow();
}); });
it('defaults to showing notes around the entire diagram', () => {
const sequence = generator.generate({stages: [
{type: 'note right', agents: [], foo: 'bar'},
{type: 'note left', agents: [], foo: 'bar'},
{type: 'note over', agents: [], foo: 'bar'},
{type: 'note right', agents: ['[']},
]});
expect(sequence.stages).toEqual([
{type: 'note right', agents: [']'], foo: 'bar'},
{type: 'note left', agents: ['['], foo: 'bar'},
{type: 'note over', agents: ['[', ']'], foo: 'bar'},
{type: 'note right', agents: ['[']},
]);
});
it('rejects attempts to change implicit agents', () => { it('rejects attempts to change implicit agents', () => {
expect(() => generator.generate({stages: [ expect(() => generator.generate({stages: [
{type: AGENT_BEGIN, agents: ['['], mode: 'box'}, {type: AGENT_BEGIN, agents: ['['], mode: 'box'},

View File

@ -49,12 +49,19 @@ define(['core/ArrayUtilities'], (array) => {
]; ];
const NOTE_TYPES = { const NOTE_TYPES = {
'text': {
mode: 'text',
types: {
'left': {type: 'note left', skip: ['of'], min: 0, max: null},
'right': {type: 'note right', skip: ['of'], min: 0, max: null},
},
},
'note': { 'note': {
mode: 'note', mode: 'note',
types: { types: {
'over': {type: 'note over', skip: [], min: 1, max: null}, 'over': {type: 'note over', skip: [], min: 0, max: null},
'left': {type: 'note left', skip: ['of'], min: 1, max: null}, 'left': {type: 'note left', skip: ['of'], min: 0, max: null},
'right': {type: 'note right', skip: ['of'], min: 1, max: null}, 'right': {type: 'note right', skip: ['of'], min: 0, max: null},
'between': {type: 'note between', skip: [], min: 2, max: null}, 'between': {type: 'note between', skip: [], min: 2, max: null},
}, },
}, },

View File

@ -325,7 +325,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
}); });
it('rejects note between for a single agent', () => { it('rejects note between for a single agent', () => {
expect(() => parser.parse('state between A: hi')).toThrow(); expect(() => parser.parse('note between A: hi')).toThrow();
}); });
it('converts state', () => { it('converts state', () => {
@ -342,6 +342,16 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
expect(() => parser.parse('state over A, B: hi')).toThrow(); expect(() => parser.parse('state over A, B: hi')).toThrow();
}); });
it('converts text blocks', () => {
const parsed = parser.parse('text right of A: doing stuff');
expect(parsed.stages).toEqual([{
type: 'note right',
agents: ['A'],
mode: 'text',
label: 'doing stuff',
}]);
});
it('converts agent commands', () => { it('converts agent commands', () => {
const parsed = parser.parse( const parsed = parser.parse(
'define A, B\n' + 'define A, B\n' +

View File

@ -170,6 +170,8 @@ define([
agents.forEach((agentR) => { agents.forEach((agentR) => {
const infoR = this.agentInfos.get(agentR); const infoR = this.agentInfos.get(agentR);
const sepR = agentSpaces.get(agentR) || SEP_ZERO; const sepR = agentSpaces.get(agentR) || SEP_ZERO;
infoR.maxRPad = Math.max(infoR.maxRPad, sepR.right);
infoR.maxLPad = Math.max(infoR.maxLPad, sepR.left);
agents.forEach((agentL) => { agents.forEach((agentL) => {
const infoL = this.agentInfos.get(agentL); const infoL = this.agentInfos.get(agentL);
if(infoL.index >= infoR.index) { if(infoL.index >= infoR.index) {
@ -853,8 +855,6 @@ define([
} }
}); });
agentInfo.x = currentX; agentInfo.x = currentX;
this.minX = Math.min(this.minX, currentX);
this.maxX = Math.max(this.maxX, currentX);
orderedInfos.push(agentInfo); orderedInfos.push(agentInfo);
}); });
@ -873,6 +873,11 @@ define([
}); });
agentInfo.x = currentX; agentInfo.x = currentX;
}); });
this.agentInfos.forEach(({label, x, maxRPad, maxLPad}) => {
this.minX = Math.min(this.minX, x - maxLPad);
this.maxX = Math.max(this.maxX, x + maxRPad);
});
} }
buildAgentInfos(agents, stages) { buildAgentInfos(agents, stages) {
@ -885,6 +890,8 @@ define([
x: null, x: null,
latestYStart: null, latestYStart: null,
latestY: 0, latestY: 0,
maxRPad: 0,
maxLPad: 0,
separations: new Map(), separations: new Map(),
}); });
}); });

View File

@ -178,6 +178,19 @@ define([
}, },
note: { note: {
'text': {
margin: {top: 0, left: 2, right: 2, bottom: 0},
padding: {top: 2, left: 2, right: 2, bottom: 2},
overlap: {left: 10, right: 10},
boxRenderer: SVGShapes.renderBox.bind(null, {
'fill': '#FFFFFF',
}),
labelAttrs: {
'font-family': 'sans-serif',
'font-size': 8,
'line-height': LINE_HEIGHT,
},
},
'note': { 'note': {
margin: {top: 0, left: 5, right: 5, bottom: 0}, margin: {top: 0, left: 5, right: 5, bottom: 0},
padding: {top: 5, left: 5, right: 10, bottom: 5}, padding: {top: 5, left: 5, right: 10, bottom: 5},