package layered
import (
"fmt"
"strconv"
"strings"
"github.com/d2lang/elk-go/internal/geometry"
basegraph "github.com/d2lang/elk-go/internal/graph"
)
func copyTypedProperties(target *basegraph .PropertyMap , source *basegraph .PropertyMap ) {
target .CopyFrom (source )
setEnum (source , target , DirectionOption , ParseDirection )
setEnum (source , target , PortSideOption , ParsePortSide )
setEnum (source , target , Hierarchy , parseHierarchyHandling )
setEnum (source , target , PortConstraintsOption , parsePortConstraints )
setEnum (source , target , EdgeRoutingOption , parseEdgeRouting )
setEnum (source , target , AlignmentOption , parseAlignment )
setEnum (source , target , CycleBreaking , ParseCycleBreakingStrategy )
setEnum (source , target , Layering , ParseLayeringStrategy )
setEnum (source , target , CrossingMinimization , parseCrossingMinimization )
setEnum (source , target , NodePlacement , parseNodePlacement )
setEnum (source , target , NetworkSimplexRecomputeNodePlacement , parseNodePlacement )
setEnum (source , target , NetworkSimplexNodeFlexibility , parseNodeFlexibility )
setEnum (source , target , NetworkSimplexNodeFlexibilityDefault , parseNodeFlexibility )
setEnum (source , target , BKFixedAlignment , parseFixedAlignment )
setEnum (source , target , BKEdgeStraightening , parseEdgeStraightening )
setEnum (source , target , SplineRoutingModeOption , parseSplineRoutingMode )
setEnum (source , target , PostCompactionStrategy , parseGraphCompactionStrategy )
setEnum (source , target , PostCompactionConstraints , parseConstraintCalculationStrategy )
setEnum (source , target , NodePromotionStrategyOption , parseNodePromotionStrategy )
setEnum (source , target , PortSortingStrategyOption , parsePortSortingStrategy )
setEnum (source , target , WrappingStrategyOption , parseWrappingStrategy )
setEnum (source , target , WrappingCuttingStrategy , parseCuttingStrategy )
setEnum (source , target , WrappingValidifyStrategy , parseValidifyStrategy )
setEnum (source , target , ConsiderModelOrder , parseOrderingStrategy )
setEnum (source , target , ComponentOrdering , parseComponentOrderingStrategy )
setEnum (source , target , LongEdgeOrdering , parseLongEdgeOrderingStrategy )
setEnum (source , target , CycleBreakingGroupOrder , parseGroupOrderStrategy )
setEnum (source , target , CrossingMinimizationGroupOrder , parseGroupOrderStrategy )
setEnum (source , target , LayerUnzippingStrategyOption , parseLayerUnzippingStrategy )
setEnum (source , target , GreedySwitch , parseGreedySwitch )
setEnum (source , target , GreedySwitchHierarchical , parseGreedySwitch )
setEnum (source , target , LayerConstraintOption , parseLayerConstraint )
setEnum (source , target , InteractiveReferencePointOption , parseInteractiveReferencePoint )
setEnum (source , target , DirectionCongruencyOption , parseDirectionCongruency )
setEnum (source , target , EdgeLabelsPlacement , parseEdgeLabelPlacement )
setEnum (source , target , LabelSideOption , parseLabelSide )
setEnum (source , target , SelfLoopDistribution , parseSelfLoopDistribution )
setEnum (source , target , SelfLoopOrdering , parseSelfLoopOrdering )
setEnum (source , target , CenterEdgeLabelPlacement , parseCenterEdgeLabelPlacement )
setEnum (source , target , EdgeLabelSideSelectionOption , parseEdgeLabelSideSelection )
copyInt (source , target , RandomSeed )
copyInt (source , target , Thoroughness )
copyInt (source , target , CoffmanGrahamLayerBound )
copyInt (source , target , MinWidthUpperBound )
copyInt (source , target , MinWidthUpperLayerScaling )
copyInt (source , target , GreedySwitchActivationThreshold )
copyInt (source , target , PriorityDirection )
copyInt (source , target , PriorityShortness )
copyInt (source , target , PriorityStraightness )
copyInt (source , target , PortIndex )
copyInt (source , target , LayerIDOption )
copyInt (source , target , PositionIDOption )
copyInt (source , target , PositionChoiceConstraint )
copyInt (source , target , LayerChoiceConstraint )
copyInt (source , target , NodePromotionMaxIterations )
copyInt (source , target , HighDegreeNodeThreshold )
copyInt (source , target , HighDegreeNodeTreeHeight )
copyInt (source , target , LayerUnzippingLayerSplit )
copyInt (source , target , CycleBreakingGroupID )
copyInt (source , target , CrossingMinimizationGroupID )
copyInt (source , target , ComponentGroupID )
copyInt (source , target , CycleBreakingPreferredSourceID )
copyInt (source , target , CycleBreakingPreferredTargetID )
copyInt (source , target , WrappingCuttingMSDFreedom )
copyBool (source , target , NoLayout )
copyBool (source , target , SeparateComponents )
copyBool (source , target , EdgeLabelsInline )
copyBool (source , target , FavorStraightEdges )
copyBool (source , target , ForceNodeModelOrder )
copyBool (source , target , SemiInteractive )
copyBool (source , target , GeneratePositionAndLayerIDs )
copyBool (source , target , FeedbackEdges )
copyBool (source , target , MergeEdges )
copyBool (source , target , MergeHierarchyEdges )
copyBool (source , target , UnnecessaryBendpoints )
copyBool (source , target , NoModelOrder )
copyBool (source , target , PortModelOrder )
copyBool (source , target , LayerUnzippingMinimizeEdgeLength )
copyBool (source , target , LayerUnzippingResetOnLongEdges )
copyBool (source , target , HighDegreeNodeTreatment )
copyBool (source , target , WrappingMultiEdgeImproveCuts )
copyBool (source , target , WrappingMultiEdgeImproveWrappedEdges )
for _ , property := range []*basegraph .Property [float64 ]{
&AspectRatio , &EdgeThickness , &PortBorderOffset ,
&LinearSegmentsDeflectionDampening , &HierarchicalSweepiness ,
&SpacingComponentComponent ,
&SpacingEdgeEdge , &SpacingEdgeLabel , &SpacingEdgeNode ,
&SpacingLabelLabel , &SpacingLabelNode , &SpacingLabelPortHorizontal ,
&SpacingLabelPortVertical , &SpacingNodeNode , &SpacingNodeSelfLoop ,
&SpacingPortPort , &SpacingBaseValue , &SpacingEdgeNodeBetweenLayers ,
&SpacingEdgeEdgeBetweenLayers , &SpacingNodeNodeBetweenLayers ,
&PolylineSlopedEdgeZoneWidth ,
&SplineSloppyLayerSpacingFactor ,
&WrappingAdditionalEdgeSpacing , &WrappingCorrectionFactor ,
&WrappingMultiEdgeDistancePenalty ,
&CrossingCounterNodeInfluence , &CrossingCounterPortInfluence ,
} {
copyFloat (source , target , *property )
}
copyFloatAlias (source , target , SpacingNodeNodeBetweenLayers ,
"org.eclipse.elk.spacing.nodeNodeBetweenLayers" )
copyFloatAlias (source , target , SpacingEdgeNodeBetweenLayers ,
"org.eclipse.elk.spacing.edgeNodeBetweenLayers" )
copyFloatAlias (source , target , SpacingEdgeEdgeBetweenLayers ,
"org.eclipse.elk.spacing.edgeEdgeBetweenLayers" )
}
func setEnum[T any ](
source , target *basegraph .PropertyMap ,
property basegraph .Property [T ],
parse func (string ) (T , bool ),
) {
value , found := source .Raw (property .ID )
if !found {
return
}
if typed , ok := value .(T ); ok {
basegraph .Set (target , property , typed )
return
}
if parsed , ok := parse (fmt .Sprint (value )); ok {
basegraph .Set (target , property , parsed )
}
}
func copyInt(source , target *basegraph .PropertyMap , property basegraph .Property [int ]) {
value , found := source .Raw (property .ID )
if !found {
return
}
switch typed := value .(type ) {
case int :
basegraph .Set (target , property , typed )
case int32 :
basegraph .Set (target , property , int (typed ))
case int64 :
basegraph .Set (target , property , int (typed ))
case float64 :
basegraph .Set (target , property , int (typed ))
case string :
if parsed , err := strconv .Atoi (typed ); err == nil {
basegraph .Set (target , property , parsed )
}
}
}
func copyBool(source , target *basegraph .PropertyMap , property basegraph .Property [bool ]) {
value , found := source .Raw (property .ID )
if !found {
return
}
switch typed := value .(type ) {
case bool :
basegraph .Set (target , property , typed )
case string :
if parsed , err := strconv .ParseBool (typed ); err == nil {
basegraph .Set (target , property , parsed )
}
}
}
func copyFloat(source , target *basegraph .PropertyMap , property basegraph .Property [float64 ]) {
copyFloatAlias (source , target , property , property .ID )
}
func copyFloatAlias(source , target *basegraph .PropertyMap , property basegraph .Property [float64 ], id string ) {
value , found := source .Raw (id )
if !found {
return
}
var result float64
switch typed := value .(type ) {
case float64 :
result = typed
case float32 :
result = float64 (typed )
case int :
result = float64 (typed )
case int32 :
result = float64 (typed )
case int64 :
result = float64 (typed )
case string :
parsed , err := strconv .ParseFloat (typed , 64 )
if err != nil {
return
}
result = parsed
default :
return
}
basegraph .Set (target , property , result )
}
func parseHierarchyHandling(value string ) (HierarchyHandling , bool ) {
switch strings .ToUpper (value ) {
case "INHERIT" :
return HierarchyInherit , true
case "INCLUDE_CHILDREN" :
return HierarchyIncludeChildren , true
case "SEPARATE_CHILDREN" :
return HierarchySeparateChildren , true
default :
return 0 , false
}
}
func parsePortConstraints(value string ) (PortConstraints , bool ) {
switch strings .ToUpper (value ) {
case "UNDEFINED" :
return PortConstraintsUndefined , true
case "FREE" :
return PortConstraintsFree , true
case "FIXED_SIDE" :
return PortConstraintsFixedSide , true
case "FIXED_ORDER" :
return PortConstraintsFixedOrder , true
case "FIXED_RATIO" :
return PortConstraintsFixedRatio , true
case "FIXED_POS" :
return PortConstraintsFixedPosition , true
default :
return 0 , false
}
}
func parseEdgeRouting(value string ) (EdgeRouting , bool ) {
switch strings .ToUpper (value ) {
case "UNDEFINED" :
return EdgeRoutingUndefined , true
case "POLYLINE" :
return EdgeRoutingPolyline , true
case "ORTHOGONAL" :
return EdgeRoutingOrthogonal , true
case "SPLINES" :
return EdgeRoutingSplines , true
default :
return 0 , false
}
}
func parseAlignment(value string ) (Alignment , bool ) {
switch strings .ToUpper (value ) {
case "AUTOMATIC" :
return AlignmentAutomatic , true
case "LEFT" :
return AlignmentLeft , true
case "RIGHT" :
return AlignmentRight , true
case "CENTER" :
return AlignmentCenter , true
case "TOP" :
return AlignmentTop , true
case "BOTTOM" :
return AlignmentBottom , true
default :
return 0 , false
}
}
func parseCrossingMinimization(value string ) (CrossingMinimizationStrategy , bool ) {
switch strings .ToUpper (value ) {
case "LAYER_SWEEP" :
return CrossingMinimizationLayerSweep , true
case "MEDIAN_LAYER_SWEEP" :
return CrossingMinimizationMedianLayerSweep , true
case "INTERACTIVE" :
return CrossingMinimizationInteractive , true
case "NONE" :
return CrossingMinimizationNone , true
default :
return 0 , false
}
}
func parseNodePlacement(value string ) (NodePlacementStrategy , bool ) {
switch strings .ToUpper (value ) {
case "SIMPLE" :
return NodePlacementSimple , true
case "INTERACTIVE" :
return NodePlacementInteractive , true
case "LINEAR_SEGMENTS" :
return NodePlacementLinearSegments , true
case "BRANDES_KOEPF" :
return NodePlacementBrandesKoepf , true
case "NETWORK_SIMPLEX" :
return NodePlacementNetworkSimplex , true
default :
return 0 , false
}
}
func parseNodeFlexibility(value string ) (NodeFlexibility , bool ) {
switch strings .ToUpper (value ) {
case "NONE" :
return NodeFlexibilityNone , true
case "PORT_POSITION" :
return NodeFlexibilityPortPosition , true
case "NODE_SIZE_WHERE_SPACE_PERMITS" :
return NodeFlexibilitySizeWhereSpacePermits , true
case "NODE_SIZE" :
return NodeFlexibilitySize , true
default :
return 0 , false
}
}
func parseInteractiveReferencePoint(value string ) (InteractiveReferencePoint , bool ) {
switch strings .ToUpper (value ) {
case "CENTER" :
return InteractiveReferenceCenter , true
case "TOP_LEFT" :
return InteractiveReferenceTopLeft , true
default :
return 0 , false
}
}
func parseFixedAlignment(value string ) (FixedAlignment , bool ) {
switch strings .ToUpper (value ) {
case "NONE" :
return FixedAlignmentNone , true
case "LEFTUP" :
return FixedAlignmentLeftUp , true
case "RIGHTUP" :
return FixedAlignmentRightUp , true
case "LEFTDOWN" :
return FixedAlignmentLeftDown , true
case "RIGHTDOWN" :
return FixedAlignmentRightDown , true
case "BALANCED" :
return FixedAlignmentBalanced , true
default :
return 0 , false
}
}
func parseEdgeStraightening(value string ) (EdgeStraighteningStrategy , bool ) {
switch strings .ToUpper (value ) {
case "NONE" :
return EdgeStraighteningNone , true
case "IMPROVE_STRAIGHTNESS" :
return EdgeStraighteningImprove , true
default :
return 0 , false
}
}
func parseSplineRoutingMode(value string ) (SplineRoutingMode , bool ) {
switch strings .ToUpper (value ) {
case "SLOPPY" :
return SplineRoutingSloppy , true
case "CONSERVATIVE" :
return SplineRoutingConservative , true
case "CONSERVATIVE_SOFT" :
return SplineRoutingConservativeSoft , true
default :
return 0 , false
}
}
func parseGraphCompactionStrategy(value string ) (GraphCompactionStrategy , bool ) {
values := []GraphCompactionStrategy {
GraphCompactionNone , GraphCompactionLeft , GraphCompactionRight ,
GraphCompactionLeftRightConstraintLocking , GraphCompactionLeftRightConnectionLocking ,
GraphCompactionEdgeLength ,
}
names := []string {
"NONE" , "LEFT" , "RIGHT" , "LEFT_RIGHT_CONSTRAINT_LOCKING" ,
"LEFT_RIGHT_CONNECTION_LOCKING" , "EDGE_LENGTH" ,
}
for index , name := range names {
if strings .EqualFold (value , name ) {
return values [index ], true
}
}
return 0 , false
}
func parseConstraintCalculationStrategy(value string ) (ConstraintCalculationStrategy , bool ) {
switch strings .ToUpper (value ) {
case "QUADRATIC" :
return ConstraintCalculationQuadratic , true
case "SCANLINE" :
return ConstraintCalculationScanline , true
default :
return 0 , false
}
}
func parseNodePromotionStrategy(value string ) (NodePromotionStrategy , bool ) {
values := []NodePromotionStrategy {
NodePromotionNone , NodePromotionNikolov , NodePromotionNikolovPixel ,
NodePromotionNikolovImproved , NodePromotionNikolovImprovedPixel ,
NodePromotionDummyNodePercentage , NodePromotionNodeCountPercentage ,
NodePromotionNoBoundary , NodePromotionModelOrderLeftToRight ,
NodePromotionModelOrderRightToLeft ,
}
names := []string {
"NONE" , "NIKOLOV" , "NIKOLOV_PIXEL" , "NIKOLOV_IMPROVED" ,
"NIKOLOV_IMPROVED_PIXEL" , "DUMMYNODE_PERCENTAGE" , "NODECOUNT_PERCENTAGE" ,
"NO_BOUNDARY" , "MODEL_ORDER_LEFT_TO_RIGHT" , "MODEL_ORDER_RIGHT_TO_LEFT" ,
}
for index , name := range names {
if strings .EqualFold (value , name ) {
return values [index ], true
}
}
return 0 , false
}
func parsePortSortingStrategy(value string ) (PortSortingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "INPUT_ORDER" :
return PortSortingInputOrder , true
case "PORT_DEGREE" :
return PortSortingPortDegree , true
default :
return 0 , false
}
}
func parseWrappingStrategy(value string ) (WrappingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "OFF" :
return WrappingOff , true
case "SINGLE_EDGE" :
return WrappingSingleEdge , true
case "MULTI_EDGE" :
return WrappingMultiEdge , true
default :
return 0 , false
}
}
func parseCuttingStrategy(value string ) (CuttingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "ARD" :
return CuttingARD , true
case "MSD" :
return CuttingMSD , true
case "MANUAL" :
return CuttingManual , true
default :
return 0 , false
}
}
func parseValidifyStrategy(value string ) (ValidifyStrategy , bool ) {
switch strings .ToUpper (value ) {
case "NO" :
return ValidifyNo , true
case "GREEDY" :
return ValidifyGreedy , true
case "LOOK_BACK" :
return ValidifyLookBack , true
default :
return 0 , false
}
}
func parseOrderingStrategy(value string ) (OrderingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "NONE" :
return OrderingNone , true
case "NODES_AND_EDGES" :
return OrderingNodesAndEdges , true
case "PREFER_EDGES" :
return OrderingPreferEdges , true
case "PREFER_NODES" :
return OrderingPreferNodes , true
default :
return 0 , false
}
}
func parseLongEdgeOrderingStrategy(value string ) (LongEdgeOrderingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "DUMMY_NODE_OVER" :
return LongEdgeDummyNodeOver , true
case "DUMMY_NODE_UNDER" :
return LongEdgeDummyNodeUnder , true
case "EQUAL" :
return LongEdgeEqual , true
default :
return 0 , false
}
}
func parseComponentOrderingStrategy(value string ) (ComponentOrderingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "NONE" :
return ComponentOrderingNone , true
case "INSIDE_PORT_SIDE_GROUPS" :
return ComponentOrderingInsidePortSideGroups , true
case "GROUP_MODEL_ORDER" :
return ComponentOrderingGroupModelOrder , true
case "MODEL_ORDER" :
return ComponentOrderingModelOrder , true
default :
return 0 , false
}
}
func parseGroupOrderStrategy(value string ) (GroupOrderStrategy , bool ) {
switch strings .ToUpper (value ) {
case "ONLY_WITHIN_GROUP" :
return GroupOrderOnlyWithinGroup , true
case "MODEL_ORDER" :
return GroupOrderModelOrder , true
case "ENFORCED" :
return GroupOrderEnforced , true
default :
return 0 , false
}
}
func parseLayerUnzippingStrategy(value string ) (LayerUnzippingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "NONE" :
return LayerUnzippingNone , true
case "ALTERNATING" :
return LayerUnzippingAlternating , true
default :
return 0 , false
}
}
func parseGreedySwitch(value string ) (GreedySwitchType , bool ) {
switch strings .ToUpper (value ) {
case "ONE_SIDED" :
return GreedySwitchOneSided , true
case "TWO_SIDED" :
return GreedySwitchTwoSided , true
case "OFF" :
return GreedySwitchOff , true
default :
return 0 , false
}
}
func parseLayerConstraint(value string ) (LayerConstraint , bool ) {
switch strings .ToUpper (value ) {
case "NONE" :
return LayerConstraintNone , true
case "FIRST" :
return LayerConstraintFirst , true
case "FIRST_SEPARATE" :
return LayerConstraintFirstSeparate , true
case "LAST" :
return LayerConstraintLast , true
case "LAST_SEPARATE" :
return LayerConstraintLastSeparate , true
default :
return 0 , false
}
}
func parseDirectionCongruency(value string ) (DirectionCongruency , bool ) {
switch strings .ToUpper (value ) {
case "READING_DIRECTION" :
return DirectionCongruencyReading , true
case "ROTATION" :
return DirectionCongruencyRotation , true
default :
return 0 , false
}
}
func parseEdgeLabelPlacement(value string ) (EdgeLabelPlacement , bool ) {
switch strings .ToUpper (value ) {
case "CENTER" :
return EdgeLabelPlacementCenter , true
case "HEAD" :
return EdgeLabelPlacementHead , true
case "TAIL" :
return EdgeLabelPlacementTail , true
default :
return 0 , false
}
}
func parseLabelSide(value string ) (LabelSide , bool ) {
switch strings .ToUpper (value ) {
case "UNKNOWN" :
return LabelSideUnknown , true
case "ABOVE" :
return LabelSideAbove , true
case "BELOW" :
return LabelSideBelow , true
case "INLINE" :
return LabelSideInline , true
default :
return 0 , false
}
}
func parseSelfLoopDistribution(value string ) (SelfLoopDistributionStrategy , bool ) {
switch strings .ToUpper (value ) {
case "EQUALLY" :
return SelfLoopDistributionEqually , true
case "NORTH" :
return SelfLoopDistributionNorth , true
case "NORTH_SOUTH" :
return SelfLoopDistributionNorthSouth , true
default :
return 0 , false
}
}
func parseSelfLoopOrdering(value string ) (SelfLoopOrderingStrategy , bool ) {
switch strings .ToUpper (value ) {
case "STACKED" :
return SelfLoopOrderingStacked , true
case "REVERSE_STACKED" :
return SelfLoopOrderingReverseStacked , true
case "SEQUENCED" :
return SelfLoopOrderingSequenced , true
default :
return 0 , false
}
}
func parseCenterEdgeLabelPlacement(value string ) (CenterEdgeLabelPlacementStrategy , bool ) {
values := []CenterEdgeLabelPlacementStrategy {
CenterLabelMedianLayer , CenterLabelTailLayer , CenterLabelHeadLayer ,
CenterLabelSpaceEfficientLayer , CenterLabelWidestLayer , CenterLabelCenterLayer ,
}
names := []string {"MEDIAN_LAYER" , "TAIL_LAYER" , "HEAD_LAYER" , "SPACE_EFFICIENT_LAYER" , "WIDEST_LAYER" , "CENTER_LAYER" }
for index , name := range names {
if strings .EqualFold (value , name ) {
return values [index ], true
}
}
return 0 , false
}
func parseEdgeLabelSideSelection(value string ) (EdgeLabelSideSelection , bool ) {
values := []EdgeLabelSideSelection {
EdgeLabelSideAlwaysUp , EdgeLabelSideAlwaysDown , EdgeLabelSideDirectionUp ,
EdgeLabelSideDirectionDown , EdgeLabelSideSmartUp , EdgeLabelSideSmartDown ,
}
names := []string {"ALWAYS_UP" , "ALWAYS_DOWN" , "DIRECTION_UP" , "DIRECTION_DOWN" , "SMART_UP" , "SMART_DOWN" }
for index , name := range names {
if strings .EqualFold (value , name ) {
return values [index ], true
}
}
return 0 , false
}
func addSpacing(first , second geometry .Spacing ) geometry .Spacing {
return geometry .Spacing {
Top : first .Top + second .Top , Right : first .Right + second .Right ,
Bottom : first .Bottom + second .Bottom , Left : first .Left + second .Left ,
}
}
The pages are generated with Golds v0.8.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .