Exemple #1
0
 public GitRevision GetRowData(int aRow)
 {
     lock (_graphData)
     {
         Graph.ILaneRow row = _graphData[aRow];
         return(row == null ? null : row.Node.Data);
     }
 }
        private bool DrawVisibleGraph(int start, int end)
        {
            for (int rowIndex = start; rowIndex < end; rowIndex++)
            {
                Graph.ILaneRow row = _graphData[rowIndex];
                if (row == null)
                {
                    // This shouldn't be happening...If it does, clear the cache so we
                    // eventually pick it up.
                    Debug.WriteLine("Draw lane {0} NO DATA", rowIndex.ToString());
                    ClearDrawCache();
                    return(false);
                }

                Region oldClip = _graphWorkArea.Clip;

                // Get the x,y value of the current item's upper left in the cache
                int       curCacheRow = (_cacheHeadRow + rowIndex - _cacheHead) % _cacheCountMax;
                const int x           = 0;
                int       y           = curCacheRow * _rowHeight;

                var laneRect = new Rectangle(0, y, Width, _rowHeight);
                if (rowIndex == start || curCacheRow == 0)
                {
                    // Draw previous row first. Clip top to row. We also need to clear the area
                    // before we draw since nothing else would clear the top 1/2 of the item to draw.
                    _graphWorkArea.RenderingOrigin = new Point(x, y - _rowHeight);
                    var newClip = new Region(laneRect);
                    _graphWorkArea.Clip = newClip;
                    _graphWorkArea.Clear(Color.Transparent);
                    DrawItem(_graphWorkArea, _graphData[rowIndex - 1]);
                    _graphWorkArea.Clip = oldClip;
                }

                bool isLast = rowIndex == end - 1;
                if (isLast)
                {
                    var newClip = new Region(laneRect);
                    _graphWorkArea.Clip = newClip;
                }

                _graphWorkArea.RenderingOrigin = new Point(x, y);
                bool success = DrawItem(_graphWorkArea, row);

                _graphWorkArea.Clip = oldClip;

                if (!success)
                {
                    ClearDrawCache();
                    return(false);
                }
            }

            return(true);
        }
Exemple #3
0
 public string GetRowId(int aRow)
 {
     lock (_graphData)
     {
         Graph.ILaneRow row = _graphData[aRow];
         if (row == null)
         {
             return(null);
         }
         return(row.Node.Id);
     }
 }
Exemple #4
0
 public IComparable GetRowId(int aRow)
 {
     lock (graphData)
     {
         Graph.ILaneRow row = graphData[aRow];
         if (row == null)
         {
             return(null);
         }
         return(row.Node.Id);
     }
 }
Exemple #5
0
 public object GetRowData(int aRow)
 {
     lock (graphData)
     {
         Graph.ILaneRow row = graphData[aRow];
         if (row == null)
         {
             return(null);
         }
         return(row.Node.Data);
     }
 }
Exemple #6
0
        public bool RowIsRelative(int aRow)
        {
            lock (_graphData)
            {
                Graph.ILaneRow row = _graphData[aRow];
                if (row == null)
                {
                    return(false);
                }

                if (row.Node.Ancestors.Count > 0)
                {
                    return(row.Node.Ancestors[0].IsRelative);
                }

                return(true);
            }
        }
Exemple #7
0
        private void dataGrid_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
        {
            if (e.RowIndex < 0)
            {
                return;
            }
            if (Rows[e.RowIndex].Height != RowTemplate.Height)
            {
                Rows[e.RowIndex].Height = RowTemplate.Height;
                dataGrid_Scroll(null, null);
            }

            lock (_graphData)
            {
                Graph.ILaneRow row = _graphData[e.RowIndex];
                if (row == null || (e.State & DataGridViewElementStates.Visible) == 0)
                {
                    return;
                }
                if (e.ColumnIndex != 0)
                {
                    return;
                }
                var brush = (e.State & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected
                                ? _selectionBrush : Brushes.White;
                e.Graphics.FillRectangle(brush, e.CellBounds);

                Rectangle srcRect = DrawGraph(e.RowIndex);
                if (!srcRect.IsEmpty)
                {
                    e.Graphics.DrawImage
                    (
                        _graphBitmap,
                        e.CellBounds,
                        srcRect,
                        GraphicsUnit.Pixel
                    );
                }

                e.Handled = true;
            }
        }
Exemple #8
0
        // 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) * _laneWidth);

                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, _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 = (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, 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++)
                {
                    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;
                            switch (i)
                            {
                            case 0:
                                penLine = _whiteBorderPen;
                                break;

                            case 1:
                                penLine = _blackBorderPen;
                                break;

                            default:
                                if (brushLineColorPen == null)
                                {
                                    brushLineColorPen = new Pen(brushLineColor, _laneLineWidth);
                                }

                                penLine = brushLineColorPen;
                                break;
                            }

                            if (singleLane)
                            {
                                wa.DrawLine(penLine, p0, p1);
                            }
                            else
                            {
                                wa.DrawBezier(penLine, p0, c0, c1, p1);
                            }
                        }
                    }
                    finally
                    {
                        brushLineColorPen?.Dispose();
                        ((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);
        }
Exemple #10
0
        // 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];

                        //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;
                            }
                        }

                        for (int i = drawBorder ? 0 : 2; i < 3; i++)
                        {
                            Pen penLine;
                            if (i == 0)
                            {
                                penLine = new Pen(new SolidBrush(Color.White), LANE_LINE_WIDTH + 2);
                            }
                            else if (i == 1)
                            {
                                penLine = new Pen(new SolidBrush(Color.Black), LANE_LINE_WIDTH + 1);
                            }
                            else
                            {
                                penLine = new Pen(brushLineColor, LANE_LINE_WIDTH);
                            }

                            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)
                                );
                            }
                        }
                    }
                }
            }

            // 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;
                bool         drawBorder = Settings.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);
        }
