Exemplo n.º 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
                                        );
                                }
                            }
                        }
                    }
        }