139 |
pfowler |
1 |
using System;
|
|
|
2 |
using System.Collections.Generic;
|
|
|
3 |
using System.Drawing;
|
|
|
4 |
using System.Drawing.Drawing2D;
|
|
|
5 |
using System.Linq;
|
|
|
6 |
using System.Text;
|
|
|
7 |
using System.Threading.Tasks;
|
|
|
8 |
using System.Windows.Forms;
|
|
|
9 |
|
|
|
10 |
namespace NITNavComm {
|
|
|
11 |
public class SevenSegment : UserControl {
|
|
|
12 |
public SevenSegment() {
|
|
|
13 |
this.SuspendLayout();
|
|
|
14 |
this.Name = "SevenSegment";
|
|
|
15 |
this.Size = new System.Drawing.Size(32, 64);
|
|
|
16 |
this.Paint += new System.Windows.Forms.PaintEventHandler(this.SevenSegment_Paint);
|
|
|
17 |
this.Resize += new System.EventHandler(this.SevenSegment_Resize);
|
|
|
18 |
this.ResumeLayout(false);
|
|
|
19 |
|
|
|
20 |
this.TabStop = false;
|
|
|
21 |
this.Padding = new Padding(4, 4, 4, 4);
|
|
|
22 |
this.DoubleBuffered = true;
|
|
|
23 |
|
|
|
24 |
segPoints = new Point[7][];
|
|
|
25 |
for (int i = 0; i < 7; i++) segPoints[i] = new Point[6];
|
|
|
26 |
|
|
|
27 |
RecalculatePoints();
|
|
|
28 |
}
|
|
|
29 |
|
|
|
30 |
/// <summary>
|
|
|
31 |
/// Recalculate the points that represent the polygons of the
|
|
|
32 |
/// seven segments, whether we're just initializing or
|
|
|
33 |
/// changing the segment width.
|
|
|
34 |
/// </summary>
|
|
|
35 |
private void RecalculatePoints() {
|
|
|
36 |
int halfHeight = gridHeight / 2, halfWidth = elementWidth / 2;
|
|
|
37 |
|
|
|
38 |
int p = 0;
|
|
|
39 |
segPoints[p][0].X = elementWidth + 1; segPoints[p][0].Y = 0;
|
|
|
40 |
segPoints[p][1].X = gridWidth - elementWidth - 1; segPoints[p][1].Y = 0;
|
|
|
41 |
segPoints[p][2].X = gridWidth - halfWidth - 1; segPoints[p][2].Y = halfWidth;
|
|
|
42 |
segPoints[p][3].X = gridWidth - elementWidth - 1; segPoints[p][3].Y = elementWidth;
|
|
|
43 |
segPoints[p][4].X = elementWidth + 1; segPoints[p][4].Y = elementWidth;
|
|
|
44 |
segPoints[p][5].X = halfWidth + 1; segPoints[p][5].Y = halfWidth;
|
|
|
45 |
|
|
|
46 |
p++;
|
|
|
47 |
segPoints[p][0].X = 0; segPoints[p][0].Y = elementWidth + 1;
|
|
|
48 |
segPoints[p][1].X = halfWidth; segPoints[p][1].Y = halfWidth + 1;
|
|
|
49 |
segPoints[p][2].X = elementWidth; segPoints[p][2].Y = elementWidth + 1;
|
|
|
50 |
segPoints[p][3].X = elementWidth; segPoints[p][3].Y = halfHeight - halfWidth - 1;
|
|
|
51 |
segPoints[p][4].X = 4; segPoints[p][4].Y = halfHeight - 1;
|
|
|
52 |
segPoints[p][5].X = 0; segPoints[p][5].Y = halfHeight - 1;
|
|
|
53 |
|
|
|
54 |
p++;
|
|
|
55 |
segPoints[p][0].X = gridWidth - elementWidth; segPoints[p][0].Y = elementWidth + 1;
|
|
|
56 |
segPoints[p][1].X = gridWidth - halfWidth; segPoints[p][1].Y = halfWidth + 1;
|
|
|
57 |
segPoints[p][2].X = gridWidth; segPoints[p][2].Y = elementWidth + 1;
|
|
|
58 |
segPoints[p][3].X = gridWidth; segPoints[p][3].Y = halfHeight - 1;
|
|
|
59 |
segPoints[p][4].X = gridWidth - 4; segPoints[p][4].Y = halfHeight - 1;
|
|
|
60 |
segPoints[p][5].X = gridWidth - elementWidth; segPoints[p][5].Y = halfHeight - halfWidth - 1;
|
|
|
61 |
|
|
|
62 |
p++;
|
|
|
63 |
segPoints[p][0].X = elementWidth + 1; segPoints[p][0].Y = halfHeight - halfWidth;
|
|
|
64 |
segPoints[p][1].X = gridWidth - elementWidth - 1; segPoints[p][1].Y = halfHeight - halfWidth;
|
|
|
65 |
segPoints[p][2].X = gridWidth - 5; segPoints[p][2].Y = halfHeight;
|
|
|
66 |
segPoints[p][3].X = gridWidth - elementWidth - 1; segPoints[p][3].Y = halfHeight + halfWidth;
|
|
|
67 |
segPoints[p][4].X = elementWidth + 1; segPoints[p][4].Y = halfHeight + halfWidth;
|
|
|
68 |
segPoints[p][5].X = 5; segPoints[p][5].Y = halfHeight;
|
|
|
69 |
|
|
|
70 |
p++;
|
|
|
71 |
segPoints[p][0].X = 0; segPoints[p][0].Y = halfHeight + 1;
|
|
|
72 |
segPoints[p][1].X = 4; segPoints[p][1].Y = halfHeight + 1;
|
|
|
73 |
segPoints[p][2].X = elementWidth; segPoints[p][2].Y = halfHeight + halfWidth + 1;
|
|
|
74 |
segPoints[p][3].X = elementWidth; segPoints[p][3].Y = gridHeight - elementWidth - 1;
|
|
|
75 |
segPoints[p][4].X = halfWidth; segPoints[p][4].Y = gridHeight - halfWidth - 1;
|
|
|
76 |
segPoints[p][5].X = 0; segPoints[p][5].Y = gridHeight - elementWidth - 1;
|
|
|
77 |
|
|
|
78 |
p++;
|
|
|
79 |
segPoints[p][0].X = gridWidth - elementWidth; segPoints[p][0].Y = halfHeight + halfWidth + 1;
|
|
|
80 |
segPoints[p][1].X = gridWidth - 4; segPoints[p][1].Y = halfHeight + 1;
|
|
|
81 |
segPoints[p][2].X = gridWidth; segPoints[p][2].Y = halfHeight + 1;
|
|
|
82 |
segPoints[p][3].X = gridWidth; segPoints[p][3].Y = gridHeight - elementWidth - 1;
|
|
|
83 |
segPoints[p][4].X = gridWidth - halfWidth; segPoints[p][4].Y = gridHeight - halfWidth - 1;
|
|
|
84 |
segPoints[p][5].X = gridWidth - elementWidth; segPoints[p][5].Y = gridHeight - elementWidth - 1;
|
|
|
85 |
|
|
|
86 |
p++;
|
|
|
87 |
segPoints[p][0].X = elementWidth + 1; segPoints[p][0].Y = gridHeight - elementWidth;
|
|
|
88 |
segPoints[p][1].X = gridWidth - elementWidth - 1; segPoints[p][1].Y = gridHeight - elementWidth;
|
|
|
89 |
segPoints[p][2].X = gridWidth - halfWidth - 1; segPoints[p][2].Y = gridHeight - halfWidth;
|
|
|
90 |
segPoints[p][3].X = gridWidth - elementWidth - 1; segPoints[p][3].Y = gridHeight;
|
|
|
91 |
segPoints[p][4].X = elementWidth + 1; segPoints[p][4].Y = gridHeight;
|
|
|
92 |
segPoints[p][5].X = halfWidth + 1; segPoints[p][5].Y = gridHeight - halfWidth;
|
|
|
93 |
}
|
|
|
94 |
|
|
|
95 |
private Point[][] segPoints;
|
|
|
96 |
|
|
|
97 |
private int gridHeight = 80;
|
|
|
98 |
private int gridWidth = 48;
|
|
|
99 |
private int elementWidth = 10;
|
|
|
100 |
private float italicFactor = 0.0F;
|
|
|
101 |
private Color colorBackground = Color.DarkGray;
|
|
|
102 |
private Color colorDark = Color.DimGray;
|
|
|
103 |
private Color colorLight = Color.Red;
|
|
|
104 |
|
|
|
105 |
|
|
|
106 |
/// <summary>
|
|
|
107 |
/// Background color of the 7-segment display.
|
|
|
108 |
/// </summary>
|
|
|
109 |
public Color ColorBackground { get { return colorBackground; } set { colorBackground = value; Invalidate(); } }
|
|
|
110 |
/// <summary>
|
|
|
111 |
/// Color of inactive LED segments.
|
|
|
112 |
/// </summary>
|
|
|
113 |
public Color ColorDark { get { return colorDark; } set { colorDark = value; Invalidate(); } }
|
|
|
114 |
/// <summary>
|
|
|
115 |
/// Color of active LED segments.
|
|
|
116 |
/// </summary>
|
|
|
117 |
public Color ColorLight { get { return colorLight; } set { colorLight = value; Invalidate(); } }
|
|
|
118 |
|
|
|
119 |
/// <summary>
|
|
|
120 |
/// Width of LED segments.
|
|
|
121 |
/// </summary>
|
|
|
122 |
public int ElementWidth { get { return elementWidth; } set { elementWidth = value; RecalculatePoints(); Invalidate(); } }
|
|
|
123 |
/// <summary>
|
|
|
124 |
/// Shear coefficient for italicizing the displays. Try a value like -0.1.
|
|
|
125 |
/// </summary>
|
|
|
126 |
public float ItalicFactor { get { return italicFactor; } set { italicFactor = value; Invalidate(); } }
|
|
|
127 |
|
|
|
128 |
private void SevenSegment_Resize(object sender, EventArgs e) { this.Invalidate(); }
|
|
|
129 |
protected override void OnPaddingChanged(EventArgs e) { base.OnPaddingChanged(e); this.Invalidate(); }
|
|
|
130 |
|
|
|
131 |
protected override void OnPaintBackground(PaintEventArgs e) {
|
|
|
132 |
//base.OnPaintBackground(e);
|
|
|
133 |
e.Graphics.Clear(colorBackground);
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
/// <summary>
|
|
|
137 |
/// These are the various bit patterns that represent the characters
|
|
|
138 |
/// that can be displayed in the seven segments. Bits 0 through 6
|
|
|
139 |
/// correspond to each of the LEDs, from top to bottom!
|
|
|
140 |
/// </summary>
|
|
|
141 |
public enum ValuePattern {
|
|
|
142 |
None = 0x0, Zero = 0x77, One = 0x24, Two = 0x5D, Three = 0x6D,
|
|
|
143 |
Four = 0x2E, Five = 0x6B, Six = 0x7B, Seven = 0x25,
|
|
|
144 |
Eight = 0x7F, Nine = 0x6F, A = 0x3F, B = 0x7A, C = 0x53,
|
|
|
145 |
D = 0x7C, E = 0x5B, F = 0x1B, G = 0x73, H = 0x3E,
|
|
|
146 |
J = 0x74, L = 0x52, N = 0x38, O = 0x78, P = 0x1F, Q = 0x2F, R = 0x18,
|
|
|
147 |
T = 0x5A, U = 0x76, Y = 0x6E,
|
|
|
148 |
Dash = 0x8, Equals = 0x48
|
|
|
149 |
}
|
|
|
150 |
|
|
|
151 |
private string theValue = null;
|
|
|
152 |
|
|
|
153 |
/// <summary>
|
|
|
154 |
/// Character to be displayed on the seven segments. Supported characters
|
|
|
155 |
/// are digits and most letters.
|
|
|
156 |
/// </summary>
|
|
|
157 |
public string Value {
|
|
|
158 |
get { return theValue; }
|
|
|
159 |
set {
|
|
|
160 |
customPattern = 0;
|
|
|
161 |
if (value != null) {
|
|
|
162 |
//is it an integer?
|
|
|
163 |
bool success = false;
|
|
|
164 |
try {
|
|
|
165 |
int tempValue = Convert.ToInt32(value);
|
|
|
166 |
if (tempValue > 9) tempValue = 9; if (tempValue < 0) tempValue = 0;
|
|
|
167 |
switch (tempValue) {
|
|
|
168 |
case 0: customPattern = (int)ValuePattern.Zero; break;
|
|
|
169 |
case 1: customPattern = (int)ValuePattern.One; break;
|
|
|
170 |
case 2: customPattern = (int)ValuePattern.Two; break;
|
|
|
171 |
case 3: customPattern = (int)ValuePattern.Three; break;
|
|
|
172 |
case 4: customPattern = (int)ValuePattern.Four; break;
|
|
|
173 |
case 5: customPattern = (int)ValuePattern.Five; break;
|
|
|
174 |
case 6: customPattern = (int)ValuePattern.Six; break;
|
|
|
175 |
case 7: customPattern = (int)ValuePattern.Seven; break;
|
|
|
176 |
case 8: customPattern = (int)ValuePattern.Eight; break;
|
|
|
177 |
case 9: customPattern = (int)ValuePattern.Nine; break;
|
|
|
178 |
}
|
|
|
179 |
success = true;
|
|
|
180 |
} catch { }
|
|
|
181 |
if (!success) {
|
|
|
182 |
try {
|
|
|
183 |
//is it a letter?
|
|
|
184 |
string tempString = Convert.ToString(value);
|
|
|
185 |
switch (tempString.ToLower()[0]) {
|
|
|
186 |
case 'a': customPattern = (int)ValuePattern.A; break;
|
|
|
187 |
case 'b': customPattern = (int)ValuePattern.B; break;
|
|
|
188 |
case 'c': customPattern = (int)ValuePattern.C; break;
|
|
|
189 |
case 'd': customPattern = (int)ValuePattern.D; break;
|
|
|
190 |
case 'e': customPattern = (int)ValuePattern.E; break;
|
|
|
191 |
case 'f': customPattern = (int)ValuePattern.F; break;
|
|
|
192 |
case 'g': customPattern = (int)ValuePattern.G; break;
|
|
|
193 |
case 'h': customPattern = (int)ValuePattern.H; break;
|
|
|
194 |
case 'j': customPattern = (int)ValuePattern.J; break;
|
|
|
195 |
case 'l': customPattern = (int)ValuePattern.L; break;
|
|
|
196 |
case 'n': customPattern = (int)ValuePattern.N; break;
|
|
|
197 |
case 'o': customPattern = (int)ValuePattern.O; break;
|
|
|
198 |
case 'p': customPattern = (int)ValuePattern.P; break;
|
|
|
199 |
case 'q': customPattern = (int)ValuePattern.Q; break;
|
|
|
200 |
case 'r': customPattern = (int)ValuePattern.R; break;
|
|
|
201 |
case 't': customPattern = (int)ValuePattern.T; break;
|
|
|
202 |
case 'u': customPattern = (int)ValuePattern.U; break;
|
|
|
203 |
case 'y': customPattern = (int)ValuePattern.Y; break;
|
|
|
204 |
case '-': customPattern = (int)ValuePattern.Dash; break;
|
|
|
205 |
case '=': customPattern = (int)ValuePattern.Equals; break;
|
|
|
206 |
}
|
|
|
207 |
} catch { }
|
|
|
208 |
}
|
|
|
209 |
}
|
|
|
210 |
theValue = value; Invalidate();
|
|
|
211 |
}
|
|
|
212 |
}
|
|
|
213 |
|
|
|
214 |
private int customPattern = 0;
|
|
|
215 |
/// <summary>
|
|
|
216 |
/// Set a custom bit pattern to be displayed on the seven segments. This is an
|
|
|
217 |
/// integer value where bits 0 through 6 correspond to each respective LED
|
|
|
218 |
/// segment.
|
|
|
219 |
/// </summary>
|
|
|
220 |
public int CustomPattern { get { return customPattern; } set { customPattern = value; Invalidate(); } }
|
|
|
221 |
|
|
|
222 |
private bool showDot = true, dotOn = false;
|
|
|
223 |
/// <summary>
|
|
|
224 |
/// Specifies if the decimal point LED is displayed.
|
|
|
225 |
/// </summary>
|
|
|
226 |
public bool DecimalShow { get { return showDot; } set { showDot = value; Invalidate(); } }
|
|
|
227 |
/// <summary>
|
|
|
228 |
/// Specifies if the decimal point LED is active.
|
|
|
229 |
/// </summary>
|
|
|
230 |
public bool DecimalOn { get { return dotOn; } set { dotOn = value; Invalidate(); } }
|
|
|
231 |
|
|
|
232 |
|
|
|
233 |
private void SevenSegment_Paint(object sender, PaintEventArgs e) {
|
|
|
234 |
int useValue = customPattern;
|
|
|
235 |
|
|
|
236 |
Brush brushLight = new SolidBrush(colorLight);
|
|
|
237 |
Brush brushDark = new SolidBrush(colorDark);
|
|
|
238 |
|
|
|
239 |
// Define transformation for our container...
|
|
|
240 |
RectangleF srcRect = new RectangleF(0.0F, 0.0F, gridWidth, gridHeight);
|
|
|
241 |
RectangleF destRect = new RectangleF(Padding.Left, Padding.Top, this.Width - Padding.Left - Padding.Right, this.Height - Padding.Top - Padding.Bottom);
|
|
|
242 |
|
|
|
243 |
// Begin graphics container that remaps coordinates for our convenience
|
|
|
244 |
GraphicsContainer containerState = e.Graphics.BeginContainer(destRect, srcRect, GraphicsUnit.Pixel);
|
|
|
245 |
|
|
|
246 |
Matrix trans = new Matrix();
|
|
|
247 |
trans.Shear(italicFactor, 0.0F);
|
|
|
248 |
e.Graphics.Transform = trans;
|
|
|
249 |
|
|
|
250 |
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
|
|
|
251 |
e.Graphics.PixelOffsetMode = PixelOffsetMode.Default;
|
|
|
252 |
|
|
|
253 |
// Draw elements based on whether the corresponding bit is high
|
|
|
254 |
e.Graphics.FillPolygon((useValue & 0x1) == 0x1 ? brushLight : brushDark, segPoints[0]);
|
|
|
255 |
e.Graphics.FillPolygon((useValue & 0x2) == 0x2 ? brushLight : brushDark, segPoints[1]);
|
|
|
256 |
e.Graphics.FillPolygon((useValue & 0x4) == 0x4 ? brushLight : brushDark, segPoints[2]);
|
|
|
257 |
e.Graphics.FillPolygon((useValue & 0x8) == 0x8 ? brushLight : brushDark, segPoints[3]);
|
|
|
258 |
e.Graphics.FillPolygon((useValue & 0x10) == 0x10 ? brushLight : brushDark, segPoints[4]);
|
|
|
259 |
e.Graphics.FillPolygon((useValue & 0x20) == 0x20 ? brushLight : brushDark, segPoints[5]);
|
|
|
260 |
e.Graphics.FillPolygon((useValue & 0x40) == 0x40 ? brushLight : brushDark, segPoints[6]);
|
|
|
261 |
|
|
|
262 |
if (showDot)
|
|
|
263 |
e.Graphics.FillEllipse(dotOn ? brushLight : brushDark, gridWidth - 1, gridHeight - elementWidth + 1, elementWidth, elementWidth);
|
|
|
264 |
|
|
|
265 |
e.Graphics.EndContainer(containerState);
|
|
|
266 |
}
|
|
|
267 |
|
|
|
268 |
|
|
|
269 |
}
|
|
|
270 |
}
|