상속: System.Windows.Forms.Form
예제 #1
0
        public DeltaHistogram()
        {
            base.GetItemValue   = (di) => di.BytesDelta;
            base.GetItemText    = (di) => di.Traceback.Frames.Array[di.Traceback.Frames.Offset].Function;
            base.GetItemTooltip = (di) => {
                var sf = CustomTooltip.GetDefaultStringFormat();

                var content = new DeltaInfoTooltipContent(
                    di, new DeltaInfo.RenderParams {
                    BackgroundBrush            = new SolidBrush(SystemColors.Info),
                    BackgroundColor            = SystemColors.Info,
                    TextBrush                  = new SolidBrush(SystemColors.InfoText),
                    IsExpanded                 = true,
                    IsSelected                 = false,
                    FunctionHighlightBrush     = new SolidBrush(SystemColors.Highlight),
                    FunctionHighlightTextBrush = new SolidBrush(SystemColors.HighlightText),
                    FunctionFilter             = FunctionFilter,
                    ShadeBrush                 = new SolidBrush(Color.FromArgb(31, 0, 0, 0)),
                    StringFormat               = sf
                }
                    );

                return(content);
            };
        }
예제 #2
0
        protected void ShowTooltip(int itemIndex, Point location)
        {
            if (Tooltip == null)
            {
                Tooltip = new CustomTooltip(this);
            }

            var item = Items[itemIndex];

            using (var g = CreateGraphics()) {
                var content = GetItemTooltip(item);

                content.Font     = Font;
                content.Location = PointToScreen(location);

                CustomTooltip.FitContentOnScreen(
                    g, content,
                    ref content.Font, ref content.Location, ref content.Size
                    );

                Tooltip.SetContent(content);
            }

            if (_HoverIndex != itemIndex)
            {
                var oldIndex = _HoverIndex;
                _HoverIndex = itemIndex;
                InvalidateItem(oldIndex);
                InvalidateItem(_HoverIndex);
            }
        }
예제 #3
0
        protected IEnumerator <object> FinishShowingTooltip(
            Point mouseLocation,
            HeapSnapshot.Heap heap,
            HeapSnapshot.Allocation allocation,
            HeapSnapshot.Traceback rawTraceback
            )
        {
            var uniqueRawFrames = rawTraceback.Frames.AsEnumerable().Distinct();

            var fSymbols = Instance.Database.SymbolCache.Select(uniqueRawFrames);

            using (fSymbols)
                yield return(fSymbols);

            var symbolDict = SequenceUtils.ToDictionary(
                uniqueRawFrames, fSymbols.Result
                );

            var tracebackInfo = HeapRecording.ConstructTracebackInfo(
                rawTraceback.ID, rawTraceback.Frames, symbolDict
                );

            var renderParams = new DeltaInfo.RenderParams {
                BackgroundBrush = new SolidBrush(SystemColors.Info),
                BackgroundColor = SystemColors.Info,
                TextBrush       = new SolidBrush(SystemColors.InfoText),
                IsExpanded      = true,
                IsSelected      = false,
                Font            = Font,
                ShadeBrush      = new SolidBrush(Color.FromArgb(31, 0, 0, 0)),
                StringFormat    = CustomTooltip.GetDefaultStringFormat()
            };

            var content = new HeapSnapshot.AllocationTooltipContent(
                ref allocation, ref tracebackInfo, ref renderParams
                )
            {
                Location = mouseLocation,
                Font     = Font
            };

            using (var g = CreateGraphics())
                CustomTooltip.FitContentOnScreen(
                    g, content,
                    ref content.RenderParams.Font,
                    ref content.Location, ref content.Size
                    );

            Tooltip.SetContent(content);
        }
예제 #4
0
        public GraphHistogram()
        {
            base.GetItemValue   = (sgn) => sgn.BytesRequested;
            base.GetItemText    = (sgn) => sgn.Key.ToString();
            base.GetItemTooltip = (sgn) => {
                var sf = CustomTooltip.GetDefaultStringFormat();

                TooltipContentBase content = new StackGraphTooltipContent(
                    sgn, sf
                    );

                return(content);
            };
        }
