Keep displayed month and year in sync in wxGenericCalendarCtrl.

When the date was constrained to a range in wxGenericCalendarCtrl, the display
of the month in the month combobox could get out of sync with its real value.

Ensure that the correct month is always displayed and also simplify the code
by removing the apparently unnecessarily complex logic in ChangeYear() and
ChangeMonth() functions.

Closes #11060.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65901 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-10-24 22:40:41 +00:00
parent 69060f4f0c
commit 3c9863aca7
2 changed files with 36 additions and 88 deletions

View File

@@ -202,12 +202,12 @@ private:
// is this date shown? // is this date shown?
bool IsDateShown(const wxDateTime& date) const; bool IsDateShown(const wxDateTime& date) const;
// is this date in the given range? // is this date in the currently allowed range?
bool IsDateInRange(const wxDateTime& date) const; bool IsDateInRange(const wxDateTime& date) const;
// range helpers // adjust the date to the currently allowed range, return true if it was
bool ChangeYear(wxDateTime* target) const; // changed
bool ChangeMonth(wxDateTime* target) const; bool AdjustDateToRange(wxDateTime *date) const;
// redraw the given date // redraw the given date
void RefreshDate(const wxDateTime& date); void RefreshDate(const wxDateTime& date);

View File

@@ -682,64 +682,21 @@ bool wxGenericCalendarCtrl::IsDateInRange(const wxDateTime& date) const
&& ( ( m_highdate.IsValid() ) ? ( date <= m_highdate ) : true ) ); && ( ( m_highdate.IsValid() ) ? ( date <= m_highdate ) : true ) );
} }
bool wxGenericCalendarCtrl::ChangeYear(wxDateTime* target) const bool wxGenericCalendarCtrl::AdjustDateToRange(wxDateTime *date) const
{ {
bool retval = false; if ( m_lowdate.IsValid() && *date < m_lowdate )
if ( !(IsDateInRange(*target)) )
{ {
if ( target->GetYear() < m_date.GetYear() ) *date = m_lowdate;
{ return true;
if ( target->GetYear() >= GetLowerDateLimit().GetYear() )
{
*target = GetLowerDateLimit();
retval = true;
}
else
{
*target = m_date;
}
}
else
{
if ( target->GetYear() <= GetUpperDateLimit().GetYear() )
{
*target = GetUpperDateLimit();
retval = true;
}
else
{
*target = m_date;
}
}
}
else
{
retval = true;
} }
return retval; if ( m_highdate.IsValid() && *date > m_highdate )
{
*date = m_highdate;
return true;
} }
bool wxGenericCalendarCtrl::ChangeMonth(wxDateTime* target) const return false;
{
bool retval = true;
if ( !(IsDateInRange(*target)) )
{
retval = false;
if ( target->GetMonth() < m_date.GetMonth() )
{
*target = GetLowerDateLimit();
}
else
{
*target = GetUpperDateLimit();
}
}
return retval;
} }
size_t wxGenericCalendarCtrl::GetWeek(const wxDateTime& date) const size_t wxGenericCalendarCtrl::GetWeek(const wxDateTime& date) const
@@ -1649,10 +1606,15 @@ void wxGenericCalendarCtrl::OnMonthChange(wxCommandEvent& event)
tm.mday = wxDateTime::GetNumberOfDays(mon, tm.year); tm.mday = wxDateTime::GetNumberOfDays(mon, tm.year);
} }
wxDateTime target = wxDateTime(tm.mday, mon, tm.year); wxDateTime dt(tm.mday, mon, tm.year);
if ( AdjustDateToRange(&dt) )
{
// The date must have been changed to ensure it's in valid range,
// reflect this in the month choice control.
m_comboMonth->SetSelection(dt.GetMonth());
}
ChangeMonth(&target); SetDateAndNotify(dt);
SetDateAndNotify(target);
} }
void wxGenericCalendarCtrl::HandleYearChange(wxCommandEvent& event) void wxGenericCalendarCtrl::HandleYearChange(wxCommandEvent& event)
@@ -1671,18 +1633,15 @@ void wxGenericCalendarCtrl::HandleYearChange(wxCommandEvent& event)
tm.mday = wxDateTime::GetNumberOfDays(tm.mon, year); tm.mday = wxDateTime::GetNumberOfDays(tm.mon, year);
} }
wxDateTime target = wxDateTime(tm.mday, tm.mon, year); wxDateTime dt(tm.mday, tm.mon, year);
if ( AdjustDateToRange(&dt) )
{
// As above, if the date was changed to keep it in valid range, its
// possibly changed year must be shown in the GUI.
m_spinYear->SetValue(dt.GetYear());
}
if ( ChangeYear(&target) ) SetDateAndNotify(dt);
{
SetDateAndNotify(target);
}
else
{
// In this case we don't want to change the date. That would put us
// inside the same year but a strange number of months forward/back..
m_spinYear->SetValue(target.GetYear());
}
} }
void wxGenericCalendarCtrl::OnYearChange(wxSpinEvent& event) void wxGenericCalendarCtrl::OnYearChange(wxSpinEvent& event)
@@ -1716,43 +1675,31 @@ void wxGenericCalendarCtrl::OnSysColourChanged(wxSysColourChangedEvent& event)
void wxGenericCalendarCtrl::OnChar(wxKeyEvent& event) void wxGenericCalendarCtrl::OnChar(wxKeyEvent& event)
{ {
wxDateTime target;
switch ( event.GetKeyCode() ) switch ( event.GetKeyCode() )
{ {
case wxT('+'): case wxT('+'):
case WXK_ADD: case WXK_ADD:
target = m_date + wxDateSpan::Year(); SetDateAndNotify(m_date + wxDateSpan::Year());
if ( ChangeYear(&target) )
{
SetDateAndNotify(target);
}
break; break;
case wxT('-'): case wxT('-'):
case WXK_SUBTRACT: case WXK_SUBTRACT:
target = m_date - wxDateSpan::Year(); SetDateAndNotify(m_date - wxDateSpan::Year());
if ( ChangeYear(&target) )
{
SetDateAndNotify(target);
}
break; break;
case WXK_PAGEUP: case WXK_PAGEUP:
target = m_date - wxDateSpan::Month(); SetDateAndNotify(m_date - wxDateSpan::Month());
ChangeMonth(&target);
SetDateAndNotify(target); // always
break; break;
case WXK_PAGEDOWN: case WXK_PAGEDOWN:
target = m_date + wxDateSpan::Month(); SetDateAndNotify(m_date + wxDateSpan::Month());
ChangeMonth(&target);
SetDateAndNotify(target); // always
break; break;
case WXK_RIGHT: case WXK_RIGHT:
if ( event.ControlDown() ) if ( event.ControlDown() )
{ {
target = wxDateTime(m_date).SetToNextWeekDay( wxDateTime
target = m_date.SetToNextWeekDay(
GetWindowStyle() & wxCAL_MONDAY_FIRST GetWindowStyle() & wxCAL_MONDAY_FIRST
? wxDateTime::Sun : wxDateTime::Sat); ? wxDateTime::Sun : wxDateTime::Sat);
if ( !IsDateInRange(target) ) if ( !IsDateInRange(target) )
@@ -1768,7 +1715,8 @@ void wxGenericCalendarCtrl::OnChar(wxKeyEvent& event)
case WXK_LEFT: case WXK_LEFT:
if ( event.ControlDown() ) if ( event.ControlDown() )
{ {
target = wxDateTime(m_date).SetToPrevWeekDay( wxDateTime
target = m_date.SetToPrevWeekDay(
GetWindowStyle() & wxCAL_MONDAY_FIRST GetWindowStyle() & wxCAL_MONDAY_FIRST
? wxDateTime::Mon : wxDateTime::Sun); ? wxDateTime::Mon : wxDateTime::Sun);
if ( !IsDateInRange(target) ) if ( !IsDateInRange(target) )