]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/gizmos/ledctrl.cpp
fixed bug with the caret positioning after SetValue() introduced by the last commit
[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 if (!Value.IsEmpty())
138 {
139 for(size_t i=0; i<Value.Length(); i++) {
140 wxChar ch = Value[i];
141 wxASSERT_MSG((ch>='0' && ch<='9') || ch=='-' || ch==' ',
142 wxT("wxLEDNumberCtrl can only display numeric string values."));
143 }
144 }
145
146 m_Value = Value;
147 RecalcInternals(GetClientSize());
148
149 if (Redraw)
150 Refresh(FALSE);
151 }
152 }
153
154
155 BEGIN_EVENT_TABLE(wxLEDNumberCtrl, wxControl)
156 EVT_ERASE_BACKGROUND(wxLEDNumberCtrl::OnEraseBackground)
157 EVT_PAINT(wxLEDNumberCtrl::OnPaint)
158 EVT_SIZE(wxLEDNumberCtrl::OnSize)
159 END_EVENT_TABLE()
160
161
162 void wxLEDNumberCtrl::OnEraseBackground(wxEraseEvent &Event)
163 {
164 }
165
166
167 void wxLEDNumberCtrl::OnPaint(wxPaintEvent &Event)
168 {
169 wxPaintDC Dc(this);
170
171 int Width, Height;
172 GetClientSize(&Width, &Height);
173
174 wxBitmap *pMemoryBitmap = new wxBitmap(Width, Height);
175 wxMemoryDC MemDc;
176
177 MemDc.SelectObject(*pMemoryBitmap);
178 MemDc.BeginDrawing();
179
180 // Draw background.
181 MemDc.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID));
182 MemDc.DrawRectangle(wxRect(0, 0, Width, Height));
183 MemDc.SetBrush(wxNullBrush);
184
185 // Iterate each digit in the value, and draw.
186 const int DigitCount = m_Value.Len();
187 for (int i = 0; i < DigitCount; ++i)
188 {
189 // Draw faded lines if wanted.
190 if (m_DrawFaded)
191 DrawDigit(MemDc, DIGITALL, i);
192
193 // Draw the digits.
194 switch (m_Value[i])
195 {
196 case '0' :
197 DrawDigit(MemDc, DIGIT0, i);
198 break;
199 case '1' :
200 DrawDigit(MemDc, DIGIT1, i);
201 break;
202 case '2' :
203 DrawDigit(MemDc, DIGIT2, i);
204 break;
205 case '3' :
206 DrawDigit(MemDc, DIGIT3, i);
207 break;
208 case '4' :
209 DrawDigit(MemDc, DIGIT4, i);
210 break;
211 case '5' :
212 DrawDigit(MemDc, DIGIT5, i);
213 break;
214 case '6' :
215 DrawDigit(MemDc, DIGIT6, i);
216 break;
217 case '7' :
218 DrawDigit(MemDc, DIGIT7, i);
219 break;
220 case '8' :
221 DrawDigit(MemDc, DIGIT8, i);
222 break;
223 case '9' :
224 DrawDigit(MemDc, DIGIT9, i);
225 break;
226 case '-' :
227 DrawDigit(MemDc, DASH, i);
228 break;
229 case ' ' :
230 // just skip it
231 break;
232 default :
233 wxFAIL_MSG(_("Unknown digit value"));
234 break;
235 }
236 }
237
238 MemDc.EndDrawing();
239
240 // Blit the memory dc to screen.
241 Dc.Blit(0, 0, Width, Height, &MemDc, 0, 0, wxCOPY);
242 delete pMemoryBitmap;
243 }
244
245
246 void wxLEDNumberCtrl::DrawDigit(wxDC &Dc, int Digit, int Column)
247 {
248 wxColour LineColor(GetForegroundColour());
249
250 if (Digit == DIGITALL)
251 {
252 const int R = LineColor.Red() / 3;
253 const int G = LineColor.Green() / 3;
254 const int B = LineColor.Blue() / 3;
255
256 LineColor.Set(R, G, B);
257 }
258
259 int XPos = m_LeftStartPos;
260
261 if (Column > 0)
262 XPos += (Column * m_LineLength) + (m_DigitMargin) * Column;
263
264 // Create a pen and draw the lines.
265 wxPen Pen(LineColor, m_LineWidth, wxSOLID);
266 Dc.SetPen(Pen);
267
268 if ((Digit & LINE1))
269 {
270 Dc.DrawLine(XPos + m_LineMargin*2, m_LineMargin,
271 XPos + m_LineLength, m_LineMargin);
272 }
273
274 if (Digit & LINE2)
275 {
276 Dc.DrawLine(XPos + m_LineLength + m_LineMargin, m_LineMargin*2,
277 XPos + m_LineLength + m_LineMargin, m_LineLength + (m_LineMargin*2));
278 }
279
280 if (Digit & LINE3)
281 {
282 Dc.DrawLine(XPos + m_LineLength + m_LineMargin, m_LineLength + (m_LineMargin*4),
283 XPos + m_LineLength + m_LineMargin, m_LineLength*2 + (m_LineMargin*3));
284 }
285
286 if (Digit & LINE4)
287 {
288 Dc.DrawLine(XPos + m_LineMargin*2, m_LineLength*2 + (m_LineMargin*4),
289 XPos + m_LineLength, m_LineLength*2 + (m_LineMargin*4));
290 }
291
292 if (Digit & LINE5)
293 {
294 Dc.DrawLine(XPos + m_LineMargin, m_LineLength + (m_LineMargin*4),
295 XPos + m_LineMargin, m_LineLength*2 + (m_LineMargin*3));
296 }
297
298 if (Digit & LINE6)
299 {
300 Dc.DrawLine(XPos + m_LineMargin, m_LineMargin*2,
301 XPos + m_LineMargin, m_LineLength + (m_LineMargin*2));
302 }
303
304 if (Digit & LINE7)
305 {
306 Dc.DrawLine(XPos + m_LineMargin*2, m_LineLength + (m_LineMargin*3),
307 XPos + m_LineMargin + m_LineLength - m_LineMargin, m_LineLength + (m_LineMargin*3));
308 }
309
310 Dc.SetPen(wxNullPen);
311 }
312
313
314 void wxLEDNumberCtrl::RecalcInternals(const wxSize &CurrentSize)
315 {
316 const int Height = CurrentSize.GetHeight();
317
318 if ((Height * 0.07) < 1)
319 m_LineMargin = 1;
320 else
321 m_LineMargin = Height * 0.07;
322
323 if ((Height * 0.35) < 1)
324 m_LineLength = 1;
325 else
326 m_LineLength = Height * 0.35;
327
328 m_LineWidth = m_LineMargin;
329
330 m_DigitMargin = m_LineMargin * 4;
331
332 const int ValueWidth = (m_LineLength + m_DigitMargin) * m_Value.Len();
333 const int ClientWidth = CurrentSize.GetWidth();
334
335 switch (m_Alignment)
336 {
337 case wxLED_ALIGN_LEFT :
338 m_LeftStartPos = 0;
339 break;
340 case wxLED_ALIGN_RIGHT :
341 m_LeftStartPos = ClientWidth - ValueWidth;
342 break;
343 case wxLED_ALIGN_CENTER :
344 m_LeftStartPos = (ClientWidth - ValueWidth) / 2;
345 break;
346 default :
347 wxFAIL_MSG(_("Unknown alignent value for wxLEDNumberCtrl."));
348 break;
349 }
350 }
351
352
353 void wxLEDNumberCtrl::OnSize(wxSizeEvent &Event)
354 {
355 RecalcInternals(Event.GetSize());
356
357 Event.Skip();
358 }