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