elk
This commit is contained in:
parent
590caa243c
commit
eccec7afdd
4 changed files with 75 additions and 33 deletions
|
|
@ -32,10 +32,12 @@ var dagreJS string
|
||||||
|
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
NodeSep int
|
NodeSep int
|
||||||
|
EdgeSep int
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultOpts = Opts{
|
var DefaultOpts = Opts{
|
||||||
NodeSep: 60,
|
NodeSep: 60,
|
||||||
|
EdgeSep: 40,
|
||||||
}
|
}
|
||||||
|
|
||||||
type DagreNode struct {
|
type DagreNode struct {
|
||||||
|
|
@ -75,7 +77,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *Opts) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rootAttrs := dagreGraphAttrs{
|
rootAttrs := dagreGraphAttrs{
|
||||||
edgesep: 40,
|
edgesep: opts.EdgeSep,
|
||||||
nodesep: opts.NodeSep,
|
nodesep: opts.NodeSep,
|
||||||
}
|
}
|
||||||
isHorizontal := false
|
isHorizontal := false
|
||||||
|
|
|
||||||
|
|
@ -77,29 +77,33 @@ type ELKGraph struct {
|
||||||
Edges []*ELKEdge `json:"edges,omitempty"`
|
Edges []*ELKEdge `json:"edges,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var DefaultOpts = ELKLayoutOptions{
|
var DefaultOpts = ConfigurableOpts{
|
||||||
Algorithm: "layered",
|
Algorithm: "layered",
|
||||||
HierarchyHandling: "INCLUDE_CHILDREN",
|
|
||||||
NodeSpacing: 100.0,
|
NodeSpacing: 100.0,
|
||||||
|
Padding: "[top=75,left=75,bottom=75,right=75]",
|
||||||
EdgeNodeSpacing: 50.0,
|
EdgeNodeSpacing: 50.0,
|
||||||
SelfLoopSpacing: 50.0,
|
SelfLoopSpacing: 50.0,
|
||||||
ConsiderModelOrder: "NODES_AND_EDGES",
|
}
|
||||||
|
|
||||||
|
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 {
|
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"`
|
Direction string `json:"elk.direction"`
|
||||||
SelfLoopSpacing float64 `json:"elk.spacing.nodeSelfLoop"`
|
HierarchyHandling string `json:"elk.hierarchyHandling,omitempty"`
|
||||||
InlineEdgeLabels bool `json:"elk.edgeLabels.inline,omitempty"`
|
InlineEdgeLabels bool `json:"elk.edgeLabels.inline,omitempty"`
|
||||||
ConsiderModelOrder string `json:"elk.layered.considerModelOrder.strategy,omitempty"`
|
|
||||||
ForceNodeModelOrder bool `json:"elk.layered.crossingMinimization.forceNodeModelOrder,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 {
|
if opts == nil {
|
||||||
opts = &DefaultOpts
|
opts = &DefaultOpts
|
||||||
}
|
}
|
||||||
|
|
@ -122,12 +126,9 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ELKLayoutOptions) (err
|
||||||
elkGraph := &ELKGraph{
|
elkGraph := &ELKGraph{
|
||||||
ID: "root",
|
ID: "root",
|
||||||
LayoutOptions: &ELKLayoutOptions{
|
LayoutOptions: &ELKLayoutOptions{
|
||||||
Algorithm: "layered",
|
|
||||||
HierarchyHandling: "INCLUDE_CHILDREN",
|
HierarchyHandling: "INCLUDE_CHILDREN",
|
||||||
NodeSpacing: 100.0,
|
|
||||||
EdgeNodeSpacing: 50.0,
|
|
||||||
SelfLoopSpacing: 50.0,
|
|
||||||
ConsiderModelOrder: "NODES_AND_EDGES",
|
ConsiderModelOrder: "NODES_AND_EDGES",
|
||||||
|
ConfigurableOpts: *opts,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
switch g.Root.Attributes.Direction.Value {
|
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 {
|
if len(obj.ChildrenArray) > 0 {
|
||||||
n.LayoutOptions = &ELKLayoutOptions{
|
n.LayoutOptions = &ELKLayoutOptions{
|
||||||
Padding: "[top=75,left=75,bottom=75,right=75]",
|
|
||||||
ForceNodeModelOrder: true,
|
ForceNodeModelOrder: true,
|
||||||
|
ConfigurableOpts: ConfigurableOpts{
|
||||||
|
Padding: opts.Padding,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,16 @@ import (
|
||||||
var ELKPlugin = elkPlugin{}
|
var ELKPlugin = elkPlugin{}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
plugins = append(plugins, ELKPlugin)
|
plugins = append(plugins, &ELKPlugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
type elkPlugin struct {
|
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 {
|
if opts != nil {
|
||||||
elkOpts, ok := opts.(d2elklayout.ELKLayoutOptions)
|
elkOpts, ok := opts.(d2elklayout.ConfigurableOpts)
|
||||||
if !ok {
|
if !ok {
|
||||||
return xmain.UsageErrorf("non-dagre layout options given for dagre")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p elkPlugin) Info(context.Context) (*PluginInfo, error) {
|
func (p *elkPlugin) Info(context.Context) (*PluginInfo, error) {
|
||||||
return &PluginInfo{
|
return &PluginInfo{
|
||||||
Name: "elk",
|
Name: "elk",
|
||||||
ShortHelp: "Eclipse Layout Kernel (ELK) with the Layered algorithm.",
|
ShortHelp: "Eclipse Layout Kernel (ELK) with the Layered algorithm.",
|
||||||
|
|
@ -42,10 +42,10 @@ See https://github.com/kieler/elkjs for more.`,
|
||||||
}, nil
|
}, 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)
|
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
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
41
main.go
41
main.go
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"oss.terrastruct.com/util-go/xmain"
|
"oss.terrastruct.com/util-go/xmain"
|
||||||
|
|
||||||
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
|
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
|
||||||
|
"oss.terrastruct.com/d2/d2layouts/d2elklayout"
|
||||||
"oss.terrastruct.com/d2/d2lib"
|
"oss.terrastruct.com/d2/d2lib"
|
||||||
"oss.terrastruct.com/d2/d2plugin"
|
"oss.terrastruct.com/d2/d2plugin"
|
||||||
"oss.terrastruct.com/d2/d2renderers/d2fonts"
|
"oss.terrastruct.com/d2/d2renderers/d2fonts"
|
||||||
|
|
@ -306,18 +307,54 @@ func DiscardSlog(ctx context.Context) context.Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateLayoutOpts(ms *xmain.State) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseLayoutOpts(ms *xmain.State, layout string) (interface{}, error) {
|
func parseLayoutOpts(ms *xmain.State, layout string) (interface{}, error) {
|
||||||
if layout == "dagre" {
|
switch layout {
|
||||||
|
case "dagre":
|
||||||
nodesep, _ := ms.Opts.Flags.GetInt64("dagre-nodesep")
|
nodesep, _ := ms.Opts.Flags.GetInt64("dagre-nodesep")
|
||||||
|
edgesep, _ := ms.Opts.Flags.GetInt64("dagre-edgesep")
|
||||||
return d2dagrelayout.Opts{
|
return d2dagrelayout.Opts{
|
||||||
NodeSep: int(nodesep),
|
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
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue