X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c118fa5f2035b48f059de0353950bceedc5a10d4..f5f0774124e3a56f6fb0b1472a4c54e69c6e19c0:/src/generic/grid.cpp diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 3d79bc7f7c..fc83204fb7 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -1535,7 +1535,8 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols ) // the label of the first column had been set it would have only one // element and not numCols, so account for it int numRemaining = m_colLabels.size() - colID; - m_colLabels.RemoveAt( colID, wxMin(numCols, numRemaining) ); + if (numRemaining > 0) + m_colLabels.RemoveAt( colID, wxMin(numCols, numRemaining) ); } if ( numCols >= curNumCols ) @@ -1775,6 +1776,267 @@ void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) m_owner->DrawHighlight( dc, dirtyCells ); } +void wxGrid::Render( wxDC& dc, + const wxPoint& position, + const wxSize& size, + const wxGridCellCoords& topLeft, + const wxGridCellCoords& bottomRight, + int style ) +{ + wxCHECK_RET( bottomRight.GetCol() < GetNumberCols(), + "Invalid right column" ); + wxCHECK_RET( bottomRight.GetRow() < GetNumberRows(), + "Invalid bottom row" ); + + // store user settings and reset later + + // remove grid selection, don't paint selection colour + // unless we have wxGRID_DRAW_SELECTION + // block selections are the only ones catered for here + wxGridCellCoordsArray selectedCells; + bool hasSelection = IsSelection(); + if ( hasSelection && !( style & wxGRID_DRAW_SELECTION ) ) + { + selectedCells = GetSelectionBlockTopLeft(); + // non block selections may not have a bottom right + if ( GetSelectionBlockBottomRight().size() ) + selectedCells.Add( GetSelectionBlockBottomRight()[ 0 ] ); + + ClearSelection(); + } + + // store user device origin + wxCoord userOriginX, userOriginY; + dc.GetDeviceOrigin( &userOriginX, &userOriginY ); + + // store user scale + double scaleUserX, scaleUserY; + dc.GetUserScale( &scaleUserX, &scaleUserY ); + + // set defaults if necessary + long colLeft = topLeft.GetCol() > -1 ? topLeft.GetCol() : 0; + long rowTop = topLeft.GetRow() > -1 ? topLeft.GetRow() : 0; + long colRight = bottomRight.GetCol() > -1 ? bottomRight.GetCol() + : GetNumberCols() - 1; + long rowBottom = bottomRight.GetRow() > -1 ? bottomRight.GetRow() + : GetNumberRows() - 1; + + // get grid area size to be rendered + long offsetCols = 0, offsetRows = 0; + wxGridCellCoordsArray renderCells; + wxArrayInt arrayCols; + wxArrayInt arrayRows; + int col, row, gridWidth, gridHeight; + + // fill array with cells to be rendered + // calculate width of cell drawn area + // and get grid column offset used where startcol > 0 + gridWidth = 0; + wxGridSizesInfo sizeinfo = GetColSizes(); + for ( col = 0; col <= colRight; col++ ) + { + if ( col < colLeft ) + { + offsetCols += sizeinfo.GetSize( col ); + } + else + { + for ( row = rowTop; row <= rowBottom; row++ ) + { + renderCells.Add( wxGridCellCoords( row, col )); + arrayRows.Add( row ); // column labels rendered in DrawColLabels + } + arrayCols.Add( col ); // row labels rendered in DrawRowLabels + gridWidth += sizeinfo.GetSize( col ); + } + } + + // calculate height of rendered cells + // and row Y offset where startrow > 0 + gridHeight = 0; + sizeinfo = GetRowSizes(); + for ( row = 0; row <= rowBottom; row++ ) + { + if ( row < rowTop ) + offsetRows += sizeinfo.GetSize( row ); + else + gridHeight += sizeinfo.GetSize( row ); + } + + // add headers/labels to dimensions + if ( style & wxGRID_DRAW_ROWS_HEADER ) + gridWidth += GetRowLabelSize(); + if ( style & wxGRID_DRAW_COLS_HEADER ) + gridHeight += GetColLabelSize(); + + // set drawing start position DeviceOrigin + // if not specified use previous dc draw extents MaxX and MaxY + wxPoint positionRender = position; + if ( !positionRender.IsFullySpecified() ) + { + if ( positionRender.x == wxDefaultPosition.x ) + positionRender.x = dc.MaxX(); + + if ( positionRender.y == wxDefaultPosition.y ) + positionRender.y = dc.MaxY(); + } + + // positionRender should be in logical units + wxCoord originX = dc.LogicalToDeviceX( positionRender.x ); + wxCoord originY = dc.LogicalToDeviceY( positionRender.y ); + + dc.SetDeviceOrigin( originX, originY ); + + SetRenderScale( dc, positionRender, size, gridWidth, gridHeight ); + + // draw row headers at specified origin + if ( GetRowLabelSize() > 0 && ( style & wxGRID_DRAW_ROWS_HEADER ) ) + { + if ( style & wxGRID_DRAW_COLS_HEADER ) + { + DrawCornerLabel( dc ); // do only if both col and row labels drawn + originY += dc.LogicalToDeviceYRel( GetColLabelSize() ); + } + + originY -= dc.LogicalToDeviceYRel( offsetRows ); + dc.SetDeviceOrigin( originX, originY ); + + DrawRowLabels( dc, arrayRows ); + + // reset for columns + if ( style & wxGRID_DRAW_COLS_HEADER ) + originY -= dc.LogicalToDeviceYRel( GetColLabelSize() ); + + originY += dc.LogicalToDeviceYRel( offsetRows ); + // X offset so we don't overwrite row labels + originX += dc.LogicalToDeviceXRel( GetRowLabelSize() ); + } + + // subtract col offset where startcol > 0 + originX -= dc.LogicalToDeviceXRel( offsetCols ); + // no y offset for col labels, they are at the Y origin + + // draw column labels + if ( style & wxGRID_DRAW_COLS_HEADER ) + { + dc.SetDeviceOrigin( originX, originY ); + DrawColLabels( dc, arrayCols ); + // don't overwrite the labels, increment originY + originY += dc.LogicalToDeviceYRel( GetColLabelSize() ); + } + + // set device origin to draw grid cells and lines + originY -= dc.LogicalToDeviceYRel( offsetRows ); + dc.SetDeviceOrigin( originX, originY ); + + // draw cell area background + dc.SetBrush( GetDefaultCellBackgroundColour() ); + dc.SetPen( *wxTRANSPARENT_PEN ); + // subtract headers from grid area dimensions + unsigned cellsWidth = gridWidth, cellsHeight = gridHeight; + if ( style & wxGRID_DRAW_ROWS_HEADER ) + cellsWidth -= GetRowLabelSize(); + if ( style & wxGRID_DRAW_COLS_HEADER ) + cellsHeight -= GetColLabelSize(); + + dc.DrawRectangle( wxPoint( offsetCols, offsetRows ), + wxSize( cellsWidth, cellsHeight ) ); + + // draw cells + DrawGridCellArea( dc, renderCells ); + + // calculate region for drawing grid lines + if ( style & wxGRID_DRAW_CELL_LINES ) + { + wxRegion regionClip( offsetCols, + offsetRows, + cellsWidth, + cellsHeight ); + + DrawRangeGridLines(dc, regionClip, renderCells[0], renderCells.Last()); + } + + // draw render rectangle bounding lines + // useful where there is multi cell row or col clipping and no cell border + if ( style & wxGRID_DRAW_BOX_RECT ) + { + int bottom = offsetRows + cellsHeight, + right = offsetCols + cellsWidth - 1; + + // horiz top line if we are not drawing column header/labels + if ( !( style & wxGRID_DRAW_COLS_HEADER ) ) + { + int left = offsetCols; + left += ( style & wxGRID_DRAW_COLS_HEADER ) + ? - GetRowLabelSize() : 0; + dc.SetPen( GetRowGridLinePen( rowTop ) ); + dc.DrawLine( left, + offsetRows, + right, + offsetRows ); + } + + // horiz bottom line + dc.SetPen( GetRowGridLinePen( rowBottom ) ); + dc.DrawLine( offsetCols, bottom - 1, right, bottom - 1 ); + + // left vertical line if we are not drawing row header/labels + if ( !( style & wxGRID_DRAW_ROWS_HEADER ) ) + { + int top = offsetRows; + top += ( style & wxGRID_DRAW_COLS_HEADER ) + ? - GetColLabelSize() : 0; + dc.SetPen( GetColGridLinePen( colLeft ) ); + dc.DrawLine( offsetCols -1, + top, + offsetCols - 1, + bottom - 1 ); + } + + // right vertical line + dc.SetPen( GetColGridLinePen( colRight ) ); + dc.DrawLine( right, offsetRows, right, bottom - 1 ); + } + + // restore user setings + dc.SetDeviceOrigin( userOriginX, userOriginY ); + dc.SetUserScale( scaleUserX, scaleUserY ); + + if ( selectedCells.size() && !( style & wxGRID_DRAW_SELECTION ) ) + { + SelectBlock( selectedCells[ 0 ].GetRow(), + selectedCells[ 0 ].GetCol(), + selectedCells[ selectedCells.size() -1 ].GetRow(), + selectedCells[ selectedCells.size() -1 ].GetCol() ); + } +} + +void +wxGrid::SetRenderScale(wxDC& dc, + const wxPoint& pos, const wxSize& size, + int gridWidth, int gridHeight) +{ + double scaleX, scaleY; + wxSize sizeTemp; + + if ( size.GetX() != wxDefaultSize.GetX() ) // size.x was specified + sizeTemp.SetWidth( size.GetX() ); + else + sizeTemp.SetWidth( dc.DeviceToLogicalXRel( dc.GetSize().GetX() ) + - pos.x ); + + if ( size.GetY() != wxDefaultSize.GetY() ) // size.y was specified + sizeTemp.SetHeight( size.GetY() ); + else + sizeTemp.SetHeight( dc.DeviceToLogicalYRel( dc.GetSize().GetY() ) + - pos.y ); + + scaleX = (double)( (double) sizeTemp.GetX() / (double) gridWidth ); + scaleY = (double)( (double) sizeTemp.GetY() / (double) gridHeight ); + + dc.SetUserScale( wxMin( scaleX, scaleY), wxMin( scaleX, scaleY ) ); +} + void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect ) { wxWindow::ScrollWindow( dx, dy, rect ); @@ -5345,6 +5607,67 @@ void wxGrid::DrawHighlight(wxDC& dc, const wxGridCellCoordsArray& cells) } } +// Used by wxGrid::Render() to draw the grid lines only for the cells in the +// specified range. +void +wxGrid::DrawRangeGridLines(wxDC& dc, + const wxRegion& reg, + const wxGridCellCoords& topLeft, + const wxGridCellCoords& bottomRight) +{ + if ( !m_gridLinesEnabled ) + return; + + int top, left, width, height; + reg.GetBox( left, top, width, height ); + + // create a clipping region + wxRegion clippedcells( dc.LogicalToDeviceX( left ), + dc.LogicalToDeviceY( top ), + dc.LogicalToDeviceXRel( width ), + dc.LogicalToDeviceYRel( height ) ); + + // subtract multi cell span area from clipping region for lines + wxRect rect; + for ( int row = topLeft.GetRow(); row <= bottomRight.GetRow(); row++ ) + { + for ( int col = topLeft.GetCol(); col <= bottomRight.GetCol(); col++ ) + { + int cell_rows, cell_cols; + GetCellSize( row, col, &cell_rows, &cell_cols ); + if ( cell_rows > 1 || cell_cols > 1 ) // multi cell + { + rect = CellToRect( row, col ); + // cater for scaling + // device origin already set in ::Render() for x, y + rect.x = dc.LogicalToDeviceX( rect.x ); + rect.y = dc.LogicalToDeviceY( rect.y ); + rect.width = dc.LogicalToDeviceXRel( rect.width ); + rect.height = dc.LogicalToDeviceYRel( rect.height ) - 1; + clippedcells.Subtract( rect ); + } + else if ( cell_rows < 0 || cell_cols < 0 ) // part of multicell + { + rect = CellToRect( row + cell_rows, col + cell_cols ); + rect.x = dc.LogicalToDeviceX( rect.x ); + rect.y = dc.LogicalToDeviceY( rect.y ); + rect.width = dc.LogicalToDeviceXRel( rect.width ); + rect.height = dc.LogicalToDeviceYRel( rect.height ) - 1; + clippedcells.Subtract( rect ); + } + } + } + + dc.SetDeviceClippingRegion( clippedcells ); + + DoDrawGridLines(dc, + top, left, top + height, left + width, + topLeft.GetRow(), topLeft.GetCol(), + bottomRight.GetRow(), bottomRight.GetCol()); + + dc.DestroyClippingRegion(); +} + // This is used to redraw all grid lines e.g. when the grid line colour // has been changed // @@ -5416,9 +5739,22 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) dc.SetDeviceClippingRegion( clippedcells ); + DoDrawGridLines(dc, + top, left, bottom, right, + topRow, leftCol, m_numRows, m_numCols); + + dc.DestroyClippingRegion(); +} +void +wxGrid::DoDrawGridLines(wxDC& dc, + int top, int left, + int bottom, int right, + int topRow, int leftCol, + int bottomRow, int rightCol) +{ // horizontal grid lines - for ( int i = internalYToRow(top); i < m_numRows; i++ ) + for ( int i = topRow; i < bottomRow; i++ ) { int bot = GetRowBottom(i) - 1; @@ -5433,7 +5769,7 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) } // vertical grid lines - for ( int colPos = leftCol; colPos < m_numCols; colPos++ ) + for ( int colPos = leftCol; colPos < rightCol; colPos++ ) { int i = GetColAt( colPos ); @@ -5452,8 +5788,6 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) dc.DrawLine( colRight, top, colRight, bottom ); } } - - dc.DestroyClippingRegion(); } void wxGrid::DrawRowLabels( wxDC& dc, const wxArrayInt& rows) @@ -7681,7 +8015,7 @@ void wxGrid::SetRowSize( int row, int height ) } // See comment in SetColSize - if ( height < GetRowMinimalAcceptableHeight()) + if ( height > 0 && height < GetRowMinimalAcceptableHeight()) return; if ( m_rowHeights.IsEmpty() ) @@ -7700,7 +8034,10 @@ void wxGrid::SetRowSize( int row, int height ) } if ( !GetBatchCount() ) + { CalcDimensions(); + Refresh(); + } } void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols )