From 65e4e78efb62104d4d0f9ac32e3fff24f9c14b6e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 22 Feb 2000 16:03:54 +0000 Subject: [PATCH] column autosizing added git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6213 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/grid.h | 51 ++++++++- samples/newgrid/griddemo.cpp | 13 ++- src/generic/grid.cpp | 204 +++++++++++++++++++++++++++-------- 3 files changed, 220 insertions(+), 48 deletions(-) diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 3c10ae8507..2420ed4c02 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -105,6 +105,12 @@ public: int row, int col, bool isSelected) = 0; + // get the preferred size of the cell for its contents + virtual wxSize GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col) = 0; + // virtual dtor for any base class virtual ~wxGridCellRenderer(); }; @@ -121,12 +127,23 @@ public: int row, int col, bool isSelected); + // return the string extent + virtual wxSize GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col); + protected: // set the text colours before drawing void SetTextColoursAndFont(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, bool isSelected); + + // calc the string extent for given string/font + wxSize DoGetBestSize(wxGridCellAttr& attr, + wxDC& dc, + const wxString& text); }; // the default renderer for the cells containing numeric (long) data @@ -140,6 +157,14 @@ public: const wxRect& rect, int row, int col, bool isSelected); + + virtual wxSize GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col); + +protected: + wxString GetString(wxGrid& grid, int row, int col); }; class WXDLLEXPORT wxGridCellFloatRenderer : public wxGridCellStringRenderer @@ -161,6 +186,13 @@ public: int row, int col, bool isSelected); + virtual wxSize GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col); +protected: + wxString GetString(wxGrid& grid, int row, int col); + private: // formatting parameters int m_width, @@ -180,6 +212,15 @@ public: const wxRect& rect, int row, int col, bool isSelected); + + // return the checkmark size + virtual wxSize GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col); + +private: + static wxSize ms_sizeCheckMark; }; // ---------------------------------------------------------------------------- @@ -1001,6 +1042,14 @@ public: void SetColSize( int col, int width ); + // automatically size the column to fit to its contents, if setAsMin is + // TRUE, this optimal width will also be set as minimal width for this + // column + void AutoSizeColumn( int col, bool setAsMin = TRUE ); + + // auto size all columns (very ineffective for big grids!) + void AutoSizeColumns( bool setAsMin = TRUE ); + // column won't be resized to be lesser width - this must be called during // the grid creation because it won't resize the column if it's already // narrower than the minimal width @@ -1506,8 +1555,6 @@ protected: DECLARE_EVENT_TABLE() }; - - // ---------------------------------------------------------------------------- // Grid event class and event types // ---------------------------------------------------------------------------- diff --git a/samples/newgrid/griddemo.cpp b/samples/newgrid/griddemo.cpp index b73608eed9..c308c4e38a 100644 --- a/samples/newgrid/griddemo.cpp +++ b/samples/newgrid/griddemo.cpp @@ -959,8 +959,13 @@ BugsGridFrame::BugsGridFrame() wxGridTableBase *table = new BugsGridTable(); grid->SetTable(table, TRUE); - for ( size_t row = 0; row < WXSIZEOF(gs_dataBugsGrid); row++ ) - { - grid->SetReadOnly(row, Col_Id); - } + wxGridCellAttr *attrRO = new wxGridCellAttr, + *attrRangeEditor = new wxGridCellAttr; + attrRO->SetReadOnly(); + attrRangeEditor->SetEditor(new wxGridCellNumberEditor(1, 5)); + + grid->SetColAttr(Col_Id, attrRO); + grid->SetColAttr(Col_Priority, attrRangeEditor); + + grid->AutoSizeColumns(); } diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index d728ad8407..4779b848a9 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -961,6 +961,25 @@ void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid, dc.SetFont( attr.GetFont() ); } +wxSize wxGridCellStringRenderer::DoGetBestSize(wxGridCellAttr& attr, + wxDC& dc, + const wxString& text) +{ + wxCoord x, y; + dc.SetFont(attr.GetFont()); + dc.GetTextExtent(text, &x, &y); + + return wxSize(x, y); +} + +wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col) +{ + return DoGetBestSize(attr, dc, grid.GetCellValue(row, col)); +} + void wxGridCellStringRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -983,6 +1002,23 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid, rect, hAlign, vAlign); } +// ---------------------------------------------------------------------------- +// wxGridCellNumberRenderer +// ---------------------------------------------------------------------------- + +wxString wxGridCellNumberRenderer::GetString(wxGrid& grid, int row, int col) +{ + wxGridTableBase *table = grid.GetTable(); + wxString text; + if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) ) + { + text.Printf(_T("%ld"), table->GetValueAsLong(row, col)); + } + //else: leave the string empty or put 0 into it? + + return text; +} + void wxGridCellNumberRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -1002,15 +1038,15 @@ void wxGridCellNumberRenderer::Draw(wxGrid& grid, wxRect rect = rectCell; rect.Inflate(-1); - wxGridTableBase *table = grid.GetTable(); - wxString text; - if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) ) - { - text.Printf(_T("%ld"), table->GetValueAsLong(row, col)); - } - //else: leave the string empty or put 0 into it? + grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign); +} - grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign); +wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col) +{ + return DoGetBestSize(attr, dc, GetString(grid, row, col)); } // ---------------------------------------------------------------------------- @@ -1023,6 +1059,24 @@ wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision) SetPrecision(precision); } +wxString wxGridCellFloatRenderer::GetString(wxGrid& grid, int row, int col) +{ + wxGridTableBase *table = grid.GetTable(); + wxString text; + if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) ) + { + if ( !m_format ) + { + m_format.Printf(_T("%%%d.%d%%f"), m_width, m_precision); + } + + text.Printf(m_format, table->GetValueAsDouble(row, col)); + } + //else: leave the string empty or put 0 into it? + + return text; +} + void wxGridCellFloatRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, @@ -1042,66 +1096,76 @@ void wxGridCellFloatRenderer::Draw(wxGrid& grid, wxRect rect = rectCell; rect.Inflate(-1); - wxGridTableBase *table = grid.GetTable(); - wxString text; - if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) ) - { - if ( !m_format ) - { - m_format.Printf(_T("%%%d.%d%%f"), m_width, m_precision); - } - - text.Printf(m_format, table->GetValueAsDouble(row, col)); - } - //else: leave the string empty or put 0 into it? + grid.DrawTextRectangle(dc, GetString(grid, row, col), rect, hAlign, vAlign); +} - grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign); +wxSize wxGridCellFloatRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + int row, int col) +{ + return DoGetBestSize(attr, dc, GetString(grid, row, col)); } // ---------------------------------------------------------------------------- // wxGridCellBoolRenderer // ---------------------------------------------------------------------------- -void wxGridCellBoolRenderer::Draw(wxGrid& grid, - wxGridCellAttr& attr, - wxDC& dc, - const wxRect& rect, - int row, int col, - bool isSelected) -{ - wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); +wxSize wxGridCellBoolRenderer::ms_sizeCheckMark; - // between checkmark and box - static const wxCoord margin = 4; +// between checkmark and box +static const wxCoord wxGRID_CHECKMARK_MARGIN = 4; - // get checkbox size - static wxCoord s_checkSize = 0; - if ( s_checkSize == 0 ) +wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid, + wxGridCellAttr& WXUNUSED(attr), + wxDC& WXUNUSED(dc), + int WXUNUSED(row), + int WXUNUSED(col)) +{ + // compute it only once (no locks for MT safeness in GUI thread...) + if ( !ms_sizeCheckMark.x ) { - // compute it only once (no locks for MT safeness in GUI thread...) + // get checkbox size + wxCoord checkSize = 0; wxCheckBox *checkbox = new wxCheckBox(&grid, -1, wxEmptyString); wxSize size = checkbox->GetBestSize(); - s_checkSize = size.y + margin; + checkSize = size.y + wxGRID_CHECKMARK_MARGIN; - // FIXME wxGTK::wxCheckBox::GetBestSize() is really weird... + // FIXME wxGTK::wxCheckBox::GetBestSize() gives "wrong" result #ifdef __WXGTK__ - s_checkSize -= size.y / 2; + checkSize -= size.y / 2; #endif delete checkbox; + + ms_sizeCheckMark.x = ms_sizeCheckMark.y = checkSize; } + return ms_sizeCheckMark; +} + +void wxGridCellBoolRenderer::Draw(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + const wxRect& rect, + int row, int col, + bool isSelected) +{ + wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); + // draw a check mark in the centre (ignoring alignment - TODO) + wxSize size = GetBestSize(grid, attr, dc, row, col); wxRect rectMark; - rectMark.x = rect.x + rect.width/2 - s_checkSize/2; - rectMark.y = rect.y + rect.height/2 - s_checkSize/2; - rectMark.width = rectMark.height = s_checkSize; + rectMark.x = rect.x + rect.width/2 - size.x/2; + rectMark.y = rect.y + rect.height/2 - size.y/2; + rectMark.width = size.x; + rectMark.height = size.y; dc.SetBrush(*wxTRANSPARENT_BRUSH); dc.SetPen(wxPen(attr.GetTextColour(), 1, wxSOLID)); dc.DrawRectangle(rectMark); - rectMark.Inflate(-margin); + rectMark.Inflate(-wxGRID_CHECKMARK_MARGIN); bool value; if (grid.GetTable()->CanGetValueAs(row, col, wxT("bool"))) @@ -6599,6 +6663,62 @@ int wxGrid::GetColMinimalWidth(int col) const return obj ? (int)obj : WXGRID_MIN_COL_WIDTH; } +void wxGrid::AutoSizeColumn( int col, bool setAsMin ) +{ + wxClientDC dc(m_gridWin); + + wxCoord width, widthMax = 0; + for ( int row = 0; row < m_numRows; row++ ) + { + wxGridCellAttr* attr = GetCellAttr(row, col); + wxGridCellRenderer* renderer = attr->GetRenderer(GetDefaultRendererForCell(row,col)); + if ( renderer ) + { + width = renderer->GetBestSize(*this, *attr, dc, row, col).x; + if ( width > widthMax ) + { + widthMax = width; + } + } + + attr->DecRef(); + } + + // now also compare with the column label width + dc.SetFont( GetLabelFont() ); + dc.GetTextExtent( GetColLabelValue(col), &width, NULL ); + if ( width > widthMax ) + { + widthMax = width; + } + + if ( !widthMax ) + { + // empty column - give default width (notice that if widthMax is less + // than default width but != 0, it's ok) + widthMax = m_defaultColWidth; + } + else + { + // leave some space around text + widthMax += 10; + } + + SetColSize(col, widthMax); + if ( setAsMin ) + { + SetColMinimalWidth(col, widthMax); + } +} + +void wxGrid::AutoSizeColumns( bool setAsMin ) +{ + for ( int col = 0; col < m_numCols; col++ ) + { + AutoSizeColumn(col, setAsMin); + } +} + // // ------ cell value accessor functions // -- 2.45.2