Files
dmex b02427417c PH1.x: fixed build
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@5614 21ef857c-d57f-4fe0-8362-d861dc6d29cd
2014-02-25 23:14:38 +00:00

552 lines
17 KiB
C#

/*
* Process Hacker -
* plotter control
*
* Copyright (C) 2008-2009 wj32
* Copyright (C) 2008 Dean
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using ProcessHacker.Common;
namespace ProcessHacker.Components
{
public partial class Plotter : UserControl
{
private static int _globalMoveStep = 3;
public static int GlobalMoveStep
{
get { return _globalMoveStep; }
set { _globalMoveStep = value; }
}
public delegate string GetToolTipDelegate(int item);
private const BufferedGraphics NO_MANAGED_BACK_BUFFER = null;
private BufferedGraphicsContext _graphicManager;
private BufferedGraphics _managedBackBuffer;
private bool _showToolTip;
private Point _mouseLocation;
private string _lastToolTip;
public Plotter()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
_graphicManager = BufferedGraphicsManager.Current;
_graphicManager.MaximumBuffer =
new Size(this.Width + 1, this.Height + 1);
_managedBackBuffer =
_graphicManager.Allocate(this.CreateGraphics(), this.ClientRectangle);
this.Draw();
}
public GetToolTipDelegate GetToolTip;
private int _gridStartPos = 0;
private void Plotter_Paint(object sender, PaintEventArgs e)
{
try
{
this.Render(e.Graphics);
}
catch (Exception ex)
{
Logging.Log(ex);
}
}
public void Render(Graphics g)
{
_managedBackBuffer.Render(g);
}
public void Draw()
{
this.Draw(_managedBackBuffer.Graphics);
if (_showToolTip)
this.ShowToolTip();
this.Refresh();
}
public void Draw(Graphics g)
{
int tWidth = this.Width;
int tHeight = this.Height;
int moveStep = this.EffectiveMoveStep;
g.SmoothingMode = Settings.Instance.PlotterAntialias ?
SmoothingMode.AntiAlias : SmoothingMode.Default;
g.FillRectangle(new SolidBrush(this.BackColor), 0, 0, tWidth, tHeight);
// Draw the grid (if enabled).
if (_showGrid)
{
int x = tWidth / _gridSize.Width;
int y = tHeight / _gridSize.Height;
Pen pGrid = new Pen(_gridColor);
int pos;
for (int i = 0; i <= x; i++)
{
pos = tWidth - (i * _gridSize.Width + _gridStartPos - 1);
g.DrawLine(pGrid, pos, 0, pos, tHeight);
}
for (int i = 0; i <= y; i++)
{
pos = i * _gridSize.Height - 1;
g.DrawLine(pGrid, 0, pos, tWidth, pos);
}
}
// Validate and if necessary, fix the data.
if (_useLongData && (_longData1 == null || (this.UseSecondLine && _longData2 == null)))
return;
if (_useLongData)
this.FixLongData();
if (_data1 == null || (this.UseSecondLine && _data2 == null))
return;
// Draw the lines.
int px = tWidth - moveStep;
int start = 0;
Pen lGrid1 = new Pen(_lineColor1);
Pen lGrid2 = new Pen(_lineColor2);
while (start < _data1.Count - 1)
{
float f = _data1[start + 1];
float fPre = _data1[start];
int h = (int)(tHeight - (tHeight * f));
int hPre = (int)(tHeight - (tHeight * fPre));
// Fill in the area below the line.
g.FillPolygon(new SolidBrush(Color.FromArgb(100, _lineColor1)),
new Point[] { new Point(px, h), new Point(px + moveStep, hPre),
new Point(px + moveStep, tHeight), new Point(px, tHeight) });
g.DrawLine(lGrid1, px, h, px + moveStep, hPre);
if (this.UseSecondLine)
{
f = _data2[start + 1];
fPre = _data2[start];
if (!this.OverlaySecondLine)
{
f += _data1[start + 1];
fPre += _data1[start];
if (f > 1.0f)
f = 1.0f;
if (fPre > 1.0f)
fPre = 1.0f;
}
h = (int)(tHeight - (tHeight * f));
hPre = (int)(tHeight - (tHeight * fPre));
// Draw the second line.
if (this.OverlaySecondLine)
{
g.FillPolygon(new SolidBrush(Color.FromArgb(100, _lineColor2)),
new Point[] { new Point(px, h), new Point(px + moveStep, hPre),
new Point(px + moveStep, tHeight), new Point(px, tHeight) });
g.DrawLine(lGrid2, px, h, px + moveStep, hPre);
}
else
{
g.FillPolygon(new SolidBrush(Color.FromArgb(100, _lineColor2)),
new Point[] { new Point(px, h), new Point(px + moveStep, hPre),
new Point(px + moveStep, tHeight - (int)(tHeight * _data1[start])),
new Point(px, tHeight - (int)(tHeight * _data1[start + 1])) });
g.DrawLine(lGrid2, px, h, px + moveStep, hPre);
}
}
if (px < 0)
{
break;
}
px -= moveStep;
start++;
}
// Draw the text, if any.
if (!string.IsNullOrEmpty(_text))
{
// Draw the background for the text.
g.FillRectangle(new SolidBrush(_textBoxColor),
new Rectangle(_boxPosition, _boxSize));
// Draw the text.
TextRenderer.DrawText(g, _text, this.Font, _textPosition, _textColor);
}
}
private void ShowToolTip()
{
this.ShowToolTip(false);
}
private void ShowToolTip(bool force)
{
if (this.GetToolTip != null)
{
int itemIndex = (this.Width - _mouseLocation.X) / this.EffectiveMoveStep;
if (itemIndex < this.Data1.Count)
{
try
{
string currentToolTip = this.GetToolTip(itemIndex);
if (currentToolTip != _lastToolTip || force)
toolTip.Show(currentToolTip, this,
new Point(_mouseLocation.X + 10, _mouseLocation.Y + 10),
int.MaxValue);
_lastToolTip = currentToolTip;
}
catch (Exception ex)
{
Logging.Log(ex);
}
}
else
{
toolTip.Hide(this);
}
}
}
public void MoveGrid()
{
_gridStartPos += this.EffectiveMoveStep;
if (_gridStartPos >= _gridSize.Width)
{
_gridStartPos -= _gridSize.Width;
}
}
public void FixLongData()
{
// find the largest value
long max = 0;
// restrict scaling to the currently visible data points
int maxIndex = this.Width / this.EffectiveMoveStep;
for (int i = 0; i < _longData1.Count && i <= maxIndex; i++)
if (_longData1[i] > max)
max = _longData1[i];
for (int i = 0; i < _longData2.Count && i <= maxIndex; i++)
if (_longData2[i] > max)
max = _longData2[i];
if (max < _minMaxValue)
max = _minMaxValue;
// redo the float list
_data1 = new List<float>();
_data2 = new List<float>();
for (int i = 0; i < _longData1.Count && i <= maxIndex; i++)
{
if (max != 0)
_data1.Add((float)_longData1[i] / max);
else
_data1.Add(0);
}
for (int i = 0; i < _longData2.Count && i <= maxIndex; i++)
{
if (max != 0)
_data2.Add((float)_longData2[i] / max);
else
_data2.Add(0);
}
}
#region Text
private Point _textPosition, _boxPosition;
private Size _textSize, _boxSize;
private Padding _textMargin = new Padding(3, 3, 3, 3);
public Padding TextMargin
{
get { return _textMargin; }
set { _textMargin = value; }
}
private Padding _textPadding = new Padding(3, 3, 3, 3);
public Padding TextPadding
{
get { return _textPadding; }
set { _textPadding = value; }
}
private ContentAlignment _textAlign = ContentAlignment.TopLeft;
public ContentAlignment TextPosition
{
get { return _textAlign; }
set { _textAlign = value; }
}
private string _text;
public override string Text
{
get
{
return _text;
}
set
{
base.Text = _text = value;
_textSize = TextRenderer.MeasureText(this.Text, this.Font);
_boxSize = new Size(
_textSize.Width + _textPadding.Left + _textPadding.Right,
_textSize.Height + _textPadding.Top + _textPadding.Bottom);
// work out Y
switch (_textAlign)
{
case ContentAlignment.BottomCenter:
case ContentAlignment.BottomLeft:
case ContentAlignment.BottomRight:
_boxPosition.Y = this.Size.Height - _boxSize.Height - _textMargin.Bottom;
break;
case ContentAlignment.MiddleCenter:
case ContentAlignment.MiddleLeft:
case ContentAlignment.MiddleRight:
_boxPosition.Y = (this.Size.Height - _boxSize.Height) / 2;
break;
case ContentAlignment.TopCenter:
case ContentAlignment.TopLeft:
case ContentAlignment.TopRight:
_boxPosition.Y = _textMargin.Top;
break;
}
// work out X
switch (_textAlign)
{
case ContentAlignment.BottomLeft:
case ContentAlignment.MiddleLeft:
case ContentAlignment.TopLeft:
_boxPosition.X = _textMargin.Left;
break;
case ContentAlignment.BottomCenter:
case ContentAlignment.MiddleCenter:
case ContentAlignment.TopCenter:
_boxPosition.X = (this.Size.Width - _boxSize.Width) / 2;
break;
case ContentAlignment.BottomRight:
case ContentAlignment.MiddleRight:
case ContentAlignment.TopRight:
_boxPosition.X = this.Size.Width - _boxSize.Width - _textMargin.Right;
break;
}
_textPosition = new Point(
_boxPosition.X + _textPadding.Left,
_boxPosition.Y + _textPadding.Top);
}
}
private Color _textBoxColor = Color.FromArgb(127, Color.Black);
public Color TextBoxColor
{
get { return _textBoxColor; }
set { _textBoxColor = value; }
}
private Color _textColor = Color.FromArgb(0, 255, 0);
public Color TextColor
{
get { return _textColor; }
set { _textColor = value; }
}
#endregion
public bool UseSecondLine { get; set; }
public bool OverlaySecondLine { get; set; }
private Color _lineColor1 = Color.FromArgb(0, 255, 0);
public Color LineColor1
{
get { return _lineColor1; }
set { _lineColor1 = value; }
}
private Color _lineColor2 = Color.FromArgb(255, 0, 0);
public Color LineColor2
{
get { return _lineColor2; }
set { _lineColor2 = value; }
}
private bool _showGrid = true;
public bool ShowGrid
{
get { return _showGrid; }
set { _showGrid = value; }
}
private Color _gridColor = Color.Green;
public Color GridColor
{
get { return _gridColor; }
set { _gridColor = value; }
}
private Size _gridSize = new Size(12, 12);
public Size GridSize
{
get { return _gridSize; }
set { _gridSize = value; }
}
private int _moveStep = -1;
public int MoveStep
{
get { return _moveStep; }
set { _moveStep = value; }
}
public int EffectiveMoveStep
{
get { return _moveStep == -1 ? GlobalMoveStep : _moveStep; }
}
private IList<float> _data1;
public IList<float> Data1
{
get { return _data1; }
set { _data1 = value; }
}
private IList<float> _data2;
public IList<float> Data2
{
get { return _data2; }
set { _data2 = value; }
}
private bool _useLongData;
public bool UseLongData
{
get { return _useLongData; }
set { _useLongData = value; }
}
private IList<long> _longData1;
public IList<long> LongData1
{
get { return _longData1; }
set { _longData1 = value; }
}
private IList<long> _longData2;
public IList<long> LongData2
{
get { return _longData2; }
set { _longData2 = value; }
}
private long _minMaxValue = 0;
/// <summary>
/// The minimum scaling value to be used for long data.
/// </summary>
public long MinMaxValue
{
get { return _minMaxValue; }
set { _minMaxValue = value; }
}
private void Plotter_Resize(object sender, EventArgs e)
{
if (_managedBackBuffer != NO_MANAGED_BACK_BUFFER)
_managedBackBuffer.Dispose();
if (_graphicManager == null)
_graphicManager = BufferedGraphicsManager.Current;
_graphicManager.MaximumBuffer =
new Size(this.Width + 1, this.Height + 1);
_managedBackBuffer =
_graphicManager.Allocate(this.CreateGraphics(), this.ClientRectangle);
this.Draw();
}
private void Plotter_MouseEnter(object sender, EventArgs e)
{
_showToolTip = true;
}
private void Plotter_MouseLeave(object sender, EventArgs e)
{
_showToolTip = false;
toolTip.Hide(this);
}
private void Plotter_MouseMove(object sender, MouseEventArgs e)
{
if (e.Location != _mouseLocation)
{
_mouseLocation = e.Location;
this.ShowToolTip(true);
}
else
{
_mouseLocation = e.Location;
this.ShowToolTip();
}
}
}
}