protected internal override void Enter(int index, PlotCommit <L> currCommit) { SetupChildren(currCommit); int nChildren = currCommit.GetChildCount(); if (nChildren == 0) { return; } if (nChildren == 1 && currCommit.children[0].ParentCount < 2) { // Only one child, child has only us as their parent. // Stay in the same lane as the child. // PlotCommit c = currCommit.children[0]; if (c.lane == null) { // Hmmph. This child must be the first along this lane. // c.lane = NextFreeLane(); activeLanes.AddItem(c.lane); } for (int r = index - 1; r >= 0; r--) { PlotCommit rObj = this[r]; if (rObj == c) { break; } rObj.AddPassingLane(c.lane); } currCommit.lane = c.lane; } else { // More than one child, or our child is a merge. // Use a different lane. // // Process all our children. Especially important when there is more // than one child (e.g. a commit is processed where other branches // fork out). For each child the following is done // 1. If no lane was assigned to the child a new lane is created and // assigned // 2. The lane of the child is closed. If this frees a position, // this position will be added freePositions list. // If we have multiple children which where previously not on a lane // each such child will get his own new lane but all those new lanes // will be on the same position. We have to take care that not // multiple newly created (in step 1) lanes occupy that position on // which the // parent's lane will be on. Therefore we delay closing the lane // with the parents position until all children are processed. // The lane on that position the current commit will be on PlotLane reservedLane = null; for (int i = 0; i < nChildren; i++) { PlotCommit c = currCommit.children[i]; // don't forget to position all of your children if they are // not already positioned. if (c.lane == null) { c.lane = NextFreeLane(); activeLanes.AddItem(c.lane); if (reservedLane != null) { CloseLane(c.lane); } else { reservedLane = c.lane; } } else { if (reservedLane == null && activeLanes.Contains(c.lane)) { reservedLane = c.lane; } else { CloseLane(c.lane); } } } // finally all children are processed. We can close the lane on that // position our current commit will be on. if (reservedLane != null) { CloseLane(reservedLane); } currCommit.lane = NextFreeLane(); activeLanes.AddItem(currCommit.lane); // take care: when connecting yourself to your child make sure that // you will not be located on a lane on which a passed commit is // located on. Otherwise we would have to draw a line through a // commit. int remaining = nChildren; BitSet blockedPositions = new BitSet(); for (int r = index - 1; r >= 0; r--) { PlotCommit rObj = this[r]; if (currCommit.IsChild(rObj)) { if (--remaining == 0) { break; } } if (rObj != null) { PlotLane lane = rObj.GetLane(); if (lane != null) { blockedPositions.Set(lane.GetPosition()); } rObj.AddPassingLane(currCommit.lane); } } // Now let's check whether we have to reposition the lane if (blockedPositions.Get(currCommit.lane.GetPosition())) { int newPos = -1; foreach (int pos in freePositions) { if (!blockedPositions.Get(pos)) { newPos = pos; break; } } if (newPos == -1) { newPos = positionsAllocated++; } freePositions.AddItem(currCommit.lane.GetPosition()); currCommit.lane.position = newPos; } } }
/// <summary>Paint one commit using the underlying graphics library.</summary> /// <remarks>Paint one commit using the underlying graphics library.</remarks> /// <param name="commit">the commit to render in this cell. Must not be null.</param> /// <param name="h">total height (in pixels) of this cell.</param> protected internal virtual void PaintCommit(PlotCommit <TLane> commit, int h) { int dotSize = ComputeDotSize(h); TLane myLane = commit.GetLane(); int myLaneX = LaneC(myLane); TColor myColor = LaneColor(myLane); int maxCenter = 0; foreach (TLane passingLane in (TLane[])commit.passingLanes) { int cx = LaneC(passingLane); TColor c = LaneColor(passingLane); DrawLine(c, cx, 0, cx, h, LINE_WIDTH); maxCenter = Math.Max(maxCenter, cx); } int nParent = commit.ParentCount; for (int i = 0; i < nParent; i++) { PlotCommit <TLane> p; TLane pLane; TColor pColor; int cx; p = (PlotCommit <TLane>)commit.GetParent(i); pLane = p.GetLane(); if (pLane == null) { continue; } pColor = LaneColor(pLane); cx = LaneC(pLane); if (Math.Abs(myLaneX - cx) > LANE_WIDTH) { if (myLaneX < cx) { int ix = cx - LANE_WIDTH / 2; DrawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH); DrawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH); } else { int ix = cx + LANE_WIDTH / 2; DrawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH); DrawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH); } } else { DrawLine(pColor, myLaneX, h / 2, cx, h, LINE_WIDTH); } maxCenter = Math.Max(maxCenter, cx); } int dotX = myLaneX - dotSize / 2 - 1; int dotY = (h - dotSize) / 2; if (commit.GetChildCount() > 0) { DrawLine(myColor, myLaneX, 0, myLaneX, dotY, LINE_WIDTH); } if (commit.Has(RevFlag.UNINTERESTING)) { DrawBoundaryDot(dotX, dotY, dotSize, dotSize); } else { DrawCommitDot(dotX, dotY, dotSize, dotSize); } int textx = Math.Max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8; int n = commit.refs.Length; for (int i_1 = 0; i_1 < n; ++i_1) { textx += DrawLabel(textx + dotSize, h / 2, commit.refs[i_1]); } string msg = commit.GetShortMessage(); DrawText(msg, textx + dotSize + n * 2, h / 2); }
protected internal override void Enter(int index, PlotCommit <L> currCommit) { SetupChildren(currCommit); int nChildren = currCommit.GetChildCount(); if (nChildren == 0) { return; } if (nChildren == 1 && currCommit.children[0].ParentCount < 2) { // Only one child, child has only us as their parent. // Stay in the same lane as the child. // PlotCommit c = currCommit.children[0]; if (c.lane == null) { // Hmmph. This child must be the first along this lane. // c.lane = NextFreeLane(); activeLanes.AddItem(c.lane); } for (int r = index - 1; r >= 0; r--) { PlotCommit rObj = this[r]; if (rObj == c) { break; } rObj.AddPassingLane(c.lane); } currCommit.lane = c.lane; HandleBlockedLanes(index, currCommit, nChildren); } else { // More than one child, or our child is a merge. // Use a different lane. // // Process all our children. Especially important when there is more // than one child (e.g. a commit is processed where other branches // fork out). For each child the following is done // 1. If no lane was assigned to the child a new lane is created and // assigned // 2. The lane of the child is closed. If this frees a position, // this position will be added freePositions list. // If we have multiple children which where previously not on a lane // each such child will get his own new lane but all those new lanes // will be on the same position. We have to take care that not // multiple newly created (in step 1) lanes occupy that position on // which the // parent's lane will be on. Therefore we delay closing the lane // with the parents position until all children are processed. // The lane on that position the current commit will be on PlotLane reservedLane = null; for (int i = 0; i < nChildren; i++) { PlotCommit c = currCommit.children[i]; // don't forget to position all of your children if they are // not already positioned. if (c.lane == null) { c.lane = NextFreeLane(); activeLanes.AddItem(c.lane); if (reservedLane != null) { CloseLane(c.lane); } else { reservedLane = c.lane; } } else { if (reservedLane == null && activeLanes.Contains(c.lane)) { reservedLane = c.lane; } else { CloseLane(c.lane); } } } // finally all children are processed. We can close the lane on that // position our current commit will be on. if (reservedLane != null) { CloseLane(reservedLane); } currCommit.lane = NextFreeLane(); activeLanes.AddItem(currCommit.lane); HandleBlockedLanes(index, currCommit, nChildren); } }