1 // ============================================================================
3 // ============================================================================
6 #pragma implementation "wxLEDNumberCtrl.h"
16 #include "wx/dcclient.h"
17 #include "wx/dcmemory.h"
21 #include "wx/gizmos/ledctrl.h"
23 // ----------------------------------------------------------------------------
25 // ----------------------------------------------------------------------------
27 // A LED digit is build up like this, with maximum 7 Lines :
35 // Each number contains combinations of the lines, and they are set up below.
44 const int DECIMALSIGN
= 128;
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
;
58 const int DIGITALL
= -1;
60 // ============================================================================
61 // wxLEDNumberCtrl class implementation
62 // ============================================================================
64 wxLEDNumberCtrl::wxLEDNumberCtrl()
65 : m_Alignment(wxLED_ALIGN_LEFT
),
76 wxLEDNumberCtrl::wxLEDNumberCtrl(wxWindow
*parent
, wxWindowID id
,
77 const wxPoint
& pos
, const wxSize
& size
,
79 : m_Alignment(wxLED_ALIGN_LEFT
),
87 Create(parent
, id
, pos
, size
, style
);
91 bool wxLEDNumberCtrl::Create(wxWindow
*parent
, wxWindowID id
,
92 const wxPoint
& pos
, const wxSize
& size
,
95 bool RetVal
= wxControl::Create(parent
, id
, pos
, size
, style
);
97 if ((style
& wxLED_DRAW_FADED
) != 0)
99 if ((style
& wxLED_ALIGN_MASK
) != 0)
100 SetAlignment((wxLEDValueAlign
)(style
& wxLED_ALIGN_MASK
));
102 SetBackgroundColour(*wxBLACK
);
103 SetForegroundColour(*wxGREEN
);
109 void wxLEDNumberCtrl::SetAlignment(wxLEDValueAlign Alignment
, bool Redraw
)
111 if (Alignment
!= m_Alignment
)
113 m_Alignment
= Alignment
;
114 RecalcInternals(GetClientSize());
122 void wxLEDNumberCtrl::SetDrawFaded(bool DrawFaded
, bool Redraw
)
124 if (DrawFaded
!= m_DrawFaded
)
126 m_DrawFaded
= DrawFaded
;
134 void wxLEDNumberCtrl::SetValue(wxString
const &Value
, bool Redraw
)
136 if (Value
!= m_Value
)
141 for(size_t i
=0; i
<Value
.Length(); i
++) {
142 wxChar ch
= Value
[i
];
143 wxASSERT_MSG((ch
>='0' && ch
<='9') || ch
=='-' || ch
==' ' || ch
=='.',
144 wxT("wxLEDNumberCtrl can only display numeric string values."));
150 RecalcInternals(GetClientSize());
158 BEGIN_EVENT_TABLE(wxLEDNumberCtrl
, wxControl
)
159 EVT_ERASE_BACKGROUND(wxLEDNumberCtrl::OnEraseBackground
)
160 EVT_PAINT(wxLEDNumberCtrl::OnPaint
)
161 EVT_SIZE(wxLEDNumberCtrl::OnSize
)
165 void wxLEDNumberCtrl::OnEraseBackground(wxEraseEvent
&WXUNUSED(event
))
170 void wxLEDNumberCtrl::OnPaint(wxPaintEvent
&WXUNUSED(event
))
175 GetClientSize(&Width
, &Height
);
177 wxBitmap
*pMemoryBitmap
= new wxBitmap(Width
, Height
);
180 MemDc
.SelectObject(*pMemoryBitmap
);
181 MemDc
.BeginDrawing();
184 MemDc
.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID
));
185 MemDc
.DrawRectangle(wxRect(0, 0, Width
, Height
));
186 MemDc
.SetBrush(wxNullBrush
);
188 // Iterate each digit in the value, and draw.
189 const int DigitCount
= m_Value
.Len();
190 for (int offset
=0, i
= 0; offset
< DigitCount
; ++offset
, ++i
)
192 char c
= m_Value
.GetChar(offset
);
194 // Draw faded lines if wanted.
195 if (m_DrawFaded
&& (c
!= '.'))
196 DrawDigit(MemDc
, DIGITALL
, i
);
202 DrawDigit(MemDc
, DIGIT0
, i
);
205 DrawDigit(MemDc
, DIGIT1
, i
);
208 DrawDigit(MemDc
, DIGIT2
, i
);
211 DrawDigit(MemDc
, DIGIT3
, i
);
214 DrawDigit(MemDc
, DIGIT4
, i
);
217 DrawDigit(MemDc
, DIGIT5
, i
);
220 DrawDigit(MemDc
, DIGIT6
, i
);
223 DrawDigit(MemDc
, DIGIT7
, i
);
226 DrawDigit(MemDc
, DIGIT8
, i
);
229 DrawDigit(MemDc
, DIGIT9
, i
);
232 DrawDigit(MemDc
, DASH
, i
);
235 // Display the decimal in the previous segment
237 DrawDigit(MemDc
, DECIMALSIGN
, i
);
243 wxFAIL_MSG(wxT("Unknown digit value"));
250 // Blit the memory dc to screen.
251 Dc
.Blit(0, 0, Width
, Height
, &MemDc
, 0, 0, wxCOPY
);
252 delete pMemoryBitmap
;
256 void wxLEDNumberCtrl::DrawDigit(wxDC
&Dc
, int Digit
, int Column
)
258 wxColour
LineColor(GetForegroundColour());
260 if (Digit
== DIGITALL
)
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);
266 LineColor
.Set(R
, G
, B
);
269 int XPos
= m_LeftStartPos
+ Column
* (m_LineLength
+ m_DigitMargin
);
271 // Create a pen and draw the lines.
272 wxPen
Pen(LineColor
, m_LineWidth
, wxSOLID
);
277 Dc
.DrawLine(XPos
+ m_LineMargin
*2, m_LineMargin
,
278 XPos
+ m_LineLength
+ m_LineMargin
*2, m_LineMargin
);
283 Dc
.DrawLine(XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineMargin
*2,
284 XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineLength
+ (m_LineMargin
*2));
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));
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));
301 Dc
.DrawLine(XPos
+ m_LineMargin
, m_LineLength
+ (m_LineMargin
*4),
302 XPos
+ m_LineMargin
, m_LineLength
*2 + (m_LineMargin
*4));
307 Dc
.DrawLine(XPos
+ m_LineMargin
, m_LineMargin
*2,
308 XPos
+ m_LineMargin
, m_LineLength
+ (m_LineMargin
*2));
313 Dc
.DrawLine(XPos
+ m_LineMargin
*2, m_LineLength
+ (m_LineMargin
*3),
314 XPos
+ m_LineMargin
*2 + m_LineLength
, m_LineLength
+ (m_LineMargin
*3));
317 if (Digit
& DECIMALSIGN
)
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));
323 Dc
.SetPen(wxNullPen
);
327 void wxLEDNumberCtrl::RecalcInternals(const wxSize
&CurrentSize
)
329 // Dimensions of LED segments
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
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
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
351 const int Height
= CurrentSize
.GetHeight();
353 if ((Height
* 0.075) < 1)
356 m_LineMargin
= (int)(Height
* 0.075);
358 if ((Height
* 0.275) < 1)
361 m_LineLength
= (int)(Height
* 0.275);
363 m_LineWidth
= m_LineMargin
;
365 m_DigitMargin
= m_LineMargin
* 4;
367 // Count the number of characters in the string; '.' characters are not
368 // included because they do not take up space in the display
370 for (unsigned int i
= 0; i
< m_Value
.Len(); i
++)
371 if (m_Value
.GetChar(i
) != '.')
373 const int ValueWidth
= (m_LineLength
+ m_DigitMargin
) * count
;
374 const int ClientWidth
= CurrentSize
.GetWidth();
378 case wxLED_ALIGN_LEFT
:
379 m_LeftStartPos
= m_LineMargin
;
381 case wxLED_ALIGN_RIGHT
:
382 m_LeftStartPos
= ClientWidth
- ValueWidth
- m_LineMargin
;
384 case wxLED_ALIGN_CENTER
:
385 m_LeftStartPos
= (ClientWidth
- ValueWidth
) / 2;
388 wxFAIL_MSG(wxT("Unknown alignent value for wxLEDNumberCtrl."));
394 void wxLEDNumberCtrl::OnSize(wxSizeEvent
&Event
)
396 RecalcInternals(Event
.GetSize());