Пример #1
0
        protected override void OnPaint(PaintEventArgs e)
        {
            int height = ClientSize.Height;

            int  pixelsPerHour = (PixelsPerHour * (_Scrollable ? ZoomRatio : 128)) / 128;
            long maxValue = MaximumThreshold;
            long minTicks = 0, maxTicks = 0;
            int  contentWidth;

            const long hourInTicks = Squared.Util.Time.SecondInTicks * 60 * 60;

            if (Items.Count > 0)
            {
                maxValue = Math.Max(MaximumThreshold, (from s in Items select _ItemValueGetter(s)).Max());
                minTicks = (from s in Items select s.Timestamp.Ticks).Min();
                maxTicks = (from s in Items select s.Timestamp.Ticks).Max();

                bool rescaled = false;

rescale:
                _ContentWidth = contentWidth = (int)(
                    (maxTicks - minTicks)
                    * pixelsPerHour / hourInTicks
                    ) + MarginWidth;

                if (!_Scrollable && !rescaled)
                {
                    var ratio = (ClientSize.Width / (double)(contentWidth + 1)) * 128.0;
                    _ZoomRatio = (int)Math.Floor(ratio);
                    if (_ZoomRatio < 1)
                    {
                        _ZoomRatio = 1;
                    }

                    pixelsPerHour = (PixelsPerHour * _ZoomRatio) / 128;
                    if (pixelsPerHour < 1)
                    {
                        pixelsPerHour = 1;
                    }

                    rescaled = true;

                    goto rescale;
                }
            }
            else
            {
                _ContentWidth = contentWidth = MarginWidth;
            }

            if (_Scrollable)
            {
                height -= ScrollBar.Height;

                if (_ScrollOffset > contentWidth - ClientSize.Width)
                {
                    _ScrollOffset = contentWidth - ClientSize.Width;
                }
                if (_ScrollOffset < 0)
                {
                    _ScrollOffset = 0;
                }

                int  scrollMax = contentWidth - ClientSize.Width + ScrollBar.LargeChange - 1;
                bool enabled   = (scrollMax > 0);
                if (scrollMax < 0)
                {
                    scrollMax = 0;
                }

                // WinForms' scrollbar control is terrible
                if (ScrollBar.Maximum != scrollMax)
                {
                    ScrollBar.Maximum = scrollMax;
                }
                if (ScrollBar.Value != _ScrollOffset)
                {
                    ScrollBar.Value = _ScrollOffset;
                }
                if (ScrollBar.Enabled != enabled)
                {
                    ScrollBar.Enabled = enabled;
                }
                if (!ScrollBar.Visible)
                {
                    ScrollBar.Visible = true;
                }
                if (!ZoomInButton.Visible)
                {
                    ZoomInButton.Visible = true;
                }
                if (!ZoomOutButton.Visible)
                {
                    ZoomOutButton.Visible = true;
                }
            }
            else
            {
                if (ScrollBar.Visible)
                {
                    ScrollBar.Visible = false;
                }
                if (ZoomInButton.Visible)
                {
                    ZoomInButton.Visible = false;
                }
                if (ZoomOutButton.Visible)
                {
                    ZoomOutButton.Visible = false;
                }

                _ScrollOffset = 0;
            }

            using (var outlinePen = new Pen(Color.Black))
                using (var gridPen = new Pen(Color.FromArgb(96, 0, 0, 0)))
                    using (var scratch = Scratch.Get(e.Graphics, ClientRectangle)) {
                        var g = scratch.Graphics;
                        g.Clear(BackColor);

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

                        float y = 0;
                        using (var textBrush = new SolidBrush(ForeColor))
                        {
                            g.DrawLine(gridPen, 0, height - VerticalMargin, ClientSize.Width, height - VerticalMargin);
                            g.DrawLine(gridPen, 0, VerticalMargin, Width, VerticalMargin);

                            var lineHeight = g.MeasureString("AaBbYyZz", Font).Height;
                            var numLines   = (int)Math.Min(
                                Math.Max(2, Math.Floor((height / lineHeight) * GridLineRatio)),
                                MaxGridLines
                                );
                            for (int i = 0; i <= numLines; i++)
                            {
                                var value = (maxValue * i / numLines);
                                var text  = _ItemValueFormatter(value);
                                y = (float)(height - VerticalMargin - ((value / (double)maxValue) * (height - VerticalMargin * 2)));

                                g.DrawLine(gridPen, 0, y, ClientSize.Width, y);
                                g.DrawString(text, Font, textBrush, new PointF(4, y));
                            }
                        }

                        var itemXCoordinates = (from item in Items
                                                select
                                                    (int)((item.Timestamp.Ticks - minTicks)
                                                          * pixelsPerHour / hourInTicks
                                                          ) - _ScrollOffset).ToArray();
                        var itemYCoordinates = (from item in Items
                                                select
                                                    (float)(height - VerticalMargin - (
                                                                (_ItemValueGetter(item) / (double)maxValue) *
                                                                (height - VerticalMargin * 2)
                                                                )));

                        var valueSeriesYCoordinates = (
                            from series in DataSeries.Values
                            select(
                                from value in series
                                select
                                    (float)(height - VerticalMargin - (
                                                (value / (double)maxValue) *
                                                (height - VerticalMargin * 2)
                                                ))
                                )
                            );

                        var firstIndex = Math.Max(0, IndexFromPoint(new Point(0, 0), -1));

                        using (var brush = new SolidBrush(Color.FromArgb(127, ForeColor)))
                            DrawValueSeries(
                                g,
                                itemXCoordinates.Skip(firstIndex),
                                itemYCoordinates.Skip(firstIndex),
                                ClientSize.Width, height,
                                brush, outlinePen
                                );

                        int seriesIndex = 0;
                        foreach (var series in valueSeriesYCoordinates)
                        {
                            int hue = (HSV.HueMax * seriesIndex) / DataSeries.Count;

                            var seriesColor = HSV.ColorFromHSV(
                                (UInt16)hue, HSV.SaturationMax, HSV.ValueMax
                                );

                            using (var brush = new SolidBrush(Color.FromArgb(15, seriesColor)))
                                using (var pen = new Pen(Color.FromArgb(160, seriesColor)))
                                    DrawValueSeries(
                                        g, itemXCoordinates.Skip(firstIndex),
                                        series.Skip(firstIndex),
                                        ClientSize.Width, height,
                                        brush, pen
                                        );

                            seriesIndex += 1;
                        }

                        firstIndex = Selection.First;
                        var takeCount = Selection.Second - Selection.First + 1;

                        using (var brush = new SolidBrush(SystemColors.Highlight))
                            using (var pen = new Pen(SystemColors.HighlightText)
                            {
                                Width = 2.0f
                            })
                                DrawValueSeries(
                                    g,
                                    itemXCoordinates.Skip(firstIndex).Take(takeCount),
                                    itemYCoordinates.Skip(firstIndex).Take(takeCount),
                                    ClientSize.Width, height,
                                    brush, pen
                                    );

                        var cursorPos = PointToClient(Cursor.Position);

                        DateTime mouseTime;
                        if (ClientRectangle.Contains(cursorPos) && TimeFromPoint(_MouseMoveLocation, out mouseTime))
                        {
                            using (var pen = new Pen(Color.FromArgb(127, SystemColors.HighlightText))) {
                                pen.Width = 2.0f;
                                g.DrawLine(pen, _MouseMoveLocation.X, 0, _MouseMoveLocation.X, height);
                            }

                            var mouseIndex = IndexFromTime(mouseTime, -1);
                            if (!_MouseDownLocation.HasValue)
                            {
                                using (var pen = new Pen(SystemColors.HighlightText)) {
                                    pen.Width = 2.0f;
                                    var item = Items[mouseIndex];
                                    var x    = (int)((item.Timestamp.Ticks - minTicks) * pixelsPerHour / hourInTicks) - _ScrollOffset;
                                    g.DrawLine(
                                        pen,
                                        x, 0, x, height
                                        );
                                }
                            }
                        }
                    }
        }
Пример #2
0
        protected override void OnPaint(PaintEventArgs e)
        {
            bool retrying = false, selectedItemVisible = false;
            int  minVisibleIndex = int.MaxValue, maxVisibleIndex = int.MinValue;
            var  width = ClientSize.Width - ScrollBar.Width;

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 = new StringFormat {
                Alignment = StringAlignment.Near,
                LineAlignment = StringAlignment.Near,
                FormatFlags = StringFormatFlags.FitBlackBox | StringFormatFlags.NoWrap |
                              StringFormatFlags.DisplayFormatControl | StringFormatFlags.MeasureTrailingSpaces,
                HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None,
                Trimming = StringTrimming.None
            })
                using (var shadeBrush = new SolidBrush(Color.FromArgb(31, 0, 0, 0)))
                    using (var elideBackgroundBrush = new SolidBrush(Color.FromArgb(192, SystemColors.Window)))
                        using (var elideTextBrush = new SolidBrush(Color.FromArgb(220, SystemColors.WindowText)))
                            using (var backgroundBrush = new SolidBrush(BackColor))
                                using (var textBrush = new SolidBrush(ForeColor))
                                    using (var highlightBrush = new SolidBrush(SystemColors.Highlight))
                                        using (var highlightTextBrush = new SolidBrush(SystemColors.HighlightText)) {
                                            var lineHeight = e.Graphics.MeasureString("AaBbYyZz", Font, width, sf).Height;
                                            CollapsedSize = (int)Math.Ceiling(lineHeight * 3);

                                            var renderParams = new DeltaInfo.RenderParams {
                                                Font                       = Font,
                                                FunctionFilter             = FunctionFilter,
                                                FunctionHighlightBrush     = highlightBrush,
                                                FunctionHighlightTextBrush = highlightTextBrush,
                                                ElideBackgroundBrush       = elideBackgroundBrush,
                                                ElideTextBrush             = elideTextBrush,
                                                ShadeBrush                 = shadeBrush,
                                                StringFormat               = sf,
                                            };

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

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

                                                var rgn = new Rectangle(
                                                    0, y, width,
                                                    data.Expanded ?
                                                    (int)Math.Ceiling(lineHeight * (item.Traceback.Frames.Count + 1)) :
                                                    CollapsedSize
                                                    );

                                                using (var scratch = Scratch.Get(e.Graphics, rgn)) {
                                                    var g = scratch.Graphics;

                                                    g.ResetClip();
                                                    g.Clear(selected ? highlightBrush.Color : backgroundBrush.Color);

                                                    renderParams.BackgroundColor = selected ? highlightBrush.Color : backgroundBrush.Color;
                                                    renderParams.BackgroundBrush = selected ? highlightBrush : backgroundBrush;
                                                    renderParams.TextBrush       = selected ? highlightTextBrush : textBrush;

                                                    renderParams.ContentRegion = rgn;
                                                    renderParams.IsExpanded    = data.Expanded;
                                                    renderParams.IsSelected    = selected;

                                                    y += (int)Math.Ceiling(item.Render(g, ref renderParams));
                                                }

                                                VisibleItems.Add(new VisibleItem {
                                                    Y1 = y1, Y2 = y, Index = i
                                                });

                                                if ((y1 >= 0) && (y < ClientSize.Height) || ((y - y1) >= ClientSize.Height))
                                                {
                                                    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));
                                            }
                                        }

            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.Height / CollapsedSize);

            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);
        }
