From: Vadim Zeitlin Date: Tue, 16 Sep 2008 08:32:12 +0000 (+0000) Subject: start of the great grid folding: introduce wxGridOperations class and use it to avoid... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/bec7026270ecdb5f9019c3180b228da0469df710 start of the great grid folding: introduce wxGridOperations class and use it to avoid duplicating the same code for rows and columns in a couple of methods git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55652 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 3ed65db5ba..767635a16f 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -84,6 +84,10 @@ class WXDLLIMPEXP_FWD_CORE wxTextCtrl; class WXDLLIMPEXP_FWD_CORE wxSpinCtrl; #endif +class wxGridOperations; +class wxGridRowOperations; +class wxGridColumnOperations; + // ---------------------------------------------------------------------------- // macros // ---------------------------------------------------------------------------- @@ -1264,7 +1268,7 @@ public: // coordinates for mouse events etc. // void XYToCell( int x, int y, wxGridCellCoords& ) const; - int YToRow( int y ) const; + int YToRow( int y, bool clipToMinMax = false ) const; int XToCol( int x, bool clipToMinMax = false ) const; int YToEdgeOfRow( int y ) const; @@ -1405,6 +1409,12 @@ public: bool GetDefaultCellOverflow() const; bool GetCellOverflow( int row, int col ) const; void GetCellSize( int row, int col, int *num_rows, int *num_cols ) const; + wxSize GetCellSize(const wxGridCellCoords& coords) + { + wxSize s; + GetCellSize(coords.GetRow(), coords.GetCol(), &s.x, &s.y); + return s; + } void SetDefaultRowSize( int height, bool resizeExistingRows = false ); void SetRowSize( int row, int height ); @@ -1982,8 +1992,13 @@ protected: bool m_canDragColMove; bool m_canDragGridSize; bool m_canDragCell; + + // the last position (horizontal or vertical depending on whether the user + // is resizing a column or a row) where a row or column separator line was + // dragged by the user or -1 of there is no drag operation in progress int m_dragLastPos; int m_dragRowOrCol; + bool m_isDragging; wxPoint m_startDragPos; @@ -2042,11 +2057,21 @@ protected: bool SetModelValues(); friend class WXDLLIMPEXP_FWD_ADV wxGridSelection; + friend class wxGridRowOperations; + friend class wxGridColumnOperations; private: // implement wxScrolledWindow method to return m_gridWin size virtual wxSize GetSizeAvailableForScrollTarget(const wxSize& size); + + // 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; + + DECLARE_DYNAMIC_CLASS( wxGrid ) DECLARE_EVENT_TABLE() DECLARE_NO_COPY_CLASS(wxGrid) diff --git a/include/wx/generic/gridsel.h b/include/wx/generic/gridsel.h index fff21a3684..ab83260f91 100644 --- a/include/wx/generic/gridsel.h +++ b/include/wx/generic/gridsel.h @@ -21,10 +21,16 @@ class WXDLLIMPEXP_ADV wxGridSelection { public: - wxGridSelection( wxGrid * grid, wxGrid::wxGridSelectionModes sel = - wxGrid::wxGridSelectCells ); + wxGridSelection(wxGrid *grid, + wxGrid::wxGridSelectionModes sel = wxGrid::wxGridSelectCells); + bool IsSelection(); - bool IsInSelection ( int row, int col ); + bool IsInSelection(int row, int col); + bool IsInSelection(const wxGridCellCoords& coords) + { + return IsInSelection(coords.GetRow(), coords.GetCol()); + } + void SetSelectionMode(wxGrid::wxGridSelectionModes selmode); wxGrid::wxGridSelectionModes GetSelectionMode() { return m_selectionMode; } void SelectRow( int row, @@ -46,6 +52,15 @@ public: bool ControlDown = false, bool ShiftDown = false, bool AltDown = false, bool MetaDown = false ); + void ToggleCellSelection( const wxGridCellCoords& coords, + bool ControlDown = false, + bool ShiftDown = false, + bool AltDown = false, bool MetaDown = false ) + { + ToggleCellSelection(coords.GetRow(), coords.GetCol(), + ControlDown, ShiftDown, AltDown, MetaDown); + } + void ClearSelection(); void UpdateRows( size_t pos, int numRows ); diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 3506da69f0..0f8f95ea1b 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -9,6 +9,13 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +/* + TODO: + + - Replace use of wxINVERT with wxOverlay + - Make Begin/EndBatch() the same as the generic Freeze/Thaw() + */ + // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" @@ -388,7 +395,7 @@ WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGridDataTypeInfo*, wxGridDataTypeInfoArray, class WXDLLIMPEXP_ADV wxGridTypeRegistry { public: - wxGridTypeRegistry() {} + wxGridTypeRegistry() {} ~wxGridTypeRegistry(); void RegisterDataType(const wxString& typeName, @@ -414,6 +421,211 @@ private: wxGridDataTypeInfoArray m_typeinfo; }; +// ---------------------------------------------------------------------------- +// operations classes abstracting the difference between operating on rows and +// columns +// ---------------------------------------------------------------------------- + +// This class allows to write a function only once because by using its methods +// it will apply to both columns and rows. +// +// This is an abstract interface definition, the two concrete implementations +// below should be used when working with rows and columns respectively. +class wxGridOperations +{ +public: + // Returns the operations in the other direction, i.e. wxGridRowOperations + // if this object is a wxGridColumnOperations and vice versa. + virtual wxGridOperations& Dual() const = 0; + + // Return the number of rows or columns. + virtual int GetNumberOfLines(const wxGrid *grid) const = 0; + + // Return the selection mode which allows selecting rows or columns. + virtual wxGrid::wxGridSelectionModes GetSelectionMode() const = 0; + + // Make a wxGridCellCoords from the given components: thisDir is row or + // column and otherDir is column or row + virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const = 0; + + // Calculate the scrolled position of the given abscissa or ordinate. + virtual int CalcScrolledPosition(wxGrid *grid, int pos) const = 0; + + // Selects the horizontal or vertical component from the given object. + virtual int Select(const wxPoint& pt) const = 0; + virtual int Select(const wxSize& sz) const = 0; + virtual int Select(const wxRect& r) const = 0; + virtual int& Select(wxRect& r) const = 0; + + // Returns width or height of the rectangle + virtual int& SelectSize(wxRect& r) const = 0; + + // Make a wxSize such that Select() applied to it returns first component + virtual wxSize MakeSize(int first, int second) const = 0; + + + // Draws a line parallel to the row or column, i.e. horizontal or vertical: + // pos is the vertical or horizontal position of the line and start and end + // are the coordinates of the line extremities in the other direction + virtual void + DrawParallelLine(wxDC& dc, int start, int end, int pos) const = 0; + + + // Return the row or column at the given pixel coordinate. + virtual int PosToLine(wxGrid *grid, int pos, bool clip = false) const = 0; + + // Get the top/left position, in pixels, of the given row or column + virtual int GetLineStartPos(const wxGrid *grid, int line) const = 0; + + // Get wxGrid::m_rowBottoms/m_colRights array + virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const = 0; + + // Get default height row height or column width + virtual int GetDefaultLineSize(const wxGrid *grid) const = 0; + + // Return the minimal acceptable row height or column width + virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const = 0; + + // Return the minimal row height or column width + virtual int GetMinimalLineSize(const wxGrid *grid, int line) const = 0; + + // Set the row height or column width + virtual void SetLineSize(wxGrid *grid, int line, int size) const = 0; + + + // Return the index of the line at the given position + // + // NB: currently this is always identity for the rows as reordering is only + // implemented for the lines + virtual int GetLineAt(const wxGrid *grid, int line) const = 0; + + + // Get the row or column label window + virtual wxWindow *GetHeaderWindow(wxGrid *grid) const = 0; + + // Get the width or height of the row or column label window + virtual int GetHeaderWindowSize(wxGrid *grid) const = 0; +}; + +class wxGridRowOperations : public wxGridOperations +{ +public: + virtual wxGridOperations& Dual() const; + + virtual int GetNumberOfLines(const wxGrid *grid) const + { return grid->GetNumberRows(); } + + virtual wxGrid::wxGridSelectionModes GetSelectionMode() const + { return wxGrid::wxGridSelectRows; } + + virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const + { return wxGridCellCoords(thisDir, otherDir); } + + virtual int CalcScrolledPosition(wxGrid *grid, int pos) const + { return grid->CalcScrolledPosition(wxPoint(pos, 0)).x; } + + virtual int Select(const wxPoint& pt) const { return pt.x; } + virtual int Select(const wxSize& sz) const { return sz.x; } + virtual int Select(const wxRect& r) const { return r.x; } + virtual int& Select(wxRect& r) const { return r.x; } + virtual int& SelectSize(wxRect& r) const { return r.width; } + virtual wxSize MakeSize(int first, int second) const + { return wxSize(first, second); } + + virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const + { dc.DrawLine(start, pos, end, pos); } + + virtual int PosToLine(wxGrid *grid, int pos, bool clip = false) const + { return grid->YToRow(pos, clip); } + virtual int GetLineStartPos(const wxGrid *grid, int line) const + { return grid->GetRowTop(line); } + virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const + { return grid->m_rowBottoms; } + virtual int GetDefaultLineSize(const wxGrid *grid) const + { return grid->GetDefaultRowSize(); } + virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const + { return grid->GetRowMinimalAcceptableHeight(); } + virtual int GetMinimalLineSize(const wxGrid *grid, int line) const + { return grid->GetRowMinimalHeight(line); } + virtual void SetLineSize(wxGrid *grid, int line, int size) const + { grid->SetRowSize(line, size); } + + virtual int GetLineAt(const wxGrid * WXUNUSED(grid), int line) const + { return line; } // TODO: implement row reordering + + virtual wxWindow *GetHeaderWindow(wxGrid *grid) const + { return grid->GetGridRowLabelWindow(); } + virtual int GetHeaderWindowSize(wxGrid *grid) const + { return grid->GetRowLabelSize(); } +}; + +class wxGridColumnOperations : public wxGridOperations +{ +public: + virtual wxGridOperations& Dual() const; + + virtual int GetNumberOfLines(const wxGrid *grid) const + { return grid->GetNumberCols(); } + + virtual wxGrid::wxGridSelectionModes GetSelectionMode() const + { return wxGrid::wxGridSelectColumns; } + + virtual wxGridCellCoords MakeCoords(int thisDir, int otherDir) const + { return wxGridCellCoords(otherDir, thisDir); } + + virtual int CalcScrolledPosition(wxGrid *grid, int pos) const + { return grid->CalcScrolledPosition(wxPoint(0, pos)).y; } + + virtual int Select(const wxPoint& pt) const { return pt.y; } + virtual int Select(const wxSize& sz) const { return sz.y; } + virtual int Select(const wxRect& r) const { return r.y; } + virtual int& Select(wxRect& r) const { return r.y; } + virtual int& SelectSize(wxRect& r) const { return r.height; } + virtual wxSize MakeSize(int first, int second) const + { return wxSize(second, first); } + + virtual void DrawParallelLine(wxDC& dc, int start, int end, int pos) const + { dc.DrawLine(pos, start, pos, end); } + + virtual int PosToLine(wxGrid *grid, int pos, bool clip = false) const + { return grid->XToCol(pos, clip); } + virtual int GetLineStartPos(const wxGrid *grid, int line) const + { return grid->GetColLeft(line); } + virtual const wxArrayInt& GetLineEnds(const wxGrid *grid) const + { return grid->m_colRights; } + virtual int GetDefaultLineSize(const wxGrid *grid) const + { return grid->GetDefaultColSize(); } + virtual int GetMinimalAcceptableLineSize(const wxGrid *grid) const + { return grid->GetColMinimalAcceptableWidth(); } + virtual int GetMinimalLineSize(const wxGrid *grid, int line) const + { return grid->GetColMinimalWidth(line); } + virtual void SetLineSize(wxGrid *grid, int line, int size) const + { grid->SetColSize(line, size); } + + virtual int GetLineAt(const wxGrid *grid, int line) const + { return grid->GetColAt(line); } + + virtual wxWindow *GetHeaderWindow(wxGrid *grid) const + { return grid->GetGridColLabelWindow(); } + virtual int GetHeaderWindowSize(wxGrid *grid) const + { return grid->GetColLabelSize(); } +}; + +wxGridOperations& wxGridRowOperations::Dual() const +{ + static wxGridColumnOperations s_colOper; + + return s_colOper; +} + +wxGridOperations& wxGridColumnOperations::Dual() const +{ + static wxGridRowOperations s_rowOper; + + return s_rowOper; +} + + // ---------------------------------------------------------------------------- // globals // ---------------------------------------------------------------------------- @@ -4057,23 +4269,8 @@ void wxGridWindow::OnFocus(wxFocusEvent& event) event.Skip(); } -////////////////////////////////////////////////////////////////////// - -// Internal Helper function for computing row or column from some -// (unscrolled) coordinate value, using either -// m_defaultRowHeight/m_defaultColWidth or binary search on array -// of m_rowBottoms/m_ColRights to speed up the search! - -// Internal helper macros for simpler use of that function - -static int CoordToRowOrCol(int coord, int defaultDist, int minDist, - const wxArrayInt& BorderArray, int nMax, - bool clipToMinMax); - #define internalXToCol(x) XToCol(x, true) -#define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ - m_minAcceptableRowHeight, \ - m_rowBottoms, m_numRows, true) +#define internalYToRow(y) YToRow(y, true) ///////////////////////////////////////////////////////////////////// @@ -6258,124 +6455,106 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) } } -void wxGrid::DoEndDragResizeRow() +void wxGrid::DoEndDragResizeLine(const wxGridOperations& oper) { - if ( m_dragLastPos >= 0 ) - { - // erase the last line and resize the row - // - int cw, ch, left, dummy; - m_gridWin->GetClientSize( &cw, &ch ); - CalcUnscrolledPosition( 0, 0, &left, &dummy ); + if ( m_dragLastPos == -1 ) + return; - wxClientDC dc( m_gridWin ); - PrepareDC( dc ); - dc.SetLogicalFunction( wxINVERT ); - dc.DrawLine( left, m_dragLastPos, left + cw, m_dragLastPos ); - HideCellEditControl(); - SaveEditControlValue(); + const wxGridOperations& doper = oper.Dual(); - int rowTop = GetRowTop(m_dragRowOrCol); - SetRowSize( m_dragRowOrCol, - wxMax( m_dragLastPos - rowTop, m_minAcceptableRowHeight ) ); + const wxSize size = m_gridWin->GetClientSize(); - if ( !GetBatchCount() ) - { - // Only needed to get the correct rect.y: - wxRect rect ( CellToRect( m_dragRowOrCol, 0 ) ); - rect.x = 0; - CalcScrolledPosition(0, rect.y, &dummy, &rect.y); - rect.width = m_rowLabelWidth; - rect.height = ch - rect.y; - m_rowLabelWin->Refresh( true, &rect ); - rect.width = cw; + const wxPoint ptOrigin = CalcUnscrolledPosition(wxPoint(0, 0)); - // if there is a multicell block, paint all of it - if (m_table) - { - int i, cell_rows, cell_cols, subtract_rows = 0; - int leftCol = XToCol(left); - int rightCol = internalXToCol(left + cw); - if (leftCol >= 0) - { - for (i=leftCol; iRefresh( false, &rect ); - } + // erase the last line we drew + wxClientDC dc(m_gridWin); + PrepareDC(dc); + dc.SetLogicalFunction(wxINVERT); - ShowCellEditControl(); - } -} + const int posLineStart = oper.Select(ptOrigin); + const int posLineEnd = oper.Select(ptOrigin) + oper.Select(size); + oper.DrawParallelLine(dc, posLineStart, posLineEnd, m_dragLastPos); -void wxGrid::DoEndDragResizeCol() -{ - if ( m_dragLastPos >= 0 ) + // temporarily hide the edit control before resizing + HideCellEditControl(); + SaveEditControlValue(); + + // do resize the line + const int lineStart = oper.GetLineStartPos(this, m_dragRowOrCol); + oper.SetLineSize(this, m_dragRowOrCol, + wxMax(m_dragLastPos - lineStart, + oper.GetMinimalLineSize(this, m_dragRowOrCol))); + + // refresh now if we're not frozen + if ( !GetBatchCount() ) { - // erase the last line and resize the col - // - int cw, ch, dummy, top; - m_gridWin->GetClientSize( &cw, &ch ); - CalcUnscrolledPosition( 0, 0, &dummy, &top ); + // we need to refresh everything beyond the resized line in the header + // window - wxClientDC dc( m_gridWin ); - PrepareDC( dc ); - dc.SetLogicalFunction( wxINVERT ); - dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top + ch ); - HideCellEditControl(); - SaveEditControlValue(); + // get the position from which to refresh in the other direction + wxRect rect(CellToRect(oper.MakeCoords(m_dragRowOrCol, 0))); + rect.SetPosition(CalcScrolledPosition(rect.GetPosition())); - int colLeft = GetColLeft(m_dragRowOrCol); - SetColSize( m_dragRowOrCol, - wxMax( m_dragLastPos - colLeft, - GetColMinimalWidth(m_dragRowOrCol) ) ); + // we only need the ordinate (for rows) or abscissa (for columns) here, + // and need to cover the entire window in the other direction + oper.Select(rect) = 0; - if ( !GetBatchCount() ) + wxRect rectHeader(rect.GetPosition(), + oper.MakeSize + ( + oper.GetHeaderWindowSize(this), + doper.Select(size) - doper.Select(rect) + )); + + oper.GetHeaderWindow(this)->Refresh(true, &rectHeader); + + + // also refresh the grid window: extend the rectangle + if ( m_table ) { - // Only needed to get the correct rect.x: - wxRect rect ( CellToRect( 0, m_dragRowOrCol ) ); - rect.y = 0; - CalcScrolledPosition(rect.x, 0, &rect.x, &dummy); - rect.width = cw - rect.x; - rect.height = m_colLabelHeight; - m_colLabelWin->Refresh( true, &rect ); - rect.height = ch; + oper.SelectSize(rect) = oper.Select(size); - // if there is a multicell block, paint all of it - if (m_table) + int subtractLines = 0; + const int lineStart = oper.PosToLine(this, posLineStart); + if ( lineStart >= 0 ) { - int i, cell_rows, cell_cols, subtract_cols = 0; - int topRow = YToRow(top); - int bottomRow = internalYToRow(top + cw); - if (topRow >= 0) + // ensure that if we have a multi-cell block we redraw all of + // it by increasing the refresh area to cover it entirely if a + // part of it is affected + const int lineEnd = oper.PosToLine(this, posLineEnd, true); + for ( int line = lineStart; line < lineEnd; line++ ) { - for (i=topRow; iRefresh( false, &rect ); - } + int startPos = + oper.GetLineStartPos(this, m_dragRowOrCol + subtractLines); + startPos = doper.CalcScrolledPosition(this, startPos); + + doper.Select(rect) = startPos; + doper.SelectSize(rect) = doper.Select(size) - startPos; - ShowCellEditControl(); + m_gridWin->Refresh(false, &rect); + } } + + // show the edit control back again + ShowCellEditControl(); +} + +void wxGrid::DoEndDragResizeRow() +{ + DoEndDragResizeLine(wxGridRowOperations()); +} + +void wxGrid::DoEndDragResizeCol() +{ + DoEndDragResizeLine(wxGridColumnOperations()); } void wxGrid::DoEndDragMoveCol() @@ -8457,137 +8636,101 @@ void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords ) const } } -// Internal Helper function for computing row or column from some -// (unscrolled) coordinate value, using either -// m_defaultRowHeight/m_defaultColWidth or binary search on array -// of m_rowBottoms/m_ColRights to speed up the search! - -static int CoordToRowOrCol(int coord, int defaultDist, int minDist, - const wxArrayInt& BorderArray, int nMax, - bool clipToMinMax) +// compute row or column from some (unscrolled) coordinate value, using either +// 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 { - if (coord < 0) - return clipToMinMax && (nMax > 0) ? 0 : -1; + const int numLines = oper.GetNumberOfLines(this); - if (!defaultDist) - defaultDist = 1; + if ( coord < 0 ) + return clipToMinMax && numLines > 0 ? oper.GetLineAt(this, 0) : -1; - size_t i_max = coord / defaultDist, - i_min = 0; + const int defaultLineSize = oper.GetDefaultLineSize(this); + wxCHECK_MSG( defaultLineSize, -1, "can't have 0 default line size" ); - if (BorderArray.IsEmpty()) - { - if ((int) i_max < nMax) - return i_max; - return clipToMinMax ? nMax - 1 : -1; - } + int maxPos = coord / defaultLineSize, + minPos = 0; - if ( i_max >= BorderArray.GetCount()) - { - i_max = BorderArray.GetCount() - 1; - } - else + // check for the simplest case: if we have no explicit line sizes + // configured, then we already know the line this position falls in + const wxArrayInt& lineEnds = oper.GetLineEnds(this); + if ( lineEnds.empty() ) { - if ( coord >= BorderArray[i_max]) - { - i_min = i_max; - if (minDist) - i_max = coord / minDist; - else - i_max = BorderArray.GetCount() - 1; - } + if ( maxPos < numLines ) + return maxPos; - if ( i_max >= BorderArray.GetCount()) - i_max = BorderArray.GetCount() - 1; + return clipToMinMax ? numLines - 1 : -1; } - if ( coord >= BorderArray[i_max]) - return clipToMinMax ? (int)i_max : -1; - if ( coord < BorderArray[0] ) - return 0; - while ( i_max - i_min > 0 ) + // adjust maxPos before starting the binary search + if ( maxPos >= numLines ) { - wxCHECK_MSG(BorderArray[i_min] <= coord && coord < BorderArray[i_max], - 0, _T("wxGrid: internal error in CoordToRowOrCol")); - if (coord >= BorderArray[ i_max - 1]) - return i_max; - else - i_max--; - int median = i_min + (i_max - i_min + 1) / 2; - if (coord < BorderArray[median]) - i_max = median; - else - i_min = median; + maxPos = numLines - 1; } - - return i_max; -} - -int wxGrid::YToRow( int y ) const -{ - return CoordToRowOrCol(y, m_defaultRowHeight, - m_minAcceptableRowHeight, m_rowBottoms, m_numRows, false); -} - -int wxGrid::XToCol( int x, bool clipToMinMax ) const -{ - if (x < 0) - return clipToMinMax && (m_numCols > 0) ? GetColAt( 0 ) : -1; - - wxASSERT_MSG(m_defaultColWidth > 0, wxT("Default column width can not be zero")); - - int maxPos = x / m_defaultColWidth; - int minPos = 0; - - if (m_colRights.IsEmpty()) - { - if(maxPos < m_numCols) - return GetColAt( maxPos ); - return clipToMinMax ? GetColAt( m_numCols - 1 ) : -1; - } - - if ( maxPos >= m_numCols) - maxPos = m_numCols - 1; else { - if ( x >= m_colRights[GetColAt( maxPos )]) + if ( coord >= lineEnds[oper.GetLineAt(this, maxPos)]) { minPos = maxPos; - if (m_minAcceptableColWidth) - maxPos = x / m_minAcceptableColWidth; + const int minDist = oper.GetMinimalAcceptableLineSize(this); + if ( minDist ) + maxPos = coord / minDist; else - maxPos = m_numCols - 1; + maxPos = numLines - 1; } - if ( maxPos >= m_numCols) - maxPos = m_numCols - 1; + + if ( maxPos >= numLines ) + maxPos = numLines - 1; } - //X is beyond the last column - if ( x >= m_colRights[GetColAt( maxPos )]) - return clipToMinMax ? GetColAt( maxPos ) : -1; + // check if the position is beyond the last column + const int lineAtMaxPos = oper.GetLineAt(this, maxPos); + if ( coord >= lineEnds[lineAtMaxPos] ) + return clipToMinMax ? lineAtMaxPos : -1; - //X is before the first column - if ( x < m_colRights[GetColAt( 0 )] ) - return GetColAt( 0 ); + // or before the first one + const int lineAt0 = oper.GetLineAt(this, 0); + if ( coord < lineEnds[lineAt0] ) + return lineAt0; - //Perform a binary search - while ( maxPos - minPos > 0 ) + + // finally do perform the binary search + while ( minPos < maxPos ) { - wxCHECK_MSG(m_colRights[GetColAt( minPos )] <= x && x < m_colRights[GetColAt( maxPos )], - 0, _T("wxGrid: internal error in XToCol")); + wxCHECK_MSG( lineEnds[oper.GetLineAt(this, minPos)] <= coord && + coord < lineEnds[oper.GetLineAt(this, maxPos)], + -1, + "wxGrid: internal error in PosToLine()" ); - if (x >= m_colRights[GetColAt( maxPos - 1 )]) - return GetColAt( maxPos ); + if ( coord >= lineEnds[oper.GetLineAt(this, maxPos - 1)] ) + return oper.GetLineAt(this, maxPos); else maxPos--; - int median = minPos + (maxPos - minPos + 1) / 2; - if (x < m_colRights[GetColAt( median )]) + + const int median = minPos + (maxPos - minPos + 1) / 2; + if ( coord < lineEnds[oper.GetLineAt(this, median)] ) maxPos = median; else minPos = median; } - return GetColAt( maxPos ); + + return oper.GetLineAt(this, maxPos); +} + +int wxGrid::YToRow(int y, bool clipToMinMax) const +{ + return PosToLine(y, clipToMinMax, wxGridRowOperations()); +} + +int wxGrid::XToCol(int x, bool clipToMinMax) const +{ + return PosToLine(x, clipToMinMax, wxGridColumnOperations()); } // return the row number that that the y coord is near @@ -10779,46 +10922,40 @@ void wxGrid::SelectAll() // cell, row and col deselection // ---------------------------------------------------------------------------- -void wxGrid::DeselectRow( int row ) +void wxGrid::DeselectLine(int line, const wxGridOperations& oper) { if ( !m_selection ) return; - if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows ) + const wxGridSelectionModes mode = m_selection->GetSelectionMode(); + if ( mode == oper.GetSelectionMode() ) { - if ( m_selection->IsInSelection(row, 0 ) ) - m_selection->ToggleCellSelection(row, 0); + const wxGridCellCoords c(oper.MakeCoords(line, 0)); + if ( m_selection->IsInSelection(c) ) + m_selection->ToggleCellSelection(c); } - else + else if ( mode != oper.Dual().GetSelectionMode() ) { - int nCols = GetNumberCols(); - for ( int i = 0; i < nCols; i++ ) + const int nOther = oper.Dual().GetNumberOfLines(this); + for ( int i = 0; i < nOther; i++ ) { - if ( m_selection->IsInSelection(row, i ) ) - m_selection->ToggleCellSelection(row, i); + const wxGridCellCoords c(oper.MakeCoords(line, i)); + if ( m_selection->IsInSelection(c) ) + m_selection->ToggleCellSelection(c); } } + //else: can only select orthogonal lines so no lines in this direction + // could have been selected anyhow } -void wxGrid::DeselectCol( int col ) +void wxGrid::DeselectRow(int row) { - if ( !m_selection ) - return; + DeselectLine(row, wxGridRowOperations()); +} - if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns ) - { - if ( m_selection->IsInSelection(0, col ) ) - m_selection->ToggleCellSelection(0, col); - } - else - { - int nRows = GetNumberRows(); - for ( int i = 0; i < nRows; i++ ) - { - if ( m_selection->IsInSelection(i, col ) ) - m_selection->ToggleCellSelection(i, col); - } - } +void wxGrid::DeselectCol(int col) +{ + DeselectLine(col, wxGridColumnOperations()); } void wxGrid::DeselectCell( int row, int col )