Example #1
0
		private static GraphAtom[] BuildGraphLine0Child(IList<T> parents, T[] line, int[] linecolors, IGraphColorProvider cprov, ref int lineCount)
		{
			GraphAtom[] res;
			int lineColor = 0;
			// find position to insert dot
			int j = lineCount;
			while((j != 0) && (line[j - 1] == null))
			{
				--j;
			}
			// allocate memory for graph line
			switch(parents.Count)
			{
				case 0:
					// just a dot, generates no topology
					res = new GraphAtom[j + 1];
					// paint dot
					res[j].Paint(GraphElement.Dot, 0);
					break;
				case 1:
					// allocate color
					bool colorFound = false;
					int spaceId = -1;
					for(int i = 0; i < lineCount; ++i)
					{
						if(line[i] == parents[0] && !colorFound)
						{
							lineColor = linecolors[i];
							colorFound = true;
							if(spaceId != -1) break;
						}
						if(line[i] == null && spaceId == -1)
						{
							spaceId = i;
							if(colorFound) break;
						}
					}
					if(!colorFound)
					{
						lineColor = cprov.AcquireColor();
					}
					if(spaceId == -1)
					{
						// generate 1 new line
						lineCount = j + 1;
						res = new GraphAtom[lineCount];
					}
					else
					{
						j = spaceId;
						res = new GraphAtom[lineCount];
						ContinueVerticalLines(res, line, linecolors, j + 1, lineCount - 1);
					}
					// paint dot
					res[j].Paint(GraphElement.Dot, 0);
					line[j] = parents[0];
					linecolors[j] = lineColor;
					res[j].Paint(GraphElement.VerticalBottom, lineColor);
					break;
				default:
					var d = new Dictionary<int, int>(parents.Count);
					for(int p = 0; p < parents.Count; ++p)
					{
						for(int i = 0; i < lineCount; ++i)
						{
							if(line[i] == parents[p])
							{
								d.Add(p, i);
								break;
							}
						}
					}
					// generate parents - 1 new lines
					lineCount = j + 1 + parents.Count - d.Count - 1;
					if(d.Count == parents.Count)
					{
						res = new GraphAtom[j + 1];
					}
					else
					{
						res = new GraphAtom[j + 1 + parents.Count - d.Count - 1];
					}
					// paint dot
					res[j].Paint(GraphElement.Dot, 0);
					// paint lines for parents
					int newLineId = j;
					for(int i = 0; i < parents.Count; ++i)
					{
						int to;
						if(d.TryGetValue(i, out to))
						{
							lineColor = linecolors[to];
							DrawBottomConnection(res, lineColor, j, to);
						}
						else
						{
							// something like
							// ... ... ...
							// .+- --- ...
							// .|. \.. \..
							line[newLineId] = parents[i];
							linecolors[newLineId] = lineColor = cprov.AcquireColor();
							DrawBottomConnection(res, lineColor, j, newLineId);
							newLineId++;
						}
					}
					break;
			}
			// continue lines from previos graph lines, preserving color
			ContinueVerticalLines(res, line, linecolors, 0, j - 1);
			return res;
		}
Example #2
0
		private static int ColorLookup(T[] line, int lineCount, T parent, int[] linecolors, IGraphColorProvider cprov)
		{
			for(int i = 0; i < lineCount; ++i)
			{
				if(line[i] == parent) return linecolors[i];
			}
			return cprov.AcquireColor();
		}
Example #3
0
		private static void BuildUpperConnections(GraphAtom[] res, int[] linecolors, IGraphColorProvider cprov, IList<int> pos, int id)
		{
			int j = pos[id];
			for(int i = 0; i < pos.Count; ++i)
			{
				int cpos = pos[i];
				int lineColor = linecolors[i];
				if(cpos < j)
				{
					res[cpos].Paint(GraphElement.RightTopCorner, lineColor);
					if(i != pos.Count - 1)
					{
						int next = pos[i + 1];
						if(next >= j)
						{
							next = j - 1;
							res[j].Paint(GraphElement.HorizontalLeft, lineColor);
						}
						for(int k = cpos + 1; k <= next; ++k)
						{
							res[k].Paint(GraphElement.Horizontal, lineColor);
						}
					}
					else
					{
						int next = j - 1;
						res[j].Paint(GraphElement.HorizontalLeft, lineColor);
						for(int k = cpos + 1; k <= next; ++k)
						{
							res[k].Paint(GraphElement.Horizontal, lineColor);
						}
					}
					cprov.ReleaseColor(lineColor);
				}
				else if(cpos > j)
				{
					res[cpos].Paint(GraphElement.LeftTopCorner, lineColor);
					if(i != 0)
					{
						int prev = pos[i - 1];
						if(prev <= j)
						{
							prev = j + 1;
							res[j].Paint(GraphElement.HorizontalRight, lineColor);
						}
						for(int k = prev; k < cpos; ++k)
						{
							res[k].Paint(GraphElement.Horizontal, lineColor);
						}
					}
					else
					{
						int prev = j + 1;
						res[j].Paint(GraphElement.HorizontalRight, lineColor);
						for(int k = prev; k < cpos; ++k)
						{
							res[k].Paint(GraphElement.Horizontal, lineColor);
						}
					}
					cprov.ReleaseColor(lineColor);
				}
				else
				{
					res[cpos].Paint(GraphElement.VerticalTop, lineColor);
				}
			}
		}
