1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/calctrl.cpp 
   3 // Purpose:     implementation fo the generic wxCalendarCtrl 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows license 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "calctrl.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  32     #include "wx/dcclient.h" 
  33     #include "wx/settings.h" 
  35     #include "wx/combobox.h" 
  36     #include "wx/stattext.h" 
  39 #include "wx/calctrl.h" 
  43 // ---------------------------------------------------------------------------- 
  45 // ---------------------------------------------------------------------------- 
  47 class wxMonthComboBox 
: public wxComboBox
 
  50     wxMonthComboBox(wxCalendarCtrl 
*cal
); 
  52     void OnMonthChange(wxCommandEvent
& event
) { m_cal
->OnMonthChange(event
); } 
  55     wxCalendarCtrl 
*m_cal
; 
  60 class wxYearSpinCtrl 
: public wxSpinCtrl
 
  63     wxYearSpinCtrl(wxCalendarCtrl 
*cal
); 
  65     void OnYearChange(wxSpinEvent
& event
) { m_cal
->OnYearChange(event
); } 
  68     wxCalendarCtrl 
*m_cal
; 
  73 // ---------------------------------------------------------------------------- 
  75 // ---------------------------------------------------------------------------- 
  77 BEGIN_EVENT_TABLE(wxCalendarCtrl
, wxControl
) 
  78     EVT_PAINT(wxCalendarCtrl::OnPaint
) 
  80     EVT_CHAR(wxCalendarCtrl::OnChar
) 
  82     EVT_LEFT_DOWN(wxCalendarCtrl::OnClick
) 
  83     EVT_LEFT_DCLICK(wxCalendarCtrl::OnDClick
) 
  86 BEGIN_EVENT_TABLE(wxMonthComboBox
, wxComboBox
) 
  87     EVT_COMBOBOX(-1, wxMonthComboBox::OnMonthChange
) 
  90 BEGIN_EVENT_TABLE(wxYearSpinCtrl
, wxSpinCtrl
) 
  91     EVT_SPINCTRL(-1, wxYearSpinCtrl::OnYearChange
) 
  94 IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl
, wxControl
) 
  96 // ============================================================================ 
  98 // ============================================================================ 
 100 // ---------------------------------------------------------------------------- 
 101 // wxMonthComboBox and wxYearSpinCtrl 
 102 // ---------------------------------------------------------------------------- 
 104 wxMonthComboBox::wxMonthComboBox(wxCalendarCtrl 
*cal
) 
 105                : wxComboBox(cal
->GetParent(), -1, 
 115     for ( m 
= wxDateTime::Jan
; m 
< wxDateTime::Inv_Month
; wxNextMonth(m
) ) 
 117         Append(wxDateTime::GetMonthName(m
)); 
 120     SetSelection(m_cal
->GetDate().GetMonth()); 
 123 wxYearSpinCtrl::wxYearSpinCtrl(wxCalendarCtrl 
*cal
) 
 124               : wxSpinCtrl(cal
->GetParent(), -1, 
 125                            cal
->GetDate().Format(_T("%Y")), 
 129                            -4300, 10000, cal
->GetDate().GetYear()) 
 134 // ---------------------------------------------------------------------------- 
 136 // ---------------------------------------------------------------------------- 
 138 void wxCalendarCtrl::Init() 
 146     wxDateTime::WeekDay wd
; 
 147     for ( wd 
= wxDateTime::Sun
; wd 
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) ) 
 149         m_weekdays
[wd
] = wxDateTime::GetWeekDayName(wd
, wxDateTime::Name_Abbr
); 
 152     for ( size_t n 
= 0; n 
< WXSIZEOF(m_attrs
); n
++ ) 
 158     m_colHighlightFg 
= ss
.GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
 159     m_colHighlightBg 
= ss
.GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
); 
 161     m_colHolidayFg 
= *wxRED
; 
 162     // don't set m_colHolidayBg - by default, same as our bg colour 
 164     m_colHeaderFg 
= *wxBLUE
; 
 165     m_colHeaderBg 
