/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var labeling = new GenericLabeling(); labeling.AutoFlipping = true; labeling.OptimizationStrategy = OptimizationStrategyItem; if (labeling.OptimizationStrategy == OptimizationStrategy.None) { labeling.ProfitModel = new SimpleProfitModel(); } labeling.RemoveNodeOverlaps = !AllowNodeOverlapsItem; labeling.RemoveEdgeOverlaps = !AllowEdgeOverlapsItem; labeling.PlaceEdgeLabels = PlaceEdgeLabelsItem; labeling.PlaceNodeLabels = PlaceNodeLabelsItem; labeling.ReduceAmbiguity = ReduceAmbiguityItem; var selectionOnly = ConsiderSelectedFeaturesOnlyItem; labeling.AffectedLabelsDpKey = null; if (graphControl.Selection != null && selectionOnly) { labeling.AffectedLabelsDpKey = SelectedLabelsKey; } return(labeling); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var labeling = new GenericLabeling(); labeling.AutoFlipping = true; labeling.OptimizationStrategy = OptimizationStrategyItem; if (labeling.OptimizationStrategy == OptimizationStrategy.None) { labeling.ProfitModel = new SimpleProfitModel(); } labeling.RemoveNodeOverlaps = !AllowNodeOverlapsItem; labeling.RemoveEdgeOverlaps = !AllowEdgeOverlapsItem; labeling.PlaceEdgeLabels = PlaceEdgeLabelsItem; labeling.PlaceNodeLabels = PlaceNodeLabelsItem; labeling.ReduceAmbiguity = ReduceAmbiguityItem; var selectionOnly = ConsiderSelectedFeaturesOnlyItem; labeling.AffectedLabelsDpKey = null; ILayoutAlgorithm layout = labeling; if (graphControl.Selection != null && selectionOnly) { labeling.AffectedLabelsDpKey = SelectedLabelsStage.ProviderKey; layout = new SelectedLabelsStage(labeling); } AddPreferredPlacementDescriptor(graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem); SetupEdgeLabelModels(graphControl); return(layout); }
/// <summary> /// Removes all edges that are incident to group nodes and passes it to the core layout algorithm. /// </summary> /// <remarks> /// This stage removes some edges from the graph such that no edges incident to group nodes /// exist. Then, it applies the core layout algorithm to the reduced graph. /// After it produces the result, it re-inserts the previously removed edges and routes them. /// </remarks> public override void ApplyLayout(LayoutGraph graph) { var groupingSupport = new yWorks.Layout.Grouping.GroupingSupport(graph); if (!GroupingSupport.IsGrouped(graph)) { ApplyLayoutCore(graph); } else { var hiddenEdgesMap = Maps.CreateHashedEdgeMap(); var edgeHider = new LayoutGraphHider(graph); var existHiddenEdges = false; foreach (var edge in graph.Edges) { if (groupingSupport.IsGroupNode(edge.Source) || groupingSupport.IsGroupNode(edge.Target)) { hiddenEdgesMap.Set(edge, true); edgeHider.Hide(edge); existHiddenEdges = true; } else { hiddenEdgesMap.Set(edge, false); } } ApplyLayoutCore(graph); if (existHiddenEdges) { edgeHider.UnhideAll(); // routes the marked edges RouteMarkedEdges(graph, hiddenEdgesMap); if (ConsiderEdgeLabels) { // all labels of hidden edges should be marked var affectedLabelsDpKey = "affectedLabelsDpKey"; var nonTreeLabelsMap = Maps.CreateHashedDataMap(); foreach (var edge in graph.Edges) { var ell = graph.GetLabelLayout(edge); foreach (var labelLayout in ell) { nonTreeLabelsMap.Set(labelLayout, hiddenEdgesMap.Get(edge)); } } // add selection marker graph.AddDataProvider(affectedLabelsDpKey, nonTreeLabelsMap); // place marked labels var labeling = new GenericLabeling { PlaceNodeLabels = false, PlaceEdgeLabels = true, AffectedLabelsDpKey = affectedLabelsDpKey, }; labeling.ApplyLayout(graph); // dispose selection key graph.RemoveDataProvider(affectedLabelsDpKey); } } } }
///<inheritdoc/> protected override void PerformPreLayout() { String selGroupPolicy = (String)Handler.GetValue(GROUPING, GROUP_LAYOUT_POLICY); String edgeLabelingName = (String)Handler.GetValue(LABELING, EDGE_LABELING); MultiStageLayout multiStageLayout = LayoutAlgorithm as MultiStageLayout; IDataProvider upwardDP = null; if ((upwardDP = CurrentLayoutGraph.GetDataProvider(OrthogonalLayout.DirectedEdgeDpKey)) == null) { //determine upward edges if not already marked. if ((bool)Handler.GetValue(EDGES, DRAW_SELECTED_EDGES_UPWARDS)) { CurrentLayoutGraph.AddDataProvider(OrthogonalLayout.DirectedEdgeDpKey, upwardDP = new UpwardEdgeDP(this)); } } // if ((bool)Handler.GetValue(EDGES, UPWARD_EDGE_BUS_ROUTING) && upwardDP != null) { // sgDPOrig = CurrentLayoutGraph.GetDataProvider(PortConstraintKeys.SourceGroupIdDpKey); // tgDPOrig = CurrentLayoutGraph.GetDataProvider(PortConstraintKeys.TargetGroupIdDpKey); // sourceGroupMap = CurrentLayoutGraph.CreateEdgeMap(); // tgMap = CurrentLayoutGraph.CreateEdgeMap(); // CurrentLayoutGraph.AddDataProvider(PortConstraintKeys.SourceGroupIdDpKey, sourceGroupMap); // CurrentLayoutGraph.AddDataProvider(PortConstraintKeys.TargetGroupIdDpKey, tgMap); // AutoGroupEdges(CurrentLayoutGraph, sourceGroupMap, tgMap, upwardDP); // } if ((selGroupPolicy != IGNORE_GROUPS) && ContainsGroupNodes()) { multiStageLayout.HideGroupsStageEnabled = false; if (FIX_GROUPS == selGroupPolicy) { var fgl = new FixGroupLayoutStage(); fgl.InterEdgeRoutingStyle = InterEdgeRoutingStyle.Orthogonal; if (multiStageLayout != null) { multiStageLayout.PrependStage(fgl); preStage = fgl; } } } else { multiStageLayout.HideGroupsStageEnabled = true; } if (edgeLabelingName == GENERIC && multiStageLayout != null) { var la = new GenericLabeling(); la.MaximumDuration = 0; la.PlaceNodeLabels = false; la.PlaceEdgeLabels = true; la.AutoFlipping = true; la.ProfitModel = new SimpleProfitModel(); multiStageLayout.Labeling = la; } }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var router = new EdgeRouter(); router.Scope = ScopeItem; router.MinimumNodeToEdgeDistance = MinimumNodeToEdgeDistanceItem; if (GridEnabledItem) { router.Grid = new Grid(0, 0, GridSpacingItem); } else { router.Grid = null; } router.ConsiderNodeLabels = ConsiderNodeLabelsItem; router.ConsiderEdgeLabels = ConsiderEdgeLabelsItem; router.Rerouting = EnableReroutingItem; // Note that CreateConfiguredLayoutData replaces the settings on the DefaultEdgeLayoutDescriptor // by providing a custom one for each edge. router.DefaultEdgeLayoutDescriptor.RoutingStyle = EdgeRoutingStyleItem; router.DefaultEdgeLayoutDescriptor.PreferredOctilinearSegmentLength = PreferredOctilinearSegmentLengthItem; router.DefaultEdgeLayoutDescriptor.MaximumOctilinearSegmentRatio = MaximumOctilinearSegmentRatioItem; router.DefaultEdgeLayoutDescriptor.SourceCurveConnectionStyle = SourceConnectionStyleItem; router.DefaultEdgeLayoutDescriptor.TargetCurveConnectionStyle = TargetConnectionStyleItem; router.MaximumDuration = MaximumDurationItem * 1000; var layout = new SequentialLayout(); layout.AppendLayout(router); if (EdgeLabelingItem == EnumEdgeLabeling.None) { router.IntegratedEdgeLabeling = false; } else if (EdgeLabelingItem == EnumEdgeLabeling.Integrated) { router.IntegratedEdgeLabeling = true; } else if (EdgeLabelingItem == EnumEdgeLabeling.Generic) { var genericLabeling = new GenericLabeling(); genericLabeling.PlaceEdgeLabels = true; genericLabeling.PlaceNodeLabels = false; genericLabeling.ReduceAmbiguity = ReduceAmbiguityItem; layout.AppendLayout(genericLabeling); } AddPreferredPlacementDescriptor(graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem); return(layout); }
private void ApplyLabeling(LayoutGraph graph) { GenericLabeling labeling = new GenericLabeling(); labeling.MaximumDuration = 0; labeling.ReduceAmbiguity = true; labeling.PlaceNodeLabels = true; labeling.PlaceEdgeLabels = true; labeling.AffectedLabelsDpKey = AffectedLabelsDpKey; labeling.ProfitModel = new BpmnLabelProfitModel(graph); labeling.CustomProfitModelRatio = 0.15; labeling.ApplyLayout(graph); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new CircularLayout(); var balloonLayout = layout.BalloonLayout; layout.LayoutStyle = LayoutStyleItem; layout.EdgeRoutingPolicy = EdgeRoutingPolicyItem; layout.ExteriorEdgeLayoutDescriptor.CircleDistance = CircleDistanceItem; layout.ExteriorEdgeLayoutDescriptor.EdgeToEdgeDistance = EdgeToEdgeDistanceItem; layout.ExteriorEdgeLayoutDescriptor.PreferredAngle = PreferredAngleItem; layout.ExteriorEdgeLayoutDescriptor.PreferredCurveLength = PreferredCurveLengthItem; layout.ExteriorEdgeLayoutDescriptor.Smoothness = SmoothnessItem; layout.SubgraphLayoutEnabled = ActOnSelectionOnlyItem; layout.MaximumDeviationAngle = MaximumDeviationAngleItem; layout.FromSketchMode = FromSketchItem; layout.ConsiderNodeLabels = HandleNodeLabelsItem; layout.PartitionStyle = PartitionStyleItem; layout.SingleCycleLayout.MinimumNodeDistance = MinimumNodeDistanceItem; layout.SingleCycleLayout.AutomaticRadius = ChooseRadiusAutomaticallyItem; layout.SingleCycleLayout.FixedRadius = FixedRadiusItem; balloonLayout.PreferredChildWedge = PreferredChildWedgeItem; balloonLayout.MinimumEdgeLength = MinimumEdgeLengthItem; balloonLayout.CompactnessFactor = CompactnessFactorItem; balloonLayout.AllowOverlaps = AllowOverlapsItem; layout.PlaceChildrenOnCommonRadius = PlaceChildrenOnCommonRadiusItem; balloonLayout.MinimumNodeDistance = MinimumTreeNodeDistanceItem; if (EdgeLabelingItem) { var genericLabeling = new GenericLabeling(); genericLabeling.PlaceEdgeLabels = true; genericLabeling.PlaceNodeLabels = false; genericLabeling.ReduceAmbiguity = ReduceAmbiguityItem; layout.LabelingEnabled = true; layout.Labeling = genericLabeling; } var ebc = layout.EdgeBundling; var bundlingDescriptor = new EdgeBundleDescriptor(); bundlingDescriptor.Bundled = EdgeBundlingItem; ebc.BundlingStrength = EdgeBundlingStrengthItem; ebc.DefaultBundleDescriptor = bundlingDescriptor; AddPreferredPlacementDescriptor(graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem); return(layout); }
/// <summary> /// Runs an organic layout with edge labeling. /// </summary> private void RunLayout() { var genericLabeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, ReduceAmbiguity = true }; var layout = new OrganicLayout { MinimumNodeDistance = 60, NodeEdgeOverlapAvoided = true, LabelingEnabled = true, Labeling = genericLabeling }; graphControl.MorphLayout(layout, TimeSpan.FromSeconds(1)); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new OrganicLayout(); layout.PreferredEdgeLength = PreferredEdgeLengthItem; layout.ConsiderNodeLabels = ConsiderNodeLabelsItem; layout.NodeOverlapsAllowed = AllowNodeOverlapsItem; layout.MinimumNodeDistance = MinimumNodeDistanceItem; layout.Scope = ScopeItem; layout.CompactnessFactor = CompactnessItem; layout.ConsiderNodeSizes = true; layout.ClusterNodes = UseAutoClusteringItem; layout.ClusteringQuality = AutoClusteringQualityItem; layout.NodeEdgeOverlapAvoided = AvoidNodeEdgeOverlapsItem; layout.Deterministic = ActivateDeterministicModeItem; layout.MaximumDuration = 1000 * MaximumDurationItem; layout.QualityTimeRatio = QualityTimeRatioItem; if (EdgeLabelingItem) { var genericLabeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, ReduceAmbiguity = ReduceAmbiguityItem }; layout.LabelingEnabled = true; layout.Labeling = genericLabeling; } ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; ConfigureOutputRestrictions(graphControl, layout); layout.ChainSubstructureStyle = ChainSubstructureStyleItem; layout.CycleSubstructureStyle = CycleSubstructureStyleItem; layout.StarSubstructureStyle = StarSubstructureStyleItem; layout.ParallelSubstructureStyle = ParallelSubstructureStyleItem; if (UseEdgeGroupingItem) { graphControl.Graph.MapperRegistry.CreateConstantMapper <IEdge, object>(PortConstraintKeys.SourceGroupIdDpKey, "Group"); graphControl.Graph.MapperRegistry.CreateConstantMapper <IEdge, object>(PortConstraintKeys.TargetGroupIdDpKey, "Group"); } AddPreferredPlacementDescriptor(graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem); return(layout); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new OrganicLayout(); layout.PreferredEdgeLength = PreferredEdgeLengthItem; layout.ConsiderNodeLabels = ConsiderNodeLabelsItem; layout.NodeOverlapsAllowed = AllowNodeOverlapsItem; layout.MinimumNodeDistance = MinimumNodeDistanceItem; layout.Scope = ScopeItem; layout.CompactnessFactor = CompactnessItem; layout.ConsiderNodeSizes = true; layout.ClusteringPolicy = ClusteringPolicyItem; layout.ClusteringQuality = ClusteringQualityItem; layout.NodeEdgeOverlapAvoided = AvoidNodeEdgeOverlapsItem; layout.Deterministic = ActivateDeterministicModeItem; layout.MaximumDuration = 1000 * MaximumDurationItem; layout.QualityTimeRatio = QualityTimeRatioItem; if (EdgeLabelingItem) { var genericLabeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, ReduceAmbiguity = ReduceAmbiguityItem }; layout.LabelingEnabled = true; layout.Labeling = genericLabeling; } ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; ConfigureOutputRestrictions(graphControl, layout); layout.ChainSubstructureStyle = ChainSubstructureStyleItem; layout.CycleSubstructureSize = CycleSubstructureSizeItem; layout.CycleSubstructureStyle = CycleSubstructureStyleItem; layout.ChainSubstructureSize = ChainSubstructureSizeItem; layout.StarSubstructureStyle = StarSubstructureStyleItem; layout.StarSubstructureSize = StarSubstructureSizeItem; layout.ParallelSubstructureStyle = ParallelSubstructureStyleItem; layout.ParallelSubstructureSize = ParallelSubstructureSizeItem; return(layout); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new RadialLayout(); layout.MinimumNodeToNodeDistance = MinimumNodeToNodeDistanceItem; if (EdgeRoutingStrategyItem != EdgeRoutingStyle.Bundled) { layout.EdgeRoutingStrategy = (EdgeRoutingStrategy)EdgeRoutingStrategyItem; } var minimumBendAngle = 1 + (MaximumSmoothness - EdgeSmoothnessItem) * SmoothnessAngleFactor; layout.MinimumBendAngle = minimumBendAngle; layout.MinimumLayerDistance = MinimumLayerDistanceItem; layout.MaximumChildSectorAngle = MaximumChildSectorSizeItem; layout.CenterNodesPolicy = CenterStrategyItem; layout.LayeringStrategy = LayeringStrategyItem; layout.ConsiderNodeLabels = ConsiderNodeLabelsItem; var ebc = layout.EdgeBundling; ebc.BundlingStrength = EdgeBundlingStrengthItem; ebc.DefaultBundleDescriptor = new EdgeBundleDescriptor { Bundled = EdgeRoutingStrategyItem == EdgeRoutingStyle.Bundled }; if (EdgeLabelingItem) { var labeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false }; layout.LabelingEnabled = true; layout.Labeling = labeling; } AddPreferredPlacementDescriptor(graphControl.Graph, LabelPlacementAlongEdgeItem, LabelPlacementSideOfEdgeItem, LabelPlacementOrientationItem, LabelPlacementDistanceItem); return(layout); }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = ConfigureClassicLayout(); layout.ParallelEdgeRouterEnabled = false; ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.MultiRows; layout.SubgraphLayoutEnabled = ActOnSelectionOnlyItem; layout.PrependStage(CreateTreeReductionStage()); var placeLabels = EdgeLabelingItem == EnumEdgeLabeling.Integrated || EdgeLabelingItem == EnumEdgeLabeling.Generic; // required to prevent WrongGraphStructure exception which may be thrown by TreeLayout if there are edges // between group nodes layout.PrependStage(new HandleEdgesBetweenGroupsStage(placeLabels)); layout.ConsiderNodeLabels = this.ConsiderNodeLabelsItem; if (EdgeLabelingItem == EnumEdgeLabeling.Generic) { layout.IntegratedEdgeLabeling = false; var labeling = new GenericLabeling(); labeling.PlaceEdgeLabels = true; labeling.PlaceNodeLabels = false; labeling.ReduceAmbiguity = ReduceAmbiguityItem; layout.LabelingEnabled = true; layout.Labeling = labeling; } else if (EdgeLabelingItem == EnumEdgeLabeling.Integrated) { layout.IntegratedEdgeLabeling = true; } return(layout); }
///<inheritdoc/> protected override void ConfigureLayout() { labeler = new GenericLabeling(); if (!(bool)Handler.GetValue(QUALITY, USE_OPTIMIZATION)) { labeler.MaximumDuration = 0; } labeler.AutoFlipping = true; labeler.OptimizationStrategy = (OptimizationStrategy)Handler.GetValue(QUALITY, OPTIMIZATION_STRATEGY); if (labeler.OptimizationStrategy == OptimizationStrategy.None) { labeler.ProfitModel = new SimpleProfitModel(); } labeler.RemoveNodeOverlaps = !(bool)Handler.GetValue(QUALITY, ALLOW_NODE_OVERLAPS); labeler.RemoveEdgeOverlaps = !(bool)Handler.GetValue(QUALITY, ALLOW_EDGE_OVERLAPS); labeler.PlaceEdgeLabels = (bool)Handler.GetValue(SCOPE, PLACE_EDGE_LABELS); labeler.PlaceNodeLabels = (bool)Handler.GetValue(SCOPE, PLACE_NODE_LABELS); bool selectionOnly = (bool)Handler.GetValue(SCOPE, CONSIDER_SELECTED_FEATURES_ONLY); labeler.AffectedLabelsDpKey = null; LayoutAlgorithm = labeler; var graph = this.Context.SafeLookup <IGraph>(); string edgeLabelingName = (string)Handler.GetValue(MODEL, EDGE_LABEL_MODEL); SetupEdgeLabelModels(graph, edgeLabelingName); var graphSelection = Context.Lookup <ISelectionModel <IModelItem> >(); if (graphSelection != null && selectionOnly) { labeler.AffectedLabelsDpKey = SelectedLabelsStage.ProviderKey; LayoutAlgorithm = new SelectedLabelsStage(labeler); } }
/// <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); }
/// <summary> /// Does the label placement using the generic labeling algorithm. Before this, the model and size of the labels is /// set according to the option handlers settings. /// </summary> private async Task DoLabelPlacement() { if (inLayout) { return; } inLayout = true; toolBar.IsEnabled = false; editorControl.IsEnabled = false; //desired label model ILabelModel labelModel = LabelModels[(string)handler[LABEL_MODEL].Value]; int size = (int)handler[LABEL_SIZE].Value; foreach (var label in graphControl.Graph.Labels) { if (label.Owner is INode) { // only update the label model parameter if the label model changed if (labelModel != graphControl.Graph.NodeDefaults.Labels.LayoutParameter.Model) { graphControl.Graph.SetLabelLayoutParameter(label, labelModel.CreateDefaultParameter()); } var cityLabelStyle = label.Style as CityLabelStyle; if (cityLabelStyle != null && cityLabelStyle.InnerLabelStyle is DefaultLabelStyle) { ((DefaultLabelStyle)cityLabelStyle.InnerLabelStyle).TextSize = size; } graphControl.Graph.AdjustLabelPreferredSize(label); } } { // set as default label model parameter graphControl.Graph.NodeDefaults.Labels.LayoutParameter = labelModel.CreateDefaultParameter(); var cityLabelStyle = graphControl.Graph.NodeDefaults.Labels.Style as CityLabelStyle; if (cityLabelStyle != null && cityLabelStyle.InnerLabelStyle is DefaultLabelStyle) { ((DefaultLabelStyle)cityLabelStyle.InnerLabelStyle).TextSize = size; } } graphControl.Invalidate(); // configure and run the layout algorithm var labelingAlgorithm = new GenericLabeling { MaximumDuration = 0, OptimizationStrategy = OptimizationStrategy.Balanced, PlaceEdgeLabels = false, PlaceNodeLabels = true, ReduceLabelOverlaps = true, ProfitModel = new ExtendedLabelCandidateProfitModel(), }; var layoutExecutor = new LayoutExecutor(graphControl, graphControl.Graph, labelingAlgorithm) { Duration = TimeSpan.FromMilliseconds(500), EasedAnimation = true, AnimateViewport = false, UpdateContentRect = true }; await layoutExecutor.Start(); toolBar.IsEnabled = true; editorControl.IsEnabled = true; inLayout = false; }
/// <inheritdoc /> protected override ILayoutAlgorithm CreateConfiguredLayout(GraphControl graphControl) { var layout = new HierarchicLayout(); // mark incremental elements if required var fromSketch = UseDrawingAsSketchItem; var incrementalLayout = SelectedElementsIncrementallyItem; var selectedElements = graphControl.Selection.SelectedEdges.Any() || graphControl.Selection.SelectedNodes.Any(); if (incrementalLayout && selectedElements) { layout.LayoutMode = LayoutMode.Incremental; } else if (fromSketch) { layout.LayoutMode = LayoutMode.Incremental; } else { layout.LayoutMode = LayoutMode.FromScratch; } ((SimplexNodePlacer)layout.NodePlacer).BarycenterMode = SymmetricPlacementItem; layout.ComponentLayoutEnabled = LayoutComponentsSeparatelyItem; layout.MinimumLayerDistance = MinimumLayerDistanceItem; layout.NodeToEdgeDistance = NodeToEdgeDistanceItem; layout.NodeToNodeDistance = NodeToNodeDistanceItem; layout.EdgeToEdgeDistance = EdgeToEdgeDistanceItem; var nld = layout.NodeLayoutDescriptor; var eld = layout.EdgeLayoutDescriptor; layout.AutomaticEdgeGrouping = AutomaticEdgeGroupingEnabledItem; eld.RoutingStyle = new RoutingStyle(EdgeRoutingItem); eld.RoutingStyle.CurveShortcuts = CurveShortcutsItem; eld.RoutingStyle.CurveUTurnSymmetry = CurveUTurnSymmetryItem; eld.MinimumFirstSegmentLength = MinimumFirstSegmentLengthItem; eld.MinimumLastSegmentLength = MinimumLastSegmentLengthItem; eld.MinimumDistance = MinimumEdgeDistanceItem; eld.MinimumLength = MinimumEdgeLengthItem; eld.MinimumSlope = MinimumSlopeItem; eld.SourcePortOptimization = PcOptimizationEnabledItem; eld.TargetPortOptimization = PcOptimizationEnabledItem; eld.RecursiveEdgeStyle = RecursiveEdgeStyleItem; nld.MinimumDistance = Math.Min(layout.NodeToNodeDistance, layout.NodeToEdgeDistance); nld.MinimumLayerHeight = 0; nld.LayerAlignment = LayerAlignmentItem; var ol = (OrientationLayout)layout.OrientationLayout; ol.Orientation = OrientationItem; if (ConsiderNodeLabelsItem) { layout.ConsiderNodeLabels = true; layout.NodeLayoutDescriptor.NodeLabelMode = NodeLabelMode.ConsiderForDrawing; } else { layout.ConsiderNodeLabels = false; } if (EdgeLabelingItem != EnumEdgeLabeling.None) { if (EdgeLabelingItem == EnumEdgeLabeling.Generic) { layout.IntegratedEdgeLabeling = false; var labeling = new GenericLabeling { PlaceNodeLabels = false, PlaceEdgeLabels = true, AutoFlipping = true, ReduceAmbiguity = ReduceAmbiguityItem, ProfitModel = new SimpleProfitModel(), }; layout.LabelingEnabled = true; layout.Labeling = labeling; } else if (EdgeLabelingItem == EnumEdgeLabeling.Integrated) { layout.IntegratedEdgeLabeling = true; ((SimplexNodePlacer)layout.NodePlacer).LabelCompaction = CompactEdgeLabelPlacementItem; } } else { layout.IntegratedEdgeLabeling = false; } layout.FromScratchLayeringStrategy = RankingPolicyItem; layout.ComponentArrangementPolicy = ComponentArrangementPolicyItem; ((SimplexNodePlacer)layout.NodePlacer).NodeCompaction = NodeCompactionItem; ((SimplexNodePlacer)layout.NodePlacer).StraightenEdges = StraightenEdgesItem; //configure AsIsLayerer var layerer = layout.LayoutMode == LayoutMode.FromScratch ? layout.FromScratchLayerer : layout.FixedElementsLayerer; var ail = layerer as AsIsLayerer; if (ail != null) { ail.NodeHalo = HaloItem; ail.NodeScalingFactor = ScaleItem; ail.MinimumNodeSize = MinimumSizeItem; ail.MaximumNodeSize = MaximumSizeItem; } //configure grouping ((SimplexNodePlacer)layout.NodePlacer).GroupCompactionStrategy = GroupHorizontalCompactionItem; if (!fromSketch && GroupLayeringStrategyItem == GroupLayeringStrategyOptions.LayoutGroups) { layout.GroupAlignmentPolicy = GroupAlignmentItem; layout.CompactGroups = GroupEnableCompactionItem; layout.RecursiveGroupLayering = true; } else { layout.RecursiveGroupLayering = false; } if (TreatRootGroupAsSwimlanesItem) { var stage = new TopLevelGroupToSwimlaneStage { OrderSwimlanesFromSketch = UseOrderFromSketchItem, Spacing = SwimlineSpacingItem }; layout.AppendStage(stage); } layout.BackLoopRouting = BackloopRoutingItem; layout.BackLoopRoutingForSelfLoops = BackloopRoutingForSelfLoopsItem; layout.MaximumDuration = MaximumDurationItem * 1000; if (GridEnabledItem) { layout.GridSpacing = GridSpacingItem; } return(layout); }
/// <summary> /// Run a layout and an analysis algorithm if wanted. /// </summary> /// <param name="incremental">Whether to run in incremental mode, i.e. only moving new items.</param> /// <param name="clearUndo">Whether to clear the undo queue after the layout.</param> /// <param name="runAlgorithm">Whether to apply the <see cref="CurrentConfig">current analysis algorithm</see>, too.</param> /// <returns></returns> private async Task RunLayout(bool incremental, bool clearUndo, bool runAlgorithm) { // the actual organic layout var layout = new OrganicLayout { Deterministic = true, ConsiderNodeSizes = true, Scope = incremental ? Scope.MainlySubset : Scope.All, LabelingEnabled = false, PreferredEdgeLength = 100, MinimumNodeDistance = 10 }; ((ComponentLayout)layout.ComponentLayout).Style = ComponentArrangementStyles.None | ComponentArrangementStyles.ModifierNoOverlap; OrganicLayoutData layoutData = null; if (incremental && incrementalNodesMapper != null) { layoutData = new OrganicLayoutData(); layoutData.AffectedNodes.Mapper = incrementalNodesMapper; } inLayout = true; SetUiDisabled(true); // run the layout in an asynchronous, animated fashion await graphControl.MorphLayout(layout, TimeSpan.FromSeconds(0.5), layoutData); // run algorithm if (runAlgorithm) { // apply graph algorithms after layout ApplyAlgorithm(); var algorithm = algorithmComboBox.SelectedItem as Algorithm; if (algorithm != null && algorithm.DisplayName.EndsWith("Centrality")) { // since centrality changes the node sizes, node overlaps need to be removed await graphControl.MorphLayout(new OrganicRemoveOverlapsStage(), TimeSpan.FromSeconds(0.2)); } } // labeling: place labels after the layout and the analysis (which might have generated or changed labels) var labeling = new GenericLabeling { PlaceEdgeLabels = true, PlaceNodeLabels = false, Deterministic = true }; var labelingData = new LabelingData { EdgeLabelPreferredPlacement = { Delegate = label => { var preferredPlacementDescriptor = new PreferredPlacementDescriptor(); if ("Centrality".Equals(label.Tag)) { preferredPlacementDescriptor.SideOfEdge = LabelPlacements.OnEdge; } else { preferredPlacementDescriptor.SideOfEdge = LabelPlacements.RightOfEdge | LabelPlacements.LeftOfEdge; preferredPlacementDescriptor.DistanceToEdge = 5; } preferredPlacementDescriptor.Freeze(); return(preferredPlacementDescriptor); } } }; await graphControl.MorphLayout(labeling, TimeSpan.FromSeconds(0.2), labelingData); // cleanup if (clearUndo) { graphControl.Graph.GetUndoEngine().Clear(); } // clean up data provider incrementalNodesMapper.Clear(); // enable the UI's buttons ReleaseLocks(); SetUiDisabled(false); UpdateUiState(); }
/// <summary> /// Does the label placement using the generic labeling algorithm. Before this, the model and size of the labels is /// set according to the option handlers settings. /// </summary> private async Task DoLabelPlacement() { if (inLayout) { return; } inLayout = true; toolStrip.Enabled = false; //desired label model ILabelModel labelModel = LabelModels[labelModelComboBox.SelectedItem.ToString()]; //desired label size int size = Convert.ToInt32(sizeNumericUpDown.NumericUpDownControl.Text); foreach (var label in graphControl.Graph.Labels) { if (label.Owner is INode) { // only update the label model parameter if the label model changed if (labelModel != graphControl.Graph.NodeDefaults.Labels.LayoutParameter.Model) { graphControl.Graph.SetLabelLayoutParameter(label, labelModel.CreateDefaultParameter()); } var cityLabelStyle = label.Style as CityLabelStyle; if (cityLabelStyle != null && cityLabelStyle.InnerLabelStyle is DefaultLabelStyle) { var font = ((DefaultLabelStyle)cityLabelStyle.InnerLabelStyle).Font; ((DefaultLabelStyle)cityLabelStyle.InnerLabelStyle).Font = new Font(font.FontFamily, size); } graphControl.Graph.AdjustLabelPreferredSize(label); } } { // set as default label model parameter graphControl.Graph.NodeDefaults.Labels.LayoutParameter = labelModel.CreateDefaultParameter(); var cityLabelStyle = graphControl.Graph.NodeDefaults.Labels.Style as CityLabelStyle; if (cityLabelStyle != null && cityLabelStyle.InnerLabelStyle is DefaultLabelStyle) { var font = ((DefaultLabelStyle)cityLabelStyle.InnerLabelStyle).Font; ((DefaultLabelStyle)cityLabelStyle.InnerLabelStyle).Font = new Font(font.FontFamily, size); } } graphControl.Invalidate(); // configure and run the layout algorithm var labelingAlgorithm = new GenericLabeling { MaximumDuration = 0, OptimizationStrategy = OptimizationStrategy.Balanced, PlaceEdgeLabels = false, PlaceNodeLabels = true, ReduceLabelOverlaps = true, ProfitModel = new ExtendedLabelCandidateProfitModel(), }; var layoutExecutor = new LayoutExecutor(graphControl, graphControl.Graph, labelingAlgorithm) { Duration = TimeSpan.FromMilliseconds(500), EasedAnimation = true, AnimateViewport = false, UpdateContentRect = true }; await layoutExecutor.Start(); toolStrip.Enabled = true; inLayout = false; }
///<inheritdoc/> protected override void ConfigureLayout() { LayoutGraph graph = CurrentLayoutGraph; HierarchicLayout hl = new HierarchicLayout(); LayoutAlgorithm = hl; // mark incremental elements if required IDataMap incrementalElements; OptionGroup generalGroup = (OptionGroup)Handler.GetGroupByName(GENERAL); OptionGroup currentGroup = (OptionGroup)generalGroup.GetGroupByName(INTERACTION); OptionGroup groupingGroup = (OptionGroup)Handler.GetGroupByName(GROUPING); bool fromSketch = (bool)currentGroup[USE_DRAWING_AS_SKETCH].Value; bool incrementalLayout = (bool)currentGroup[SELECTED_ELEMENTS_INCREMENTALLY].Value; bool selectedElements = !IsEdgeSelectionEmpty() || !IsNodeSelectionEmpty(); if (incrementalLayout && selectedElements) { // create storage for both nodes and edges incrementalElements = Maps.CreateHashedDataMap(); // configure the mode hl.LayoutMode = LayoutMode.Incremental; IIncrementalHintsFactory ihf = hl.CreateIncrementalHintsFactory(); foreach (Node node in graph.Nodes) { if (IsSelected(node)) { incrementalElements.Set(node, ihf.CreateLayerIncrementallyHint(node)); } } foreach (Edge edge in graph.Edges) { if (IsSelected(edge)) { incrementalElements.Set(edge, ihf.CreateSequenceIncrementallyHint(edge)); } } graph.AddDataProvider(HierarchicLayout.IncrementalHintsDpKey, incrementalElements); } else if (fromSketch) { hl.LayoutMode = LayoutMode.Incremental; } else { hl.LayoutMode = LayoutMode.FromScratch; } // cast to implementation simplex var np = (SimplexNodePlacer)hl.NodePlacer; np.BarycenterMode = (bool)generalGroup[SYMMETRIC_PLACEMENT].Value; np.StraightenEdges = (bool)Handler.GetValue(EDGE_SETTINGS, EDGE_STRAIGHTENING_OPTIMIZATION_ENABLED); hl.ComponentLayoutEnabled = (bool)generalGroup[LAYOUT_COMPONENTS_SEPARATELY].Value; currentGroup = (OptionGroup)generalGroup.GetGroupByName(MINIMUM_DISTANCES); hl.MinimumLayerDistance = (double)currentGroup[MINIMUM_LAYER_DISTANCE].Value; hl.NodeToEdgeDistance = (double)currentGroup[NODE_TO_EDGE_DISTANCE].Value; hl.NodeToNodeDistance = (double)currentGroup[NODE_TO_NODE_DISTANCE].Value; hl.EdgeToEdgeDistance = (double)currentGroup[EDGE_TO_EDGE_DISTANCE].Value; NodeLayoutDescriptor nld = hl.NodeLayoutDescriptor; EdgeLayoutDescriptor eld = hl.EdgeLayoutDescriptor; currentGroup = (OptionGroup)Handler.GetGroupByName(EDGE_SETTINGS); hl.AutomaticEdgeGrouping = (bool)currentGroup[AUTOMATIC_EDGE_GROUPING_ENABLED].Value; string edgeRoutingChoice = (string)currentGroup[EDGE_ROUTING].Value; eld.RoutingStyle = edgeRoutingEnum[edgeRoutingChoice]; eld.MinimumFirstSegmentLength = (double)currentGroup[MINIMUM_FIRST_SEGMENT_LENGTH].Value; eld.MinimumLastSegmentLength = (double)currentGroup[MINIMUM_LAST_SEGMENT_LENGTH].Value; eld.MinimumDistance = (double)currentGroup[MINIMUM_EDGE_DISTANCE].Value; eld.MinimumLength = (double)currentGroup[MINIMUM_EDGE_LENGTH].Value; eld.MinimumSlope = (double)currentGroup[MINIMUM_SLOPE].Value; eld.SourcePortOptimization = (bool)currentGroup[PC_OPTIMIZATION_ENABLED].Value; eld.TargetPortOptimization = (bool)currentGroup[PC_OPTIMIZATION_ENABLED].Value; var isIncrementalModeEnabled = (fromSketch || (incrementalLayout && selectedElements)); var recursiveRoutingMode = Handler.GetValue(EDGE_SETTINGS, RECURSIVE_EDGE_ROUTING); if (!isIncrementalModeEnabled && recursiveRoutingMode == RECURSIVE_EDGE_ROUTING_DIRECTED) { eld.RecursiveEdgeStyle = RecursiveEdgeStyle.Directed; } else if (!isIncrementalModeEnabled && recursiveRoutingMode == RECURSIVE_EDGE_ROUTING_UNDIRECTED) { eld.RecursiveEdgeStyle = RecursiveEdgeStyle.Undirected; } else { eld.RecursiveEdgeStyle = RecursiveEdgeStyle.Off; } nld.MinimumDistance = Math.Min(hl.NodeToNodeDistance, hl.NodeToEdgeDistance); nld.MinimumLayerHeight = 0; OptionGroup rankGroup = (OptionGroup)Handler.GetGroupByName(RANKS); string layerAlignmentChoice = (string)rankGroup[LAYER_ALIGNMENT].Value; nld.LayerAlignment = alignmentEnum[layerAlignmentChoice]; ol = (OrientationLayout)hl.OrientationLayout; string orientationChoice = (string)generalGroup[ORIENTATION].Value; ol.Orientation = orientEnum[orientationChoice]; OptionGroup labelingGroup = (OptionGroup)Handler.GetGroupByName(LABELING); currentGroup = (OptionGroup)labelingGroup.GetGroupByName(LABELING_EDGE_PROPERTIES); string el = (string)currentGroup[EDGE_LABELING].Value; if (!el.Equals(EDGE_LABELING_NONE)) { if (el.Equals(EDGE_LABELING_GENERIC)) { var la = new GenericLabeling(); la.MaximumDuration = 0; la.PlaceNodeLabels = false; la.PlaceEdgeLabels = true; la.AutoFlipping = true; la.ProfitModel = new SimpleProfitModel(); hl.PrependStage(la); } else if (el.Equals(EDGE_LABELING_HIERARCHIC)) { bool copactEdgeLabelPlacement = (bool)currentGroup[COMPACT_EDGE_LABEL_PLACEMENT].Value; if (hl.NodePlacer is SimplexNodePlacer) { np.LabelCompaction = copactEdgeLabelPlacement; } hl.IntegratedEdgeLabeling = true; } } else { hl.IntegratedEdgeLabeling = false; } currentGroup = (OptionGroup)labelingGroup.GetGroupByName(NODE_PROPERTIES); if ((bool)currentGroup[CONSIDER_NODE_LABELS].Value) { hl.ConsiderNodeLabels = true; hl.NodeLayoutDescriptor.NodeLabelMode = NodeLabelMode.ConsiderForDrawing; } else { hl.ConsiderNodeLabels = false; } string rp = (string)rankGroup[RANKING_POLICY].Value; hl.FromScratchLayeringStrategy = rankingPolicies[rp]; if (rp.Equals(BFS_LAYERS)) { CurrentLayoutGraph.AddDataProvider(BFSLayerer.CoreNodesDpKey, new SelectedNodesDP(this)); } hl.ComponentArrangementPolicy = componentAlignmentEnum[(string)rankGroup[COMPONENT_ARRANGEMENT_POLICY].Value]; //configure AsIsLayerer Object layerer = (hl.LayoutMode == LayoutMode.FromScratch) ? hl.FromScratchLayerer : hl.FixedElementsLayerer; // if (layerer is OldLayererWrapper) { // layerer = ((OldLayererWrapper)layerer).OldLayerer; // } if (layerer is AsIsLayerer) { AsIsLayerer ail = (AsIsLayerer)layerer; currentGroup = (OptionGroup)rankGroup.GetGroupByName(FROM_SKETCH_PROPERTIES); ail.NodeHalo = (double)currentGroup[HALO].Value; ail.NodeScalingFactor = (double)currentGroup[SCALE].Value; ail.MinimumNodeSize = (double)currentGroup[MINIMUM_SIZE].Value; ail.MaximumNodeSize = (double)currentGroup[MAXIMUM_SIZE].Value; } //configure grouping np.GroupCompactionStrategy = groupHorizCompactionEnum[(string)groupingGroup[GROUP_HORIZONTAL_COMPACTION].Value]; if (!fromSketch && groupStrategyEnum[(string)groupingGroup[GROUP_LAYERING_STRATEGY].Value]) { GroupAlignmentPolicy alignmentPolicy = groupAlignmentEnum[(string)groupingGroup[GROUP_ALIGNMENT].Value]; hl.GroupAlignmentPolicy = alignmentPolicy; hl.CompactGroups = (bool)groupingGroup[GROUP_ENABLE_COMPACTION].Value; hl.RecursiveGroupLayering = true; } else { hl.RecursiveGroupLayering = false; } OptionGroup swimGroup = (OptionGroup)Handler.GetGroupByName(SWIMLANES); if ((bool)swimGroup[TREAT_ROOT_GROUPS_AS_SWIMLANES].Value) { TopLevelGroupToSwimlaneStage stage = new TopLevelGroupToSwimlaneStage(); stage.OrderSwimlanesFromSketch = (bool)swimGroup[USE_ORDER_FROM_SKETCH].Value; stage.Spacing = (double)swimGroup[SWIMLANE_SPACING].Value; hl.AppendStage(stage); } hl.BackLoopRouting = (bool)Handler.GetValue(EDGE_SETTINGS, BACKLOOP_ROUTING); hl.MaximumDuration = ((int)Handler.GetValue(GENERAL, MAXIMUM_DURATION)) * 1000; bool gridEnabled = (bool)Handler.GetValue(GRID, GRID_ENABLED); if (gridEnabled) { hl.GridSpacing = (double)Handler.GetValue(GRID, GRID_SPACING); String portAssignment = (string)Handler.GetValue(GRID, GRID_PORT_ASSIGNMENT); PortAssignmentMode gridPortAssignment; switch (portAssignment) { case GRID_PORT_ASSIGNMENT_ON_GRID: gridPortAssignment = PortAssignmentMode.OnGrid; break; case GRID_PORT_ASSIGNMENT_ON_SUBGRID: gridPortAssignment = PortAssignmentMode.OnSubgrid; break; default: gridPortAssignment = PortAssignmentMode.Default; break; } graph.AddDataProvider(HierarchicLayoutCore.NodeLayoutDescriptorDpKey, new NodeLayoutDescriptorAdapter(hl.NodeLayoutDescriptor, graph, gridPortAssignment)); } }