Пример #3
0
        protected override void OnPaint(PaintEventArgs e)
        {
            if (Snapshot == null)
            {
                e.Graphics.Clear(BackColor);
                return;
            }

            var width       = ClientSize.Width - ScrollBar.Width;
            var bytesPerRow = BytesPerRow;

            var contentHeight = ContentHeight;

            if (_ScrollOffset >= contentHeight)
            {
                _ScrollOffset = contentHeight - 1;
            }
            if (_ScrollOffset < 0)
            {
                _ScrollOffset = 0;
            }

            using (var shadeBrush = new SolidBrush(SystemColors.ControlLight))
                using (var backgroundBrush = new SolidBrush(BackColor)) {
                    foreach (var vh in WalkHeaps(Snapshot, _ScrollOffset, bytesPerRow, width))
                    {
                        var rgn = new Rectangle(0, vh.FirstRow * RowHeight, width, vh.HeightInRows * RowHeight);
                        if (rgn.Y > ClientSize.Height)
                        {
                            break;
                        }
                        if (rgn.Bottom < 0)
                        {
                            continue;
                        }

                        var clippedRgn = rgn;
                        clippedRgn.Intersect(e.ClipRectangle);

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

                                g.SmoothingMode = SmoothingMode.None;

                                g.ResetClip();
                                g.Clear(shadeBrush.Color);

                                foreach (var vha in WalkHeapAllocations(vh.Heap, bytesPerRow, vh.FirstRow, width))
                                {
                                    if (vha.Rectangle.Y < 0)
                                    {
                                        continue;
                                    }
                                    if (vha.Rectangle.Bottom > ClientSize.Height)
                                    {
                                        break;
                                    }

                                    bool  isSelected = (vha.Index == TooltipAllocationIndex) && (vha.Heap == TooltipHeap);
                                    Color itemColor;

                                    if (isSelected)
                                    {
                                        itemColor = SystemColors.Highlight;
                                    }
                                    else
                                    {
                                        itemColor = SelectItemColor(vha.Allocation);
                                    }

                                    using (var brush = new SolidBrush(itemColor))
                                        g.FillRectangle(brush, vha.Rectangle);
                                }
                            }
                        }
                    }

                    var lastContentY = (contentHeight - _ScrollOffset) * RowHeight;
                    if (lastContentY < ClientSize.Height)
                    {
                        e.Graphics.FillRectangle(
                            backgroundBrush, new Rectangle(
                                0, lastContentY,
                                ClientSize.Width, ClientSize.Height - lastContentY
                                )
                            );
                    }
                }

            var largeChange = ClientSize.Height / RowHeight;

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

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

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

            base.OnPaint(e);
        }