= *wxLIGHT_GREY
; 
 168 bool wxCalendarCtrl::Create(wxWindow 
* WXUNUSED(parent
), 
 169                             wxWindowID 
WXUNUSED(id
), 
 170                             const wxDateTime
& date
, 
 171                             const wxPoint
& WXUNUSED(pos
), 
 174                             const wxString
& WXUNUSED(name
)) 
 176     // needed to get the arrow keys normally used for the dialog navigation 
 177     SetWindowStyle(style 
| wxWANTS_CHARS
); 
 179     m_date 
= date
.IsValid() ? date 
: wxDateTime::Today(); 
 181     m_spinYear 
= new wxYearSpinCtrl(this); 
 182     m_staticYear 
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%Y")), 
 183                                     wxDefaultPosition
, wxDefaultSize
, 
 186     m_comboMonth 
= new wxMonthComboBox(this); 
 187     m_staticMonth 
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%B")), 
 188                                      wxDefaultPosition
, wxDefaultSize
, 
 191     ShowCurrentControls(); 
 194     if ( size
.x 
== -1 || size
.y 
== -1 ) 
 196         sizeReal 
= DoGetBestSize(); 
 209     SetBackgroundColour(*wxWHITE
); 
 210     SetFont(*wxSWISS_FONT
); 
 217 wxCalendarCtrl::~wxCalendarCtrl() 
 219     for ( size_t n 
= 0; n 
< WXSIZEOF(m_attrs
); n
++ ) 
 225 // ---------------------------------------------------------------------------- 
 226 // forward wxWin functions to subcontrols 
 227 // ---------------------------------------------------------------------------- 
 229 bool wxCalendarCtrl::Show(bool show
) 
 231     if ( !wxControl::Show(show
) ) 
 236     GetMonthControl()->Show(show
); 
 237     GetYearControl()->Show(show
); 
 242 bool wxCalendarCtrl::Enable(bool enable
) 
 244     if ( !wxControl::Enable(enable
) ) 
 249     GetMonthControl()->Enable(enable
); 
 250     GetYearControl()->Enable(enable
); 
 255 // ---------------------------------------------------------------------------- 
 256 // enable/disable month/year controls 
 257 // ---------------------------------------------------------------------------- 
 259 void wxCalendarCtrl::ShowCurrentControls() 
 261     if ( AllowMonthChange() ) 
 263         m_comboMonth
->Show(); 
 264         m_staticMonth
->Hide(); 
 266         if ( AllowYearChange() ) 
 269             m_staticYear
->Hide(); 
 277         m_comboMonth
->Hide(); 
 278         m_staticMonth
->Show(); 
 281     // year change not allowed here 
 283     m_staticYear
->Show(); 
 286 wxControl 
*wxCalendarCtrl::GetMonthControl() const 
 288     return AllowMonthChange() ? (wxControl 
*)m_comboMonth 
: (wxControl 
*)m_staticMonth
; 
 291 wxControl 
*wxCalendarCtrl::GetYearControl() const 
 293     return AllowYearChange() ? (wxControl 
*)m_spinYear 
: (wxControl 
*)m_staticYear
; 
 296 void wxCalendarCtrl::EnableYearChange(bool enable
) 
 298     if ( enable 
!= AllowYearChange() ) 
 300         long style 
= GetWindowStyle(); 
 302             style 
&= ~wxCAL_NO_YEAR_CHANGE
; 
 304             style 
|= wxCAL_NO_YEAR_CHANGE
; 
 305         SetWindowStyle(style
); 
 307         ShowCurrentControls(); 
 311 void wxCalendarCtrl::EnableMonthChange(bool enable
) 
 313     if ( enable 
!= AllowMonthChange() ) 
 315         long style 
= GetWindowStyle(); 
 317             style 
&= ~wxCAL_NO_MONTH_CHANGE
; 
 319             style 
|= wxCAL_NO_MONTH_CHANGE
; 
 320         SetWindowStyle(style
); 
 322         ShowCurrentControls(); 
 326 // ---------------------------------------------------------------------------- 
 328 // ---------------------------------------------------------------------------- 
 330 void wxCalendarCtrl::SetDate(const wxDateTime
& date
) 
 332     bool sameMonth 
