// end DrawGraph private bool DrawItem(Graphics wa, Graph.LaneRow row) { if (row == null || row.NodeLane == -1) { return false; } // Clip to the area we're drawing in, but draw 1 pixel past so // that the top/bottom of the line segment's anti-aliasing isn't // visible in the final rendering. int top = wa.RenderingOrigin.Y + _rowHeight / 2; var laneRect = new Rectangle(0, top, Width, _rowHeight); Region oldClip = wa.Clip; var newClip = new Region(laneRect); newClip.Intersect(oldClip); wa.Clip = newClip; wa.Clear(Color.Transparent); for (int r = 0; r < 2; r++) for (int lane = 0; lane < row.Count; lane++) { int mid = wa.RenderingOrigin.X + (int)((lane + 0.5) * LaneWidth); for (int item = 0; item < row.LaneInfoCount(lane); item++) { Graph.LaneInfo laneInfo = row[lane, item]; //Draw all non-relative items first, them draw //all relative items on top if (laneInfo.Junctions.FirstOrDefault() != null) if (laneInfo.Junctions.First().IsRelative == (r == 0)) continue; List<Color> curColors = GetJunctionColors(laneInfo.Junctions); // Create the brush for drawing the line Brush brushLineColor; bool drawBorder = BranchBorders; //hide border for "non-relatives" if (curColors.Count == 1 || !StripedBranchChange) { if (curColors[0] != _nonRelativeColor) { brushLineColor = new SolidBrush(curColors[0]); } else if (curColors.Count > 1 && curColors[1] != _nonRelativeColor) { brushLineColor = new SolidBrush(curColors[1]); } else { drawBorder = false; brushLineColor = new SolidBrush(_nonRelativeColor); } } else { brushLineColor = new HatchBrush(HatchStyle.DarkDownwardDiagonal, curColors[0], curColors[1]); if (curColors[0] == _nonRelativeColor && curColors[1] == _nonRelativeColor) drawBorder = false; } for (int i = drawBorder ? 0 : 2; i < 3; i++) { Pen penLine; if (i == 0) { penLine = new Pen(new SolidBrush(Color.White), LaneLineWidth + 2); } else if (i == 1) { penLine = new Pen(new SolidBrush(Color.Black), LaneLineWidth + 1); } else { penLine = new Pen(brushLineColor, LaneLineWidth); } if (laneInfo.ConnectLane == lane) { wa.DrawLine ( penLine, new Point(mid, top - 1), new Point(mid, top + _rowHeight + 2) ); } else { wa.DrawBezier ( penLine, new Point(mid, top - 1), new Point(mid, top + _rowHeight + 2), new Point(mid + (laneInfo.ConnectLane - lane) * LaneWidth, top - 1), new Point(mid + (laneInfo.ConnectLane - lane) * LaneWidth, top + _rowHeight + 2) ); } } } } // Reset the clip region wa.Clip = oldClip; { // Draw node var nodeRect = new Rectangle ( wa.RenderingOrigin.X + (LaneWidth - NodeDimensions) / 2 + row.NodeLane * LaneWidth, wa.RenderingOrigin.Y + (_rowHeight - NodeDimensions) / 2, NodeDimensions, NodeDimensions ); Brush nodeBrush; bool drawBorder = BranchBorders; List<Color> nodeColors = GetJunctionColors(row.Node.Ancestors); if (nodeColors.Count == 1) { nodeBrush = new SolidBrush(nodeColors[0]); if (nodeColors[0] == _nonRelativeColor) drawBorder = false; } else { nodeBrush = new LinearGradientBrush(nodeRect, nodeColors[0], nodeColors[1], LinearGradientMode.Horizontal); if (nodeColors[0] == _nonRelativeColor && nodeColors[1] == Color.LightGray) drawBorder = false; } if (_filterMode == FilterType.Highlight && row.Node.IsFiltered) { Rectangle highlightRect = nodeRect; highlightRect.Inflate(2, 3); wa.FillRectangle(Brushes.Yellow, highlightRect); wa.DrawRectangle(new Pen(Brushes.Black), highlightRect); } if (row.Node.Data == null) { wa.FillEllipse(Brushes.White, nodeRect); wa.DrawEllipse(new Pen(Color.Red, 2), nodeRect); } else if (row.Node.IsActive) { wa.FillRectangle(nodeBrush, nodeRect); nodeRect.Inflate(1, 1); wa.DrawRectangle(new Pen(Color.Black, 3), nodeRect); } else if (row.Node.IsSpecial) { wa.FillRectangle(nodeBrush, nodeRect); if (drawBorder) { wa.DrawRectangle(new Pen(Color.Black, 1), nodeRect); } } else { wa.FillEllipse(nodeBrush, nodeRect); if (drawBorder) { wa.DrawEllipse(new Pen(Color.Black, 1), nodeRect); } } } return true; }
private void DrawItemLoop(Graphics wa, Graph.ILaneRow row, int top) { for (int r = 0; r < 2; r++) for (int lane = 0; lane < row.Count; lane++) { int mid = wa.RenderingOrigin.X + (int)((lane + 0.5) * LANE_WIDTH); for (int item = 0; item < row.LaneInfoCount(lane); item++) { Graph.LaneInfo laneInfo = row[lane, item]; //Draw all non-relative items first, them draw //all relative items on top if (laneInfo.Junctions.FirstOrDefault() != null) if (laneInfo.Junctions.First().IsRelative == (r == 0)) continue; List<Color> curColors = GetJunctionColors(laneInfo.Junctions); // Create the brush for drawing the line Brush brushLineColor; bool drawBorder = Settings.BranchBorders; //hide border for "non-relatives" if (curColors.Count == 1 || !Settings.StripedBranchChange) { if (curColors[0] != nonRelativeColor) { brushLineColor = new SolidBrush(curColors[0]); } else if (curColors.Count > 1 && curColors[1] != nonRelativeColor) { brushLineColor = new SolidBrush(curColors[1]); } else { drawBorder = false; brushLineColor = new SolidBrush(nonRelativeColor); } } else { brushLineColor = new HatchBrush(HatchStyle.DarkDownwardDiagonal, curColors[0], curColors[1]); if (curColors[0] == nonRelativeColor && curColors[1] == nonRelativeColor) drawBorder = false; } laneInfo = DrawPenLoop(wa, top, lane, mid, laneInfo, brushLineColor, drawBorder); } } }
// end drawGraph private bool DrawItem(Graphics wa, Graph.ILaneRow row) { if (row == null || row.NodeLane == -1) { return false; } // Clip to the area we're drawing in, but draw 1 pixel past so // that the top/bottom of the line segment's anti-aliasing isn't // visible in the final rendering. int top = wa.RenderingOrigin.Y + rowHeight / 2; var laneRect = new Rectangle(0, top, Width, rowHeight); Region oldClip = wa.Clip; var newClip = new Region(laneRect); newClip.Intersect(oldClip); wa.Clip = newClip; wa.Clear(Color.Transparent); //for (int r = 0; r < 2; r++) for (int lane = 0; lane < row.Count; lane++) { int mid = wa.RenderingOrigin.X + (int)((lane + 0.5) * LANE_WIDTH); for (int item = 0; item < row.LaneInfoCount(lane); item++) { Graph.LaneInfo laneInfo = row[lane, item]; bool highLight = (RevisionGraphDrawStyle == RevisionGraphDrawStyleEnum.DrawNonRelativesGray && laneInfo.Junctions.Any(j => j.IsRelative)) || (RevisionGraphDrawStyle == RevisionGraphDrawStyleEnum.HighlightSelected && laneInfo.Junctions.Any(j => j.HighLight)) || (RevisionGraphDrawStyle == RevisionGraphDrawStyleEnum.Normal); List<Color> curColors = GetJunctionColors(laneInfo.Junctions); // Create the brush for drawing the line Brush brushLineColor = null; Pen brushLineColorPen = null; try { bool drawBorder = Settings.BranchBorders && highLight; //hide border for "non-relatives" if (curColors.Count == 1 || !Settings.StripedBranchChange) { if (curColors[0] != nonRelativeColor) { brushLineColor = new SolidBrush(curColors[0]); } else if (curColors.Count > 1 && curColors[1] != nonRelativeColor) { brushLineColor = new SolidBrush(curColors[1]); } else { drawBorder = false; brushLineColor = new SolidBrush(nonRelativeColor); } } else { Color lastRealColor = curColors.LastOrDefault(c => c != nonRelativeColor); if (lastRealColor.IsEmpty) { brushLineColor = new SolidBrush(nonRelativeColor); drawBorder = false; } else { brushLineColor = new HatchBrush(HatchStyle.DarkDownwardDiagonal, curColors[0], lastRealColor); } } for (int i = drawBorder ? 0 : 2; i < 3; i++) { Pen penLine = null; if (i == 0) { penLine = whiteBorderPen; } else if (i == 1) { penLine = blackBorderPen; } else { if (brushLineColorPen == null) brushLineColorPen = new Pen(brushLineColor, LANE_LINE_WIDTH); penLine = brushLineColorPen; } if (laneInfo.ConnectLane == lane) { wa.DrawLine ( penLine, new Point(mid, top - 1), new Point(mid, top + rowHeight + 2) ); } else { wa.DrawBezier ( penLine, new Point(mid, top - 1), new Point(mid, top + rowHeight + 2), new Point(mid + (laneInfo.ConnectLane - lane) * LANE_WIDTH, top - 1), new Point(mid + (laneInfo.ConnectLane - lane) * LANE_WIDTH, top + rowHeight + 2) ); } } } finally { if (brushLineColorPen != null) ((IDisposable)brushLineColorPen).Dispose(); if (brushLineColor != null) ((IDisposable)brushLineColor).Dispose(); } } } // Reset the clip region wa.Clip = oldClip; { // Draw node var nodeRect = new Rectangle ( wa.RenderingOrigin.X + (LANE_WIDTH - NODE_DIMENSION) / 2 + row.NodeLane * LANE_WIDTH, wa.RenderingOrigin.Y + (rowHeight - NODE_DIMENSION) / 2, NODE_DIMENSION, NODE_DIMENSION ); Brush nodeBrush; List<Color> nodeColors = GetJunctionColors(row.Node.Ancestors); bool highlight = (RevisionGraphDrawStyle == RevisionGraphDrawStyleEnum.DrawNonRelativesGray && row.Node.Ancestors.Any(j => j.IsRelative)) || (RevisionGraphDrawStyle == RevisionGraphDrawStyleEnum.HighlightSelected && row.Node.Ancestors.Any(j => j.HighLight)) || (RevisionGraphDrawStyle == RevisionGraphDrawStyleEnum.Normal); bool drawBorder = Settings.BranchBorders && highlight; if (nodeColors.Count == 1) { nodeBrush = new SolidBrush(highlight ? nodeColors[0] : nonRelativeColor); if (nodeColors[0] == nonRelativeColor) drawBorder = false; } else { nodeBrush = new LinearGradientBrush(nodeRect, nodeColors[0], nodeColors[1], LinearGradientMode.Horizontal); if (nodeColors.All(c => c == nonRelativeColor)) drawBorder = false; } if (filterMode == FilterType.Highlight && row.Node.IsFiltered) { Rectangle highlightRect = nodeRect; highlightRect.Inflate(2, 3); wa.FillRectangle(Brushes.Yellow, highlightRect); wa.DrawRectangle(Pens.Black, highlightRect); } if (row.Node.Data == null) { wa.FillEllipse(Brushes.White, nodeRect); using (var pen = new Pen(Color.Red, 2)) { wa.DrawEllipse(pen, nodeRect); } } else if (row.Node.IsActive) { wa.FillRectangle(nodeBrush, nodeRect); nodeRect.Inflate(1, 1); using (var pen = new Pen(Color.Black, 3)) wa.DrawRectangle(pen, nodeRect); } else if (row.Node.IsSpecial) { wa.FillRectangle(nodeBrush, nodeRect); if (drawBorder) { wa.DrawRectangle(Pens.Black, nodeRect); } } else { wa.FillEllipse(nodeBrush, nodeRect); if (drawBorder) { wa.DrawEllipse(Pens.Black, nodeRect); } } } return true; }
private bool DrawItem(Graphics wa, Graph.ILaneRow row) { if (row == null || row.NodeLane == -1) { return false; } // Clip to the area we're drawing in, but draw 1 pixel past so // that the top/bottom of the line segment's anti-aliasing isn't // visible in the final rendering. int top = wa.RenderingOrigin.Y + _rowHeight / 2; var laneRect = new Rectangle(0, top, (int)wa.ClipBounds.Width, _rowHeight); Region oldClip = wa.Clip; var newClip = new Region(laneRect); newClip.Intersect(oldClip); wa.Clip = newClip; // wa.Clear(Color.Transparent); //Getting RevisionGraphDrawStyle results in call to AppSettings. This is not very cheap, cache. revisionGraphDrawStyleCache = RevisionGraphDrawStyle; //for (int r = 0; r < 2; r++) for (int lane = 0; lane < row.Count; lane++) { int mid = wa.RenderingOrigin.X + (int)((lane + 0.5) * _laneWidth); for (int item = 0; item < row.LaneInfoCount(lane); item++) { if (item > 2) { } Graph.LaneInfo laneInfo = row[lane, item]; bool highLight = (revisionGraphDrawStyleCache == RevisionGraphDrawStyleEnum.DrawNonRelativesGray && laneInfo.Junctions.Any(j => j.IsRelative)) || (revisionGraphDrawStyleCache == RevisionGraphDrawStyleEnum.HighlightSelected && laneInfo.Junctions.Any(j => j.HighLight)) || (revisionGraphDrawStyleCache == RevisionGraphDrawStyleEnum.Normal); List<Color> curColors = GetJunctionColors(laneInfo.Junctions); // Create the brush for drawing the line Brush brushLineColor = null; Pen brushLineColorPen = null; try { bool drawBorder = highLight && AppSettings.BranchBorders; //hide border for "non-relatives" if (curColors.Count == 1 || !AppSettings.StripedBranchChange) { if (curColors[0] != _nonRelativeColor) { brushLineColor = new SolidBrush(curColors[0]); } else if (curColors.Count > 1 && curColors[1] != _nonRelativeColor) { brushLineColor = new SolidBrush(curColors[1]); } else { drawBorder = false; brushLineColor = new SolidBrush(_nonRelativeColor); } } else { Color lastRealColor = curColors.LastOrDefault(c => c != _nonRelativeColor); if (lastRealColor.IsEmpty) { brushLineColor = new SolidBrush(_nonRelativeColor); drawBorder = false; } else { brushLineColor = new HatchBrush(HatchStyle.DarkDownwardDiagonal, curColors[0], lastRealColor); } } // Precalculate line endpoints bool singleLane = laneInfo.ConnectLane == lane; int x0 = mid; int y0 = top - 1; int x1 = singleLane ? x0 : mid + (laneInfo.ConnectLane - lane) * _laneWidth; int y1 = top + _rowHeight; Point p0 = new Point(x0, y0); Point p1 = new Point(x1, y1); // Precalculate curve control points when needed Point c0, c1; if (singleLane) { c0 = c1 = Point.Empty; } else { // Controls the curvature of cross-lane lines (0 = straight line, 1 = 90 degree turns) const float severity = 0.5f; c0 = new Point(x0, (int)(y0 * (1.0f - severity) + y1 * severity)); c1 = new Point(x1, (int)(y1 * (1.0f - severity) + y0 * severity)); } for (int i = drawBorder ? 0 : 2; i < 3; i++) { Pen penLine = null; if (i == 0) { penLine = _whiteBorderPen; } else if (i == 1) { penLine = _blackBorderPen; } else { if (brushLineColorPen == null) brushLineColorPen = new Pen(brushLineColor, _laneLineWidth); penLine = brushLineColorPen; } if (laneInfo.ConnectLane == lane) { wa.DrawLine ( penLine, new Point(mid, top - 1), new Point(mid, top + _rowHeight + 2) ); } else { wa.DrawBezier ( penLine, new Point(mid, top - 1), new Point(mid, top + _rowHeight + 2), new Point(mid + (laneInfo.ConnectLane - lane) * _laneWidth, top - 1), new Point(mid + (laneInfo.ConnectLane - lane) * _laneWidth, top + _rowHeight + 2) ); } } } finally { if (brushLineColorPen != null) ((IDisposable)brushLineColorPen).Dispose(); if (brushLineColor != null) ((IDisposable)brushLineColor).Dispose(); } } } // Reset the clip region wa.Clip = oldClip; { // Draw node var nodeRect = new Rectangle ( wa.RenderingOrigin.X + (_laneWidth - _nodeDimension) / 2 + row.NodeLane * _laneWidth, wa.RenderingOrigin.Y + (_rowHeight - _nodeDimension) / 2, _nodeDimension, _nodeDimension ); Brush nodeBrush; List<Color> nodeColors = GetJunctionColors(row.Node.Ancestors); bool highlight = (revisionGraphDrawStyleCache == RevisionGraphDrawStyleEnum.DrawNonRelativesGray && row.Node.Ancestors.Any(j => j.IsRelative)) || (revisionGraphDrawStyleCache == RevisionGraphDrawStyleEnum.HighlightSelected && row.Node.Ancestors.Any(j => j.HighLight)) || (revisionGraphDrawStyleCache == RevisionGraphDrawStyleEnum.Normal); bool drawBorder = AppSettings.BranchBorders && highlight; if (nodeColors.Count == 1) { nodeBrush = new SolidBrush(highlight ? nodeColors[0] : _nonRelativeColor); if (nodeColors[0] == _nonRelativeColor) drawBorder = false; } else { nodeBrush = new LinearGradientBrush(nodeRect, nodeColors[0], nodeColors[1], LinearGradientMode.Horizontal); if (nodeColors.All(c => c == _nonRelativeColor)) drawBorder = false; } if (_filterMode == FilterType.Highlight && row.Node.IsFiltered) { Rectangle highlightRect = nodeRect; highlightRect.Inflate(2, 3); wa.FillRectangle(Brushes.Yellow, highlightRect); wa.DrawRectangle(Pens.Black, highlightRect); } if (row.Node.Data == null) { wa.FillEllipse(Brushes.White, nodeRect); using (var pen = new Pen(Color.Red, 2)) { wa.DrawEllipse(pen, nodeRect); } } else if (row.Node.IsActive) { wa.FillRectangle(nodeBrush, nodeRect); nodeRect.Inflate(1, 1); using (var pen = new Pen(Color.Black, 3)) wa.DrawRectangle(pen, nodeRect); } else if (row.Node.IsSpecial) { wa.FillRectangle(nodeBrush, nodeRect); if (drawBorder) { wa.DrawRectangle(Pens.Black, nodeRect); } } else { wa.FillEllipse(nodeBrush, nodeRect); if (drawBorder) { wa.DrawEllipse(Pens.Black, nodeRect); } } } return true; }