示例#1
0
        /// <summary>
        /// Creates a <see cref="LayoutData"/> used while dragging and finishing the gesture.
        /// </summary>
        private LayoutData CreateClearAreaLayoutData()
        {
            // force the router to let edges leave the nodes at the center of the south side
            // and to let enter the nodes in the center of the north side
            var sourcePortCandidate = PortCandidate.CreateCandidate(0, 0, PortDirections.South);
            var targetPortCandidate = PortCandidate.CreateCandidate(0, 0, PortDirections.North);

            return(new CompositeLayoutData(
                       resetToWorkingGraphStageData,
                       new ClearAreaLayoutData
            {
                AreaNodes = { Source = subtree.Nodes },
                ComponentIds = { Mapper = components },
                SourcePortCandidates = { Constant = new List <PortCandidate> {
                                             sourcePortCandidate
                                         } },
                TargetPortCandidates = { Constant = new List <PortCandidate> {
                                             targetPortCandidate
                                         } }
            }));
        }
        static TableLayout()
        {
            // set up port candidates for edges (edges should be attached to the left/right side of the corresponding node
            var candidates = new List <PortCandidate>
            {
                PortCandidate.CreateCandidate(PortDirections.West),
                PortCandidate.CreateCandidate(PortDirections.East)
            };

            // configure layout algorithms
            var rowLayout = new RowLayout(); // used for laying out the nodes (rows) within the group nodes (tables)

            layoutData = new RecursiveGroupLayoutData
            {
                SourcePortCandidates = { Constant = candidates },
                TargetPortCandidates = { Constant = candidates },

                // map each group node to its corresponding layout algorithm;
                // in this case each group node shall be laid out using the RowLayout
                GroupNodeLayouts = { Constant = rowLayout }
            };
        }