= m_date
.GetMonth() == date
.GetMonth(), 
 333          sameYear 
= m_date
.GetYear() == date
.GetYear(); 
 335     if ( sameMonth 
&& sameYear 
) 
 337         // just change the day 
 342         if ( !AllowMonthChange() || (!AllowYearChange() && !sameYear
) ) 
 351         // update the controls 
 352         m_comboMonth
->SetSelection(m_date
.GetMonth()); 
 354         if ( AllowYearChange() ) 
 356             m_spinYear
->SetValue(m_date
.Format(_T("%Y"))); 
 359         // as the month changed, holidays did too 
 362         // update the calendar 
 367 void wxCalendarCtrl::ChangeDay(const wxDateTime
& date
) 
 369     if ( m_date 
!= date 
) 
 371         // we need to refresh the row containing the old date and the one 
 372         // containing the new one 
 373         wxDateTime dateOld 
= m_date
; 
 376         RefreshDate(dateOld
); 
 378         // if the date is in the same row, it was already drawn correctly 
 379         if ( GetWeek(m_date
) != GetWeek(dateOld
) ) 
 386 void wxCalendarCtrl::SetDateAndNotify(const wxDateTime
& date
) 
 388     wxDateTime::Tm tm1 
= m_date
.GetTm(), 
 392     if ( tm1
.year 
!= tm2
.year 
) 
 393         type 
= wxEVT_CALENDAR_YEAR_CHANGED
; 
 394     else if ( tm1
.mon 
!= tm2
.mon 
) 
 395         type 
= wxEVT_CALENDAR_MONTH_CHANGED
; 
 396     else if ( tm1
.mday 
!= tm2
.mday 
) 
 397         type 
= wxEVT_CALENDAR_DAY_CHANGED
; 
 403     GenerateEvents(type
, wxEVT_CALENDAR_SEL_CHANGED
); 
 406 // ---------------------------------------------------------------------------- 
 408 // ---------------------------------------------------------------------------- 
 410 wxDateTime 
wxCalendarCtrl::GetStartDate() const 
 412     wxDateTime::Tm tm 
= m_date
.GetTm(); 
 414     wxDateTime date 
= wxDateTime(1, tm
.mon
, tm
.year
); 
 417     date
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
 
 418                           ? wxDateTime::Mon 
: wxDateTime::Sun
); 
 423 bool wxCalendarCtrl::IsDateShown(const wxDateTime
& date
) const 
 425     return date
.GetMonth() == m_date
.GetMonth(); 
 428 size_t wxCalendarCtrl::GetWeek(const wxDateTime
& date
) const 
 430     return date
.GetWeekOfMonth(GetWindowStyle() & wxCAL_MONDAY_FIRST
 
 431                                ? wxDateTime::Monday_First
 
 432                                : wxDateTime::Sunday_First
); 
 435 // ---------------------------------------------------------------------------- 
 437 // ---------------------------------------------------------------------------- 
 439 // this is a composite control and it must arrange its parts each time its 
 440 // size or position changes: the combobox and spinctrl are along the top of 
 441 // the available area and the calendar takes up therest of the space 
 443 // the static controls are supposed to be always smaller than combo/spin so we 
 444 // always use the latter for size calculations and position the static to take 
 447 // the constants used for the layout 
 448 #define VERT_MARGIN     5           // distance between combo and calendar 
 449 #define HORZ_MARGIN    15           //                            spin 
 451 wxSize 
wxCalendarCtrl::DoGetBestSize() const 
 453     // calc the size of the calendar 
 454     ((wxCalendarCtrl 
*)this)->RecalcGeometry(); // const_cast 
 456     wxCoord width 
= 7*m_widthCol
, 
 457             height 
= 7*m_heightRow
; 
 459     wxSize sizeCombo 
= m_comboMonth
->GetBestSize(), 
 460            sizeSpin 
= m_spinYear
->GetBestSize(); 
 462     height 
