示例#1
0
		/// <summary>
		/// Initializes a new instance of the PathFinder class.
		/// Path-finding will depend on the direction of arrows.
		/// </summary>
		/// <param name="diagram">A FlowChart instance in which to look for paths or cycles.</param>
		public PathFinder(FlowChart diagram)
		{
			graph = new FCGraph(diagram, false);
			ignoreDirection = false;
		}
示例#2
0
		/// <summary>
		/// Initializes a new instance of the PathFinder class.
		/// </summary>
		/// <param name="diagram">A FlowChart instance in which to look for paths or cycles.</param>
		/// <param name="ignoreDirection">Specifies whether the direction of arrows
		/// should be considered when looking for paths or cycles.</param>
		public PathFinder(FlowChart diagram, bool ignoreDirection)
		{
			graph = new FCGraph(diagram, false, ignoreDirection);
			this.ignoreDirection = ignoreDirection;
		}
示例#3
0
		public virtual bool Arrange(FlowChart chart)
		{
			chart.UndoManager.onStartLayout("Anneal layout");

			// Build the graph
			FCGraph graph = new FCGraph(chart, _keepGroupLayout);

			// Find the root adapter
			Layout.INode rootNode = null;
			if (_root != null)
			{
				foreach (FCNode node in graph.Nodes)
				{
					if (node.Node == _root)
					{
						rootNode = node;
						break;
					}
				}
			}

			// Split graph to subgraphs
			Layout.IGraph[] subgraphs = null;
			if (_splitGraph)
			{
				subgraphs = Layout.GraphSplitter.Split(
					graph, new FCGraphBuilder(chart, false));
			}
			else
			{
				subgraphs = new Layout.IGraph[] { graph };
			}
			
			// Create the layouter
			Layout.AnnealLayout layout = new Layout.AnnealLayout();

			Layout.LayoutProgress progress = null;
			if (_progress != null)
				progress = new Layout.LayoutProgress(this.OnLayoutProgress);

			Layout.AnnealLayoutInfo info = new Layout.AnnealLayoutInfo();

			info.DistributionFactor = this.DistributionFactor;
			info.BoundaryFactor = this.BoundaryFactor;
			info.EdgeLengthFactor = this.ArrowLengthFactor;
			info.CrossingEdgesCost = this.CrossingArrowsCost;
			info.NodeEdgeDistFactor = this.NodeArrowDistFactor;

			info.IterationsPerStage = this.IterationsPerStage;
			info.Stages = this.Stages;
			info.Temperature = this.InitialTemperature;
			info.TemperatureScale = this.TemperatureScale;

			info.LayoutArea = this.LayoutArea;
			info.WidthHeightRatio = this.WidthHeightRatio;
			info.Randomize = this.Randomize;

			float xOffset = 0;
			foreach (FCGraph subgraph in subgraphs)
			{
				// If a root node is specified and the subgraph
				// does not contain that node, do not arrange
				// the subgraph
				if (rootNode != null)
				{
					if (!subgraph.Nodes.Contains(rootNode))
						continue;
				}

				layout.Arrange(subgraph, info, progress);

				// Translate the whole subgraph
				RectangleF graphBounds = subgraph.GetBounds(false);
				float xToMove = xOffset - graphBounds.X;
				float yToMove = -graphBounds.Y;

				foreach (FCNode node in subgraph.Nodes)
				{
					RectangleF nodeBounds = node.Bounds;
					RectangleF oldBounds = node.Node.BoundingRect;
					nodeBounds.X += xToMove;
					nodeBounds.Y += yToMove;
					node.Bounds = nodeBounds;
					if (_layoutNode != null)
						_layoutNode(node.Node, oldBounds);
				}

				xOffset += graphBounds.Width;

				// Update arrows
				foreach (FCLink link in subgraph.Links)
				{
					Arrow arrow = link.Arrow;

					if (arrow.IgnoreLayout)
						continue;

					// If the arrow being arranged is dynamic,
					// ignore the anchoring flag?
					if (arrow.Dynamic)
						arrow.updatePosFromOrgAndDest(false);
					arrow.arrangePoints(_anchoring);

					if (_layoutLink != null)
						_layoutLink(arrow);
				}
			}

			chart.Invalidate();
			chart.UndoManager.onEndLayout();

			return true;
		}