Exemple #11
0
        private bool DrawItem(Graphics wa, Graph.ILaneRow row)
        {
            ThreadHelper.AssertOnUIThread();

            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);

            // 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++)
                {
                    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);

                    UpdateJunctionColors(laneInfo.Junctions);

                    // Create the brush for drawing the line
                    Brush lineBrush = null;
                    Pen   linePen   = null;
                    try
                    {
                        bool drawBorder = highLight && AppSettings.BranchBorders; // hide border for "non-relatives"

                        if (_junctionColors.Count == 1 || !AppSettings.StripedBranchChange)
                        {
                            if (_junctionColors[0] != _nonRelativeColor)
                            {
                                lineBrush = new SolidBrush(_junctionColors[0]);
                            }
                            else if (_junctionColors.Count > 1 && _junctionColors[1] != _nonRelativeColor)
                            {
                                lineBrush = new SolidBrush(_junctionColors[1]);
                            }
                            else
                            {
                                drawBorder = false;
                                lineBrush  = new SolidBrush(_nonRelativeColor);
                            }
                        }
                        else
                        {
                            Color lastRealColor = _junctionColors.LastOrDefault(c => c != _nonRelativeColor);

                            if (lastRealColor.IsEmpty)
                            {
                                lineBrush  = new SolidBrush(_nonRelativeColor);
                                drawBorder = false;
                            }
                            else
                            {
                                lineBrush = new HatchBrush(HatchStyle.DarkDownwardDiagonal, _junctionColors[0], lastRealColor);
                            }
                        }

                        // Precalculate line endpoints
                        bool sameLane = laneInfo.ConnectLane == lane;
                        int  x0       = mid;
                        int  y0       = top - 1;
                        int  x1       = sameLane ? 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 (sameLane)
                        {
                            // We are drawing between two points in the same
                            // lane, so there will be no curve
                            c0 = c1 = default;
                        }
                        else
                        {
                            // Left shifting int is fast equivalent of dividing by two,
                            // thus computing the average of y0 and y1.
                            var yMid = (y0 + y1) >> 1;

                            c0 = new Point(x0, yMid);
                            c1 = new Point(x1, yMid);
                        }

                        for (int i = drawBorder ? 0 : 2; i < 3; i++)
                        {
                            Pen pen;
                            switch (i)
                            {
                            case 0:
                                pen = _whiteBorderPen;
                                break;

                            case 1:
                                pen = _blackBorderPen;
                                break;

                            default:
                                if (linePen == null)
                                {
                                    linePen = new Pen(lineBrush, _laneLineWidth);
                                }

                                pen = linePen;
                                break;
                            }

                            if (sameLane)
                            {
                                wa.DrawLine(pen, p0, p1);
                            }
                            else
                            {
                                wa.DrawBezier(pen, p0, c0, c1, p1);
                            }
                        }
                    }
                    finally
                    {
                        linePen?.Dispose();
                        lineBrush?.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;

            UpdateJunctionColors(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 drawNodeBorder = AppSettings.BranchBorders && highlight;

            if (_junctionColors.Count == 1)
            {
                nodeBrush = new SolidBrush(highlight ? _junctionColors[0] : _nonRelativeColor);
                if (_junctionColors[0] == _nonRelativeColor)
                {
                    drawNodeBorder = false;
                }
            }
            else
            {
                nodeBrush = new LinearGradientBrush(
                    nodeRect, _junctionColors[0], _junctionColors[1],
                    LinearGradientMode.Horizontal);
                if (_junctionColors.All(c => c == _nonRelativeColor))
                {
                    drawNodeBorder = false;
                }
            }

            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 (drawNodeBorder)
                {
                    wa.DrawRectangle(Pens.Black, nodeRect);
                }
            }
            else
            {
                wa.FillEllipse(nodeBrush, nodeRect);
                if (drawNodeBorder)
                {
                    wa.DrawEllipse(Pens.Black, nodeRect);
                }
            }

            nodeBrush.Dispose();

            return(true);

            void UpdateJunctionColors(IEnumerable <Junction> junction)
            {
                _junctionColors.Clear();

                // Color of non-relative branches.
                _junctionColors.AddRange(junction.Select(GetJunctionColor));

                if (_junctionColors.Count == 0)
                {
                    _junctionColors.Add(Color.Black);
                }
            }
        }
