From: Vadim Zeitlin Date: Fri, 12 Dec 2008 17:34:13 +0000 (+0000) Subject: fix compuation of dirty cells when the columns are reordered, this didn't work at... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/cd4f6f5f8fec6168cebe58afe71d27064ff9a0f8?ds=inline fix compuation of dirty cells when the columns are reordered, this didn't work at all before git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57291 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 1e0e44b01c..ec0043baf7 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -1313,6 +1313,12 @@ public: 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; @@ -1505,33 +1511,48 @@ public: 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 @@ -2225,6 +2246,14 @@ private: 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 // -------------------------------- @@ -2273,8 +2302,10 @@ private: // 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, diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index a3f5cb24c7..3ec21337c0 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -616,7 +616,7 @@ public: } - // 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; @@ -5602,9 +5602,8 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg ) const 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; @@ -5612,19 +5611,23 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg ) const 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; @@ -8737,15 +8740,14 @@ wxGridCellCoords wxGrid::XYToCell(int x, int y) const // 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" ); @@ -8789,12 +8791,12 @@ wxGrid::PosToLine(int coord, // 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 @@ -8803,10 +8805,10 @@ wxGrid::PosToLine(int coord, 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--; @@ -8817,7 +8819,17 @@ wxGrid::PosToLine(int coord, 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 @@ -8830,6 +8842,11 @@ int wxGrid::XToCol(int x, 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. //