+= VERT_MARGIN 
+ wxMax(sizeCombo
.y
, sizeSpin
.y
); 
 464     if ( GetWindowStyle() & (wxRAISED_BORDER 
| wxSUNKEN_BORDER
) ) 
 466         // the border would clip the last line otherwise 
 470     return wxSize(width
, height
); 
 473 void wxCalendarCtrl::DoSetSize(int x
, int y
, 
 474                                int width
, int height
, 
 477     wxControl::DoSetSize(x
, y
, width
, height
, sizeFlags
); 
 480 void wxCalendarCtrl::DoMoveWindow(int x
, int y
, int width
, int height
) 
 482     wxSize sizeCombo 
= m_comboMonth
->GetSize(); 
 483     wxSize sizeStatic 
= m_staticMonth
->GetSize(); 
 485     int dy 
= (sizeCombo
.y 
- sizeStatic
.y
) / 2; 
 486     m_comboMonth
->Move(x
, y
); 
 487     m_staticMonth
->SetSize(x
, y 
+ dy
, sizeCombo
.x
, sizeStatic
.y
); 
 489     int xDiff 
= sizeCombo
.x 
+ HORZ_MARGIN
; 
 490     m_spinYear
->SetSize(x 
+ xDiff
, y
, width 
- xDiff
, sizeCombo
.y
); 
 491     m_staticYear
->SetSize(x 
+ xDiff
, y 
+ dy
, width 
- xDiff
, sizeStatic
.y
); 
 493     wxSize sizeSpin 
= m_spinYear
->GetSize(); 
 494     int yDiff 
= wxMax(sizeSpin
.y
, sizeCombo
.y
) + VERT_MARGIN
; 
 496     wxControl::DoMoveWindow(x
, y 
+ yDiff
, width
, height 
- yDiff
); 
 499 void wxCalendarCtrl::DoGetPosition(int *x
, int *y
) const 
 501     wxControl::DoGetPosition(x
, y
); 
 503     // our real top corner is not in this position 
 506         *y 
-= GetMonthControl()->GetSize().y 
+ VERT_MARGIN
; 
 510 void wxCalendarCtrl::DoGetSize(int *width
, int *height
) const 
 512     wxControl::DoGetSize(width
, height
); 
 514     // our real height is bigger 
 517         *height 
+= GetMonthControl()->GetSize().y 
+ VERT_MARGIN
; 
 521 void wxCalendarCtrl::RecalcGeometry() 
 523     if ( m_widthCol 
!= 0 ) 
 530     // determine the column width (we assume that the weekday names are always 
 531     // wider (in any language) than the numbers) 
 533     wxDateTime::WeekDay wd
; 
 534     for ( wd 
= wxDateTime::Sun
; wd 
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) ) 
 537         dc
.GetTextExtent(m_weekdays
[wd
], &width
, &m_heightRow
); 
 538         if ( width 
> m_widthCol 
) 
 544     // leave some margins 
 549 // ---------------------------------------------------------------------------- 
 551 // ---------------------------------------------------------------------------- 
 553 void wxCalendarCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 562     printf("--- starting to paint, selection: %s, week %u\n", 
 563            m_date
.Format("%a %d-%m-%Y %H:%M:%S").c_str(), 
 567     // first draw the week days 
 568     if ( IsExposed(0, 0, 7*m_widthCol
, m_heightRow
) ) 
 571         puts("painting the header"); 
 574         dc
.SetBackgroundMode(wxTRANSPARENT
); 
 575         dc
.SetTextForeground(m_colHeaderFg
); 
 576         dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
)); 
 577         dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
)); 
 578         dc
.DrawRectangle(0, 0, 7*m_widthCol
, m_heightRow
); 
 580         bool startOnMonday 
