Way to center a node in a table

In the following example I am trying to add a caption above my “actual” node, which I have been doing by putting them both into rows of a table. When the caption is shorter than the node contents it is fine, but when the caption is larger, then the spacing in the table causes the node to be uncentered with respect to the caption

[dot verbose=true]

digraph {
    test [label=<
    <TABLE BORDER="0">
      <TR>
        <TD COLSPAN="3">This is a really long caption</TD>
      </TR>
      <TR>
        <TD></TD>
        <TD BORDER="1">Node</TD>
        <TD></TD>
      </TR>
    </TABLE>
>,style="invisible"];}

[/dot]

I tried playing around with the order of the cells to understand what was going on and it seems that the first cell in the row is assigned any extra width:

[dot verbose=true]

digraph {
    test [label=<
    <TABLE>
      <TR>
        <TD COLSPAN="3">This is a really long caption</TD>
      </TR>
      <TR>
        <TD>Node</TD>
        <TD></TD>
        <TD></TD>
      </TR>
    </TABLE>
>,style="invisible"];}

[/dot]

[dot verbose=true]

digraph {
    test [label=<
    <TABLE>
      <TR>
        <TD COLSPAN="3">This is a really long caption</TD>
      </TR>
      <TR>
        <TD></TD>
        <TD>Node</TD>
        <TD></TD>
      </TR>
    </TABLE>
>,style="invisible"];}

[/dot]

[dot verbose=true]

digraph {
    test [label=<
    <TABLE>
      <TR>
        <TD COLSPAN="3">This is a really long caption</TD>
      </TR>
      <TR>
        <TD></TD>
        <TD></TD>
        <TD>Node</TD>
      </TR>
    </TABLE>
>,style="invisible"];}

[/dot]

Ideally I would have the empty cells on the left and right grow to take up any extra space, and have the central cell just large enough to fix the contents. Is there any way to have this happen automatically, or a better way to achieve my desired end result of having the node and caption aligned together?

Thanks!

1 Like

Curious. I can’t find a way to make the HTML record behave, but here is an alternative (use clusters instead):
digraph {
subgraph clusterTest {
peripheries=0 // no box surrounding the cluster
labelloc=t
label=“This is a really long caption”
n[label=“node” shape=rectangle]
}
}
Giving:
longExternal3

1 Like

Thanks @steveroush!

My actual example is a bit more involved, where I want to have captions above and below the box, so something like

[dot]

digraph {
    test [label=<
    <TABLE BORDER="0">
      <TR>
        <TD COLSPAN="3">This is a really long caption</TD>
      </TR>
      <TR>
        <TD></TD>
        <TD BORDER="1">Node</TD>
        <TD></TD>
      </TR>
      <TR>
        <TD COLSPAN="3">Bottom caption</TD>
      </TR>
    </TABLE>
>,style="invisible"];}

[/dot]

Any suggestions on how to get this to work?

1 Like

Kludge on top of kludge, but legal & seems to look OK. Embed one cluster inside another, then set margin=0 to tighten things up:

digraph {
subgraph clusterLower {
peripheries=0 // no box surrounding the cluster
labelloc=b
margin=0 // reduce distance from node to upper/lower label
label=“This is a lower long caption”

subgraph clusterUpper {
peripheries=0 // no box surrounding the cluster
labelloc=t
margin=0 // reduce distance from node to upper/lower label
label=“This is a really long upper caption”
n[label=“node” shape=rectangle]
}
}
}
Gives:
longExternal3

1 Like

Perfect I will give it a shot, thanks so much @steveroush!

1 Like

I tried this out with multiple nodes of this type, and it seems that the nodes are free to slide within the clusters:

[dot verbose=true]

digraph {
  compound=true;
  subgraph clusterLower {
    peripheries=0 // no box surrounding the cluster
    labelloc=b
    margin=0 // reduce distance from node to upper/lower label
    label="This is a lower long caption"

    subgraph clusterUpper {
      peripheries=0 // no box surrounding the cluster
      labelloc=t
      margin=0 // reduce distance from node to upper/lower label
      label="This is a really long upper caption"
      n[label="node" shape=rectangle]
    }
  }

  subgraph clusterLower2 {
    peripheries=0 // no box surrounding the cluster
    labelloc=b
    margin=0 // reduce distance from node to upper/lower label
    label="This is a lower long caption"

    subgraph clusterUpper2 {
      peripheries=0 // no box surrounding the cluster
      labelloc=t
      margin=0 // reduce distance from node to upper/lower label
      label="This is a really long upper caption"
      n2[label="node" shape=rectangle]
    }
  }

  subgraph clusterLower3 {
    peripheries=0 // no box surrounding the cluster
    labelloc=b
    margin=0 // reduce distance from node to upper/lower label
    label="This is a lower long caption"

    subgraph clusterUpper3 {
      peripheries=0 // no box surrounding the cluster
      labelloc=t
      margin=0 // reduce distance from node to upper/lower label
      label="This is a really long upper caption"
      n3[label="node" shape=rectangle]
    }
  }

  n -> n2;
  n -> n3;
}

[/dot]

Is there a way to prevent this from happening and lock them in place in the center?

Thanks so much again for all the help!

1 Like

The documentation is (slightly) ambiguous regarding whether you can set separate X & Y values for a cluster margin (e.g. margin=“20,0”). That would probably solve the problem.
Unfortunately, clusters only take one value for both X & Y. (Rats)
So, we combine html & clusters into a mondo kludge:

digraph {
graph [splines=false]  // if you want straight lines & not curves
compound=true;
subgraph clusterLower {
peripheries=0 // no box surrounding the cluster
labelloc=b
margin="0,0" // reduce distance from node to upper/lower label
label="This is a lower long caption"

subgraph clusterUpper {
  peripheries=0 // no box surrounding the cluster
  labelloc=t
  margin="0,0" // reduce distance from node to upper/lower label
  label="This is a really long upper caption"
  //n[label="node" shape=rectangle]
    N1 [label=<
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
  <TR>
<TD BORDER="0">                 </TD>
    <TD BORDER="1" PORT="n1" CELLPADDING="4">Node</TD>
<TD BORDER="0">              </TD>
  </TR>
</TABLE>>,style="invisible"];
 }
}

subgraph clusterLower2 {
//graph [margin="2,40"] // reduce distance from node to upper/lower label
margin=0
peripheries=0 // no box surrounding the cluster
labelloc=b

label="This is a lower long caption"

subgraph clusterUpper2 {
  //peripheries=0 // no box surrounding the cluster
  labelloc=t
  label="This is a really long upper caption"
  //n2[label="node" shape=rectangle]

 N2 [label=<
  <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
   <TR>
      <TD BORDER="1" PORT="n2" CELLPADDING="4">Node</TD>
  <TD BORDER="0">              </TD>
    </TR>
  </TABLE>>,style="invisible"];
  }
}

subgraph clusterLower3 {
  peripheries=0 // no box surrounding the cluster
  labelloc=b
  margin=0 // reduce distance from node to upper/lower label
  label="This is a lower long caption"

  subgraph clusterUpper3 {
    peripheries=0 // no box surrounding the cluster
    labelloc=t
    margin=0 // reduce distance from node to upper/lower label
    label="This is a really long upper caption"
    //n3[label="node" shape=rectangle]
    N3 [label=<
 <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
  <TR>
<TD BORDER="0">              </TD>
    <TD BORDER="1" PORT="n3" CELLPADDING="4">Node</TD>
  </TR>
 </TABLE>>,style="invisible"];
 }
}

N1:n1:s -> N2:n2;
N1:n1:s -> N3:n3;
}

Giving:

I’m not happy with it, but it (maybe, kinda) works. I’ll ponder some more.

1 Like