using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace SpeedTracker
{
public partial class LedDigit : Control, IDisposable
{
public enum PaletteIndex:int
{
Background=0,
Foreground=1,
DecimalForeground=2
}
Point[] segmentPointList = new Point[22];
private int _value;
private bool _enabled = true;
private float _horizontalThicknessFactor = 0.25f;
private float _verticalThicknessFactor = 0.2f;
private bool _isDecimalDigit = false;
private SolidBrush[] ColorPalette = null;
class Polygon
{
public Point[] PointList;
public int ColorIndex;
public void Initialize(int[] vertexList, Point[] segmentSource)
{
if((PointList==null)||(vertexList.Length!=PointList.Length))
PointList = new Point[vertexList.Length];
for(var i=0;i<vertexList.Length;++i)
{
var vertextIndex = vertexList[i];
PointList[i] = new Point(segmentSource[vertextIndex].X, segmentSource[vertextIndex].Y);
}
}
}
static readonly int[][] EdgeList = new int[][]
{
new [] {0,1,13},
new []{1,14,13},
new []{1,2,15,14},
new []{2,4,15},
new []{2,3,4},
new []{13,14,17,12},
new []{15,4,5,16},
new []{12,17,18},
new []{17,16,19,18},
new []{16,5,19},
new []{12,18,21,11},
new[]{19,5,6,20},
new[]{9,10,11},
new[]{11,21,9},//13
new[]{21,20,8,9},//14
new[]{20,6,8},
new[]{6,7,8}
};
static readonly int[][] DigitSegmentList = new int[][]
{
new int[]{1,2,3,5,6,7,9,0xa, 0xb, 0xd, 0xe, 0xf},
new int[]{3, 6, 9, 0xb, 0xF, 0x10},
new int[]{1,2,3,6,7,8,9,0xa, 0xd, 0xe, 0xf},
new int[]{1,2,3,6,8,9,0xb,0xd,0xe,0xf},
new int[]{1,3,4,5,6,7,8,9,0xb,0xf,0x10},
new int[]{1,2,3,5,7,8,9,0xb,0xd,0xe,0xf},
new int[]{1,2,3,5,7,8,9,0xa,0xb,0xd,0xe,0xf},
new int[]{1,2,3,6,9,0xB,0xF,0x10},
new int[]{1,2,3,5,6,7,8,9,0xa,0xb,0xd,0xe, 0xf},
new int[]{1,2,3,5,6,7,8,9,0xB,0xd,0xe,0xf},
new int[]{1,2,3,5,6,7,8,9,0xa,0xb,0xc,0xd,0xf},
new int[]{0,1,2,3,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf},
new int[]{},
new int[]{},
new int[]{},
new int[]{}
};
private Polygon[] _shapeList;
public int Value
{
get
{
return _value;
}
set
{
_value = value%10;
UpdateSegmentColorIndex();
Invalidate();
}
}
public float HorizontalThicknessFactor
{
get { return _horizontalThicknessFactor; }
set
{
_horizontalThicknessFactor = value;
InitPolygonList();
}
}
public float VerticalThicknessFactor
{
get { return _verticalThicknessFactor; }
set
{
_verticalThicknessFactor = value;
InitPolygonList();
}
}
public bool Enabled
{
get { return _enabled; }
set
{
_enabled = value;
UpdateSegmentColorIndex();
}
}
void UpdateSegmentColorIndex()
{
if ((_shapeList != null)&&(DigitSegmentList!=null))
{
for (var i = 0; i < _shapeList.Length; ++i)
{
_shapeList[i].ColorIndex = 0;
}
var activationList = DigitSegmentList[_value];
if (Enabled)
{
for (var i = 0; i < activationList.Length; ++i)
{
_shapeList[activationList[i]].ColorIndex = (int)((IsDecimalDigit)?PaletteIndex.Foreground:PaletteIndex.DecimalForeground);
}
}
}
}
void DestroyBackBuffer()
{
if (_offBitmap != null)
{
_offBitmap.Dispose();
_offBitmap = null;
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
DestroyBackBuffer();
this.Invalidate();
}
void InitPolygonList()
{
if((_shapeList==null)||(_shapeList.Length!=EdgeList.Length))
_shapeList = new Polygon[EdgeList.Length];
for(var i=0;i<EdgeList.Length;++i)
{
_shapeList[i] = new Polygon();
_shapeList[i].Initialize(EdgeList[i],segmentPointList);
}
UpdateSegmentColorIndex();
}
private int _margin;
bool VisualSettingsChanged { get; set; }
public LedDigit()
{
InitializeComponent();
ColorPalette = new SolidBrush[]{new SolidBrush(Color.WhiteSmoke),new SolidBrush(Color.Red), new SolidBrush(Color.DarkViolet), };
Resize+=LedDigit_Resize;
}
public void SetColor(PaletteIndex index, Color c)
{
SolidBrush oldBrush = ColorPalette[(int)index];
ColorPalette[(int)index]=new SolidBrush(c);
oldBrush.Dispose();
if(PaletteIndex.Background==index)
BackColor = c;
}
void LedDigit_Resize(object sender, EventArgs e)
{
VisualSettingsChanged = true;
}
void SetLayoutChanged()
{
VisualSettingsChanged = true;
}
public int Margin
{
get { return _margin; }
set
{
_margin = value;
SetLayoutChanged();
}
}
public bool IsDecimalDigit
{
get { return _isDecimalDigit; }
set
{
_isDecimalDigit = value;
VisualSettingsChanged=true;
}
}
void RefreshPointList()
{
int realWidth = Width - Margin*2;
int realHeight = Height - Margin*2;
int x1 = Margin;
int x2 = Margin + (int)((realWidth) * HorizontalThicknessFactor);
int x3 = Margin + (int)(realWidth - (realWidth * HorizontalThicknessFactor));
int x4 = Margin + (int)realWidth;
int y1 = Margin;
int y2 = Margin + (int)(realHeight * VerticalThicknessFactor );
int y3 = Margin + (int)(realHeight * 0.5 - (realHeight * VerticalThicknessFactor * 0.5) );
int y4 = Margin + (int) (realHeight*0.5);
int y5 = Margin + (int)(realHeight * 0.5 + (realHeight * VerticalThicknessFactor * 0.5) );
int y6 = Margin + (int)(realHeight - (realHeight * VerticalThicknessFactor));
int y7 = Margin + realHeight;
#region Populate Point Coordinates
segmentPointList[0].X = x1;
segmentPointList[0].Y = y1;
segmentPointList[1].X = x2;
segmentPointList[1].Y = y1;
segmentPointList[2].X = x3;
segmentPointList[2].Y = y1;
segmentPointList[3].X = x4;
segmentPointList[3].Y = y1;
segmentPointList[4].X = x4;
segmentPointList[4].Y = y2;
segmentPointList[5].X = x4;
segmentPointList[5].Y = y4;
segmentPointList[6].X = x4;
segmentPointList[6].Y = y6;
segmentPointList[7].X = x4;
segmentPointList[7].Y = y7;
segmentPointList[8].X = x3;
segmentPointList[8].Y = y7;
segmentPointList[9].X = x2;
segmentPointList[9].Y = y7;
segmentPointList[10].X = x1;
segmentPointList[10].Y = y7;
segmentPointList[11].X = x1;
segmentPointList[11].Y = y6;
segmentPointList[12].X = x1;
segmentPointList[12].Y = y4;
segmentPointList[13].X = x1;
segmentPointList[13].Y = y2;
segmentPointList[14].X = x2;
segmentPointList[14].Y = y2;
segmentPointList[15].X = x3;
segmentPointList[15].Y = y2;
segmentPointList[16].X = x3;
segmentPointList[16].Y = y3;
segmentPointList[17].X = x2;
segmentPointList[17].Y = y3;
segmentPointList[18].X = x2;
segmentPointList[18].Y = y5;
segmentPointList[19].X = x3;
segmentPointList[19].Y = y5;
segmentPointList[20].X = x3;
segmentPointList[20].Y = y6;
segmentPointList[21].X = x2;
segmentPointList[21].Y = y6;
#endregion
InitPolygonList();
}
protected override void OnPaintBackground(PaintEventArgs e)
{
}
private Bitmap _offBitmap = null;
protected override void OnPaint(PaintEventArgs pe)
{
//base.OnPaint(pe);
if (_offBitmap == null)
{
_offBitmap = new Bitmap(ClientSize.Width, ClientSize.Height);
}
var gOff = Graphics.FromImage(_offBitmap);
gOff.Clear(BackColor);
if(VisualSettingsChanged)
{
RefreshPointList();
}
for(var i=0;i<_shapeList.Length;++i)
gOff.FillPolygon(ColorPalette[_shapeList[i].ColorIndex],_shapeList[i].PointList);
pe.Graphics.DrawImage(_offBitmap,0,0);
}
#region IDisposable Members
void IDisposable.Dispose()
{
if(ColorPalette!=null)
{
for(var i=0;i<ColorPalette.Length;++i)
{
ColorPalette[i].Dispose();
}
}
}
#endregion
}
}