X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2121eb69fa8d49f4484f7170159e61f2e8885de4..6cfe484434ddd9e130a0e6e2d5868fd67f189b92:/src/generic/grid.cpp diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 68c6411e8f..22939d4afc 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -18,6 +18,8 @@ #if wxUSE_GRID +#include "wx/grid.h" + #ifndef WX_PRECOMP #include "wx/utils.h" #include "wx/dcclient.h" @@ -37,9 +39,10 @@ #include "wx/tokenzr.h" #include "wx/renderer.h" -#include "wx/grid.h" #include "wx/generic/gridsel.h" +const wxChar wxGridNameStr[] = wxT("grid"); + #if defined(__WXMOTIF__) #define WXUNUSED_MOTIF(identifier) WXUNUSED(identifier) #else @@ -1230,6 +1233,9 @@ bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event) // wxGridCellBoolEditor // ---------------------------------------------------------------------------- +// the default values for GetValue() +wxString wxGridCellBoolEditor::ms_stringValues[2] = { _T(""), _T("1") }; + void wxGridCellBoolEditor::Create(wxWindow* parent, wxWindowID id, wxEvtHandler* evtHandler) @@ -1335,7 +1341,19 @@ void wxGridCellBoolEditor::BeginEdit(int row, int col, wxGrid* grid) else { wxString cellval( grid->GetTable()->GetValue(row, col) ); - m_startValue = !( !cellval || (cellval == wxT("0")) ); + + if ( cellval == ms_stringValues[false] ) + m_startValue = false; + else if ( cellval == ms_stringValues[true] ) + m_startValue = true; + else + { + // do not try to be smart here and convert it to true or false + // because we'll still overwrite it with something different and + // this risks to be very surprising for the user code, let them + // know about it + wxFAIL_MSG( _T("invalid value for a cell with bool editor!") ); + } } CBox()->SetValue(m_startValue); @@ -1355,10 +1373,11 @@ bool wxGridCellBoolEditor::EndEdit(int row, int col, if ( changed ) { - if (grid->GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL)) - grid->GetTable()->SetValueAsBool(row, col, value); + wxGridTableBase * const table = grid->GetTable(); + if ( table->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) ) + table->SetValueAsBool(row, col, value); else - grid->GetTable()->SetValue(row, col, value ? _T("1") : wxEmptyString); + table->SetValue(row, col, GetValue()); } return changed; @@ -1413,12 +1432,23 @@ void wxGridCellBoolEditor::StartingKey(wxKeyEvent& event) } } - -// return the value as "1" for true and the empty string for false wxString wxGridCellBoolEditor::GetValue() const { - bool bSet = CBox()->GetValue(); - return bSet ? _T("1") : wxEmptyString; + return ms_stringValues[CBox()->GetValue()]; +} + +/* static */ void +wxGridCellBoolEditor::UseStringValues(const wxString& valueTrue, + const wxString& valueFalse) +{ + ms_stringValues[false] = valueFalse; + ms_stringValues[true] = valueTrue; +} + +/* static */ bool +wxGridCellBoolEditor::IsTrueValue(const wxString& value) +{ + return value == ms_stringValues[true]; } #endif // wxUSE_CHECKBOX @@ -2214,7 +2244,7 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid, else { wxString cellval( grid.GetTable()->GetValue(row, col) ); - value = !( !cellval || (cellval == wxT("0")) ); + value = wxGridCellBoolEditor::IsTrueValue(cellval); } if ( value ) @@ -2289,6 +2319,7 @@ wxGridCellAttr *wxGridCellAttr::Clone() const if ( IsReadOnly() ) attr->SetReadOnly(); + attr->SetOverflow( m_overflow == Overflow ); attr->SetKind( m_attrkind ); return attr; @@ -3878,7 +3909,8 @@ void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) ) GetClientSize( &client_width, &client_height ); // VZ: any reason for this ifdef? (FIXME) -#ifdef __WXGTK__ +#if 0 +def __WXGTK__ wxRect rect; rect.SetX( 1 ); rect.SetY( 1 ); @@ -4131,7 +4163,7 @@ wxGrid::wxGrid( wxWindow *parent, m_rowMinHeights(GRID_HASH_SIZE) { Create(); - SetBestFittingSize(size); + SetInitialSize(size); } bool wxGrid::Create(wxWindow *parent, wxWindowID id, @@ -4146,7 +4178,7 @@ bool wxGrid::Create(wxWindow *parent, wxWindowID id, m_rowMinHeights = wxLongToLongHashMap(GRID_HASH_SIZE); Create(); - SetBestFittingSize(size); + SetInitialSize(size); return true; } @@ -4166,8 +4198,12 @@ wxGrid::~wxGrid() total ? (gs_nAttrCacheHits*100) / total : 0); #endif - if (m_ownTable) + // if we own the table, just delete it, otherwise at least don't leave it + // with dangling view pointer + if ( m_ownTable ) delete m_table; + else if ( m_table && m_table->GetView() == this ) + m_table->SetView(NULL); delete m_typeRegistry; delete m_selection; @@ -4449,8 +4485,9 @@ void wxGrid::Init() // default widths/heights are used for all rows/columns, we may not use these // arrays at all // -// with some extra code, it should be possible to only store the -// widths/heights different from default ones but this will be done later... +// with some extra code, it should be possible to only store the widths/heights +// different from default ones (resulting in space savings for huge grids) but +// this is not done currently // ---------------------------------------------------------------------------- void wxGrid::InitRowHeights() @@ -4461,10 +4498,9 @@ void wxGrid::InitRowHeights() m_rowHeights.Alloc( m_numRows ); m_rowBottoms.Alloc( m_numRows ); - int rowBottom = 0; - m_rowHeights.Add( m_defaultRowHeight, m_numRows ); + int rowBottom = 0; for ( int i = 0; i < m_numRows; i++ ) { rowBottom += m_defaultRowHeight; @@ -4479,10 +4515,10 @@ void wxGrid::InitColWidths() m_colWidths.Alloc( m_numCols ); m_colRights.Alloc( m_numCols ); - int colRight = 0; m_colWidths.Add( m_defaultColWidth, m_numCols ); + int colRight = 0; for ( int i = 0; i < m_numCols; i++ ) { colRight = ( GetColPos( i ) + 1 ) * m_defaultColWidth; @@ -4526,17 +4562,12 @@ int wxGrid::GetRowBottom(int row) const void wxGrid::CalcDimensions() { - int cw, ch; - GetClientSize( &cw, &ch ); - - if ( m_rowLabelWin->IsShown() ) - cw -= m_rowLabelWidth; - if ( m_colLabelWin->IsShown() ) - ch -= m_colLabelHeight; + // compute the size of the scrollable area + int w = m_numCols > 0 ? GetColRight(GetColAt(m_numCols - 1)) : 0; + int h = m_numRows > 0 ? GetRowBottom(m_numRows - 1) : 0; - // grid total size - int w = m_numCols > 0 ? GetColRight(GetColAt( m_numCols - 1 )) + m_extraWidth + 1 : 0; - int h = m_numRows > 0 ? GetRowBottom(m_numRows - 1) + m_extraHeight + 1 : 0; + w += m_extraWidth; + h += m_extraHeight; // take into account editor if shown if ( IsCellEditControlShown() ) @@ -4573,7 +4604,8 @@ void wxGrid::CalcDimensions() // do set scrollbar parameters SetScrollbars( m_scrollLineX, m_scrollLineY, - GetScrollX(w), GetScrollY(h), x, y, + GetScrollX(w), GetScrollY(h), + x, y, GetBatchCount() != 0); // if our OnSize() hadn't been called (it would if we have scrollbars), we @@ -4591,6 +4623,33 @@ void wxGrid::CalcWindowSizes() int cw, ch; GetClientSize( &cw, &ch ); + // this block of code tries to work around the following problem: the grid + // could have been just resized to have enough space to show the full grid + // window contents without the scrollbars, but its client size could be + // not big enough because the grid has the scrollbars right now and so the + // scrollbars would remain even though we don't need them any more + // + // to prevent this from happening, check if we have enough space for + // everything without the scrollbars and explicitly disable them then + wxSize size = GetSize() - GetWindowBorderSize(); + if ( size != wxSize(cw, ch) ) + { + // check if we have enough space for grid window after accounting for + // the fixed size elements + size.x -= m_rowLabelWidth; + size.y -= m_colLabelHeight; + + const wxSize vsize = m_gridWin->GetVirtualSize(); + + if ( size.x >= vsize.x && size.y >= vsize.y ) + { + // yes, we do, so remove the scrollbars and use the new client size + // (which should be the same as full window size - borders now) + SetScrollbars(0, 0, 0, 0); + GetClientSize(&cw, &ch); + } + } + if ( m_cornerLabelWin && m_cornerLabelWin->IsShown() ) m_cornerLabelWin->SetSize( 0, 0, m_rowLabelWidth, m_colLabelHeight ); @@ -7066,8 +7125,10 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) return; } +#if !(defined(__WXMAC__) && wxMAC_USE_CORE_GRAPHICS) wxClientDC dc( m_gridWin ); PrepareDC( dc ); +#endif if ( m_currentCellCoords != wxGridNoCellCoords ) { @@ -7090,15 +7151,21 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) // Otherwise refresh redraws the highlight! m_currentCellCoords = coords; +#if defined(__WXMAC__) && wxMAC_USE_CORE_GRAPHICS + m_gridWin->Refresh(true /*, & r */); +#else DrawGridCellArea( dc, cells ); DrawAllGridLines( dc, r ); +#endif } } m_currentCellCoords = coords; wxGridCellAttr *attr = GetCellAttr( coords ); +#if !(defined(__WXMAC__) && wxMAC_USE_CORE_GRAPHICS) DrawCellHighlight( dc, attr ); +#endif attr->DecRef(); } @@ -7474,7 +7541,7 @@ void wxGrid::DrawCell( wxDC& dc, const wxGridCellCoords& coords ) // edit control is erased by this code after being rendered. // On wxMac (QD build only), the cell editor is a wxTextCntl and is rendered // implicitly, causing this out-of order render. -#if !defined(__WXMAC__) || wxMAC_USE_CORE_GRAPHICS +#if !defined(__WXMAC__) wxGridCellEditor *editor = attr->GetEditor(this, row, col); editor->PaintBackground(rect, attr); editor->DecRef(); @@ -7669,17 +7736,16 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) int rightCol = GetColPos( internalXToCol(right) ); int bottomRow = internalYToRow(bottom); -#ifndef __WXMAC__ - // CS: I don't know why suddenly unscrolled coordinates are used for clipping +#if !defined(__WXMAC__) || wxMAC_USE_CORE_GRAPHICS wxRegion clippedcells(0, 0, cw, ch); int i, j, cell_rows, cell_cols; wxRect rect; - for (j=topRow; j 1) || (cell_cols > 1)) @@ -7794,7 +7860,8 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row ) wxRect rect; -#ifdef __WXGTK20__ +#if 0 +def __WXGTK20__ rect.SetX( 1 ); rect.SetY( GetRowTop(row) + 1 ); rect.SetWidth( m_rowLabelWidth - 2 ); @@ -7856,7 +7923,8 @@ void wxGrid::DrawColLabel( wxDC& dc, int col ) wxRect rect; -#ifdef __WXGTK20__ +#if 0 +def __WXGTK20__ rect.SetX( colLeft + 1 ); rect.SetY( 1 ); rect.SetWidth( GetColWidth(col) - 2 ); @@ -10198,8 +10266,7 @@ void wxGrid::SetRowSize( int row, int height ) int diff = h - m_rowHeights[row]; m_rowHeights[row] = h; - int i; - for ( i = row; i < m_numRows; i++ ) + for ( int i = row; i < m_numRows; i++ ) { m_rowBottoms[i] += diff; } @@ -10262,12 +10329,9 @@ void wxGrid::SetColSize( int col, int width ) int diff = w - m_colWidths[col]; m_colWidths[col] = w; - int i; - int colPos; - for ( colPos = GetColPos( col ); colPos < m_numCols; colPos++ ) + for ( int colPos = GetColPos(col); colPos < m_numCols; colPos++ ) { - i = GetColAt( colPos ); - m_colRights[i] += diff; + m_colRights[GetColAt(colPos)] += diff; } if ( !GetBatchCount() ) @@ -10384,12 +10448,12 @@ void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column ) if ( column ) { - dc.GetTextExtent( GetColLabelValue(col), &w, &h ); + dc.GetMultiLineTextExtent( GetColLabelValue(col), &w, &h ); if ( GetColLabelTextOrientation() == wxVERTICAL ) w = h; } else - dc.GetTextExtent( GetRowLabelValue(row), &w, &h ); + dc.GetMultiLineTextExtent( GetRowLabelValue(row), &w, &h ); extent = column ? w : h; if ( extent > extentMax ) @@ -10496,21 +10560,17 @@ void wxGrid::AutoSize() { BeginBatch(); - wxSize size(SetOrCalcColumnSizes(false), SetOrCalcRowSizes(false)); - - // round up the size to a multiple of scroll step - this ensures that we - // won't get the scrollbars if we're sized exactly to this width - // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary - // scrollbar steps - wxSize sizeFit( - GetScrollX(size.x + m_extraWidth + 1) * m_scrollLineX, - GetScrollY(size.y + m_extraHeight + 1) * m_scrollLineY ); + // we need to round up the size of the scrollable area to a multiple of + // scroll step to ensure that we don't get the scrollbars when we're sized + // exactly to fit our contents + wxSize size(SetOrCalcColumnSizes(false) - m_rowLabelWidth + m_extraWidth, + SetOrCalcRowSizes(false) - m_colLabelHeight + m_extraHeight); + wxSize sizeFit(GetScrollX(size.x) * GetScrollLineX(), + GetScrollY(size.y) * GetScrollLineY()); // distribute the extra space between the columns/rows to avoid having // extra white space - - // Remove the extra m_extraWidth + 1 added above - wxCoord diff = sizeFit.x - size.x + (m_extraWidth + 1); + wxCoord diff = sizeFit.x - size.x; if ( diff && m_numCols ) { // try to resize the columns uniformly @@ -10535,7 +10595,7 @@ void wxGrid::AutoSize() } // same for rows - diff = sizeFit.y - size.y - (m_extraHeight + 1); + diff = sizeFit.y - size.y; if ( diff && m_numRows ) { // try to resize the columns uniformly @@ -10559,9 +10619,13 @@ void wxGrid::AutoSize() } } - EndBatch(); + // we know that we're not going to have scrollbars so disable them now to + // avoid trouble in SetClientSize() which can otherwise set the correct + // client size but also leave space for (not needed any more) scrollbars + SetScrollbars(0, 0, 0, 0, 0, 0, true); + SetClientSize(sizeFit.x + m_rowLabelWidth, sizeFit.y + m_colLabelHeight); - SetClientSize(sizeFit); + EndBatch(); } void wxGrid::AutoSizeRowLabelSize( int row ) @@ -10615,46 +10679,22 @@ void wxGrid::AutoSizeColLabelSize( int col ) wxSize wxGrid::DoGetBestSize() const { - // don't set sizes, only calculate them wxGrid *self = (wxGrid *)this; // const_cast - int width, height; - width = self->SetOrCalcColumnSizes(true); - height = self->SetOrCalcRowSizes(true); - - if (!width) - width = 100; - if (!height) - height = 80; - - // Round up to a multiple the scroll rate - // NOTE: this still doesn't get rid of the scrollbars; - // is there any magic incantation for that? - int xpu, ypu; - GetScrollPixelsPerUnit(&xpu, &ypu); - if (xpu) - width += 1 + xpu - (width % xpu); - if (ypu) - height += 1 + ypu - (height % ypu); - - // limit to 1/4 of the screen size - int maxwidth, maxheight; - wxDisplaySize( &maxwidth, &maxheight ); - maxwidth /= 2; - maxheight /= 2; - if ( width > maxwidth ) - width = maxwidth; - if ( height > maxheight ) - height = maxheight; - - wxSize best(width, height); + // we do the same as in AutoSize() here with the exception that we don't + // change the column/row sizes, only calculate them + wxSize size(self->SetOrCalcColumnSizes(true) - m_rowLabelWidth + m_extraWidth, + self->SetOrCalcRowSizes(true) - m_colLabelHeight + m_extraHeight); + wxSize sizeFit(GetScrollX(size.x) * GetScrollLineX(), + GetScrollY(size.y) * GetScrollLineY()); // NOTE: This size should be cached, but first we need to add calls to // InvalidateBestSize everywhere that could change the results of this // calculation. // CacheBestSize(size); - return best; + return wxSize(sizeFit.x + m_rowLabelWidth, sizeFit.y + m_colLabelHeight) + + GetWindowBorderSize(); } void wxGrid::Fit()