= (GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0; 
 581         for ( size_t wd 
= 0; wd 
< 7; wd
++ ) 
 585                 n 
= wd 
== 6 ? 0 : wd 
+ 1; 
 589             dc
.DrawText(m_weekdays
[n
], wd
*m_widthCol 
+ 1, 0); 
 593     // then the calendar itself 
 594     dc
.SetTextForeground(*wxBLACK
); 
 595     //dc.SetFont(*wxNORMAL_FONT); 
 597     wxCoord y 
= m_heightRow
; 
 599     wxDateTime date 
= GetStartDate(); 
 601     printf("starting calendar from %s\n", 
 602             date
.Format("%a %d-%m-%Y %H:%M:%S").c_str()); 
 605     dc
.SetBackgroundMode(wxSOLID
); 
 606     for ( size_t nWeek 
= 1; nWeek 
<= 6; nWeek
++, y 
+= m_heightRow 
) 
 608         // if the update region doesn't intersect this row, don't paint it 
 609         if ( !IsExposed(0, y
, 7*m_widthCol
, m_heightRow 
- 1) ) 
 611             date 
+= wxDateSpan::Week(); 
 617         printf("painting week %d at y = %d\n", nWeek
, y
); 
 620         for ( size_t wd 
= 0; wd 
< 7; wd
++ ) 
 622             if ( IsDateShown(date
) ) 
 624                 // don't use wxDate::Format() which prepends 0s 
 625                 unsigned int day 
= date
.GetDay(); 
 626                 wxString dayStr 
= wxString::Format(_T("%u"), day
); 
 628                 dc
.GetTextExtent(dayStr
, &width
, (wxCoord 
*)NULL
); 
 630                 bool changedColours 
= FALSE
, 
 633                 wxCalendarDateAttr 
*attr 
= m_attrs
[day 
- 1]; 
 635                 bool isSel 
= m_date 
== date
; 
 638                     dc
.SetTextForeground(m_colHighlightFg
); 
 639                     dc
.SetTextBackground(m_colHighlightBg
); 
 641                     changedColours 
= TRUE
; 
 645                     wxColour colFg
, colBg
; 
 647                     if ( attr
->IsHoliday() ) 
 649                         colFg 
= m_colHolidayFg
; 
 650                         colBg 
= m_colHolidayBg
; 
 654                         colFg 
= attr
->GetTextColour(); 
 655                         colBg 
= attr
->GetBackgroundColour(); 
 660                         dc
.SetTextForeground(colFg
); 
 661                         changedColours 
= TRUE
; 
 666                         dc
.SetTextBackground(colBg
); 
 667                         changedColours 
= TRUE
; 
 670                     if ( attr
->HasFont() ) 
 672                         dc
.SetFont(attr
->GetFont()); 
 677                 wxCoord x 
= wd
*m_widthCol 
+ (m_widthCol 
- width
) / 2; 
 678                 dc
.DrawText(dayStr
, x
, y 
+ 1); 
 680                 if ( !isSel 
&& attr 
&& attr
->HasBorder() ) 
 683                     if ( attr
->HasBorderColour() ) 
 685                         colBorder 
= attr
->GetBorderColour(); 
 689                         colBorder 
= m_foregroundColour
; 
 692                     wxPen 
pen(colBorder
, 1, wxSOLID
); 
 694                     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 696                     switch ( attr
->GetBorder() ) 
 698                         case wxCAL_BORDER_SQUARE
: 
 699                             dc
.DrawRectangle(x 
- 2, y
, 
 700                                              width 
+ 4, m_heightRow
); 
 703                         case wxCAL_BORDER_ROUND
: 
 704                             dc
.DrawEllipse(x 
- 2, y
, 
 705                                            width 
+ 4, m_heightRow
); 
 709                             wxFAIL_MSG(_T("unknown border type")); 
 713                 if ( changedColours 
) 
 715                     dc
.SetTextForeground(m_foregroundColour
); 
 716                     dc
.SetTextBackground(m_backgroundColour
); 
 724             //else: just don't draw it 
 726             date 
+= wxDateSpan::Day(); 
 730     puts("+++ finished painting"); 
 734 void wxCalendarCtrl::RefreshDate(const wxDateTime
& date
) 
 740     // always refresh the whole row at once because our OnPaint() will draw 
 741     // the whole row anyhow - and this allows the small optimisation in 
 742     // OnClick() below to work 
 744     rect
.y 
= m_heightRow 
* GetWeek(date
); 
 745     rect
.width 
= 7*m_widthCol
; 
 746     rect
.height 
= m_heightRow
; 
 749     printf("*** refreshing week %d at (%d, %d)-(%d, %d)\n", 
 752            rect
.x 
+ rect
.width
, rect
.y 
+ rect
.height
); 
 755     Refresh(TRUE
, &rect
); 
 758 // ---------------------------------------------------------------------------- 
 760 // ---------------------------------------------------------------------------- 
 762 void wxCalendarCtrl::OnDClick(wxMouseEvent
& event
) 
 764     if ( HitTest(event
.GetPosition()) != wxCAL_HITTEST_DAY 
) 
 770         GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
); 
 774 void wxCalendarCtrl::OnClick(wxMouseEvent
& event
) 
 777     wxDateTime::WeekDay wday