示例#3
0
        protected override LayoutData CreateConfiguredLayoutData(GraphControl graphControl, ILayoutAlgorithm layout)
        {
            var layoutData = new EdgeRouterData();

            layoutData.EdgeLayoutDescriptors.Delegate = edge => {
                var descriptor = new EdgeLayoutDescriptor {
                    MinimumEdgeToEdgeDistance        = MinimumEdgeToEdgeDistanceItem,
                    MinimumNodeCornerDistance        = MinimumNodeCornerDistanceItem,
                    MinimumFirstSegmentLength        = MinimumFirstSegmentLengthItem,
                    MinimumLastSegmentLength         = MinimumLastSegmentLengthItem,
                    PreferredOctilinearSegmentLength = PreferredOctilinearSegmentLengthItem,
                    MaximumOctilinearSegmentRatio    = PreferredPolylineSegmentRatioItem,
                    SourceCurveConnectionStyle       = SourceConnectionStyleItem,
                    TargetCurveConnectionStyle       = TargetConnectionStyleItem,
                    CurveUTurnSymmetry = CurveUTurnSymmetryItem,
                    CurveShortcuts     = CurveShortcutsItem,
                    RoutingStyle       = EdgeRoutingStyleItem,
                    RoutingPolicy      = RoutingPolicyItem,
                };
                if (OptimizationStrategyItem == EnumStrategies.Balanced)
                {
                    descriptor.PenaltySettings = PenaltySettings.OptimizationBalanced;
                }
                else if (OptimizationStrategyItem == EnumStrategies.MinimizeBends)
                {
                    descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeBends;
                }
                else if (OptimizationStrategyItem == EnumStrategies.MinimizeEdgeLength)
                {
                    descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeLengths;
                }
                else
                {
                    descriptor.PenaltySettings = PenaltySettings.OptimizationEdgeCrossings;
                }

                if (MonotonicRestrictionItem == EnumMonotonyFlags.Horizontal)
                {
                    descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Horizontal;
                }
                else if (MonotonicRestrictionItem == EnumMonotonyFlags.Vertical)
                {
                    descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Vertical;
                }
                else if (MonotonicRestrictionItem == EnumMonotonyFlags.Both)
                {
                    descriptor.MonotonicPathRestriction = MonotonicPathRestriction.Both;
                }
                else
                {
                    descriptor.MonotonicPathRestriction = MonotonicPathRestriction.None;
                }

                descriptor.MinimumEdgeToEdgeDistance = MinimumEdgeToEdgeDistanceItem;
                descriptor.MinimumNodeCornerDistance = MinimumNodeCornerDistanceItem;
                descriptor.MinimumFirstSegmentLength = MinimumFirstSegmentLengthItem;
                descriptor.MinimumLastSegmentLength  = MinimumLastSegmentLengthItem;

                if (UseIntermediatePointsItem)
                {
                    descriptor.IntermediateRoutingPoints =
                        edge.Bends
                        .Select(b => new YPoint(b.Location.X, b.Location.Y))
                        .Cast <object>()
                        .ToList();
                }

                return(descriptor);
            };

            var selection = graphControl.Selection;

            if (ScopeItem == Scope.RouteEdgesAtAffectedNodes)
            {
                layoutData.AffectedNodes.Source = selection.SelectedNodes;
            }
            else if (ScopeItem == Scope.RouteAffectedEdges)
            {
                layoutData.AffectedEdges.Source = selection.SelectedEdges;
            }
            else
            {
                layoutData.AffectedEdges.Delegate = edge => true;
                layoutData.AffectedNodes.Delegate = node => true;
            }

            if (PortSidesItem != PortSides.Any)
            {
                PortCandidate[] candidates;
                if (PortSidesItem == PortSides.LeftRight)
                {
                    candidates = new[] {
                        PortCandidate.CreateCandidate(PortDirections.East), PortCandidate.CreateCandidate(PortDirections.West)
                    };
                }
                else
                {
                    candidates = new[] {
                        PortCandidate.CreateCandidate(PortDirections.North), PortCandidate.CreateCandidate(PortDirections.South)
                    };
                }
                layoutData.SourcePortCandidates.Constant = candidates;
                layoutData.TargetPortCandidates.Constant = candidates;
            }

            switch (BusRoutingItem)
            {
            case EnumBusRouting.SingleBus:
                // All edges in a single bus
                layoutData.Buses.Add(CreateBusDescriptor()).Delegate = edge => true;
                break;

            case EnumBusRouting.ByLabel:
                var byLabel = new Dictionary <string, List <IEdge> >();
                foreach (var edge in graphControl.Graph.Edges)
                {
                    if (edge.Labels.Count > 0)
                    {
                        var          label = edge.Labels[0].Text;
                        List <IEdge> list;
                        if (!byLabel.TryGetValue(label, out list))
                        {
                            list           = new List <IEdge>();
                            byLabel[label] = list;
                        }
                        list.Add(edge);
                    }
                }
                foreach (var edges in byLabel.Values)
                {
                    // Add a bus per label. Unlabeled edges don't get grouped into a bus
                    layoutData.Buses.Add(CreateBusDescriptor()).Source = edges;
                }
                break;

            case EnumBusRouting.ByColor:
                var comparer = new ColorComparer();
                var byColor  = new Dictionary <Brush, List <IEdge> >(comparer);
                foreach (var edge in graphControl.Graph.Edges)
                {
                    var brush = ((PolylineEdgeStyle)edge.Style).Pen.Brush;
                    if (!comparer.Equals(brush, Brushes.Black))
                    {
                        List <IEdge> list;
                        if (!byColor.TryGetValue(brush, out list))
                        {
                            list           = new List <IEdge>();
                            byColor[brush] = list;
                        }
                        list.Add(edge);
                    }
                }
                foreach (var edges in byColor.Values)
                {
                    // Add a bus per color. Black edges don't get grouped into a bus
                    layoutData.Buses.Add(CreateBusDescriptor()).Source = edges;
                }
                break;
            }

            return(layoutData.CombineWith(
                       CreateLabelingLayoutData(
                           graphControl.Graph,
                           LabelPlacementAlongEdgeItem,
                           LabelPlacementSideOfEdgeItem,
                           LabelPlacementOrientationItem,
                           LabelPlacementDistanceItem
                           )
                       ));
        }
