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 // ----------------------------------------------------------------------------
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
) { m_cal
->OnYearChange(event
); }
72 void OnYearChange(wxSpinEvent
& event
) { m_cal
->OnYearChange(event
); }
75 wxCalendarCtrl
*m_cal
;
78 DECLARE_NO_COPY_CLASS(wxYearSpinCtrl
)
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 BEGIN_EVENT_TABLE(wxCalendarCtrl
, wxControl
)
86 EVT_PAINT(wxCalendarCtrl::OnPaint
)
88 EVT_CHAR(wxCalendarCtrl::OnChar
)
90 EVT_LEFT_DOWN(wxCalendarCtrl::OnClick
)
91 EVT_LEFT_DCLICK(wxCalendarCtrl::OnDClick
)
94 BEGIN_EVENT_TABLE(wxMonthComboBox
, wxComboBox
)
95 EVT_COMBOBOX(-1, wxMonthComboBox::OnMonthChange
)
98 BEGIN_EVENT_TABLE(wxYearSpinCtrl
, wxSpinCtrl
)
99 EVT_TEXT(-1, wxYearSpinCtrl::OnYearTextChange
)
100 EVT_SPINCTRL(-1, wxYearSpinCtrl::OnYearChange
)
103 IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl
, wxControl
)
104 IMPLEMENT_DYNAMIC_CLASS(wxCalendarEvent
, wxCommandEvent
)
106 // ----------------------------------------------------------------------------
108 // ----------------------------------------------------------------------------
110 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_SEL_CHANGED
)
111 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_DAY_CHANGED
)
112 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_MONTH_CHANGED
)
113 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_YEAR_CHANGED
)
114 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_DOUBLECLICKED
)
115 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_WEEKDAY_CLICKED
)
117 // ============================================================================
119 // ============================================================================
121 // ----------------------------------------------------------------------------
122 // wxMonthComboBox and wxYearSpinCtrl
123 // ----------------------------------------------------------------------------
125 wxMonthComboBox::wxMonthComboBox(wxCalendarCtrl
*cal
)
126 : wxComboBox(cal
->GetParent(), -1,
131 wxCB_READONLY
| wxCLIP_SIBLINGS
)
136 for ( m
= wxDateTime::Jan
; m
< wxDateTime::Inv_Month
; wxNextMonth(m
) )
138 Append(wxDateTime::GetMonthName(m
));
141 SetSelection(m_cal
->GetDate().GetMonth());
142 SetSize(-1, -1, -1, -1, wxSIZE_AUTO_WIDTH
|wxSIZE_AUTO_HEIGHT
);
145 wxYearSpinCtrl::wxYearSpinCtrl(wxCalendarCtrl
*cal
)
146 : wxSpinCtrl(cal
->GetParent(), -1,
147 cal
->GetDate().Format(_T("%Y")),
150 wxSP_ARROW_KEYS
| wxCLIP_SIBLINGS
,
151 -4300, 10000, cal
->GetDate().GetYear())
157 // ----------------------------------------------------------------------------
159 // ----------------------------------------------------------------------------
161 wxCalendarCtrl::wxCalendarCtrl(wxWindow
*parent
,
163 const wxDateTime
& date
,
167 const wxString
& name
)
171 (void)Create(parent
, id
, date
, pos
, size
, style
, name
);
174 void wxCalendarCtrl::Init()
179 m_userChangedYear
= FALSE
;
184 wxDateTime::WeekDay wd
;
185 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
187 m_weekdays
[wd
] = wxDateTime::GetWeekDayName(wd
, wxDateTime::Name_Abbr
);
190 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
195 m_colHighlightFg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
196 m_colHighlightBg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
198 m_colHolidayFg
= *wxRED
;
199 // don't set m_colHolidayBg - by default, same as our bg colour
201 m_colHeaderFg
= *wxBLUE
;
202 m_colHeaderBg
= *wxLIGHT_GREY
;
205 bool wxCalendarCtrl::Create(wxWindow
*parent
,
207 const wxDateTime
& date
,
211 const wxString
& name
)
213 if ( !wxControl::Create(parent
, id
, pos
, size
,
214 style
| wxCLIP_CHILDREN
| wxWANTS_CHARS
,
215 wxDefaultValidator
, name
) )
220 // needed to get the arrow keys normally used for the dialog navigation
221 SetWindowStyle(style
| wxWANTS_CHARS
);
223 m_date
= date
.IsValid() ? date
: wxDateTime::Today();
225 m_lowdate
= wxDefaultDateTime
;
226 m_highdate
= wxDefaultDateTime
;
228 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
230 m_spinYear
= new wxYearSpinCtrl(this);
231 m_staticYear
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%Y")),
232 wxDefaultPosition
, wxDefaultSize
,
235 m_comboMonth
= new wxMonthComboBox(this);
236 m_staticMonth
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%B")),
237 wxDefaultPosition
, wxDefaultSize
,
241 ShowCurrentControls();
244 if ( size
.x
== -1 || size
.y
== -1 )
246 sizeReal
= DoGetBestSize();
257 // we need to set the position as well because the main control position
258 // is not the same as the one specified in pos if we have the controls
260 SetSize(pos
.x
, pos
.y
, sizeReal
.x
, sizeReal
.y
);
262 SetBackgroundColour(*wxWHITE
);
263 SetFont(*wxSWISS_FONT
);
270 wxCalendarCtrl::~wxCalendarCtrl()
272 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
278 // ----------------------------------------------------------------------------
279 // forward wxWin functions to subcontrols
280 // ----------------------------------------------------------------------------
282 bool wxCalendarCtrl::Destroy()
285 m_staticYear
->Destroy();
287 m_spinYear
->Destroy();
289 m_comboMonth
->Destroy();
291 m_staticMonth
->Destroy();
296 m_staticMonth
= NULL
;
298 return wxControl::Destroy();
301 bool wxCalendarCtrl::Show(bool show
)
303 if ( !wxControl::Show(show
) )
308 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
310 if ( GetMonthControl() )
312 GetMonthControl()->Show(show
);
313 GetYearControl()->Show(show
);
320 bool wxCalendarCtrl::Enable(bool enable
)
322 if ( !wxControl::Enable(enable
) )
327 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
329 GetMonthControl()->Enable(enable
);
330 GetYearControl()->Enable(enable
);
336 // ----------------------------------------------------------------------------
337 // enable/disable month/year controls
338 // ----------------------------------------------------------------------------
340 void wxCalendarCtrl::ShowCurrentControls()
342 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
344 if ( AllowMonthChange() )
346 m_comboMonth
->Show();
347 m_staticMonth
->Hide();
349 if ( AllowYearChange() )
352 m_staticYear
->Hide();
360 m_comboMonth
->Hide();
361 m_staticMonth
->Show();
364 // year change not allowed here
366 m_staticYear
->Show();
370 wxControl
*wxCalendarCtrl::GetMonthControl() const
372 return AllowMonthChange() ? (wxControl
*)m_comboMonth
: (wxControl
*)m_staticMonth
;
375 wxControl
*wxCalendarCtrl::GetYearControl() const
377 return AllowYearChange() ? (wxControl
*)m_spinYear
: (wxControl
*)m_staticYear
;
380 void wxCalendarCtrl::EnableYearChange(bool enable
)
382 if ( enable
!= AllowYearChange() )
384 long style
= GetWindowStyle();
386 style
&= ~wxCAL_NO_YEAR_CHANGE
;
388 style
|= wxCAL_NO_YEAR_CHANGE
;
389 SetWindowStyle(style
);
391 ShowCurrentControls();
392 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
399 void wxCalendarCtrl::EnableMonthChange(bool enable
)
401 if ( enable
!= AllowMonthChange() )
403 long style
= GetWindowStyle();
405 style
&= ~wxCAL_NO_MONTH_CHANGE
;
407 style
|= wxCAL_NO_MONTH_CHANGE
;
408 SetWindowStyle(style
);
410 ShowCurrentControls();
411 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
418 // ----------------------------------------------------------------------------
420 // ----------------------------------------------------------------------------
422 bool wxCalendarCtrl::SetDate(const wxDateTime
& date
)
426 bool sameMonth
= m_date
.GetMonth() == date
.GetMonth(),
427 sameYear
= m_date
.GetYear() == date
.GetYear();
429 if ( IsDateInRange(date
) )
431 if ( sameMonth
&& sameYear
)
433 // just change the day
438 if ( AllowMonthChange() && (AllowYearChange() || sameYear
) )
443 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
445 // update the controls
446 m_comboMonth
->SetSelection(m_date
.GetMonth());
448 if ( AllowYearChange() )
450 if ( !m_userChangedYear
)
451 m_spinYear
->SetValue(m_date
.Format(_T("%Y")));
452 else // don't overwrite what the user typed in
453 m_userChangedYear
= FALSE
;
457 // as the month changed, holidays did too
460 // update the calendar
474 void wxCalendarCtrl::ChangeDay(const wxDateTime
& date
)
476 if ( m_date
!= date
)
478 // we need to refresh the row containing the old date and the one
479 // containing the new one
480 wxDateTime dateOld
= m_date
;
483 RefreshDate(dateOld
);
485 // if the date is in the same row, it was already drawn correctly
486 if ( GetWeek(m_date
) != GetWeek(dateOld
) )
493 void wxCalendarCtrl::SetDateAndNotify(const wxDateTime
& date
)
495 wxDateTime::Tm tm1
= m_date
.GetTm(),
499 if ( tm1
.year
!= tm2
.year
)
500 type
= wxEVT_CALENDAR_YEAR_CHANGED
;
501 else if ( tm1
.mon
!= tm2
.mon
)
502 type
= wxEVT_CALENDAR_MONTH_CHANGED
;
503 else if ( tm1
.mday
!= tm2
.mday
)
504 type
= wxEVT_CALENDAR_DAY_CHANGED
;
510 GenerateEvents(type
, wxEVT_CALENDAR_SEL_CHANGED
);
514 // ----------------------------------------------------------------------------
516 // ----------------------------------------------------------------------------
518 bool wxCalendarCtrl::SetLowerDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
522 if ( !(date
.IsValid()) || ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) )
534 bool wxCalendarCtrl::SetUpperDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
538 if ( !(date
.IsValid()) || ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
) )
550 bool wxCalendarCtrl::SetDateRange(const wxDateTime
& lowerdate
/* = wxDefaultDateTime */, const wxDateTime
& upperdate
/* = wxDefaultDateTime */)
555 ( !( lowerdate
.IsValid() ) || ( ( upperdate
.IsValid() ) ? ( lowerdate
<= upperdate
) : TRUE
) ) &&
556 ( !( upperdate
.IsValid() ) || ( ( lowerdate
.IsValid() ) ? ( upperdate
>= lowerdate
) : TRUE
) ) )
558 m_lowdate
= lowerdate
;
559 m_highdate
= upperdate
;
569 // ----------------------------------------------------------------------------
571 // ----------------------------------------------------------------------------
573 wxDateTime
wxCalendarCtrl::GetStartDate() const
575 wxDateTime::Tm tm
= m_date
.GetTm();
577 wxDateTime date
= wxDateTime(1, tm
.mon
, tm
.year
);
580 date
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
581 ? wxDateTime::Mon
: wxDateTime::Sun
);
583 if ( GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
)
585 // We want to offset the calendar if we start on the first..
586 if ( date
.GetDay() == 1 )
588 date
-= wxDateSpan::Week();
595 bool wxCalendarCtrl::IsDateShown(const wxDateTime
& date
) const
597 if ( !(GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
599 return date
.GetMonth() == m_date
.GetMonth();
607 bool wxCalendarCtrl::IsDateInRange(const wxDateTime
& date
) const
610 // Check if the given date is in the range specified
611 retval
= ( ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
)
612 && ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) );
616 bool wxCalendarCtrl::ChangeYear(wxDateTime
* target
) const
620 if ( !(IsDateInRange(*target
)) )
622 if ( target
->GetYear() < m_date
.GetYear() )
624 if ( target
->GetYear() >= GetLowerDateLimit().GetYear() )
626 *target
= GetLowerDateLimit();
636 if ( target
->GetYear() <= GetUpperDateLimit().GetYear() )
638 *target
= GetUpperDateLimit();
655 bool wxCalendarCtrl::ChangeMonth(wxDateTime
* target
) const
659 if ( !(IsDateInRange(*target
)) )
663 if ( target
->GetMonth() < m_date
.GetMonth() )
665 *target
= GetLowerDateLimit();
669 *target
= GetUpperDateLimit();
676 size_t wxCalendarCtrl::GetWeek(const wxDateTime
& date
) const
678 size_t retval
= date
.GetWeekOfMonth(GetWindowStyle() & wxCAL_MONDAY_FIRST
679 ? wxDateTime::Monday_First
680 : wxDateTime::Sunday_First
);
682 if ( (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
684 // we need to offset an extra week if we "start" on the 1st of the month
685 wxDateTime::Tm tm
= date
.GetTm();
687 wxDateTime datetest
= wxDateTime(1, tm
.mon
, tm
.year
);
690 datetest
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
691 ? wxDateTime::Mon
: wxDateTime::Sun
);
693 if ( datetest
.GetDay() == 1 )
702 // ----------------------------------------------------------------------------
704 // ----------------------------------------------------------------------------
706 // this is a composite control and it must arrange its parts each time its
707 // size or position changes: the combobox and spinctrl are along the top of
708 // the available area and the calendar takes up therest of the space
710 // the static controls are supposed to be always smaller than combo/spin so we
711 // always use the latter for size calculations and position the static to take
714 // the constants used for the layout
715 #define VERT_MARGIN 5 // distance between combo and calendar
717 #define HORZ_MARGIN 5 // spin
719 #define HORZ_MARGIN 15 // spin
721 wxSize
wxCalendarCtrl::DoGetBestSize() const
723 // calc the size of the calendar
724 ((wxCalendarCtrl
*)this)->RecalcGeometry(); // const_cast
726 wxCoord width
= 7*m_widthCol
,
727 height
= 7*m_heightRow
+ m_rowOffset
+ VERT_MARGIN
;
729 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
731 // the combobox doesn't report its height correctly (it returns the
732 // height including the drop down list) so don't use it
733 height
+= m_spinYear
->GetBestSize().y
;
736 if ( !HasFlag(wxBORDER_NONE
) )
738 // the border would clip the last line otherwise
743 return wxSize(width
, height
);
746 void wxCalendarCtrl::DoSetSize(int x
, int y
,
747 int width
, int height
,
750 wxControl::DoSetSize(x
, y
, width
, height
, sizeFlags
);
753 void wxCalendarCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
757 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
759 wxSize sizeCombo
= m_comboMonth
->GetSize();
760 wxSize sizeStatic
= m_staticMonth
->GetSize();
761 wxSize sizeSpin
= m_spinYear
->GetSize();
762 int dy
= (sizeCombo
.y
- sizeStatic
.y
) / 2;
764 In the calender the size of the combobox for the year
765 is just defined by a margin from the month combobox to
766 the left border. While in wxUniv the year control can't
767 show all 4 digits, in wxMsw it show almost twice as
768 much. Instead the year should use it's best size and be
769 left aligned to the calendar. Just in case the month in
770 any language is longer than it has space in the
771 calendar it is shortend.This way the year always can
774 This patch relies on the fact that a combobox has a
775 good best size implementation. This is not the case
776 with wxMSW but I don't know why.
781 #ifdef __WXUNIVERSAL__
782 if (sizeCombo
.x
+ HORZ_MARGIN
- sizeSpin
.x
> width
)
784 m_comboMonth
->SetSize(x
, y
, width
- HORZ_MARGIN
- sizeSpin
.x
, sizeCombo
.y
);
788 m_comboMonth
->Move(x
, y
);
790 m_staticMonth
->Move(x
, y
+ dy
);
791 m_spinYear
->Move(x
+ width
- sizeSpin
.x
, y
);
792 m_staticYear
->Move(x
+ width
- sizeSpin
.x
, y
+ dy
);
794 m_comboMonth
->Move(x
, y
);
795 m_staticMonth
->SetSize(x
, y
+ dy
, sizeCombo
.x
, sizeStatic
.y
);
797 int xDiff
= sizeCombo
.x
+ HORZ_MARGIN
;
799 m_spinYear
->SetSize(x
+ xDiff
, y
, width
- xDiff
, sizeCombo
.y
);
800 m_staticYear
->SetSize(x
+ xDiff
, y
+ dy
, width
- xDiff
, sizeStatic
.y
);
802 yDiff
= wxMax(sizeSpin
.y
, sizeCombo
.y
) + VERT_MARGIN
;
804 else // no controls on the top
809 wxControl::DoMoveWindow(x
, y
+ yDiff
, width
, height
- yDiff
);
812 void wxCalendarCtrl::DoGetPosition(int *x
, int *y
) const
814 wxControl::DoGetPosition(x
, y
);
816 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
818 // our real top corner is not in this position
821 *y
-= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
826 void wxCalendarCtrl::DoGetSize(int *width
, int *height
) const
828 wxControl::DoGetSize(width
, height
);
830 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
832 // our real height is bigger
833 if ( height
&& GetMonthControl())
835 *height
+= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
840 void wxCalendarCtrl::RecalcGeometry()
842 if ( m_widthCol
!= 0 )
849 // determine the column width (we assume that the weekday names are always
850 // wider (in any language) than the numbers)
852 wxDateTime::WeekDay wd
;
853 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
856 dc
.GetTextExtent(m_weekdays
[wd
], &width
, &m_heightRow
);
857 if ( width
> m_widthCol
)
863 // leave some margins
867 m_rowOffset
= (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) ? m_heightRow
: 0; // conditional in relation to style
870 // ----------------------------------------------------------------------------
872 // ----------------------------------------------------------------------------
874 void wxCalendarCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
883 wxLogDebug("--- starting to paint, selection: %s, week %u\n",
884 m_date
.Format("%a %d-%m-%Y %H:%M:%S").c_str(),
890 if ( HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
892 // draw the sequential month-selector
894 dc
.SetBackgroundMode(wxTRANSPARENT
);
895 dc
.SetTextForeground(*wxBLACK
);
896 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
897 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
898 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
900 // Get extent of month-name + year
901 wxCoord monthw
, monthh
;
902 wxString headertext
= m_date
.Format(wxT("%B %Y"));
903 dc
.GetTextExtent(headertext
, &monthw
, &monthh
);
905 // draw month-name centered above weekdays
906 wxCoord monthx
= ((m_widthCol
* 7) - monthw
) / 2;
907 wxCoord monthy
= ((m_heightRow
- monthh
) / 2) + y
;
908 dc
.DrawText(headertext
, monthx
, monthy
);
910 // calculate the "month-arrows"
911 wxPoint leftarrow
[3];
912 wxPoint rightarrow
[3];
914 int arrowheight
= monthh
/ 2;
916 leftarrow
[0] = wxPoint(0, arrowheight
/ 2);
917 leftarrow
[1] = wxPoint(arrowheight
/ 2, 0);
918 leftarrow
[2] = wxPoint(arrowheight
/ 2, arrowheight
- 1);
920 rightarrow
[0] = wxPoint(0, 0);
921 rightarrow
[1] = wxPoint(arrowheight
/ 2, arrowheight
/ 2);
922 rightarrow
[2] = wxPoint(0, arrowheight
- 1);
924 // draw the "month-arrows"
926 wxCoord arrowy
= (m_heightRow
- arrowheight
) / 2;
927 wxCoord larrowx
= (m_widthCol
- (arrowheight
/ 2)) / 2;
928 wxCoord rarrowx
= ((m_widthCol
- (arrowheight
/ 2)) / 2) + m_widthCol
*6;
929 m_leftArrowRect
= wxRect(0, 0, 0, 0);
930 m_rightArrowRect
= wxRect(0, 0, 0, 0);
932 if ( AllowMonthChange() )
934 wxDateTime ldpm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) - wxDateSpan::Day(); // last day prev month
935 // Check if range permits change
936 if ( IsDateInRange(ldpm
) && ( ( ldpm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
938 m_leftArrowRect
= wxRect(larrowx
- 3, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
939 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
940 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
941 dc
.DrawPolygon(3, leftarrow
, larrowx
, arrowy
, wxWINDING_RULE
);
942 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
943 dc
.DrawRectangle(m_leftArrowRect
);
945 wxDateTime fdnm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) + wxDateSpan::Month(); // first day next month
946 if ( IsDateInRange(fdnm
) && ( ( fdnm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
948 m_rightArrowRect
= wxRect(rarrowx
- 4, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
949 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
950 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
951 dc
.DrawPolygon(3, rightarrow
, rarrowx
, arrowy
, wxWINDING_RULE
);
952 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
953 dc
.DrawRectangle(m_rightArrowRect
);
960 // first draw the week days
961 if ( IsExposed(0, y
, 7*m_widthCol
, m_heightRow
) )
964 wxLogDebug("painting the header");
967 dc
.SetBackgroundMode(wxTRANSPARENT
);
968 dc
.SetTextForeground(m_colHeaderFg
);
969 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
970 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
971 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
973 bool startOnMonday
= (GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
974 for ( size_t wd
= 0; wd
< 7; wd
++ )
978 n
= wd
== 6 ? 0 : wd
+ 1;
982 dc
.GetTextExtent(m_weekdays
[n
], &dayw
, &dayh
);
983 dc
.DrawText(m_weekdays
[n
], (wd
*m_widthCol
) + ((m_widthCol
- dayw
) / 2), y
); // center the day-name
987 // then the calendar itself
988 dc
.SetTextForeground(*wxBLACK
);
989 //dc.SetFont(*wxNORMAL_FONT);
992 wxDateTime date
= GetStartDate();
995 wxLogDebug("starting calendar from %s\n",
996 date
.Format("%a %d-%m-%Y %H:%M:%S").c_str());
999 dc
.SetBackgroundMode(wxSOLID
);
1000 for ( size_t nWeek
= 1; nWeek
<= 6; nWeek
++, y
+= m_heightRow
)
1002 // if the update region doesn't intersect this row, don't paint it
1003 if ( !IsExposed(0, y
, 7*m_widthCol
, m_heightRow
- 1) )
1005 date
+= wxDateSpan::Week();
1011 wxLogDebug("painting week %d at y = %d\n", nWeek
, y
);
1014 for ( size_t wd
= 0; wd
< 7; wd
++ )
1016 if ( IsDateShown(date
) )
1018 // don't use wxDate::Format() which prepends 0s
1019 unsigned int day
= date
.GetDay();
1020 wxString dayStr
= wxString::Format(_T("%u"), day
);
1022 dc
.GetTextExtent(dayStr
, &width
, (wxCoord
*)NULL
);
1024 bool changedColours
= FALSE
,
1025 changedFont
= FALSE
;
1028 wxCalendarDateAttr
*attr
= NULL
;
1030 if ( date
.GetMonth() != m_date
.GetMonth() || !IsDateInRange(date
) )
1032 // surrounding week or out-of-range
1034 dc
.SetTextForeground(*wxLIGHT_GREY
);
1035 changedColours
= TRUE
;
1039 isSel
= date
.IsSameDate(m_date
);
1040 attr
= m_attrs
[day
- 1];
1044 dc
.SetTextForeground(m_colHighlightFg
);
1045 dc
.SetTextBackground(m_colHighlightBg
);
1047 changedColours
= TRUE
;
1051 wxColour colFg
, colBg
;
1053 if ( attr
->IsHoliday() )
1055 colFg
= m_colHolidayFg
;
1056 colBg
= m_colHolidayBg
;
1060 colFg
= attr
->GetTextColour();
1061 colBg
= attr
->GetBackgroundColour();
1066 dc
.SetTextForeground(colFg
);
1067 changedColours
= TRUE
;
1072 dc
.SetTextBackground(colBg
);
1073 changedColours
= TRUE
;
1076 if ( attr
->HasFont() )
1078 dc
.SetFont(attr
->GetFont());
1084 wxCoord x
= wd
*m_widthCol
+ (m_widthCol
- width
) / 2;
1085 dc
.DrawText(dayStr
, x
, y
+ 1);
1087 if ( !isSel
&& attr
&& attr
->HasBorder() )
1090 if ( attr
->HasBorderColour() )
1092 colBorder
= attr
->GetBorderColour();
1096 colBorder
= m_foregroundColour
;
1099 wxPen
pen(colBorder
, 1, wxSOLID
);
1101 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1103 switch ( attr
->GetBorder() )
1105 case wxCAL_BORDER_SQUARE
:
1106 dc
.DrawRectangle(x
- 2, y
,
1107 width
+ 4, m_heightRow
);
1110 case wxCAL_BORDER_ROUND
:
1111 dc
.DrawEllipse(x
- 2, y
,
1112 width
+ 4, m_heightRow
);
1116 wxFAIL_MSG(_T("unknown border type"));
1120 if ( changedColours
)
1122 dc
.SetTextForeground(m_foregroundColour
);
1123 dc
.SetTextBackground(m_backgroundColour
);
1131 //else: just don't draw it
1133 date
+= wxDateSpan::Day();
1137 // Greying out out-of-range background
1138 bool showSurrounding
= (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) != 0;
1140 date
= ( showSurrounding
) ? GetStartDate() : wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear());
1141 if ( !IsDateInRange(date
) )
1143 wxDateTime firstOOR
= GetLowerDateLimit() - wxDateSpan::Day(); // first out-of-range
1145 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1146 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1148 HighlightRange(&dc
, date
, firstOOR
, wxTRANSPARENT_PEN
, &oorbrush
);
1151 date
= ( showSurrounding
) ? GetStartDate() + wxDateSpan::Weeks(6) - wxDateSpan::Day() : wxDateTime().SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear());
1152 if ( !IsDateInRange(date
) )
1154 wxDateTime firstOOR
= GetUpperDateLimit() + wxDateSpan::Day(); // first out-of-range
1156 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1157 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1159 HighlightRange(&dc
, firstOOR
, date
, wxTRANSPARENT_PEN
, &oorbrush
);
1163 wxLogDebug("+++ finished painting");
1167 void wxCalendarCtrl::RefreshDate(const wxDateTime
& date
)
1173 // always refresh the whole row at once because our OnPaint() will draw
1174 // the whole row anyhow - and this allows the small optimisation in
1175 // OnClick() below to work
1178 rect
.y
= (m_heightRow
* GetWeek(date
)) + m_rowOffset
;
1180 rect
.width
= 7*m_widthCol
;
1181 rect
.height
= m_heightRow
;
1184 // VZ: for some reason, the selected date seems to occupy more space under
1185 // MSW - this is probably some bug in the font size calculations, but I
1186 // don't know where exactly. This fix is ugly and leads to more
1187 // refreshes than really needed, but without it the selected days
1188 // leaves even more ugly underscores on screen.
1193 wxLogDebug("*** refreshing week %d at (%d, %d)-(%d, %d)\n",
1196 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1199 Refresh(TRUE
, &rect
);
1202 void wxCalendarCtrl::HighlightRange(wxPaintDC
* pDC
, const wxDateTime
& fromdate
, const wxDateTime
& todate
, wxPen
* pPen
, wxBrush
* pBrush
)
1204 // Highlights the given range using pen and brush
1205 // Does nothing if todate < fromdate
1209 wxLogDebug("+++ HighlightRange: (%s) - (%s) +++", fromdate
.Format("%d %m %Y"), todate
.Format("%d %m %Y"));
1212 if ( todate
>= fromdate
)
1219 // implicit: both dates must be currently shown - checked by GetDateCoord
1220 if ( GetDateCoord(fromdate
, &fd
, &fw
) && GetDateCoord(todate
, &td
, &tw
) )
1223 wxLogDebug("Highlight range: (%i, %i) - (%i, %i)", fd
, fw
, td
, tw
);
1225 if ( ( (tw
- fw
) == 1 ) && ( td
< fd
) )
1227 // special case: interval 7 days or less not in same week
1228 // split in two seperate intervals
1229 wxDateTime tfd
= fromdate
+ wxDateSpan::Days(7-fd
);
1230 wxDateTime ftd
= tfd
+ wxDateSpan::Day();
1232 wxLogDebug("Highlight: Seperate segments");
1235 HighlightRange(pDC
, fromdate
, tfd
, pPen
, pBrush
);
1236 HighlightRange(pDC
, ftd
, todate
, pPen
, pBrush
);
1241 wxPoint corners
[8]; // potentially 8 corners in polygon
1245 // simple case: same week
1247 corners
[0] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
);
1248 corners
[1] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1 ) * m_heightRow
) + m_rowOffset
);
1249 corners
[2] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
);
1250 corners
[3] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
);
1255 // "complex" polygon
1256 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1260 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1261 corners
[cidx
] = wxPoint(0, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1264 corners
[cidx
] = wxPoint(0, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1265 corners
[cidx
] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1269 corners
[cidx
] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1270 corners
[cidx
] = wxPoint(7 * m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1273 corners
[cidx
] = wxPoint(7 * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1279 pDC
->SetBrush(*pBrush
);
1281 pDC
->DrawPolygon(numpoints
, corners
);
1287 wxLogDebug("--- HighlightRange ---");
1291 bool wxCalendarCtrl::GetDateCoord(const wxDateTime
& date
, int *day
, int *week
) const
1296 wxLogDebug("+++ GetDateCoord: (%s) +++", date
.Format("%d %m %Y"));
1299 if ( IsDateShown(date
) )
1301 bool startOnMonday
= ( GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
1304 *day
= date
.GetWeekDay();
1306 if ( *day
== 0 ) // sunday
1308 *day
= ( startOnMonday
) ? 7 : 1;
1312 day
+= ( startOnMonday
) ? 0 : 1;
1315 int targetmonth
= date
.GetMonth() + (12 * date
.GetYear());
1316 int thismonth
= m_date
.GetMonth() + (12 * m_date
.GetYear());
1319 if ( targetmonth
== thismonth
)
1321 *week
= GetWeek(date
);
1325 if ( targetmonth
< thismonth
)
1327 *week
= 1; // trivial
1329 else // targetmonth > thismonth
1335 // get the datecoord of the last day in the month currently shown
1337 wxLogDebug(" +++ LDOM +++");
1339 GetDateCoord(ldcm
.SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear()), &lastday
, &lastweek
);
1341 wxLogDebug(" --- LDOM ---");
1344 wxTimeSpan span
= date
- ldcm
;
1346 int daysfromlast
= span
.GetDays();
1348 wxLogDebug("daysfromlast: %i", daysfromlast
);
1350 if ( daysfromlast
+ lastday
> 7 ) // past week boundary
1352 int wholeweeks
= (daysfromlast
/ 7);
1353 *week
= wholeweeks
+ lastweek
;
1354 if ( (daysfromlast
- (7 * wholeweeks
) + lastday
) > 7 )
1374 wxLogDebug("--- GetDateCoord: (%s) = (%i, %i) ---", date
.Format("%d %m %Y"), *day
, *week
);
1380 // ----------------------------------------------------------------------------
1382 // ----------------------------------------------------------------------------
1384 void wxCalendarCtrl::OnDClick(wxMouseEvent
& event
)
1386 if ( HitTest(event
.GetPosition()) != wxCAL_HITTEST_DAY
)
1392 GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
);
1396 void wxCalendarCtrl::OnClick(wxMouseEvent
& event
)
1399 wxDateTime::WeekDay wday
;
1400 switch ( HitTest(event
.GetPosition(), &date
, &wday
) )
1402 case wxCAL_HITTEST_DAY
:
1403 if ( IsDateInRange(date
) )
1407 GenerateEvents(wxEVT_CALENDAR_DAY_CHANGED
,
1408 wxEVT_CALENDAR_SEL_CHANGED
);
1412 case wxCAL_HITTEST_HEADER
:
1414 wxCalendarEvent
event(this, wxEVT_CALENDAR_WEEKDAY_CLICKED
);
1415 event
.m_wday
= wday
;
1416 (void)GetEventHandler()->ProcessEvent(event
);
1420 case wxCAL_HITTEST_DECMONTH
:
1421 case wxCAL_HITTEST_INCMONTH
:
1422 case wxCAL_HITTEST_SURROUNDING_WEEK
:
1423 SetDateAndNotify(date
); // we probably only want to refresh the control. No notification.. (maybe as an option?)
1427 wxFAIL_MSG(_T("unknown hittest code"));
1430 case wxCAL_HITTEST_NOWHERE
:
1436 wxCalendarHitTestResult
wxCalendarCtrl::HitTest(const wxPoint
& pos
,
1438 wxDateTime::WeekDay
*wd
)
1444 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1445 if ( (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
1449 // we need to find out if the hit is on left arrow, on month or on right arrow
1451 if ( wxRegion(m_leftArrowRect
).Contains(pos
) == wxInRegion
)
1455 if ( IsDateInRange(m_date
- wxDateSpan::Month()) )
1457 *date
= m_date
- wxDateSpan::Month();
1461 *date
= GetLowerDateLimit();
1465 return wxCAL_HITTEST_DECMONTH
;
1468 if ( wxRegion(m_rightArrowRect
).Contains(pos
) == wxInRegion
)
1472 if ( IsDateInRange(m_date
+ wxDateSpan::Month()) )
1474 *date
= m_date
+ wxDateSpan::Month();
1478 *date
= GetUpperDateLimit();
1482 return wxCAL_HITTEST_INCMONTH
;
1487 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1489 int wday
= pos
.x
/ m_widthCol
;
1490 // if ( y < m_heightRow )
1491 if ( y
< (m_heightRow
+ m_rowOffset
) )
1493 if ( y
> m_rowOffset
)
1497 if ( GetWindowStyle() & wxCAL_MONDAY_FIRST
)
1499 wday
= wday
== 6 ? 0 : wday
+ 1;
1502 *wd
= (wxDateTime::WeekDay
)wday
;
1505 return wxCAL_HITTEST_HEADER
;
1509 return wxCAL_HITTEST_NOWHERE
;
1513 // int week = (y - m_heightRow) / m_heightRow;
1514 int week
= (y
- (m_heightRow
+ m_rowOffset
)) / m_heightRow
;
1515 if ( week
>= 6 || wday
>= 7 )
1517 return wxCAL_HITTEST_NOWHERE
;
1520 wxDateTime dt
= GetStartDate() + wxDateSpan::Days(7*week
+ wday
);
1522 if ( IsDateShown(dt
) )
1527 if ( dt
.GetMonth() == m_date
.GetMonth() )
1530 return wxCAL_HITTEST_DAY
;
1534 return wxCAL_HITTEST_SURROUNDING_WEEK
;
1539 return wxCAL_HITTEST_NOWHERE
;
1543 // ----------------------------------------------------------------------------
1544 // subcontrols events handling
1545 // ----------------------------------------------------------------------------
1547 void wxCalendarCtrl::OnMonthChange(wxCommandEvent
& event
)
1549 wxDateTime::Tm tm
= m_date
.GetTm();
1551 wxDateTime::Month mon
= (wxDateTime::Month
)event
.GetInt();
1552 if ( tm
.mday
> wxDateTime::GetNumberOfDays(mon
, tm
.year
) )
1554 tm
.mday
= wxDateTime::GetNumberOfDays(mon
, tm
.year
);
1557 wxDateTime target
= wxDateTime(tm
.mday
, mon
, tm
.year
);
1559 ChangeMonth(&target
);
1560 SetDateAndNotify(target
);
1563 void wxCalendarCtrl::OnYearChange(wxCommandEvent
& event
)
1565 int year
= (int)event
.GetInt();
1566 if ( year
== INT_MIN
)
1568 // invalid year in the spin control, ignore it
1572 // set the flag for SetDate(): otherwise it would overwrite the year
1573 // typed in by the user
1574 m_userChangedYear
= TRUE
;
1576 wxDateTime::Tm tm
= m_date
.GetTm();
1578 if ( tm
.mday
> wxDateTime::GetNumberOfDays(tm
.mon
, year
) )
1580 tm
.mday
= wxDateTime::GetNumberOfDays(tm
.mon
, year
);
1583 wxDateTime target
= wxDateTime(tm
.mday
, tm
.mon
, year
);
1585 if ( ChangeYear(&target
) )
1587 SetDateAndNotify(target
);
1591 // In this case we don't want to change the date. That would put us
1592 // inside the same year but a strange number of months forward/back..
1593 m_spinYear
->SetValue(target
.GetYear());
1597 // ----------------------------------------------------------------------------
1598 // keyboard interface
1599 // ----------------------------------------------------------------------------
1601 void wxCalendarCtrl::OnChar(wxKeyEvent
& event
)
1604 switch ( event
.GetKeyCode() )
1608 target
= m_date
+ wxDateSpan::Year();
1609 if ( ChangeYear(&target
) )
1611 SetDateAndNotify(target
);
1617 target
= m_date
- wxDateSpan::Year();
1618 if ( ChangeYear(&target
) )
1620 SetDateAndNotify(target
);
1625 target
= m_date
- wxDateSpan::Month();
1626 ChangeMonth(&target
);
1627 SetDateAndNotify(target
); // always
1631 target
= m_date
+ wxDateSpan::Month();
1632 ChangeMonth(&target
);
1633 SetDateAndNotify(target
); // always
1637 if ( event
.ControlDown() )
1639 target
= wxDateTime(m_date
).SetToNextWeekDay(
1640 GetWindowStyle() & wxCAL_MONDAY_FIRST
1641 ? wxDateTime::Sun
: wxDateTime::Sat
);
1642 if ( !IsDateInRange(target
) )
1644 target
= GetUpperDateLimit();
1646 SetDateAndNotify(target
);
1649 SetDateAndNotify(m_date
+ wxDateSpan::Day());
1653 if ( event
.ControlDown() )
1655 target
= wxDateTime(m_date
).SetToPrevWeekDay(
1656 GetWindowStyle() & wxCAL_MONDAY_FIRST
1657 ? wxDateTime::Mon
: wxDateTime::Sun
);
1658 if ( !IsDateInRange(target
) )
1660 target
= GetLowerDateLimit();
1662 SetDateAndNotify(target
);
1665 SetDateAndNotify(m_date
- wxDateSpan::Day());
1669 SetDateAndNotify(m_date
- wxDateSpan::Week());
1673 SetDateAndNotify(m_date
+ wxDateSpan::Week());
1677 if ( event
.ControlDown() )
1678 SetDateAndNotify(wxDateTime::Today());
1680 SetDateAndNotify(wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear()));
1684 SetDateAndNotify(wxDateTime(m_date
).SetToLastMonthDay());
1688 GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
);
1696 // ----------------------------------------------------------------------------
1697 // holidays handling
1698 // ----------------------------------------------------------------------------
1700 void wxCalendarCtrl::EnableHolidayDisplay(bool display
)
1702 long style
= GetWindowStyle();
1704 style
|= wxCAL_SHOW_HOLIDAYS
;
1706 style
&= ~wxCAL_SHOW_HOLIDAYS
;
1708 SetWindowStyle(style
);
1713 ResetHolidayAttrs();
1718 void wxCalendarCtrl::SetHolidayAttrs()
1720 if ( GetWindowStyle() & wxCAL_SHOW_HOLIDAYS
)
1722 ResetHolidayAttrs();
1724 wxDateTime::Tm tm
= m_date
.GetTm();
1725 wxDateTime
dtStart(1, tm
.mon
, tm
.year
),
1726 dtEnd
= dtStart
.GetLastMonthDay();
1728 wxDateTimeArray hol
;
1729 wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart
, dtEnd
, hol
);
1731 size_t count
= hol
.GetCount();
1732 for ( size_t n
= 0; n
< count
; n
++ )
1734 SetHoliday(hol
[n
].GetDay());
1739 void wxCalendarCtrl::SetHoliday(size_t day
)
1741 wxCHECK_RET( day
> 0 && day
< 32, _T("invalid day in SetHoliday") );
1743 wxCalendarDateAttr
*attr
= GetAttr(day
);
1746 attr
= new wxCalendarDateAttr
;
1749 attr
->SetHoliday(TRUE
);
1751 // can't use SetAttr() because it would delete this pointer
1752 m_attrs
[day
- 1] = attr
;
1755 void wxCalendarCtrl::ResetHolidayAttrs()
1757 for ( size_t day
= 0; day
< 31; day
++ )
1761 m_attrs
[day
]->SetHoliday(FALSE
);
1766 // ----------------------------------------------------------------------------
1768 // ----------------------------------------------------------------------------
1770 void wxCalendarEvent::Init()
1772 m_wday
= wxDateTime::Inv_WeekDay
;
1775 wxCalendarEvent::wxCalendarEvent(wxCalendarCtrl
*cal
, wxEventType type
)
1776 : wxCommandEvent(type
, cal
->GetId())
1778 m_date
= cal
->GetDate();
1779 SetEventObject(cal
);
1782 #endif // wxUSE_CALENDARCTRL