]>
Commit | Line | Data |
---|---|---|
950e7faf RD |
1 | // ============================================================================ |
2 | // headers | |
3 | // ============================================================================ | |
4 | ||
5 | #ifdef __GNUG__ | |
6 | #pragma implementation "wxLEDNumberCtrl.h" | |
7 | #endif | |
8 | ||
9 | #include "wx/wxprec.h" | |
10 | ||
11 | #ifdef __BORLANDC__ | |
12 | #pragma hdrstop | |
13 | #endif //__BORLANDC__ | |
14 | ||
15 | #ifndef WX_PRECOMP | |
16 | #include "wx/dcclient.h" | |
17 | #include "wx/dcmemory.h" | |
18 | #include "wx/intl.h" | |
19 | #endif | |
20 | ||
21 | #include "wx/gizmos/ledctrl.h" | |
22 | ||
23 | // ---------------------------------------------------------------------------- | |
24 | // constants | |
25 | // ---------------------------------------------------------------------------- | |
26 | ||
27 | // A LED digit is build up like this, with maximum 7 Lines : | |
28 | // | |
29 | // 111 | |
30 | // 6 2 | |
31 | // 777 | |
32 | // 5 3 | |
33 | // 444 | |
34 | // | |
35 | // Each number contains combinations of the lines, and they are set up below. | |
36 | ||
37 | const int LINE1 = 1; | |
38 | const int LINE2 = 2; | |
39 | const int LINE3 = 4; | |
40 | const int LINE4 = 8; | |
41 | const int LINE5 = 16; | |
42 | const int LINE6 = 32; | |
43 | const int LINE7 = 64; | |
db11ea90 | 44 | const int DECIMALSIGN = 128; |
950e7faf RD |
45 | |
46 | const int DIGIT0 = LINE1 | LINE2 | LINE3 | LINE4 | LINE5 | LINE6; | |
47 | const int DIGIT1 = LINE2 | LINE3; | |
48 | const int DIGIT2 = LINE1 | LINE2 | LINE4 | LINE5 | LINE7; | |
49 | const int DIGIT3 = LINE1 | LINE2 | LINE3 | LINE4 | LINE7; | |
50 | const int DIGIT4 = LINE2 | LINE3 | LINE6 | LINE7; | |
51 | const int DIGIT5 = LINE1 | LINE3 | LINE4 | LINE6 | LINE7; | |
52 | const int DIGIT6 = LINE1 | LINE3 | LINE4 | LINE5 | LINE6 | LINE7; | |
53 | const int DIGIT7 = LINE1 | LINE2 | LINE3; | |
54 | const int DIGIT8 = LINE1 | LINE2 | LINE3 | LINE4 | LINE5 | LINE6 | LINE7; | |
55 | const int DIGIT9 = LINE1 | LINE2 | LINE3 | LINE6 | LINE7; | |
56 | const int DASH = LINE7; | |
57 | ||
58 | const int DIGITALL = -1; | |
59 | ||
60 | // ============================================================================ | |
61 | // wxLEDNumberCtrl class implementation | |
62 | // ============================================================================ | |
63 | ||
64 | wxLEDNumberCtrl::wxLEDNumberCtrl() | |
65 | : m_Alignment(wxLED_ALIGN_LEFT), | |
66 | m_LineMargin(-1), | |
67 | m_DigitMargin(-1), | |
68 | m_LineLength(-1), | |
69 | m_LineWidth(-1), | |
a2d49353 | 70 | m_DrawFaded(false), |
950e7faf RD |
71 | m_LeftStartPos(-1) |
72 | { | |
73 | } | |
74 | ||
75 | ||
76 | wxLEDNumberCtrl::wxLEDNumberCtrl(wxWindow *parent, wxWindowID id, | |
77 | const wxPoint& pos, const wxSize& size, | |
78 | long style) | |
79 | : m_Alignment(wxLED_ALIGN_LEFT), | |
80 | m_LineMargin(-1), | |
81 | m_DigitMargin(-1), | |
82 | m_LineLength(-1), | |
83 | m_LineWidth(-1), | |
a2d49353 | 84 | m_DrawFaded(false), |
950e7faf RD |
85 | m_LeftStartPos(-1) |
86 | { | |
87 | Create(parent, id, pos, size, style); | |
88 | } | |
89 | ||
90 | ||
91 | bool wxLEDNumberCtrl::Create(wxWindow *parent, wxWindowID id, | |
92 | const wxPoint& pos, const wxSize& size, | |
93 | long style) | |
94 | { | |
95 | bool RetVal = wxControl::Create(parent, id, pos, size, style); | |
96 | ||
97 | if ((style & wxLED_DRAW_FADED) != 0) | |
a2d49353 | 98 | SetDrawFaded(true); |
950e7faf RD |
99 | if ((style & wxLED_ALIGN_MASK) != 0) |
100 | SetAlignment((wxLEDValueAlign)(style & wxLED_ALIGN_MASK)); | |
101 | ||
102 | SetBackgroundColour(*wxBLACK); | |
103 | SetForegroundColour(*wxGREEN); | |
104 | ||
105 | return RetVal; | |
106 | } | |
107 | ||
108 | ||
109 | void wxLEDNumberCtrl::SetAlignment(wxLEDValueAlign Alignment, bool Redraw) | |
110 | { | |
111 | if (Alignment != m_Alignment) | |
112 | { | |
113 | m_Alignment = Alignment; | |
114 | RecalcInternals(GetClientSize()); | |
115 | ||
116 | if (Redraw) | |
a2d49353 | 117 | Refresh(false); |
950e7faf RD |
118 | } |
119 | } | |
120 | ||
121 | ||
122 | void wxLEDNumberCtrl::SetDrawFaded(bool DrawFaded, bool Redraw) | |
123 | { | |
124 | if (DrawFaded != m_DrawFaded) | |
125 | { | |
126 | m_DrawFaded = DrawFaded; | |
127 | ||
128 | if (Redraw) | |
a2d49353 | 129 | Refresh(false); |
950e7faf RD |
130 | } |
131 | } | |
132 | ||
133 | ||
134 | void wxLEDNumberCtrl::SetValue(wxString const &Value, bool Redraw) | |
135 | { | |
136 | if (Value != m_Value) | |
137 | { | |
03342448 | 138 | #ifdef __WXDEBUG__ |
72f09e49 | 139 | if (!Value.empty()) |
950e7faf RD |
140 | { |
141 | for(size_t i=0; i<Value.Length(); i++) { | |
142 | wxChar ch = Value[i]; | |
db11ea90 | 143 | wxASSERT_MSG((ch>='0' && ch<='9') || ch=='-' || ch==' ' || ch=='.', |
950e7faf RD |
144 | wxT("wxLEDNumberCtrl can only display numeric string values.")); |
145 | } | |
146 | } | |
03342448 | 147 | #endif |
950e7faf RD |
148 | |
149 | m_Value = Value; | |
150 | RecalcInternals(GetClientSize()); | |
151 | ||
152 | if (Redraw) | |
a2d49353 | 153 | Refresh(false); |
950e7faf RD |
154 | } |
155 | } | |
156 | ||
157 | ||
158 | BEGIN_EVENT_TABLE(wxLEDNumberCtrl, wxControl) | |
159 | EVT_ERASE_BACKGROUND(wxLEDNumberCtrl::OnEraseBackground) | |
160 | EVT_PAINT(wxLEDNumberCtrl::OnPaint) | |
161 | EVT_SIZE(wxLEDNumberCtrl::OnSize) | |
162 | END_EVENT_TABLE() | |
163 | ||
164 | ||
c3f815fa | 165 | void wxLEDNumberCtrl::OnEraseBackground(wxEraseEvent &WXUNUSED(event)) |
950e7faf RD |
166 | { |
167 | } | |
168 | ||
169 | ||
c3f815fa | 170 | void wxLEDNumberCtrl::OnPaint(wxPaintEvent &WXUNUSED(event)) |
950e7faf RD |
171 | { |
172 | wxPaintDC Dc(this); | |
173 | ||
174 | int Width, Height; | |
175 | GetClientSize(&Width, &Height); | |
176 | ||
177 | wxBitmap *pMemoryBitmap = new wxBitmap(Width, Height); | |
178 | wxMemoryDC MemDc; | |
179 | ||
180 | MemDc.SelectObject(*pMemoryBitmap); | |
181 | MemDc.BeginDrawing(); | |
182 | ||
183 | // Draw background. | |
184 | MemDc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID)); | |
185 | MemDc.DrawRectangle(wxRect(0, 0, Width, Height)); | |
186 | MemDc.SetBrush(wxNullBrush); | |
187 | ||
188 | // Iterate each digit in the value, and draw. | |
189 | const int DigitCount = m_Value.Len(); | |
db11ea90 | 190 | for (int offset=0, i = 0; offset < DigitCount; ++offset, ++i) |
950e7faf | 191 | { |
289cd4e2 | 192 | wxChar c = m_Value.GetChar(offset); |
db11ea90 | 193 | |
950e7faf | 194 | // Draw faded lines if wanted. |
289cd4e2 | 195 | if (m_DrawFaded && (c != _T('.'))) |
950e7faf RD |
196 | DrawDigit(MemDc, DIGITALL, i); |
197 | ||
198 | // Draw the digits. | |
db11ea90 | 199 | switch (c) |
950e7faf | 200 | { |
289cd4e2 | 201 | case _T('0') : |
950e7faf RD |
202 | DrawDigit(MemDc, DIGIT0, i); |
203 | break; | |
289cd4e2 | 204 | case _T('1') : |
950e7faf RD |
205 | DrawDigit(MemDc, DIGIT1, i); |
206 | break; | |
289cd4e2 | 207 | case _T('2') : |
950e7faf RD |
208 | DrawDigit(MemDc, DIGIT2, i); |
209 | break; | |
289cd4e2 | 210 | case _T('3') : |
950e7faf RD |
211 | DrawDigit(MemDc, DIGIT3, i); |
212 | break; | |
289cd4e2 | 213 | case _T('4') : |
950e7faf RD |
214 | DrawDigit(MemDc, DIGIT4, i); |
215 | break; | |
289cd4e2 | 216 | case _T('5') : |
950e7faf RD |
217 | DrawDigit(MemDc, DIGIT5, i); |
218 | break; | |
289cd4e2 | 219 | case _T('6') : |
950e7faf RD |
220 | DrawDigit(MemDc, DIGIT6, i); |
221 | break; | |
289cd4e2 | 222 | case _T('7') : |
950e7faf RD |
223 | DrawDigit(MemDc, DIGIT7, i); |
224 | break; | |
289cd4e2 | 225 | case _T('8') : |
950e7faf RD |
226 | DrawDigit(MemDc, DIGIT8, i); |
227 | break; | |
289cd4e2 | 228 | case _T('9') : |
950e7faf RD |
229 | DrawDigit(MemDc, DIGIT9, i); |
230 | break; | |
289cd4e2 | 231 | case _T('-') : |
950e7faf RD |
232 | DrawDigit(MemDc, DASH, i); |
233 | break; | |
289cd4e2 | 234 | case _T('.') : |
db11ea90 WS |
235 | // Display the decimal in the previous segment |
236 | i--; | |
237 | DrawDigit(MemDc, DECIMALSIGN, i); | |
238 | break; | |
289cd4e2 | 239 | case _T(' ') : |
950e7faf RD |
240 | // just skip it |
241 | break; | |
242 | default : | |
501d97d4 | 243 | wxFAIL_MSG(wxT("Unknown digit value")); |
950e7faf RD |
244 | break; |
245 | } | |
246 | } | |
247 | ||
248 | MemDc.EndDrawing(); | |
249 | ||
250 | // Blit the memory dc to screen. | |
251 | Dc.Blit(0, 0, Width, Height, &MemDc, 0, 0, wxCOPY); | |
252 | delete pMemoryBitmap; | |
253 | } | |
254 | ||
255 | ||
256 | void wxLEDNumberCtrl::DrawDigit(wxDC &Dc, int Digit, int Column) | |
257 | { | |
258 | wxColour LineColor(GetForegroundColour()); | |
259 | ||
260 | if (Digit == DIGITALL) | |
261 | { | |
72f09e49 WS |
262 | const unsigned char R = (unsigned char)(LineColor.Red() / 16); |
263 | const unsigned char G = (unsigned char)(LineColor.Green() / 16); | |
264 | const unsigned char B = (unsigned char)(LineColor.Blue() / 16); | |
950e7faf RD |
265 | |
266 | LineColor.Set(R, G, B); | |
267 | } | |
268 | ||
db11ea90 | 269 | int XPos = m_LeftStartPos + Column * (m_LineLength + m_DigitMargin); |
950e7faf RD |
270 | |
271 | // Create a pen and draw the lines. | |
272 | wxPen Pen(LineColor, m_LineWidth, wxSOLID); | |
273 | Dc.SetPen(Pen); | |
274 | ||
275 | if ((Digit & LINE1)) | |
276 | { | |
277 | Dc.DrawLine(XPos + m_LineMargin*2, m_LineMargin, | |
db11ea90 | 278 | XPos + m_LineLength + m_LineMargin*2, m_LineMargin); |
a2d49353 | 279 | } |
950e7faf RD |
280 | |
281 | if (Digit & LINE2) | |
282 | { | |
db11ea90 WS |
283 | Dc.DrawLine(XPos + m_LineLength + m_LineMargin*3, m_LineMargin*2, |
284 | XPos + m_LineLength + m_LineMargin*3, m_LineLength + (m_LineMargin*2)); | |
950e7faf RD |
285 | } |
286 | ||
287 | if (Digit & LINE3) | |
288 | { | |
db11ea90 WS |
289 | Dc.DrawLine(XPos + m_LineLength + m_LineMargin*3, m_LineLength + (m_LineMargin*4), |
290 | XPos + m_LineLength + m_LineMargin*3, m_LineLength*2 + (m_LineMargin*4)); | |
950e7faf RD |
291 | } |
292 | ||
293 | if (Digit & LINE4) | |
294 | { | |
db11ea90 WS |
295 | Dc.DrawLine(XPos + m_LineMargin*2, m_LineLength*2 + (m_LineMargin*5), |
296 | XPos + m_LineLength + m_LineMargin*2, m_LineLength*2 + (m_LineMargin*5)); | |
950e7faf RD |
297 | } |
298 | ||
299 | if (Digit & LINE5) | |
300 | { | |
301 | Dc.DrawLine(XPos + m_LineMargin, m_LineLength + (m_LineMargin*4), | |
db11ea90 | 302 | XPos + m_LineMargin, m_LineLength*2 + (m_LineMargin*4)); |
950e7faf RD |
303 | } |
304 | ||
305 | if (Digit & LINE6) | |
306 | { | |
307 | Dc.DrawLine(XPos + m_LineMargin, m_LineMargin*2, | |
308 | XPos + m_LineMargin, m_LineLength + (m_LineMargin*2)); | |
309 | } | |
310 | ||
311 | if (Digit & LINE7) | |
312 | { | |
313 | Dc.DrawLine(XPos + m_LineMargin*2, m_LineLength + (m_LineMargin*3), | |
db11ea90 WS |
314 | XPos + m_LineMargin*2 + m_LineLength, m_LineLength + (m_LineMargin*3)); |
315 | } | |
316 | ||
317 | if (Digit & DECIMALSIGN) | |
318 | { | |
319 | Dc.DrawLine(XPos + m_LineLength + m_LineMargin*4, m_LineLength*2 + (m_LineMargin*5), | |
320 | XPos + m_LineLength + m_LineMargin*4, m_LineLength*2 + (m_LineMargin*5)); | |
950e7faf RD |
321 | } |
322 | ||
323 | Dc.SetPen(wxNullPen); | |
324 | } | |
325 | ||
326 | ||
327 | void wxLEDNumberCtrl::RecalcInternals(const wxSize &CurrentSize) | |
328 | { | |
db11ea90 WS |
329 | // Dimensions of LED segments |
330 | // | |
331 | // Size of character is based on the HEIGH of the widget, NOT the width. | |
332 | // Segment height is calculated as follows: | |
333 | // Each segment is m_LineLength pixels long. | |
334 | // There is m_LineMargin pixels at the top and bottom of each line segment | |
335 | // There is m_LineMargin pixels at the top and bottom of each digit | |
336 | // | |
337 | // Therefore, the heigth of each character is: | |
338 | // m_LineMargin : Top digit boarder | |
339 | // m_LineMargin+m_LineLength+m_LineMargin : Top half of segment | |
340 | // m_LineMargin+m_LineLength+m_LineMargin : Bottom half of segment | |
341 | // m_LineMargin : Bottom digit boarder | |
342 | // ---------------------- | |
343 | // m_LineMargin*6 + m_LineLength*2 == Total height of digit. | |
344 | // Therefore, (m_LineMargin*6 + m_LineLength*2) must equal Height | |
345 | // | |
346 | // Spacing between characters can then be calculated as follows: | |
347 | // m_LineMargin : before the digit, | |
348 | // m_LineMargin+m_LineLength+m_LineMargin : for the digit width | |
349 | // m_LineMargin : after the digit | |
350 | // = m_LineMargin*4 + m_LineLength | |
950e7faf RD |
351 | const int Height = CurrentSize.GetHeight(); |
352 | ||
db11ea90 | 353 | if ((Height * 0.075) < 1) |
950e7faf RD |
354 | m_LineMargin = 1; |
355 | else | |
db11ea90 | 356 | m_LineMargin = (int)(Height * 0.075); |
950e7faf | 357 | |
db11ea90 | 358 | if ((Height * 0.275) < 1) |
950e7faf RD |
359 | m_LineLength = 1; |
360 | else | |
db11ea90 | 361 | m_LineLength = (int)(Height * 0.275); |
950e7faf RD |
362 | |
363 | m_LineWidth = m_LineMargin; | |
364 | ||
365 | m_DigitMargin = m_LineMargin * 4; | |
366 | ||
db11ea90 WS |
367 | // Count the number of characters in the string; '.' characters are not |
368 | // included because they do not take up space in the display | |
369 | int count = 0; | |
370 | for (unsigned int i = 0; i < m_Value.Len(); i++) | |
371 | if (m_Value.GetChar(i) != '.') | |
372 | count++; | |
373 | const int ValueWidth = (m_LineLength + m_DigitMargin) * count; | |
950e7faf RD |
374 | const int ClientWidth = CurrentSize.GetWidth(); |
375 | ||
376 | switch (m_Alignment) | |
377 | { | |
378 | case wxLED_ALIGN_LEFT : | |
db11ea90 | 379 | m_LeftStartPos = m_LineMargin; |
950e7faf RD |
380 | break; |
381 | case wxLED_ALIGN_RIGHT : | |
db11ea90 | 382 | m_LeftStartPos = ClientWidth - ValueWidth - m_LineMargin; |
950e7faf RD |
383 | break; |
384 | case wxLED_ALIGN_CENTER : | |
385 | m_LeftStartPos = (ClientWidth - ValueWidth) / 2; | |
386 | break; | |
387 | default : | |
501d97d4 | 388 | wxFAIL_MSG(wxT("Unknown alignent value for wxLEDNumberCtrl.")); |
950e7faf RD |
389 | break; |
390 | } | |
391 | } | |
392 | ||
393 | ||
394 | void wxLEDNumberCtrl::OnSize(wxSizeEvent &Event) | |
395 | { | |
396 | RecalcInternals(Event.GetSize()); | |
397 | ||
398 | Event.Skip(); | |
399 | } |