예제 #5
0
        protected void ShowTooltip(int itemIndex, Point location)
        {
            if (Tooltip == null)
            {
                Tooltip = new CustomTooltip(this);
            }

            var item = Items[itemIndex];
            var sf   = CustomTooltip.GetDefaultStringFormat();

            using (var g = CreateGraphics()) {
                var content = new DeltaInfoTooltipContent(
                    item, new DeltaInfo.RenderParams {
                    BackgroundBrush            = new SolidBrush(SystemColors.Info),
                    BackgroundColor            = SystemColors.Info,
                    TextBrush                  = new SolidBrush(SystemColors.InfoText),
                    IsExpanded                 = true,
                    IsSelected                 = false,
                    FunctionHighlightBrush     = new SolidBrush(SystemColors.Highlight),
                    FunctionHighlightTextBrush = new SolidBrush(SystemColors.HighlightText),
                    FunctionFilter             = FunctionFilter,
                    Font         = Font,
                    ShadeBrush   = new SolidBrush(Color.FromArgb(31, 0, 0, 0)),
                    StringFormat = sf
                }
                    )
                {
                    Location = this.PointToScreen(location)
                };

                CustomTooltip.FitContentOnScreen(
                    g, content,
                    ref content.RenderParams.Font,
                    ref content.Location, ref content.Size
                    );

                Tooltip.SetContent(content);
            }

            if (_HoverIndex != itemIndex)
            {
                var oldIndex = _HoverIndex;
                _HoverIndex = itemIndex;
                InvalidateItem(oldIndex);
                InvalidateItem(_HoverIndex);
            }
        }
예제 #6
0
        protected void ShowTooltip(LayoutItem item, Point location)
        {
            if (Tooltip == null)
            {
                Tooltip = new CustomTooltip(this);
            }

            using (var g = CreateGraphics()) {
                var content = GetItemTooltip(item.Item);

                content.Font     = Font;
                content.Location = PointToScreen(new Point(
                                                     (int)item.Rectangle.Left,
                                                     (int)item.Rectangle.Bottom + 2
                                                     ));

                CustomTooltip.FitContentOnScreen(
                    g, content,
                    ref content.Font, ref content.Location, ref content.Size
                    );

                Tooltip.SetContent(content);
            }

            if (_HoverItem != item)
            {
                var oldItem = _HoverItem;
                _HoverItem = item;

                if (oldItem != null)
                {
                    Invalidate(oldItem.Rectangle);
                }

                Invalidate(item.Rectangle);
            }
        }
예제 #7
0
        protected override void OnMouseMove(MouseEventArgs e)
        {
            HeapSnapshot.Heap heap;
            int allocationIndex;

            if (AllocationFromPoint(e.Location, out heap, out allocationIndex))
            {
                if ((heap != TooltipHeap) || (allocationIndex != TooltipAllocationIndex))
                {
                    TooltipAllocationIndex = allocationIndex;
                    TooltipHeap            = heap;

                    if (Tooltip == null)
                    {
                        Tooltip = new CustomTooltip(this);
                    }

                    Instance.Scheduler.Start(
                        FinishShowingTooltip(
                            PointToScreen(e.Location),
                            heap, heap.Allocations[allocationIndex],
                            Snapshot.Tracebacks[heap.Allocations[allocationIndex].TracebackID]
                            ),
                        TaskExecutionPolicy.RunAsBackgroundTask
                        );

                    Invalidate();
                }
            }
            else
            {
                HideTooltip();

                base.OnMouseMove(e);
            }
        }
