1
/***************************************************************
3
* Purpose: Code for Class wxLEDPanel
4
* Author: Christian Gr�fe (info@mcs-soft.de)
6
* Copyright: Christian Gr�fe (www.mcs-soft.de)
7
* License: wxWindows licence
8
**************************************************************/
10
// For compilers that support precompilation, includes "wx.h".
11
#include "wx/wxprec.h"
21
#include <wx/dcbuffer.h>
22
#include "wx/wxledpanel.h"
24
#define TIMER_SCROLL_ID 1000
26
BEGIN_EVENT_TABLE(wxLEDPanel, wxControl)
27
EVT_PAINT(wxLEDPanel::OnPaint)
28
EVT_ERASE_BACKGROUND(wxLEDPanel::OnEraseBackground)
29
EVT_TIMER(TIMER_SCROLL_ID,wxLEDPanel::OnScrollTimer)
32
wxLEDPanel::wxLEDPanel() :
33
m_align(wxALIGN_LEFT|wxALIGN_TOP),
37
m_show_inactivs(true),
39
m_scrolldirection(wxALL),
44
wxLEDPanel::wxLEDPanel(wxWindow* parent, wxWindowID id, const wxSize& ledsize,
45
const wxSize& fieldsize, int padding, const wxPoint& pos,
46
long style, const wxValidator& validator) :
47
m_align(wxALIGN_LEFT|wxALIGN_TOP),
51
m_show_inactivs(true),
53
m_scrolldirection(wxALL),
56
Create(parent,id,ledsize,fieldsize,padding,pos,style,validator);
59
wxLEDPanel::~wxLEDPanel()
63
bool wxLEDPanel::Create(wxWindow* parent, wxWindowID id, const wxSize& ledsize,
64
const wxSize& fieldsize, int padding, const wxPoint& pos,
65
long style, const wxValidator& validator)
71
size.SetWidth((ledsize.GetWidth()+padding)*fieldsize.GetWidth()+padding);
72
size.SetHeight((ledsize.GetHeight()+padding)*fieldsize.GetHeight()+padding);
75
if(!wxControl::Create(parent,id,pos,size,style,validator))
78
// initialise MatrixObjekt
79
m_field.Init(0,fieldsize.GetWidth(),fieldsize.GetHeight());
81
// default backgroundcolor is black (call parent, to prevent the call of PrepareBackground)
82
wxWindow::SetBackgroundColour(*wxBLACK);
84
// default led-color is red
85
this->SetLEDColour(wxLED_COLOUR_RED);
91
m_scrollTimer.SetOwner(this,TIMER_SCROLL_ID);
96
wxSize wxLEDPanel::DoGetBestSize() const
99
size.SetWidth((m_ledsize.GetWidth()+m_padding)*m_field.GetWidth()+m_padding);
100
size.SetHeight((m_ledsize.GetHeight()+m_padding)*m_field.GetHeight()+m_padding);
104
void wxLEDPanel::Clear()
109
void wxLEDPanel::Reset()
114
/** @return the size of the field in points */
115
wxSize wxLEDPanel::GetFieldsize() const
117
return m_field.GetSize();
120
/** @return the size of one LED on the field */
121
wxSize wxLEDPanel::GetLEDSize() const
127
* Sets the colour of the LEDs
128
* @param colourID the ID of the new colour
130
void wxLEDPanel::SetLEDColour(wxLEDColour colourID)
136
// colourID speichern
137
m_activ_colour_id=colourID;
139
int w=m_ledsize.GetWidth()+m_padding;
140
int h=m_ledsize.GetHeight()+m_padding;
142
// create Bitmaps for "LED on" und "LED off"
143
wxBitmap led_on(w,h);
144
wxBitmap led_off(w,h);
145
wxBitmap led_none(w,h);
148
m_mdc_led_on.SelectObject(led_on);
151
m_mdc_led_on.SetBackground(this->GetBackgroundColour());
152
m_mdc_led_on.Clear();
155
pen.SetColour(s_colour_dark[colourID-1]);
156
brush.SetColour(s_colour[colourID-1]);
157
m_mdc_led_on.SetPen(pen);
158
m_mdc_led_on.SetBrush(brush);
159
m_mdc_led_on.DrawEllipse(wxPoint(0,0),m_ledsize);
161
// left top corner in lighter colour
162
pen.SetColour(s_colour_light[colourID-1]);
163
m_mdc_led_on.SetPen(pen);
164
m_mdc_led_on.DrawEllipticArc(0,0,m_ledsize.GetWidth(),m_ledsize.GetHeight(),75.0,195.0);
168
m_mdc_led_off.SelectObject(led_off);
171
m_mdc_led_off.SetBackground(this->GetBackgroundColour());
172
m_mdc_led_off.Clear();
175
pen.SetColour(s_colour_dark[colourID-1]);
176
brush.SetColour(s_colour_verydark[colourID-1]);
177
m_mdc_led_off.SetPen(pen);
178
m_mdc_led_off.SetBrush(brush);
179
m_mdc_led_off.DrawEllipse(wxPoint(0,0),m_ledsize);
183
m_mdc_led_none.SelectObject(led_none);
184
m_mdc_led_none.SetBackground(this->GetBackgroundColour());
185
m_mdc_led_none.Clear();
191
/** @return the real colour of a LED */
192
const wxColour& wxLEDPanel::GetLEDColour() const
194
return s_colour[m_activ_colour_id];
197
/** Overwritten to prepare the background with the new backgroundcolour
198
* @param colour the new backroundcolour
200
bool wxLEDPanel::SetBackgroundColour(const wxColour& colour)
202
if (wxWindow::SetBackgroundColour(colour))
211
/** Sets the speed for the scrolling
212
* @param speed the speed in ms (optimal range between 80-120)
214
void wxLEDPanel::SetScrollSpeed(int speed)
217
m_scrollTimer.Stop();
223
if(m_scrollspeed>0 && m_scrolldirection!=wxALL)
224
m_scrollTimer.Start(speed,true);
227
/** @return the speed of the scrolling */
228
int wxLEDPanel::GetScrollSpeed() const
230
return m_scrollspeed;
233
/** Sets the direction to scroll
234
* @param d the direction (wxALL for no scrolling)
236
void wxLEDPanel::SetScrollDirection(wxDirection d)
239
m_scrollTimer.Stop();
244
if(m_scrollspeed>0 && m_scrolldirection!=wxALL)
245
m_scrollTimer.Start(m_scrollspeed,true);
248
/** @return the current direction of the scrolling (wxALL for no scrolling)*/
249
wxDirection wxLEDPanel::GetScrollDirection() const
251
return m_scrolldirection;
254
/** Swaps the LED states
255
* @param invert if true, all active LEDs are drawn as inactiv and all inactiv drawn as activ
257
void wxLEDPanel::ShowInvertet(bool invert)
259
if(m_invert==invert) return;
265
/** Should the inactive LEDs be drawn */
266
void wxLEDPanel::ShowInactivLEDs(bool show_inactivs)
268
if(m_show_inactivs==show_inactivs) return;
270
m_show_inactivs=show_inactivs;
274
void wxLEDPanel::SetContentAlign(int a)
279
// Reset the Horizontal position
284
m_field.SetDatesAt(m_pos,m_content_mo);
287
int wxLEDPanel::GetContentAlign() const
292
void wxLEDPanel::SetText(const wxString& text, int align)
295
if(text.IsEmpty()) return;
297
// the MO for the Text
298
MatrixObject* tmp=NULL;
301
if(align!=-1) m_align=align;
307
// get the MO for the text
308
if(m_align&wxALIGN_CENTER_HORIZONTAL)
309
tmp=m_font.GetMOForText(text,wxALIGN_CENTER_HORIZONTAL);
310
else if(m_align&wxALIGN_RIGHT)
311
tmp=m_font.GetMOForText(text,wxALIGN_RIGHT);
312
else tmp=m_font.GetMOForText(text); // wxALIGN_LEFT
314
// save the MO, and delete the tmp
315
m_content_mo.Init(*tmp);
318
// Find the place for the text
323
m_field.SetDatesAt(m_pos,m_content_mo);
326
/** @return the current text */
327
wxString wxLEDPanel::GetText() const
332
void wxLEDPanel::SetImage(const wxImage img)
334
if(!img.IsOk()) return;
337
m_content_mo.Init(img);
340
// Find the place for the bitmap
345
m_field.SetDatesAt(m_pos,m_content_mo);
348
wxImage wxLEDPanel::GetContentAsImage() const
350
return m_content_mo.GetAsImage();
353
void wxLEDPanel::SetAnimation(const wxAnimation ani)
355
if(!ani.IsOk() || ani.GetFrameCount()==0) return;
361
m_content_mo.Init(ani.GetFrame(0));
363
// Find the place for the bitmap
368
m_field.SetDatesAt(m_pos,m_content_mo);
371
m_scrollTimer.Stop();
372
m_scrollspeed = m_ani.GetDelay(0);
373
m_scrollTimer.Start(m_scrollspeed,true);
376
const wxAnimation wxLEDPanel::GetAnimation() const
381
void wxLEDPanel::SetContentPaddingLeft(int padLeft)
386
// Reset the text position
391
m_field.SetDatesAt(m_pos,m_content_mo);
394
int wxLEDPanel::GetContentPaddingLeft() const
399
void wxLEDPanel::SetContentPaddingRight(int padRight)
404
// Reset the text position
409
m_field.SetDatesAt(m_pos,m_content_mo);
412
int wxLEDPanel::GetContentPaddingRight() const
417
/** Sets the space between two letters
418
* @param leterSpace the space in points (one point = one LED)
420
void wxLEDPanel::SetLetterSpace(int letterSpace)
422
// is already this size?
423
if(m_font.GetLetterSpace()==letterSpace) return;
425
m_font.SetLetterSpace(letterSpace);
429
/** @return the space between two letters in points */
430
int wxLEDPanel::GetLetterSpace() const
432
return m_font.GetLetterSpace();
435
void wxLEDPanel::SetFontType(wxLEDFontType t)
437
if(m_font.GetFontType()==t) return;
439
m_font.SetFontType(t);
443
wxLEDFontType wxLEDPanel::GetFontType() const
445
return m_font.GetFontType();
448
/** this draws the data on the Control */
449
void wxLEDPanel::DrawField(wxDC& dc, bool backgroundMode)
452
int w=m_ledsize.GetWidth()+m_padding;
453
int h=m_ledsize.GetHeight()+m_padding;
456
// Z�hler f�r Zeile und Spalte
459
// Pointer to avoid unnesecerie if blocks in the for block
460
wxMemoryDC* p_mdc_data=((m_invert)?((m_show_inactivs)?(&m_mdc_led_off):(&m_mdc_led_none)):(&m_mdc_led_on));
461
wxMemoryDC* p_mdc_nodata=((m_invert)?(&m_mdc_led_on):((m_show_inactivs)?(&m_mdc_led_off):(&m_mdc_led_none)));
463
int l = m_field.GetLength();
464
int fw = m_field.GetWidth();
465
const char* field = m_field.GetData();
472
point.x=x*w+m_padding;
473
point.y=y*h+m_padding;
476
if(field[i] && !backgroundMode)
478
dc.Blit(point.x,point.y,w,h,p_mdc_data,0,0);
480
else if(backgroundMode)
482
dc.Blit(point.x,point.y,w,h,p_mdc_nodata,0,0);
487
if(x==fw) {++y; x=0;}
491
/** Do nothing to avoid flicker */
492
void wxLEDPanel::OnEraseBackground(wxEraseEvent& event)
496
void wxLEDPanel::OnPaint(wxPaintEvent &event)
498
wxBufferedPaintDC dc(this);
499
//dc.SetBackground(this->GetBackgroundColour());
503
dc.Blit(0,0,m_mdc_background.GetSize().GetWidth(),m_mdc_background.GetSize().GetHeight(),&m_mdc_background,0,0);
508
void wxLEDPanel::ShiftLeft()
514
if(m_pos.x+m_content_mo.GetWidth()<=0)
516
m_pos.x=m_field.GetWidth();
523
// TODO check bounds!
524
// data for the new line
525
for(int i=0;i<m_content_mo.GetHeight();++i)
527
char d=m_content_mo.GetDataFrom(abs(m_pos.x-m_field.GetWidth()+1),i);
528
if(d>0) m_field.SetDataAt(m_field.GetWidth()-1,m_pos.y+i,d);
532
void wxLEDPanel::ShiftRight()
537
if(m_pos.x>=m_field.GetWidth())
539
m_pos.x=-m_content_mo.GetWidth(); // TODO without +1 error (in SetDatesAt??)
544
m_field.ShiftRight();
546
// TODO check bounds!
547
// TODO at first run -> false y-pos!
548
// data for the new line
549
for(int i=0;i<m_content_mo.GetHeight();++i)
551
char d=m_content_mo.GetDataFrom(abs(m_pos.x-m_field.GetWidth()+1),i);
552
if(d>0) m_field.SetDataAt(0,m_pos.y+i,d);
556
void wxLEDPanel::ShiftUp()
561
if(m_pos.y+m_content_mo.GetHeight()<=0)
562
m_pos.y=m_field.GetHeight();
564
// TODO optimize with shift
566
m_field.SetDatesAt(m_pos,m_content_mo);
569
void wxLEDPanel::ShiftDown()
574
if(m_pos.y>=m_field.GetHeight())
575
m_pos.y=-m_content_mo.GetHeight();
577
// TODO optimize with shift
579
m_field.SetDatesAt(m_pos,m_content_mo);
583
void wxLEDPanel::OnScrollTimer(wxTimerEvent& event)
585
if(m_scrollspeed==0||m_content_mo.IsEmpty()) return;
588
m_scrollTimer.Stop();
594
switch(m_scrolldirection)
597
case wxLEFT: this->ShiftLeft(); break;
598
case wxRIGHT: this->ShiftRight(); break;
599
case wxDOWN: this->ShiftDown(); break;
600
case wxUP: this->ShiftUp(); break;
607
if(m_aniFrameNr >= m_ani.GetFrameCount())
610
m_content_mo.Init(m_ani.GetFrame(m_aniFrameNr));
612
m_field.SetDatesAt(m_pos,m_content_mo);
613
m_scrollspeed = m_ani.GetDelay(m_aniFrameNr);
620
m_scrollTimer.Start(m_scrollspeed,true);
623
/** Resets the position of the content after scrolling */
624
void wxLEDPanel::ResetPos()
627
if(m_content_mo.GetData()==NULL) return;
629
// horizontal text pos
630
if(m_scrolldirection!=wxLEFT && m_scrolldirection!=wxRIGHT)
632
if(m_align & wxALIGN_RIGHT)
633
m_pos.x=m_field.GetWidth()-m_content_mo.GetWidth()-m_padRight;
634
else if(m_align & wxALIGN_CENTER_HORIZONTAL)
635
m_pos.x=(m_field.GetWidth()-m_content_mo.GetWidth())/2;
639
else if(m_scrolldirection==wxLEFT)
640
m_pos.x=m_field.GetWidth();
641
else if(m_scrolldirection==wxRIGHT)
642
m_pos.x=-m_content_mo.GetWidth();
645
if(m_scrolldirection!=wxUP && m_scrolldirection!=wxDOWN)
647
if(m_align & wxALIGN_BOTTOM)
648
m_pos.y=m_field.GetHeight()-m_content_mo.GetHeight();
649
else if(m_align & wxALIGN_CENTER_VERTICAL)
650
m_pos.y=(m_field.GetHeight()-m_content_mo.GetHeight())/2;
654
else if(m_scrolldirection==wxUP)
655
m_pos.y=m_field.GetHeight();
656
else if(m_scrolldirection==wxDOWN)
657
m_pos.y=-m_content_mo.GetHeight();
660
/** Prepares the backgroundimage, to optimze speed */
661
void wxLEDPanel::PrepareBackground()
663
wxSize s=DoGetBestSize();
664
wxBitmap bmpBG(s.GetWidth(),s.GetHeight());
666
m_mdc_background.SelectObject(bmpBG);
668
// clear the background
669
m_mdc_background.SetBackground(this->GetBackgroundColour());
670
m_mdc_background.Clear();
672
if(m_invert || m_show_inactivs)
673
DrawField(m_mdc_background, true);
676
// Red, Green, Blue, Yellow, Magenta, Cyan, Grey
677
const wxColour wxLEDPanel::s_colour[7]=
678
{ wxColour(255,0,0), wxColour(0,255,0), wxColour(0,0,255),
679
wxColour(255,255,0), wxColour(255,0,255), wxColour(0,255,255),
680
wxColour(128,128,128) };
682
const wxColour wxLEDPanel::s_colour_dark[7]=
683
{ wxColour(128,0,0), wxColour(0,128,0), wxColour(0,0,128),
684
wxColour(128,128,0), wxColour(128,0,128), wxColour(0,128,128),
685
wxColour(64,64,64) };
687
const wxColour wxLEDPanel::s_colour_verydark[7]=
688
{ wxColour(64,0,0), wxColour(0,64,0), wxColour(0,0,64),
689
wxColour(64,64,0), wxColour(64,0,64), wxColour(0,64,64),
690
wxColour(32,32,32) };
692
const wxColour wxLEDPanel::s_colour_light[7]=
693
{ wxColour(255,128,128), wxColour(128,255,128), wxColour(128,128,255),
694
wxColour(255,255,128), wxColour(255,128,255), wxColour(128,255,255),
695
wxColour(192,192,192) };