示例#4
0
            /// <summary>
            /// Creates a new instance configured for the specified graph.
            /// </summary>
            /// <param name="graph">The graph to configure the layout data for</param>
            /// <param name="fromSketch"/> Whether the <see cref="HierarchicLayout"/> shall be run in incremental layout mode.
            public LayoutData(IGraph graph, bool fromSketch)
            {
                // set up port candidates for edges (edges should be attached to the left/right side of the corresponding node
                var candidates = new List <PortCandidate>
                {
                    PortCandidate.CreateCandidate(PortDirections.West),
                    PortCandidate.CreateCandidate(PortDirections.East)
                };

                // configure the different sub group layout settings
                var leftToRightTreeLayout = new TreeReductionStage();

                leftToRightTreeLayout.NonTreeEdgeRouter = leftToRightTreeLayout.CreateStraightLineRouter();
                leftToRightTreeLayout.CoreLayout        = new TreeLayout {
                    LayoutOrientation = LayoutOrientation.LeftToRight,
                };

                var rightToLeftTreeLayout = new TreeReductionStage();

                rightToLeftTreeLayout.NonTreeEdgeRouter = rightToLeftTreeLayout.CreateStraightLineRouter();
                rightToLeftTreeLayout.CoreLayout        = new TreeLayout {
                    LayoutOrientation = LayoutOrientation.RightToLeft,
                };

                var view = graph.Lookup <IFoldingView>();

                Items.Add(new RecursiveGroupLayoutData {
                    SourcePortCandidates = { Constant = candidates },
                    TargetPortCandidates = { Constant = candidates },

                    // map each group node to the layout algorithm that should be used for its content
                    GroupNodeLayouts =
                    {
                        Delegate = node => {
                            switch (GetTierType(node, view, graph))
                            {
                            case TierType.LeftTreeGroupNode:
                                return(leftToRightTreeLayout);

                            case TierType.RightTreeGroupNode:
                                return(rightToLeftTreeLayout);

                            default:
                                return(null);
                            }
                        }
                    }
                });

                var hlData = new HierarchicLayoutData {
                    NodeLayoutDescriptors =
                    {
                        Delegate                   = node => {
                            // align tree group nodes within their layer
                            switch (GetTierType(node, view, graph))
                            {
                            case TierType.LeftTreeGroupNode:
                                return(new NodeLayoutDescriptor {
                                    LayerAlignment = 1
                                });

                            case TierType.RightTreeGroupNode:
                                return(new NodeLayoutDescriptor {
                                    LayerAlignment = 0
                                });

                            default:
                                return(null);
                            }
                        }
                    }
                };

                if (!fromSketch)
                {
                    // insert layer constraints to guarantee the desired placement for "left" and "right" group nodes
                    var layerConstraintData = hlData.LayerConstraints;
                    foreach (var node in graph.Nodes)
                    {
                        // align tree group nodes within their layer
                        TierType type = GetTierType(node, view, graph);
                        if (type == TierType.LeftTreeGroupNode)
                        {
                            layerConstraintData.PlaceAtTop(node);
                        }
                        else if (type == TierType.RightTreeGroupNode)
                        {
                            layerConstraintData.PlaceAtBottom(node);
                        }
                    }
                }
                Items.Add(hlData);
            }
示例#5
0
        /// <summary>
        /// Perform the layout operation
        /// </summary>
        private async Task ApplyLayout()
        {
            // layout starting, disable button
            layoutButton.IsEnabled = false;

            // create the layout algorithm
            var layout = new HierarchicLayout
            {
                OrthogonalRouting = true,
                LayoutOrientation = LayoutOrientation.TopToBottom
            };

            // do the layout
            await graphControl.MorphLayout(layout,
                                           TimeSpan.FromSeconds(1),
                                           new HierarchicLayoutData {
                //Automatically determine port constraints for source and target
                NodePortCandidateSets =
                {
                    Delegate              = node => {
                        var candidateSet  = new PortCandidateSet();
                        // iterate the port descriptors
                        var descriptors   = PortDescriptor.CreatePortDescriptors(((FlowChartNodeStyle)node.Style).FlowChartType);
                        foreach (var portDescriptor in descriptors)
                        {
                            PortCandidate candidate;
                            // isn't a fixed port candidate (location is variable)
                            if (portDescriptor.X == int.MaxValue)
                            {
                                // create a port candidate at the specified side (east, west, north, south) and apply a cost to it
                                candidate = PortCandidate.CreateCandidate(portDescriptor.Side, portDescriptor.Cost);
                            }
                            else
                            {
                                // create a candidate at a fixed location and side
                                var x     = portDescriptor.X - node.Layout.Width / 2;
                                var y     = portDescriptor.Y - node.Layout.Height / 2;
                                candidate = PortCandidate.CreateCandidate(x, y, portDescriptor.Side, portDescriptor.Cost);
                            }
                            candidateSet.Add(candidate, portDescriptor.Capacity);
                        }
                        return(candidateSet);
                    }
                },
                SourceGroupIds = { Delegate           = edge => {
                                       // create bus-like edge groups for outgoing edges at Start nodes
                                       var sourceNode = edge.SourcePort.Owner as INode;
                                       if (sourceNode != null && ((((FlowChartNodeStyle)sourceNode.Style).FlowChartType)) == FlowChartType.Start)
                                       {
                                           return(sourceNode);
                                       }
                                       return(null);
                                   } },

                TargetGroupIds = { Delegate           = edge => {
                                       // create bus-like edge groups for incoming edges at Branch nodes
                                       var targetNode = edge.TargetPort.Owner as INode;
                                       if (targetNode != null && (((FlowChartNodeStyle)targetNode.Style).FlowChartType) == FlowChartType.Branch)
                                       {
                                           return(targetNode);
                                       }
                                       return(null);
                                   } }
            });

            // enable button again
            layoutButton.IsEnabled = true;
        }