Exemple #12
0
        private Rectangle drawGraph(int aNeededRow)
        {
            lock (graphData)
            {
                if (aNeededRow < 0 || graphData.Count == 0 || graphData.Count <= aNeededRow)
                {
                    return(Rectangle.Empty);
                }

                #region Make sure the graph cache bitmap is setup

                int height = cacheCountMax * rowHeight;
                int width  = dataGridColumnGraph.Width;
                if (graphBitmap == null ||
                    //Resize the bitmap when the with or height is changed. The height won't change very often.
                    //The with changes more often, when branches become visible/invisible.
                    //Try to be 'smart' and not resize the bitmap for each little change. Enlarge when needed
                    //but never shrink the bitmap since the huge performance hit is worse than the little extra memory.
                    graphBitmap.Width < width || graphBitmap.Height != height)
                {
                    if (graphBitmap != null)
                    {
                        graphBitmap.Dispose();
                        graphBitmap = null;
                    }
                    if (width > 0 && height > 0)
                    {
                        graphBitmap   = new Bitmap(Math.Max(width, LANE_WIDTH * 3), height, PixelFormat.Format32bppPArgb);
                        graphWorkArea = Graphics.FromImage(graphBitmap);
                        graphWorkArea.SmoothingMode = SmoothingMode.AntiAlias;
                        cacheHead  = 0;
                        cacheCount = 0;
                    }
                    else
                    {
                        return(Rectangle.Empty);
                    }
                }

                #endregion

                // Compute how much the head needs to move to show the requested item.
                int neededHeadAdjustment = aNeededRow - cacheHead;
                if (neededHeadAdjustment > 0)
                {
                    neededHeadAdjustment -= cacheCountMax - 1;
                    if (neededHeadAdjustment < 0)
                    {
                        neededHeadAdjustment = 0;
                    }
                }
                int newRows = 0;
                if (cacheCount < cacheCountMax)
                {
                    newRows = (aNeededRow - cacheCount) + 1;
                }

                // Adjust the head of the cache
                cacheHead    = cacheHead + neededHeadAdjustment;
                cacheHeadRow = (cacheHeadRow + neededHeadAdjustment) % cacheCountMax;
                if (cacheHeadRow < 0)
                {
                    cacheHeadRow = cacheCountMax + cacheHeadRow;
                }

                int start;
                int end;
                if (newRows > 0)
                {
                    start      = cacheHead + cacheCount;
                    cacheCount = Math.Min(cacheCount + newRows, cacheCountMax);
                    end        = cacheHead + cacheCount;
                }
                else if (neededHeadAdjustment > 0)
                {
                    end   = cacheHead + cacheCount;
                    start = Math.Max(cacheHead, end - neededHeadAdjustment);
                }
                else if (neededHeadAdjustment < 0)
                {
                    start = cacheHead;
                    end   = start + Math.Min(cacheCountMax, -neededHeadAdjustment);
                }
                else
                {
                    // Item already in the cache
                    return(CreateRectangle(aNeededRow, width));
                }

                if (RevisionGraphVisible)
                {
                    for (int rowIndex = start; rowIndex < end; rowIndex++)
                    {
                        Graph.ILaneRow row = graphData[rowIndex];
                        if (row == null)
                        {
                            // This shouldn't be happening...If it does, clear the cache so we
                            // eventually pick it up.
                            Console.WriteLine("Draw lane {0} {1}", rowIndex, "NO DATA");
                            clearDrawCache();
                            return(Rectangle.Empty);
                        }

                        Region oldClip = graphWorkArea.Clip;

                        // Get the x,y value of the current item's upper left in the cache
                        int curCacheRow = (cacheHeadRow + rowIndex - cacheHead) % cacheCountMax;
                        int x           = 0;
                        int y           = curCacheRow * rowHeight;

                        var laneRect = new Rectangle(0, y, Width, rowHeight);
                        if (rowIndex == start || curCacheRow == 0)
                        {
                            // Draw previous row first. Clip top to row. We also need to clear the area
                            // before we draw since nothing else would clear the top 1/2 of the item to draw.
                            graphWorkArea.RenderingOrigin = new Point(x, y - rowHeight);
                            var newClip = new Region(laneRect);
                            graphWorkArea.Clip = newClip;
                            graphWorkArea.Clear(Color.Transparent);
                            drawItem(graphWorkArea, graphData[rowIndex - 1]);
                            graphWorkArea.Clip = oldClip;
                        }

                        bool isLast = (rowIndex == end - 1);
                        if (isLast)
                        {
                            var newClip = new Region(laneRect);
                            graphWorkArea.Clip = newClip;
                        }

                        graphWorkArea.RenderingOrigin = new Point(x, y);
                        bool success = drawItem(graphWorkArea, row);

                        graphWorkArea.Clip = oldClip;

                        if (!success)
                        {
                            clearDrawCache();
                            return(Rectangle.Empty);
                        }
                    }
                }

                return(CreateRectangle(aNeededRow, width));
            } // end lock
        }