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 licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
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"
37 #include "wx/textctrl.h"
40 #if wxUSE_CALENDARCTRL
42 #include "wx/spinctrl.h"
44 #include "wx/calctrl.h"
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 class wxMonthComboBox
: public wxComboBox
55 wxMonthComboBox(wxCalendarCtrl
*cal
);
57 void OnMonthChange(wxCommandEvent
& event
) { m_cal
->OnMonthChange(event
); }
60 wxCalendarCtrl
*m_cal
;
63 DECLARE_NO_COPY_CLASS(wxMonthComboBox
)
66 class wxYearSpinCtrl
: public wxSpinCtrl
69 wxYearSpinCtrl(wxCalendarCtrl
*cal
);
71 void OnYearTextChange(wxCommandEvent
& event
)
73 m_cal
->SetUserChangedYear();
74 m_cal
->OnYearChange(event
);
76 void OnYearChange(wxSpinEvent
& event
) { m_cal
->OnYearChange(event
); }
79 wxCalendarCtrl
*m_cal
;
82 DECLARE_NO_COPY_CLASS(wxYearSpinCtrl
)
85 // ----------------------------------------------------------------------------
87 // ----------------------------------------------------------------------------
89 BEGIN_EVENT_TABLE(wxCalendarCtrl
, wxControl
)
90 EVT_PAINT(wxCalendarCtrl::OnPaint
)
92 EVT_CHAR(wxCalendarCtrl::OnChar
)
94 EVT_LEFT_DOWN(wxCalendarCtrl::OnClick
)
95 EVT_LEFT_DCLICK(wxCalendarCtrl::OnDClick
)
98 BEGIN_EVENT_TABLE(wxMonthComboBox
, wxComboBox
)
99 EVT_COMBOBOX(-1, wxMonthComboBox::OnMonthChange
)
102 BEGIN_EVENT_TABLE(wxYearSpinCtrl
, wxSpinCtrl
)
103 EVT_TEXT(-1, wxYearSpinCtrl::OnYearTextChange
)
104 EVT_SPINCTRL(-1, wxYearSpinCtrl::OnYearChange
)
107 IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl
, wxControl
)
108 IMPLEMENT_DYNAMIC_CLASS(wxCalendarEvent
, wxCommandEvent
)
110 // ----------------------------------------------------------------------------
112 // ----------------------------------------------------------------------------
114 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_SEL_CHANGED
)
115 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_DAY_CHANGED
)
116 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_MONTH_CHANGED
)
117 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_YEAR_CHANGED
)
118 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_DOUBLECLICKED
)
119 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_WEEKDAY_CLICKED
)
121 // ============================================================================
123 // ============================================================================
125 // ----------------------------------------------------------------------------
126 // wxMonthComboBox and wxYearSpinCtrl
127 // ----------------------------------------------------------------------------
129 wxMonthComboBox::wxMonthComboBox(wxCalendarCtrl
*cal
)
130 : wxComboBox(cal
->GetParent(), -1,
135 wxCB_READONLY
| wxCLIP_SIBLINGS
)
140 for ( m
= wxDateTime::Jan
; m
< wxDateTime::Inv_Month
; wxNextMonth(m
) )
142 Append(wxDateTime::GetMonthName(m
));
145 SetSelection(m_cal
->GetDate().GetMonth());
146 SetSize(-1, -1, -1, -1, wxSIZE_AUTO_WIDTH
|wxSIZE_AUTO_HEIGHT
);
149 wxYearSpinCtrl::wxYearSpinCtrl(wxCalendarCtrl
*cal
)
150 : wxSpinCtrl(cal
->GetParent(), -1,
151 cal
->GetDate().Format(_T("%Y")),
154 wxSP_ARROW_KEYS
| wxCLIP_SIBLINGS
,
155 -4300, 10000, cal
->GetDate().GetYear())
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 wxCalendarCtrl::wxCalendarCtrl(wxWindow
*parent
,
167 const wxDateTime
& date
,
171 const wxString
& name
)
175 (void)Create(parent
, id
, date
, pos
, size
, style
, name
);
178 void wxCalendarCtrl::Init()
183 m_staticMonth
= NULL
;
185 m_userChangedYear
= FALSE
;
190 wxDateTime::WeekDay wd
;
191 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
193 m_weekdays
[wd
] = wxDateTime::GetWeekDayName(wd
, wxDateTime::Name_Abbr
);
196 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
201 m_colHighlightFg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
202 m_colHighlightBg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
204 m_colHolidayFg
= *wxRED
;
205 // don't set m_colHolidayBg - by default, same as our bg colour
207 m_colHeaderFg
= *wxBLUE
;
208 m_colHeaderBg
= *wxLIGHT_GREY
;
211 bool wxCalendarCtrl::Create(wxWindow
*parent
,
213 const wxDateTime
& date
,
217 const wxString
& name
)
219 if ( !wxControl::Create(parent
, id
, pos
, size
,
220 style
| wxCLIP_CHILDREN
| wxWANTS_CHARS
,
221 wxDefaultValidator
, name
) )
226 // needed to get the arrow keys normally used for the dialog navigation
227 SetWindowStyle(style
| wxWANTS_CHARS
);
229 m_date
= date
.IsValid() ? date
: wxDateTime::Today();
231 m_lowdate
= wxDefaultDateTime
;
232 m_highdate
= wxDefaultDateTime
;
234 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
236 m_spinYear
= new wxYearSpinCtrl(this);
237 m_staticYear
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%Y")),
238 wxDefaultPosition
, wxDefaultSize
,
241 m_comboMonth
= new wxMonthComboBox(this);
242 m_staticMonth
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%B")),
243 wxDefaultPosition
, wxDefaultSize
,
247 ShowCurrentControls();
250 if ( size
.x
== -1 || size
.y
== -1 )
252 sizeReal
= DoGetBestSize();
263 // we need to set the position as well because the main control position
264 // is not the same as the one specified in pos if we have the controls
266 SetSize(pos
.x
, pos
.y
, sizeReal
.x
, sizeReal
.y
);
268 SetBackgroundColour(*wxWHITE
);
269 SetFont(*wxSWISS_FONT
);
276 wxCalendarCtrl::~wxCalendarCtrl()
278 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
284 // ----------------------------------------------------------------------------
285 // forward wxWin functions to subcontrols
286 // ----------------------------------------------------------------------------
288 bool wxCalendarCtrl::Destroy()
291 m_staticYear
->Destroy();
293 m_spinYear
->Destroy();
295 m_comboMonth
->Destroy();
297 m_staticMonth
->Destroy();
302 m_staticMonth
= NULL
;
304 return wxControl::Destroy();
307 bool wxCalendarCtrl::Show(bool show
)
309 if ( !wxControl::Show(show
) )
314 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
316 if ( GetMonthControl() )
318 GetMonthControl()->Show(show
);
319 GetYearControl()->Show(show
);
326 bool wxCalendarCtrl::Enable(bool enable
)
328 if ( !wxControl::Enable(enable
) )
333 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
335 GetMonthControl()->Enable(enable
);
336 GetYearControl()->Enable(enable
);
342 // ----------------------------------------------------------------------------
343 // enable/disable month/year controls
344 // ----------------------------------------------------------------------------
346 void wxCalendarCtrl::ShowCurrentControls()
348 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
350 if ( AllowMonthChange() )
352 m_comboMonth
->Show();
353 m_staticMonth
->Hide();
355 if ( AllowYearChange() )
358 m_staticYear
->Hide();
366 m_comboMonth
->Hide();
367 m_staticMonth
->Show();
370 // year change not allowed here
372 m_staticYear
->Show();
376 wxControl
*wxCalendarCtrl::GetMonthControl() const
378 return AllowMonthChange() ? (wxControl
*)m_comboMonth
: (wxControl
*)m_staticMonth
;
381 wxControl
*wxCalendarCtrl::GetYearControl() const
383 return AllowYearChange() ? (wxControl
*)m_spinYear
: (wxControl
*)m_staticYear
;
386 void wxCalendarCtrl::EnableYearChange(bool enable
)
388 if ( enable
!= AllowYearChange() )
390 long style
= GetWindowStyle();
392 style
&= ~wxCAL_NO_YEAR_CHANGE
;
394 style
|= wxCAL_NO_YEAR_CHANGE
;
395 SetWindowStyle(style
);
397 ShowCurrentControls();
398 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
405 void wxCalendarCtrl::EnableMonthChange(bool enable
)
407 if ( enable
!= AllowMonthChange() )
409 long style
= GetWindowStyle();
411 style
&= ~wxCAL_NO_MONTH_CHANGE
;
413 style
|= wxCAL_NO_MONTH_CHANGE
;
414 SetWindowStyle(style
);
416 ShowCurrentControls();
417 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
424 // ----------------------------------------------------------------------------
426 // ----------------------------------------------------------------------------
428 bool wxCalendarCtrl::SetDate(const wxDateTime
& date
)
432 bool sameMonth
= m_date
.GetMonth() == date
.GetMonth(),
433 sameYear
= m_date
.GetYear() == date
.GetYear();
435 if ( IsDateInRange(date
) )
437 if ( sameMonth
&& sameYear
)
439 // just change the day
444 if ( AllowMonthChange() && (AllowYearChange() || sameYear
) )
449 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
451 // update the controls
452 m_comboMonth
->SetSelection(m_date
.GetMonth());
454 if ( AllowYearChange() )
456 if ( !m_userChangedYear
)
457 m_spinYear
->SetValue(m_date
.Format(_T("%Y")));
461 // as the month changed, holidays did too
464 // update the calendar
475 m_userChangedYear
= FALSE
;
480 void wxCalendarCtrl::ChangeDay(const wxDateTime
& date
)
482 if ( m_date
!= date
)
484 // we need to refresh the row containing the old date and the one
485 // containing the new one
486 wxDateTime dateOld
= m_date
;
489 RefreshDate(dateOld
);
491 // if the date is in the same row, it was already drawn correctly
492 if ( GetWeek(m_date
) != GetWeek(dateOld
) )
499 void wxCalendarCtrl::SetDateAndNotify(const wxDateTime
& date
)
501 wxDateTime::Tm tm1
= m_date
.GetTm(),
505 if ( tm1
.year
!= tm2
.year
)
506 type
= wxEVT_CALENDAR_YEAR_CHANGED
;
507 else if ( tm1
.mon
!= tm2
.mon
)
508 type
= wxEVT_CALENDAR_MONTH_CHANGED
;
509 else if ( tm1
.mday
!= tm2
.mday
)
510 type
= wxEVT_CALENDAR_DAY_CHANGED
;
516 GenerateEvents(type
, wxEVT_CALENDAR_SEL_CHANGED
);
520 // ----------------------------------------------------------------------------
522 // ----------------------------------------------------------------------------
524 bool wxCalendarCtrl::SetLowerDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
528 if ( !(date
.IsValid()) || ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) )
540 bool wxCalendarCtrl::SetUpperDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
544 if ( !(date
.IsValid()) || ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
) )
556 bool wxCalendarCtrl::SetDateRange(const wxDateTime
& lowerdate
/* = wxDefaultDateTime */, const wxDateTime
& upperdate
/* = wxDefaultDateTime */)
561 ( !( lowerdate
.IsValid() ) || ( ( upperdate
.IsValid() ) ? ( lowerdate
<= upperdate
) : TRUE
) ) &&
562 ( !( upperdate
.IsValid() ) || ( ( lowerdate
.IsValid() ) ? ( upperdate
>= lowerdate
) : TRUE
) ) )
564 m_lowdate
= lowerdate
;
565 m_highdate
= upperdate
;
575 // ----------------------------------------------------------------------------
577 // ----------------------------------------------------------------------------
579 wxDateTime
wxCalendarCtrl::GetStartDate() const
581 wxDateTime::Tm tm
= m_date
.GetTm();
583 wxDateTime date
= wxDateTime(1, tm
.mon
, tm
.year
);
586 date
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
587 ? wxDateTime::Mon
: wxDateTime::Sun
);
589 if ( GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
)
591 // We want to offset the calendar if we start on the first..
592 if ( date
.GetDay() == 1 )
594 date
-= wxDateSpan::Week();
601 bool wxCalendarCtrl::IsDateShown(const wxDateTime
& date
) const
603 if ( !(GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
605 return date
.GetMonth() == m_date
.GetMonth();
613 bool wxCalendarCtrl::IsDateInRange(const wxDateTime
& date
) const
616 // Check if the given date is in the range specified
617 retval
= ( ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
)
618 && ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) );
622 bool wxCalendarCtrl::ChangeYear(wxDateTime
* target
) const
626 if ( !(IsDateInRange(*target
)) )
628 if ( target
->GetYear() < m_date
.GetYear() )
630 if ( target
->GetYear() >= GetLowerDateLimit().GetYear() )
632 *target
= GetLowerDateLimit();
642 if ( target
->GetYear() <= GetUpperDateLimit().GetYear() )
644 *target
= GetUpperDateLimit();
661 bool wxCalendarCtrl::ChangeMonth(wxDateTime
* target
) const
665 if ( !(IsDateInRange(*target
)) )
669 if ( target
->GetMonth() < m_date
.GetMonth() )
671 *target
= GetLowerDateLimit();
675 *target
= GetUpperDateLimit();
682 size_t wxCalendarCtrl::GetWeek(const wxDateTime
& date
) const
684 size_t retval
= date
.GetWeekOfMonth(GetWindowStyle() & wxCAL_MONDAY_FIRST
685 ? wxDateTime::Monday_First
686 : wxDateTime::Sunday_First
);
688 if ( (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
690 // we need to offset an extra week if we "start" on the 1st of the month
691 wxDateTime::Tm tm
= date
.GetTm();
693 wxDateTime datetest
= wxDateTime(1, tm
.mon
, tm
.year
);
696 datetest
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
697 ? wxDateTime::Mon
: wxDateTime::Sun
);
699 if ( datetest
.GetDay() == 1 )
708 // ----------------------------------------------------------------------------
710 // ----------------------------------------------------------------------------
712 // this is a composite control and it must arrange its parts each time its
713 // size or position changes: the combobox and spinctrl are along the top of
714 // the available area and the calendar takes up therest of the space
716 // the static controls are supposed to be always smaller than combo/spin so we
717 // always use the latter for size calculations and position the static to take
720 // the constants used for the layout
721 #define VERT_MARGIN 5 // distance between combo and calendar
723 #define HORZ_MARGIN 5 // spin
725 #define HORZ_MARGIN 15 // spin
727 wxSize
wxCalendarCtrl::DoGetBestSize() const
729 // calc the size of the calendar
730 ((wxCalendarCtrl
*)this)->RecalcGeometry(); // const_cast
732 wxCoord width
= 7*m_widthCol
,
733 height
= 7*m_heightRow
+ m_rowOffset
+ VERT_MARGIN
;
735 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
737 // the combobox doesn't report its height correctly (it returns the
738 // height including the drop down list) so don't use it
739 height
+= m_spinYear
->GetBestSize().y
;
742 if ( !HasFlag(wxBORDER_NONE
) )
744 // the border would clip the last line otherwise
749 return wxSize(width
, height
);
752 void wxCalendarCtrl::DoSetSize(int x
, int y
,
753 int width
, int height
,
756 wxControl::DoSetSize(x
, y
, width
, height
, sizeFlags
);
759 void wxCalendarCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
763 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
765 wxSize sizeCombo
= m_comboMonth
->GetSize();
766 wxSize sizeStatic
= m_staticMonth
->GetSize();
767 wxSize sizeSpin
= m_spinYear
->GetSize();
768 int dy
= (sizeCombo
.y
- sizeStatic
.y
) / 2;
770 In the calender the size of the combobox for the year
771 is just defined by a margin from the month combobox to
772 the left border. While in wxUniv the year control can't
773 show all 4 digits, in wxMsw it show almost twice as
774 much. Instead the year should use it's best size and be
775 left aligned to the calendar. Just in case the month in
776 any language is longer than it has space in the
777 calendar it is shortend.This way the year always can
780 This patch relies on the fact that a combobox has a
781 good best size implementation. This is not the case
782 with wxMSW but I don't know why.
787 #ifdef __WXUNIVERSAL__
788 if (sizeCombo
.x
+ HORZ_MARGIN
- sizeSpin
.x
> width
)
790 m_comboMonth
->SetSize(x
, y
, width
- HORZ_MARGIN
- sizeSpin
.x
, sizeCombo
.y
);
794 m_comboMonth
->Move(x
, y
);
796 m_staticMonth
->Move(x
, y
+ dy
);
797 m_spinYear
->Move(x
+ width
- sizeSpin
.x
, y
);
798 m_staticYear
->Move(x
+ width
- sizeSpin
.x
, y
+ dy
);
800 m_comboMonth
->Move(x
, y
);
801 m_staticMonth
->SetSize(x
, y
+ dy
, sizeCombo
.x
, sizeStatic
.y
);
803 int xDiff
= sizeCombo
.x
+ HORZ_MARGIN
;
805 m_spinYear
->SetSize(x
+ xDiff
, y
, width
- xDiff
, sizeCombo
.y
);
806 m_staticYear
->SetSize(x
+ xDiff
, y
+ dy
, width
- xDiff
, sizeStatic
.y
);
808 yDiff
= wxMax(sizeSpin
.y
, sizeCombo
.y
) + VERT_MARGIN
;
810 else // no controls on the top
815 wxControl::DoMoveWindow(x
, y
+ yDiff
, width
, height
- yDiff
);
818 void wxCalendarCtrl::DoGetPosition(int *x
, int *y
) const
820 wxControl::DoGetPosition(x
, y
);
822 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
824 // our real top corner is not in this position
827 *y
-= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
832 void wxCalendarCtrl::DoGetSize(int *width
, int *height
) const
834 wxControl::DoGetSize(width
, height
);
836 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
838 // our real height is bigger
839 if ( height
&& GetMonthControl())
841 *height
+= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
846 void wxCalendarCtrl::RecalcGeometry()
848 if ( m_widthCol
!= 0 )
855 // determine the column width (we assume that the weekday names are always
856 // wider (in any language) than the numbers)
858 wxDateTime::WeekDay wd
;
859 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
862 dc
.GetTextExtent(m_weekdays
[wd
], &width
, &m_heightRow
);
863 if ( width
> m_widthCol
)
869 // leave some margins
873 m_rowOffset
= (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) ? m_heightRow
: 0; // conditional in relation to style
876 // ----------------------------------------------------------------------------
878 // ----------------------------------------------------------------------------
880 void wxCalendarCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
889 wxLogDebug("--- starting to paint, selection: %s, week %u\n",
890 m_date
.Format("%a %d-%m-%Y %H:%M:%S").c_str(),
896 if ( HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
898 // draw the sequential month-selector
900 dc
.SetBackgroundMode(wxTRANSPARENT
);
901 dc
.SetTextForeground(*wxBLACK
);
902 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
903 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
904 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
906 // Get extent of month-name + year
907 wxCoord monthw
, monthh
;
908 wxString headertext
= m_date
.Format(wxT("%B %Y"));
909 dc
.GetTextExtent(headertext
, &monthw
, &monthh
);
911 // draw month-name centered above weekdays
912 wxCoord monthx
= ((m_widthCol
* 7) - monthw
) / 2;
913 wxCoord monthy
= ((m_heightRow
- monthh
) / 2) + y
;
914 dc
.DrawText(headertext
, monthx
, monthy
);
916 // calculate the "month-arrows"
917 wxPoint leftarrow
[3];
918 wxPoint rightarrow
[3];
920 int arrowheight
= monthh
/ 2;
922 leftarrow
[0] = wxPoint(0, arrowheight
/ 2);
923 leftarrow
[1] = wxPoint(arrowheight
/ 2, 0);
924 leftarrow
[2] = wxPoint(arrowheight
/ 2, arrowheight
- 1);
926 rightarrow
[0] = wxPoint(0, 0);
927 rightarrow
[1] = wxPoint(arrowheight
/ 2, arrowheight
/ 2);
928 rightarrow
[2] = wxPoint(0, arrowheight
- 1);
930 // draw the "month-arrows"
932 wxCoord arrowy
= (m_heightRow
- arrowheight
) / 2;
933 wxCoord larrowx
= (m_widthCol
- (arrowheight
/ 2)) / 2;
934 wxCoord rarrowx
= ((m_widthCol
- (arrowheight
/ 2)) / 2) + m_widthCol
*6;
935 m_leftArrowRect
= wxRect(0, 0, 0, 0);
936 m_rightArrowRect
= wxRect(0, 0, 0, 0);
938 if ( AllowMonthChange() )
940 wxDateTime ldpm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) - wxDateSpan::Day(); // last day prev month
941 // Check if range permits change
942 if ( IsDateInRange(ldpm
) && ( ( ldpm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
944 m_leftArrowRect
= wxRect(larrowx
- 3, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
945 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
946 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
947 dc
.DrawPolygon(3, leftarrow
, larrowx
, arrowy
, wxWINDING_RULE
);
948 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
949 dc
.DrawRectangle(m_leftArrowRect
);
951 wxDateTime fdnm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) + wxDateSpan::Month(); // first day next month
952 if ( IsDateInRange(fdnm
) && ( ( fdnm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
954 m_rightArrowRect
= wxRect(rarrowx
- 4, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
955 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
956 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
957 dc
.DrawPolygon(3, rightarrow
, rarrowx
, arrowy
, wxWINDING_RULE
);
958 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
959 dc
.DrawRectangle(m_rightArrowRect
);
966 // first draw the week days
967 if ( IsExposed(0, y
, 7*m_widthCol
, m_heightRow
) )
970 wxLogDebug("painting the header");
973 dc
.SetBackgroundMode(wxTRANSPARENT
);
974 dc
.SetTextForeground(m_colHeaderFg
);
975 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
976 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
977 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
979 bool startOnMonday
= (GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
980 for ( size_t wd
= 0; wd
< 7; wd
++ )
984 n
= wd
== 6 ? 0 : wd
+ 1;
988 dc
.GetTextExtent(m_weekdays
[n
], &dayw
, &dayh
);
989 dc
.DrawText(m_weekdays
[n
], (wd
*m_widthCol
) + ((m_widthCol
- dayw
) / 2), y
); // center the day-name
993 // then the calendar itself
994 dc
.SetTextForeground(*wxBLACK
);
995 //dc.SetFont(*wxNORMAL_FONT);
998 wxDateTime date
= GetStartDate();
1001 wxLogDebug("starting calendar from %s\n",
1002 date
.Format("%a %d-%m-%Y %H:%M:%S").c_str());
1005 dc
.SetBackgroundMode(wxSOLID
);
1006 for ( size_t nWeek
= 1; nWeek
<= 6; nWeek
++, y
+= m_heightRow
)
1008 // if the update region doesn't intersect this row, don't paint it
1009 if ( !IsExposed(0, y
, 7*m_widthCol
, m_heightRow
- 1) )
1011 date
+= wxDateSpan::Week();
1017 wxLogDebug("painting week %d at y = %d\n", nWeek
, y
);
1020 for ( size_t wd
= 0; wd
< 7; wd
++ )
1022 if ( IsDateShown(date
) )
1024 // don't use wxDate::Format() which prepends 0s
1025 unsigned int day
= date
.GetDay();
1026 wxString dayStr
= wxString::Format(_T("%u"), day
);
1028 dc
.GetTextExtent(dayStr
, &width
, (wxCoord
*)NULL
);
1030 bool changedColours
= FALSE
,
1031 changedFont
= FALSE
;
1034 wxCalendarDateAttr
*attr
= NULL
;
1036 if ( date
.GetMonth() != m_date
.GetMonth() || !IsDateInRange(date
) )
1038 // surrounding week or out-of-range
1040 dc
.SetTextForeground(*wxLIGHT_GREY
);
1041 changedColours
= TRUE
;
1045 isSel
= date
.IsSameDate(m_date
);
1046 attr
= m_attrs
[day
- 1];
1050 dc
.SetTextForeground(m_colHighlightFg
);
1051 dc
.SetTextBackground(m_colHighlightBg
);
1053 changedColours
= TRUE
;
1057 wxColour colFg
, colBg
;
1059 if ( attr
->IsHoliday() )
1061 colFg
= m_colHolidayFg
;
1062 colBg
= m_colHolidayBg
;
1066 colFg
= attr
->GetTextColour();
1067 colBg
= attr
->GetBackgroundColour();
1072 dc
.SetTextForeground(colFg
);
1073 changedColours
= TRUE
;
1078 dc
.SetTextBackground(colBg
);
1079 changedColours
= TRUE
;
1082 if ( attr
->HasFont() )
1084 dc
.SetFont(attr
->GetFont());
1090 wxCoord x
= wd
*m_widthCol
+ (m_widthCol
- width
) / 2;
1091 dc
.DrawText(dayStr
, x
, y
+ 1);
1093 if ( !isSel
&& attr
&& attr
->HasBorder() )
1096 if ( attr
->HasBorderColour() )
1098 colBorder
= attr
->GetBorderColour();
1102 colBorder
= m_foregroundColour
;
1105 wxPen
pen(colBorder
, 1, wxSOLID
);
1107 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1109 switch ( attr
->GetBorder() )
1111 case wxCAL_BORDER_SQUARE
:
1112 dc
.DrawRectangle(x
- 2, y
,
1113 width
+ 4, m_heightRow
);
1116 case wxCAL_BORDER_ROUND
:
1117 dc
.DrawEllipse(x
- 2, y
,
1118 width
+ 4, m_heightRow
);
1122 wxFAIL_MSG(_T("unknown border type"));
1126 if ( changedColours
)
1128 dc
.SetTextForeground(m_foregroundColour
);
1129 dc
.SetTextBackground(m_backgroundColour
);
1137 //else: just don't draw it
1139 date
+= wxDateSpan::Day();
1143 // Greying out out-of-range background
1144 bool showSurrounding
= (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) != 0;
1146 date
= ( showSurrounding
) ? GetStartDate() : wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear());
1147 if ( !IsDateInRange(date
) )
1149 wxDateTime firstOOR
= GetLowerDateLimit() - wxDateSpan::Day(); // first out-of-range
1151 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1152 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1154 HighlightRange(&dc
, date
, firstOOR
, wxTRANSPARENT_PEN
, &oorbrush
);
1157 date
= ( showSurrounding
) ? GetStartDate() + wxDateSpan::Weeks(6) - wxDateSpan::Day() : wxDateTime().SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear());
1158 if ( !IsDateInRange(date
) )
1160 wxDateTime firstOOR
= GetUpperDateLimit() + wxDateSpan::Day(); // first out-of-range
1162 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1163 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1165 HighlightRange(&dc
, firstOOR
, date
, wxTRANSPARENT_PEN
, &oorbrush
);
1169 wxLogDebug("+++ finished painting");
1173 void wxCalendarCtrl::RefreshDate(const wxDateTime
& date
)
1179 // always refresh the whole row at once because our OnPaint() will draw
1180 // the whole row anyhow - and this allows the small optimisation in
1181 // OnClick() below to work
1184 rect
.y
= (m_heightRow
* GetWeek(date
)) + m_rowOffset
;
1186 rect
.width
= 7*m_widthCol
;
1187 rect
.height
= m_heightRow
;
1190 // VZ: for some reason, the selected date seems to occupy more space under
1191 // MSW - this is probably some bug in the font size calculations, but I
1192 // don't know where exactly. This fix is ugly and leads to more
1193 // refreshes than really needed, but without it the selected days
1194 // leaves even more ugly underscores on screen.
1199 wxLogDebug("*** refreshing week %d at (%d, %d)-(%d, %d)\n",
1202 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1205 Refresh(TRUE
, &rect
);
1208 void wxCalendarCtrl::HighlightRange(wxPaintDC
* pDC
, const wxDateTime
& fromdate
, const wxDateTime
& todate
, wxPen
* pPen
, wxBrush
* pBrush
)
1210 // Highlights the given range using pen and brush
1211 // Does nothing if todate < fromdate
1215 wxLogDebug("+++ HighlightRange: (%s) - (%s) +++", fromdate
.Format("%d %m %Y"), todate
.Format("%d %m %Y"));
1218 if ( todate
>= fromdate
)
1225 // implicit: both dates must be currently shown - checked by GetDateCoord
1226 if ( GetDateCoord(fromdate
, &fd
, &fw
) && GetDateCoord(todate
, &td
, &tw
) )
1229 wxLogDebug("Highlight range: (%i, %i) - (%i, %i)", fd
, fw
, td
, tw
);
1231 if ( ( (tw
- fw
) == 1 ) && ( td
< fd
) )
1233 // special case: interval 7 days or less not in same week
1234 // split in two seperate intervals
1235 wxDateTime tfd
= fromdate
+ wxDateSpan::Days(7-fd
);
1236 wxDateTime ftd
= tfd
+ wxDateSpan::Day();
1238 wxLogDebug("Highlight: Seperate segments");
1241 HighlightRange(pDC
, fromdate
, tfd
, pPen
, pBrush
);
1242 HighlightRange(pDC
, ftd
, todate
, pPen
, pBrush
);
1247 wxPoint corners
[8]; // potentially 8 corners in polygon
1251 // simple case: same week
1253 corners
[0] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
);
1254 corners
[1] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1 ) * m_heightRow
) + m_rowOffset
);
1255 corners
[2] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
);
1256 corners
[3] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
);
1261 // "complex" polygon
1262 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1266 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1267 corners
[cidx
] = wxPoint(0, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1270 corners
[cidx
] = wxPoint(0, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1271 corners
[cidx
] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1275 corners
[cidx
] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1276 corners
[cidx
] = wxPoint(7 * m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1279 corners
[cidx
] = wxPoint(7 * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1285 pDC
->SetBrush(*pBrush
);
1287 pDC
->DrawPolygon(numpoints
, corners
);
1293 wxLogDebug("--- HighlightRange ---");
1297 bool wxCalendarCtrl::GetDateCoord(const wxDateTime
& date
, int *day
, int *week
) const
1302 wxLogDebug("+++ GetDateCoord: (%s) +++", date
.Format("%d %m %Y"));
1305 if ( IsDateShown(date
) )
1307 bool startOnMonday
= ( GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
1310 *day
= date
.GetWeekDay();
1312 if ( *day
== 0 ) // sunday
1314 *day
= ( startOnMonday
) ? 7 : 1;
1318 day
+= ( startOnMonday
) ? 0 : 1;
1321 int targetmonth
= date
.GetMonth() + (12 * date
.GetYear());
1322 int thismonth
= m_date
.GetMonth() + (12 * m_date
.GetYear());
1325 if ( targetmonth
== thismonth
)
1327 *week
= GetWeek(date
);
1331 if ( targetmonth
< thismonth
)
1333 *week
= 1; // trivial
1335 else // targetmonth > thismonth
1341 // get the datecoord of the last day in the month currently shown
1343 wxLogDebug(" +++ LDOM +++");
1345 GetDateCoord(ldcm
.SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear()), &lastday
, &lastweek
);
1347 wxLogDebug(" --- LDOM ---");
1350 wxTimeSpan span
= date
- ldcm
;
1352 int daysfromlast
= span
.GetDays();
1354 wxLogDebug("daysfromlast: %i", daysfromlast
);
1356 if ( daysfromlast
+ lastday
> 7 ) // past week boundary
1358 int wholeweeks
= (daysfromlast
/ 7);
1359 *week
= wholeweeks
+ lastweek
;
1360 if ( (daysfromlast
- (7 * wholeweeks
) + lastday
) > 7 )
1380 wxLogDebug("--- GetDateCoord: (%s) = (%i, %i) ---", date
.Format("%d %m %Y"), *day
, *week
);
1386 // ----------------------------------------------------------------------------
1388 // ----------------------------------------------------------------------------
1390 void wxCalendarCtrl::OnDClick(wxMouseEvent
& event
)
1392 if ( HitTest(event
.GetPosition()) != wxCAL_HITTEST_DAY
)
1398 GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
);
1402 void wxCalendarCtrl::OnClick(wxMouseEvent
& event
)
1405 wxDateTime::WeekDay wday
;
1406 switch ( HitTest(event
.GetPosition(), &date
, &wday
) )
1408 case wxCAL_HITTEST_DAY
:
1409 if ( IsDateInRange(date
) )
1413 GenerateEvents(wxEVT_CALENDAR_DAY_CHANGED
,
1414 wxEVT_CALENDAR_SEL_CHANGED
);
1418 case wxCAL_HITTEST_HEADER
:
1420 wxCalendarEvent
event(this, wxEVT_CALENDAR_WEEKDAY_CLICKED
);
1421 event
.m_wday
= wday
;
1422 (void)GetEventHandler()->ProcessEvent(event
);
1426 case wxCAL_HITTEST_DECMONTH
:
1427 case wxCAL_HITTEST_INCMONTH
:
1428 case wxCAL_HITTEST_SURROUNDING_WEEK
:
1429 SetDateAndNotify(date
); // we probably only want to refresh the control. No notification.. (maybe as an option?)
1433 wxFAIL_MSG(_T("unknown hittest code"));
1436 case wxCAL_HITTEST_NOWHERE
:
1442 wxCalendarHitTestResult
wxCalendarCtrl::HitTest(const wxPoint
& pos
,
1444 wxDateTime::WeekDay
*wd
)
1450 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1451 if ( (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
1455 // we need to find out if the hit is on left arrow, on month or on right arrow
1457 if ( wxRegion(m_leftArrowRect
).Contains(pos
) == wxInRegion
)
1461 if ( IsDateInRange(m_date
- wxDateSpan::Month()) )
1463 *date
= m_date
- wxDateSpan::Month();
1467 *date
= GetLowerDateLimit();
1471 return wxCAL_HITTEST_DECMONTH
;
1474 if ( wxRegion(m_rightArrowRect
).Contains(pos
) == wxInRegion
)
1478 if ( IsDateInRange(m_date
+ wxDateSpan::Month()) )
1480 *date
= m_date
+ wxDateSpan::Month();
1484 *date
= GetUpperDateLimit();
1488 return wxCAL_HITTEST_INCMONTH
;
1493 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1495 int wday
= pos
.x
/ m_widthCol
;
1496 // if ( y < m_heightRow )
1497 if ( y
< (m_heightRow
+ m_rowOffset
) )
1499 if ( y
> m_rowOffset
)
1503 if ( GetWindowStyle() & wxCAL_MONDAY_FIRST
)
1505 wday
= wday
== 6 ? 0 : wday
+ 1;
1508 *wd
= (wxDateTime::WeekDay
)wday
;
1511 return wxCAL_HITTEST_HEADER
;
1515 return wxCAL_HITTEST_NOWHERE
;
1519 // int week = (y - m_heightRow) / m_heightRow;
1520 int week
= (y
- (m_heightRow
+ m_rowOffset
)) / m_heightRow
;
1521 if ( week
>= 6 || wday
>= 7 )
1523 return wxCAL_HITTEST_NOWHERE
;
1526 wxDateTime dt
= GetStartDate() + wxDateSpan::Days(7*week
+ wday
);
1528 if ( IsDateShown(dt
) )
1533 if ( dt
.GetMonth() == m_date
.GetMonth() )
1536 return wxCAL_HITTEST_DAY
;
1540 return wxCAL_HITTEST_SURROUNDING_WEEK
;
1545 return wxCAL_HITTEST_NOWHERE
;
1549 // ----------------------------------------------------------------------------
1550 // subcontrols events handling
1551 // ----------------------------------------------------------------------------
1553 void wxCalendarCtrl::OnMonthChange(wxCommandEvent
& event
)
1555 wxDateTime::Tm tm
= m_date
.GetTm();
1557 wxDateTime::Month mon
= (wxDateTime::Month
)event
.GetInt();
1558 if ( tm
.mday
> wxDateTime::GetNumberOfDays(mon
, tm
.year
) )
1560 tm
.mday
= wxDateTime::GetNumberOfDays(mon
, tm
.year
);
1563 wxDateTime target
= wxDateTime(tm
.mday
, mon
, tm
.year
);
1565 ChangeMonth(&target
);
1566 SetDateAndNotify(target
);
1569 void wxCalendarCtrl::OnYearChange(wxCommandEvent
& event
)
1571 int year
= (int)event
.GetInt();
1572 if ( year
== INT_MIN
)
1574 // invalid year in the spin control, ignore it
1578 wxDateTime::Tm tm
= m_date
.GetTm();
1580 if ( tm
.mday
> wxDateTime::GetNumberOfDays(tm
.mon
, year
) )
1582 tm
.mday
= wxDateTime::GetNumberOfDays(tm
.mon
, year
);
1585 wxDateTime target
= wxDateTime(tm
.mday
, tm
.mon
, year
);
1587 if ( ChangeYear(&target
) )
1589 SetDateAndNotify(target
);
1593 // In this case we don't want to change the date. That would put us
1594 // inside the same year but a strange number of months forward/back..
1595 m_spinYear
->SetValue(target
.GetYear());
1599 // ----------------------------------------------------------------------------
1600 // keyboard interface
1601 // ----------------------------------------------------------------------------
1603 void wxCalendarCtrl::OnChar(wxKeyEvent
& event
)
1606 switch ( event
.GetKeyCode() )
1610 target
= m_date
+ wxDateSpan::Year();
1611 if ( ChangeYear(&target
) )
1613 SetDateAndNotify(target
);
1619 target
= m_date
- wxDateSpan::Year();
1620 if ( ChangeYear(&target
) )
1622 SetDateAndNotify(target
);
1627 target
= m_date
- wxDateSpan::Month();
1628 ChangeMonth(&target
);
1629 SetDateAndNotify(target
); // always
1633 target
= m_date
+ wxDateSpan::Month();
1634 ChangeMonth(&target
);
1635 SetDateAndNotify(target
); // always
1639 if ( event
.ControlDown() )
1641 target
= wxDateTime(m_date
).SetToNextWeekDay(
1642 GetWindowStyle() & wxCAL_MONDAY_FIRST
1643 ? wxDateTime::Sun
: wxDateTime::Sat
);
1644 if ( !IsDateInRange(target
) )
1646 target
= GetUpperDateLimit();
1648 SetDateAndNotify(target
);
1651 SetDateAndNotify(m_date
+ wxDateSpan::Day());
1655 if ( event
.ControlDown() )
1657 target
= wxDateTime(m_date
).SetToPrevWeekDay(
1658 GetWindowStyle() & wxCAL_MONDAY_FIRST
1659 ? wxDateTime::Mon
: wxDateTime::Sun
);
1660 if ( !IsDateInRange(target
) )
1662 target
= GetLowerDateLimit();
1664 SetDateAndNotify(target
);
1667 SetDateAndNotify(m_date
- wxDateSpan::Day());
1671 SetDateAndNotify(m_date
- wxDateSpan::Week());
1675 SetDateAndNotify(m_date
+ wxDateSpan::Week());
1679 if ( event
.ControlDown() )
1680 SetDateAndNotify(wxDateTime::Today());
1682 SetDateAndNotify(wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear()));
1686 SetDateAndNotify(wxDateTime(m_date
).SetToLastMonthDay());
1690 GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
);
1698 // ----------------------------------------------------------------------------
1699 // holidays handling
1700 // ----------------------------------------------------------------------------
1702 void wxCalendarCtrl::EnableHolidayDisplay(bool display
)
1704 long style
= GetWindowStyle();
1706 style
|= wxCAL_SHOW_HOLIDAYS
;
1708 style
&= ~wxCAL_SHOW_HOLIDAYS
;
1710 SetWindowStyle(style
);
1715 ResetHolidayAttrs();
1720 void wxCalendarCtrl::SetHolidayAttrs()
1722 if ( GetWindowStyle() & wxCAL_SHOW_HOLIDAYS
)
1724 ResetHolidayAttrs();
1726 wxDateTime::Tm tm
= m_date
.GetTm();
1727 wxDateTime
dtStart(1, tm
.mon
, tm
.year
),
1728 dtEnd
= dtStart
.GetLastMonthDay();
1730 wxDateTimeArray hol
;
1731 wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart
, dtEnd
, hol
);
1733 size_t count
= hol
.GetCount();
1734 for ( size_t n
= 0; n
< count
; n
++ )
1736 SetHoliday(hol
[n
].GetDay());
1741 void wxCalendarCtrl::SetHoliday(size_t day
)
1743 wxCHECK_RET( day
> 0 && day
< 32, _T("invalid day in SetHoliday") );
1745 wxCalendarDateAttr
*attr
= GetAttr(day
);
1748 attr
= new wxCalendarDateAttr
;
1751 attr
->SetHoliday(TRUE
);
1753 // can't use SetAttr() because it would delete this pointer
1754 m_attrs
[day
- 1] = attr
;
1757 void wxCalendarCtrl::ResetHolidayAttrs()
1759 for ( size_t day
= 0; day
< 31; day
++ )
1763 m_attrs
[day
]->SetHoliday(FALSE
);
1768 // ----------------------------------------------------------------------------
1770 // ----------------------------------------------------------------------------
1772 void wxCalendarEvent::Init()
1774 m_wday
= wxDateTime::Inv_WeekDay
;
1777 wxCalendarEvent::wxCalendarEvent(wxCalendarCtrl
*cal
, wxEventType type
)
1778 : wxCommandEvent(type
, cal
->GetId())
1780 m_date
= cal
->GetDate();
1781 SetEventObject(cal
);
1784 #endif // wxUSE_CALENDARCTRL