Add support for custom numeric formats to wxGrid.

Allow %e and %g formats (as well as their upper-letter equivalents) in
addition to the default %f format for number display in wxGrid.

Closes #13583.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69856 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2011-11-28 13:23:33 +00:00
parent 09c0ebcf96
commit 1d8d3cc5a1
7 changed files with 280 additions and 59 deletions

View File

@@ -477,6 +477,7 @@ All (GUI):
- Allow setting window shape to arbitrary wxGraphicsPath. - Allow setting window shape to arbitrary wxGraphicsPath.
- Added wxTextEntry::AutoCompleteDirectories(). - Added wxTextEntry::AutoCompleteDirectories().
- Support float, double and file name values in wxGenericValidator (troelsk). - Support float, double and file name values in wxGenericValidator (troelsk).
- Add support for custom numeric formats to wxGrid (Kinaou Hervé).
- Fix keyboard navigation in wxGrid with hidden columns (ivan_14_32). - Fix keyboard navigation in wxGrid with hidden columns (ivan_14_32).
- Add wxDataViewEvent::IsEditCancelled() (Allonii). - Add wxDataViewEvent::IsEditCancelled() (Allonii).
- Send EVT_DATAVIEW_ITEM_CONTEXT_MENU events even when not clicking on an item. - Send EVT_DATAVIEW_ITEM_CONTEXT_MENU events even when not clicking on an item.

View File

@@ -81,13 +81,17 @@ protected:
class WXDLLIMPEXP_ADV wxGridCellFloatRenderer : public wxGridCellStringRenderer class WXDLLIMPEXP_ADV wxGridCellFloatRenderer : public wxGridCellStringRenderer
{ {
public: public:
wxGridCellFloatRenderer(int width = -1, int precision = -1); wxGridCellFloatRenderer(int width = -1,
int precision = -1,
int format = wxGRID_FLOAT_FORMAT_DEFAULT);
// get/change formatting parameters // get/change formatting parameters
int GetWidth() const { return m_width; } int GetWidth() const { return m_width; }
void SetWidth(int width) { m_width = width; m_format.clear(); } void SetWidth(int width) { m_width = width; m_format.clear(); }
int GetPrecision() const { return m_precision; } int GetPrecision() const { return m_precision; }
void SetPrecision(int precision) { m_precision = precision; m_format.clear(); } void SetPrecision(int precision) { m_precision = precision; m_format.clear(); }
int GetFormat() const { return m_style; }
void SetFormat(int format) { m_style = format; m_format.clear(); }
// draw the string right aligned with given width/precision // draw the string right aligned with given width/precision
virtual void Draw(wxGrid& grid, virtual void Draw(wxGrid& grid,
@@ -102,7 +106,8 @@ public:
wxDC& dc, wxDC& dc,
int row, int col); int row, int col);
// parameters string format is "width[,precision]" // parameters string format is "width[,precision[,format]]"
// with format being one of f|e|g|E|F|G
virtual void SetParameters(const wxString& params); virtual void SetParameters(const wxString& params);
virtual wxGridCellRenderer *Clone() const; virtual wxGridCellRenderer *Clone() const;
@@ -115,6 +120,7 @@ private:
int m_width, int m_width,
m_precision; m_precision;
int m_style;
wxString m_format; wxString m_format;
}; };

View File

@@ -154,11 +154,38 @@ private:
wxDECLARE_NO_COPY_CLASS(wxGridCellNumberEditor); wxDECLARE_NO_COPY_CLASS(wxGridCellNumberEditor);
}; };
enum wxGridCellFloatFormat
{
// Decimal floating point (%f)
wxGRID_FLOAT_FORMAT_FIXED = 0x0010,
// Scientific notation (mantise/exponent) using e character (%e)
wxGRID_FLOAT_FORMAT_SCIENTIFIC = 0x0020,
// Use the shorter of %e or %f (%g)
wxGRID_FLOAT_FORMAT_COMPACT = 0x0040,
// To use in combination with one of the above formats (%F/%E/%G)
wxGRID_FLOAT_FORMAT_UPPER = 0x0080,
// Format used by default.
wxGRID_FLOAT_FORMAT_DEFAULT = wxGRID_FLOAT_FORMAT_FIXED,
// A mask to extract format from the combination of flags.
wxGRID_FLOAT_FORMAT_MASK = wxGRID_FLOAT_FORMAT_FIXED |
wxGRID_FLOAT_FORMAT_SCIENTIFIC |
wxGRID_FLOAT_FORMAT_COMPACT |
wxGRID_FLOAT_FORMAT_UPPER
};
// the editor for floating point numbers (double) data // the editor for floating point numbers (double) data
class WXDLLIMPEXP_ADV wxGridCellFloatEditor : public wxGridCellTextEditor class WXDLLIMPEXP_ADV wxGridCellFloatEditor : public wxGridCellTextEditor
{ {
public: public:
wxGridCellFloatEditor(int width = -1, int precision = -1); wxGridCellFloatEditor(int width = -1,
int precision = -1,
int format = wxGRID_FLOAT_FORMAT_DEFAULT);
virtual void Create(wxWindow* parent, virtual void Create(wxWindow* parent,
wxWindowID id, wxWindowID id,
@@ -176,18 +203,22 @@ public:
virtual wxGridCellEditor *Clone() const virtual wxGridCellEditor *Clone() const
{ return new wxGridCellFloatEditor(m_width, m_precision); } { return new wxGridCellFloatEditor(m_width, m_precision); }
// parameters string format is "width,precision" // parameters string format is "width[,precision[,format]]"
// format to choose beween f|e|g|E|G (f is used by default)
virtual void SetParameters(const wxString& params); virtual void SetParameters(const wxString& params);
protected: protected:
// string representation of our value // string representation of our value
wxString GetString() const; wxString GetString();
private: private:
int m_width, int m_width,
m_precision; m_precision;
double m_value; double m_value;
int m_style;
wxString m_format;
wxDECLARE_NO_COPY_CLASS(wxGridCellFloatEditor); wxDECLARE_NO_COPY_CLASS(wxGridCellFloatEditor);
}; };

View File

@@ -178,6 +178,31 @@ public:
virtual void SetParameters(const wxString& params); virtual void SetParameters(const wxString& params);
}; };
/**
Specifier used to format the data to string for the numbers handled by
wxGridCellFloatRenderer and wxGridCellFloatEditor.
@since 2.9.3
*/
enum wxGridCellFloatFormat
{
/// Decimal floating point (%f).
wxGRID_FLOAT_FORMAT_FIXED = 0x0010,
/// Scientific notation (mantise/exponent) using e character (%e).
wxGRID_FLOAT_FORMAT_SCIENTIFIC = 0x0020,
/// Use the shorter of %e or %f (%g).
wxGRID_FLOAT_FORMAT_COMPACT = 0x0040,
/// To use in combination with one of the above formats for the upper
/// case version (%F/%E/%G)
wxGRID_FLOAT_FORMAT_UPPER = 0x0080,
/// The format used by default (wxGRID_FLOAT_FORMAT_FIXED).
wxGRID_FLOAT_FORMAT_DEFAULT = wxGRID_FLOAT_FORMAT_FIXED
};
/** /**
@class wxGridCellFloatRenderer @class wxGridCellFloatRenderer
@@ -201,8 +226,22 @@ public:
Minimum number of characters to be shown. Minimum number of characters to be shown.
@param precision @param precision
Number of digits after the decimal dot. Number of digits after the decimal dot.
@param format
The format used to display the string, must be a combination of
wxGridCellFloatFormat enum elements. This parameter is only
available since wxWidgets 2.9.3.
*/ */
wxGridCellFloatRenderer(int width = -1, int precision = -1); wxGridCellFloatRenderer(int width = -1, int precision = -1,
int format = wxGRID_FLOAT_FORMAT_DEFAULT);
/**
Returns the specifier used to format the data to string.
The returned value is a combination of wxGridCellFloatFormat elements.
@since 2.9.3
*/
int GetFormat() const;
/** /**
Returns the precision. Returns the precision.
@@ -215,7 +254,18 @@ public:
int GetWidth() const; int GetWidth() const;
/** /**
Parameters string format is "width[,precision]". Set the format to use for display the number.
@param format
Must be a combination of wxGridCellFloatFormat enum elements.
@since 2.9.3
*/
void SetFormat(int format);
/**
The parameters string format is "width[,precision[,format]]" where
@c format should be choosen beween f|e|g|E|G (f is used by default)
*/ */
virtual void SetParameters(const wxString& params); virtual void SetParameters(const wxString& params);
@@ -596,11 +646,17 @@ public:
Minimum number of characters to be shown. Minimum number of characters to be shown.
@param precision @param precision
Number of digits after the decimal dot. Number of digits after the decimal dot.
@param format
The format to use for displaying the number, a combination of
wxGridCellFloatFormat enum elements. This parameter is only
available since wxWidgets 2.9.3.
*/ */
wxGridCellFloatEditor(int width = -1, int precision = -1); wxGridCellFloatEditor(int width = -1, int precision = -1,
int format = wxGRID_FLOAT_FORMAT_DEFAULT);
/** /**
Parameters string format is "width,precision" The parameters string format is "width[,precision[,format]]" where
@c format should be choosen beween f|e|g|E|G (f is used by default)
*/ */
virtual void SetParameters(const wxString& params); virtual void SetParameters(const wxString& params);
}; };

View File

@@ -439,22 +439,33 @@ GridFrame::GridFrame()
grid->SetCellValue(5, 8, wxT("Bg from row attr\nText col from cell attr")); grid->SetCellValue(5, 8, wxT("Bg from row attr\nText col from cell attr"));
grid->SetCellValue(5, 5, wxT("Bg from row attr Text col from col attr and this text is so long that it covers over many many empty cells but is broken by one that isn't")); grid->SetCellValue(5, 5, wxT("Bg from row attr Text col from col attr and this text is so long that it covers over many many empty cells but is broken by one that isn't"));
// Some numeric columns with different formatting.
grid->SetColFormatFloat(6); grid->SetColFormatFloat(6);
grid->SetCellValue(0, 6, wxString::Format(wxT("%g"), 3.1415)); grid->SetCellValue(0, 6, "Default\nfloat format");
grid->SetCellValue(1, 6, wxString::Format(wxT("%g"), 1415.0)); grid->SetCellValue(1, 6, wxString::Format(wxT("%g"), 3.1415));
grid->SetCellValue(2, 6, wxString::Format(wxT("%g"), 12345.67890)); grid->SetCellValue(2, 6, wxString::Format(wxT("%g"), 1415.0));
grid->SetCellValue(3, 6, wxString::Format(wxT("%g"), 12345.67890));
grid->SetColFormatFloat(7, 6, 2); grid->SetColFormatFloat(7, 6, 2);
grid->SetCellValue(0, 7, wxString::Format(wxT("%g"), 3.1415)); grid->SetCellValue(0, 7, "Width 6\nprecision 2");
grid->SetCellValue(1, 7, wxString::Format(wxT("%g"), 1415.0)); grid->SetCellValue(1, 7, wxString::Format(wxT("%g"), 3.1415));
grid->SetCellValue(2, 7, wxString::Format(wxT("%g"), 12345.67890)); grid->SetCellValue(2, 7, wxString::Format(wxT("%g"), 1415.0));
grid->SetCellValue(3, 7, wxString::Format(wxT("%g"), 12345.67890));
grid->SetColFormatNumber(8); grid->SetColFormatCustom(8,
grid->SetCellValue(0, 8, "17"); wxString::Format("%s:%i,%i,%s", wxGRID_VALUE_FLOAT, -1, 4, "g"));
grid->SetCellValue(1, 8, "0"); grid->SetCellValue(0, 8, "Compact\nformat");
grid->SetCellValue(2, 8, "-666"); grid->SetCellValue(1, 8, wxT("31415e-4"));
grid->SetCellAlignment(2, 8, wxALIGN_CENTRE, wxALIGN_TOP); grid->SetCellValue(2, 8, wxT("1415"));
grid->SetCellValue(2, 9, "<- This numeric cell should be centred"); grid->SetCellValue(3, 8, wxT("123456789e-4"));
grid->SetColFormatNumber(9);
grid->SetCellValue(0, 9, "Integer\ncolumn");
grid->SetCellValue(1, 9, "17");
grid->SetCellValue(2, 9, "0");
grid->SetCellValue(3, 9, "-666");
grid->SetCellAlignment(3, 9, wxALIGN_CENTRE, wxALIGN_TOP);
grid->SetCellValue(3, 10, "<- This numeric cell should be centred");
const wxString choices[] = const wxString choices[] =
{ {

View File

@@ -598,10 +598,13 @@ wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
// wxGridCellFloatRenderer // wxGridCellFloatRenderer
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision) wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width,
int precision,
int format)
{ {
SetWidth(width); SetWidth(width);
SetPrecision(precision); SetPrecision(precision);
SetFormat(format);
} }
wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const
@@ -609,6 +612,7 @@ wxGridCellRenderer *wxGridCellFloatRenderer::Clone() const
wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer; wxGridCellFloatRenderer *renderer = new wxGridCellFloatRenderer;
renderer->m_width = m_width; renderer->m_width = m_width;
renderer->m_precision = m_precision; renderer->m_precision = m_precision;
renderer->m_style = m_style;
renderer->m_format = m_format; renderer->m_format = m_format;
return renderer; return renderer;
@@ -641,22 +645,30 @@ wxString wxGridCellFloatRenderer::GetString(const wxGrid& grid, int row, int col
if ( m_precision == -1 ) if ( m_precision == -1 )
{ {
// default width/precision // default width/precision
m_format = wxT("%f"); m_format = wxT("%");
} }
else else
{ {
m_format.Printf(wxT("%%.%df"), m_precision); m_format.Printf(wxT("%%.%d"), m_precision);
} }
} }
else if ( m_precision == -1 ) else if ( m_precision == -1 )
{ {
// default precision // default precision
m_format.Printf(wxT("%%%d.f"), m_width); m_format.Printf(wxT("%%%d."), m_width);
} }
else else
{ {
m_format.Printf(wxT("%%%d.%df"), m_width, m_precision); m_format.Printf(wxT("%%%d.%d"), m_width, m_precision);
} }
bool isUpper = ( ( m_style & wxGRID_FLOAT_FORMAT_UPPER ) == wxGRID_FLOAT_FORMAT_UPPER);
if ( ( m_style & wxGRID_FLOAT_FORMAT_SCIENTIFIC ) == wxGRID_FLOAT_FORMAT_SCIENTIFIC)
m_format += isUpper ? wxT('E') : wxT('e');
else if ( ( m_style & wxGRID_FLOAT_FORMAT_COMPACT ) == wxGRID_FLOAT_FORMAT_COMPACT)
m_format += isUpper ? wxT('G') : wxT('g');
else
m_format += wxT('f');
} }
text.Printf(m_format, val); text.Printf(m_format, val);
@@ -704,10 +716,12 @@ void wxGridCellFloatRenderer::SetParameters(const wxString& params)
// reset to defaults // reset to defaults
SetWidth(-1); SetWidth(-1);
SetPrecision(-1); SetPrecision(-1);
SetFormat(wxGRID_FLOAT_FORMAT_DEFAULT);
} }
else else
{ {
wxString tmp = params.BeforeFirst(wxT(',')); wxString rest;
wxString tmp = params.BeforeFirst(wxT(','), &rest);
if ( !tmp.empty() ) if ( !tmp.empty() )
{ {
long width; long width;
@@ -721,7 +735,7 @@ void wxGridCellFloatRenderer::SetParameters(const wxString& params)
} }
} }
tmp = params.AfterFirst(wxT(',')); tmp = rest.BeforeFirst(wxT(','));
if ( !tmp.empty() ) if ( !tmp.empty() )
{ {
long precision; long precision;
@@ -734,6 +748,43 @@ void wxGridCellFloatRenderer::SetParameters(const wxString& params)
wxLogDebug(wxT("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str()); wxLogDebug(wxT("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str());
} }
} }
tmp = rest.AfterFirst(wxT(','));
if ( !tmp.empty() )
{
if ( tmp[0] == wxT('f') )
{
SetFormat(wxGRID_FLOAT_FORMAT_FIXED);
}
else if ( tmp[0] == wxT('e') )
{
SetFormat(wxGRID_FLOAT_FORMAT_SCIENTIFIC);
}
else if ( tmp[0] == wxT('g') )
{
SetFormat(wxGRID_FLOAT_FORMAT_COMPACT);
}
else if ( tmp[0] == wxT('E') )
{
SetFormat(wxGRID_FLOAT_FORMAT_SCIENTIFIC |
wxGRID_FLOAT_FORMAT_UPPER);
}
else if ( tmp[0] == wxT('F') )
{
SetFormat(wxGRID_FLOAT_FORMAT_FIXED |
wxGRID_FLOAT_FORMAT_UPPER);
}
else if ( tmp[0] == wxT('G') )
{
SetFormat(wxGRID_FLOAT_FORMAT_COMPACT |
wxGRID_FLOAT_FORMAT_UPPER);
}
else
{
wxLogDebug("Invalid wxGridCellFloatRenderer format "
"parameter string '%s ignored", params);
}
}
} }
} }

View File

@@ -862,10 +862,13 @@ wxString wxGridCellNumberEditor::GetValue() const
// wxGridCellFloatEditor // wxGridCellFloatEditor
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxGridCellFloatEditor::wxGridCellFloatEditor(int width, int precision) wxGridCellFloatEditor::wxGridCellFloatEditor(int width,
int precision,
int format)
{ {
m_width = width; m_width = width;
m_precision = precision; m_precision = precision;
m_style = format;
} }
void wxGridCellFloatEditor::Create(wxWindow* parent, void wxGridCellFloatEditor::Create(wxWindow* parent,
@@ -988,51 +991,113 @@ void wxGridCellFloatEditor::SetParameters(const wxString& params)
// reset to default // reset to default
m_width = m_width =
m_precision = -1; m_precision = -1;
m_style = wxGRID_FLOAT_FORMAT_DEFAULT;
m_format.clear();
} }
else else
{ {
long tmp; wxString rest;
if ( params.BeforeFirst(wxT(',')).ToLong(&tmp) ) wxString tmp = params.BeforeFirst(wxT(','), &rest);
if ( !tmp.empty() )
{ {
m_width = (int)tmp; long width;
if ( tmp.ToLong(&width) )
if ( params.AfterFirst(wxT(',')).ToLong(&tmp) )
{ {
m_precision = (int)tmp; m_width = (int)width;
}
// skip the error message below else
return; {
wxLogDebug(wxT("Invalid wxGridCellFloatRenderer width parameter string '%s ignored"), params.c_str());
} }
} }
wxLogDebug(wxT("Invalid wxGridCellFloatEditor parameter string '%s' ignored"), params.c_str()); tmp = rest.BeforeFirst(wxT(','));
if ( !tmp.empty() )
{
long precision;
if ( tmp.ToLong(&precision) )
{
m_precision = (int)precision;
}
else
{
wxLogDebug(wxT("Invalid wxGridCellFloatRenderer precision parameter string '%s ignored"), params.c_str());
}
}
tmp = rest.AfterFirst(wxT(','));
if ( !tmp.empty() )
{
if ( tmp[0] == wxT('f') )
{
m_style = wxGRID_FLOAT_FORMAT_FIXED;
}
else if ( tmp[0] == wxT('e') )
{
m_style = wxGRID_FLOAT_FORMAT_SCIENTIFIC;
}
else if ( tmp[0] == wxT('g') )
{
m_style = wxGRID_FLOAT_FORMAT_COMPACT;
}
else if ( tmp[0] == wxT('E') )
{
m_style = wxGRID_FLOAT_FORMAT_SCIENTIFIC |
wxGRID_FLOAT_FORMAT_UPPER;
}
else if ( tmp[0] == wxT('F') )
{
m_style = wxGRID_FLOAT_FORMAT_FIXED |
wxGRID_FLOAT_FORMAT_UPPER;
}
else if ( tmp[0] == wxT('G') )
{
m_style = wxGRID_FLOAT_FORMAT_COMPACT |
wxGRID_FLOAT_FORMAT_UPPER;
}
else
{
wxLogDebug("Invalid wxGridCellFloatRenderer format "
"parameter string '%s ignored", params);
}
}
} }
} }
wxString wxGridCellFloatEditor::GetString() const wxString wxGridCellFloatEditor::GetString()
{ {
wxString fmt; if ( !m_format )
if ( m_precision == -1 && m_width != -1)
{ {
// default precision if ( m_precision == -1 && m_width != -1)
fmt.Printf(wxT("%%%d.f"), m_width); {
} // default precision
else if ( m_precision != -1 && m_width == -1) m_format.Printf(wxT("%%%d."), m_width);
{ }
// default width else if ( m_precision != -1 && m_width == -1)
fmt.Printf(wxT("%%.%df"), m_precision); {
} // default width
else if ( m_precision != -1 && m_width != -1 ) m_format.Printf(wxT("%%.%d"), m_precision);
{ }
fmt.Printf(wxT("%%%d.%df"), m_width, m_precision); else if ( m_precision != -1 && m_width != -1 )
} {
else m_format.Printf(wxT("%%%d.%d"), m_width, m_precision);
{ }
// default width/precision else
fmt = wxT("%f"); {
// default width/precision
m_format = wxT("%");
}
bool isUpper = (m_style & wxGRID_FLOAT_FORMAT_UPPER) != 0;
if ( m_style & wxGRID_FLOAT_FORMAT_SCIENTIFIC )
m_format += isUpper ? wxT('E') : wxT('e');
else if ( m_style & wxGRID_FLOAT_FORMAT_COMPACT )
m_format += isUpper ? wxT('G') : wxT('g');
else
m_format += wxT('f');
} }
return wxString::Format(fmt, m_value); return wxString::Format(m_format, m_value);
} }
bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event) bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)