// Required for wxIs... functions
#include <ctype.h>
-WX_DECLARE_HASH_SET_WITH_DECL(int, wxIntegerHash, wxIntegerEqual,
- wxGridFixedIndicesSet, class WXDLLIMPEXP_ADV);
+WX_DECLARE_HASH_SET_WITH_DECL_PTR(int, ::wxIntegerHash, ::wxIntegerEqual,
+ wxGridFixedIndicesSet, class WXDLLIMPEXP_ADV);
// ----------------------------------------------------------------------------
wxASSERT_MSG( (!((num_rows > 0) && (num_cols <= 0)) ||
!((num_rows <= 0) && (num_cols > 0)) ||
!((num_rows == 0) && (num_cols == 0))),
- wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values"));
+ wxT("wxGridCellAttr::SetSize only takes two positive values or negative/zero values"));
m_sizeRows = num_rows;
m_sizeCols = num_cols;
// 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 )
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 );
// grid mouse event processing
// ----------------------------------------------------------------------------
-void
+bool
wxGrid::DoGridCellDrag(wxMouseEvent& event,
const wxGridCellCoords& coords,
bool isFirstDrag)
{
+ bool performDefault = true ;
+
if ( coords == wxGridNoCellCoords )
- return; // we're outside any valid cell
+ return performDefault; // we're outside any valid cell
// Hide the edit control, so it won't interfere with drag-shrinking.
if ( IsCellEditControlShown() )
switch ( event.GetModifiers() )
{
- case wxMOD_CMD:
+ case wxMOD_CONTROL:
if ( m_selectedBlockCorner == wxGridNoCellCoords)
m_selectedBlockCorner = coords;
UpdateBlockBeingSelected(m_selectedBlockCorner, coords);
if ( m_selectedBlockCorner == wxGridNoCellCoords)
m_selectedBlockCorner = coords;
- SendEvent(wxEVT_GRID_CELL_BEGIN_DRAG, coords, event);
- return;
+ // if event is handled by user code, no further processing
+ if ( SendEvent(wxEVT_GRID_CELL_BEGIN_DRAG, coords, event) != 0 )
+ performDefault = false;
+
+ return performDefault;
}
}
// we don't handle the other key modifiers
event.Skip();
}
+
+ return performDefault;
}
void wxGrid::DoGridLineDrag(wxMouseEvent& event, const wxGridOperations& oper)
switch ( m_cursorMode )
{
case WXGRID_CURSOR_SELECT_CELL:
- DoGridCellDrag(event, coords, isFirstDrag);
+ // no further handling if handled by user
+ if ( DoGridCellDrag(event, coords, isFirstDrag) == false )
+ return;
break;
case WXGRID_CURSOR_RESIZE_ROW:
mouseEv.GetY() + GetColLabelSize(),
false,
mouseEv);
+
+ if ( type == wxEVT_GRID_CELL_BEGIN_DRAG )
+ {
+ // by default the dragging is not supported, the user code must
+ // explicitly allow the event for it to take place
+ gridEvt.Veto();
+ }
+
claimed = GetEventHandler()->ProcessEvent(gridEvt);
vetoed = !gridEvt.IsAllowed();
}
}
}
+// 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
//
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;
}
// vertical grid lines
- for ( int colPos = leftCol; colPos < m_numCols; colPos++ )
+ for ( int colPos = leftCol; colPos < rightCol; colPos++ )
{
int i = GetColAt( colPos );
dc.DrawLine( colRight, top, colRight, bottom );
}
}
-
- dc.DestroyClippingRegion();
}
void wxGrid::DrawRowLabels( wxDC& dc, const wxArrayInt& rows)
}
// See comment in SetColSize
- if ( height < GetRowMinimalAcceptableHeight())
+ if ( height > 0 && height < GetRowMinimalAcceptableHeight())
return;
if ( m_rowHeights.IsEmpty() )
}
if ( !GetBatchCount() )
+ {
CalcDimensions();
+ Refresh();
+ }
}
void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols )
AutoSize();
}
+#if WXWIN_COMPATIBILITY_2_8
wxPen& wxGrid::GetDividerPen() const
{
return wxNullPen;
}
+#endif // WXWIN_COMPATIBILITY_2_8
// ----------------------------------------------------------------------------
// cell value accessor functions