/// <summary>
        /// Perform the layout operation
        /// </summary>
        private async Task DoLayout(Scope scope)
        {
            // layout starting, disable button
            layoutButton.IsEnabled = false;

            var busRouterData = new BusRouterData
            {
                EdgeDescriptors = { Delegate = edge => new BusDescriptor(((PolylineEdgeStyle)edge.Style).Pen) }
            };

            // layout applies only to selected subset of edges
            if (scope == Scope.RouteAffectedEdges)
            {
                busRouterData.AffectedEdges.Items = edgesToRoute;
            }

            // tell the layout algorithm about the scope it should operate in
            layout.Scope = scope;

            // do the layout
            await graphControl.MorphLayout(layout, TimeSpan.FromSeconds(1), busRouterData);

            // layout finished, enable layout button again
            layoutButton.IsEnabled = true;
        }
        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);
        }
        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);
                busIds[edge] = new BusDescriptor(id, isFixed);
            }

            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);
                return(new CompositeLayoutData {
                    Items =
                    {
                        layoutData,
                        new HideNonOrthogonalEdgesLayoutData {
                            SelectedNodes = { Source = graphSelection.SelectedNodes }
                        }
                    }
                });
            }

            return(layoutData);
        }