This commit is contained in:
Alexander Wang 2022-12-29 22:43:01 -08:00
parent 590caa243c
commit eccec7afdd
No known key found for this signature in database
GPG key ID: D89FA31966BDBECE
4 changed files with 75 additions and 33 deletions

View file

@ -32,10 +32,12 @@ var dagreJS string
type Opts struct {
NodeSep int
EdgeSep int
}
var DefaultOpts = Opts{
NodeSep: 60,
EdgeSep: 40,
}
type DagreNode struct {
@ -75,7 +77,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *Opts) (err error) {
}
rootAttrs := dagreGraphAttrs{
edgesep: 40,
edgesep: opts.EdgeSep,
nodesep: opts.NodeSep,
}
isHorizontal := false

View file

@ -77,29 +77,33 @@ type ELKGraph struct {
Edges []*ELKEdge `json:"edges,omitempty"`
}
var DefaultOpts = ELKLayoutOptions{
Algorithm: "layered",
HierarchyHandling: "INCLUDE_CHILDREN",
NodeSpacing: 100.0,
EdgeNodeSpacing: 50.0,
SelfLoopSpacing: 50.0,
ConsiderModelOrder: "NODES_AND_EDGES",
var DefaultOpts = ConfigurableOpts{
Algorithm: "layered",
NodeSpacing: 100.0,
Padding: "[top=75,left=75,bottom=75,right=75]",
EdgeNodeSpacing: 50.0,
SelfLoopSpacing: 50.0,
}
type ConfigurableOpts struct {
Algorithm string `json:"elk.algorithm,omitempty"`
NodeSpacing int `json:"spacing.nodeNodeBetweenLayers,omitempty"`
Padding string `json:"elk.padding,omitempty"`
EdgeNodeSpacing int `json:"spacing.edgeNodeBetweenLayers,omitempty"`
SelfLoopSpacing int `json:"elk.spacing.nodeSelfLoop"`
}
type ELKLayoutOptions struct {
Algorithm string `json:"elk.algorithm,omitempty"`
HierarchyHandling string `json:"elk.hierarchyHandling,omitempty"`
NodeSpacing float64 `json:"spacing.nodeNodeBetweenLayers,omitempty"`
Padding string `json:"elk.padding,omitempty"`
EdgeNodeSpacing float64 `json:"spacing.edgeNodeBetweenLayers,omitempty"`
Direction string `json:"elk.direction"`
SelfLoopSpacing float64 `json:"elk.spacing.nodeSelfLoop"`
InlineEdgeLabels bool `json:"elk.edgeLabels.inline,omitempty"`
ConsiderModelOrder string `json:"elk.layered.considerModelOrder.strategy,omitempty"`
ForceNodeModelOrder bool `json:"elk.layered.crossingMinimization.forceNodeModelOrder,omitempty"`
Direction string `json:"elk.direction"`
HierarchyHandling string `json:"elk.hierarchyHandling,omitempty"`
InlineEdgeLabels bool `json:"elk.edgeLabels.inline,omitempty"`
ForceNodeModelOrder bool `json:"elk.layered.crossingMinimization.forceNodeModelOrder,omitempty"`
ConsiderModelOrder string `json:"elk.layered.considerModelOrder.strategy,omitempty"`
ConfigurableOpts
}
func Layout(ctx context.Context, g *d2graph.Graph, opts *ELKLayoutOptions) (err error) {
func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err error) {
if opts == nil {
opts = &DefaultOpts
}
@ -122,12 +126,9 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ELKLayoutOptions) (err
elkGraph := &ELKGraph{
ID: "root",
LayoutOptions: &ELKLayoutOptions{
Algorithm: "layered",
HierarchyHandling: "INCLUDE_CHILDREN",
NodeSpacing: 100.0,
EdgeNodeSpacing: 50.0,
SelfLoopSpacing: 50.0,
ConsiderModelOrder: "NODES_AND_EDGES",
ConfigurableOpts: *opts,
},
}
switch g.Root.Attributes.Direction.Value {
@ -171,8 +172,10 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ELKLayoutOptions) (err
if len(obj.ChildrenArray) > 0 {
n.LayoutOptions = &ELKLayoutOptions{
Padding: "[top=75,left=75,bottom=75,right=75]",
ForceNodeModelOrder: true,
ConfigurableOpts: ConfigurableOpts{
Padding: opts.Padding,
},
}
}

View file

@ -13,16 +13,16 @@ import (
var ELKPlugin = elkPlugin{}
func init() {
plugins = append(plugins, ELKPlugin)
plugins = append(plugins, &ELKPlugin)
}
type elkPlugin struct {
opts *d2elklayout.ELKLayoutOptions
opts *d2elklayout.ConfigurableOpts
}
func (p elkPlugin) HydrateOpts(ctx context.Context, opts interface{}) error {
func (p *elkPlugin) HydrateOpts(ctx context.Context, opts interface{}) error {
if opts != nil {
elkOpts, ok := opts.(d2elklayout.ELKLayoutOptions)
elkOpts, ok := opts.(d2elklayout.ConfigurableOpts)
if !ok {
return xmain.UsageErrorf("non-dagre layout options given for dagre")
}
@ -32,7 +32,7 @@ func (p elkPlugin) HydrateOpts(ctx context.Context, opts interface{}) error {
return nil
}
func (p elkPlugin) Info(context.Context) (*PluginInfo, error) {
func (p *elkPlugin) Info(context.Context) (*PluginInfo, error) {
return &PluginInfo{
Name: "elk",
ShortHelp: "Eclipse Layout Kernel (ELK) with the Layered algorithm.",
@ -42,10 +42,10 @@ See https://github.com/kieler/elkjs for more.`,
}, nil
}
func (p elkPlugin) Layout(ctx context.Context, g *d2graph.Graph) error {
func (p *elkPlugin) Layout(ctx context.Context, g *d2graph.Graph) error {
return d2elklayout.Layout(ctx, g, p.opts)
}
func (p elkPlugin) PostProcess(ctx context.Context, in []byte) ([]byte, error) {
func (p *elkPlugin) PostProcess(ctx context.Context, in []byte) ([]byte, error) {
return in, nil
}

41
main.go
View file

@ -18,6 +18,7 @@ import (
"oss.terrastruct.com/util-go/xmain"
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
"oss.terrastruct.com/d2/d2layouts/d2elklayout"
"oss.terrastruct.com/d2/d2lib"
"oss.terrastruct.com/d2/d2plugin"
"oss.terrastruct.com/d2/d2renderers/d2fonts"
@ -306,18 +307,54 @@ func DiscardSlog(ctx context.Context) context.Context {
}
func populateLayoutOpts(ms *xmain.State) error {
_, err := ms.Opts.Int64("", "dagre-nodesep", "", int64(d2dagrelayout.DefaultOpts.NodeSep), "number of pixels that separate nodes horizontally in the layout.")
_, err := ms.Opts.Int64("", "dagre-nodesep", "", int64(d2dagrelayout.DefaultOpts.NodeSep), "number of pixels that separate nodes horizontally.")
if err != nil {
return err
}
_, err = ms.Opts.Int64("", "dagre-edgesep", "", int64(d2dagrelayout.DefaultOpts.EdgeSep), "number of pixels that separate edges horizontally.")
if err != nil {
return err
}
ms.Opts.String("", "elk-algorithm", "", d2elklayout.DefaultOpts.Algorithm, "number of pixels that separate nodes horizontally.")
_, err = ms.Opts.Int64("", "elk-nodeNodeBetweenLayers", "", int64(d2elklayout.DefaultOpts.NodeSpacing), "number of pixels that separate edges horizontally.")
if err != nil {
return err
}
ms.Opts.String("", "elk-padding", "", d2elklayout.DefaultOpts.Padding, "number of pixels that separate nodes horizontally.")
_, err = ms.Opts.Int64("", "elk-edgeNodeBetweenLayers", "", int64(d2elklayout.DefaultOpts.EdgeNodeSpacing), "number of pixels that separate edges horizontally.")
if err != nil {
return err
}
_, err = ms.Opts.Int64("", "elk-nodeSelfLoop", "", int64(d2elklayout.DefaultOpts.SelfLoopSpacing), "number of pixels that separate edges horizontally.")
if err != nil {
return err
}
return nil
}
func parseLayoutOpts(ms *xmain.State, layout string) (interface{}, error) {
if layout == "dagre" {
switch layout {
case "dagre":
nodesep, _ := ms.Opts.Flags.GetInt64("dagre-nodesep")
edgesep, _ := ms.Opts.Flags.GetInt64("dagre-edgesep")
return d2dagrelayout.Opts{
NodeSep: int(nodesep),
EdgeSep: int(edgesep),
}, nil
case "elk":
algorithm, _ := ms.Opts.Flags.GetString("elk-algorithm")
nodeSpacing, _ := ms.Opts.Flags.GetInt64("elk-nodeNodeBetweenLayers")
padding, _ := ms.Opts.Flags.GetString("elk-padding")
edgeNodeSpacing, _ := ms.Opts.Flags.GetInt64("elk-edgeNodeSpacing")
selfLoopSpacing, _ := ms.Opts.Flags.GetInt64("elk-nodeSelfLoop")
return d2elklayout.ConfigurableOpts{
Algorithm: algorithm,
NodeSpacing: int(nodeSpacing),
Padding: padding,
EdgeNodeSpacing: int(edgeNodeSpacing),
SelfLoopSpacing: int(selfLoopSpacing),
}, nil
}