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
);
179 MemDc
.SetBrush(wxBrush(GetBackgroundColour(), wxSOLID
));
180 MemDc
.DrawRectangle(wxRect(0, 0, Width
, Height
));
181 MemDc
.SetBrush(wxNullBrush
);
183 // Iterate each digit in the value, and draw.
184 const int DigitCount
= m_Value
.Len();
185 for (int offset
=0, i
= 0; offset
< DigitCount
; ++offset
, ++i
)
187 wxChar c
= m_Value
.GetChar(offset
);
189 // Draw faded lines if wanted.
190 if (m_DrawFaded
&& (c
!= _T('.')))
191 DrawDigit(MemDc
, DIGITALL
, i
);
197 DrawDigit(MemDc
, DIGIT0
, i
);
200 DrawDigit(MemDc
, DIGIT1
, i
);
203 DrawDigit(MemDc
, DIGIT2
, i
);
206 DrawDigit(MemDc
, DIGIT3
, i
);
209 DrawDigit(MemDc
, DIGIT4
, i
);
212 DrawDigit(MemDc
, DIGIT5
, i
);
215 DrawDigit(MemDc
, DIGIT6
, i
);
218 DrawDigit(MemDc
, DIGIT7
, i
);
221 DrawDigit(MemDc
, DIGIT8
, i
);
224 DrawDigit(MemDc
, DIGIT9
, i
);
227 DrawDigit(MemDc
, DASH
, i
);
230 // Display the decimal in the previous segment
232 DrawDigit(MemDc
, DECIMALSIGN
, i
);
238 wxFAIL_MSG(wxT("Unknown digit value"));
243 // Blit the memory dc to screen.
244 Dc
.Blit(0, 0, Width
, Height
, &MemDc
, 0, 0, wxCOPY
);
245 delete pMemoryBitmap
;
249 void wxLEDNumberCtrl::DrawDigit(wxDC
&Dc
, int Digit
, int Column
)
251 wxColour
LineColor(GetForegroundColour());
253 if (Digit
== DIGITALL
)
255 const unsigned char R
= (unsigned char)(LineColor
.Red() / 16);
256 const unsigned char G
= (unsigned char)(LineColor
.Green() / 16);
257 const unsigned char B
= (unsigned char)(LineColor
.Blue() / 16);
259 LineColor
.Set(R
, G
, B
);
262 int XPos
= m_LeftStartPos
+ Column
* (m_LineLength
+ m_DigitMargin
);
264 // Create a pen and draw the lines.
265 wxPen
Pen(LineColor
, m_LineWidth
, wxSOLID
);
270 Dc
.DrawLine(XPos
+ m_LineMargin
*2, m_LineMargin
,
271 XPos
+ m_LineLength
+ m_LineMargin
*2, m_LineMargin
);
276 Dc
.DrawLine(XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineMargin
*2,
277 XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineLength
+ (m_LineMargin
*2));
282 Dc
.DrawLine(XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineLength
+ (m_LineMargin
*4),
283 XPos
+ m_LineLength
+ m_LineMargin
*3, m_LineLength
*2 + (m_LineMargin
*4));
288 Dc
.DrawLine(XPos
+ m_LineMargin
*2, m_LineLength
*2 + (m_LineMargin
*5),
289 XPos
+ m_LineLength
+ m_LineMargin
*2, m_LineLength
*2 + (m_LineMargin
*5));
294 Dc
.DrawLine(XPos
+ m_LineMargin
, m_LineLength
+ (m_LineMargin
*4),
295 XPos
+ m_LineMargin
, m_LineLength
*2 + (m_LineMargin
*4));
300 Dc
.DrawLine(XPos
+ m_LineMargin
, m_LineMargin
*2,
301 XPos
+ m_LineMargin
, m_LineLength
+ (m_LineMargin
*2));
306 Dc
.DrawLine(XPos
+ m_LineMargin
*2, m_LineLength
+ (m_LineMargin
*3),
307 XPos
+ m_LineMargin
*2 + m_LineLength
, m_LineLength
+ (m_LineMargin
*3));
310 if (Digit
& DECIMALSIGN
)
312 Dc
.DrawLine(XPos
+ m_LineLength
+ m_LineMargin
*4, m_LineLength
*2 + (m_LineMargin
*5),
313 XPos
+ m_LineLength
+ m_LineMargin
*4, m_LineLength
*2 + (m_LineMargin
*5));
316 Dc
.SetPen(wxNullPen
);
320 void wxLEDNumberCtrl::RecalcInternals(const wxSize
&CurrentSize
)
322 // Dimensions of LED segments
324 // Size of character is based on the HEIGH of the widget, NOT the width.
325 // Segment height is calculated as follows:
326 // Each segment is m_LineLength pixels long.
327 // There is m_LineMargin pixels at the top and bottom of each line segment
328 // There is m_LineMargin pixels at the top and bottom of each digit
330 // Therefore, the heigth of each character is:
331 // m_LineMargin : Top digit boarder
332 // m_LineMargin+m_LineLength+m_LineMargin : Top half of segment
333 // m_LineMargin+m_LineLength+m_LineMargin : Bottom half of segment
334 // m_LineMargin : Bottom digit boarder
335 // ----------------------
336 // m_LineMargin*6 + m_LineLength*2 == Total height of digit.
337 // Therefore, (m_LineMargin*6 + m_LineLength*2) must equal Height
339 // Spacing between characters can then be calculated as follows:
340 // m_LineMargin : before the digit,
341 // m_LineMargin+m_LineLength+m_LineMargin : for the digit width
342 // m_LineMargin : after the digit
343 // = m_LineMargin*4 + m_LineLength
344 const int Height
= CurrentSize
.GetHeight();
346 if ((Height
* 0.075) < 1)
349 m_LineMargin
= (int)(Height
* 0.075);
351 if ((Height
* 0.275) < 1)
354 m_LineLength
= (int)(Height
* 0.275);
356 m_LineWidth
= m_LineMargin
;
358 m_DigitMargin
= m_LineMargin
* 4;
360 // Count the number of characters in the string; '.' characters are not
361 // included because they do not take up space in the display
363 for (unsigned int i
= 0; i
< m_Value
.Len(); i
++)
364 if (m_Value
.GetChar(i
) != '.')
366 const int ValueWidth
= (m_LineLength
+ m_DigitMargin
) * count
;
367 const int ClientWidth
= CurrentSize
.GetWidth();
371 case wxLED_ALIGN_LEFT
:
372 m_LeftStartPos
= m_LineMargin
;
374 case wxLED_ALIGN_RIGHT
:
375 m_LeftStartPos
= ClientWidth
- ValueWidth
- m_LineMargin
;
377 case wxLED_ALIGN_CENTER
:
378 m_LeftStartPos
= (ClientWidth
- ValueWidth
) / 2;
381 wxFAIL_MSG(wxT("Unknown alignent value for wxLEDNumberCtrl."));
387 void wxLEDNumberCtrl::OnSize(wxSizeEvent
&Event
)
389 RecalcInternals(Event
.GetSize());