wxGridCellCoords XYToCell(const wxPoint& pos) const
{ return XYToCell(pos.x, pos.y); }
+ // these functions return the index of the row/columns corresponding to the
+ // given logical position in pixels
+ //
+ // if clipToMinMax is false (default, wxNOT_FOUND is returned if the
+ // position is outside any row/column, otherwise the first/last element is
+ // returned in this case
int YToRow( int y, bool clipToMinMax = false ) const;
int XToCol( int x, bool clipToMinMax = false ) const;
void SetColSize( int col, int width );
- //Column positions
- int GetColAt( int colPos ) const
+ // columns index <-> positions mapping: by default, the position of the
+ // column is the same as its index, but the columns can also be reordered
+ // (either by calling SetColPos() explicitly or by the user dragging the
+ // columns around) in which case their indices don't correspond to their
+ // positions on display any longer
+ //
+ // internally we always work with indices except for the functions which
+ // have "Pos" in their names (and which work with columns, not pixels) and
+ // only the display and hit testing code really cares about display
+ // positions at all
+
+ // return the column index corresponding to the given (valid) position
+ int GetColAt(int pos) const
{
- if ( m_colAt.IsEmpty() )
- return colPos;
- else
- return m_colAt[colPos];
+ return m_colAt.empty() ? pos : m_colAt[pos];
}
- void SetColPos( int colID, int newPos );
+ // reorder the columns so that the column with the given index is now shown
+ // as the position pos
+ void SetColPos(int idx, int pos);
- int GetColPos( int colID ) const
+ // return the position at which the column with the given index is
+ // displayed: notice that this is a slow operation as we don't maintain the
+ // reverse mapping currently
+ int GetColPos(int idx) const
{
if ( m_colAt.IsEmpty() )
- return colID;
- else
+ return idx;
+
+ for ( int i = 0; i < m_numCols; i++ )
{
- for ( int i = 0; i < m_numCols; i++ )
- {
- if ( m_colAt[i] == colID )
- return i;
- }
+ if ( m_colAt[i] == idx )
+ return i;
}
- return -1;
+ wxFAIL_MSG( "invalid column index" );
+
+ return wxNOT_FOUND;
}
+
+
// automatically size the column or row to fit to its contents, if
// setAsMin is true, this optimal width will also be set as minimal width
// for this column
void DoClipGridLines(bool& var, bool clip);
+ // return the position (not index) of the column at the given logical pixel
+ // position
+ //
+ // this always returns a valid position, even if the coordinate is out of
+ // bounds (in which case first/last column is returned)
+ int XToPos(int x) const;
+
+
// event handlers and their helpers
// --------------------------------
// common implementations of methods defined for both rows and columns
void DeselectLine(int line, const wxGridOperations& oper);
void DoEndDragResizeLine(const wxGridOperations& oper);
- int PosToLine(int pos, bool clipToMinMax,
- const wxGridOperations& oper) const;
+ int PosToLinePos(int pos, bool clipToMinMax,
+ const wxGridOperations& oper) const;
+ int PosToLine(int pos, bool clipToMinMax,
+ const wxGridOperations& oper) const;
int PosToEdgeOfLine(int pos, const wxGridOperations& oper) const;
bool DoMoveCursor(bool expandSelection,
}
- // Return the row or column at the given pixel coordinate.
+ // Return the index of the row or column at the given pixel coordinate.
virtual int
PosToLine(const wxGrid *grid, int pos, bool clip = false) const = 0;
CalcUnscrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom );
// find the cells within these bounds
- //
- int row, col;
- for ( row = internalYToRow(top); row < m_numRows; row++ )
+ wxArrayInt cols;
+ for ( int row = internalYToRow(top); row < m_numRows; row++ )
{
if ( GetRowBottom(row) <= top )
continue;
if ( GetRowTop(row) > bottom )
break;
- int colPos;
- for ( colPos = GetColPos( internalXToCol(left) ); colPos < m_numCols; colPos++ )
+ // add all dirty cells in this row: notice that the columns which
+ // are dirty don't depend on the row so we compute them only once
+ // for the first dirty row and then reuse for all the next ones
+ if ( cols.empty() )
{
- col = GetColAt( colPos );
+ // do determine the dirty columns
+ for ( int pos = XToPos(left); pos <= XToPos(right); pos++ )
+ cols.push_back(GetColAt(pos));
- if ( GetColRight(col) <= left )
- continue;
-
- if ( GetColLeft(col) > right )
+ // if there are no dirty columns at all, nothing to do
+ if ( cols.empty() )
break;
-
- cellsExposed.Add( wxGridCellCoords( row, col ) );
}
+
+ const size_t count = cols.size();
+ for ( size_t n = 0; n < count; n++ )
+ cellsExposed.Add(wxGridCellCoords(row, cols[n]));
}
++iter;
// m_defaultRowHeight/m_defaultColWidth or binary search on array of
// m_rowBottoms/m_colRights to do it quickly (linear search shouldn't be used
// for large grids)
-int
-wxGrid::PosToLine(int coord,
- bool clipToMinMax,
- const wxGridOperations& oper) const
+int wxGrid::PosToLinePos(int coord,
+ bool clipToMinMax,
+ const wxGridOperations& oper) const
{
const int numLines = oper.GetNumberOfLines(this);
if ( coord < 0 )
- return clipToMinMax && numLines > 0 ? oper.GetLineAt(this, 0) : -1;
+ return clipToMinMax && numLines > 0 ? 0 : wxNOT_FOUND;
const int defaultLineSize = oper.GetDefaultLineSize(this);
wxCHECK_MSG( defaultLineSize, -1, "can't have 0 default line size" );
// check if the position is beyond the last column
const int lineAtMaxPos = oper.GetLineAt(this, maxPos);
if ( coord >= lineEnds[lineAtMaxPos] )
- return clipToMinMax ? lineAtMaxPos : -1;
+ return clipToMinMax ? maxPos : -1;
// or before the first one
const int lineAt0 = oper.GetLineAt(this, 0);
if ( coord < lineEnds[lineAt0] )
- return lineAt0;
+ return 0;
// finally do perform the binary search
wxCHECK_MSG( lineEnds[oper.GetLineAt(this, minPos)] <= coord &&
coord < lineEnds[oper.GetLineAt(this, maxPos)],
-1,
- "wxGrid: internal error in PosToLine()" );
+ "wxGrid: internal error in PosToLinePos()" );
if ( coord >= lineEnds[oper.GetLineAt(this, maxPos - 1)] )
- return oper.GetLineAt(this, maxPos);
+ return maxPos;
else
maxPos--;
minPos = median;
}
- return oper.GetLineAt(this, maxPos);
+ return maxPos;
+}
+
+int
+wxGrid::PosToLine(int coord,
+ bool clipToMinMax,
+ const wxGridOperations& oper) const
+{
+ int pos = PosToLinePos(coord, clipToMinMax, oper);
+
+ return pos == wxNOT_FOUND ? wxNOT_FOUND : oper.GetLineAt(this, pos);
}
int wxGrid::YToRow(int y, bool clipToMinMax) const
return PosToLine(x, clipToMinMax, wxGridColumnOperations());
}
+int wxGrid::XToPos(int x) const
+{
+ return PosToLinePos(x, true /* clip */, wxGridColumnOperations());
+}
+
// return the row number that that the y coord is near the edge of, or -1 if
// not near an edge.
//