1 // ============================================================================
3 // ============================================================================
12 #include "wx/dcclient.h"
13 #include "wx/dcmemory.h"
17 #include "wx/gizmos/ledctrl.h"
19 // ----------------------------------------------------------------------------
21 // ----------------------------------------------------------------------------
23 // A LED digit is build up like this, with maximum 7 Lines :
31 // Each number contains combinations of the lines, and they are set up below.
40 const int DECIMALSIGN
= 128;
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
;
54 const int DIGITALL
= -1;
56 // ============================================================================
57 // wxLEDNumberCtrl class implementation
58 // ============================================================================
60 wxLEDNumberCtrl::wxLEDNumberCtrl()
61 : m_Alignment(wxLED_ALIGN_LEFT
),
72 wxLEDNumberCtrl::wxLEDNumberCtrl(wxWindow
*parent
, wxWindowID id
,
73 const wxPoint
& pos
, const wxSize
& size
,
75 : m_Alignment(wxLED_ALIGN_LEFT
),
83 Create(parent
, id
, pos
, size
, style
);
87 bool wxLEDNumberCtrl::Create(wxWindow
*parent
, wxWindowID id
,
88 const wxPoint
& pos
, const wxSize
& size
,
91 bool RetVal
= wxControl::Create(parent
, id
, pos
, size
, style
);
93 if ((style
& wxLED_DRAW_FADED
) != 0)
95 if ((style
& wxLED_ALIGN_MASK
) != 0)
96 SetAlignment((wxLEDValueAlign
)(style
& wxLED_ALIGN_MASK
));
98 SetBackgroundColour(*wxBLACK
);
99 SetForegroundColour(*wxGREEN
);
105 void wxLEDNumberCtrl::SetAlignment(wxLEDValueAlign Alignment
, bool Redraw
)
107 if (Alignment
!= m_Alignment
)
109 m_Alignment
= Alignment
;
110 RecalcInternals(GetClientSize());
118 void wxLEDNumberCtrl::SetDrawFaded(bool DrawFaded
, bool Redraw
)
120 if (DrawFaded
!= m_DrawFaded
)
122 m_DrawFaded
= DrawFaded
;
130 void wxLEDNumberCtrl::SetValue(wxString
const &Value
, bool Redraw
)
132 if (Value
!= m_Value
)
137 for(size_t i
=0; i
<Value
.Length(); i
++) {
138 wxChar ch
= Value
[i
];
139 wxASSERT_MSG((ch
>='0' && ch
<='9') || ch
=='-' || ch
==' ' || ch
=='.',
140 wxT("wxLEDNumberCtrl can only display numeric string values."));
146 RecalcInternals(GetClientSize());
154 BEGIN_EVENT_TABLE(wxLEDNumberCtrl
, wxControl
)
155 EVT_ERASE_BACKGROUND(wxLEDNumberCtrl::OnEraseBackground
)
156 EVT_PAINT(wxLEDNumberCtrl::OnPaint
)
157 EVT_SIZE(wxLEDNumberCtrl::OnSize
)
161 void wxLEDNumberCtrl::OnEraseBackground(wxEraseEvent
&WXUNUSED(event
))
166 void wxLEDNumberCtrl::OnPaint(wxPaintEvent
&WXUNUSED(event
))
171 GetClientSize(&Width
, &Height
);
173 wxBitmap
*pMemoryBitmap
= new wxBitmap(Width
, Height
);
176 MemDc
.SelectObject(*pMemoryBitmap
);
177 MemDc
.BeginDrawing();
180 MemDc
.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID
));
181 MemDc
.DrawRectangle(wxRect(0, 0, Width
, Height
));
182 MemDc
.SetBrush(wxNullBrush
);
184 // Iterate each digit in the value, and draw.
185 const int DigitCount
= m_Value
.Len();
186 for (int offset
=0, i
= 0; offset
< DigitCount
; ++offset
, ++i
)
188 wxChar c
= m_Value
.GetChar(offset
);
190 // Draw faded lines if wanted.
191 if (m_DrawFaded
&& (c
!= _T('.')))
192 DrawDigit(MemDc
, DIGITALL
, i
);
198 DrawDigit(MemDc
, DIGIT0
, i
);
201 DrawDigit(MemDc
, DIGIT1
, i
);
204 DrawDigit(MemDc
, DIGIT2
, i
);
207 DrawDigit(MemDc
, DIGIT3
, i
);
210 DrawDigit(MemDc
, DIGIT4
, i
);
213 DrawDigit(MemDc
, DIGIT5
, i
);
216 DrawDigit(MemDc
, DIGIT6
, i
);
219 DrawDigit(MemDc
, DIGIT7
, i
);
222 DrawDigit(MemDc
, DIGIT8
, i
);
225 DrawDigit(MemDc
, DIGIT9
, i
);
228 DrawDigit(MemDc
, DASH
, i
);
231 // Display the decimal in the previous segment
233 DrawDigit(MemDc
, DECIMALSIGN
, i
);
239 wxFAIL_MSG(wxT("Unknown digit value"));
246 // Blit the memory dc to screen.
247 Dc
.Blit(0, 0, Width
, Height
, &MemDc
, 0, 0, wxCOPY
);
248 delete pMemoryBitmap
;
252 void wxLEDNumberCtrl::DrawDigit(wxDC
&Dc
, int Digit
, int Column
)
254 wxColour
LineColor(GetForegroundColour());
256 if (Digit
== DIGITALL
)
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);
262 LineColor
.Set(R
, G
, B
);
265 int XPos
= m_LeftStartPos
+ Column
* (m_LineLength
+ m_DigitMargin
);
267 // Create a pen and draw the lines.
268 wxPen
Pen(LineColor
, m_LineWidth
, wxSOLID
);
273 Dc
.DrawLine(XPos
+ m_LineMargin
*2, m_LineMargin
,
274 XPos
+ m_LineLength
+ m_LineMargin
*2, m_LineMargin
);
279 Dc
.DrawLine(XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineMargin
*2,
280 XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineLength
+ (m_LineMargin
*2));
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));
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));
297 Dc
.DrawLine(XPos
+ m_LineMargin
, m_LineLength
+ (m_LineMargin
*4),
298 XPos
+ m_LineMargin
, m_LineLength
*2 + (m_LineMargin
*4));
303 Dc
.DrawLine(XPos
+ m_LineMargin
, m_LineMargin
*2,
304 XPos
+ m_LineMargin
, m_LineLength
+ (m_LineMargin
*2));
309 Dc
.DrawLine(XPos
+ m_LineMargin
*2, m_LineLength
+ (m_LineMargin
*3),
310 XPos
+ m_LineMargin
*2 + m_LineLength
, m_LineLength
+ (m_LineMargin
*3));
313 if (Digit
& DECIMALSIGN
)
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));
319 Dc
.SetPen(wxNullPen
);
323 void wxLEDNumberCtrl::RecalcInternals(const wxSize
&CurrentSize
)
325 // Dimensions of LED segments
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
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
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
347 const int Height
= CurrentSize
.GetHeight();
349 if ((Height
* 0.075) < 1)
352 m_LineMargin
= (int)(Height
* 0.075);
354 if ((Height
* 0.275) < 1)
357 m_LineLength
= (int)(Height
* 0.275);
359 m_LineWidth
= m_LineMargin
;
361 m_DigitMargin
= m_LineMargin
* 4;
363 // Count the number of characters in the string; '.' characters are not
364 // included because they do not take up space in the display
366 for (unsigned int i
= 0; i
< m_Value
.Len(); i
++)
367 if (m_Value
.GetChar(i
) != '.')
369 const int ValueWidth
= (m_LineLength
+ m_DigitMargin
) * count
;
370 const int ClientWidth
= CurrentSize
.GetWidth();
374 case wxLED_ALIGN_LEFT
:
375 m_LeftStartPos
= m_LineMargin
;
377 case wxLED_ALIGN_RIGHT
:
378 m_LeftStartPos
= ClientWidth
- ValueWidth
- m_LineMargin
;
380 case wxLED_ALIGN_CENTER
:
381 m_LeftStartPos
= (ClientWidth
- ValueWidth
) / 2;
384 wxFAIL_MSG(wxT("Unknown alignent value for wxLEDNumberCtrl."));
390 void wxLEDNumberCtrl::OnSize(wxSizeEvent
&Event
)
392 RecalcInternals(Event
.GetSize());