diff --git a/docs/changes.txt b/docs/changes.txt index a3fa1d5894..61dbacf733 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -517,6 +517,7 @@ GTK: - wxTLW generates wxEVT_MAXIMIZE. - Fix copying clipboard data to primary selection (David Hart). - Implement wxGraphicsContext::GetSize() (Marcin Wojdyr). +- Implement wxCalendarCtrl::SetDateRange() for the native control. MSW: diff --git a/include/wx/gtk/calctrl.h b/include/wx/gtk/calctrl.h index e9afdfec17..fee84ec1a8 100644 --- a/include/wx/gtk/calctrl.h +++ b/include/wx/gtk/calctrl.h @@ -38,15 +38,31 @@ public: virtual bool SetDate(const wxDateTime& date); virtual wxDateTime GetDate() const; + virtual bool SetDateRange(const wxDateTime& lowerdate = wxDefaultDateTime, + const wxDateTime& upperdate = wxDefaultDateTime); + virtual bool GetDateRange(wxDateTime *lowerdate, wxDateTime *upperdate) const; + virtual bool EnableMonthChange(bool enable = true); virtual void Mark(size_t day, bool mark); // implementation // -------------- - wxDateTime m_selectedDate; + + void GTKGenerateEvent(wxEventType type); private: + bool IsInValidRange(const wxDateTime& dt) const; + + // Range of the dates that can be selected by user, either or both may be + // invalid to indicate that no corresponding restriction is set. + wxDateTime m_validStart, + m_validEnd; + + // Last known selected date, may be different from the real selection in + // the control while a handler for day-selected is running. + wxDateTime m_selectedDate; + DECLARE_DYNAMIC_CLASS(wxGtkCalendarCtrl) wxDECLARE_NO_COPY_CLASS(wxGtkCalendarCtrl); }; diff --git a/interface/wx/calctrl.h b/interface/wx/calctrl.h index 799465bc89..e4f2cd8702 100644 --- a/interface/wx/calctrl.h +++ b/interface/wx/calctrl.h @@ -424,7 +424,9 @@ public: /** Sets the current date. - The @a date parameter must be valid. + 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. */ virtual bool SetDate(const wxDateTime& date); @@ -476,14 +478,12 @@ public: /** @name Date Range Functions - - The functions in this section are currently implemented in the generic - and MSW versions and do nothing in the native GTK implementation. */ //@{ /** - Restrict the dates shown by the control to the specified range. + Restrict the dates that can be selected in the control to the specified + range. If either date is set, the corresponding limit will be enforced and @true returned. If none are set, the existing restrictions are removed diff --git a/samples/calendar/calendar.cpp b/samples/calendar/calendar.cpp index 7496322332..73cf2adf12 100644 --- a/samples/calendar/calendar.cpp +++ b/samples/calendar/calendar.cpp @@ -280,7 +280,6 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) #ifdef __WXGTK20__ EVT_UPDATE_UI(Calendar_Cal_Monday, MyFrame::OnUpdateUIGenericOnly) EVT_UPDATE_UI(Calendar_Cal_Holidays, MyFrame::OnUpdateUIGenericOnly) - EVT_UPDATE_UI(Calendar_Cal_LimitDates, MyFrame::OnUpdateUIGenericOnly) #endif EVT_UPDATE_UI(Calendar_Cal_Special, MyFrame::OnUpdateUIGenericOnly) EVT_UPDATE_UI(Calendar_Cal_SurroundWeeks, MyFrame::OnUpdateUIGenericOnly) diff --git a/src/gtk/calctrl.cpp b/src/gtk/calctrl.cpp index 09104839e0..9d23433761 100644 --- a/src/gtk/calctrl.cpp +++ b/src/gtk/calctrl.cpp @@ -28,27 +28,19 @@ extern "C" { static void gtk_day_selected_callback(GtkWidget *WXUNUSED(widget), wxGtkCalendarCtrl *cal) { - wxDateTime date = cal->GetDate(); - if (cal->m_selectedDate == date) - return; - - cal->m_selectedDate = date; - - cal->GenerateEvent(wxEVT_CALENDAR_SEL_CHANGED); - // send deprecated event - cal->GenerateEvent(wxEVT_CALENDAR_DAY_CHANGED); + cal->GTKGenerateEvent(wxEVT_CALENDAR_SEL_CHANGED); } static void gtk_day_selected_double_click_callback(GtkWidget *WXUNUSED(widget), wxGtkCalendarCtrl *cal) { - cal->GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED); + cal->GTKGenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED); } static void gtk_month_changed_callback(GtkWidget *WXUNUSED(widget), wxGtkCalendarCtrl *cal) { - cal->GenerateEvent(wxEVT_CALENDAR_PAGE_CHANGED); + cal->GTKGenerateEvent(wxEVT_CALENDAR_PAGE_CHANGED); } // callbacks that send deprecated events @@ -56,13 +48,13 @@ static void gtk_month_changed_callback(GtkWidget *WXUNUSED(widget), static void gtk_prev_month_callback(GtkWidget *WXUNUSED(widget), wxGtkCalendarCtrl *cal) { - cal->GenerateEvent(wxEVT_CALENDAR_MONTH_CHANGED); + cal->GTKGenerateEvent(wxEVT_CALENDAR_MONTH_CHANGED); } static void gtk_prev_year_callback(GtkWidget *WXUNUSED(widget), wxGtkCalendarCtrl *cal) { - cal->GenerateEvent(wxEVT_CALENDAR_YEAR_CHANGED); + cal->GTKGenerateEvent(wxEVT_CALENDAR_YEAR_CHANGED); } } @@ -127,6 +119,74 @@ bool wxGtkCalendarCtrl::Create(wxWindow *parent, return true; } +void wxGtkCalendarCtrl::GTKGenerateEvent(wxEventType type) +{ + // First check if the new date is in the specified range. + wxDateTime dt = GetDate(); + if ( !IsInValidRange(dt) ) + { + if ( m_validStart.IsValid() && dt < m_validStart ) + dt = m_validStart; + else + dt = m_validEnd; + + SetDate(dt); + + return; + } + + if ( type == wxEVT_CALENDAR_SEL_CHANGED ) + { + // Don't generate this event if the new date is the same as the old + // one. + if ( m_selectedDate == dt ) + return; + + m_selectedDate = dt; + + GenerateEvent(type); + + // Also send the deprecated event together with the new one. + GenerateEvent(wxEVT_CALENDAR_DAY_CHANGED); + } + else + { + GenerateEvent(type); + } +} + +bool wxGtkCalendarCtrl::IsInValidRange(const wxDateTime& dt) const +{ + return (!m_validStart.IsValid() || m_validStart <= dt) && + (!m_validEnd.IsValid() || dt <= m_validEnd); +} + +bool +wxGtkCalendarCtrl::SetDateRange(const wxDateTime& lowerdate, + const wxDateTime& upperdate) +{ + if ( lowerdate.IsValid() && upperdate.IsValid() && lowerdate >= upperdate ) + return false; + + m_validStart = lowerdate; + m_validEnd = upperdate; + + return true; +} + +bool +wxGtkCalendarCtrl::GetDateRange(wxDateTime *lowerdate, + wxDateTime *upperdate) const +{ + if ( lowerdate ) + *lowerdate = m_validStart; + if ( upperdate ) + *upperdate = m_validEnd; + + return m_validStart.IsValid() || m_validEnd.IsValid(); +} + + bool wxGtkCalendarCtrl::EnableMonthChange(bool enable) { if ( !wxCalendarCtrlBase::EnableMonthChange(enable) ) @@ -140,6 +200,9 @@ bool wxGtkCalendarCtrl::EnableMonthChange(bool enable) bool wxGtkCalendarCtrl::SetDate(const wxDateTime& date) { + if ( date.IsValid() && !IsInValidRange(date) ) + return false; + g_signal_handlers_block_by_func(m_widget, (gpointer) gtk_day_selected_callback, this); g_signal_handlers_block_by_func(m_widget,