graphviz: record node with a bold title
I'm trying to use graphviz to do something similar to UML class diagrams.
I wonder whether there is a way to make a node of style 'register' have its first field i开发者_如何学运维n a bold font, to make it different from the other fields.
My node looks like this:
digraph i {
"node" [
label = "<f0> title | <f1> index | ... | <f2> field1 | <f3> field2"
shape = "record"
];
}
I tried this but it doesn't work: (embedding html)
digraph i {
"node" [
label = "<f0> <B>title</B> | <f1> index | ... | <f2> field1 | <f3> field2"
shape = "record"
];
}
I don't believe record-based nodes allow HTML formatting in them. The node shape documentation suggests that record-based nodes have been deprecated in favor of using a none-shaped node with an HTML-like label, which is much more flexible with formatting. These labels are surrounded with <> instead of double quotes.
I haven't been able to test this, but this is close to what you want:
digraph i {
"node" [
label =<<TABLE BORDER="1" CELLBORDER="1" CELLSPACING="0">
<TR><TD PORT="f0"><B>title</B></TD></TR>
<TR><TD PORT="f1">index</TD></TR>
<TR><TD PORT="f2">field1</TD></TR>
<TR><TD PORT="f3">field2</TD></TR>
</TABLE>>
shape = "none"
];
}
Output:
Answering the UML use case more broadly, there is now an official UML example at: https://graphviz.org/Gallery/directed/UML_Class_diagram.html Like https://stackoverflow.com/a/6177064/895245 it uses <b>
to make the titles bold:
digraph UML_Class_diagram {
graph [
label="UML Class diagram demo"
labelloc="t"
fontname="Helvetica,Arial,sans-serif"
]
node [
fontname="Helvetica,Arial,sans-serif"
shape=record
style=filled
fillcolor=gray95
]
edge [fontname="Helvetica,Arial,sans-serif"]
edge [arrowhead=vee style=dashed]
Client -> Interface1 [label=dependency]
Client -> Interface2
edge [dir=back arrowtail=empty style=""]
Interface1 -> Class1 [xlabel=inheritance]
Interface2 -> Class1 [dir=none]
Interface2 [label="" xlabel="Simple\ninterface" shape=circle]
Interface1[label = <{<b>«interface» I/O</b> | + property<br align="left"/>...<br align="left"/>|+ method<br align="left"/>...<br align="left"/>}>]
Class1[label = <{<b>I/O class</b> | + property<br align="left"/>...<br align="left"/>|+ method<br align="left"/>...<br align="left"/>}>]
edge [dir=back arrowtail=empty style=dashed]
Class1 -> System_1 [label=implementation]
System_1 [
shape=plain
label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr> <td> <b>System</b> </td> </tr>
<tr> <td>
<table border="0" cellborder="0" cellspacing="0" >
<tr> <td align="left" >+ property</td> </tr>
<tr> <td port="ss1" align="left" >- Subsystem 1</td> </tr>
<tr> <td port="ss2" align="left" >- Subsystem 2</td> </tr>
<tr> <td port="ss3" align="left" >- Subsystem 3</td> </tr>
<tr> <td align="left">...</td> </tr>
</table>
</td> </tr>
<tr> <td align="left">+ method<br/>...<br align="left"/></td> </tr>
</table>>
]
edge [dir=back arrowtail=diamond]
System_1:ss1 -> Subsystem_1 [xlabel="composition"]
Subsystem_1 [
shape=plain
label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr> <td> <b>Subsystem 1</b> </td> </tr>
<tr> <td>
<table border="0" cellborder="0" cellspacing="0" >
<tr> <td align="left">+ property</td> </tr>
<tr> <td align="left" port="r1">- resource</td> </tr>
<tr> <td align="left">...</td> </tr>
</table>
</td> </tr>
<tr> <td align="left">
+ method<br/>
...<br align="left"/>
</td> </tr>
</table>>
]
Subsystem_2 [
shape=plain
label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr> <td> <b>Subsystem 2</b> </td> </tr>
<tr> <td>
<table align="left" border="0" cellborder="0" cellspacing="0" >
<tr> <td align="left">+ property</td> </tr>
<tr> <td align="left" port="r1">- resource</td> </tr>
<tr> <td align="left">...</td> </tr>
</table>
</td> </tr>
<tr> <td align="left">
+ method<br/>
...<br align="left"/>
</td> </tr>
</table>>
]
Subsystem_3 [
shape=plain
label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr> <td> <b>Subsystem 3</b> </td> </tr>
<tr> <td>
<table border="0" cellborder="0" cellspacing="0" >
<tr> <td align="left">+ property</td> </tr>
<tr> <td align="left" port="r1">- resource</td> </tr>
<tr> <td align="left">...</td> </tr>
</table>
</td> </tr>
<tr> <td align="left">
+ method<br/>
...<br align="left"/>
</td> </tr>
</table>>
]
System_1:ss2 -> Subsystem_2;
System_1:ss3 -> Subsystem_3;
edge [xdir=back arrowtail=odiamond]
Subsystem_1:r1 -> "Shared resource" [label=aggregation]
Subsystem_2:r1 -> "Shared resource"
Subsystem_3:r1 -> "Shared resource"
"Shared resource" [
label = <{
<b>Shared resource</b>
|
+ property<br align="left"/>
...<br align="left"/>
|
+ method<br align="left"/>
...<br align="left"/>
}>
]
}
The HTML approach is however way too verbose for casually creating UML diagrams without extra tooling, as it requires too much formatting repetition.
A lightweight "poor man's approach" that still more clearly highlights node title than records could be to use subgraphs:
digraph {
node [shape=box]
subgraph cluster_house {
label="House"
hcw [label="Clean water"]
hdw [label="Dirty water"]
}
subgraph cluster_street {
label="Street"
scw [label="Clean water"]
sdw [label="Dirty water"]
}
scw -> hcw
hdw -> sdw
}
Docs: https://graphviz.org/docs/attrs/cluster/
Tested on Graphviz 2.42.2, Ubuntu 22.04.
精彩评论