///<inheritdoc/> protected override void SetupHandler() { BalloonLayout balloonLayout = new BalloonLayout(); OptionGroup generalGroup = Handler.AddGroup(GENERAL); generalGroup.AddList(ROOT_NODE_POLICY, enumRoot.Keys, DIRECTED_ROOT); IOptionItem allowNonTreeItem = generalGroup.AddBool(ALLOW_NON_TREE_EDGES, true); IOptionItem nonTreeStyleItem = generalGroup.AddList(ROUTING_STYLE_FOR_NON_TREE_EDGES, enumRoute, ROUTE_ORTHOGONAL); ConstraintManager cm = new ConstraintManager(Handler); cm.SetEnabledOnValueEquals(allowNonTreeItem, true, nonTreeStyleItem); IOptionItem ebs = generalGroup.AddDouble(EDGE_BUNDLING_STRENGTH, 0.99, 0, 1); cm.SetEnabledOnValueEquals(nonTreeStyleItem, ROUTE_BUNDLED, ebs); generalGroup.AddBool(ACT_ON_SELECTION_ONLY, false); generalGroup.AddInt(PREFERRED_CHILD_WEDGE, balloonLayout.PreferredChildWedge, 1, 359); generalGroup.AddInt(PREFERRED_ROOT_WEDGE, balloonLayout.PreferredRootWedge, 1, 360); generalGroup.AddInt(MINIMAL_EDGE_LENGTH, balloonLayout.MinimumEdgeLength, 10, int.MaxValue); generalGroup.AddDouble(COMPACTNESS_FACTOR, balloonLayout.CompactnessFactor, 0.1, 0.9); generalGroup.AddBool(ALLOW_OVERLAPS, balloonLayout.AllowOverlaps); generalGroup.AddBool(BALLOON_FROM_SKETCH, balloonLayout.FromSketchMode); generalGroup.AddBool(PLACE_CHILDREN_INTERLEAVED, balloonLayout.InterleavedMode == InterleavedMode.AllNodes); generalGroup.AddBool(STRAIGHTEN_CHAINS, balloonLayout.ChainStraighteningMode); OptionGroup labelingGroup = Handler.AddGroup(LABELING); labelingGroup.AddBool(INTEGRATED_EDGE_LABELING, true); labelingGroup.AddList(NODE_LABELING_STYLE, nodeLabelingPolicies, nodeLabelingPolicies[3]); }
private void SetupLayouts() { // create TreeLayout var treeLayout = new TreeLayout { LayoutOrientation = LayoutOrientation.LeftToRight }; treeLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(treeLayout); layoutMapper["Tree"] = treeLayout; layoutComboBox.Items.Add("Tree"); // create BalloonLayout var balloonLayout = new BalloonLayout { FromSketchMode = true, CompactnessFactor = 1.0, AllowOverlaps = true }; balloonLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(balloonLayout); layoutMapper["Balloon"] = balloonLayout; layoutComboBox.Items.Add("Balloon"); // create OrganicLayout var organicLayout = new OrganicLayout { MinimumNodeDistance = 40, Deterministic = true }; organicLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(organicLayout); layoutMapper["Organic"] = organicLayout; layoutComboBox.Items.Add("Organic"); // create OrthogonalLayout var orthogonalLayout = new OrthogonalLayout(); orthogonalLayout.PrependStage(new FixNodeLayoutStage()); layouts.Add(orthogonalLayout); layoutMapper["Orthogonal"] = orthogonalLayout; layoutComboBox.Items.Add("Orthogonal"); // set it as initial value currentLayout = treeLayout; layoutComboBox.SelectedIndex = 0; }
///<inheritdoc/> protected override void ConfigureLayout() { BalloonLayout balloon = new BalloonLayout(); ((ComponentLayout)balloon.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; string rootNodePolicyChoice = (string)Handler.GetValue(GENERAL, ROOT_NODE_POLICY); balloon.RootNodePolicy = enumRoot[rootNodePolicyChoice]; balloon.PreferredChildWedge = (int)Handler.GetValue(GENERAL, PREFERRED_CHILD_WEDGE); balloon.PreferredRootWedge = (int)Handler.GetValue(GENERAL, PREFERRED_ROOT_WEDGE); balloon.MinimumEdgeLength = (int)Handler.GetValue(GENERAL, MINIMAL_EDGE_LENGTH); balloon.CompactnessFactor = (double)Handler.GetValue(GENERAL, COMPACTNESS_FACTOR); balloon.AllowOverlaps = (bool)Handler.GetValue(GENERAL, ALLOW_OVERLAPS); balloon.FromSketchMode = (bool)Handler.GetValue(GENERAL, BALLOON_FROM_SKETCH); balloon.ChainStraighteningMode = (bool)Handler.GetValue(GENERAL, STRAIGHTEN_CHAINS); balloon.InterleavedMode = (bool)Handler.GetValue(GENERAL, PLACE_CHILDREN_INTERLEAVED) ? InterleavedMode.AllNodes : InterleavedMode.Off; balloon.IntegratedEdgeLabeling = (bool)Handler.GetValue(LABELING, INTEGRATED_EDGE_LABELING); switch ((string)Handler.GetValue(LABELING, NODE_LABELING_STYLE)) { case NODE_LABELING_STYLE_RAYLIKE_LEAVES: balloon.IntegratedNodeLabeling = true; balloon.NodeLabelingPolicy = NodeLabelingPolicy.RayLikeLeaves; break; case NODE_LABELING_STYLE_CONSIDER_CURRENT_POSITION: balloon.ConsiderNodeLabels = true; break; case NODE_LABELING_STYLE_HORIZONTAL: balloon.IntegratedEdgeLabeling = true; balloon.NodeLabelingPolicy = NodeLabelingPolicy.Horizontal; break; } balloon.SubgraphLayoutEnabled = (bool)Handler.GetValue(GENERAL, ACT_ON_SELECTION_ONLY); multiStageLayout = balloon; LayoutAlgorithm = balloon; }
///<inheritdoc/> protected override void SetupHandler() { CircularLayout layout = new CircularLayout(); BalloonLayout treeLayout = layout.BalloonLayout; OptionGroup generalGroup = Handler.AddGroup(GENERAL); var styleItem = generalGroup.AddList(LAYOUT_STYLE, globalLayoutStyles.Keys, BCC_COMPACT); generalGroup.AddBool(ACT_ON_SELECTION_ONLY, false); generalGroup.AddBool(FROM_SKETCH, false); generalGroup.AddBool(HANDLE_NODE_LABELS, false); OptionGroup cycleGroup = Handler.AddGroup(CYCLE); cycleGroup.AddList(PARTITION_LAYOUT_STYLE, partitionLayoutStyles.Keys, PARTITION_LAYOUTSTYLE_CYCLIC); IOptionItem minDistItem = cycleGroup.AddInt(MINIMAL_NODE_DISTANCE, 30, 0, int.MaxValue); IOptionItem autoRadiusItem = cycleGroup.AddBool(CHOOSE_RADIUS_AUTOMATICALLY, true); IOptionItem fixedRadiusItem = cycleGroup.AddInt(FIXED_RADIUS, 200, 1, int.MaxValue); ConstraintManager cm = new ConstraintManager(Handler); cm.SetEnabledOnValueEquals(autoRadiusItem, true, minDistItem); cm.SetEnabledOnValueEquals(autoRadiusItem, false, fixedRadiusItem); OptionGroup bundlingGroup = Handler.AddGroup(EDGE_BUNDLING); IOptionItem bundlingEnabled = bundlingGroup.AddBool(EDGE_BUNDLING_ENABLED, false); IOptionItem bundlingStrength = bundlingGroup.AddDouble(EDGE_BUNDLING_STRENGTH, 0.95, 0, 1); cm.SetEnabledOnValueEquals(bundlingEnabled, true, bundlingStrength); OptionGroup treeGroup = Handler.AddGroup(TREE); treeGroup.AddInt(PREFERRED_CHILD_WEDGE, treeLayout.PreferredChildWedge, 1, 360); treeGroup.AddInt(MINIMAL_EDGE_LENGTH, treeLayout.MinimumEdgeLength, 1, int.MaxValue); treeGroup.AddInt(MAXIMAL_DEVIATION_ANGLE, layout.MaximumDeviationAngle, 1, 360); treeGroup.AddDouble(COMPACTNESS_FACTOR, treeLayout.CompactnessFactor, 0.1, 0.9); treeGroup.AddInt(MINIMAL_TREE_NODE_DISTANCE, treeLayout.MinimumNodeDistance, 0, int.MaxValue); treeGroup.AddBool(ALLOW_OVERLAPS, treeLayout.AllowOverlaps); treeGroup.AddBool(PLACE_CHILDREN_ON_COMMON_RADIUS, true); cm.SetEnabledOnCondition(ConstraintManager.LogicalCondition.Not(cm.CreateValueEqualsCondition(styleItem, SINGLE_CYCLE)), treeGroup); }
/// <summary> /// Runs a balloon layout where the hierarchy edges are the tree edges and original edges are bundled. /// </summary> private async Task RunBalloonLayout(IListEnumerable <INode> affectedNodes = null) { // create the balloon layout var layout = new BalloonLayout { IntegratedNodeLabeling = true, NodeLabelingPolicy = NodeLabelingPolicy.RayLikeLeaves, FromSketchMode = true, CompactnessFactor = 0.1, AllowOverlaps = true }; // prepend a TreeReduction stage with the hierarchy edges as tree edges layout.PrependStage(new TreeReductionStage()); var nonTreeEdges = GraphControl.Graph.Edges.Where(e => !aggregationHelper.IsHierarchyEdge(e)).ToList(); // mark all other edges to be bundled var bundleDescriptorMap = new ItemMapping <IEdge, EdgeBundleDescriptor>(); foreach (var nonTreeEdge in nonTreeEdges) { bundleDescriptorMap.Mapper[nonTreeEdge] = new EdgeBundleDescriptor { Bundled = true }; } var treeReductionStageData = new TreeReductionStageData { NonTreeEdges = { Items = nonTreeEdges }, EdgeBundleDescriptors = bundleDescriptorMap }; // create a layout executor that also zooms to all nodes that were affected by the last operation var layoutExecutor = new ZoomToNodesLayoutExecutor(affectedNodes ?? ListEnumerable <INode> .Empty, GraphControl, layout) { Duration = TimeSpan.FromSeconds(0.5), AnimateViewport = true, EasedAnimation = true, LayoutData = treeReductionStageData }; await layoutExecutor.Start(); }
///<inheritdoc/> protected override void ConfigureLayout() { CircularLayout layout = new CircularLayout(); ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; BalloonLayout treeLayout = layout.BalloonLayout; layout.LayoutStyle = globalLayoutStyles[(string)Handler.GetValue(GENERAL, LAYOUT_STYLE)]; layout.SubgraphLayoutEnabled = (bool)Handler.GetValue(GENERAL, ACT_ON_SELECTION_ONLY); layout.MaximumDeviationAngle = (int)Handler.GetValue(TREE, MAXIMAL_DEVIATION_ANGLE); layout.FromSketchMode = (bool)Handler.GetValue(GENERAL, FROM_SKETCH); layout.ConsiderNodeLabels = (bool)Handler.GetValue(GENERAL, HANDLE_NODE_LABELS); layout.PartitionStyle = partitionLayoutStyles[(string)Handler.GetValue(CYCLE, PARTITION_LAYOUT_STYLE)]; layout.SingleCycleLayout.MinimumNodeDistance = (int)Handler.GetValue(CYCLE, MINIMAL_NODE_DISTANCE); layout.SingleCycleLayout.AutomaticRadius = (bool)Handler.GetValue(CYCLE, CHOOSE_RADIUS_AUTOMATICALLY); layout.SingleCycleLayout.FixedRadius = (int)Handler.GetValue(CYCLE, FIXED_RADIUS); treeLayout.PreferredChildWedge = ((int)Handler.GetValue(TREE, PREFERRED_CHILD_WEDGE)); treeLayout.MinimumEdgeLength = (int)Handler.GetValue(TREE, MINIMAL_EDGE_LENGTH); treeLayout.CompactnessFactor = (double)Handler.GetValue(TREE, COMPACTNESS_FACTOR); treeLayout.AllowOverlaps = (bool)Handler.GetValue(TREE, ALLOW_OVERLAPS); layout.PlaceChildrenOnCommonRadius = (bool)Handler.GetValue(TREE, PLACE_CHILDREN_ON_COMMON_RADIUS); treeLayout.MinimumNodeDistance = (int)Handler.GetValue(TREE, MINIMAL_TREE_NODE_DISTANCE); // Edge Bundling EdgeBundling ebc = layout.EdgeBundling; EdgeBundleDescriptor descriptor = new EdgeBundleDescriptor(); descriptor.Bundled = (bool)Handler.GetValue(EDGE_BUNDLING, EDGE_BUNDLING_ENABLED); ebc.DefaultBundleDescriptor = descriptor; ebc.BundlingStrength = (double)Handler.GetValue(EDGE_BUNDLING, EDGE_BUNDLING_STRENGTH); LayoutAlgorithm = layout; }
/// <summary> /// Setup default values for various configuration parameters. /// </summary> public BalloonLayoutConfig() { var layout = new BalloonLayout(); RootNodePolicyItem = RootNodePolicy.DirectedRoot; RoutingStyleForNonTreeEdgesItem = EnumRoute.Orthogonal; ActOnSelectionOnlyItem = false; EdgeBundlingStrengthItem = 1; PreferredChildWedgeItem = layout.PreferredChildWedge; PreferredRootWedgeItem = layout.PreferredRootWedge; MinimumEdgeLengthItem = layout.MinimumEdgeLength; CompactnessFactorItem = layout.CompactnessFactor; AllowOverlapsItem = layout.AllowOverlaps; FromSketchItem = layout.FromSketchMode; PlaceChildrenInterleavedItem = layout.InterleavedMode == InterleavedMode.AllNodes; StraightenChainsItem = layout.ChainStraighteningMode; NodeLabelingStyleItem = EnumNodeLabelingPolicies.ConsiderCurrentPosition; EdgeLabelingItem = EnumEdgeLabeling.None; LabelPlacementAlongEdgeItem = EnumLabelPlacementAlongEdge.Centered; LabelPlacementSideOfEdgeItem = EnumLabelPlacementSideOfEdge.OnEdge; LabelPlacementOrientationItem = EnumLabelPlacementOrientation.Horizontal; LabelPlacementDistanceItem = 10; }
/// <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); }