//*
// Name: Graph Component Control
// Author: AceInfinity
// Copyright 2012 - Tech.Reboot.Pro
//
// Description:
// Experimental graph control allowing you to manually plot points
// on the grid using the left and right mouse clicks.
//
//
// Known Bugs:
//
// - Resize does not affect the points and line positioning
//*
using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
class GraphComponent : PictureBox
{
#region Private Fields
private int _TopPadding = 15;
private Font _TitleFont = new Font(FontFamily.GenericSansSerif, 8f);
private List<List<Point>> _Points = new List<List<Point>>();
private int _PointSize = 3;
#endregion Private Fields
#region Public Properties
public Color TitleColor { get; set; }
public bool ShowVerticalMargin { get; set; }
public bool ShowHorizontalMargin { get; set; }
public Color GridLinesColor { get; set; }
public Color GridMarginsColor { get; set; }
public Color LineColor { get; set; }
public Color DotBorderColor { get; set; }
public Color DotTopGradient { get; set; }
public Color DotBottomGradient { get; set; }
public int TileSize { get; set; }
public List<List<Point>> Points
{
get { return _Points; }
private set
{
_Points = value;
Invalidate();
}
}
#endregion Public Properties
#region Constructor
public GraphComponent()
{
DoubleBuffered = true;
//Title
Text = "GraphComponent";
TitleColor = Color.FromArgb(50, 50, 50);
//Grid
TileSize = 5;
ShowVerticalMargin = true;
ShowHorizontalMargin = true;
GridLinesColor = Color.FromArgb(200, 200, 200);
GridMarginsColor = Color.FromArgb(125, 125, 125);
//Plot
LineColor = Color.FromArgb(0, 200, 255);
DotBorderColor = Color.FromArgb(0, 170, 255);
DotTopGradient = Color.FromArgb(119, 221, 255);
DotBottomGradient = Color.FromArgb(0, 100, 200);
}
#endregion Constructor
#region Overrides
#region Paint Event Methods
/// <summary>
/// Method used to paint the control.
/// </summary>
/// <param name="pe"></param>
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
int horTiles = this.Width / TileSize;
int verTiles = this.Height + _TopPadding / TileSize;
Pen P = new Pen(GridLinesColor);
// Draw Tiles
for (int v = 0; v < verTiles; v++)
{
for (int h = 0; h < horTiles; h++)
{
pe.Graphics.DrawRectangle(P, new Rectangle(h * TileSize, v * TileSize + _TopPadding, TileSize, TileSize));
}
}
P = new Pen(GridMarginsColor);
// Draw Center Margins
if (ShowVerticalMargin)
{
int margin = this.Width / 2 / TileSize * TileSize; // Make sure it aligns with the edge of a tile
pe.Graphics.DrawLine(P, margin, _TopPadding, margin, this.Height); // Vertical Margin
}
if (ShowHorizontalMargin)
{
int margin = this.Height / 2 / TileSize * TileSize; // Make sure it aligns with the edge of a tile
pe.Graphics.DrawLine(P, 0, margin, this.Width, margin); // Horizontal Margin
}
// Draw Title String
SolidBrush SB = new SolidBrush(TitleColor);
pe.Graphics.DrawString(this.Text, _TitleFont, SB, 0, 2);
if (Points.Count > 0)
{
P = new Pen(DotBorderColor);
Pen LnPen = new Pen(LineColor);
// Draw Points
LinearGradientBrush LGB = default(LinearGradientBrush);
foreach (List<Point> pts in Points)
{
foreach (Point p in pts)
{
Rectangle rect = new Rectangle(p.X - (_PointSize / 2), p.Y - (_PointSize / 2), _PointSize, _PointSize);
LGB = new LinearGradientBrush(rect, DotTopGradient, DotBottomGradient, 70f);
pe.Graphics.DrawEllipse(P, rect);
pe.Graphics.FillEllipse(LGB, rect);
}
for (int x = 0; x < pts.Count - 1; x++)
{
pe.Graphics.DrawLine(LnPen, pts[x], pts[x + 1]);
}
}
LGB.Dispose();
LnPen.Dispose();
}
SB.Dispose();
P.Dispose();
}
#endregion
#region Mouse Event Methods
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
int posX = ((e.X / TileSize) * TileSize);
int posY = ((e.Y / TileSize) * TileSize);
if (e.Button == MouseButtons.Left)
{
// Add new point
List<Point> P = new List<Point>();
P.Add(new Point(posX, posY));
Points.Add(P);
}
else if (e.Button == MouseButtons.Right)
{
// Modify last point
List<Point> LastP = Points.LastOrDefault();
if (LastP != null)
{
LastP.Add(new Point(posX, posY));
}
}
Invalidate();
}
#endregion Mouse Event Methods
#region Resize Event Methods
/// <summary>
/// OnResize event method, calls to re-paint the control.
/// </summary>
/// <param name="e"></param>
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
Invalidate();
}
#endregion Resize Event Methods
#region Properties
/// <summary>
/// Make sure that the minimum size of the control doesn't go below 100 x 100.
/// </summary>
private Size _MinimumSize = new Size(100, 100);
public override Size MinimumSize
{
get { return _MinimumSize; }
set
{
Size s = value;
if (value.Height < 100) s.Height = 100;
if (value.Width < 100) s.Width = 100;
base.MinimumSize = s;
}
}
/// <summary>
/// Set the default cursor to the cross.
/// </summary>
protected override Cursor DefaultCursor { get { return Cursors.Cross; } }
#endregion Properties
#endregion Overrides
#region Other Methods
/// <summary>
/// Wipes all points & lines off the grid
/// </summary>
public void ClearPoints()
{
Points.Clear();
Invalidate();
}
#endregion Other Methods
}