Skip to content

Commit

Permalink
Merge pull request #1134 from alixander/dagre-edge-width
Browse files Browse the repository at this point in the history
add padding between dagre edge labels
  • Loading branch information
alixander authored Apr 4, 2023
2 parents 5a1b5df + cadaaeb commit d1c980d
Show file tree
Hide file tree
Showing 31 changed files with 2,478 additions and 1,591 deletions.
2 changes: 2 additions & 0 deletions ci/release/changelogs/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#### Improvements 🧹

- Labels on parallel `dagre` connections include a gap between them [#1134](https://github.com/terrastruct/d2/pull/1134)

#### Bugfixes ⛑️

- Fix a bug in 32bit builds [#1115](https://github.com/terrastruct/d2/issues/1115)
Expand Down
84 changes: 56 additions & 28 deletions d2layouts/d2dagrelayout/layout.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var dagreJS string
const (
MIN_SEGMENT_LEN = 10
MIN_RANK_SEP = 60
EDGE_LABEL_GAP = 20
)

type ConfigurableOpts struct {
Expand Down Expand Up @@ -173,37 +174,30 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
}
}
for _, edge := range g.Edges {
// dagre doesn't work with edges to containers so we connect container edges to their first child instead (going all the way down)
// we will chop the edge where it intersects the container border so it only shows the edge from the container
src := edge.Src
for len(src.Children) > 0 && src.Class == nil && src.SQLTable == nil {
// We want to get the bottom node of sources, setting its rank higher than all children
src = getLongestEdgeChainTail(g, src)
}
dst := edge.Dst
for len(dst.Children) > 0 && dst.Class == nil && dst.SQLTable == nil {
dst = dst.ChildrenArray[0]

// We want to get the top node of destinations
for _, child := range dst.ChildrenArray {
isHead := true
for _, e := range g.Edges {
if inContainer(e.Src, child) != nil && inContainer(e.Dst, dst) != nil {
isHead = false
break
}
}
if isHead {
dst = child
break
}
src, dst := getEdgeEndpoints(g, edge)

width := edge.LabelDimensions.Width
height := edge.LabelDimensions.Height

numEdges := 0
for _, e := range g.Edges {
otherSrc, otherDst := getEdgeEndpoints(g, e)
if (otherSrc == src && otherDst == dst) || (otherSrc == dst && otherDst == src) {
numEdges++
}
}
if edge.SrcArrow && !edge.DstArrow {
// for `b <- a`, edge.Edge is `a -> b` and we expect this routing result
src, dst = dst, src

// We want to leave some gap between multiple edges
if numEdges > 1 {
switch g.Root.Attributes.Direction.Value {
case "down", "up", "":
width += EDGE_LABEL_GAP
case "left", "right":
height += EDGE_LABEL_GAP
}
}
loadScript += generateAddEdgeLine(src.AbsID(), dst.AbsID(), edge.AbsID(), edge.LabelDimensions.Width, edge.LabelDimensions.Height)

loadScript += generateAddEdgeLine(src.AbsID(), dst.AbsID(), edge.AbsID(), width, height)
}

if debugJS {
Expand Down Expand Up @@ -528,6 +522,40 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err
return nil
}

func getEdgeEndpoints(g *d2graph.Graph, edge *d2graph.Edge) (*d2graph.Object, *d2graph.Object) {
// dagre doesn't work with edges to containers so we connect container edges to their first child instead (going all the way down)
// we will chop the edge where it intersects the container border so it only shows the edge from the container
src := edge.Src
for len(src.Children) > 0 && src.Class == nil && src.SQLTable == nil {
// We want to get the bottom node of sources, setting its rank higher than all children
src = getLongestEdgeChainTail(g, src)
}
dst := edge.Dst
for len(dst.Children) > 0 && dst.Class == nil && dst.SQLTable == nil {
dst = dst.ChildrenArray[0]

// We want to get the top node of destinations
for _, child := range dst.ChildrenArray {
isHead := true
for _, e := range g.Edges {
if inContainer(e.Src, child) != nil && inContainer(e.Dst, dst) != nil {
isHead = false
break
}
}
if isHead {
dst = child
break
}
}
}
if edge.SrcArrow && !edge.DstArrow {
// for `b <- a`, edge.Edge is `a -> b` and we expect this routing result
src, dst = dst, src
}
return src, dst
}

func setGraphAttrs(attrs dagreOpts) string {
return fmt.Sprintf(`g.setGraph({
ranksep: %d,
Expand Down
168 changes: 84 additions & 84 deletions d2renderers/d2sketch/testdata/dots-real/sketch.exp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
168 changes: 84 additions & 84 deletions d2renderers/d2sketch/testdata/paper-real/sketch.exp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
176 changes: 88 additions & 88 deletions d2renderers/d2sketch/testdata/terminal/sketch.exp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified e2etests-cli/testdata/TestCLI_E2E/internal_linked_pdf.exp.pdf
Binary file not shown.
6 changes: 6 additions & 0 deletions e2etests/stable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ logs: { shape: page; style.multiple: true }
network.data processor -> api server
`,
},
{
name: "edge-label-overflow",
script: `student -> committee chair: Apply for appeal
student <- committee chair: Deny. Need more information
committee chair -> committee: Accept appeal`,
},
{
name: "mono-edge",
script: `direction: right
Expand Down
44 changes: 22 additions & 22 deletions e2etests/testdata/patterns/real-lines/dagre/board.exp.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

174 changes: 87 additions & 87 deletions e2etests/testdata/patterns/real-lines/dagre/sketch.exp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 16 additions & 16 deletions e2etests/testdata/patterns/real/dagre/board.exp.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d1c980d

Please sign in to comment.