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
)
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_userChangedYear
= FALSE
;
188 wxDateTime::WeekDay wd
;
189 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
191 m_weekdays
[wd
] = wxDateTime::GetWeekDayName(wd
, wxDateTime::Name_Abbr
);
194 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
199 m_colHighlightFg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
200 m_colHighlightBg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
202 m_colHolidayFg
= *wxRED
;
203 // don't set m_colHolidayBg - by default, same as our bg colour
205 m_colHeaderFg
= *wxBLUE
;
206 m_colHeaderBg
= *wxLIGHT_GREY
;
209 bool wxCalendarCtrl::Create(wxWindow
*parent
,
211 const wxDateTime
& date
,
215 const wxString
& name
)
217 if ( !wxControl::Create(parent
, id
, pos
, size
,
218 style
| wxCLIP_CHILDREN
| wxWANTS_CHARS
,
219 wxDefaultValidator
, name
) )
224 // needed to get the arrow keys normally used for the dialog navigation
225 SetWindowStyle(style
| wxWANTS_CHARS
);
227 m_date
= date
.IsValid() ? date
: wxDateTime::Today();
229 m_lowdate
= wxDefaultDateTime
;
230 m_highdate
= wxDefaultDateTime
;
232 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
234 m_spinYear
= new wxYearSpinCtrl(this);
235 m_staticYear
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%Y")),
236 wxDefaultPosition
, wxDefaultSize
,
239 m_comboMonth
= new wxMonthComboBox(this);
240 m_staticMonth
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%B")),
241 wxDefaultPosition
, wxDefaultSize
,
245 ShowCurrentControls();
248 if ( size
.x
== -1 || size
.y
== -1 )
250 sizeReal
= DoGetBestSize();
261 // we need to set the position as well because the main control position
262 // is not the same as the one specified in pos if we have the controls
264 SetSize(pos
.x
, pos
.y
, sizeReal
.x
, sizeReal
.y
);
266 SetBackgroundColour(*wxWHITE
);
267 SetFont(*wxSWISS_FONT
);
274 wxCalendarCtrl::~wxCalendarCtrl()
276 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
282 // ----------------------------------------------------------------------------
283 // forward wxWin functions to subcontrols
284 // ----------------------------------------------------------------------------
286 bool wxCalendarCtrl::Destroy()
289 m_staticYear
->Destroy();
291 m_spinYear
->Destroy();
293 m_comboMonth
->Destroy();
295 m_staticMonth
->Destroy();
300 m_staticMonth
= NULL
;
302 return wxControl::Destroy();
305 bool wxCalendarCtrl::Show(bool show
)
307 if ( !wxControl::Show(show
) )
312 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
314 if ( GetMonthControl() )
316 GetMonthControl()->Show(show
);
317 GetYearControl()->Show(show
);
324 bool wxCalendarCtrl::Enable(bool enable
)
326 if ( !wxControl::Enable(enable
) )
331 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
333 GetMonthControl()->Enable(enable
);
334 GetYearControl()->Enable(enable
);
340 // ----------------------------------------------------------------------------
341 // enable/disable month/year controls
342 // ----------------------------------------------------------------------------
344 void wxCalendarCtrl::ShowCurrentControls()
346 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
348 if ( AllowMonthChange() )
350 m_comboMonth
->Show();
351 m_staticMonth
->Hide();
353 if ( AllowYearChange() )
356 m_staticYear
->Hide();
364 m_comboMonth
->Hide();
365 m_staticMonth
->Show();
368 // year change not allowed here
370 m_staticYear
->Show();
374 wxControl
*wxCalendarCtrl::GetMonthControl() const
376 return AllowMonthChange() ? (wxControl
*)m_comboMonth
: (wxControl
*)m_staticMonth
;
379 wxControl
*wxCalendarCtrl::GetYearControl() const
381 return AllowYearChange() ? (wxControl
*)m_spinYear
: (wxControl
*)m_staticYear
;
384 void wxCalendarCtrl::EnableYearChange(bool enable
)
386 if ( enable
!= AllowYearChange() )
388 long style
= GetWindowStyle();
390 style
&= ~wxCAL_NO_YEAR_CHANGE
;
392 style
|= wxCAL_NO_YEAR_CHANGE
;
393 SetWindowStyle(style
);
395 ShowCurrentControls();
396 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
403 void wxCalendarCtrl::EnableMonthChange(bool enable
)
405 if ( enable
!= AllowMonthChange() )
407 long style
= GetWindowStyle();
409 style
&= ~wxCAL_NO_MONTH_CHANGE
;
411 style
|= wxCAL_NO_MONTH_CHANGE
;
412 SetWindowStyle(style
);
414 ShowCurrentControls();
415 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
422 // ----------------------------------------------------------------------------
424 // ----------------------------------------------------------------------------
426 bool wxCalendarCtrl::SetDate(const wxDateTime
& date
)
430 bool sameMonth
= m_date
.GetMonth() == date
.GetMonth(),
431 sameYear
= m_date
.GetYear() == date
.GetYear();
433 if ( IsDateInRange(date
) )
435 if ( sameMonth
&& sameYear
)
437 // just change the day
442 if ( AllowMonthChange() && (AllowYearChange() || sameYear
) )
447 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
449 // update the controls
450 m_comboMonth
->SetSelection(m_date
.GetMonth());
452 if ( AllowYearChange() )
454 if ( !m_userChangedYear
)
455 m_spinYear
->SetValue(m_date
.Format(_T("%Y")));
459 // as the month changed, holidays did too
462 // update the calendar
473 m_userChangedYear
= FALSE
;
478 void wxCalendarCtrl::ChangeDay(const wxDateTime
& date
)
480 if ( m_date
!= date
)
482 // we need to refresh the row containing the old date and the one
483 // containing the new one
484 wxDateTime dateOld
= m_date
;
487 RefreshDate(dateOld
);
489 // if the date is in the same row, it was already drawn correctly
490 if ( GetWeek(m_date
) != GetWeek(dateOld
) )
497 void wxCalendarCtrl::SetDateAndNotify(const wxDateTime
& date
)
499 wxDateTime::Tm tm1
= m_date
.GetTm(),
503 if ( tm1
.year
!= tm2
.year
)
504 type
= wxEVT_CALENDAR_YEAR_CHANGED
;
505 else if ( tm1
.mon
!= tm2
.mon
)
506 type
= wxEVT_CALENDAR_MONTH_CHANGED
;
507 else if ( tm1
.mday
!= tm2
.mday
)
508 type
= wxEVT_CALENDAR_DAY_CHANGED
;
514 GenerateEvents(type
, wxEVT_CALENDAR_SEL_CHANGED
);
518 // ----------------------------------------------------------------------------
520 // ----------------------------------------------------------------------------
522 bool wxCalendarCtrl::SetLowerDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
526 if ( !(date
.IsValid()) || ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) )
538 bool wxCalendarCtrl::SetUpperDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
542 if ( !(date
.IsValid()) || ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
) )
554 bool wxCalendarCtrl::SetDateRange(const wxDateTime
& lowerdate
/* = wxDefaultDateTime */, const wxDateTime
& upperdate
/* = wxDefaultDateTime */)
559 ( !( lowerdate
.IsValid() ) || ( ( upperdate
.IsValid() ) ? ( lowerdate
<= upperdate
) : TRUE
) ) &&
560 ( !( upperdate
.IsValid() ) || ( ( lowerdate
.IsValid() ) ? ( upperdate
>= lowerdate
) : TRUE
) ) )
562 m_lowdate
= lowerdate
;
563 m_highdate
= upperdate
;
573 // ----------------------------------------------------------------------------
575 // ----------------------------------------------------------------------------
577 wxDateTime
wxCalendarCtrl::GetStartDate() const
579 wxDateTime::Tm tm
= m_date
.GetTm();
581 wxDateTime date
= wxDateTime(1, tm
.mon
, tm
.year
);
584 date
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
585 ? wxDateTime::Mon
: wxDateTime::Sun
);
587 if ( GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
)
589 // We want to offset the calendar if we start on the first..
590 if ( date
.GetDay() == 1 )
592 date
-= wxDateSpan::Week();
599 bool wxCalendarCtrl::IsDateShown(const wxDateTime
& date
) const
601 if ( !(GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
603 return date
.GetMonth() == m_date
.GetMonth();
611 bool wxCalendarCtrl::IsDateInRange(const wxDateTime
& date
) const
614 // Check if the given date is in the range specified
615 retval
= ( ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
)
616 && ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) );
620 bool wxCalendarCtrl::ChangeYear(wxDateTime
* target
) const
624 if ( !(IsDateInRange(*target
)) )
626 if ( target
->GetYear() < m_date
.GetYear() )
628 if ( target
->GetYear() >= GetLowerDateLimit().GetYear() )
630 *target
= GetLowerDateLimit();
640 if ( target
->GetYear() <= GetUpperDateLimit().GetYear() )
642 *target
= GetUpperDateLimit();
659 bool wxCalendarCtrl::ChangeMonth(wxDateTime
* target
) const
663 if ( !(IsDateInRange(*target
)) )
667 if ( target
->GetMonth() < m_date
.GetMonth() )
669 *target
= GetLowerDateLimit();
673 *target
= GetUpperDateLimit();
680 size_t wxCalendarCtrl::GetWeek(const wxDateTime
& date
) const
682 size_t retval
= date
.GetWeekOfMonth(GetWindowStyle() & wxCAL_MONDAY_FIRST
683 ? wxDateTime::Monday_First
684 : wxDateTime::Sunday_First
);
686 if ( (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
688 // we need to offset an extra week if we "start" on the 1st of the month
689 wxDateTime::Tm tm
= date
.GetTm();
691 wxDateTime datetest
= wxDateTime(1, tm
.mon
, tm
.year
);
694 datetest
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
695 ? wxDateTime::Mon
: wxDateTime::Sun
);
697 if ( datetest
.GetDay() == 1 )
706 // ----------------------------------------------------------------------------
708 // ----------------------------------------------------------------------------
710 // this is a composite control and it must arrange its parts each time its
711 // size or position changes: the combobox and spinctrl are along the top of
712 // the available area and the calendar takes up therest of the space
714 // the static controls are supposed to be always smaller than combo/spin so we
715 // always use the latter for size calculations and position the static to take
718 // the constants used for the layout
719 #define VERT_MARGIN 5 // distance between combo and calendar
721 #define HORZ_MARGIN 5 // spin
723 #define HORZ_MARGIN 15 // spin
725 wxSize
wxCalendarCtrl::DoGetBestSize() const
727 // calc the size of the calendar
728 ((wxCalendarCtrl
*)this)->RecalcGeometry(); // const_cast
730 wxCoord width
= 7*m_widthCol
,
731 height
= 7*m_heightRow
+ m_rowOffset
+ VERT_MARGIN
;
733 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
735 // the combobox doesn't report its height correctly (it returns the
736 // height including the drop down list) so don't use it
737 height
+= m_spinYear
->GetBestSize().y
;
740 if ( !HasFlag(wxBORDER_NONE
) )
742 // the border would clip the last line otherwise
747 return wxSize(width
, height
);
750 void wxCalendarCtrl::DoSetSize(int x
, int y
,
751 int width
, int height
,
754 wxControl::DoSetSize(x
, y
, width
, height
, sizeFlags
);
757 void wxCalendarCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
761 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
763 wxSize sizeCombo
= m_comboMonth
->GetSize();
764 wxSize sizeStatic
= m_staticMonth
->GetSize();
765 wxSize sizeSpin
= m_spinYear
->GetSize();
766 int dy
= (sizeCombo
.y
- sizeStatic
.y
) / 2;
768 In the calender the size of the combobox for the year
769 is just defined by a margin from the month combobox to
770 the left border. While in wxUniv the year control can't
771 show all 4 digits, in wxMsw it show almost twice as
772 much. Instead the year should use it's best size and be
773 left aligned to the calendar. Just in case the month in
774 any language is longer than it has space in the
775 calendar it is shortend.This way the year always can
778 This patch relies on the fact that a combobox has a
779 good best size implementation. This is not the case
780 with wxMSW but I don't know why.
785 #ifdef __WXUNIVERSAL__
786 if (sizeCombo
.x
+ HORZ_MARGIN
- sizeSpin
.x
> width
)
788 m_comboMonth
->SetSize(x
, y
, width
- HORZ_MARGIN
- sizeSpin
.x
, sizeCombo
.y
);
792 m_comboMonth
->Move(x
, y
);
794 m_staticMonth
->Move(x
, y
+ dy
);
795 m_spinYear
->Move(x
+ width
- sizeSpin
.x
, y
);
796 m_staticYear
->Move(x
+ width
- sizeSpin
.x
, y
+ dy
);
798 m_comboMonth
->Move(x
, y
);
799 m_staticMonth
->SetSize(x
, y
+ dy
, sizeCombo
.x
, sizeStatic
.y
);
801 int xDiff
= sizeCombo
.x
+ HORZ_MARGIN
;
803 m_spinYear
->SetSize(x
+ xDiff
, y
, width
- xDiff
, sizeCombo
.y
);
804 m_staticYear
->SetSize(x
+ xDiff
, y
+ dy
, width
- xDiff
, sizeStatic
.y
);
806 yDiff
= wxMax(sizeSpin
.y
, sizeCombo
.y
) + VERT_MARGIN
;
808 else // no controls on the top
813 wxControl::DoMoveWindow(x
, y
+ yDiff
, width
, height
- yDiff
);
816 void wxCalendarCtrl::DoGetPosition(int *x
, int *y
) const
818 wxControl::DoGetPosition(x
, y
);
820 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
822 // our real top corner is not in this position
825 *y
-= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
830 void wxCalendarCtrl::DoGetSize(int *width
, int *height
) const
832 wxControl::DoGetSize(width
, height
);
834 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
836 // our real height is bigger
837 if ( height
&& GetMonthControl())
839 *height
+= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
844 void wxCalendarCtrl::RecalcGeometry()
846 if ( m_widthCol
!= 0 )
853 // determine the column width (we assume that the weekday names are always
854 // wider (in any language) than the numbers)
856 wxDateTime::WeekDay wd
;
857 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
860 dc
.GetTextExtent(m_weekdays
[wd
], &width
, &m_heightRow
);
861 if ( width
> m_widthCol
)
867 // leave some margins
871 m_rowOffset
= (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) ? m_heightRow
: 0; // conditional in relation to style
874 // ----------------------------------------------------------------------------
876 // ----------------------------------------------------------------------------
878 void wxCalendarCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
887 wxLogDebug("--- starting to paint, selection: %s, week %u\n",
888 m_date
.Format("%a %d-%m-%Y %H:%M:%S").c_str(),
894 if ( HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
896 // draw the sequential month-selector
898 dc
.SetBackgroundMode(wxTRANSPARENT
);
899 dc
.SetTextForeground(*wxBLACK
);
900 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
901 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
902 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
904 // Get extent of month-name + year
905 wxCoord monthw
, monthh
;
906 wxString headertext
= m_date
.Format(wxT("%B %Y"));
907 dc
.GetTextExtent(headertext
, &monthw
, &monthh
);
909 // draw month-name centered above weekdays
910 wxCoord monthx
= ((m_widthCol
* 7) - monthw
) / 2;
911 wxCoord monthy
= ((m_heightRow
- monthh
) / 2) + y
;
912 dc
.DrawText(headertext
, monthx
, monthy
);
914 // calculate the "month-arrows"
915 wxPoint leftarrow
[3];
916 wxPoint rightarrow
[3];
918 int arrowheight
= monthh
/ 2;
920 leftarrow
[0] = wxPoint(0, arrowheight
/ 2);
921 leftarrow
[1] = wxPoint(arrowheight
/ 2, 0);
922 leftarrow
[2] = wxPoint(arrowheight
/ 2, arrowheight
- 1);
924 rightarrow
[0] = wxPoint(0, 0);
925 rightarrow
[1] = wxPoint(arrowheight
/ 2, arrowheight
/ 2);
926 rightarrow
[2] = wxPoint(0, arrowheight
- 1);
928 // draw the "month-arrows"
930 wxCoord arrowy
= (m_heightRow
- arrowheight
) / 2;
931 wxCoord larrowx
= (m_widthCol
- (arrowheight
/ 2)) / 2;
932 wxCoord rarrowx
= ((m_widthCol
- (arrowheight
/ 2)) / 2) + m_widthCol
*6;
933 m_leftArrowRect
= wxRect(0, 0, 0, 0);
934 m_rightArrowRect
= wxRect(0, 0, 0, 0);
936 if ( AllowMonthChange() )
938 wxDateTime ldpm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) - wxDateSpan::Day(); // last day prev month
939 // Check if range permits change
940 if ( IsDateInRange(ldpm
) && ( ( ldpm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
942 m_leftArrowRect
= wxRect(larrowx
- 3, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
943 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
944 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
945 dc
.DrawPolygon(3, leftarrow
, larrowx
, arrowy
, wxWINDING_RULE
);
946 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
947 dc
.DrawRectangle(m_leftArrowRect
);
949 wxDateTime fdnm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) + wxDateSpan::Month(); // first day next month
950 if ( IsDateInRange(fdnm
) && ( ( fdnm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
952 m_rightArrowRect
= wxRect(rarrowx
- 4, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
953 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
954 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
955 dc
.DrawPolygon(3, rightarrow
, rarrowx
, arrowy
, wxWINDING_RULE
);
956 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
957 dc
.DrawRectangle(m_rightArrowRect
);
964 // first draw the week days
965 if ( IsExposed(0, y
, 7*m_widthCol
, m_heightRow
) )
968 wxLogDebug("painting the header");
971 dc
.SetBackgroundMode(wxTRANSPARENT
);
972 dc
.SetTextForeground(m_colHeaderFg
);
973 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
974 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
975 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
977 bool startOnMonday
= (GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
978 for ( size_t wd
= 0; wd
< 7; wd
++ )
982 n
= wd
== 6 ? 0 : wd
+ 1;
986 dc
.GetTextExtent(m_weekdays
[n
], &dayw
, &dayh
);
987 dc
.DrawText(m_weekdays
[n
], (wd
*m_widthCol
) + ((m_widthCol
- dayw
) / 2), y
); // center the day-name
991 // then the calendar itself
992 dc
.SetTextForeground(*wxBLACK
);
993 //dc.SetFont(*wxNORMAL_FONT);
996 wxDateTime date
= GetStartDate();
999 wxLogDebug("starting calendar from %s\n",
1000 date
.Format("%a %d-%m-%Y %H:%M:%S").c_str());
1003 dc
.SetBackgroundMode(wxSOLID
);
1004 for ( size_t nWeek
= 1; nWeek
<= 6; nWeek
++, y
+= m_heightRow
)
1006 // if the update region doesn't intersect this row, don't paint it
1007 if ( !IsExposed(0, y
, 7*m_widthCol
, m_heightRow
- 1) )
1009 date
+= wxDateSpan::Week();
1015 wxLogDebug("painting week %d at y = %d\n", nWeek
, y
);
1018 for ( size_t wd
= 0; wd
< 7; wd
++ )
1020 if ( IsDateShown(date
) )
1022 // don't use wxDate::Format() which prepends 0s
1023 unsigned int day
= date
.GetDay();
1024 wxString dayStr
= wxString::Format(_T("%u"), day
);
1026 dc
.GetTextExtent(dayStr
, &width
, (wxCoord
*)NULL
);
1028 bool changedColours
= FALSE
,
1029 changedFont
= FALSE
;
1032 wxCalendarDateAttr
*attr
= NULL
;
1034 if ( date
.GetMonth() != m_date
.GetMonth() || !IsDateInRange(date
) )
1036 // surrounding week or out-of-range
1038 dc
.SetTextForeground(*wxLIGHT_GREY
);
1039 changedColours
= TRUE
;
1043 isSel
= date
.IsSameDate(m_date
);
1044 attr
= m_attrs
[day
- 1];
1048 dc
.SetTextForeground(m_colHighlightFg
);
1049 dc
.SetTextBackground(m_colHighlightBg
);
1051 changedColours
= TRUE
;
1055 wxColour colFg
, colBg
;
1057 if ( attr
->IsHoliday() )
1059 colFg
= m_colHolidayFg
;
1060 colBg
= m_colHolidayBg
;
1064 colFg
= attr
->GetTextColour();
1065 colBg
= attr
->GetBackgroundColour();
1070 dc
.SetTextForeground(colFg
);
1071 changedColours
= TRUE
;
1076 dc
.SetTextBackground(colBg
);
1077 changedColours
= TRUE
;
1080 if ( attr
->HasFont() )
1082 dc
.SetFont(attr
->GetFont());
1088 wxCoord x
= wd
*m_widthCol
+ (m_widthCol
- width
) / 2;
1089 dc
.DrawText(dayStr
, x
, y
+ 1);
1091 if ( !isSel
&& attr
&& attr
->HasBorder() )
1094 if ( attr
->HasBorderColour() )
1096 colBorder
= attr
->GetBorderColour();
1100 colBorder
= m_foregroundColour
;
1103 wxPen
pen(colBorder
, 1, wxSOLID
);
1105 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1107 switch ( attr
->GetBorder() )
1109 case wxCAL_BORDER_SQUARE
:
1110 dc
.DrawRectangle(x
- 2, y
,
1111 width
+ 4, m_heightRow
);
1114 case wxCAL_BORDER_ROUND
:
1115 dc
.DrawEllipse(x
- 2, y
,
1116 width
+ 4, m_heightRow
);
1120 wxFAIL_MSG(_T("unknown border type"));
1124 if ( changedColours
)
1126 dc
.SetTextForeground(m_foregroundColour
);
1127 dc
.SetTextBackground(m_backgroundColour
);
1135 //else: just don't draw it
1137 date
+= wxDateSpan::Day();
1141 // Greying out out-of-range background
1142 bool showSurrounding
= (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) != 0;
1144 date
= ( showSurrounding
) ? GetStartDate() : wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear());
1145 if ( !IsDateInRange(date
) )
1147 wxDateTime firstOOR
= GetLowerDateLimit() - wxDateSpan::Day(); // first out-of-range
1149 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1150 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1152 HighlightRange(&dc
, date
, firstOOR
, wxTRANSPARENT_PEN
, &oorbrush
);
1155 date
= ( showSurrounding
) ? GetStartDate() + wxDateSpan::Weeks(6) - wxDateSpan::Day() : wxDateTime().SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear());
1156 if ( !IsDateInRange(date
) )
1158 wxDateTime firstOOR
= GetUpperDateLimit() + wxDateSpan::Day(); // first out-of-range
1160 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1161 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1163 HighlightRange(&dc
, firstOOR
, date
, wxTRANSPARENT_PEN
, &oorbrush
);
1167 wxLogDebug("+++ finished painting");
1171 void wxCalendarCtrl::RefreshDate(const wxDateTime
& date
)
1177 // always refresh the whole row at once because our OnPaint() will draw
1178 // the whole row anyhow - and this allows the small optimisation in
1179 // OnClick() below to work
1182 rect
.y
= (m_heightRow
* GetWeek(date
)) + m_rowOffset
;
1184 rect
.width
= 7*m_widthCol
;
1185 rect
.height
= m_heightRow
;
1188 // VZ: for some reason, the selected date seems to occupy more space under
1189 // MSW - this is probably some bug in the font size calculations, but I
1190 // don't know where exactly. This fix is ugly and leads to more
1191 // refreshes than really needed, but without it the selected days
1192 // leaves even more ugly underscores on screen.
1197 wxLogDebug("*** refreshing week %d at (%d, %d)-(%d, %d)\n",
1200 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1203 Refresh(TRUE
, &rect
);
1206 void wxCalendarCtrl::HighlightRange(wxPaintDC
* pDC
, const wxDateTime
& fromdate
, const wxDateTime
& todate
, wxPen
* pPen
, wxBrush
* pBrush
)
1208 // Highlights the given range using pen and brush
1209 // Does nothing if todate < fromdate
1213 wxLogDebug("+++ HighlightRange: (%s) - (%s) +++", fromdate
.Format("%d %m %Y"), todate
.Format("%d %m %Y"));
1216 if ( todate
>= fromdate
)
1223 // implicit: both dates must be currently shown - checked by GetDateCoord
1224 if ( GetDateCoord(fromdate
, &fd
, &fw
) && GetDateCoord(todate
, &td
, &tw
) )
1227 wxLogDebug("Highlight range: (%i, %i) - (%i, %i)", fd
, fw
, td
, tw
);
1229 if ( ( (tw
- fw
) == 1 ) && ( td
< fd
) )
1231 // special case: interval 7 days or less not in same week
1232 // split in two seperate intervals
1233 wxDateTime tfd
= fromdate
+ wxDateSpan::Days(7-fd
);
1234 wxDateTime ftd
= tfd
+ wxDateSpan::Day();
1236 wxLogDebug("Highlight: Seperate segments");
1239 HighlightRange(pDC
, fromdate
, tfd
, pPen
, pBrush
);
1240 HighlightRange(pDC
, ftd
, todate
, pPen
, pBrush
);
1245 wxPoint corners
[8]; // potentially 8 corners in polygon
1249 // simple case: same week
1251 corners
[0] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
);
1252 corners
[1] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1 ) * m_heightRow
) + m_rowOffset
);
1253 corners
[2] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
);
1254 corners
[3] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
);
1259 // "complex" polygon
1260 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1264 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1265 corners
[cidx
] = wxPoint(0, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1268 corners
[cidx
] = wxPoint(0, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1269 corners
[cidx
] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1273 corners
[cidx
] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1274 corners
[cidx
] = wxPoint(7 * m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1277 corners
[cidx
] = wxPoint(7 * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1283 pDC
->SetBrush(*pBrush
);
1285 pDC
->DrawPolygon(numpoints
, corners
);
1291 wxLogDebug("--- HighlightRange ---");
1295 bool wxCalendarCtrl::GetDateCoord(const wxDateTime
& date
, int *day
, int *week
) const
1300 wxLogDebug("+++ GetDateCoord: (%s) +++", date
.Format("%d %m %Y"));
1303 if ( IsDateShown(date
) )
1305 bool startOnMonday
= ( GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
1308 *day
= date
.GetWeekDay();
1310 if ( *day
== 0 ) // sunday
1312 *day
= ( startOnMonday
) ? 7 : 1;
1316 day
+= ( startOnMonday
) ? 0 : 1;
1319 int targetmonth
= date
.GetMonth() + (12 * date
.GetYear());
1320 int thismonth
= m_date
.GetMonth() + (12 * m_date
.GetYear());
1323 if ( targetmonth
== thismonth
)
1325 *week
= GetWeek(date
);
1329 if ( targetmonth
< thismonth
)
1331 *week
= 1; // trivial
1333 else // targetmonth > thismonth
1339 // get the datecoord of the last day in the month currently shown
1341 wxLogDebug(" +++ LDOM +++");
1343 GetDateCoord(ldcm
.SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear()), &lastday
, &lastweek
);
1345 wxLogDebug(" --- LDOM ---");
1348 wxTimeSpan span
= date
- ldcm
;
1350 int daysfromlast
= span
.GetDays();
1352 wxLogDebug("daysfromlast: %i", daysfromlast
);
1354 if ( daysfromlast
+ lastday
> 7 ) // past week boundary
1356 int wholeweeks
= (daysfromlast
/ 7);
1357 *week
= wholeweeks
+ lastweek
;
1358 if ( (daysfromlast
- (7 * wholeweeks
) + lastday
) > 7 )
1378 wxLogDebug("--- GetDateCoord: (%s) = (%i, %i) ---", date
.Format("%d %m %Y"), *day
, *week
);
1384 // ----------------------------------------------------------------------------
1386 // ----------------------------------------------------------------------------
1388 void wxCalendarCtrl::OnDClick(wxMouseEvent
& event
)
1390 if ( HitTest(event
.GetPosition()) != wxCAL_HITTEST_DAY
)
1396 GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
);
1400 void wxCalendarCtrl::OnClick(wxMouseEvent
& event
)
1403 wxDateTime::WeekDay wday
;
1404 switch ( HitTest(event
.GetPosition(), &date
, &wday
) )
1406 case wxCAL_HITTEST_DAY
:
1407 if ( IsDateInRange(date
) )
1411 GenerateEvents(wxEVT_CALENDAR_DAY_CHANGED
,
1412 wxEVT_CALENDAR_SEL_CHANGED
);
1416 case wxCAL_HITTEST_HEADER
:
1418 wxCalendarEvent
event(this, wxEVT_CALENDAR_WEEKDAY_CLICKED
);
1419 event
.m_wday
= wday
;
1420 (void)GetEventHandler()->ProcessEvent(event
);
1424 case wxCAL_HITTEST_DECMONTH
:
1425 case wxCAL_HITTEST_INCMONTH
:
1426 case wxCAL_HITTEST_SURROUNDING_WEEK
:
1427 SetDateAndNotify(date
); // we probably only want to refresh the control. No notification.. (maybe as an option?)
1431 wxFAIL_MSG(_T("unknown hittest code"));
1434 case wxCAL_HITTEST_NOWHERE
:
1440 wxCalendarHitTestResult
wxCalendarCtrl::HitTest(const wxPoint
& pos
,
1442 wxDateTime::WeekDay
*wd
)
1448 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1449 if ( (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
1453 // we need to find out if the hit is on left arrow, on month or on right arrow
1455 if ( wxRegion(m_leftArrowRect
).Contains(pos
) == wxInRegion
)
1459 if ( IsDateInRange(m_date
- wxDateSpan::Month()) )
1461 *date
= m_date
- wxDateSpan::Month();
1465 *date
= GetLowerDateLimit();
1469 return wxCAL_HITTEST_DECMONTH
;
1472 if ( wxRegion(m_rightArrowRect
).Contains(pos
) == wxInRegion
)
1476 if ( IsDateInRange(m_date
+ wxDateSpan::Month()) )
1478 *date
= m_date
+ wxDateSpan::Month();
1482 *date
= GetUpperDateLimit();
1486 return wxCAL_HITTEST_INCMONTH
;
1491 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1493 int wday
= pos
.x
/ m_widthCol
;
1494 // if ( y < m_heightRow )
1495 if ( y
< (m_heightRow
+ m_rowOffset
) )
1497 if ( y
> m_rowOffset
)
1501 if ( GetWindowStyle() & wxCAL_MONDAY_FIRST
)
1503 wday
= wday
== 6 ? 0 : wday
+ 1;
1506 *wd
= (wxDateTime::WeekDay
)wday
;
1509 return wxCAL_HITTEST_HEADER
;
1513 return wxCAL_HITTEST_NOWHERE
;
1517 // int week = (y - m_heightRow) / m_heightRow;
1518 int week
= (y
- (m_heightRow
+ m_rowOffset
)) / m_heightRow
;
1519 if ( week
>= 6 || wday
>= 7 )
1521 return wxCAL_HITTEST_NOWHERE
;
1524 wxDateTime dt
= GetStartDate() + wxDateSpan::Days(7*week
+ wday
);
1526 if ( IsDateShown(dt
) )
1531 if ( dt
.GetMonth() == m_date
.GetMonth() )
1534 return wxCAL_HITTEST_DAY
;
1538 return wxCAL_HITTEST_SURROUNDING_WEEK
;
1543 return wxCAL_HITTEST_NOWHERE
;
1547 // ----------------------------------------------------------------------------
1548 // subcontrols events handling
1549 // ----------------------------------------------------------------------------
1551 void wxCalendarCtrl::OnMonthChange(wxCommandEvent
& event
)
1553 wxDateTime::Tm tm
= m_date
.GetTm();
1555 wxDateTime::Month mon
= (wxDateTime::Month
)event
.GetInt();
1556 if ( tm
.mday
> wxDateTime::GetNumberOfDays(mon
, tm
.year
) )
1558 tm
.mday
= wxDateTime::GetNumberOfDays(mon
, tm
.year
);
1561 wxDateTime target
= wxDateTime(tm
.mday
, mon
, tm
.year
);
1563 ChangeMonth(&target
);
1564 SetDateAndNotify(target
);
1567 void wxCalendarCtrl::OnYearChange(wxCommandEvent
& event
)
1569 int year
= (int)event
.GetInt();
1570 if ( year
== INT_MIN
)
1572 // invalid year in the spin control, ignore it
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