; 
 778     switch ( HitTest(event
.GetPosition(), &date
, &wday
) ) 
 780         case wxCAL_HITTEST_DAY
: 
 783             GenerateEvents(wxEVT_CALENDAR_DAY_CHANGED
, 
 784                            wxEVT_CALENDAR_SEL_CHANGED
); 
 787         case wxCAL_HITTEST_HEADER
: 
 789                 wxCalendarEvent 
event(this, wxEVT_CALENDAR_WEEKDAY_CLICKED
); 
 791                 (void)GetEventHandler()->ProcessEvent(event
); 
 796             wxFAIL_MSG(_T("unknown hittest code")); 
 799         case wxCAL_HITTEST_NOWHERE
: 
 805 wxCalendarHitTestResult 
wxCalendarCtrl::HitTest(const wxPoint
& pos
, 
 807                                                 wxDateTime::WeekDay 
*wd
) 
 811     int wday 
= pos
.x 
/ m_widthCol
; 
 814     if ( y 
< m_heightRow 
) 
 818             if ( GetWindowStyle() & wxCAL_MONDAY_FIRST 
) 
 820                 wday 
= wday 
== 6 ? 0 : wday 
+ 1; 
 823             *wd 
= (wxDateTime::WeekDay
)wday
; 
 826         return wxCAL_HITTEST_HEADER
; 
 829     int week 
= (y 
- m_heightRow
) / m_heightRow
; 
 830     if ( week 
>= 6 || wday 
>= 7 ) 
 832         return wxCAL_HITTEST_NOWHERE
; 
 835     wxDateTime dt 
= GetStartDate() + wxDateSpan::Days(7*week 
+ wday
); 
 837     if ( IsDateShown(dt
) ) 
 842         return wxCAL_HITTEST_DAY
; 
 846         return wxCAL_HITTEST_NOWHERE
; 
 850 // ---------------------------------------------------------------------------- 
 851 // subcontrols events handling 
 852 // ---------------------------------------------------------------------------- 
 854 void wxCalendarCtrl::OnMonthChange(wxCommandEvent
& event
) 
 856     wxDateTime::Tm tm 
= m_date
.GetTm(); 
 858     wxDateTime::Month mon 
= (wxDateTime::Month
)event
.GetInt(); 
 859     if ( tm
.mday 
> wxDateTime::GetNumberOfDays(mon
, tm
.year
) ) 
 861         tm
.mday 
= wxDateTime::GetNumberOfDays(mon
, tm
.year
); 
 864     SetDateAndNotify(wxDateTime(tm
.mday
, mon
, tm
.year
)); 
 867 void wxCalendarCtrl::OnYearChange(wxSpinEvent
& event
) 
 869     wxDateTime::Tm tm 
= m_date
.GetTm(); 
 871     int year 
= (int)event
.GetInt(); 
 872     if ( tm
.mday 
> wxDateTime::GetNumberOfDays(tm
.mon
, year
) ) 
 874         tm