示例#4
0
		public virtual bool Arrange(FlowChart chart)
		{
			chart.UndoManager.onStartLayout("Grid layout");

			// Build the graph
			FCGraph graph = new FCGraph(chart, _keepGroupLayout);

			// Find the root adapter
			Layout.INode rootNode = null;
			if (_root != null)
			{
				foreach (FCNode node in graph.Nodes)
				{
					if (node.Node == _root)
					{
						rootNode = node;
						break;
					}
				}
			}

			// Split graph to subgraphs
			Layout.IGraph[] subgraphs = null;

			if (_splitGraph)
			{
				subgraphs = Layout.GraphSplitter.Split(
					graph, new FCGraphBuilder(chart, false));
			}
			else
			{
				subgraphs = new Layout.IGraph[] { graph };
			}

			// Create the layouter
			Layout.GridLayout layout = new Layout.GridLayout();

			Layout.LayoutProgress progress = null;
			if (_progress != null)
				progress = new Layout.LayoutProgress(this.OnLayoutProgress);

			Layout.GridLayoutInfo info = new Layout.GridLayoutInfo();
			info.GridSize = this.GridSize;
			info.Iterations = this.Iterations;
			info.XGap = this.XGap;
			info.YGap = this.YGap;
			info.RndSeed = this.RndSeed;

			float xOffset = XGap;
			foreach (FCGraph subgraph in subgraphs)
			{
				// If a root node is specified and the subgraph
				// does not contain that node, do not arrange
				// the subgraph
				if (rootNode != null)
				{
					if (!subgraph.Nodes.Contains(rootNode))
						continue;
				}

				// Set the start and end nodes
				info.StartNode = null;
				info.EndNode = null;
				foreach (FCNode node in subgraph.Nodes)
				{
					if (node.Node == _startNode)
						info.StartNode = node;
					if (node.Node == _endNode)
						info.EndNode = node;
				}

				// Ensure both start and end nodes are set
				if (info.StartNode == null || info.EndNode == null)
				{
					info.StartNode = null;
					info.EndNode = null;
				}

				layout.Arrange(subgraph, info, progress);

				// Translate the whole subgraph
				RectangleF graphBounds = subgraph.GetBounds(false);
				float xToMove = xOffset - graphBounds.X;
				float yToMove = info.YGap - graphBounds.Y;

				foreach (FCNode node in subgraph.Nodes)
				{
					RectangleF nodeBounds = node.Bounds;
					RectangleF oldBounds = node.Node.BoundingRect;
					nodeBounds.X += xToMove;
					nodeBounds.Y += yToMove;
					node.Bounds = nodeBounds;
					if (_layoutNode != null)
						_layoutNode(node.Node, oldBounds);
				}

				xOffset += graphBounds.Width + info.GridSize;

				// Update arrows
				foreach (FCLink link in subgraph.Links)
				{
					if (link.Arrow.IgnoreLayout)
						continue;

					link.Arrow.arrangePoints(_anchoring);
					if (_layoutLink != null)
						_layoutLink(link.Arrow);
				}
			}

			chart.RouteAllArrows();
			chart.Invalidate();
			chart.UndoManager.onEndLayout();

			return true;
		}
示例#5
0
		public virtual bool Arrange(FlowChart chart)
		{
			chart.UndoManager.onStartLayout("Layered layout");

			// Disable undo to prevent unneeded actions.
			// For example: RouteAllArrows is invoked each time
			// when a new dummy box is created, which is a very
			// expensive operation even with no AutoRoute arrows present.
			bool undo = chart.UndoManager.UndoEnabled;
			chart.UndoManager.enable(false);

			// Build the graph
			FCGraph graph = new FCGraph(chart, _keepGroupLayout);

			// Find the root adapter
			Layout.INode rootNode = null;
			if (_root != null)
			{
				foreach (FCNode node in graph.Nodes)
				{
					if (node.Node == _root)
					{
						rootNode = node;
						break;
					}
				}
			}

			// Split graph to subgraphs
			Layout.IGraph[] subgraphs = Layout.GraphSplitter.Split(
				graph, new FCGraphBuilder(chart, false));

			// Make sure all arrows are polylines with 1 segment.
			// Arrows' AutoRoute flag is also undesired.
			// Note: Process only the arrows belonging to
			// the subgraph, which contains the specified root (if any)
			if (rootNode == null)
			{
				foreach (Arrow arrow in chart.Arrows)
				{
					if (arrow.isReflexive())
						continue;

					arrow.AutoRoute = false;
					arrow.Style = MindFusion.FlowChartX.ArrowStyle.Polyline;
					arrow.SegmentCount = 1;
				}
			}
			else
			{
				foreach (FCGraph subgraph in subgraphs)
				{
					if (subgraph.Nodes.Contains(rootNode))
					{
						foreach (FCLink link in subgraph.Links)
						{
							Arrow arrow = link.Arrow;

							if (arrow.isReflexive())
								continue;

							arrow.AutoRoute = false;
							arrow.Style = MindFusion.FlowChartX.ArrowStyle.Polyline;
							arrow.SegmentCount = 1;
						}

						break;
					}
				}
			}

			// Create the layouter
			Layout.LayeredLayout layout = new Layout.LayeredLayout();

			Layout.LayoutProgress progress = null;
			if (_progress != null)
				progress = new Layout.LayoutProgress(this.OnLayoutProgress);

			Layout.LayeredLayoutInfo info = new Layout.LayeredLayoutInfo();
			info.ArrowsCompactFactor = this.ArrowsCompactFactor;
			info.Direction = (Layout.Direction)this.Direction;
			info.LayerDistance = this.LayerDistance;
			info.NodeDistance = this.NodeDistance;
			info.Orientation = (Layout.Orientation)this.Orientation;
			info.SplitLayers = this.SplitLayers;
			info.XGap = this.XGap;
			info.YGap = this.YGap;
			info.TimeLimit = this.TimeLimit;

			float xOffset = this.XGap;
			foreach (FCGraph subgraph in subgraphs)
			{
				// If a root node is specified and the subgraph
				// does not contain that node, do not arrange
				// the subgraph
				if (rootNode != null)
				{
					if (!subgraph.Nodes.Contains(rootNode))
						continue;
				}

				layout.Arrange(subgraph, info, progress);

				// Translate the whole subgraph
				RectangleF graphBounds = subgraph.GetBounds(true);
				float xToMove = xOffset - graphBounds.X;
				float yToMove = this.YGap - graphBounds.Y;

				foreach (FCNode node in subgraph.Nodes)
				{
					RectangleF nodeBounds = node.Bounds;
					RectangleF oldBounds = node.Node.BoundingRect;
					nodeBounds.X += xToMove;
					nodeBounds.Y += yToMove;
					node.Bounds = nodeBounds;
					if (_layoutNode != null)
						_layoutNode(node.Node, oldBounds);
				}

				// Update arrows' inner points; the end points
				// must have already been offset by the loop above
				foreach (FCLink link in subgraph.Links)
				{
					// Arrows that retain form need not be updated
					if (link.Arrow.RetainForm)
						continue;

					for (int i = 1; i < link.Arrow.Points.Count - 1; i++)
					{
						PointF pt = link.Arrow.Points[i];
						pt.X += xToMove;
						pt.Y += yToMove;
						link.Arrow.Points[i] = pt;
					}
				}

				xOffset += graphBounds.Width + this.XGap;

				// Update arrows
				foreach (FCLink link in subgraph.Links)
				{
					Arrow arrow = link.Arrow;

					if (arrow.IgnoreLayout)
						continue;

					// Update end points
					if (arrow.SegmentCount == 1)
					{
						arrow.arrangePoints(_anchoring);
					}
					else
					{
						int orgnAnchor = arrow.OrgnAnchor;
						int destAnchor = arrow.DestAnchor;

						arrow.Points[0] = arrow.getOrgnLink().getIntersection(
							arrow.Origin.getCenter(), arrow.Points[1]);
						arrow.Points[arrow.Points.Count - 1] = arrow.getDestLink().getIntersection(
							arrow.Points[arrow.Points.Count - 2], arrow.Destination.getCenter());

						switch (_anchoring)
						{

							case Anchoring.Ignore:
								// Do nothing
								break;

							case Anchoring.Keep:
								if (orgnAnchor >= 0)
								{
									arrow.OrgnAnchor = -1;
									arrow.OrgnAnchor = orgnAnchor;
								}
								if (destAnchor >= 0)
								{
									arrow.DestAnchor = -1;
									arrow.DestAnchor = destAnchor;
								}
								break;

							case Anchoring.Reassign:
								arrow.Points[0] =
									arrow.Origin.getNearestAnchor(
									arrow.Points[0], arrow, false, ref orgnAnchor);
								arrow.Points[arrow.Points.Count - 1] =
									arrow.Destination.getNearestAnchor(
									arrow.Points[arrow.Points.Count - 1], arrow, true, ref destAnchor);
								arrow.setOrgnAnchor(orgnAnchor);
								arrow.setDestAnchor(destAnchor);
								break;

						}
					}

					arrow.UpdateFromPoints();

					if (_layoutLink != null)
						_layoutLink(arrow);
				}
			}

			chart.Invalidate();
			chart.UndoManager.enable(undo);
			chart.UndoManager.onEndLayout();

			return true;
		}
示例#6
0
		public virtual bool Arrange(FlowChart chart)
		{
			chart.UndoManager.onStartLayout("Spring layout");

			// Build the graph
			FCGraph graph = new FCGraph(chart, _keepGroupLayout);

			// Find the root adapter
			Layout.INode rootNode = null;
			if (_root != null)
			{
				foreach (FCNode node in graph.Nodes)
				{
					if (node.Node == _root)
					{
						rootNode = node;
						break;
					}
				}
			}

			// Split graph to subgraphs
			Layout.IGraph[] subgraphs = Layout.GraphSplitter.Split(
				graph, new FCGraphBuilder(chart, false));

			// Create the layouter
			Layout.SpringLayout layout = new Layout.SpringLayout();
			layout.Stretch = _stretch;

			Layout.LayoutProgress progress = null;
			if (_progress != null)
				progress = new Layout.LayoutProgress(this.OnLayoutProgress);

			Layout.SpringLayoutInfo info = new Layout.SpringLayoutInfo();
			info.IterationCount = this.IterationCount;
			info.MinimizeCrossings = this.MinimizeCrossings;
			info.NodeDistance = this.NodeDistance;
			info.EnableClusters = this.EnableClusters;
			info.RepulsionFactor = this.RepulsionFactor;
			info.RndSeed = this.RndSeed;

			float xOffset = 0;
			foreach (FCGraph subgraph in subgraphs)
			{
				// If a root node is specified and the subgraph
				// does not contain that node, do not arrange
				// the subgraph
				if (rootNode != null)
				{
					if (!subgraph.Nodes.Contains(rootNode))
						continue;
				}

				layout.Arrange(subgraph, info, progress);

				// Translate the whole subgraph
				RectangleF graphBounds = subgraph.GetBounds(false);
				float xToMove = xOffset - graphBounds.X;
				float yToMove = -graphBounds.Y;

				foreach (FCNode node in subgraph.Nodes)
				{
					RectangleF nodeBounds = node.Bounds;
					RectangleF oldBounds = node.Node.BoundingRect;
					nodeBounds.X += xToMove;
					nodeBounds.Y += yToMove;
					node.Bounds = nodeBounds;
					if (_layoutNode != null)
						_layoutNode(node.Node, oldBounds);
				}

				xOffset += graphBounds.Width + this.NodeDistance;

				// Update arrows
				foreach (FCLink link in subgraph.Links)
				{
					Arrow arrow = link.Arrow;

					if (arrow.IgnoreLayout)
						continue;

					// If the arrow being arranged is dynamic,
					// ignore the anchoring flag?
					if (arrow.Dynamic)
						arrow.updatePosFromOrgAndDest(false);
					arrow.arrangePoints(_anchoring);

					if (_layoutLink != null)
						_layoutLink(arrow);
				}
			}

			chart.Invalidate();
			chart.UndoManager.onEndLayout();

			return true;
		}
