digraph TestAccountLoadSequence { { // Make sure they're on the same row rank=same; // Style the actor nodes node [shape=box]; actor1_top [label="TestAddAccount"]; actor2_top [label="AccomondationManager"]; actor3_top [label="AccountList"]; // Tie them together in the right order edge [style = invis]; actor1_top -> actor2_top -> actor3_top; } // Define the actor nodes in the bottom. This is a copy paste //of the top subgraph - s/top/bottom/g { rank=same; node [shape=box]; actor1_bottom [label="TestAddAccount"]; actor2_bottom [label="AccomondationManager"]; actor3_bottom [label="AccountList"]; edge [style = invis]; actor1_bottom -> actor2_bottom -> actor3_bottom; } // Style the event nodes node [shape=point]; edge [arrowhead=none]; // Define the event nodes. Here they are prefixed with // the actor name. actor1_event1 actor1_event3 // Now we connect each of the events like pearls on a string. actor1_top -> actor1_event1 -> actor1_event3 -> actor1_bottom; // Repeat. The event above has a corresponding node in the // destination actor. actor2_event1 actor2_event2 actor2_top -> actor2_event1 -> actor2_event2 -> actor2_bottom; // And one more time. actor3_event2 actor3_event3 actor3_top -> actor3_event2 -> actor3_event3 -> actor3_bottom; // We connect each event src/dest. First we make sure they // are vertically aligned. {rank=same; actor1_event1 actor2_event1} {rank=same; actor2_event2 actor3_event2} {ranke=same; actor3_event3 actor1_event3} // Finally, we connect the dots. edge [constraint=false, arrowhead=normal]; actor1_event1 -> actor2_event1 [xlabel="AddAccount(Acount)"]; actor2_event2 -> actor3_event2 [xlabel="add"]; actor3_event3 -> actor1_event3 [xlabel="return"]; }