Beginnings of theme switching capability
This commit is contained in:
parent
5b6cbd518e
commit
f6f557bcd7
|
@ -11,13 +11,15 @@
|
||||||
'sequence/Generator',
|
'sequence/Generator',
|
||||||
'sequence/Renderer',
|
'sequence/Renderer',
|
||||||
'sequence/themes/Basic',
|
'sequence/themes/Basic',
|
||||||
|
'sequence/themes/Chunky',
|
||||||
], (
|
], (
|
||||||
Interface,
|
Interface,
|
||||||
Exporter,
|
Exporter,
|
||||||
Parser,
|
Parser,
|
||||||
Generator,
|
Generator,
|
||||||
Renderer,
|
Renderer,
|
||||||
Theme
|
BasicTheme,
|
||||||
|
ChunkyTheme
|
||||||
) => {
|
) => {
|
||||||
const defaultCode = (
|
const defaultCode = (
|
||||||
'title Labyrinth\n' +
|
'title Labyrinth\n' +
|
||||||
|
@ -41,7 +43,10 @@
|
||||||
defaultCode,
|
defaultCode,
|
||||||
parser: new Parser(),
|
parser: new Parser(),
|
||||||
generator: new Generator(),
|
generator: new Generator(),
|
||||||
renderer: new Renderer(new Theme()),
|
renderer: new Renderer({themes: [
|
||||||
|
new BasicTheme(),
|
||||||
|
new ChunkyTheme(),
|
||||||
|
]}),
|
||||||
exporter: new Exporter(),
|
exporter: new Exporter(),
|
||||||
localStorage: 'src',
|
localStorage: 'src',
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,8 +17,18 @@
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FAVICON_SRC = (
|
||||||
|
'theme chunky\n' +
|
||||||
|
'define ABC as A, DEF as B\n' +
|
||||||
|
'A -> B\n' +
|
||||||
|
'B -> ]\n' +
|
||||||
|
'] -> B\n' +
|
||||||
|
'B -> A\n' +
|
||||||
|
'terminators fade'
|
||||||
|
);
|
||||||
|
|
||||||
const SAMPLE_REGEX = new RegExp(
|
const SAMPLE_REGEX = new RegExp(
|
||||||
/<img src="screenshots\/([^"]*)"[^>]*>[\s]*```(?!shell).*\n([^]+?)```/g
|
/<img src="([^"]*)"[^>]*>[\s]*```(?!shell).*\n([^]+?)```/g
|
||||||
);
|
);
|
||||||
|
|
||||||
function findSamples(content) {
|
function findSamples(content) {
|
||||||
|
@ -34,9 +44,23 @@
|
||||||
code: match[2],
|
code: match[2],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
results.push({
|
||||||
|
file: 'favicon.png',
|
||||||
|
code: FAVICON_SRC,
|
||||||
|
height: 64,
|
||||||
|
});
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function filename(path) {
|
||||||
|
const p = path.lastIndexOf('/');
|
||||||
|
if(p !== -1) {
|
||||||
|
return path.substr(p + 1);
|
||||||
|
} else {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const PNG_RESOLUTION = 4;
|
const PNG_RESOLUTION = 4;
|
||||||
|
|
||||||
/* jshint -W072 */ // Allow several required modules
|
/* jshint -W072 */ // Allow several required modules
|
||||||
|
@ -45,25 +69,30 @@
|
||||||
'sequence/Generator',
|
'sequence/Generator',
|
||||||
'sequence/Renderer',
|
'sequence/Renderer',
|
||||||
'sequence/themes/Basic',
|
'sequence/themes/Basic',
|
||||||
|
'sequence/themes/Chunky',
|
||||||
'interface/Exporter',
|
'interface/Exporter',
|
||||||
], (
|
], (
|
||||||
Parser,
|
Parser,
|
||||||
Generator,
|
Generator,
|
||||||
Renderer,
|
Renderer,
|
||||||
Theme,
|
BasicTheme,
|
||||||
|
ChunkyTheme,
|
||||||
Exporter
|
Exporter
|
||||||
) => {
|
) => {
|
||||||
const parser = new Parser();
|
const parser = new Parser();
|
||||||
const generator = new Generator();
|
const generator = new Generator();
|
||||||
const theme = new Theme();
|
const themes = [
|
||||||
|
new BasicTheme(),
|
||||||
|
new ChunkyTheme(),
|
||||||
|
];
|
||||||
|
|
||||||
const status = makeNode('div', {'class': 'status'});
|
const status = makeNode('div', {'class': 'status'});
|
||||||
const statusText = makeText('Loading\u2026');
|
const statusText = makeText('Loading\u2026');
|
||||||
status.appendChild(statusText);
|
status.appendChild(statusText);
|
||||||
document.body.appendChild(status);
|
document.body.appendChild(status);
|
||||||
|
|
||||||
function renderSample({file, code}) {
|
function renderSample({file, code, height}) {
|
||||||
const renderer = new Renderer(theme);
|
const renderer = new Renderer({themes});
|
||||||
const exporter = new Exporter();
|
const exporter = new Exporter();
|
||||||
|
|
||||||
const hold = makeNode('div', {'class': 'hold'});
|
const hold = makeNode('div', {'class': 'hold'});
|
||||||
|
@ -78,12 +107,15 @@
|
||||||
hold.appendChild(raster);
|
hold.appendChild(raster);
|
||||||
|
|
||||||
hold.appendChild(makeNode('img', {
|
hold.appendChild(makeNode('img', {
|
||||||
'src': 'screenshots/' + file,
|
'src': file,
|
||||||
'class': 'original',
|
'class': 'original',
|
||||||
'title': 'original',
|
'title': 'original',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const downloadPNG = makeNode('a', {'href': '#', 'download': file});
|
const downloadPNG = makeNode('a', {
|
||||||
|
'href': '#',
|
||||||
|
'download': filename(file),
|
||||||
|
});
|
||||||
downloadPNG.appendChild(makeText('Download PNG'));
|
downloadPNG.appendChild(makeText('Download PNG'));
|
||||||
hold.appendChild(downloadPNG);
|
hold.appendChild(downloadPNG);
|
||||||
|
|
||||||
|
@ -92,7 +124,11 @@
|
||||||
const parsed = parser.parse(code);
|
const parsed = parser.parse(code);
|
||||||
const sequence = generator.generate(parsed);
|
const sequence = generator.generate(parsed);
|
||||||
renderer.render(sequence);
|
renderer.render(sequence);
|
||||||
exporter.getPNGURL(renderer, PNG_RESOLUTION, (url) => {
|
let resolution = PNG_RESOLUTION;
|
||||||
|
if(height) {
|
||||||
|
resolution = height / renderer.height;
|
||||||
|
}
|
||||||
|
exporter.getPNGURL(renderer, resolution, (url) => {
|
||||||
raster.setAttribute('src', url);
|
raster.setAttribute('src', url);
|
||||||
downloadPNG.setAttribute('href', url);
|
downloadPNG.setAttribute('href', url);
|
||||||
});
|
});
|
||||||
|
|
|
@ -121,6 +121,9 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
'title': {type: 'keyword', suggest: true, then: {
|
'title': {type: 'keyword', suggest: true, then: {
|
||||||
'': textToEnd,
|
'': textToEnd,
|
||||||
}},
|
}},
|
||||||
|
'theme': {type: 'keyword', suggest: true, then: {
|
||||||
|
'': textToEnd,
|
||||||
|
}},
|
||||||
'terminators': {type: 'keyword', suggest: true, then: {
|
'terminators': {type: 'keyword', suggest: true, then: {
|
||||||
'none': {type: 'keyword', suggest: true, then: {}},
|
'none': {type: 'keyword', suggest: true, then: {}},
|
||||||
'cross': {type: 'keyword', suggest: true, then: {}},
|
'cross': {type: 'keyword', suggest: true, then: {}},
|
||||||
|
|
|
@ -539,6 +539,7 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
return {
|
return {
|
||||||
meta: {
|
meta: {
|
||||||
title: meta.title,
|
title: meta.title,
|
||||||
|
theme: meta.theme,
|
||||||
},
|
},
|
||||||
agents: this.agents.slice(),
|
agents: this.agents.slice(),
|
||||||
stages: globals.stages,
|
stages: globals.stages,
|
||||||
|
|
|
@ -148,13 +148,13 @@ defineDescribe('Sequence Generator', ['./Generator'], (Generator) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('.generate', () => {
|
describe('.generate', () => {
|
||||||
it('propagates title metadata', () => {
|
it('propagates title and theme metadata', () => {
|
||||||
const input = {
|
const input = {
|
||||||
meta: {title: 'bar'},
|
meta: {title: 'bar', theme: 'zig', nope: 'skip'},
|
||||||
stages: [],
|
stages: [],
|
||||||
};
|
};
|
||||||
const sequence = generator.generate(input);
|
const sequence = generator.generate(input);
|
||||||
expect(sequence.meta).toEqual({title: 'bar'});
|
expect(sequence.meta).toEqual({title: 'bar', theme: 'zig'});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns an empty sequence for blank input', () => {
|
it('returns an empty sequence for blank input', () => {
|
||||||
|
|
|
@ -188,6 +188,15 @@ define([
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
(line, meta) => { // theme
|
||||||
|
if(tokenKeyword(line[0]) !== 'theme') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta.theme = joinLabel(line, 1);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
(line, meta) => { // terminators
|
(line, meta) => { // terminators
|
||||||
if(tokenKeyword(line[0]) !== 'terminators') {
|
if(tokenKeyword(line[0]) !== 'terminators') {
|
||||||
return null;
|
return null;
|
||||||
|
@ -356,6 +365,7 @@ define([
|
||||||
const result = {
|
const result = {
|
||||||
meta: {
|
meta: {
|
||||||
title: '',
|
title: '',
|
||||||
|
theme: '',
|
||||||
terminators: 'none',
|
terminators: 'none',
|
||||||
},
|
},
|
||||||
stages: [],
|
stages: [],
|
||||||
|
|
|
@ -33,6 +33,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
expect(parsed).toEqual({
|
expect(parsed).toEqual({
|
||||||
meta: {
|
meta: {
|
||||||
title: '',
|
title: '',
|
||||||
|
theme: '',
|
||||||
terminators: 'none',
|
terminators: 'none',
|
||||||
},
|
},
|
||||||
stages: [],
|
stages: [],
|
||||||
|
@ -44,6 +45,11 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
expect(parsed.meta.title).toEqual('foo');
|
expect(parsed.meta.title).toEqual('foo');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('reads theme metadata', () => {
|
||||||
|
const parsed = parser.parse('theme foo');
|
||||||
|
expect(parsed.meta.theme).toEqual('foo');
|
||||||
|
});
|
||||||
|
|
||||||
it('reads terminators metadata', () => {
|
it('reads terminators metadata', () => {
|
||||||
const parsed = parser.parse('terminators bar');
|
const parsed = parser.parse('terminators bar');
|
||||||
expect(parsed.meta.terminators).toEqual('bar');
|
expect(parsed.meta.terminators).toEqual('bar');
|
||||||
|
|
|
@ -63,8 +63,24 @@ define([
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeThemes(themes) {
|
||||||
|
if(themes.length === 0) {
|
||||||
|
throw new Error('Cannot render without a theme');
|
||||||
|
}
|
||||||
|
const themeMap = new Map();
|
||||||
|
themes.forEach((theme) => {
|
||||||
|
themeMap.set(theme.name, theme);
|
||||||
|
});
|
||||||
|
themeMap.set('', themes[0]);
|
||||||
|
return themeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
let globalNamespace = 0;
|
||||||
|
|
||||||
return class Renderer {
|
return class Renderer {
|
||||||
constructor(theme, {
|
constructor({
|
||||||
|
themes = [],
|
||||||
|
namespace = null,
|
||||||
components = null,
|
components = null,
|
||||||
SVGTextBlockClass = SVGShapes.TextBlock,
|
SVGTextBlockClass = SVGShapes.TextBlock,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
|
@ -93,11 +109,16 @@ define([
|
||||||
this.state = {};
|
this.state = {};
|
||||||
this.width = 0;
|
this.width = 0;
|
||||||
this.height = 0;
|
this.height = 0;
|
||||||
this.theme = theme;
|
this.themes = makeThemes(themes);
|
||||||
|
this.theme = null;
|
||||||
|
this.namespace = namespace;
|
||||||
|
if(namespace === null) {
|
||||||
|
this.namespace = 'R' + globalNamespace;
|
||||||
|
++ globalNamespace;
|
||||||
|
}
|
||||||
this.components = components;
|
this.components = components;
|
||||||
this.SVGTextBlockClass = SVGTextBlockClass;
|
this.SVGTextBlockClass = SVGTextBlockClass;
|
||||||
this.knownDefs = new Set();
|
this.knownDefs = new Set();
|
||||||
this.currentSequence = null;
|
|
||||||
this.buildStaticElements();
|
this.buildStaticElements();
|
||||||
this.components.forEach((component) => {
|
this.components.forEach((component) => {
|
||||||
component.makeState(this.state);
|
component.makeState(this.state);
|
||||||
|
@ -112,11 +133,13 @@ define([
|
||||||
|
|
||||||
this.defs = svg.make('defs');
|
this.defs = svg.make('defs');
|
||||||
this.mask = svg.make('mask', {
|
this.mask = svg.make('mask', {
|
||||||
'id': 'lineMask',
|
'id': this.namespace + 'LineMask',
|
||||||
'maskUnits': 'userSpaceOnUse',
|
'maskUnits': 'userSpaceOnUse',
|
||||||
});
|
});
|
||||||
this.maskReveal = svg.make('rect', {'fill': '#FFFFFF'});
|
this.maskReveal = svg.make('rect', {'fill': '#FFFFFF'});
|
||||||
this.agentLines = svg.make('g', {'mask': 'url(#lineMask)'});
|
this.agentLines = svg.make('g', {
|
||||||
|
'mask': 'url(#' + this.namespace + 'LineMask)',
|
||||||
|
});
|
||||||
this.blocks = svg.make('g');
|
this.blocks = svg.make('g');
|
||||||
this.sections = svg.make('g');
|
this.sections = svg.make('g');
|
||||||
this.actionShapes = svg.make('g');
|
this.actionShapes = svg.make('g');
|
||||||
|
@ -133,11 +156,15 @@ define([
|
||||||
}
|
}
|
||||||
|
|
||||||
addDef(name, generator) {
|
addDef(name, generator) {
|
||||||
|
const namespacedName = this.namespace + name;
|
||||||
if(this.knownDefs.has(name)) {
|
if(this.knownDefs.has(name)) {
|
||||||
return;
|
return namespacedName;
|
||||||
}
|
}
|
||||||
this.knownDefs.add(name);
|
this.knownDefs.add(name);
|
||||||
this.defs.appendChild(generator());
|
const def = generator();
|
||||||
|
def.setAttribute('id', namespacedName);
|
||||||
|
this.defs.appendChild(def);
|
||||||
|
return namespacedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
addSeparation(agentName1, agentName2, dist) {
|
addSeparation(agentName1, agentName2, dist) {
|
||||||
|
@ -517,16 +544,6 @@ define([
|
||||||
this.height = (y1 - y0);
|
this.height = (y1 - y0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTheme(theme) {
|
|
||||||
if(this.theme === theme) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.theme = theme;
|
|
||||||
if(this.currentSequence) {
|
|
||||||
this.render(this.currentSequence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_reset() {
|
_reset() {
|
||||||
this.knownDefs.clear();
|
this.knownDefs.clear();
|
||||||
svg.empty(this.defs);
|
svg.empty(this.defs);
|
||||||
|
@ -546,6 +563,12 @@ define([
|
||||||
render(sequence) {
|
render(sequence) {
|
||||||
this._reset();
|
this._reset();
|
||||||
|
|
||||||
|
const themeName = sequence.meta.theme;
|
||||||
|
this.theme = this.themes.get(themeName);
|
||||||
|
if(!this.theme) {
|
||||||
|
this.theme = this.themes.get('');
|
||||||
|
}
|
||||||
|
|
||||||
this.title.set({
|
this.title.set({
|
||||||
attrs: this.theme.titleAttrs,
|
attrs: this.theme.titleAttrs,
|
||||||
text: sequence.meta.title,
|
text: sequence.meta.title,
|
||||||
|
@ -564,7 +587,6 @@ define([
|
||||||
|
|
||||||
this.sizer.resetCache();
|
this.sizer.resetCache();
|
||||||
this.sizer.detach();
|
this.sizer.detach();
|
||||||
this.currentSequence = sequence;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getAgentX(name) {
|
getAgentX(name) {
|
||||||
|
|
|
@ -3,14 +3,14 @@ defineDescribe('Sequence Renderer', [
|
||||||
'./themes/Basic',
|
'./themes/Basic',
|
||||||
], (
|
], (
|
||||||
Renderer,
|
Renderer,
|
||||||
Theme
|
BasicTheme
|
||||||
) => {
|
) => {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
let renderer = null;
|
let renderer = null;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
renderer = new Renderer(new Theme());
|
renderer = new Renderer({themes: [new BasicTheme()]});
|
||||||
document.body.appendChild(renderer.svg());
|
document.body.appendChild(renderer.svg());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -155,11 +155,8 @@ define([
|
||||||
render(y, {x, label}, env, isBegin) {
|
render(y, {x, label}, env, isBegin) {
|
||||||
const config = env.theme.agentCap.fade;
|
const config = env.theme.agentCap.fade;
|
||||||
|
|
||||||
const gradID = isBegin ? 'fadeIn' : 'fadeOut';
|
const gradID = env.addDef(isBegin ? 'FadeIn' : 'FadeOut', () => {
|
||||||
|
|
||||||
env.addDef(gradID, () => {
|
|
||||||
const grad = svg.make('linearGradient', {
|
const grad = svg.make('linearGradient', {
|
||||||
'id': gradID,
|
|
||||||
'x1': '0%',
|
'x1': '0%',
|
||||||
'y1': isBegin ? '100%' : '0%',
|
'y1': isBegin ? '100%' : '0%',
|
||||||
'x2': '0%',
|
'x2': '0%',
|
||||||
|
|
|
@ -9,7 +9,7 @@ defineDescribe('Sequence Integration', [
|
||||||
Parser,
|
Parser,
|
||||||
Generator,
|
Generator,
|
||||||
Renderer,
|
Renderer,
|
||||||
Theme,
|
BasicTheme,
|
||||||
SVGTextBlock
|
SVGTextBlock
|
||||||
) => {
|
) => {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -20,10 +20,14 @@ defineDescribe('Sequence Integration', [
|
||||||
let theme = null;
|
let theme = null;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
theme = new Theme();
|
theme = new BasicTheme();
|
||||||
parser = new Parser();
|
parser = new Parser();
|
||||||
generator = new Generator();
|
generator = new Generator();
|
||||||
renderer = new Renderer(theme, {SVGTextBlockClass: SVGTextBlock});
|
renderer = new Renderer({
|
||||||
|
themes: [new BasicTheme()],
|
||||||
|
namespace: '',
|
||||||
|
SVGTextBlockClass: SVGTextBlock,
|
||||||
|
});
|
||||||
document.body.appendChild(renderer.svg());
|
document.body.appendChild(renderer.svg());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -45,12 +49,12 @@ defineDescribe('Sequence Integration', [
|
||||||
expect(getSimplifiedContent(renderer)).toEqual(
|
expect(getSimplifiedContent(renderer)).toEqual(
|
||||||
'<svg width="100%" height="100%" viewBox="-5 -5 10 10">' +
|
'<svg width="100%" height="100%" viewBox="-5 -5 10 10">' +
|
||||||
'<defs>' +
|
'<defs>' +
|
||||||
'<mask id="lineMask" maskUnits="userSpaceOnUse">' +
|
'<mask id="LineMask" maskUnits="userSpaceOnUse">' +
|
||||||
'<rect fill="#FFFFFF" x="-5" y="-5" width="10" height="10">' +
|
'<rect fill="#FFFFFF" x="-5" y="-5" width="10" height="10">' +
|
||||||
'</rect>' +
|
'</rect>' +
|
||||||
'</mask>' +
|
'</mask>' +
|
||||||
'</defs>' +
|
'</defs>' +
|
||||||
'<g mask="url(#lineMask)"></g>' +
|
'<g mask="url(#LineMask)"></g>' +
|
||||||
'</svg>'
|
'</svg>'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -63,12 +67,12 @@ defineDescribe('Sequence Integration', [
|
||||||
expect(getSimplifiedContent(renderer)).toEqual(
|
expect(getSimplifiedContent(renderer)).toEqual(
|
||||||
'<svg width="100%" height="100%" viewBox="-11.5 -16 23 21">' +
|
'<svg width="100%" height="100%" viewBox="-11.5 -16 23 21">' +
|
||||||
'<defs>' +
|
'<defs>' +
|
||||||
'<mask id="lineMask" maskUnits="userSpaceOnUse">' +
|
'<mask id="LineMask" maskUnits="userSpaceOnUse">' +
|
||||||
'<rect fill="#FFFFFF" x="-11.5" y="-16" width="23" height="21">' +
|
'<rect fill="#FFFFFF" x="-11.5" y="-16" width="23" height="21">' +
|
||||||
'</rect>' +
|
'</rect>' +
|
||||||
'</mask>' +
|
'</mask>' +
|
||||||
'</defs>' +
|
'</defs>' +
|
||||||
'<g mask="url(#lineMask)"></g>' +
|
'<g mask="url(#LineMask)"></g>' +
|
||||||
'<text' +
|
'<text' +
|
||||||
' x="0"' +
|
' x="0"' +
|
||||||
' font-family="sans-serif"' +
|
' font-family="sans-serif"' +
|
||||||
|
|
|
@ -235,8 +235,9 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return class Theme {
|
return class BasicTheme {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.name = 'basic';
|
||||||
Object.assign(this, SETTINGS);
|
Object.assign(this, SETTINGS);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
defineDescribe('Basic Theme', ['./Basic'], (Theme) => {
|
defineDescribe('Basic Theme', ['./Basic'], (BasicTheme) => {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const theme = new BasicTheme();
|
||||||
|
|
||||||
|
it('has a name', () => {
|
||||||
|
expect(theme.name).toEqual('basic');
|
||||||
|
});
|
||||||
|
|
||||||
it('contains settings for the theme', () => {
|
it('contains settings for the theme', () => {
|
||||||
const theme = new Theme();
|
|
||||||
expect(theme.outerMargin).toEqual(5);
|
expect(theme.outerMargin).toEqual(5);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,247 @@
|
||||||
|
define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const LINE_HEIGHT = 1.3;
|
||||||
|
|
||||||
|
const SETTINGS = {
|
||||||
|
titleMargin: 10,
|
||||||
|
outerMargin: 5,
|
||||||
|
agentMargin: 8,
|
||||||
|
actionMargin: 5,
|
||||||
|
agentLineHighlightRadius: 4,
|
||||||
|
|
||||||
|
agentCap: {
|
||||||
|
box: {
|
||||||
|
padding: {
|
||||||
|
top: 1,
|
||||||
|
left: 3,
|
||||||
|
right: 3,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
|
arrowBottom: 2 + 14 * 1.3 / 2,
|
||||||
|
boxAttrs: {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'rx': 4,
|
||||||
|
'ry': 4,
|
||||||
|
},
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-weight': 'bold',
|
||||||
|
'font-size': 14,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cross: {
|
||||||
|
size: 20,
|
||||||
|
attrs: {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bar: {
|
||||||
|
attrs: {
|
||||||
|
'fill': '#000000',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'height': 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fade: {
|
||||||
|
width: 5,
|
||||||
|
height: 10,
|
||||||
|
},
|
||||||
|
none: {
|
||||||
|
height: 10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
connect: {
|
||||||
|
loopbackRadius: 6,
|
||||||
|
lineAttrs: {
|
||||||
|
'solid': {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
},
|
||||||
|
'dash': {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'stroke-dasharray': '4, 2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
arrow: {
|
||||||
|
width: 10,
|
||||||
|
height: 12,
|
||||||
|
attrs: {
|
||||||
|
'fill': '#000000',
|
||||||
|
'stroke-width': 0,
|
||||||
|
'stroke-linejoin': 'miter',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
padding: 6,
|
||||||
|
margin: {top: 2, bottom: 1},
|
||||||
|
attrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-size': 8,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
loopbackAttrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-size': 8,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mask: {
|
||||||
|
padding: {
|
||||||
|
top: 0,
|
||||||
|
left: 3,
|
||||||
|
right: 3,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
block: {
|
||||||
|
margin: {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
boxAttrs: {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1.5,
|
||||||
|
'rx': 2,
|
||||||
|
'ry': 2,
|
||||||
|
},
|
||||||
|
section: {
|
||||||
|
padding: {
|
||||||
|
top: 3,
|
||||||
|
bottom: 2,
|
||||||
|
},
|
||||||
|
mode: {
|
||||||
|
padding: {
|
||||||
|
top: 1,
|
||||||
|
left: 3,
|
||||||
|
right: 3,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
boxAttrs: {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'rx': 2,
|
||||||
|
'ry': 2,
|
||||||
|
},
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-weight': 'bold',
|
||||||
|
'font-size': 9,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
padding: {
|
||||||
|
top: 1,
|
||||||
|
left: 5,
|
||||||
|
right: 3,
|
||||||
|
bottom: 0,
|
||||||
|
},
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-size': 8,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'left',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
attrs: {
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1.5,
|
||||||
|
'stroke-dasharray': '4, 2',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
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': {
|
||||||
|
margin: {top: 0, left: 5, right: 5, bottom: 0},
|
||||||
|
padding: {top: 5, left: 5, right: 10, bottom: 5},
|
||||||
|
overlap: {left: 10, right: 10},
|
||||||
|
boxRenderer: SVGShapes.renderNote.bind(null, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}, {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-size': 8,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'state': {
|
||||||
|
margin: {top: 0, left: 5, right: 5, bottom: 0},
|
||||||
|
padding: {top: 7, left: 7, right: 7, bottom: 7},
|
||||||
|
overlap: {left: 10, right: 10},
|
||||||
|
boxRenderer: SVGShapes.renderBox.bind(null, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
'rx': 10,
|
||||||
|
'ry': 10,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-size': 8,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
titleAttrs: {
|
||||||
|
'font-family': 'sans-serif',
|
||||||
|
'font-size': 20,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
'class': 'title',
|
||||||
|
},
|
||||||
|
|
||||||
|
agentLineAttrs: {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return class ChunkyTheme {
|
||||||
|
constructor() {
|
||||||
|
this.name = 'chunky';
|
||||||
|
Object.assign(this, SETTINGS);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
defineDescribe('Chunky Theme', ['./Chunky'], (ChunkyTheme) => {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const theme = new ChunkyTheme();
|
||||||
|
|
||||||
|
it('has a name', () => {
|
||||||
|
expect(theme.name).toEqual('chunky');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains settings for the theme', () => {
|
||||||
|
expect(theme.outerMargin).toEqual(5);
|
||||||
|
});
|
||||||
|
});
|
|
@ -9,6 +9,7 @@ define([
|
||||||
'sequence/Generator_spec',
|
'sequence/Generator_spec',
|
||||||
'sequence/Renderer_spec',
|
'sequence/Renderer_spec',
|
||||||
'sequence/themes/Basic_spec',
|
'sequence/themes/Basic_spec',
|
||||||
|
'sequence/themes/Chunky_spec',
|
||||||
'sequence/components/AgentCap_spec',
|
'sequence/components/AgentCap_spec',
|
||||||
'sequence/components/AgentHighlight_spec',
|
'sequence/components/AgentHighlight_spec',
|
||||||
'sequence/components/Connect_spec',
|
'sequence/components/Connect_spec',
|
||||||
|
|
Loading…
Reference in New Issue