Handle self edges
This commit is contained in:
parent
c4dc93faee
commit
9776d856fa
2 changed files with 58 additions and 7 deletions
|
|
@ -383,3 +383,39 @@ func TestNestedSequenceDiagrams(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSelfEdges(t *testing.T) {
|
||||||
|
g := d2graph.NewGraph(nil)
|
||||||
|
g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram}
|
||||||
|
n1 := g.Root.EnsureChild([]string{"n1"})
|
||||||
|
n1.Box = geo.NewBox(nil, 100, 100)
|
||||||
|
|
||||||
|
g.Edges = []*d2graph.Edge{
|
||||||
|
{
|
||||||
|
Src: n1,
|
||||||
|
Dst: n1,
|
||||||
|
Index: 0,
|
||||||
|
Attributes: d2graph.Attributes{
|
||||||
|
Label: d2graph.Scalar{Value: "left to right"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := log.WithTB(context.Background(), t, nil)
|
||||||
|
Layout(ctx, g, func(ctx context.Context, g *d2graph.Graph) error {
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
route := g.Edges[0].Route
|
||||||
|
if len(route) != 4 {
|
||||||
|
t.Fatalf("expected route to have 4 points, got %d", len(route))
|
||||||
|
}
|
||||||
|
|
||||||
|
if route[0].X != route[3].X {
|
||||||
|
t.Fatalf("route does not end at the same actor, start at %.5f, end at %.5f", route[0].X, route[3].X)
|
||||||
|
}
|
||||||
|
|
||||||
|
if route[3].Y-route[0].Y != MIN_MESSAGE_DISTANCE {
|
||||||
|
t.Fatalf("expected route height to be %.f5, got %.5f", MIN_MESSAGE_DISTANCE, route[3].Y-route[0].Y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,8 @@ func (sd *sequenceDiagram) placeActors() {
|
||||||
// │
|
// │
|
||||||
// │
|
// │
|
||||||
func (sd *sequenceDiagram) addLifelineEdges() {
|
func (sd *sequenceDiagram) addLifelineEdges() {
|
||||||
endY := sd.getMessageY(len(sd.messages))
|
lastRoute := sd.messages[len(sd.messages)-1].Route
|
||||||
|
endY := lastRoute[len(lastRoute)-1].Y + MIN_MESSAGE_DISTANCE
|
||||||
for _, actor := range sd.actors {
|
for _, actor := range sd.actors {
|
||||||
actorBottom := actor.Center()
|
actorBottom := actor.Center()
|
||||||
actorBottom.Y = actor.TopLeft.Y + actor.Height
|
actorBottom.Y = actor.TopLeft.Y + actor.Height
|
||||||
|
|
@ -241,6 +242,7 @@ func (sd *sequenceDiagram) routeMessages() {
|
||||||
for rank, message := range sd.messages {
|
for rank, message := range sd.messages {
|
||||||
message.ZIndex = 2
|
message.ZIndex = 2
|
||||||
isLeftToRight := message.Src.TopLeft.X < message.Dst.TopLeft.X
|
isLeftToRight := message.Src.TopLeft.X < message.Dst.TopLeft.X
|
||||||
|
isSelfMessage := message.Src == message.Dst
|
||||||
|
|
||||||
// finds the proper anchor point based on the message direction
|
// finds the proper anchor point based on the message direction
|
||||||
var startX, endX float64
|
var startX, endX float64
|
||||||
|
|
@ -252,7 +254,9 @@ func (sd *sequenceDiagram) routeMessages() {
|
||||||
startX = message.Src.TopLeft.X
|
startX = message.Src.TopLeft.X
|
||||||
}
|
}
|
||||||
|
|
||||||
if sd.isActor(message.Dst) {
|
if isSelfMessage {
|
||||||
|
endX = startX
|
||||||
|
} else if sd.isActor(message.Dst) {
|
||||||
endX = message.Dst.Center().X
|
endX = message.Dst.Center().X
|
||||||
} else if isLeftToRight {
|
} else if isLeftToRight {
|
||||||
endX = message.Dst.TopLeft.X
|
endX = message.Dst.TopLeft.X
|
||||||
|
|
@ -260,14 +264,25 @@ func (sd *sequenceDiagram) routeMessages() {
|
||||||
endX = message.Dst.TopLeft.X + message.Dst.Width
|
endX = message.Dst.TopLeft.X + message.Dst.Width
|
||||||
}
|
}
|
||||||
|
|
||||||
messageY := sd.getMessageY(rank)
|
startY := sd.getMessageY(rank)
|
||||||
message.Route = []*geo.Point{
|
if isSelfMessage {
|
||||||
geo.NewPoint(startX, messageY),
|
message.Route = []*geo.Point{
|
||||||
geo.NewPoint(endX, messageY),
|
geo.NewPoint(startX, startY),
|
||||||
|
geo.NewPoint(startX+MIN_MESSAGE_DISTANCE, startY),
|
||||||
|
geo.NewPoint(startX+MIN_MESSAGE_DISTANCE, startY+MIN_MESSAGE_DISTANCE),
|
||||||
|
geo.NewPoint(startX, startY+MIN_MESSAGE_DISTANCE),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.Route = []*geo.Point{
|
||||||
|
geo.NewPoint(startX, startY),
|
||||||
|
geo.NewPoint(endX, startY),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if message.Attributes.Label.Value != "" {
|
if message.Attributes.Label.Value != "" {
|
||||||
if isLeftToRight {
|
if isSelfMessage {
|
||||||
|
message.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter))
|
||||||
|
} else if isLeftToRight {
|
||||||
message.LabelPosition = go2.Pointer(string(label.OutsideTopCenter))
|
message.LabelPosition = go2.Pointer(string(label.OutsideTopCenter))
|
||||||
} else {
|
} else {
|
||||||
// the label will be placed above the message because the orientation is based on the edge normal vector
|
// the label will be placed above the message because the orientation is based on the edge normal vector
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue