private void RouteMarkedEdges(LayoutGraph graph, IDataMap markedEdgesMap) { if (MarkedEdgeRouter == null) { return; } IDataProvider backupDp = null; if (EdgeSelectionKey != null) { backupDp = graph.GetDataProvider(EdgeSelectionKey); graph.AddDataProvider(EdgeSelectionKey, markedEdgesMap); } if (MarkedEdgeRouter is StraightLineEdgeRouter) { var router = (StraightLineEdgeRouter)MarkedEdgeRouter; router.Scope = Scope.RouteAffectedEdges; router.AffectedEdgesDpKey = EdgeSelectionKey; } MarkedEdgeRouter.ApplyLayout(graph); if (EdgeSelectionKey != null) { graph.RemoveDataProvider(EdgeSelectionKey); if (backupDp != null) { graph.AddDataProvider(EdgeSelectionKey, backupDp); } } }
public override void ApplyLayout(LayoutGraph graph) { var dataProvider = graph.GetDataProvider(SelectedLabelsAtItemKey); graph.AddDataProvider(ProviderKey, new MyDataProviderAdapter(dataProvider, graph)); ApplyLayoutCore(graph); graph.RemoveDataProvider(ProviderKey); }
/// <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/> public override void ApplyLayout(LayoutGraph graph) { // first layout the non-tree edges nonTreeEdgeRouter.Scope = Scope.RouteAffectedEdges; nonTreeEdgeRouter.ApplyLayout(graph); // the tree reduction stage only prepares a data provider to mark the non-tree edges but we need // a provider to mark the labels of all non-tree edges: // for t var nonTreeEdgeDp = graph.GetDataProvider(LayoutKeys.AffectedEdgesDpKey); graph.AddDataProvider("nonTreeLabels", new NonTeeEdgesDataProvider(graph, nonTreeEdgeDp)); nonTreeEdgeLabelLayout.AffectedLabelsDpKey = "nonTreeLabels"; nonTreeEdgeLabelLayout.ApplyLayout(graph); graph.RemoveDataProvider("nonTreeLabels"); }
protected override void OptimizeAfterSequencing(IComparer <object> inEdgeOrder, IComparer <object> outEdgeOrder, LayoutGraph graph, ILayers layers, ILayoutDataProvider ldp, IItemFactory itemFactory) { edge2LaneCrossing = Maps.CreateHashedEdgeMap(); node2LaneAlignment = Maps.CreateHashedNodeMap(); var criticalEdges = Maps.CreateHashedEdgeMap(); // determine whether an edge crosses a swim lane border and if so in which direction foreach (var edge in graph.Edges) { var originalEdge = GetOriginalEdge(edge, ldp); // now we have a 'real' edge with valid valid source and target nodes var originalSourceId = GetLaneId(originalEdge.Source, ldp); var originalTargetId = GetLaneId(originalEdge.Target, ldp); LaneCrossing crossing = LaneCrossing.None; if (originalSourceId != originalTargetId) { // check if we need to flip the sides because edge and original edge have different directions var flipSides = edge.Source != originalEdge.Source; var sourceId = flipSides ? originalTargetId : originalSourceId; var targetId = flipSides ? originalSourceId : originalTargetId; crossing = sourceId > targetId ? LaneCrossing.ToWest : LaneCrossing.ToEast; } edge2LaneCrossing.Set(edge, crossing); } // determine basic node alignment foreach (var n in graph.Nodes) { LaneAlignment alignment = CalculateLaneAlignment(n); node2LaneAlignment.Set(n, alignment); } foreach (var n in graph.Nodes) { // sort the edges with the provided comparer n.SortInEdges(inEdgeOrder); n.SortOutEdges(outEdgeOrder); // calculate 'critical' in and out-edges whose nodes should be aligned in flow var bestInEdge = n.InDegree > 0 ? GetBestFlowEdge(n.InEdges, ldp, graph) : null; var bestOutEdge = n.OutDegree > 0 ? GetBestFlowEdge(n.OutEdges, ldp, graph) : null; if (bestInEdge != null) { criticalEdges.SetDouble(bestInEdge, criticalEdges.GetDouble(bestInEdge) + 0.5); } if (bestOutEdge != null) { criticalEdges.SetDouble(bestOutEdge, criticalEdges.GetDouble(bestOutEdge) + 0.5); } if (n.Degree <= 4) { // should usually be the case and we can distribute each edge to its own side // remember which node side is already taken by an in- or out-edge bool westTakenByInEdge = false; bool eastTakenByInEdge = false; bool westTakenByOutEdge = false; bool eastTakenByOutEdge = false; if (n.InDegree > 0 && n.OutDegree < 3) { // if there are at least three out-edges, we distribute those first, otherwise we start with the in-edges var firstInEdge = n.FirstInEdge; var lastInEdge = n.LastInEdge; if (GetLaneCrossing(firstInEdge) == LaneCrossing.ToEast && (n.InDegree > 1 || IsSameLayerEdge(firstInEdge, ldp))) { // the first in-edge comes from west and is either a same layer edge or there are other in-edges ConstrainWest(firstInEdge, false, itemFactory); westTakenByInEdge = true; } if (!westTakenByInEdge || n.OutDegree < 2) { // don't use west and east side for in-edges if there are at least 2 out-edges if (GetLaneCrossing(lastInEdge) == LaneCrossing.ToWest && (n.InDegree > 1 || IsSameLayerEdge(lastInEdge, ldp))) { // the last in-edge comes from east and is either // a same-layer edge or there are other in-edges ConstrainEast(lastInEdge, false, itemFactory); eastTakenByInEdge = true; } } } if (n.OutDegree > 0) { var firstOutEdge = n.FirstOutEdge; var lastOutEdge = n.LastOutEdge; if (!westTakenByInEdge) { // the west side is still free if (BpmnLayout.IsBoundaryInterrupting(firstOutEdge, graph) || (GetLaneCrossing(firstOutEdge) == LaneCrossing.ToWest) && (n.OutDegree > 1 || IsSameLayerEdge(firstOutEdge, ldp))) { // the first out-edge is either boundary interrupting or goes to west and // is either a same layer edge or there are other out-edges ConstrainWest(firstOutEdge, true, itemFactory); westTakenByOutEdge = true; } else if (eastTakenByInEdge && n.OutDegree >= 2 && !IsSameLayerEdge(firstOutEdge.NextOutEdge, ldp)) { // the east side is already taken but we have more then one out edge. // if the second out edge is a same layer edge, constraining the firstOutEdge could lead to // no in-flow edge ConstrainWest(firstOutEdge, true, itemFactory); westTakenByOutEdge = true; } } if (!eastTakenByInEdge) { // the east side is still free if (GetLaneCrossing(lastOutEdge) == LaneCrossing.ToEast && (n.OutDegree > 1 || IsSameLayerEdge(lastOutEdge, ldp))) { // the last out-edge goes to east and // is either a same layer edge or there are other out-edges ConstrainEast(lastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } else if (westTakenByInEdge && n.OutDegree >= 2 && !IsSameLayerEdge(lastOutEdge.PrevOutEdge, ldp)) { // the west side is already taken but we have more then one out edge. // if the second last out edge is a same layer edge, constraining the lastOutEdge could lead to // no in-flow edge ConstrainEast(lastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } } } // distribute remaining in-edges if (n.InDegree == 2 && !(eastTakenByInEdge || westTakenByInEdge)) { // two in-edges but none distributed, yet if (bestInEdge == n.FirstInEdge && !eastTakenByOutEdge) { // first in-edge is in-flow edge and east side is still free ConstrainEast(n.LastInEdge, false, itemFactory); eastTakenByInEdge = true; } else if (bestInEdge == n.LastInEdge && !westTakenByOutEdge) { // last in-edge is in-flow edge and west side is still free ConstrainWest(n.FirstInEdge, false, itemFactory); westTakenByInEdge = true; } } else if (n.InDegree == 3 && !(eastTakenByInEdge && westTakenByInEdge) && !(IsSameLayerEdge(n.FirstInEdge.NextInEdge, ldp))) { // three in-edges but not both sides taken, yet and the middle edge is no same layer edge if (!eastTakenByOutEdge) { // if not already taken, constraint the last in-edge to east ConstrainEast(n.LastInEdge, false, itemFactory); eastTakenByInEdge = true; } if (!westTakenByOutEdge) { // if not already taken, constraint the first in-edge to west ConstrainWest(n.FirstInEdge, false, itemFactory); westTakenByInEdge = true; } } // distribute remaining out-edges if (n.OutDegree == 2 && !(eastTakenByOutEdge || westTakenByOutEdge)) { // two out-edges but none distributed, yet if (bestOutEdge == n.FirstOutEdge && !eastTakenByInEdge) { // first out-edge is in-flow edge and east side is still free ConstrainEast(n.LastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } else if (bestOutEdge == n.LastOutEdge && !westTakenByInEdge) { // last out-edge is in-flow edge and west side is still free ConstrainWest(n.FirstOutEdge, true, itemFactory); westTakenByOutEdge = true; } } else if (n.OutDegree == 3 && !(eastTakenByOutEdge && westTakenByOutEdge) && !(IsSameLayerEdge(n.FirstOutEdge.NextOutEdge, ldp))) { // three out-edges but not both sides taken, yet and the middle edge is no same layer edge if (!eastTakenByInEdge) { // if not already taken, constraint the last out-edge to east ConstrainEast(n.LastOutEdge, true, itemFactory); eastTakenByOutEdge = true; } if (!westTakenByInEdge) { // if not already taken, constraint the first out-edge to west ConstrainWest(n.FirstOutEdge, true, itemFactory); westTakenByOutEdge = true; } } } } // register the data provider for critical edge paths. It is deregistered again by BpmnLayout itself graph.AddDataProvider(HierarchicLayout.CriticalEdgePriorityDpKey, criticalEdges); sameLayerData = null; edge2LaneCrossing = null; node2LaneAlignment = null; }
/// <summary> /// Executes the layout algorithm. /// </summary> /// <remarks> /// <para> /// Enlarges the node layout to fully encompass the rotated layout (the rotated layout's bounding box). /// If the <see cref="EdgeRoutingMode"/> is set to <see cref="RoutingMode.FixedPort"/> /// port constraints are created to keep the ports at their current location. /// Existing port constraints are adjusted to the rotation. /// </para> /// <para> /// Then, the <see cref="LayoutStageBase.CoreLayout"/> is executed. /// </para> /// <para> /// After the core layout the original node sizes are restored. /// If the <see cref="EdgeRoutingMode"/> is set to <see cref="RoutingMode.ShortestStraightPathToBorder"/> /// the last edge segment is extended from the bounding box to the rotated layout. /// </para> /// </remarks> public override void ApplyLayout(LayoutGraph graph) { if (CoreLayout == null) { return; } var boundsProvider = graph.GetDataProvider(RotatedNodeLayoutDpKey); if (boundsProvider == null) { // no provider: this stage adds nothing to the core layout CoreLayout.ApplyLayout(graph); return; } bool addedSourcePortConstraints = false; bool addedTargetPortContstraints = false; IDataMap sourcePortConstraints = (IDataMap)graph.GetDataProvider(PortConstraintKeys.SourcePortConstraintDpKey); IDataMap targetPortConstraints = (IDataMap)graph.GetDataProvider(PortConstraintKeys.TargetPortConstraintDpKey); if (EdgeRoutingMode == RoutingMode.FixedPort) { // Fixed port: create port constraints to keep the ports at position // in this case: create data providers if there are none yet if (sourcePortConstraints == null) { sourcePortConstraints = graph.CreateEdgeMap(); graph.AddDataProvider(PortConstraintKeys.SourcePortConstraintDpKey, sourcePortConstraints); addedSourcePortConstraints = true; } if (targetPortConstraints == null) { targetPortConstraints = graph.CreateEdgeMap(); graph.AddDataProvider(PortConstraintKeys.TargetPortConstraintDpKey, targetPortConstraints); addedTargetPortContstraints = true; } } try { var originalDimensions = new Dictionary <Node, OldDimensions>(); foreach (var node in graph.Nodes) { var nodeShape = (RotatedNodeShape)boundsProvider.Get(node); var orientedLayout = nodeShape != null ? nodeShape.OrientedLayout : null; var outline = nodeShape != null ? nodeShape.Outline : null; if (orientedLayout != null) { // if the current node is rotated: apply fixes // remember old layout and size var oldLayout = graph.GetLayout(node); var newLayout = orientedLayout.GetBounds().ToYRectangle(); var offset = new PointD(newLayout.X - oldLayout.X, newLayout.Y - oldLayout.Y); var originalSize = new SizeD(oldLayout.Width, oldLayout.Height); var oldDimensions = new OldDimensions { offset = offset, size = originalSize, outline = outline }; if (EdgeRoutingMode == RoutingMode.FixedPort) { // EdgeRoutingMode: FixedPort: keep the ports at their current location // The oriented layout's corners to find the best PortSide var tl = new PointD(orientedLayout.AnchorX + orientedLayout.UpX * orientedLayout.Height, orientedLayout.AnchorY + orientedLayout.UpY * orientedLayout.Height); var tr = new PointD(orientedLayout.AnchorX + orientedLayout.UpX * orientedLayout.Height - orientedLayout.UpY * orientedLayout.Width, orientedLayout.AnchorY + orientedLayout.UpY * orientedLayout.Height + orientedLayout.UpX * orientedLayout.Width); var bl = new PointD(orientedLayout.AnchorX, orientedLayout.AnchorY); var br = new PointD(orientedLayout.AnchorX - orientedLayout.UpY * orientedLayout.Width, orientedLayout.AnchorY + orientedLayout.UpX * orientedLayout.Width); // for each out edge foreach (var edge in node.OutEdges) { // create a strong port constraint for the side which is closest to the port location (without rotation) var constraint = sourcePortConstraints.Get(edge); if (constraint == null) { var point = graph.GetSourcePointAbs(edge).ToPointD(); var side = FindBestSide(point, bl, br, tl, tr); sourcePortConstraints.Set(edge, PortConstraint.Create(side, true)); } } foreach (var edge in node.InEdges) { // create a strong port constraint for the side which is closest to the port location (without rotation) var constraint = targetPortConstraints.Get(edge); if (constraint == null) { var point = graph.GetTargetPointAbs(edge).ToPointD(); var side = FindBestSide(point, bl, br, tl, tr); targetPortConstraints.Set(edge, PortConstraint.Create(side, true)); } } } // For source and target port constraints: fix the PortSide according to the rotation var angle = Math.Atan2(orientedLayout.UpY, orientedLayout.UpX); if (sourcePortConstraints != null) { foreach (var edge in node.OutEdges) { FixPortConstraintSide(sourcePortConstraints, edge, angle); } } if (targetPortConstraints != null) { foreach (var edge in node.InEdges) { FixPortConstraintSide(targetPortConstraints, edge, angle); } } // enlarge the node layout var position = new YPoint(newLayout.X, newLayout.Y); oldDimensions.location = position; originalDimensions.Add(node, oldDimensions); graph.SetLocation(node, position); graph.SetSize(node, newLayout); } } // =============================================================== CoreLayout.ApplyLayout(graph); // =============================================================== var groups = graph.GetDataProvider(GroupingKeys.GroupDpKey); foreach (var node in graph.Nodes) { if (groups != null && groups.GetBool(node)) { // groups don't need to be adjusted to their former size and location because their bounds are entirely // calculated by the layout algorithm and they are not rotated continue; } // for each node which has been corrected: undo the correction var oldDimensions = originalDimensions[node]; var offset = oldDimensions.offset; var originalSize = oldDimensions.size; var newLayout = graph.GetLayout(node); // create a general path representing the new roated layout var path = oldDimensions.outline; var transform = new Matrix2D(); transform.Translate(new PointD(newLayout.X - oldDimensions.location.X, newLayout.Y - oldDimensions.location.Y)); path.Transform(transform); // restore the original size graph.SetLocation(node, new YPoint(newLayout.X - offset.X, newLayout.Y - offset.Y)); graph.SetSize(node, originalSize.ToYDimension()); if (EdgeRoutingMode == RoutingMode.NoRouting) { // NoRouting still needs fix for self-loops foreach (var edge in node.Edges) { if (edge.SelfLoop) { FixPorts(graph, edge, path, false); FixPorts(graph, edge, path, true); } } continue; } if (EdgeRoutingMode != RoutingMode.ShortestStraightPathToBorder) { continue; } // enlarge the adjacent segment to the oriented rectangle (represented by the path) // handling in and out edges separately will automatically cause selfloops to be handled correctly foreach (var edge in node.InEdges) { FixPorts(graph, edge, path, false); } foreach (var edge in node.OutEdges) { FixPorts(graph, edge, path, true); } } } finally { // if data provider for the port constraints have been added // remove and dispose them if (addedSourcePortConstraints) { graph.RemoveDataProvider(PortConstraintKeys.SourcePortConstraintDpKey); graph.DisposeEdgeMap((IEdgeMap)sourcePortConstraints); } if (addedTargetPortContstraints) { graph.RemoveDataProvider(PortConstraintKeys.TargetPortConstraintDpKey); graph.DisposeEdgeMap((IEdgeMap)targetPortConstraints); } } }
///<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)); } }