]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/gizmos/ledctrl.cpp
Added knowledge of virtual size to wx(Scrolled)Windows, they can now
[wxWidgets.git] / contrib / src / gizmos / ledctrl.cpp
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;
44
45 const int DIGIT0 = LINE1 | LINE2 | LINE3 | LINE4 | LINE5 | LINE6;
46 const int DIGIT1 = LINE2 | LINE3;
47 const int DIGIT2 = LINE1 | LINE2 | LINE4 | LINE5 | LINE7;
48 const int DIGIT3 = LINE1 | LINE2 | LINE3 | LINE4 | LINE7;
49 const int DIGIT4 = LINE2 | LINE3 | LINE6 | LINE7;
50 const int DIGIT5 = LINE1 | LINE3 | LINE4 | LINE6 | LINE7;
51 const int DIGIT6 = LINE1 | LINE3 | LINE4 | LINE5 | LINE6 | LINE7;
52 const int DIGIT7 = LINE1 | LINE2 | LINE3;
53 const int DIGIT8 = LINE1 | LINE2 | LINE3 | LINE4 | LINE5 | LINE6 | LINE7;
54 const int DIGIT9 = LINE1 | LINE2 | LINE3 | LINE6 | LINE7;
55 const int DASH = LINE7;
56
57 const int DIGITALL = -1;
58
59 // ============================================================================
60 // wxLEDNumberCtrl class implementation
61 // ============================================================================
62
63 wxLEDNumberCtrl::wxLEDNumberCtrl()
64 : m_Alignment(wxLED_ALIGN_LEFT),
65 m_LineMargin(-1),
66 m_DigitMargin(-1),
67 m_LineLength(-1),
68 m_LineWidth(-1),
69 m_DrawFaded(FALSE),
70 m_LeftStartPos(-1)
71 {
72 }
73
74
75 wxLEDNumberCtrl::wxLEDNumberCtrl(wxWindow *parent, wxWindowID id,
76 const wxPoint& pos, const wxSize& size,
77 long style)
78 : m_Alignment(wxLED_ALIGN_LEFT),
79 m_LineMargin(-1),
80 m_DigitMargin(-1),
81 m_LineLength(-1),
82 m_LineWidth(-1),
83 m_DrawFaded(FALSE),
84 m_LeftStartPos(-1)
85 {
86 Create(parent, id, pos, size, style);
87 }
88
89
90 bool wxLEDNumberCtrl::Create(wxWindow *parent, wxWindowID id,
91 const wxPoint& pos, const wxSize& size,
92 long style)
93 {
94 bool RetVal = wxControl::Create(parent, id, pos, size, style);
95
96 if ((style & wxLED_DRAW_FADED) != 0)
97 SetDrawFaded(TRUE);
98 if ((style & wxLED_ALIGN_MASK) != 0)
99 SetAlignment((wxLEDValueAlign)(style & wxLED_ALIGN_MASK));
100
101 SetBackgroundColour(*wxBLACK);
102 SetForegroundColour(*wxGREEN);
103
104 return RetVal;
105 }
106
107
108 void wxLEDNumberCtrl::SetAlignment(wxLEDValueAlign Alignment, bool Redraw)
109 {
110 if (Alignment != m_Alignment)
111 {
112 m_Alignment = Alignment;
113 RecalcInternals(GetClientSize());
114
115 if (Redraw)
116 Refresh(FALSE);
117 }
118 }
119
120
121 void wxLEDNumberCtrl::SetDrawFaded(bool DrawFaded, bool Redraw)
122 {
123 if (DrawFaded != m_DrawFaded)
124 {
125 m_DrawFaded = DrawFaded;
126
127 if (Redraw)
128 Refresh(FALSE);
129 }
130 }
131
132
133 void wxLEDNumberCtrl::SetValue(wxString const &Value, bool Redraw)
134 {
135 if (Value != m_Value)
136 {
137 #ifdef __WXDEBUG__
138 if (!Value.IsEmpty())
139 {
140 for(size_t i=0; i<Value.Length(); i++) {
141 wxChar ch = Value[i];
142 wxASSERT_MSG((ch>='0' && ch<='9') || ch=='-' || ch==' ',
143 wxT("wxLEDNumberCtrl can only display numeric string values."));
144 }
145 }
146 #endif
147
148 m_Value = Value;
149 RecalcInternals(GetClientSize());
150
151 if (Redraw)
152 Refresh(FALSE);
153 }
154 }
155
156
157 BEGIN_EVENT_TABLE(wxLEDNumberCtrl, wxControl)
158 EVT_ERASE_BACKGROUND(wxLEDNumberCtrl::OnEraseBackground)
159 EVT_PAINT(wxLEDNumberCtrl::OnPaint)
160 EVT_SIZE(wxLEDNumberCtrl::OnSize)
161 END_EVENT_TABLE()
162
163
164 void wxLEDNumberCtrl::OnEraseBackground(wxEraseEvent &Event)
165 {
166 }
167
168
169 void wxLEDNumberCtrl::OnPaint(wxPaintEvent &Event)
170 {
171 wxPaintDC Dc(this);
172
173 int Width, Height;
174 GetClientSize(&Width, &Height);
175
176 wxBitmap *pMemoryBitmap = new wxBitmap(Width, Height);
177 wxMemoryDC MemDc;
178
179 MemDc.SelectObject(*pMemoryBitmap);
180 MemDc.BeginDrawing();
181
182 // Draw background.
183 MemDc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
184 MemDc.DrawRectangle(wxRect(0, 0, Width, Height));
185 MemDc.SetBrush(wxNullBrush);
186
187 // Iterate each digit in the value, and draw.
188 const int DigitCount = m_Value.Len();
189 for (int i = 0; i < DigitCount; ++i)
190 {
191 // Draw faded lines if wanted.
192 if (m_DrawFaded)
193 DrawDigit(MemDc, DIGITALL, i);
194
195 // Draw the digits.
196 switch (m_Value.GetChar(i))
197 {
198 case '0' :
199 DrawDigit(MemDc, DIGIT0, i);
200 break;
201 case '1' :
202 DrawDigit(MemDc, DIGIT1, i);
203 break;
204 case '2' :
205 DrawDigit(MemDc, DIGIT2, i);
206 break;
207 case '3' :
208 DrawDigit(MemDc, DIGIT3, i);
209 break;
210 case '4' :
211 DrawDigit(MemDc, DIGIT4, i);
212 break;
213 case '5' :
214 DrawDigit(MemDc, DIGIT5, i);
215 break;
216 case '6' :
217 DrawDigit(MemDc, DIGIT6, i);
218 break;
219 case '7' :
220 DrawDigit(MemDc, DIGIT7, i);
221 break;
222 case '8' :
223 DrawDigit(MemDc, DIGIT8, i);
224 break;
225 case '9' :
226 DrawDigit(MemDc, DIGIT9, i);
227 break;
228 case '-' :
229 DrawDigit(MemDc, DASH, i);
230 break;
231 case ' ' :
232 // just skip it
233 break;
234 default :
235 wxFAIL_MSG(wxT("Unknown digit value"));
236 break;
237 }
238 }
239
240 MemDc.EndDrawing();
241
242 // Blit the memory dc to screen.
243 Dc.Blit(0, 0, Width, Height, &MemDc, 0, 0, wxCOPY);
244 delete pMemoryBitmap;
245 }
246
247
248 void wxLEDNumberCtrl::DrawDigit(wxDC &Dc, int Digit, int Column)
249 {
250 wxColour LineColor(GetForegroundColour());
251
252 if (Digit == DIGITALL)
253 {
254 const int R = LineColor.Red() / 3;
255 const int G = LineColor.Green() / 3;
256 const int B = LineColor.Blue() / 3;
257
258 LineColor.Set(R, G, B);
259 }
260
261 int XPos = m_LeftStartPos;
262
263 if (Column > 0)
264 XPos += (Column * m_LineLength) + (m_DigitMargin) * Column;
265
266 // Create a pen and draw the lines.
267 wxPen Pen(LineColor, m_LineWidth, wxSOLID);
268 Dc.SetPen(Pen);
269
270 if ((Digit & LINE1))
271 {
272 Dc.DrawLine(XPos + m_LineMargin*2, m_LineMargin,
273 XPos + m_LineLength, m_LineMargin);
274 }
275
276 if (Digit & LINE2)
277 {
278 Dc.DrawLine(XPos + m_LineLength + m_LineMargin, m_LineMargin*2,
279 XPos + m_LineLength + m_LineMargin, m_LineLength + (m_LineMargin*2));
280 }
281
282 if (Digit & LINE3)
283 {
284 Dc.DrawLine(XPos + m_LineLength + m_LineMargin, m_LineLength + (m_LineMargin*4),
285 XPos + m_LineLength + m_LineMargin, m_LineLength*2 + (m_LineMargin*3));
286 }
287
288 if (Digit & LINE4)
289 {
290 Dc.DrawLine(XPos + m_LineMargin*2, m_LineLength*2 + (m_LineMargin*4),
291 XPos + m_LineLength, m_LineLength*2 + (m_LineMargin*4));
292 }
293
294 if (Digit & LINE5)
295 {
296 Dc.DrawLine(XPos + m_LineMargin, m_LineLength + (m_LineMargin*4),
297 XPos + m_LineMargin, m_LineLength*2 + (m_LineMargin*3));
298 }
299
300 if (Digit & LINE6)
301 {
302 Dc.DrawLine(XPos + m_LineMargin, m_LineMargin*2,
303 XPos + m_LineMargin, m_LineLength + (m_LineMargin*2));
304 }
305
306 if (Digit & LINE7)
307 {
308 Dc.DrawLine(XPos + m_LineMargin*2, m_LineLength + (m_LineMargin*3),
309 XPos + m_LineMargin + m_LineLength - m_LineMargin, m_LineLength + (m_LineMargin*3));
310 }
311
312 Dc.SetPen(wxNullPen);
313 }
314
315
316 void wxLEDNumberCtrl::RecalcInternals(const wxSize &CurrentSize)
317 {
318 const int Height = CurrentSize.GetHeight();
319
320 if ((Height * 0.07) < 1)
321 m_LineMargin = 1;
322 else
323 m_LineMargin = (int)(Height * 0.07);
324
325 if ((Height * 0.35) < 1)
326 m_LineLength = 1;
327 else
328 m_LineLength = (int)(Height * 0.35);
329
330 m_LineWidth = m_LineMargin;
331
332 m_DigitMargin = m_LineMargin * 4;
333
334 const int ValueWidth = (m_LineLength + m_DigitMargin) * m_Value.Len();
335 const int ClientWidth = CurrentSize.GetWidth();
336
337 switch (m_Alignment)
338 {
339 case wxLED_ALIGN_LEFT :
340 m_LeftStartPos = 0;
341 break;
342 case wxLED_ALIGN_RIGHT :
343 m_LeftStartPos = ClientWidth - ValueWidth;
344 break;
345 case wxLED_ALIGN_CENTER :
346 m_LeftStartPos = (ClientWidth - ValueWidth) / 2;
347 break;
348 default :
349 wxFAIL_MSG(wxT("Unknown alignent value for wxLEDNumberCtrl."));
350 break;
351 }
352 }
353
354
355 void wxLEDNumberCtrl::OnSize(wxSizeEvent &Event)
356 {
357 RecalcInternals(Event.GetSize());
358
359 Event.Skip();
360 }