graphviz: record node with a bold title
Asked Answered
E

2

15

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 in 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"
  ];  
}
Erwin answered 30/5, 2011 at 0:28 Comment(0)
L
19

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:

enter image description here

Loony answered 30/5, 2011 at 13:41 Comment(3)
This results in a picture showing only the word "node" for me. Only after removing the <B> and </B> a table is shown.Dunne
@Dunne Your version of Graphviz might not support <B> yet. See the notes in the manual NOTE:The font markups for bold, italic, underlining, subscript and superscript (<B>, <I>, <U>, <SUB> and <SUP>) are only available in versions after 14 October 2011, and the markup for strike-through (<S>) requires versions later than 15 September 2013.Fokos
Also i'd recommend BORDER="1", or else the outer border becomes thicker.Greenwood
G
1

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://mcmap.net/q/776898/-graphviz-record-node-with-a-bold-title 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"/>
            }>
    ]
}

enter image description here

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
}

enter image description here

Docs: https://graphviz.org/docs/attrs/cluster/

Tested on Graphviz 2.42.2, Ubuntu 22.04.

Greenwood answered 14/12, 2022 at 9:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.