/// <summary> /// Configures the tree reduction stage that will handle edges that do not belong to the tree. /// </summary> private TreeReductionStage CreateTreeReductionStage() { var reductionStage = new TreeReductionStage(); if (EdgeLabelingItem == EnumEdgeLabeling.Integrated) { reductionStage.NonTreeEdgeLabelingAlgorithm = new GenericLabeling(); } reductionStage.MultiParentAllowed = (LayoutStyleItem == EnumStyle.Classic && !EnforceGlobalLayeringItem && ChildPlacementPolicyItem != LeafPlacement.AllLeavesOnSameLayer) || (LayoutStyleItem == EnumStyle.Default && (NodePlacerItem == EnumNodePlacer.Default || NodePlacerItem == EnumNodePlacer.Bus || NodePlacerItem == EnumNodePlacer.LeftRight || NodePlacerItem == EnumNodePlacer.Dendrogram) && AllowMultiParentsItem); if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Organic) { reductionStage.NonTreeEdgeRouter = new OrganicEdgeRouter(); reductionStage.NonTreeEdgeSelectionKey = OrganicEdgeRouter.AffectedEdgesDpKey; } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Orthogonal) { var edgeRouter = new EdgeRouter { Rerouting = true, Scope = Scope.RouteAffectedEdges }; reductionStage.NonTreeEdgeRouter = edgeRouter; reductionStage.NonTreeEdgeSelectionKey = edgeRouter.AffectedEdgesDpKey; } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.StraightLine) { reductionStage.NonTreeEdgeRouter = reductionStage.CreateStraightLineRouter(); } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Bundled) { var ebc = reductionStage.EdgeBundling; ebc.BundlingStrength = EdgeBundlingStrengthItem; ebc.DefaultBundleDescriptor = new EdgeBundleDescriptor { Bundled = true }; } return reductionStage; }
/// <summary> /// configures tree reduction state and non-tree edge routing. /// </summary> protected override void PerformPreLayout() { if ((bool)Handler.GetValue(GENERAL, ALLOW_NON_TREE_EDGES)) { additionalStage = new TreeReductionStage(); multiStageLayout.AppendStage(additionalStage); string routingStyleChoice = (string)Handler.GetValue(GENERAL, ROUTING_STYLE_FOR_NON_TREE_EDGES); if (ROUTE_ORGANIC.Equals(routingStyleChoice)) { OrganicEdgeRouter organic = new OrganicEdgeRouter(); additionalStage.NonTreeEdgeRouter = organic; additionalStage.NonTreeEdgeSelectionKey = OrganicEdgeRouter.AffectedEdgesDpKey; } if (ROUTE_ORTHOGONAL.Equals(routingStyleChoice)) { EdgeRouter orthogonal = new EdgeRouter() { Scope = Scope.RouteAffectedEdges }; additionalStage.NonTreeEdgeSelectionKey = orthogonal.AffectedEdgesDpKey; additionalStage.NonTreeEdgeRouter = orthogonal; } if (ROUTE_STRAIGHTLINE.Equals(routingStyleChoice)) { additionalStage.NonTreeEdgeRouter = additionalStage.CreateStraightLineRouter(); } else if (ROUTE_BUNDLED.Equals(routingStyleChoice)) { // Edge Bundling EdgeBundling ebc = additionalStage.EdgeBundling; EdgeBundleDescriptor descriptor = new EdgeBundleDescriptor(); descriptor.Bundled = true; ebc.DefaultBundleDescriptor = descriptor; ebc.BundlingStrength = (double)Handler.GetValue(GENERAL, EDGE_BUNDLING_STRENGTH); // Sets a new straight-line router in case some edges are not bundled, e.g. self-loops additionalStage.NonTreeEdgeRouter = additionalStage.CreateStraightLineRouter(); } } }
/// <summary> /// Configures the tree reduction stage that will handle edges that do not belong to the tree. /// </summary> private TreeReductionStage CreateTreeReductionStage() { var reductionStage = new TreeReductionStage(); if (EdgeLabelingItem == EnumEdgeLabeling.Integrated) { reductionStage.NonTreeEdgeLabelingAlgorithm = new GenericLabeling(); } reductionStage.MultiParentAllowed = (NodePlacerItem == EnumNodePlacer.Default || NodePlacerItem == EnumNodePlacer.Bus || NodePlacerItem == EnumNodePlacer.LeftRight || NodePlacerItem == EnumNodePlacer.Dendrogram) && AllowMultiParentsItem; if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Organic) { reductionStage.NonTreeEdgeRouter = new OrganicEdgeRouter(); reductionStage.NonTreeEdgeSelectionKey = OrganicEdgeRouter.AffectedEdgesDpKey; } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Orthogonal) { var edgeRouter = new EdgeRouter { Rerouting = true, Scope = Scope.RouteAffectedEdges }; reductionStage.NonTreeEdgeRouter = edgeRouter; reductionStage.NonTreeEdgeSelectionKey = edgeRouter.AffectedEdgesDpKey; } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.StraightLine) { reductionStage.NonTreeEdgeRouter = reductionStage.CreateStraightLineRouter(); } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Bundled) { var ebc = reductionStage.EdgeBundling; ebc.BundlingStrength = EdgeBundlingStrengthItem; ebc.DefaultBundleDescriptor = new EdgeBundleDescriptor { Bundled = true }; } return(reductionStage); }
/// <summary> /// Creates a new instance configured for the specified graph. /// </summary> /// <param name="graph">The graph to configure the layout data for</param> /// <param name="fromSketch"/> Whether the <see cref="HierarchicLayout"/> shall be run in incremental layout mode. public LayoutData(IGraph graph, bool fromSketch) { // set up port candidates for edges (edges should be attached to the left/right side of the corresponding node var candidates = new List <PortCandidate> { PortCandidate.CreateCandidate(PortDirections.West), PortCandidate.CreateCandidate(PortDirections.East) }; // configure the different sub group layout settings var leftToRightTreeLayout = new TreeReductionStage(); leftToRightTreeLayout.NonTreeEdgeRouter = leftToRightTreeLayout.CreateStraightLineRouter(); leftToRightTreeLayout.CoreLayout = new TreeLayout { LayoutOrientation = LayoutOrientation.LeftToRight, }; var rightToLeftTreeLayout = new TreeReductionStage(); rightToLeftTreeLayout.NonTreeEdgeRouter = rightToLeftTreeLayout.CreateStraightLineRouter(); rightToLeftTreeLayout.CoreLayout = new TreeLayout { LayoutOrientation = LayoutOrientation.RightToLeft, }; var view = graph.Lookup <IFoldingView>(); Items.Add(new RecursiveGroupLayoutData { SourcePortCandidates = { Constant = candidates }, TargetPortCandidates = { Constant = candidates }, // map each group node to the layout algorithm that should be used for its content GroupNodeLayouts = { Delegate = node => { switch (GetTierType(node, view, graph)) { case TierType.LeftTreeGroupNode: return(leftToRightTreeLayout); case TierType.RightTreeGroupNode: return(rightToLeftTreeLayout); default: return(null); } } } }); var hlData = new HierarchicLayoutData { NodeLayoutDescriptors = { Delegate = node => { // align tree group nodes within their layer switch (GetTierType(node, view, graph)) { case TierType.LeftTreeGroupNode: return(new NodeLayoutDescriptor { LayerAlignment = 1 }); case TierType.RightTreeGroupNode: return(new NodeLayoutDescriptor { LayerAlignment = 0 }); default: return(null); } } } }; if (!fromSketch) { // insert layer constraints to guarantee the desired placement for "left" and "right" group nodes var layerConstraintData = hlData.LayerConstraints; foreach (var node in graph.Nodes) { // align tree group nodes within their layer TierType type = GetTierType(node, view, graph); if (type == TierType.LeftTreeGroupNode) { layerConstraintData.PlaceAtTop(node); } else if (type == TierType.RightTreeGroupNode) { layerConstraintData.PlaceAtBottom(node); } } } Items.Add(hlData); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new BalloonLayout(); ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; layout.RootNodePolicy = RootNodePolicyItem; layout.PreferredChildWedge = PreferredChildWedgeItem; layout.PreferredRootWedge = PreferredRootWedgeItem; layout.MinimumEdgeLength = MinimumEdgeLengthItem; layout.CompactnessFactor = 1 - CompactnessFactorItem; layout.AllowOverlaps = AllowOverlapsItem; layout.FromSketchMode = FromSketchItem; layout.ChainStraighteningMode = StraightenChainsItem; layout.InterleavedMode = PlaceChildrenInterleavedItem ? InterleavedMode.AllNodes : InterleavedMode.Off; switch (NodeLabelingStyleItem) { case EnumNodeLabelingPolicies.None: layout.ConsiderNodeLabels = false; break; case EnumNodeLabelingPolicies.RaylikeLeaves: layout.IntegratedNodeLabeling = true; layout.NodeLabelingPolicy = NodeLabelingPolicy.RayLikeLeaves; break; case EnumNodeLabelingPolicies.ConsiderCurrentPosition: layout.ConsiderNodeLabels = true; break; case EnumNodeLabelingPolicies.Horizontal: layout.IntegratedNodeLabeling = true; layout.NodeLabelingPolicy = NodeLabelingPolicy.Horizontal; break; default: layout.ConsiderNodeLabels = false; break; } // configures tree reduction stage and non-tree edge routing. layout.SubgraphLayoutEnabled = ActOnSelectionOnlyItem; MultiStageLayout multiStageLayout = layout; var treeReductionStage = new TreeReductionStage(); multiStageLayout.AppendStage(treeReductionStage); if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Organic) { var organic = new OrganicEdgeRouter(); treeReductionStage.NonTreeEdgeRouter = organic; treeReductionStage.NonTreeEdgeSelectionKey = OrganicEdgeRouter.AffectedEdgesDpKey; } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Orthogonal) { var edgeRouter = new EdgeRouter { Rerouting = true, Scope = Scope.RouteAffectedEdges }; treeReductionStage.NonTreeEdgeSelectionKey = edgeRouter.AffectedEdgesDpKey; treeReductionStage.NonTreeEdgeRouter = edgeRouter; } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.StraightLine) { treeReductionStage.NonTreeEdgeRouter = treeReductionStage.CreateStraightLineRouter(); } else if (RoutingStyleForNonTreeEdgesItem == EnumRoute.Bundled) { var ebc = treeReductionStage.EdgeBundling; var bundleDescriptor = new EdgeBundleDescriptor { Bundled = true }; ebc.BundlingStrength = EdgeBundlingStrengthItem; ebc.DefaultBundleDescriptor = bundleDescriptor; } if (EdgeLabelingItem == EnumEdgeLabeling.Generic) { layout.IntegratedEdgeLabeling = false; var genericLabeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, ReduceAmbiguity = ReduceAmbiguityItem }; layout.LabelingEnabled = true; layout.Labeling = genericLabeling; } else if (EdgeLabelingItem == EnumEdgeLabeling.Integrated) { layout.IntegratedEdgeLabeling = true; treeReductionStage.NonTreeEdgeLabelingAlgorithm = new GenericLabeling(); } if (NodeLabelingStyleItem == EnumNodeLabelingPolicies.RaylikeLeaves || NodeLabelingStyleItem == EnumNodeLabelingPolicies.Horizontal) { foreach (var label in graphControl.Graph.GetNodeLabels()) { graphControl.Graph.SetLabelLayoutParameter(label, FreeNodeLabelModel.Instance.FindBestParameter(label, FreeNodeLabelModel.Instance, label.GetLayout())); } } return(layout); }