How to tell dot to put the edge label in a box?

In one graph I have longer edge label (conditions of state change). I would like to put these edge labels in a box and keep their position roughly where edge labels normally are drawn. How can I do this?

Example: In a simple graph like this

digraph finite_state_machine {
    rankdir=LR
    {
	    node [shape=record,style=rounded]
        A B
    }
    A -> B [label=<This should <br/>be in a box>]
}

basic-for-boxed-label

Here I would like to put the edge label text “This should be in a box” in a box. Is there a “label style” for this?

1 Like

Great question, unfortunately I don’t think there is any simple way to do this. If you look at the styles page (style | Graphviz), you’ll note there are no label styles.
I guess the expectation was that text formatting was all that was needed.

However, below is a small gvpr program that seems to do what you want. It post-processes your result (in dot output format - DOT | Graphviz) and replaces the label with a node that contains the label.
You have to add a new attribute boxit=1 to all appropriate edges. Like so:

digraph finite_state_machine {
    rankdir=LR
    {
	    node [shape=record,style=rounded]
        A B
    }
    A -> B [label=<This should <br/>be in a box>  boxit=1]
}

and this gvpr program, named boxIt.gvpr:

BEG_G{
 string tmpS, newName="___NewNode_";
 int I=0;
 node_t aNode;
}
E{
  if (hasAttr($,"boxit") && $.boxit=="1"){
    I++;
    tmpS=newName+(string)I;
    aNode=node($G,tmpS);
    // whoops, we need to slide thex text "up" a little bit
    //aNode.pos=$.lp;
    aNode.pos=xOf($.lp) + "," + (string) (7. + (float)yOf($.lp));
    aNode.label=$.label;
    aNode.shape="rect";
    aNode.margin=".04,.0";    
    $.label="";
    $.lp="";
  }
}

and then use this command line:
dot myFile.gv |gvpr -cf boxIt.gvpr |neato -n2 -Tpng > myFile.png
Giving:
boxMyLabel1

This scheme is not industrial-strength, but seems to work.

p.s. You might request boxed labels as an enhancement here: Issues · graphviz / graphviz · GitLab

1 Like

Maybe this is a silly suggestion, but why not just use a degenerate table:

digraph finite_state_machine {
    rankdir=LR
    {
            node [shape=record,style=rounded]
        A B
    }
    A -> B [label=<<table border="0"><tr><td border="1">This should <br/>be in a box</td></tr></table>>]
}

blah.dot

3 Likes

Silly in a very useful way. Neat.

Hey, that’s super cool, @smattr ! Great way to think about it outside the box! Will try it out.

Wow, gvpr seems to be very powerful!

It might be very obvious toanswer, but I don’t undertsand why do you pipe the resulting gv stream to neato -Tpng and not to dot -Tpng?


ps: I followed you suggestion and submitted for this a feature request. Maybe somebody thinks this could be fun to implement - may be not. (It might not fit into the way Graphviz internally works…)

gvpr is quite powerful. [note that you could probably do the same using the Python interface to Graphviz - or other language interfaces]
The result is piped into neato -n (or neato -n2) because dot will ignore any pos (positioning X,Y) values and will completely re-layout the graph. Neato will accept the pos values & use accordingly (FAQ | Graphviz)

1 Like

Hi again, I wanted to follow up on this topic. I have generated a small “real world” state diagram with the different methods discussed. I wanted to share their output and visually compare them here. – Maybe someone is interested in this. The diagrams show always the same states and transitions.

Diagrams

First the state diagram with plain labels on the transitions:

 

Then the state diagram with (HTML-table) boxed labels on the transitions:

 

Additionally here the state diagram with “decorated” labels on the transitions (see decorate | Graphviz):

 

And finally the state diagram with the transition text in their own (differently styled) nodes:

 


Discussion

I think I will go with the last version (transition text as nodes), despite the fact that in this version nodes are not anymore only for states reserved. IMHO it is still a bit cleaner than the other options.

Runner up is the first version (plain label style) which, I guess, Graphviz itself suggests. The other two versions appear to me to busy and distracting.

1 Like
  • not a fan of the decorated labels
  • for labels within their own nodes, I’d suggest dir=none on the in-bound edge
  • I think I remember a request to support edge label text on-top-of the edge (similar to option 4), but I can’t find the request
1 Like

Agreed. Updated.