diff --git a/include/wx/generic/gridctrl.h b/include/wx/generic/gridctrl.h index d55edddfd3..1bdb812751 100644 --- a/include/wx/generic/gridctrl.h +++ b/include/wx/generic/gridctrl.h @@ -171,6 +171,8 @@ public: #include "wx/datetime.h" +namespace wxGridPrivate { class DateParseParams; } + // renderer for the cells containing dates only, without time component class WXDLLIMPEXP_ADV wxGridCellDateRenderer : public wxGridCellStringRenderer { @@ -207,7 +209,11 @@ public: protected: wxString GetString(const wxGrid& grid, int row, int col); - virtual bool Parse(const wxString& text, wxDateTime& result); + + // This is overridden in wxGridCellDateTimeRenderer which uses a separate + // input format and forbids fallback to ParseDate(). + virtual void + GetDateParseParams(wxGridPrivate::DateParseParams& params) const; wxString m_oformat; wxDateTime::TimeZone m_tz; @@ -222,18 +228,17 @@ public: wxGridCellDateTimeRenderer(const wxGridCellDateTimeRenderer& other) : wxGridCellDateRenderer(other), - m_iformat(other.m_iformat), - m_dateDef(other.m_dateDef) + m_iformat(other.m_iformat) { } virtual wxGridCellRenderer *Clone() const wxOVERRIDE; protected: - virtual bool Parse(const wxString& text, wxDateTime& result) wxOVERRIDE; + virtual void + GetDateParseParams(wxGridPrivate::DateParseParams& params) const wxOVERRIDE; wxString m_iformat; - wxDateTime m_dateDef; }; #endif // wxUSE_DATETIME diff --git a/include/wx/generic/grideditors.h b/include/wx/generic/grideditors.h index 4510d31944..025c9faff7 100644 --- a/include/wx/generic/grideditors.h +++ b/include/wx/generic/grideditors.h @@ -390,7 +390,9 @@ public: class WXDLLIMPEXP_ADV wxGridCellDateEditor : public wxGridCellEditor { public: - wxGridCellDateEditor() { } + explicit wxGridCellDateEditor(const wxString& format = wxString()); + + virtual void SetParameters(const wxString& params) wxOVERRIDE; virtual void Create(wxWindow* parent, wxWindowID id, @@ -414,6 +416,7 @@ protected: private: wxDateTime m_value; + wxString m_format; wxDECLARE_NO_COPY_CLASS(wxGridCellDateEditor); }; diff --git a/include/wx/generic/private/grid.h b/include/wx/generic/private/grid.h index 1330bb1044..07c432f588 100644 --- a/include/wx/generic/private/grid.h +++ b/include/wx/generic/private/grid.h @@ -1084,5 +1084,60 @@ wxGetContentRect(wxSize contentSize, int hAlign, int vAlign); +namespace wxGridPrivate +{ + +#if wxUSE_DATETIME + +// This is used as TryGetValueAsDate() parameter. +class DateParseParams +{ +public: + // Unfortunately we have to provide the default ctor (and also make the + // members non-const) because we use these objects as out-parameters as + // they are not fully declared in the public headers. The factory functions + // below must be used to create a really usable object. + DateParseParams() : fallbackParseDate(false) { } + + // Use these functions to really initialize the object. + static DateParseParams WithFallback(const wxString& format) + { + return DateParseParams(format, true); + } + + static DateParseParams WithoutFallback(const wxString& format) + { + return DateParseParams(format, false); + } + + // The usual format, e.g. "%x" or "%Y-%m-%d". + wxString format; + + // Whether fall back to ParseDate() is allowed. + bool fallbackParseDate; + +private: + DateParseParams(const wxString& format_, bool fallbackParseDate_) + : format(format_), + fallbackParseDate(fallbackParseDate_) + { + } +}; + +// Helper function trying to get a date from the given cell: if possible, get +// the date value from the table directly, otherwise get the string value for +// this cell and try to parse it using the specified date format and, if this +// doesn't work and fallbackParseDate is true, try using ParseDate() as a +// fallback. If this still fails, returns false. +bool +TryGetValueAsDate(wxDateTime& result, + const DateParseParams& params, + const wxGrid& grid, + int row, int col); + +#endif // wxUSE_DATETIME + +} // namespace wxGridPrivate + #endif // wxUSE_GRID #endif // _WX_GENERIC_GRID_PRIVATE_H_ diff --git a/interface/wx/grid.h b/interface/wx/grid.h index 9e33e41e4d..3a6129a3f6 100644 --- a/interface/wx/grid.h +++ b/interface/wx/grid.h @@ -248,16 +248,6 @@ public: */ wxGridCellDateTimeRenderer(const wxString& outformat = wxDefaultDateTimeFormat, const wxString& informat = wxDefaultDateTimeFormat); - - - /** - Sets the strptime()-like format string which will be used to parse - the date/time. - - @param params - strptime()-like format string used to parse the date/time. - */ - virtual void SetParameters(const wxString& params); }; /** @@ -1092,8 +1082,14 @@ class wxGridCellDateEditor : public wxGridCellEditor public: /** Date editor constructor. + + @param format Optional format for the date displayed in the associated + cell. By default, the locale-specific date format ("%x") is assumed. + You would typically want to specify the same format as the one + used with the cell renderer, if a non-default one is used. + Note that this parameter is only available since wxWidgets 3.1.5. */ - wxGridCellDateEditor(); + explicit wxGridCellDateEditor(const wxString& format = wxString()); }; diff --git a/src/generic/gridctrl.cpp b/src/generic/gridctrl.cpp index a82d8ea24f..f1e83880d8 100644 --- a/src/generic/gridctrl.cpp +++ b/src/generic/gridctrl.cpp @@ -76,6 +76,47 @@ void wxGridCellRenderer::Draw(wxGrid& grid, #if wxUSE_DATETIME +bool +wxGridPrivate::TryGetValueAsDate(wxDateTime& result, + const DateParseParams& params, + const wxGrid& grid, + int row, int col) +{ + wxGridTableBase *table = grid.GetTable(); + + if ( table->CanGetValueAs(row, col, wxGRID_VALUE_DATETIME) ) + { + void * tempval = table->GetValueAsCustom(row, col,wxGRID_VALUE_DATETIME); + + if (tempval) + { + result = *((wxDateTime *)tempval); + delete (wxDateTime *)tempval; + + return true; + } + + } + + const wxString text = table->GetValue(row, col); + + wxString::const_iterator end; + + if ( result.ParseFormat(text, params.format, &end) && end == text.end() ) + return true; + + // Check if we can fall back to free-form parsing, which notably allows us + // to parse strings such as "today" or "tomorrow" which would be never + // accepted by ParseFormat(). + if ( params.fallbackParseDate && + result.ParseDate(text, &end) && end == text.end() ) + return true; + + return false; +} + +using namespace wxGridPrivate; + // Enables a grid cell to display a formatted date wxGridCellDateRenderer::wxGridCellDateRenderer(const wxString& outformat) @@ -98,41 +139,23 @@ wxGridCellRenderer *wxGridCellDateRenderer::Clone() const wxString wxGridCellDateRenderer::GetString(const wxGrid& grid, int row, int col) { - wxGridTableBase *table = grid.GetTable(); - - bool hasDatetime = false; - wxDateTime val; wxString text; - if ( table->CanGetValueAs(row, col, wxGRID_VALUE_DATETIME) ) - { - void * tempval = table->GetValueAsCustom(row, col,wxGRID_VALUE_DATETIME); - if (tempval) - { - val = *((wxDateTime *)tempval); - hasDatetime = true; - delete (wxDateTime *)tempval; - } + DateParseParams params; + GetDateParseParams(params); - } - - if (!hasDatetime ) - { - text = table->GetValue(row, col); - hasDatetime = Parse(text, val); - } - - if ( hasDatetime ) + wxDateTime val; + if ( TryGetValueAsDate(val, params, grid, row, col) ) text = val.Format(m_oformat, m_tz ); // If we failed to parse string just show what we where given? return text; } -bool wxGridCellDateRenderer::Parse(const wxString& text, wxDateTime& result) +void +wxGridCellDateRenderer::GetDateParseParams(DateParseParams& params) const { - wxString::const_iterator end; - return result.ParseDate(text, &end) && end == text.end(); + params = DateParseParams::WithFallback(m_oformat); } void wxGridCellDateRenderer::Draw(wxGrid& grid, @@ -192,7 +215,6 @@ void wxGridCellDateRenderer::SetParameters(const wxString& params) wxGridCellDateTimeRenderer::wxGridCellDateTimeRenderer(const wxString& outformat, const wxString& informat) : wxGridCellDateRenderer(outformat) , m_iformat(informat) - , m_dateDef(wxDefaultDateTime) { } @@ -201,10 +223,10 @@ wxGridCellRenderer *wxGridCellDateTimeRenderer::Clone() const return new wxGridCellDateTimeRenderer(*this); } -bool wxGridCellDateTimeRenderer::Parse(const wxString& text, wxDateTime& result) +void +wxGridCellDateTimeRenderer::GetDateParseParams(DateParseParams& params) const { - const char * const end = result.ParseFormat(text, m_iformat, m_dateDef); - return end && !*end; + params = DateParseParams::WithoutFallback(m_iformat); } #endif // wxUSE_DATETIME diff --git a/src/generic/grideditors.cpp b/src/generic/grideditors.cpp index 0c7df337e4..5f0793bcd5 100644 --- a/src/generic/grideditors.cpp +++ b/src/generic/grideditors.cpp @@ -1861,6 +1861,19 @@ struct wxGridCellDateEditorKeyHandler }; #endif // __WXGTK__ +wxGridCellDateEditor::wxGridCellDateEditor(const wxString& format) +{ + SetParameters(format); +} + +void wxGridCellDateEditor::SetParameters(const wxString& params) +{ + if ( params.empty() ) + m_format = "%x"; + else + m_format = params; +} + void wxGridCellDateEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) { @@ -1907,8 +1920,10 @@ void wxGridCellDateEditor::BeginEdit(int row, int col, wxGrid* grid) { wxASSERT_MSG(m_control, "The wxGridCellDateEditor must be created first!"); - const wxString dateStr = grid->GetTable()->GetValue(row, col); - if ( !m_value.ParseDate(dateStr) ) + using namespace wxGridPrivate; + + if ( !TryGetValueAsDate(m_value, DateParseParams::WithFallback(m_format), + *grid, row, col) ) { // Invalidate m_value, so that it always compares different // to any value returned from DatePicker()->GetValue(). @@ -1960,7 +1975,7 @@ void wxGridCellDateEditor::Reset() wxGridCellEditor *wxGridCellDateEditor::Clone() const { - return new wxGridCellDateEditor(); + return new wxGridCellDateEditor(m_format); } wxString wxGridCellDateEditor::GetValue() const