Example #4
0
		private static GraphAtom[] BuildGraphLine(IList<T> parents, T[] line, int[] linecolors, IGraphColorProvider cprov, IList<int> pos, int id, ref int lineCount)
		{
			GraphAtom[] res;
			int j = pos[id];
			switch(parents.Count)
			{
				case 0:
					#region Line stops here
					{
						// allocate memory for new line
						res = new GraphAtom[lineCount];
						// paint
						// ...
						// .+.
						// ...
						res[j].Paint(GraphElement.Dot, 0);
						for(int i = 0; i < pos.Count; ++i)
						{
							line[pos[i]] = null;
						}
						cprov.ReleaseColor(linecolors[j]);
						if(j == lineCount - 1) // reduce graph width if it was last line
						{
							while(lineCount != 0 && line[lineCount - 1] == null)
							{
								--lineCount;
							}
						}
						// continue lines from previous graph line
						ContinueVerticalLines(res, line, linecolors, 0, lineCount - 1);
					}
					#endregion
					break;
				case 1:
					#region Line continues - most common case
					{
						int lineColor;
						if(pos.Count > 1)
						{
							lineColor = cprov.AcquireColor();
							cprov.ReleaseColor(linecolors[j]);
							linecolors[j] = lineColor;
						}
						else
						{
							lineColor = linecolors[j];
						}
						for(int i = 0; i < pos.Count; ++i)
						{
							line[pos[i]] = null;
						}
						line[j] = parents[0];
						// allocate memory for new graph line
						res = new GraphAtom[lineCount];
						// paint
						res[j].Paint(GraphElement.Dot, 0);
						res[j].Paint(GraphElement.VerticalBottom, lineColor);
						// continue lines from previous graph line
						ContinueVerticalLines(res, line, linecolors, 0, j - 1);
						ContinueVerticalLines(res, line, linecolors, j + 1, lineCount - 1);
					}
					#endregion
					break;
				default:
					#region Several lines start here (point where 1+ git branches were merged)
					{
						line[j] = null;
						bool lastItem = j == lineCount - 1;
						var lineColor = 0;
						Dictionary<T, int> unmergeable = null;
						var mergeable = new Dictionary<T, List<int>>(parents.Count);
						// find mergeable parents
						for(int i = 0; i < lineCount; ++i)
						{
							var p = line[i];
							if(p != null)
							{
								bool found = false;
								for(int c = 0; c < parents.Count; ++c)
								{
									if(p == parents[c])
									{
										found = true;
										List<int> positions;
										if(!mergeable.TryGetValue(p, out positions))
										{
											positions = new List<int>(parents.Count);
											mergeable.Add(p, positions);
										}
										positions.Add(i);
										break;
									}
								}
								if(found)
								{
									if(mergeable.Count == parents.Count) break;
								}
							}
						}
						if(parents.Count == mergeable.Count)
						{
							T closest = default(T);
							int closestPosition = 0;
							int minD = int.MaxValue;
							bool found = true;
							foreach(var kvp in mergeable)
							{
								var positions = kvp.Value;
								for(int i = 0; i < positions.Count; ++i)
								{
									if(positions[i] <= j)
									{
										found = false;
										break;
									}
									else
									{
										var d = positions[i] - j;
										if(d > 0 && d < minD)
										{
											closestPosition = j;
											minD = d;
											closest = kvp.Key;
										}
									}
								}
							}
							if(found)
							{
								var list = mergeable[closest];
								if(list.Count == 1)
								{
									mergeable.Remove(closest);
								}
								else
								{
									list.Remove(closestPosition);
								}
								unmergeable = new Dictionary<T, int>();
								unmergeable.Add(closest, j);
							}
						}
						else
						{
							// fill unmergeable
							int np = j;
							unmergeable = new Dictionary<T, int>(parents.Count - mergeable.Count);
							for(int c = 0; c < parents.Count; ++c)
							{
								var p = parents[c];
								if(!mergeable.ContainsKey(p))
								{
									while(line[np] != null && !pos.Contains(np))
									{
										++np;
									}
									unmergeable.Add(p, np);
									++np;
								}
							}
							if(np > lineCount)
							{
								lineCount = np;
							}
						}
						// allocate memory for new line
						res = new GraphAtom[lineCount];
						// paint dot
						res[j].Paint(GraphElement.Dot, 0);
						// paint mergeable
						foreach(var c in mergeable)
						{
							var positions = c.Value;
							int mind = int.MaxValue;
							int pid = 0;
							for(int p = 0; p < positions.Count; ++p)
							{
								int d = Math.Abs(j - positions[p]);
								if(d < mind)
								{
									mind = d;
									pid = p;
								}
							}
							int i = positions[pid];
							lineColor = linecolors[i];
							DrawBottomConnection(res, lineColor, j, i);
						}
						for(int i = 0; i < pos.Count; ++i)
						{
							line[pos[i]] = null;
						}
						// continue lines from previous graph line
						ContinueVerticalLines(res, line, linecolors, 0, lineCount - 1);
						// paint unmergeable
						int oldcolor = 0;
						if(unmergeable != null)
						{
							foreach(var c in unmergeable)
							{
								int i = c.Value;
								lineColor = cprov.AcquireColor();
								DrawBottomConnection(res, lineColor, j, i);
								if(i == j)
								{
									oldcolor = linecolors[i];
								}
								linecolors[i] = lineColor;
								line[i] = c.Key;
							}
						}
						cprov.ReleaseColor(oldcolor);
					}
					#endregion
					break;
			}
			return res;
		}