Skip to content

Commit

Permalink
<table> classifier type for presenting tabular data
Browse files Browse the repository at this point in the history
  • Loading branch information
skanaar committed Aug 28, 2020
1 parent 5961a80 commit dfff18e
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 6 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ This is how the Decorator pattern looks like in nomnoml syntax:
[<usecase> name]
[<label> name]
[<hidden> name]
[<table> name| a | 5 || b | 7]

### Directives

Expand Down Expand Up @@ -177,6 +178,7 @@ Available key/value pairs are
visual=roundrect
visual=sender
visual=start
visual=table
visual=transceiver

Available modifiers are
Expand Down
63 changes: 60 additions & 3 deletions dist/nomnoml.js
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,9 @@ var nomnoml;
if (font.indexOf('bold') === -1) {
attr.style += 'font-weight:normal;';
}
else {
attr.style += 'font-weight:bold;';
}
if (font.indexOf('italic') > -1) {
attr.style += 'font-style:italic;';
}
Expand Down Expand Up @@ -1130,6 +1133,7 @@ var nomnoml;
SENDER: nomnoml.buildStyle({ visual: 'sender' }),
START: nomnoml.buildStyle({ visual: 'start', center: true, empty: true }),
STATE: nomnoml.buildStyle({ visual: 'roundrect', center: true }),
TABLE: nomnoml.buildStyle({ visual: 'table', center: true, bold: true }),
TRANSCEIVER: nomnoml.buildStyle({ visual: 'transceiver' }),
USECASE: nomnoml.buildStyle({ visual: 'ellipse', center: true })
};
Expand Down Expand Up @@ -1171,7 +1175,7 @@ var nomnoml;
}
},
"class": box,
database: function box(config, clas) {
database: function (config, clas) {
clas.width = Math.max.apply(Math, clas.compartments.map(function (e) { return e.width; }));
clas.height = nomnoml.skanaar.sum(clas.compartments, 'height') + config.padding * 2;
clas.dividers = [];
Expand All @@ -1186,7 +1190,7 @@ var nomnoml;
clas.dividers.push([{ x: 0, y: y }, { x: clas.width, y: y }]);
}
},
ellipse: function box(config, clas) {
ellipse: function (config, clas) {
var width = Math.max.apply(Math, clas.compartments.map(function (e) { return e.width; }));
var height = nomnoml.skanaar.sum(clas.compartments, 'height');
clas.width = width * 1.25;
Expand Down Expand Up @@ -1233,7 +1237,7 @@ var nomnoml;
note: box,
package: box,
receiver: box,
rhomb: function box(config, clas) {
rhomb: function (config, clas) {
var width = Math.max.apply(Math, clas.compartments.map(function (e) { return e.width; }));
var height = nomnoml.skanaar.sum(clas.compartments, 'height');
clas.width = width * 1.5;
Expand All @@ -1257,6 +1261,56 @@ var nomnoml;
roundrect: box,
sender: box,
start: icon,
table: function (config, clas) {
if (clas.compartments.length == 1) {
box(config, clas);
return;
}
var gridcells = clas.compartments.slice(1);
var rows = [[]];
function isRowBreak(e) {
return !e.lines.length && !e.nodes.length && !e.relations.length;
}
function isRowFull(e) {
var current = nomnoml.skanaar.last(rows);
return rows[0] != current && rows[0].length == current.length;
}
function isEnd(e) {
return comp == nomnoml.skanaar.last(gridcells);
}
for (var _i = 0, gridcells_1 = gridcells; _i < gridcells_1.length; _i++) {
var comp = gridcells_1[_i];
if (!isEnd(comp) && isRowBreak(comp)) {
rows.push([]);
}
else if (isRowFull(comp)) {
rows.push([comp]);
}
else {
nomnoml.skanaar.last(rows).push(comp);
}
}
var header = clas.compartments[0];
var cellW = Math.max.apply(Math, __spreadArrays([header.width / rows[0].length], gridcells.map(function (e) { return e.width; })));
var cellH = Math.max.apply(Math, gridcells.map(function (e) { return e.height; }));
clas.width = cellW * rows[0].length;
clas.height = header.height + cellH * rows.length;
var hh = header.height;
clas.dividers = __spreadArrays([
[{ x: 0, y: header.height }, { x: 0, y: header.height }]
], rows.map(function (e, i) { return [{ x: 0, y: hh + i * cellH }, { x: clas.width, y: hh + i * cellH }]; }), rows[0].map(function (e, i) { return [{ x: (i + 1) * cellW, y: hh }, { x: (i + 1) * cellW, y: clas.height }]; }));
header.x = 0;
header.y = 0;
header.width = clas.width;
for (var i = 0; i < rows.length; i++) {
for (var j = 0; j < rows[i].length; j++) {
var cell = rows[i][j];
cell.x = j * cellW;
cell.y = hh + i * cellH;
cell.width = cellW;
}
}
},
transceiver: box
};
nomnoml.visualizers = {
Expand Down Expand Up @@ -1371,6 +1425,9 @@ var nomnoml;
g.fillStyle(config.stroke);
g.circle({ x: node.x, y: y + node.height / 2 }, node.height / 2.5).fill();
},
table: function (node, x, y, config, g) {
g.rect(x, y, node.width, node.height).fillAndStroke();
},
transceiver: function (node, x, y, config, g) {
g.circuit([
{ x: x - config.padding, y: y },
Expand Down
8 changes: 8 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ <h2>Classifier types</h2>
[&lt;usecase&gt; name]<br>
[&lt;label&gt; name]<br>
[&lt;hidden&gt; name]<br>
[&lt;table&gt; name| a|5 || b|7]<br>

<h2>Directives</h2>
#arrowSize: 1<br>
Expand Down Expand Up @@ -118,6 +119,7 @@ <h3>Available key/value pairs are</h3>
visual=roundrect<br>
visual=sender<br>
visual=start<br>
visual=table<br>
visual=transceiver

<h3>Available modifiers are</h3>
Expand Down Expand Up @@ -233,6 +235,12 @@ <h3>Layout the diagram really tight</h3>
#spacing: 12
#padding: 3</pre>

<h3>Tables</h3>
<pre>[&lt;table&gt;Fruits|
Apples | 17 ||
Oranges | 4711
]</pre>

<h3>Create your own styles</h3>
<pre>#.box: fill=#8f8 dashed
[&lt;box&gt; GreenBox]</pre>
Expand Down
1 change: 1 addition & 0 deletions src/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Visual =
'roundrect'|
'sender'|
'start'|
'table'|
'transceiver'

interface Style {
Expand Down
59 changes: 56 additions & 3 deletions src/visuals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace nomnoml {
SENDER: buildStyle({ visual:'sender' }),
START: buildStyle({ visual:'start', center:true, empty:true }),
STATE: buildStyle({ visual:'roundrect', center:true }),
TABLE: buildStyle({ visual:'table', center:true, bold:true }),
TRANSCEIVER: buildStyle({ visual:'transceiver' }),
USECASE: buildStyle({ visual:'ellipse', center:true }),
}
Expand Down Expand Up @@ -60,7 +61,7 @@ namespace nomnoml {
}
},
class: box,
database: function box(config: Config, clas: Classifier) {
database: function (config: Config, clas: Classifier) {
clas.width = Math.max(...clas.compartments.map(e => e.width))
clas.height = skanaar.sum(clas.compartments, 'height') + config.padding*2
clas.dividers = []
Expand All @@ -74,7 +75,7 @@ namespace nomnoml {
clas.dividers.push([{ x: 0, y: y }, { x: clas.width, y: y }])
}
},
ellipse: function box(config: Config, clas: Classifier) {
ellipse: function (config: Config, clas: Classifier) {
var width = Math.max(...clas.compartments.map(e => e.width))
var height = skanaar.sum(clas.compartments, 'height')
clas.width = width * 1.25
Expand Down Expand Up @@ -119,7 +120,7 @@ namespace nomnoml {
note: box,
package: box,
receiver: box,
rhomb: function box(config: Config, clas: Classifier) {
rhomb: function (config: Config, clas: Classifier) {
var width = Math.max(...clas.compartments.map(e => e.width))
var height = skanaar.sum(clas.compartments, 'height')
clas.width = width * 1.5
Expand All @@ -142,6 +143,55 @@ namespace nomnoml {
roundrect: box,
sender: box,
start: icon,
table: function (config: Config, clas: Classifier) {
if (clas.compartments.length == 1) {
box(config, clas)
return
}
var gridcells = clas.compartments.slice(1)
var rows: Compartment[][] = [[]]
function isRowBreak(e: Compartment): boolean {
return !e.lines.length && !e.nodes.length && !e.relations.length
}
function isRowFull(e: Compartment): boolean {
var current = skanaar.last(rows)
return rows[0] != current && rows[0].length == current.length
}
function isEnd(e: Compartment): boolean {
return comp == skanaar.last(gridcells)
}
for (var comp of gridcells) {
if (!isEnd(comp) && isRowBreak(comp)) {
rows.push([])
} else if (isRowFull(comp)) {
rows.push([comp])
} else {
skanaar.last(rows).push(comp)
}
}
var header = clas.compartments[0]
var cellW = Math.max(header.width/rows[0].length, ...gridcells.map(e => e.width))
var cellH = Math.max(...gridcells.map(e => e.height))
clas.width = cellW * rows[0].length
clas.height = header.height + cellH * rows.length
var hh = header.height
clas.dividers = [
[{ x: 0, y: header.height }, { x: 0, y: header.height }],
...rows.map((e,i) => [{ x: 0, y: hh+i*cellH }, { x: clas.width, y: hh+i*cellH }]),
...rows[0].map((e,i) => [{ x: (i+1)*cellW, y: hh }, { x: (i+1)*cellW, y: clas.height }]),
]
header.x = 0
header.y = 0
header.width = clas.width
for(var i=0; i<rows.length; i++) {
for(var j=0; j<rows[i].length; j++) {
var cell = rows[i][j]
cell.x = j * cellW
cell.y = hh + i * cellH
cell.width = cellW
}
}
},
transceiver: box,
}

Expand Down Expand Up @@ -256,6 +306,9 @@ namespace nomnoml {
g.fillStyle(config.stroke)
g.circle({ x:node.x, y:y+node.height/2 }, node.height/2.5).fill()
},
table : function (node, x, y, config, g) {
g.rect(x, y, node.width, node.height).fillAndStroke()
},
transceiver : function (node, x, y, config, g) {
g.circuit([
{x: x-config.padding, y: y},
Expand Down
18 changes: 18 additions & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,24 @@ <h1>Built in styles</h1>
</div>
</div>

<div class=testcase>
<h1>Table</h1>
<div nomnoml=canvas>
<script type="text/vnd.nomnoml">
[<table> Long table title|
nuts | 89 ||
bolts | 18
]

[<table> shapes|
number | 5 ||
capsule | [<state>cell] |
auto;row;break
]
</script>
</div>
</div>

<div class=testcase>
<h1>Non-boxy shapes</h1>
<div nomnoml=canvas>
Expand Down

0 comments on commit dfff18e

Please sign in to comment.