Пример #1
0
            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);
                    }
                }
            }
Пример #2
0
        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);
            }
          }
        }
      }
Пример #4
0
        /// <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;
        }
Пример #6
0
        /// <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));
            }
        }