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 #if wxUSE_EXTENDED_RTTI
108 IMPLEMENT_DYNAMIC_CLASS_XTI(wxCalendarCtrl
, wxControl
,"wx/calctrl.h")
110 WX_BEGIN_PROPERTIES_TABLE(wxCalendarCtrl
)
111 WX_HIDE_PROPERTY( Children
)
112 WX_PROPERTY( Date
,wxDateTime
, SetDate
, GetDate
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
113 WX_END_PROPERTIES_TABLE()
115 WX_BEGIN_HANDLERS_TABLE(wxCalendarCtrl
)
116 WX_END_HANDLERS_TABLE()
118 WX_CONSTRUCTOR_6( wxCalendarCtrl
, wxWindow
* , Parent
, wxWindowID
, Id
, wxDateTime
, Date
, wxPoint
, Position
, wxSize
, Size
, long , WindowStyle
)
120 IMPLEMENT_DYNAMIC_CLASS(wxCalendarCtrl
, wxControl
)
122 IMPLEMENT_DYNAMIC_CLASS(wxCalendarEvent
, wxCommandEvent
)
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
128 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_SEL_CHANGED
)
129 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_DAY_CHANGED
)
130 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_MONTH_CHANGED
)
131 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_YEAR_CHANGED
)
132 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_DOUBLECLICKED
)
133 DEFINE_EVENT_TYPE(wxEVT_CALENDAR_WEEKDAY_CLICKED
)
135 // ============================================================================
137 // ============================================================================
139 // ----------------------------------------------------------------------------
140 // wxMonthComboBox and wxYearSpinCtrl
141 // ----------------------------------------------------------------------------
143 wxMonthComboBox::wxMonthComboBox(wxCalendarCtrl
*cal
)
144 : wxComboBox(cal
->GetParent(), -1,
149 wxCB_READONLY
| wxCLIP_SIBLINGS
)
154 for ( m
= wxDateTime::Jan
; m
< wxDateTime::Inv_Month
; wxNextMonth(m
) )
156 Append(wxDateTime::GetMonthName(m
));
159 SetSelection(m_cal
->GetDate().GetMonth());
160 SetSize(-1, -1, -1, -1, wxSIZE_AUTO_WIDTH
|wxSIZE_AUTO_HEIGHT
);
163 wxYearSpinCtrl::wxYearSpinCtrl(wxCalendarCtrl
*cal
)
164 : wxSpinCtrl(cal
->GetParent(), -1,
165 cal
->GetDate().Format(_T("%Y")),
168 wxSP_ARROW_KEYS
| wxCLIP_SIBLINGS
,
169 -4300, 10000, cal
->GetDate().GetYear())
175 // ----------------------------------------------------------------------------
177 // ----------------------------------------------------------------------------
179 wxCalendarCtrl::wxCalendarCtrl(wxWindow
*parent
,
181 const wxDateTime
& date
,
185 const wxString
& name
)
189 (void)Create(parent
, id
, date
, pos
, size
, style
, name
);
192 void wxCalendarCtrl::Init()
197 m_staticMonth
= NULL
;
199 m_userChangedYear
= FALSE
;
204 wxDateTime::WeekDay wd
;
205 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
207 m_weekdays
[wd
] = wxDateTime::GetWeekDayName(wd
, wxDateTime::Name_Abbr
);
210 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
215 m_colHighlightFg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
216 m_colHighlightBg
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
218 m_colHolidayFg
= *wxRED
;
219 // don't set m_colHolidayBg - by default, same as our bg colour
221 m_colHeaderFg
= *wxBLUE
;
222 m_colHeaderBg
= *wxLIGHT_GREY
;
225 bool wxCalendarCtrl::Create(wxWindow
*parent
,
227 const wxDateTime
& date
,
231 const wxString
& name
)
233 if ( !wxControl::Create(parent
, id
, pos
, size
,
234 style
| wxCLIP_CHILDREN
| wxWANTS_CHARS
,
235 wxDefaultValidator
, name
) )
240 // needed to get the arrow keys normally used for the dialog navigation
241 SetWindowStyle(style
| wxWANTS_CHARS
);
243 m_date
= date
.IsValid() ? date
: wxDateTime::Today();
245 m_lowdate
= wxDefaultDateTime
;
246 m_highdate
= wxDefaultDateTime
;
248 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
250 m_spinYear
= new wxYearSpinCtrl(this);
251 m_staticYear
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%Y")),
252 wxDefaultPosition
, wxDefaultSize
,
255 m_comboMonth
= new wxMonthComboBox(this);
256 m_staticMonth
= new wxStaticText(GetParent(), -1, m_date
.Format(_T("%B")),
257 wxDefaultPosition
, wxDefaultSize
,
261 ShowCurrentControls();
264 if ( size
.x
== -1 || size
.y
== -1 )
266 sizeReal
= DoGetBestSize();
277 // we need to set the position as well because the main control position
278 // is not the same as the one specified in pos if we have the controls
280 SetSize(pos
.x
, pos
.y
, sizeReal
.x
, sizeReal
.y
);
282 SetBackgroundColour(*wxWHITE
);
283 SetFont(*wxSWISS_FONT
);
290 wxCalendarCtrl::~wxCalendarCtrl()
292 for ( size_t n
= 0; n
< WXSIZEOF(m_attrs
); n
++ )
298 // ----------------------------------------------------------------------------
299 // forward wxWin functions to subcontrols
300 // ----------------------------------------------------------------------------
302 bool wxCalendarCtrl::Destroy()
305 m_staticYear
->Destroy();
307 m_spinYear
->Destroy();
309 m_comboMonth
->Destroy();
311 m_staticMonth
->Destroy();
316 m_staticMonth
= NULL
;
318 return wxControl::Destroy();
321 bool wxCalendarCtrl::Show(bool show
)
323 if ( !wxControl::Show(show
) )
328 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
330 if ( GetMonthControl() )
332 GetMonthControl()->Show(show
);
333 GetYearControl()->Show(show
);
340 bool wxCalendarCtrl::Enable(bool enable
)
342 if ( !wxControl::Enable(enable
) )
347 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
349 GetMonthControl()->Enable(enable
);
350 GetYearControl()->Enable(enable
);
356 // ----------------------------------------------------------------------------
357 // enable/disable month/year controls
358 // ----------------------------------------------------------------------------
360 void wxCalendarCtrl::ShowCurrentControls()
362 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
364 if ( AllowMonthChange() )
366 m_comboMonth
->Show();
367 m_staticMonth
->Hide();
369 if ( AllowYearChange() )
372 m_staticYear
->Hide();
380 m_comboMonth
->Hide();
381 m_staticMonth
->Show();
384 // year change not allowed here
386 m_staticYear
->Show();
390 wxControl
*wxCalendarCtrl::GetMonthControl() const
392 return AllowMonthChange() ? (wxControl
*)m_comboMonth
: (wxControl
*)m_staticMonth
;
395 wxControl
*wxCalendarCtrl::GetYearControl() const
397 return AllowYearChange() ? (wxControl
*)m_spinYear
: (wxControl
*)m_staticYear
;
400 void wxCalendarCtrl::EnableYearChange(bool enable
)
402 if ( enable
!= AllowYearChange() )
404 long style
= GetWindowStyle();
406 style
&= ~wxCAL_NO_YEAR_CHANGE
;
408 style
|= wxCAL_NO_YEAR_CHANGE
;
409 SetWindowStyle(style
);
411 ShowCurrentControls();
412 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
419 void wxCalendarCtrl::EnableMonthChange(bool enable
)
421 if ( enable
!= AllowMonthChange() )
423 long style
= GetWindowStyle();
425 style
&= ~wxCAL_NO_MONTH_CHANGE
;
427 style
|= wxCAL_NO_MONTH_CHANGE
;
428 SetWindowStyle(style
);
430 ShowCurrentControls();
431 if ( GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
)
438 // ----------------------------------------------------------------------------
440 // ----------------------------------------------------------------------------
442 bool wxCalendarCtrl::SetDate(const wxDateTime
& date
)
446 bool sameMonth
= m_date
.GetMonth() == date
.GetMonth(),
447 sameYear
= m_date
.GetYear() == date
.GetYear();
449 if ( IsDateInRange(date
) )
451 if ( sameMonth
&& sameYear
)
453 // just change the day
458 if ( AllowMonthChange() && (AllowYearChange() || sameYear
) )
463 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
465 // update the controls
466 m_comboMonth
->SetSelection(m_date
.GetMonth());
468 if ( AllowYearChange() )
470 if ( !m_userChangedYear
)
471 m_spinYear
->SetValue(m_date
.Format(_T("%Y")));
475 // as the month changed, holidays did too
478 // update the calendar
489 m_userChangedYear
= FALSE
;
494 void wxCalendarCtrl::ChangeDay(const wxDateTime
& date
)
496 if ( m_date
!= date
)
498 // we need to refresh the row containing the old date and the one
499 // containing the new one
500 wxDateTime dateOld
= m_date
;
503 RefreshDate(dateOld
);
505 // if the date is in the same row, it was already drawn correctly
506 if ( GetWeek(m_date
) != GetWeek(dateOld
) )
513 void wxCalendarCtrl::SetDateAndNotify(const wxDateTime
& date
)
515 wxDateTime::Tm tm1
= m_date
.GetTm(),
519 if ( tm1
.year
!= tm2
.year
)
520 type
= wxEVT_CALENDAR_YEAR_CHANGED
;
521 else if ( tm1
.mon
!= tm2
.mon
)
522 type
= wxEVT_CALENDAR_MONTH_CHANGED
;
523 else if ( tm1
.mday
!= tm2
.mday
)
524 type
= wxEVT_CALENDAR_DAY_CHANGED
;
530 GenerateEvents(type
, wxEVT_CALENDAR_SEL_CHANGED
);
534 // ----------------------------------------------------------------------------
536 // ----------------------------------------------------------------------------
538 bool wxCalendarCtrl::SetLowerDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
542 if ( !(date
.IsValid()) || ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) )
554 bool wxCalendarCtrl::SetUpperDateLimit(const wxDateTime
& date
/* = wxDefaultDateTime */)
558 if ( !(date
.IsValid()) || ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
) )
570 bool wxCalendarCtrl::SetDateRange(const wxDateTime
& lowerdate
/* = wxDefaultDateTime */, const wxDateTime
& upperdate
/* = wxDefaultDateTime */)
575 ( !( lowerdate
.IsValid() ) || ( ( upperdate
.IsValid() ) ? ( lowerdate
<= upperdate
) : TRUE
) ) &&
576 ( !( upperdate
.IsValid() ) || ( ( lowerdate
.IsValid() ) ? ( upperdate
>= lowerdate
) : TRUE
) ) )
578 m_lowdate
= lowerdate
;
579 m_highdate
= upperdate
;
589 // ----------------------------------------------------------------------------
591 // ----------------------------------------------------------------------------
593 wxDateTime
wxCalendarCtrl::GetStartDate() const
595 wxDateTime::Tm tm
= m_date
.GetTm();
597 wxDateTime date
= wxDateTime(1, tm
.mon
, tm
.year
);
600 date
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
601 ? wxDateTime::Mon
: wxDateTime::Sun
);
603 if ( GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
)
605 // We want to offset the calendar if we start on the first..
606 if ( date
.GetDay() == 1 )
608 date
-= wxDateSpan::Week();
615 bool wxCalendarCtrl::IsDateShown(const wxDateTime
& date
) const
617 if ( !(GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
619 return date
.GetMonth() == m_date
.GetMonth();
627 bool wxCalendarCtrl::IsDateInRange(const wxDateTime
& date
) const
630 // Check if the given date is in the range specified
631 retval
= ( ( ( m_lowdate
.IsValid() ) ? ( date
>= m_lowdate
) : TRUE
)
632 && ( ( m_highdate
.IsValid() ) ? ( date
<= m_highdate
) : TRUE
) );
636 bool wxCalendarCtrl::ChangeYear(wxDateTime
* target
) const
640 if ( !(IsDateInRange(*target
)) )
642 if ( target
->GetYear() < m_date
.GetYear() )
644 if ( target
->GetYear() >= GetLowerDateLimit().GetYear() )
646 *target
= GetLowerDateLimit();
656 if ( target
->GetYear() <= GetUpperDateLimit().GetYear() )
658 *target
= GetUpperDateLimit();
675 bool wxCalendarCtrl::ChangeMonth(wxDateTime
* target
) const
679 if ( !(IsDateInRange(*target
)) )
683 if ( target
->GetMonth() < m_date
.GetMonth() )
685 *target
= GetLowerDateLimit();
689 *target
= GetUpperDateLimit();
696 size_t wxCalendarCtrl::GetWeek(const wxDateTime
& date
) const
698 size_t retval
= date
.GetWeekOfMonth(GetWindowStyle() & wxCAL_MONDAY_FIRST
699 ? wxDateTime::Monday_First
700 : wxDateTime::Sunday_First
);
702 if ( (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) )
704 // we need to offset an extra week if we "start" on the 1st of the month
705 wxDateTime::Tm tm
= date
.GetTm();
707 wxDateTime datetest
= wxDateTime(1, tm
.mon
, tm
.year
);
710 datetest
.SetToPrevWeekDay(GetWindowStyle() & wxCAL_MONDAY_FIRST
711 ? wxDateTime::Mon
: wxDateTime::Sun
);
713 if ( datetest
.GetDay() == 1 )
722 // ----------------------------------------------------------------------------
724 // ----------------------------------------------------------------------------
726 // this is a composite control and it must arrange its parts each time its
727 // size or position changes: the combobox and spinctrl are along the top of
728 // the available area and the calendar takes up therest of the space
730 // the static controls are supposed to be always smaller than combo/spin so we
731 // always use the latter for size calculations and position the static to take
734 // the constants used for the layout
735 #define VERT_MARGIN 5 // distance between combo and calendar
737 #define HORZ_MARGIN 5 // spin
739 #define HORZ_MARGIN 15 // spin
741 wxSize
wxCalendarCtrl::DoGetBestSize() const
743 // calc the size of the calendar
744 ((wxCalendarCtrl
*)this)->RecalcGeometry(); // const_cast
746 wxCoord width
= 7*m_widthCol
,
747 height
= 7*m_heightRow
+ m_rowOffset
+ VERT_MARGIN
;
749 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
751 // the combobox doesn't report its height correctly (it returns the
752 // height including the drop down list) so don't use it
753 height
+= m_spinYear
->GetBestSize().y
;
756 if ( !HasFlag(wxBORDER_NONE
) )
758 // the border would clip the last line otherwise
763 return wxSize(width
, height
);
766 void wxCalendarCtrl::DoSetSize(int x
, int y
,
767 int width
, int height
,
770 wxControl::DoSetSize(x
, y
, width
, height
, sizeFlags
);
773 void wxCalendarCtrl::DoMoveWindow(int x
, int y
, int width
, int height
)
777 if ( !HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
779 wxSize sizeCombo
= m_comboMonth
->GetSize();
780 wxSize sizeStatic
= m_staticMonth
->GetSize();
781 wxSize sizeSpin
= m_spinYear
->GetSize();
782 int dy
= (sizeCombo
.y
- sizeStatic
.y
) / 2;
784 In the calender the size of the combobox for the year
785 is just defined by a margin from the month combobox to
786 the left border. While in wxUniv the year control can't
787 show all 4 digits, in wxMsw it show almost twice as
788 much. Instead the year should use it's best size and be
789 left aligned to the calendar. Just in case the month in
790 any language is longer than it has space in the
791 calendar it is shortend.This way the year always can
794 This patch relies on the fact that a combobox has a
795 good best size implementation. This is not the case
796 with wxMSW but I don't know why.
801 #ifdef __WXUNIVERSAL__
802 if (sizeCombo
.x
+ HORZ_MARGIN
- sizeSpin
.x
> width
)
804 m_comboMonth
->SetSize(x
, y
, width
- HORZ_MARGIN
- sizeSpin
.x
, sizeCombo
.y
);
808 m_comboMonth
->Move(x
, y
);
810 m_staticMonth
->Move(x
, y
+ dy
);
811 m_spinYear
->Move(x
+ width
- sizeSpin
.x
, y
);
812 m_staticYear
->Move(x
+ width
- sizeSpin
.x
, y
+ dy
);
814 m_comboMonth
->Move(x
, y
);
815 m_staticMonth
->SetSize(x
, y
+ dy
, sizeCombo
.x
, sizeStatic
.y
);
817 int xDiff
= sizeCombo
.x
+ HORZ_MARGIN
;
819 m_spinYear
->SetSize(x
+ xDiff
, y
, width
- xDiff
, sizeCombo
.y
);
820 m_staticYear
->SetSize(x
+ xDiff
, y
+ dy
, width
- xDiff
, sizeStatic
.y
);
822 yDiff
= wxMax(sizeSpin
.y
, sizeCombo
.y
) + VERT_MARGIN
;
824 else // no controls on the top
829 wxControl::DoMoveWindow(x
, y
+ yDiff
, width
, height
- yDiff
);
832 void wxCalendarCtrl::DoGetPosition(int *x
, int *y
) const
834 wxControl::DoGetPosition(x
, y
);
836 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
838 // our real top corner is not in this position
841 *y
-= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
846 void wxCalendarCtrl::DoGetSize(int *width
, int *height
) const
848 wxControl::DoGetSize(width
, height
);
850 if ( !(GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
852 // our real height is bigger
853 if ( height
&& GetMonthControl())
855 *height
+= GetMonthControl()->GetSize().y
+ VERT_MARGIN
;
860 void wxCalendarCtrl::RecalcGeometry()
862 if ( m_widthCol
!= 0 )
869 // determine the column width (we assume that the weekday names are always
870 // wider (in any language) than the numbers)
872 wxDateTime::WeekDay wd
;
873 for ( wd
= wxDateTime::Sun
; wd
< wxDateTime::Inv_WeekDay
; wxNextWDay(wd
) )
876 dc
.GetTextExtent(m_weekdays
[wd
], &width
, &m_heightRow
);
877 if ( width
> m_widthCol
)
883 // leave some margins
887 m_rowOffset
= (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) ? m_heightRow
: 0; // conditional in relation to style
890 // ----------------------------------------------------------------------------
892 // ----------------------------------------------------------------------------
894 void wxCalendarCtrl::OnPaint(wxPaintEvent
& WXUNUSED(event
))
903 wxLogDebug("--- starting to paint, selection: %s, week %u\n",
904 m_date
.Format("%a %d-%m-%Y %H:%M:%S").c_str(),
910 if ( HasFlag(wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
912 // draw the sequential month-selector
914 dc
.SetBackgroundMode(wxTRANSPARENT
);
915 dc
.SetTextForeground(*wxBLACK
);
916 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
917 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
918 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
920 // Get extent of month-name + year
921 wxCoord monthw
, monthh
;
922 wxString headertext
= m_date
.Format(wxT("%B %Y"));
923 dc
.GetTextExtent(headertext
, &monthw
, &monthh
);
925 // draw month-name centered above weekdays
926 wxCoord monthx
= ((m_widthCol
* 7) - monthw
) / 2;
927 wxCoord monthy
= ((m_heightRow
- monthh
) / 2) + y
;
928 dc
.DrawText(headertext
, monthx
, monthy
);
930 // calculate the "month-arrows"
931 wxPoint leftarrow
[3];
932 wxPoint rightarrow
[3];
934 int arrowheight
= monthh
/ 2;
936 leftarrow
[0] = wxPoint(0, arrowheight
/ 2);
937 leftarrow
[1] = wxPoint(arrowheight
/ 2, 0);
938 leftarrow
[2] = wxPoint(arrowheight
/ 2, arrowheight
- 1);
940 rightarrow
[0] = wxPoint(0, 0);
941 rightarrow
[1] = wxPoint(arrowheight
/ 2, arrowheight
/ 2);
942 rightarrow
[2] = wxPoint(0, arrowheight
- 1);
944 // draw the "month-arrows"
946 wxCoord arrowy
= (m_heightRow
- arrowheight
) / 2;
947 wxCoord larrowx
= (m_widthCol
- (arrowheight
/ 2)) / 2;
948 wxCoord rarrowx
= ((m_widthCol
- (arrowheight
/ 2)) / 2) + m_widthCol
*6;
949 m_leftArrowRect
= wxRect(0, 0, 0, 0);
950 m_rightArrowRect
= wxRect(0, 0, 0, 0);
952 if ( AllowMonthChange() )
954 wxDateTime ldpm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) - wxDateSpan::Day(); // last day prev month
955 // Check if range permits change
956 if ( IsDateInRange(ldpm
) && ( ( ldpm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
958 m_leftArrowRect
= wxRect(larrowx
- 3, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
959 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
960 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
961 dc
.DrawPolygon(3, leftarrow
, larrowx
, arrowy
, wxWINDING_RULE
);
962 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
963 dc
.DrawRectangle(m_leftArrowRect
);
965 wxDateTime fdnm
= wxDateTime(1,m_date
.GetMonth(), m_date
.GetYear()) + wxDateSpan::Month(); // first day next month
966 if ( IsDateInRange(fdnm
) && ( ( fdnm
.GetYear() == m_date
.GetYear() ) ? TRUE
: AllowYearChange() ) )
968 m_rightArrowRect
= wxRect(rarrowx
- 4, arrowy
- 3, (arrowheight
/ 2) + 8, (arrowheight
+ 6));
969 dc
.SetBrush(wxBrush(*wxBLACK
, wxSOLID
));
970 dc
.SetPen(wxPen(*wxBLACK
, 1, wxSOLID
));
971 dc
.DrawPolygon(3, rightarrow
, rarrowx
, arrowy
, wxWINDING_RULE
);
972 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
973 dc
.DrawRectangle(m_rightArrowRect
);
980 // first draw the week days
981 if ( IsExposed(0, y
, 7*m_widthCol
, m_heightRow
) )
984 wxLogDebug("painting the header");
987 dc
.SetBackgroundMode(wxTRANSPARENT
);
988 dc
.SetTextForeground(m_colHeaderFg
);
989 dc
.SetBrush(wxBrush(m_colHeaderBg
, wxSOLID
));
990 dc
.SetPen(wxPen(m_colHeaderBg
, 1, wxSOLID
));
991 dc
.DrawRectangle(0, y
, GetClientSize().x
, m_heightRow
);
993 bool startOnMonday
= (GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
994 for ( size_t wd
= 0; wd
< 7; wd
++ )
998 n
= wd
== 6 ? 0 : wd
+ 1;
1002 dc
.GetTextExtent(m_weekdays
[n
], &dayw
, &dayh
);
1003 dc
.DrawText(m_weekdays
[n
], (wd
*m_widthCol
) + ((m_widthCol
- dayw
) / 2), y
); // center the day-name
1007 // then the calendar itself
1008 dc
.SetTextForeground(*wxBLACK
);
1009 //dc.SetFont(*wxNORMAL_FONT);
1012 wxDateTime date
= GetStartDate();
1015 wxLogDebug("starting calendar from %s\n",
1016 date
.Format("%a %d-%m-%Y %H:%M:%S").c_str());
1019 dc
.SetBackgroundMode(wxSOLID
);
1020 for ( size_t nWeek
= 1; nWeek
<= 6; nWeek
++, y
+= m_heightRow
)
1022 // if the update region doesn't intersect this row, don't paint it
1023 if ( !IsExposed(0, y
, 7*m_widthCol
, m_heightRow
- 1) )
1025 date
+= wxDateSpan::Week();
1031 wxLogDebug("painting week %d at y = %d\n", nWeek
, y
);
1034 for ( size_t wd
= 0; wd
< 7; wd
++ )
1036 if ( IsDateShown(date
) )
1038 // don't use wxDate::Format() which prepends 0s
1039 unsigned int day
= date
.GetDay();
1040 wxString dayStr
= wxString::Format(_T("%u"), day
);
1042 dc
.GetTextExtent(dayStr
, &width
, (wxCoord
*)NULL
);
1044 bool changedColours
= FALSE
,
1045 changedFont
= FALSE
;
1048 wxCalendarDateAttr
*attr
= NULL
;
1050 if ( date
.GetMonth() != m_date
.GetMonth() || !IsDateInRange(date
) )
1052 // surrounding week or out-of-range
1054 dc
.SetTextForeground(*wxLIGHT_GREY
);
1055 changedColours
= TRUE
;
1059 isSel
= date
.IsSameDate(m_date
);
1060 attr
= m_attrs
[day
- 1];
1064 dc
.SetTextForeground(m_colHighlightFg
);
1065 dc
.SetTextBackground(m_colHighlightBg
);
1067 changedColours
= TRUE
;
1071 wxColour colFg
, colBg
;
1073 if ( attr
->IsHoliday() )
1075 colFg
= m_colHolidayFg
;
1076 colBg
= m_colHolidayBg
;
1080 colFg
= attr
->GetTextColour();
1081 colBg
= attr
->GetBackgroundColour();
1086 dc
.SetTextForeground(colFg
);
1087 changedColours
= TRUE
;
1092 dc
.SetTextBackground(colBg
);
1093 changedColours
= TRUE
;
1096 if ( attr
->HasFont() )
1098 dc
.SetFont(attr
->GetFont());
1104 wxCoord x
= wd
*m_widthCol
+ (m_widthCol
- width
) / 2;
1105 dc
.DrawText(dayStr
, x
, y
+ 1);
1107 if ( !isSel
&& attr
&& attr
->HasBorder() )
1110 if ( attr
->HasBorderColour() )
1112 colBorder
= attr
->GetBorderColour();
1116 colBorder
= m_foregroundColour
;
1119 wxPen
pen(colBorder
, 1, wxSOLID
);
1121 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
1123 switch ( attr
->GetBorder() )
1125 case wxCAL_BORDER_SQUARE
:
1126 dc
.DrawRectangle(x
- 2, y
,
1127 width
+ 4, m_heightRow
);
1130 case wxCAL_BORDER_ROUND
:
1131 dc
.DrawEllipse(x
- 2, y
,
1132 width
+ 4, m_heightRow
);
1136 wxFAIL_MSG(_T("unknown border type"));
1140 if ( changedColours
)
1142 dc
.SetTextForeground(m_foregroundColour
);
1143 dc
.SetTextBackground(m_backgroundColour
);
1151 //else: just don't draw it
1153 date
+= wxDateSpan::Day();
1157 // Greying out out-of-range background
1158 bool showSurrounding
= (GetWindowStyle() & wxCAL_SHOW_SURROUNDING_WEEKS
) != 0;
1160 date
= ( showSurrounding
) ? GetStartDate() : wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear());
1161 if ( !IsDateInRange(date
) )
1163 wxDateTime firstOOR
= GetLowerDateLimit() - wxDateSpan::Day(); // first out-of-range
1165 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1166 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1168 HighlightRange(&dc
, date
, firstOOR
, wxTRANSPARENT_PEN
, &oorbrush
);
1171 date
= ( showSurrounding
) ? GetStartDate() + wxDateSpan::Weeks(6) - wxDateSpan::Day() : wxDateTime().SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear());
1172 if ( !IsDateInRange(date
) )
1174 wxDateTime firstOOR
= GetUpperDateLimit() + wxDateSpan::Day(); // first out-of-range
1176 wxBrush oorbrush
= *wxLIGHT_GREY_BRUSH
;
1177 oorbrush
.SetStyle(wxFDIAGONAL_HATCH
);
1179 HighlightRange(&dc
, firstOOR
, date
, wxTRANSPARENT_PEN
, &oorbrush
);
1183 wxLogDebug("+++ finished painting");
1187 void wxCalendarCtrl::RefreshDate(const wxDateTime
& date
)
1193 // always refresh the whole row at once because our OnPaint() will draw
1194 // the whole row anyhow - and this allows the small optimisation in
1195 // OnClick() below to work
1198 rect
.y
= (m_heightRow
* GetWeek(date
)) + m_rowOffset
;
1200 rect
.width
= 7*m_widthCol
;
1201 rect
.height
= m_heightRow
;
1204 // VZ: for some reason, the selected date seems to occupy more space under
1205 // MSW - this is probably some bug in the font size calculations, but I
1206 // don't know where exactly. This fix is ugly and leads to more
1207 // refreshes than really needed, but without it the selected days
1208 // leaves even more ugly underscores on screen.
1213 wxLogDebug("*** refreshing week %d at (%d, %d)-(%d, %d)\n",
1216 rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
1219 Refresh(TRUE
, &rect
);
1222 void wxCalendarCtrl::HighlightRange(wxPaintDC
* pDC
, const wxDateTime
& fromdate
, const wxDateTime
& todate
, wxPen
* pPen
, wxBrush
* pBrush
)
1224 // Highlights the given range using pen and brush
1225 // Does nothing if todate < fromdate
1229 wxLogDebug("+++ HighlightRange: (%s) - (%s) +++", fromdate
.Format("%d %m %Y"), todate
.Format("%d %m %Y"));
1232 if ( todate
>= fromdate
)
1239 // implicit: both dates must be currently shown - checked by GetDateCoord
1240 if ( GetDateCoord(fromdate
, &fd
, &fw
) && GetDateCoord(todate
, &td
, &tw
) )
1243 wxLogDebug("Highlight range: (%i, %i) - (%i, %i)", fd
, fw
, td
, tw
);
1245 if ( ( (tw
- fw
) == 1 ) && ( td
< fd
) )
1247 // special case: interval 7 days or less not in same week
1248 // split in two seperate intervals
1249 wxDateTime tfd
= fromdate
+ wxDateSpan::Days(7-fd
);
1250 wxDateTime ftd
= tfd
+ wxDateSpan::Day();
1252 wxLogDebug("Highlight: Seperate segments");
1255 HighlightRange(pDC
, fromdate
, tfd
, pPen
, pBrush
);
1256 HighlightRange(pDC
, ftd
, todate
, pPen
, pBrush
);
1261 wxPoint corners
[8]; // potentially 8 corners in polygon
1265 // simple case: same week
1267 corners
[0] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
);
1268 corners
[1] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1 ) * m_heightRow
) + m_rowOffset
);
1269 corners
[2] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
);
1270 corners
[3] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
);
1275 // "complex" polygon
1276 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1280 corners
[cidx
] = wxPoint((fd
- 1) * m_widthCol
, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1281 corners
[cidx
] = wxPoint(0, ((fw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1284 corners
[cidx
] = wxPoint(0, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1285 corners
[cidx
] = wxPoint(td
* m_widthCol
, ((tw
+ 1) * m_heightRow
) + m_rowOffset
); cidx
++;
1289 corners
[cidx
] = wxPoint(td
* m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1290 corners
[cidx
] = wxPoint(7 * m_widthCol
, (tw
* m_heightRow
) + m_rowOffset
); cidx
++;
1293 corners
[cidx
] = wxPoint(7 * m_widthCol
, (fw
* m_heightRow
) + m_rowOffset
); cidx
++;
1299 pDC
->SetBrush(*pBrush
);
1301 pDC
->DrawPolygon(numpoints
, corners
);
1307 wxLogDebug("--- HighlightRange ---");
1311 bool wxCalendarCtrl::GetDateCoord(const wxDateTime
& date
, int *day
, int *week
) const
1316 wxLogDebug("+++ GetDateCoord: (%s) +++", date
.Format("%d %m %Y"));
1319 if ( IsDateShown(date
) )
1321 bool startOnMonday
= ( GetWindowStyle() & wxCAL_MONDAY_FIRST
) != 0;
1324 *day
= date
.GetWeekDay();
1326 if ( *day
== 0 ) // sunday
1328 *day
= ( startOnMonday
) ? 7 : 1;
1332 day
+= ( startOnMonday
) ? 0 : 1;
1335 int targetmonth
= date
.GetMonth() + (12 * date
.GetYear());
1336 int thismonth
= m_date
.GetMonth() + (12 * m_date
.GetYear());
1339 if ( targetmonth
== thismonth
)
1341 *week
= GetWeek(date
);
1345 if ( targetmonth
< thismonth
)
1347 *week
= 1; // trivial
1349 else // targetmonth > thismonth
1355 // get the datecoord of the last day in the month currently shown
1357 wxLogDebug(" +++ LDOM +++");
1359 GetDateCoord(ldcm
.SetToLastMonthDay(m_date
.GetMonth(), m_date
.GetYear()), &lastday
, &lastweek
);
1361 wxLogDebug(" --- LDOM ---");
1364 wxTimeSpan span
= date
- ldcm
;
1366 int daysfromlast
= span
.GetDays();
1368 wxLogDebug("daysfromlast: %i", daysfromlast
);
1370 if ( daysfromlast
+ lastday
> 7 ) // past week boundary
1372 int wholeweeks
= (daysfromlast
/ 7);
1373 *week
= wholeweeks
+ lastweek
;
1374 if ( (daysfromlast
- (7 * wholeweeks
) + lastday
) > 7 )
1394 wxLogDebug("--- GetDateCoord: (%s) = (%i, %i) ---", date
.Format("%d %m %Y"), *day
, *week
);
1400 // ----------------------------------------------------------------------------
1402 // ----------------------------------------------------------------------------
1404 void wxCalendarCtrl::OnDClick(wxMouseEvent
& event
)
1406 if ( HitTest(event
.GetPosition()) != wxCAL_HITTEST_DAY
)
1412 GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
);
1416 void wxCalendarCtrl::OnClick(wxMouseEvent
& event
)
1419 wxDateTime::WeekDay wday
;
1420 switch ( HitTest(event
.GetPosition(), &date
, &wday
) )
1422 case wxCAL_HITTEST_DAY
:
1423 if ( IsDateInRange(date
) )
1427 GenerateEvents(wxEVT_CALENDAR_DAY_CHANGED
,
1428 wxEVT_CALENDAR_SEL_CHANGED
);
1432 case wxCAL_HITTEST_HEADER
:
1434 wxCalendarEvent
event(this, wxEVT_CALENDAR_WEEKDAY_CLICKED
);
1435 event
.m_wday
= wday
;
1436 (void)GetEventHandler()->ProcessEvent(event
);
1440 case wxCAL_HITTEST_DECMONTH
:
1441 case wxCAL_HITTEST_INCMONTH
:
1442 case wxCAL_HITTEST_SURROUNDING_WEEK
:
1443 SetDateAndNotify(date
); // we probably only want to refresh the control. No notification.. (maybe as an option?)
1447 wxFAIL_MSG(_T("unknown hittest code"));
1450 case wxCAL_HITTEST_NOWHERE
:
1456 wxCalendarHitTestResult
wxCalendarCtrl::HitTest(const wxPoint
& pos
,
1458 wxDateTime::WeekDay
*wd
)
1464 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1465 if ( (GetWindowStyle() & wxCAL_SEQUENTIAL_MONTH_SELECTION
) )
1469 // we need to find out if the hit is on left arrow, on month or on right arrow
1471 if ( wxRegion(m_leftArrowRect
).Contains(pos
) == wxInRegion
)
1475 if ( IsDateInRange(m_date
- wxDateSpan::Month()) )
1477 *date
= m_date
- wxDateSpan::Month();
1481 *date
= GetLowerDateLimit();
1485 return wxCAL_HITTEST_DECMONTH
;
1488 if ( wxRegion(m_rightArrowRect
).Contains(pos
) == wxInRegion
)
1492 if ( IsDateInRange(m_date
+ wxDateSpan::Month()) )
1494 *date
= m_date
+ wxDateSpan::Month();
1498 *date
= GetUpperDateLimit();
1502 return wxCAL_HITTEST_INCMONTH
;
1507 ///////////////////////////////////////////////////////////////////////////////////////////////////////
1509 int wday
= pos
.x
/ m_widthCol
;
1510 // if ( y < m_heightRow )
1511 if ( y
< (m_heightRow
+ m_rowOffset
) )
1513 if ( y
> m_rowOffset
)
1517 if ( GetWindowStyle() & wxCAL_MONDAY_FIRST
)
1519 wday
= wday
== 6 ? 0 : wday
+ 1;
1522 *wd
= (wxDateTime::WeekDay
)wday
;
1525 return wxCAL_HITTEST_HEADER
;
1529 return wxCAL_HITTEST_NOWHERE
;
1533 // int week = (y - m_heightRow) / m_heightRow;
1534 int week
= (y
- (m_heightRow
+ m_rowOffset
)) / m_heightRow
;
1535 if ( week
>= 6 || wday
>= 7 )
1537 return wxCAL_HITTEST_NOWHERE
;
1540 wxDateTime dt
= GetStartDate() + wxDateSpan::Days(7*week
+ wday
);
1542 if ( IsDateShown(dt
) )
1547 if ( dt
.GetMonth() == m_date
.GetMonth() )
1550 return wxCAL_HITTEST_DAY
;
1554 return wxCAL_HITTEST_SURROUNDING_WEEK
;
1559 return wxCAL_HITTEST_NOWHERE
;
1563 // ----------------------------------------------------------------------------
1564 // subcontrols events handling
1565 // ----------------------------------------------------------------------------
1567 void wxCalendarCtrl::OnMonthChange(wxCommandEvent
& event
)
1569 wxDateTime::Tm tm
= m_date
.GetTm();
1571 wxDateTime::Month mon
= (wxDateTime::Month
)event
.GetInt();
1572 if ( tm
.mday
> wxDateTime::GetNumberOfDays(mon
, tm
.year
) )
1574 tm
.mday
= wxDateTime::GetNumberOfDays(mon
, tm
.year
);
1577 wxDateTime target
= wxDateTime(tm
.mday
, mon
, tm
.year
);
1579 ChangeMonth(&target
);
1580 SetDateAndNotify(target
);
1583 void wxCalendarCtrl::OnYearChange(wxCommandEvent
& event
)
1585 int year
= (int)event
.GetInt();
1586 if ( year
== INT_MIN
)
1588 // invalid year in the spin control, ignore it
1592 wxDateTime::Tm tm
= m_date
.GetTm();
1594 if ( tm
.mday
> wxDateTime::GetNumberOfDays(tm
.mon
, year
) )
1596 tm
.mday
= wxDateTime::GetNumberOfDays(tm
.mon
, year
);
1599 wxDateTime target
= wxDateTime(tm
.mday
, tm
.mon
, year
);
1601 if ( ChangeYear(&target
) )
1603 SetDateAndNotify(target
);
1607 // In this case we don't want to change the date. That would put us
1608 // inside the same year but a strange number of months forward/back..
1609 m_spinYear
->SetValue(target
.GetYear());
1613 // ----------------------------------------------------------------------------
1614 // keyboard interface
1615 // ----------------------------------------------------------------------------
1617 void wxCalendarCtrl::OnChar(wxKeyEvent
& event
)
1620 switch ( event
.GetKeyCode() )
1624 target
= m_date
+ wxDateSpan::Year();
1625 if ( ChangeYear(&target
) )
1627 SetDateAndNotify(target
);
1633 target
= m_date
- wxDateSpan::Year();
1634 if ( ChangeYear(&target
) )
1636 SetDateAndNotify(target
);
1641 target
= m_date
- wxDateSpan::Month();
1642 ChangeMonth(&target
);
1643 SetDateAndNotify(target
); // always
1647 target
= m_date
+ wxDateSpan::Month();
1648 ChangeMonth(&target
);
1649 SetDateAndNotify(target
); // always
1653 if ( event
.ControlDown() )
1655 target
= wxDateTime(m_date
).SetToNextWeekDay(
1656 GetWindowStyle() & wxCAL_MONDAY_FIRST
1657 ? wxDateTime::Sun
: wxDateTime::Sat
);
1658 if ( !IsDateInRange(target
) )
1660 target
= GetUpperDateLimit();
1662 SetDateAndNotify(target
);
1665 SetDateAndNotify(m_date
+ wxDateSpan::Day());
1669 if ( event
.ControlDown() )
1671 target
= wxDateTime(m_date
).SetToPrevWeekDay(
1672 GetWindowStyle() & wxCAL_MONDAY_FIRST
1673 ? wxDateTime::Mon
: wxDateTime::Sun
);
1674 if ( !IsDateInRange(target
) )
1676 target
= GetLowerDateLimit();
1678 SetDateAndNotify(target
);
1681 SetDateAndNotify(m_date
- wxDateSpan::Day());
1685 SetDateAndNotify(m_date
- wxDateSpan::Week());
1689 SetDateAndNotify(m_date
+ wxDateSpan::Week());
1693 if ( event
.ControlDown() )
1694 SetDateAndNotify(wxDateTime::Today());
1696 SetDateAndNotify(wxDateTime(1, m_date
.GetMonth(), m_date
.GetYear()));
1700 SetDateAndNotify(wxDateTime(m_date
).SetToLastMonthDay());
1704 GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
);
1712 // ----------------------------------------------------------------------------
1713 // holidays handling
1714 // ----------------------------------------------------------------------------
1716 void wxCalendarCtrl::EnableHolidayDisplay(bool display
)
1718 long style
= GetWindowStyle();
1720 style
|= wxCAL_SHOW_HOLIDAYS
;
1722 style
&= ~wxCAL_SHOW_HOLIDAYS
;
1724 SetWindowStyle(style
);
1729 ResetHolidayAttrs();
1734 void wxCalendarCtrl::SetHolidayAttrs()
1736 if ( GetWindowStyle() & wxCAL_SHOW_HOLIDAYS
)
1738 ResetHolidayAttrs();
1740 wxDateTime::Tm tm
= m_date
.GetTm();
1741 wxDateTime
dtStart(1, tm
.mon
, tm
.year
),
1742 dtEnd
= dtStart
.GetLastMonthDay();
1744 wxDateTimeArray hol
;
1745 wxDateTimeHolidayAuthority::GetHolidaysInRange(dtStart
, dtEnd
, hol
);
1747 size_t count
= hol
.GetCount();
1748 for ( size_t n
= 0; n
< count
; n
++ )
1750 SetHoliday(hol
[n
].GetDay());
1755 void wxCalendarCtrl::SetHoliday(size_t day
)
1757 wxCHECK_RET( day
> 0 && day
< 32, _T("invalid day in SetHoliday") );
1759 wxCalendarDateAttr
*attr
= GetAttr(day
);
1762 attr
= new wxCalendarDateAttr
;
1765 attr
->SetHoliday(TRUE
);
1767 // can't use SetAttr() because it would delete this pointer
1768 m_attrs
[day
- 1] = attr
;
1771 void wxCalendarCtrl::ResetHolidayAttrs()
1773 for ( size_t day
= 0; day
< 31; day
++ )
1777 m_attrs
[day
]->SetHoliday(FALSE
);
1782 // ----------------------------------------------------------------------------
1784 // ----------------------------------------------------------------------------
1786 void wxCalendarEvent::Init()
1788 m_wday
= wxDateTime::Inv_WeekDay
;
1791 wxCalendarEvent::wxCalendarEvent(wxCalendarCtrl
*cal
, wxEventType type
)
1792 : wxCommandEvent(type
, cal
->GetId())
1794 m_date
= cal
->GetDate();
1795 SetEventObject(cal
);
1798 #endif // wxUSE_CALENDARCTRL