%% options copyright owner = Dirk Krause copyright year = 2013-xxxx license = bsd %% header class DkClockView : public DkWxBufferedControl { private: DECLARE_DYNAMIC_CLASS(DkClockView) /** Event table. */ DECLARE_EVENT_TABLE() protected: /** Black colour for normal mode. */ wxColour cBlack; /** Red colour for alert mode. */ wxColour cRed; /** Clock data to show. */ DkClockData *cld; /** Widget type name. */ static wxChar const windowtypename[]; /** Flag: Use red colour instead of black. */ bool bUseRed; public: /** Default constructor. */ DkClockView(); /** Constructor. @param wParent Parent window. @param wid Window ID. @param clockData Clock data to show. @param pos Window position. @param size Window size. @param style Window style. */ DkClockView( wxWindow *wParent, wxWindowID wid, DkClockData *clockData, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = 0L ); /** Create window after using the default constructor. @param wParent Parent window. @param wid Window ID. @param clockData Clock data to show. @param pos Window position. @param size Window size. @param style Window style. @return true on success, false on error. */ bool Create( wxWindow *wParent, wxWindowID wid, DkClockData *clockData, const wxPoint & pos = wxDefaultPosition, const wxSize & size = wxDefaultSize, long style = 0L ); /** Draw operation. @param pdc Device context to draw to. @param event Event to process. @param buffered Flag: Drawing into bitmap buffer. @param clWidth Client area width. @param clHeight Client area height. */ void PaintOperation( wxDC & pdc, wxPaintEvent & event, bool buffered, int clWidth, int clHeight ); /** Handler for mouse click. @param event Event to process. */ void OnLeftDown(wxMouseEvent & event); /** Get red component of normal clock colour. @return Red value. */ int getNormalRed(void) const; /** Get green component of normal clock colour. @return Green value. */ int getNormalGreen(void) const; /** Get blue component of normal clock colour. @return Blue value. */ int getNormalBlue(void) const; /** Get red component of alert clock colour. @return Red value. */ int getAlertRed(void) const; /** Get green component of alert clock colour. @return Green value. */ int getAlertGreen(void) const; /** Get blue component of alert clock colour. @return Blue value. */ int getAlertBlue(void) const; /** Set normal colour. @param r Red value. @param g Green value. @param b Blue value. */ void setNormal(int r, int g, int b); /** Set alert colour. @param r Red value. @param g Green value. @param b Blue value. */ void setAlert(int r, int g, int b); }; %% module #include "wxdkclock.h" $!trace-include IMPLEMENT_DYNAMIC_CLASS(DkClockView, DkWxBufferedControl) /** Event handler table. */ BEGIN_EVENT_TABLE(DkClockView, DkWxBufferedControl) EVT_LEFT_DOWN(DkClockView::OnLeftDown) END_EVENT_TABLE() wxChar const DkClockView::windowtypename[] = { wxT("DkClockView") }; DkClockView::DkClockView() : cBlack(0, 0, 0), #if defined(__WXMSW__) cRed(127, 0, 0) #else cRed(191, 0, 0) #endif { bUseRed = false; cld = NULL; } DkClockView::DkClockView( wxWindow *wParent, wxWindowID wid, DkClockData *clockData, const wxPoint & pos, const wxSize & size, long style ) : DkWxBufferedControl( wParent, wid, pos, size, (style | wxFULL_REPAINT_ON_RESIZE), wxDefaultValidator, wxString(windowtypename) ), cBlack(0, 0, 0), #if defined(__WXMSW__) cRed(127, 0, 0) #else cRed(191, 0, 0) #endif { $? "+ DkClockView::DkClockView" bUseRed = false; cld = clockData; $? "- DkClockView::DkClockView" } bool DkClockView::Create( wxWindow *wParent, wxWindowID wid, DkClockData *clockData, const wxPoint & pos, const wxSize & size, long style ) { bool back; back = DkWxBufferedControl::Create( wParent, wid, pos, size, (style | wxFULL_REPAINT_ON_RESIZE), wxDefaultValidator, wxString(windowtypename) ); bUseRed = false; cld = clockData; return back; } void DkClockView::PaintOperation( wxDC & pdc, wxPaintEvent & event, bool buffered, int clWidth, int clHeight ) { clockview_data_t clvdata; /* Clock data. */ double alpha; /* Current angle in radians. */ int cx; /* Center x. */ int cy; /* Center y. */ int ro; /* Outer radius. */ int rd; /* Radius 5-minutes dot. */ int rc; /* Center points radius. */ int ri; /* Inner radius. */ int lw; /* Line width of minute dots. */ int r1; /* Inner radius minute dots. */ int r2; /* Outer radius minute dots. */ int rs; /* Radius seconds arrow. */ int rm; /* Radius minuts arrow. */ int rh; /* Radius hours arrow. */ int aw; /* Width minutes and hours. */ int i; /* Current index. */ int x; /* Current x. */ int y; /* Current y. */ $? "+ DkClockView::PaintOperation" pdc.SetBackground(*wxWHITE_BRUSH); pdc.Clear(); cld->getData(&clvdata); if(clvdata.a) { bUseRed = ((bUseRed) ? false : true); } else { bUseRed = false; } cx = clWidth / 2; cy = clHeight / 2; ro = cx; if(cy < ro) { ro = cy; } ro = (int)(0.95 * (double)ro); rd = (int)(0.0497331 * (double)ro); if(rd < 1) { rd = 1; } rc = ro - rd; if(rc < 0) { rc = 0; } ri = ro - (2 * rd); if(ri < 0) { ri = 0; } lw = rd / 2; if(lw < 1) { lw = 1; } r1 = ri + (lw / 2); r2 = ro - (lw / 2); rs = ri - rd - (lw / 2); if(rs < 1) { rs = 1; } aw = rd; rm = ri - (2 * rd) - (aw / 2); if(rm < 1) { rm = 1; } rh = (int)(0.75 * (double)rm); if(rm < 1) { rh = 1; } /* 5-minute dots. */ pdc.SetPen(*wxTRANSPARENT_PEN); if(bUseRed) { pdc.SetBrush(cRed); } else { pdc.SetBrush(cBlack); } for(i = 0; i < 12; i++) { alpha = (2.0 * M_PI * (double)i) / 12.0; x = cx + (int)((double)rc * cos(alpha)); y = cy + (int)((double)rc * sin(alpha)); pdc.DrawCircle(x, y, rd); } /* Other minute ticks. */ pdc.SetBrush(wxNullBrush); if(bUseRed) { pdc.SetPen(wxPen(cRed, lw)); } else{ pdc.SetPen(wxPen(cBlack, lw)); } for(i = 0; i < 60; i++) { if(i % 5) { alpha = (2.0 * M_PI * (double)i) / 60.0; pdc.DrawLine( (cx + (int)((double)r1 * cos(alpha))), (cy + (int)((double)r1 * sin(alpha))), (cx + (int)((double)r2 * cos(alpha))), (cy + (int)((double)r2 * sin(alpha))) ); } } /* Hours arrow. */ pdc.SetBrush(wxNullBrush); if(bUseRed) { pdc.SetPen(wxPen(cRed, aw)); } else{ pdc.SetPen(wxPen(cBlack, aw)); } alpha = M_PI_2 - ((4.0 * M_PI * (double)(clvdata.h)) / 24.0); alpha = alpha - ((M_PI * (double)(clvdata.m)) / 360.0); pdc.DrawLine( cx, cy, (cx + (int)((double)rh * cos(alpha))), (cy - (int)((double)rh * sin(alpha))) ); /* Minutes arrow. */ alpha = M_PI_2 - ((2.0 * M_PI * (double)(clvdata.m)) / 60.0); pdc.DrawLine( cx, cy, (cx + (int)((double)rm * cos(alpha))), (cy - (int)((double)rm * sin(alpha))) ); /* Seconds arrow. */ pdc.SetBrush(wxNullBrush); if(bUseRed) { pdc.SetPen(wxPen(cRed, lw)); } else{ pdc.SetPen(wxPen(cBlack, lw)); } alpha = M_PI_2 - ((2.0 * M_PI * (int)(clvdata.s)) / 60.0); pdc.DrawLine( cx, cy, (cx + (int)((double)rs * cos(alpha))), (cy - (int)((double)rs * sin(alpha))) ); /* Before leaving the function choose stock objects. */ pdc.SetBrush(wxNullBrush); pdc.SetBackground(wxNullBrush); pdc.SetPen(wxNullPen); $? "- DkClockView::PaintOperation" } void DkClockView::OnLeftDown(wxMouseEvent & event) { $? "+ DkClockView::OnLeftDown" if(cld) { cld->endAlert(); SetMustUpdate(); Refresh(); Update(); } $? "- DkClockView::OnLeftDown" } int DkClockView::getNormalRed(void) const { int back; back = cBlack.Red(); if(back < 0) { back = back + 256; } return back; } int DkClockView::getNormalGreen(void) const { int back; back = cBlack.Green(); if(back < 0) { back = back + 256; } return back; } int DkClockView::getNormalBlue(void) const { int back; back = cBlack.Blue(); if(back < 0) { back = back + 256; } return back; } int DkClockView::getAlertRed(void) const { int back; back = cRed.Red(); if(back < 0) { back = back + 256; } return back; } int DkClockView::getAlertGreen(void) const { int back; back = cRed.Green(); if(back < 0) { back = back + 256; } return back; } int DkClockView::getAlertBlue(void) const { int back; back = cRed.Blue(); if(back < 0) { back = back + 256; } return back; } void DkClockView::setNormal(int r, int g, int b) { cBlack.Set((unsigned char)r, (unsigned char)g, (unsigned char)b); } void DkClockView::setAlert(int r, int g, int b) { cRed.Set((unsigned char)r, (unsigned char)g, (unsigned char)b); }