.mday 
= wxDateTime::GetNumberOfDays(tm
.mon
, year
); 
 877     SetDateAndNotify(wxDateTime(tm
.mday
, tm
.mon
, year
)); 
 880 // ---------------------------------------------------------------------------- 
 881 // keyboard interface 
 882 // ---------------------------------------------------------------------------- 
 884 void wxCalendarCtrl::OnChar(wxKeyEvent
& event
) 
 886     switch ( event
.KeyCode() ) 
 890             SetDateAndNotify(m_date 
+ wxDateSpan::Year()); 
 895             SetDateAndNotify(m_date 
- wxDateSpan::Year()); 
 899             SetDateAndNotify(m_date 
- wxDateSpan::Month()); 
 903             SetDateAndNotify(m_date 
+ wxDateSpan::Month()); 
 907             if ( event
.ControlDown() ) 
 908                 SetDateAndNotify(wxDateTime(m_date
).SetToNextWeekDay( 
 909                                  GetWindowStyle() & wxCAL_MONDAY_FIRST
 
 910                                  ? wxDateTime::Sun 
: wxDateTime::Sat
)); 
 912                 SetDateAndNotify(m_date 
+ wxDateSpan::Day()); 
 916             if ( event
.ControlDown() ) 
 917                 SetDateAndNotify(wxDateTime(m_date
).SetToPrevWeekDay( 
 918                                  GetWindowStyle() & wxCAL_MONDAY_FIRST
 
 919                                  ? wxDateTime::Mon 
: wxDateTime::Sun
)); 
 921                 SetDateAndNotify(m_date 
- wxDateSpan::Day()); 
 925             SetDateAndNotify(m_date 
- wxDateSpan::Week()); 
 929             SetDateAndNotify(m_date 
+ wxDateSpan::Week()); 
 933             if ( event
.ControlDown() ) 
 934                 SetDateAndNotify(wxDateTime::Today()); 
 936                 SetDateAndNotify(wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear())); 
 940             SetDateAndNotify(wxDateTime(m_date
).SetToLastMonthDay()); 
 944             GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
); 
 952 // ---------------------------------------------------------------------------- 
 954 // ---------------------------------------------------------------------------- 
 956 void wxCalendarCtrl::EnableHolidayDisplay(bool display
) 
 958     long style 
= GetWindowStyle(); 
 960         style 
|= wxCAL_SHOW_HOLIDAYS
; 
 962         style 
&= ~wxCAL_SHOW_HOLIDAYS
; 
 964     SetWindowStyle(style
); 
 974 void wxCalendarCtrl::SetHolidayAttrs() 
 976     if ( GetWindowStyle() & wxCAL_SHOW_HOLIDAYS 
) 
 980         wxDateTime::Tm tm 
= m_date
.GetTm(); 
 981         wxDateTime 
dtStart(1, tm
.mon
, tm
.year
), 
 982                    dtEnd 
= dtStart
.GetLastMonthDay(); 
 985         wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart
, dtEnd
, hol
); 
 987         size_t count 
= hol
.GetCount(); 
 988         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 990             SetHoliday(hol
[n
].GetDay()); 
 995 void wxCalendarCtrl::SetHoliday(size_t day
) 
 997     wxCHECK_RET( day 
> 0 && day 
< 32, _T("invalid day in SetHoliday") ); 
 999     wxCalendarDateAttr 
*attr 
= GetAttr(day
); 
1002         attr 
= new wxCalendarDateAttr
; 
1005     attr
->SetHoliday(TRUE
); 
1007     // can't use SetAttr() because it would delete this pointer 
1008     m_attrs
[day 
- 1] = attr
; 
1011 void wxCalendarCtrl::ResetHolidayAttrs() 
1013     for ( size_t day 
= 0; day 
< 31; day
++ ) 
1017             m_attrs
[day
]->SetHoliday(FALSE
); 
1022 // ---------------------------------------------------------------------------- 
1024 // ---------------------------------------------------------------------------- 
1026 void wxCalendarEvent::Init() 
1028     m_wday 
= wxDateTime::Inv_WeekDay
; 
1031 wxCalendarEvent::wxCalendarEvent(wxCalendarCtrl 
*cal
, wxEventType type
) 
1032                : wxCommandEvent(type
, cal
->GetId()) 
1034     m_date 
= cal
->GetDate();