예제 #8
0
        protected override void OnMouseMove(MouseEventArgs e)
        {
            HeapSnapshot.Heap heap;
            int allocationIndex;

            if (AllocationFromPoint(e.Location, out heap, out allocationIndex)) {
                if ((heap != TooltipHeap) || (allocationIndex != TooltipAllocationIndex)) {
                    TooltipAllocationIndex = allocationIndex;
                    TooltipHeap = heap;

                    if (Tooltip == null)
                        Tooltip = new CustomTooltip(this);

                    Instance.Scheduler.Start(
                        FinishShowingTooltip(
                            PointToScreen(e.Location),
                            heap, heap.Allocations[allocationIndex],
                            Snapshot.Tracebacks[heap.Allocations[allocationIndex].TracebackID]
                        ),
                        TaskExecutionPolicy.RunAsBackgroundTask
                    );

                    Invalidate();
                }
            } else {
                HideTooltip();

                base.OnMouseMove(e);
            }
        }
예제 #9
0
        protected override void OnPaint(PaintEventArgs e)
        {
            bool retrying = false, selectedItemVisible = false;
            int  minVisibleIndex = int.MaxValue, maxVisibleIndex = -int.MaxValue;

            int   width   = ClientSize.Width - ScrollBar.Width;
            float centerX = width / 2.0f;

            float max = GraphLog(Maximum);

retryFromHere:

            if (_SelectedIndex >= Items.Count)
            {
                _SelectedIndex = Items.Count - 1;
            }
            if (_SelectedIndex < 0)
            {
                _SelectedIndex = 0;
            }

            if (_ScrollOffset >= Items.Count)
            {
                _ScrollOffset = Items.Count - 1;
            }
            if (_ScrollOffset < 0)
            {
                _ScrollOffset = 0;
            }

            VisibleItems.Clear();

            ItemData         data;
            HashSet <string> textToFlush = new HashSet <string>(TextCache.Keys);

            using (var sf = CustomTooltip.GetDefaultStringFormat())
                using (var gridLineFont = new Font(Font.FontFamily, Font.Size * 0.85f, Font.Style))
                    using (var outlinePen = new Pen(Color.Black))
                        using (var activeOutlinePen = new Pen(SystemColors.HighlightText))
                            using (var gridPen = new Pen(Color.FromArgb(96, 0, 0, 0)))
                                using (var backgroundBrush = new SolidBrush(BackColor))
                                    using (var whiteOutlinePen = new Pen(Color.White, 2.5f))
                                        using (var blackOutlinePen = new Pen(Color.Black, 2.5f))
                                            using (var textBrush = new SolidBrush(ForeColor))
                                                using (var highlightBrush = new SolidBrush(SystemColors.Highlight)) {
                                                    blackOutlinePen.LineJoin = whiteOutlinePen.LineJoin = LineJoin.Round;

                                                    int marginHeight = 0;
                                                    for (int i = Maximum; i >= Math.Min(Maximum, 16); i /= 4)
                                                    {
                                                        marginHeight = Math.Max(marginHeight,
                                                                                (int)Math.Ceiling(e.Graphics.MeasureString(
                                                                                                      "+" + FormatSize(i), gridLineFont, ClientSize.Height, sf
                                                                                                      ).Width) + 1
                                                                                );
                                                    }

                                                    var rgn = new Rectangle(0, 0, width, marginHeight);

                                                    if (rgn.IntersectsWith(e.ClipRectangle))
                                                    {
                                                        using (var scratch = Scratch.Get(e.Graphics, rgn)) {
                                                            var g = scratch.Graphics;
                                                            g.Clear(BackColor);

                                                            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                                            g.DrawLine(gridPen, centerX, 0, centerX, marginHeight);

                                                            for (int i = Maximum; i >= Math.Min(Maximum, 16); i /= 4)
                                                            {
                                                                float x = (GraphLog(i) / max) * (width / 2.0f);

                                                                var formatted = FormatSize(i);

                                                                g.DrawLine(gridPen, centerX + x, 0, centerX + x, marginHeight);
                                                                var text = String.Format("+{0}", formatted);
                                                                textToFlush.Remove(text);
                                                                var bitmap = TextCache.Get(g, text, gridLineFont, RotateFlipType.Rotate90FlipNone, ForeColor, BackColor, sf, new SizeF(marginHeight, 999));
                                                                g.DrawImageUnscaled(bitmap, (int)(centerX + x), 0);

                                                                g.DrawLine(gridPen, centerX - x, 0, centerX - x, marginHeight);
                                                                text = String.Format("-{0}", formatted);
                                                                textToFlush.Remove(text);
                                                                bitmap = TextCache.Get(g, text, gridLineFont, RotateFlipType.Rotate90FlipNone, ForeColor, BackColor, sf, new SizeF(marginHeight, 999));
                                                                g.DrawImageUnscaled(bitmap, (int)(centerX - x - bitmap.Width), 0);
                                                            }
                                                        }
                                                    }

                                                    int y = marginHeight;

                                                    rgn = new Rectangle(0, y, width, ItemHeight);

                                                    if ((TotalDelta.GetValueOrDefault(0) != 0) && rgn.IntersectsWith(e.ClipRectangle))
                                                    {
                                                        using (var scratch = Scratch.Get(e.Graphics, rgn)) {
                                                            var barRectangle = ComputeBarRectangle(
                                                                TotalDelta.Value, centerX, rgn.Y, width, max
                                                                );

                                                            var g = scratch.Graphics;

                                                            g.ResetClip();
                                                            g.Clear(BackColor);

                                                            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                                                            g.DrawLine(gridPen, centerX, rgn.Y, centerX, rgn.Bottom);

                                                            g.DrawRectangle(
                                                                outlinePen, barRectangle.X, barRectangle.Y, barRectangle.Width, barRectangle.Height
                                                                );

                                                            var oldRenderingHint = g.TextRenderingHint;

                                                            try {
                                                                g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                                                                g.DrawString("Delta bytes", Font, textBrush, barRectangle.X, barRectangle.Y, sf);
                                                            } finally {
                                                                g.TextRenderingHint = oldRenderingHint;
                                                            }
                                                        }
                                                    }

                                                    if ((TotalDelta.GetValueOrDefault(0) != 0))
                                                    {
                                                        y += ItemHeight;
                                                    }

                                                    for (int i = _ScrollOffset; (i < Items.Count) && (y < ClientSize.Height); i++)
                                                    {
                                                        var selected = (i == SelectedIndex);

                                                        var item = Items[i];
                                                        GetItemData(i, out data);

                                                        rgn = new Rectangle(0, y, width, ItemHeight);
                                                        var bytesDelta = GetItemValue(item);

                                                        var barRectangle = ComputeBarRectangle(
                                                            bytesDelta, centerX, rgn.Y, width, max
                                                            );

                                                        var itemColor = SelectItemColor(item);

                                                        if (rgn.IntersectsWith(e.ClipRectangle))
                                                        {
                                                            using (var itemBrush = new SolidBrush(itemColor))
                                                                using (var scratch = Scratch.Get(e.Graphics, rgn)) {
                                                                    var g = scratch.Graphics;

                                                                    g.ResetClip();
                                                                    g.Clear(BackColor);

                                                                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                                                                    g.DrawLine(gridPen, centerX, rgn.Y, centerX, rgn.Bottom);

                                                                    g.FillRectangle(
                                                                        (_HoverIndex == i) ? highlightBrush : itemBrush,
                                                                        barRectangle
                                                                        );

                                                                    g.DrawRectangle(
                                                                        (_HoverIndex == i) ? activeOutlinePen : outlinePen,
                                                                        barRectangle.X - 0.5f, barRectangle.Y - 0.5f,
                                                                        barRectangle.Width + 1f, barRectangle.Height + 1f
                                                                        );

                                                                    string itemText = null;

                                                                    if ((GetItemText != null) && (itemText = GetItemText(item)) != null)
                                                                    {
                                                                        bool white = (itemColor.GetBrightness() <= 0.25f);

                                                                        textToFlush.Remove(itemText);
                                                                        var bitmap = TextCache.Get(
                                                                            g, itemText, Font, RotateFlipType.RotateNoneFlipNone,
                                                                            white ? Color.White : Color.Black,
                                                                            white ? Color.Black : Color.LightGray, sf,
                                                                            new SizeF(barRectangle.Width, barRectangle.Height)
                                                                            );

                                                                        g.DrawImageUnscaled(
                                                                            bitmap,
                                                                            (int)Math.Floor(barRectangle.X),
                                                                            (int)Math.Floor(barRectangle.Y)
                                                                            );
                                                                    }
                                                                }
                                                        }

                                                        VisibleItems.Add(new VisibleItem {
                                                            Rectangle = new Rectangle(
                                                                (int)Math.Floor(barRectangle.X),
                                                                (int)Math.Floor(barRectangle.Y),
                                                                (int)Math.Ceiling(barRectangle.Width),
                                                                (int)Math.Ceiling(barRectangle.Height)
                                                                ),
                                                            Index = i
                                                        });

                                                        y += ItemHeight;

                                                        if ((rgn.X >= 0) && (rgn.Right < ClientSize.Width))
                                                        {
                                                            minVisibleIndex      = Math.Min(minVisibleIndex, i);
                                                            maxVisibleIndex      = Math.Max(maxVisibleIndex, i);
                                                            selectedItemVisible |= selected;
                                                        }
                                                    }

                                                    if (y < ClientSize.Height)
                                                    {
                                                        e.Graphics.FillRectangle(backgroundBrush, new Rectangle(0, y, ClientSize.Width, ClientSize.Height - y));

                                                        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                                        e.Graphics.DrawLine(gridPen, centerX, y, centerX, ClientSize.Height);
                                                    }
                                                }

            if (!selectedItemVisible && !retrying && ShouldAutoscroll)
            {
                if (_SelectedIndex > maxVisibleIndex)
                {
                    _ScrollOffset += _SelectedIndex - maxVisibleIndex;
                }
                else if (_SelectedIndex < minVisibleIndex)
                {
                    _ScrollOffset -= minVisibleIndex - _SelectedIndex;
                }

                if (_ScrollOffset >= Items.Count)
                {
                    _ScrollOffset = Items.Count - 1;
                }
                if (_ScrollOffset < 0)
                {
                    _ScrollOffset = 0;
                }

                retrying = true;
                goto retryFromHere;
            }

            int largeChange = Math.Max(4, ClientSize.Width / ItemHeight);

            if (ScrollBar.LargeChange != largeChange)
            {
                ScrollBar.LargeChange = largeChange;
            }

            int scrollMax = Math.Max(1, Items.Count - 1) + largeChange - 1;

            if (ScrollBar.Maximum != scrollMax)
            {
                ScrollBar.Maximum = scrollMax;
            }
            if (ScrollBar.Value != ScrollOffset)
            {
                ScrollBar.Value = ScrollOffset;
            }

            TextCache.Flush(textToFlush);

            ShouldAutoscroll = false;
            base.OnPaint(e);
        }
