diff --git a/interface/wx/calctrl.h b/interface/wx/calctrl.h index 40bd51493d..a756e458e3 100644 --- a/interface/wx/calctrl.h +++ b/interface/wx/calctrl.h @@ -469,7 +469,8 @@ public: The @a date parameter must be valid and in the currently valid range as set by SetDateRange(), otherwise the current date is not changed and - the function returns @false. + the function returns @false and, additionally, triggers an assertion + failure if the date is invalid. */ virtual bool SetDate(const wxDateTime& date); diff --git a/src/generic/calctrlg.cpp b/src/generic/calctrlg.cpp index 58875a3066..3c5b8ce4e9 100644 --- a/src/generic/calctrlg.cpp +++ b/src/generic/calctrlg.cpp @@ -434,6 +434,8 @@ bool wxGenericCalendarCtrl::EnableMonthChange(bool enable) bool wxGenericCalendarCtrl::SetDate(const wxDateTime& date) { + wxCHECK_MSG( date.IsValid(), false, "invalid date" ); + bool retval = true; bool sameMonth = m_date.GetMonth() == date.GetMonth(), diff --git a/src/generic/datectlg.cpp b/src/generic/datectlg.cpp index d5abccfd3a..5ddadc3933 100644 --- a/src/generic/datectlg.cpp +++ b/src/generic/datectlg.cpp @@ -121,16 +121,41 @@ public: return m_combo->GetTextCtrl()->IsEmpty(); } + // This is public because it is used by wxDatePickerCtrlGeneric itself to + // change the date when the text control field changes. The reason it's + // done there and not in this class itself is mostly historic. + void ChangeDateAndNotifyIfValid() + { + wxDateTime dt; + if ( !ParseDateTime(m_combo->GetValue(), &dt) ) + { + // The user must be in the process of updating the date, don't do + // anything -- we'll take care of ensuring it's valid on focus loss + // later. + return; + } + + if ( dt == GetDate() ) + { + // No need to send event if the date hasn't changed. + return; + } + + // We change the date immediately, as it's more consistent with the + // native MSW version and avoids another event on focus loss. + SetDate(dt); + + SendDateEvent(dt); + } + +private: bool ParseDateTime(const wxString& s, wxDateTime* pDt) { wxASSERT(pDt); - if ( !s.empty() ) - { - pDt->ParseFormat(s, m_format); - if ( !pDt->IsValid() ) - return false; - } + pDt->ParseFormat(s, m_format); + if ( !pDt->IsValid() ) + return false; return true; } @@ -147,8 +172,6 @@ public: datePicker->GetEventHandler()->ProcessEvent(event); } -private: - void OnCalKey(wxKeyEvent & ev) { if (ev.GetKeyCode() == WXK_ESCAPE && !ev.HasModifiers()) @@ -183,17 +206,33 @@ private: dt = dtOld; } - m_combo->SetText(GetStringValueFor(dt)); - - if ( !dt.IsValid() && HasDPFlag(wxDP_ALLOWNONE) ) - return; - - // notify that we had to change the date after validation - if ( (dt.IsValid() && (!dtOld.IsValid() || dt != dtOld)) || - (!dt.IsValid() && dtOld.IsValid()) ) + if ( dt.IsValid() ) { + // Set it at wxCalendarCtrl level. SetDate(dt); - SendDateEvent(dt); + + // And show it in the text field. + m_combo->SetText(GetStringValue()); + + // And if the date has really changed, send an event about it. + if ( dt != dtOld ) + SendDateEvent(dt); + } + else // Invalid date currently entered. + { + if ( HasDPFlag(wxDP_ALLOWNONE) ) + { + // Clear the text part to indicate that the date is invalid. + // Would it be better to indicate this in some more clear way, + // e.g. maybe by using "[none]" or something like this? + m_combo->SetText(wxString()); + } + else + { + // Restore the original value, as we can't have invalid value + // in this control. + m_combo->SetText(GetStringValue()); + } } } @@ -252,7 +291,7 @@ private: virtual void SetStringValue(const wxString& s) wxOVERRIDE { wxDateTime dt; - if ( !s.empty() && ParseDateTime(s, &dt) ) + if ( ParseDateTime(s, &dt) ) SetDate(dt); //else: keep the old value } @@ -475,13 +514,8 @@ void wxDatePickerCtrlGeneric::OnText(wxCommandEvent &ev) ev.SetId(GetId()); GetParent()->GetEventHandler()->ProcessEvent(ev); - // We'll create an additional event if the date is valid. - // If the date isn't valid, the user's probably in the middle of typing - wxDateTime dt; - if ( !m_popup || !m_popup->ParseDateTime(m_combo->GetValue(), &dt) ) - return; - - m_popup->SendDateEvent(dt); + if ( m_popup ) + m_popup->ChangeDateAndNotifyIfValid(); } #endif // wxUSE_DATEPICKCTRL diff --git a/src/gtk/calctrl.cpp b/src/gtk/calctrl.cpp index 221fa53ef5..fbeb93edf8 100644 --- a/src/gtk/calctrl.cpp +++ b/src/gtk/calctrl.cpp @@ -198,7 +198,9 @@ bool wxGtkCalendarCtrl::EnableMonthChange(bool enable) bool wxGtkCalendarCtrl::SetDate(const wxDateTime& date) { - if ( date.IsValid() && !IsInValidRange(date) ) + wxCHECK_MSG( date.IsValid(), false, "invalid date" ); + + if ( !IsInValidRange(date) ) return false; g_signal_handlers_block_by_func(m_widget,