示例#7
0
		/// <summary>
		/// Performs the arrangement.
		/// </summary>
		public virtual bool Arrange(FlowChart chart)
		{
			if (_ignoreArrowDirection && _root == null)
				return false;

			chart.UndoManager.onStartLayout("Tree layout");

			// Build the graph
			FCGraph graph = null;
			if (_reversedArrows)
			{
				graph = new ReversedFCGraph(chart,
					_keepGroupLayout, _ignoreArrowDirection);
			}
			else
			{
				graph = new FCGraph(chart,
					_keepGroupLayout, _ignoreArrowDirection);
			}

			// Get the root node within the graph
			Layout.INode rootNode = null;
			if (_root != null)
			{
				foreach (FCNode node in graph.Nodes)
				{
					if (node.Node == _root)
					{
						rootNode = node;
						break;
					}
				}
			}

			CalculateAnchors();

			// Split graph to subgraphs
			Layout.IGraph[] subgraphs =
				Layout.GraphSplitter.Split(graph,
				new FCGraphBuilder(chart, _reversedArrows));

			float xOffset = this.XGap;
			foreach (FCGraph subgraph in subgraphs)
			{
				Layout.INode theRoot = null;
				if (subgraph.Nodes.Contains(rootNode))
				{
					// The root node of the user is within this
					// subgraph - respect the user's wishes
					theRoot = rootNode;
				}
				else
				{
					// If the user specified a root node,
					// arrange only the graph, containing
					// that node
					if (rootNode != null)
						continue;

					// If the subgraph has root node, use it,
					// otherwise select the first node as root
					Layout.INode subRoot = subgraph.Root;

					if (subRoot == null)
						theRoot = subgraph.Nodes[0];
					else
						theRoot = subRoot;
				}

				// Check if the root is layoutable
				if ((theRoot as FCNode).Node.Frozen)
					continue;

				Layout.LayoutProgress progress = null;
				if (_progress != null)
					progress = new Layout.LayoutProgress(
						this.OnLayoutProgress);

				Layout.TreeLayoutInfo info = 
					new Layout.TreeLayoutInfo();
				info.Direction = (Layout.TreeLayoutDirection)this.Direction;
				info.KeepRootPosition = this.KeepRootPosition;
				info.LevelDistance = this.LevelDistance;
				info.NodeDistance = this.NodeDistance;
				info.StretchFactor = this.StretchFactor;
				info.XGap = this.XGap;
				info.YGap = this.YGap;

				if (_layoutNode != null)
				{
					// remember the old positions
					foreach (FCNode node in subgraph.Nodes)
						node.Node.setData(Constants.OLD_BOUNDS, node.Node.BoundingRect);
				}

				// Arrange the subgraph
				switch (_type)
				{

					case TreeLayoutType.Cascading:
						new Layout.BorderTreeLayout().Arrange(
							theRoot, info, progress);
						break;

					case TreeLayoutType.Centered:
						new Layout.CenterTreeLayout().Arrange(
							theRoot, info, progress);
						break;

					case TreeLayoutType.Radial:
						new Layout.RadialTreeLayout().Arrange(
							theRoot, info, progress);
						break;

				}

				// If the root is not at fixed position, translate the whole tree
				if (!this.KeepRootPosition)
				{
					RectangleF graphBounds = subgraph.GetBounds(false);
					float xToMove = xOffset - graphBounds.X;
					float yToMove = this.YGap - graphBounds.Y;

					foreach (FCNode node in subgraph.Nodes)
					{
						RectangleF nodeBounds = node.Bounds;
						nodeBounds.X += xToMove;
						nodeBounds.Y += yToMove;
						node.Bounds = nodeBounds;
					}

					xOffset += graphBounds.Width + this.XGap;
				}

				if (_layoutNode != null)
				{
					// raise the LayoutNode event for each node
					foreach (FCNode node in subgraph.Nodes)
						_layoutNode(node.Node, (RectangleF)node.Node.getData(Constants.OLD_BOUNDS));
					chart.clearRuntimeData(Constants.OLD_BOUNDS);
				}

				// Update the arrows in this particular subgraph
				ArrayList visitedLinks = new ArrayList();
				ArrayList nodes = new ArrayList();

				nodes.Add(theRoot);

				while (nodes.Count > 0)
				{
					FCNode node = nodes[0] as FCNode;
					nodes.RemoveAt(0);

					if (node.Node.Frozen)
						continue;

					foreach (FCLink link in node.OutLinks)
					{
						if (!visitedLinks.Contains(link))
						{
							visitedLinks.Add(link);

							if (!link.Arrow.IgnoreLayout)
							{
								if (link.Destination == node)
								{
									UpdateArrow(link.Arrow, true);
									nodes.Add(link.Origin);
								}
								else
								{
									UpdateArrow(link.Arrow, false);
									nodes.Add(link.Destination);
								}

								if (_layoutLink != null)
									_layoutLink(link.Arrow);
							}
						}
					}
				}
			}

			chart.Invalidate();
			chart.UndoManager.onEndLayout();

			return true;
		}