protected override LayoutData CreateConfiguredLayoutData(GraphControl graphControl, ILayoutAlgorithm layout)
        {
            var layoutData     = new BusRouterData();
            var graph          = graphControl.Graph;
            var graphSelection = graphControl.Selection;
            var scopePartial   = ScopeItem == EnumScope.Partial;

            var busIds = layoutData.EdgeDescriptors.Mapper;

            foreach (var edge in graph.Edges)
            {
                var isFixed = scopePartial &&
                              !graphSelection.IsSelected(edge.GetSourceNode()) &&
                              !graphSelection.IsSelected(edge.GetTargetNode());
                var id         = GetBusId(edge, BusesItem);
                var descriptor = new BusDescriptor(id, isFixed)
                {
                    RoutingPolicy = RoutingPolicyItem
                };
                busIds[edge] = descriptor;
            }

            HashSet <object> selectedIds;

            switch (ScopeItem)
            {
            case EnumScope.Subset:
                layoutData.AffectedEdges.Delegate = graphSelection.IsSelected;
                break;

            case EnumScope.SubsetBus:
                selectedIds = new HashSet <object>(graphSelection
                                                   .SelectedEdges
                                                   .Select(edge => busIds[edge].BusId));
                layoutData.AffectedEdges.Delegate = edge => selectedIds.Contains(busIds[edge].BusId);
                break;

            case EnumScope.Partial:
                selectedIds = new HashSet <object>(graphSelection
                                                   .SelectedNodes
                                                   .SelectMany(node => graph.EdgesAt(node))
                                                   .Select(edge => busIds[edge].BusId));

                layoutData.AffectedEdges.Delegate = edge => selectedIds.Contains(busIds[edge].BusId);

                var hideNonOrthogonalEdgesLayoutData = new GenericLayoutData();
                hideNonOrthogonalEdgesLayoutData.AddItemCollection(HideNonOrthogonalEdgesStage.SelectedNodesDpKey).Source =
                    graphSelection.SelectedNodes;

                return(layoutData.CombineWith(hideNonOrthogonalEdgesLayoutData));
            }

            return(layoutData);
        }
        public LayoutData Create(IGraph graph, ISelectionModel <IModelItem> selection, Scope layoutScope)
        {
            var data = new GenericLayoutData();
            var hierarchicLayoutData = new HierarchicLayoutData();

            // check if only selected elements should be laid out
            var layoutOnlySelection = layoutScope == Scope.SelectedElements;

            // mark 'flow' edges, i.e. sequence flows, default flows and conditional flows
            data.AddItemCollection(BpmnLayout.SequenceFlowEdgesDpKey).Delegate = IsSequenceFlow;

            // mark boundary interrupting edges for the BalancingPortOptimizer
            data.AddItemCollection(BpmnLayout.BoundaryInterruptingEdgesDpKey).Delegate = edge => edge.SourcePort.Style is EventPortStyle;



            // mark conversations, events and gateways so their port locations are adjusted
            data.AddItemCollection(PortLocationAdjuster.AffectedNodesDpKey).Delegate = (INode node) =>
                                                                                       (node.Style is ConversationNodeStyle || node.Style is EventNodeStyle || node.Style is GatewayNodeStyle);

            // add NodeHalos around nodes with event ports or specific exterior labels so the layout keeps space for the event ports and labels as well
            AddNodeHalos(data, graph, selection, layoutOnlySelection);

            // add PreferredPlacementDescriptors for labels on sequence, default or conditional flows to place them at source side
            AddEdgeLabelPlacementDescriptors(data);

            // mark nodes, edges and labels as either fixed or affected by the layout and configure port constraints and incremental hints
            MarkFixedAndAffectedItems(data, hierarchicLayoutData, selection, layoutOnlySelection);

            // mark associations and message flows as undirected so they have less impact on layering
            hierarchicLayoutData.EdgeDirectedness.Delegate = edge => (IsMessageFlow(edge) || IsAssociation(edge)) ? 0 : 1;

            // add layer constraints for start events, sub processes and message flows
            AddLayerConstraints(graph, hierarchicLayoutData);

            // add EdgeLayoutDescriptor to specify minimum edge length for edges
            AddMinimumEdgeLength(MinimumEdgeLength, hierarchicLayoutData);


            return(data.CombineWith(hierarchicLayoutData));
        }
        private static void MarkFixedAndAffectedItems(GenericLayoutData data, HierarchicLayoutData hierarchicLayoutData, ISelectionModel <IModelItem> graphSelection,
                                                      bool layoutOnlySelection)
        {
            if (layoutOnlySelection)
            {
                var affectedEdges = Mappers.FromDelegate((IEdge edge) =>
                                                         graphSelection.IsSelected(edge) ||
                                                         graphSelection.IsSelected(edge.GetSourceNode()) ||
                                                         graphSelection.IsSelected(edge.GetTargetNode()));
                data.AddItemCollection(LayoutKeys.AffectedEdgesDpKey).Mapper = affectedEdges;

                // fix ports of unselected edges and edges at event ports
                data.AddItemMapping(PortConstraintKeys.SourcePortConstraintDpKey).Delegate =
                    edge =>
                    (!affectedEdges[edge] || edge.SourcePort.Style is EventPortStyle)
              ? PortConstraint.Create(GetSide(edge, true))
              : null;
                data.AddItemMapping(PortConstraintKeys.TargetPortConstraintDpKey).Delegate =
                    edge => !affectedEdges[edge] ? PortConstraint.Create(GetSide(edge, false)) : null;

                // give core layout hints that selected nodes and edges should be incremental
                hierarchicLayoutData.IncrementalHints.ContextDelegate = (item, factory) => {
                    if (item is INode && graphSelection.IsSelected(item))
                    {
                        return(factory.CreateLayerIncrementallyHint(item));
                    }
                    else if (item is IEdge && affectedEdges[(IEdge)item])
                    {
                        return(factory.CreateSequenceIncrementallyHint(item));
                    }
                    return(null);
                };
                data.AddItemCollection(BpmnLayout.AffectedLabelsDpKey).Delegate = label => {
                    var edge = label.Owner as IEdge;
                    if (edge != null)
                    {
                        return(affectedEdges[edge]);
                    }
                    var node = label.Owner as INode;
                    if (node != null)
                    {
                        var  isInnerLabel   = node.Layout.Contains(label.GetLayout().GetCenter());
                        bool isPool         = node.Style is PoolNodeStyle;
                        bool isChoreography = node.Style is ChoreographyNodeStyle;
                        return(!isInnerLabel && !isPool && !isChoreography && graphSelection.IsSelected(node));
                    }
                    return(false);
                };
            }
            else
            {
                // fix source port of edges at event ports
                data.AddItemMapping(PortConstraintKeys.SourcePortConstraintDpKey).Delegate =
                    edge => edge.SourcePort.Style is EventPortStyle?PortConstraint.Create(GetSide(edge, true)) : null;

                data.AddItemCollection(BpmnLayout.AffectedLabelsDpKey).Delegate = label => {
                    if (label.Owner is IEdge)
                    {
                        return(true);
                    }
                    var node = label.Owner as INode;
                    if (node != null)
                    {
                        var  isInnerLabel   = node.Layout.Contains(label.GetLayout().GetCenter());
                        bool isPool         = node.Style is PoolNodeStyle;
                        bool isChoreography = node.Style is ChoreographyNodeStyle;
                        return(!isInnerLabel && !isPool && !isChoreography);
                    }
                    return(false);
                };
            }
        }