예제 #10
0
        protected override void OnPaint(PaintEventArgs e)
        {
            bool retrying = false, selectedItemVisible = false;
            int  minVisibleIndex = int.MaxValue, maxVisibleIndex = -int.MaxValue;

            int   height  = ClientSize.Height - ScrollBar.Height;
            float centerY = height / 2.0f;

            float max = GraphLog(Maximum);

retryFromHere:

            if (_SelectedIndex >= Items.Count)
            {
                _SelectedIndex = Items.Count - 1;
            }
            if (_SelectedIndex < 0)
            {
                _SelectedIndex = 0;
            }

            if (_ScrollOffset >= Items.Count)
            {
                _ScrollOffset = Items.Count - 1;
            }
            if (_ScrollOffset < 0)
            {
                _ScrollOffset = 0;
            }

            VisibleItems.Clear();

            ItemData data;

            using (var sf = CustomTooltip.GetDefaultStringFormat())
                using (var gridLineFont = new Font(Font.FontFamily, Font.Size * 0.85f, Font.Style))
                    using (var outlinePen = new Pen(Color.Black))
                        using (var activeOutlinePen = new Pen(SystemColors.HighlightText))
                            using (var gridPen = new Pen(Color.FromArgb(96, 0, 0, 0)))
                                using (var backgroundBrush = new SolidBrush(BackColor))
                                    using (var textBrush = new SolidBrush(ForeColor))
                                        using (var highlightBrush = new SolidBrush(SystemColors.Highlight)) {
                                            int marginWidth = 0;
                                            for (int i = Maximum; i >= Math.Min(Maximum, 16); i /= 4)
                                            {
                                                marginWidth = Math.Max(marginWidth,
                                                                       (int)Math.Ceiling(e.Graphics.MeasureString(
                                                                                             "+" + FormatSize(i), gridLineFont, ClientSize.Width, sf
                                                                                             ).Width) + 1
                                                                       );
                                            }

                                            var rgn = new Rectangle(0, 0, marginWidth, height);

                                            if (rgn.IntersectsWith(e.ClipRectangle))
                                            {
                                                using (var scratch = Scratch.Get(e.Graphics, rgn)) {
                                                    var g = scratch.Graphics;
                                                    g.Clear(BackColor);

                                                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                                    g.DrawLine(gridPen, 0, centerY, marginWidth, centerY);

                                                    for (int i = Maximum; i >= Math.Min(Maximum, 16); i /= 4)
                                                    {
                                                        float y = (GraphLog(i) / max) * (height / 2.0f);

                                                        var formatted = FormatSize(i);

                                                        g.DrawLine(gridPen, 0, centerY - y, marginWidth, centerY - y);
                                                        var text = String.Format("+{0}", formatted);
                                                        g.DrawString(text, gridLineFont, textBrush, new PointF(0, centerY - y));

                                                        g.DrawLine(gridPen, 0, centerY + y, marginWidth, centerY + y);
                                                        text = String.Format("-{0}", formatted);
                                                        var sz = g.MeasureString(text, gridLineFont, marginWidth, sf);
                                                        g.DrawString(text, gridLineFont, textBrush, new PointF(0, centerY + y - sz.Height));
                                                    }
                                                }
                                            }

                                            int x = marginWidth;

                                            rgn = new Rectangle(x, 0, ItemWidth, height);
                                            if ((TotalDelta.GetValueOrDefault(0) != 0) && rgn.IntersectsWith(e.ClipRectangle))
                                            {
                                                using (var scratch = Scratch.Get(e.Graphics, rgn)) {
                                                    var barRectangle = ComputeBarRectangle(
                                                        TotalDelta.Value, rgn.X, centerY, height, max
                                                        );

                                                    var g = scratch.Graphics;

                                                    g.ResetClip();
                                                    g.Clear(BackColor);

                                                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                                                    g.DrawLine(gridPen, rgn.X, centerY, rgn.Right, centerY);

                                                    g.DrawRectangle(
                                                        outlinePen, barRectangle.X, barRectangle.Y, barRectangle.Width, barRectangle.Height
                                                        );

                                                    var oldTransform     = g.Transform;
                                                    var oldAlignment     = sf.LineAlignment;
                                                    var oldRenderingHint = g.TextRenderingHint;

                                                    try {
                                                        g.ResetTransform();
                                                        g.RotateTransform(90);
                                                        g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                                                        sf.LineAlignment    = StringAlignment.Far;
                                                        g.DrawString("Delta bytes", Font, textBrush, Math.Min(barRectangle.Y, barRectangle.Bottom), 0f, sf);
                                                    } finally {
                                                        sf.LineAlignment    = oldAlignment;
                                                        g.Transform         = oldTransform;
                                                        g.TextRenderingHint = oldRenderingHint;
                                                    }
                                                }
                                            }

                                            if ((TotalDelta.GetValueOrDefault(0) != 0))
                                            {
                                                x += ItemWidth;
                                            }

                                            for (int i = _ScrollOffset; (i < Items.Count) && (x < ClientSize.Width); i++)
                                            {
                                                var selected = (i == SelectedIndex);

                                                var item = Items[i];
                                                GetItemData(i, out data);

                                                rgn = new Rectangle(x, 0, ItemWidth, height);

                                                var barRectangle = ComputeBarRectangle(
                                                    item.BytesDelta * (item.Added ? 1 : -1),
                                                    rgn.X, centerY, height, max
                                                    );

                                                if (rgn.IntersectsWith(e.ClipRectangle))
                                                {
                                                    using (var itemBrush = new SolidBrush(SelectItemColor(ref item)))
                                                        using (var scratch = Scratch.Get(e.Graphics, rgn)) {
                                                            var g = scratch.Graphics;

                                                            g.ResetClip();
                                                            g.Clear(BackColor);

                                                            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                                                            g.DrawLine(gridPen, rgn.X, centerY, rgn.Right, centerY);

                                                            g.FillRectangle(
                                                                (_HoverIndex == i) ? highlightBrush : itemBrush,
                                                                barRectangle
                                                                );

                                                            g.DrawRectangle(
                                                                (_HoverIndex == i) ? activeOutlinePen : outlinePen,
                                                                barRectangle.X - 0.5f, barRectangle.Y - 0.5f,
                                                                barRectangle.Width + 1f, barRectangle.Height + 1f
                                                                );
                                                        }
                                                }

                                                VisibleItems.Add(new VisibleItem {
                                                    Rectangle = new Rectangle(
                                                        (int)Math.Floor(barRectangle.X),
                                                        (int)Math.Floor(barRectangle.Y),
                                                        (int)Math.Ceiling(barRectangle.Width),
                                                        (int)Math.Ceiling(barRectangle.Height)
                                                        ),
                                                    Index = i
                                                });

                                                x += ItemWidth;

                                                if ((rgn.X >= 0) && (rgn.Right < ClientSize.Width))
                                                {
                                                    minVisibleIndex      = Math.Min(minVisibleIndex, i);
                                                    maxVisibleIndex      = Math.Max(maxVisibleIndex, i);
                                                    selectedItemVisible |= selected;
                                                }
                                            }

                                            if (x < ClientSize.Width)
                                            {
                                                e.Graphics.FillRectangle(backgroundBrush, new Rectangle(x, 0, ClientSize.Width - x, ClientSize.Height));

                                                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                                e.Graphics.DrawLine(gridPen, x, centerY, ClientSize.Width, centerY);
                                            }
                                        }

            if (!selectedItemVisible && !retrying && ShouldAutoscroll)
            {
                if (_SelectedIndex > maxVisibleIndex)
                {
                    _ScrollOffset += _SelectedIndex - maxVisibleIndex;
                }
                else if (_SelectedIndex < minVisibleIndex)
                {
                    _ScrollOffset -= minVisibleIndex - _SelectedIndex;
                }

                if (_ScrollOffset >= Items.Count)
                {
                    _ScrollOffset = Items.Count - 1;
                }
                if (_ScrollOffset < 0)
                {
                    _ScrollOffset = 0;
                }

                retrying = true;
                goto retryFromHere;
            }

            int largeChange = Math.Max(4, ClientSize.Width / ItemWidth);

            if (ScrollBar.LargeChange != largeChange)
            {
                ScrollBar.LargeChange = largeChange;
            }

            int scrollMax = Math.Max(1, Items.Count - 1) + largeChange - 1;

            if (ScrollBar.Maximum != scrollMax)
            {
                ScrollBar.Maximum = scrollMax;
            }
            if (ScrollBar.Value != ScrollOffset)
            {
                ScrollBar.Value = ScrollOffset;
            }

            ShouldAutoscroll = false;
            base.OnPaint(e);
        }