Пример #4
0
        protected override void OnPaint(PaintEventArgs e)
        {
            var clipRectF = (RectangleF)e.ClipRectangle;

            if (Layout.Count == 0)
            {
                e.Graphics.Clear(BackColor);
            }

            var stringFormat = new StringFormat {
                Alignment   = StringAlignment.Near,
                FormatFlags = StringFormatFlags.FitBlackBox |
                              StringFormatFlags.NoFontFallback | StringFormatFlags.NoWrap,
                Trimming     = StringTrimming.EllipsisPath,
                HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show
            };
            var textToFlush       = new HashSet <string>(TextCache.Keys);
            int textSuppressLimit = 2;

            foreach (var group in Layout)
            {
                if (!group.Rectangle.IntersectsWith(clipRectF))
                {
                    foreach (var item in group.Items)
                    {
                        textToFlush.Remove(GetItemText(item.Item));
                    }

                    continue;
                }

                using (var scratch = Scratch.Get(e.Graphics, group.Rectangle)) {
                    var g = scratch.Graphics;
                    if (scratch.IsCancelled)
                    {
                        continue;
                    }

                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    g.Clear(BackColor);

                    foreach (var item in group.Items)
                    {
                        var   opacity = 255;
                        Color itemColor;
                        Color outlineColor;

                        if ((item.NestingDepth > 0) && (item != _HoverItem))
                        {
                            opacity = (int)(opacity * Math.Pow(0.7, item.NestingDepth));
                        }

                        if (item == _HoverItem)
                        {
                            itemColor    = SystemColors.Highlight;
                            outlineColor = SystemColors.HighlightText;
                        }
                        else
                        {
                            itemColor    = SelectItemColor(item.Item);
                            outlineColor = Color.FromArgb(opacity / 2, 0, 0, 0);
                        }

                        bool white = (itemColor.GetBrightness() <= 0.25f);

                        using (var brush = new SolidBrush(
                                   Color.FromArgb(opacity, itemColor.R, itemColor.G, itemColor.B)
                                   ))
                            g.FillRectangle(brush, item.Rectangle);

                        using (var outlinePen = new Pen(outlineColor, BlockOutlineThickness))
                            g.DrawRectangle(
                                outlinePen,
                                item.Rectangle.X, item.Rectangle.Y,
                                item.Rectangle.Width, item.Rectangle.Height
                                );

                        if ((item.NestingDepth >= textSuppressLimit) && (item != _HoverItem))
                        {
                            continue;
                        }

                        if ((item.Rectangle.Width > MinimumTextWidth) && (item.Rectangle.Height > MinimumTextHeight))
                        {
                            var itemText = GetItemText(item.Item);
                            textToFlush.Remove(itemText);

                            var bitmap = TextCache.Get(
                                g, itemText, Font, RotateFlipType.RotateNoneFlipNone,
                                white ? Color.White : Color.Black,
                                white ? Color.Black : Color.LightGray,
                                stringFormat,
                                new SizeF(item.Rectangle.Width, item.Rectangle.Height)
                                );

                            var w = (int)Math.Min(item.Rectangle.Width, bitmap.Width);
                            var h = (int)Math.Min(item.Rectangle.Height, bitmap.Height);
                            g.DrawImageUnscaledAndClipped(
                                bitmap, new Rectangle(
                                    (int)item.Rectangle.Right - w,
                                    (int)item.Rectangle.Bottom - h,
                                    w, h
                                    )
                                );
                        }
                    }
                }
            }

            TextCache.Flush(textToFlush);
        }
Пример #5
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);
        }
Пример #6
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);
        }