X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0926b2fcc257c89b29c3c0d0981566037e0fc903..757cc9def70e4685054f4a24238e2df111f6c9fd:/src/generic/grid.cpp?ds=sidebyside diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index a5860c70d5..20389dfc48 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -185,7 +185,7 @@ private: DECLARE_EVENT_TABLE() }; -class WXDLLEXPORT wxGridWindow : public wxPanel +class WXDLLEXPORT wxGridWindow : public wxWindow { public: wxGridWindow() @@ -708,73 +708,7 @@ bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event) void wxGridCellTextEditor::StartingKey(wxKeyEvent& event) { - // we don't check for !HasModifiers() because IsAcceptedKey() did it - - // insert the key in the control - wxChar ch; - int keycode = event.GetKeyCode(); - switch ( keycode ) - { - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - ch = _T('0') + keycode - WXK_NUMPAD0; - break; - - case WXK_MULTIPLY: - case WXK_NUMPAD_MULTIPLY: - ch = _T('*'); - break; - - case WXK_ADD: - case WXK_NUMPAD_ADD: - ch = _T('+'); - break; - - case WXK_SUBTRACT: - case WXK_NUMPAD_SUBTRACT: - ch = _T('-'); - break; - - case WXK_DECIMAL: - case WXK_NUMPAD_DECIMAL: - ch = _T('.'); - break; - - case WXK_DIVIDE: - case WXK_NUMPAD_DIVIDE: - ch = _T('/'); - break; - - default: - if ( keycode < 256 && keycode >= 0 && isprint(keycode) ) - { - // FIXME this is not going to work for non letters... - if ( !event.ShiftDown() ) - { - keycode = tolower(keycode); - } - - ch = (wxChar)keycode; - } - else - { - ch = _T('\0'); - } - } - - if ( ch ) - { - Text()->AppendText(ch); - } - else + if ( !Text()->EmulateKeyPress(event) ) { event.Skip(); } @@ -3486,9 +3420,9 @@ void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent& event ) ////////////////////////////////////////////////////////////////////// -IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxPanel ) +IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxWindow ) -BEGIN_EVENT_TABLE( wxGridWindow, wxPanel ) +BEGIN_EVENT_TABLE( wxGridWindow, wxWindow ) EVT_PAINT( wxGridWindow::OnPaint ) EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel) EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent ) @@ -3501,7 +3435,7 @@ wxGridWindow::wxGridWindow( wxGrid *parent, wxGridRowLabelWindow *rowLblWin, wxGridColLabelWindow *colLblWin, wxWindowID id, const wxPoint &pos, const wxSize &size ) - : wxPanel( parent, id, pos, size, wxWANTS_CHARS, "grid window" ) + : wxWindow( parent, id, pos, size, wxWANTS_CHARS, "grid window" ) { m_owner = parent; m_rowLabelWin = rowLblWin; @@ -3532,7 +3466,7 @@ void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect ) { - wxPanel::ScrollWindow( dx, dy, rect ); + wxWindow::ScrollWindow( dx, dy, rect ); m_rowLabelWin->ScrollWindow( 0, dy, rect ); m_colLabelWin->ScrollWindow( dx, 0, rect ); } @@ -3568,6 +3502,23 @@ void wxGridWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) ) ////////////////////////////////////////////////////////////////////// +// 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, bool maxOnOverflow); + +#define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \ + WXGRID_MIN_COL_WIDTH, \ + m_colRights, TRUE) +#define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \ + WXGRID_MIN_ROW_HEIGHT, \ + m_rowBottoms, TRUE) +///////////////////////////////////////////////////////////////////// IMPLEMENT_DYNAMIC_CLASS( wxGrid, wxScrolledWindow ) @@ -3629,16 +3580,17 @@ void wxGrid::Create() m_cellEditCtrlEnabled = FALSE; - m_defaultCellAttr = new wxGridCellAttr(m_defaultCellAttr); + m_defaultCellAttr = new wxGridCellAttr(); // Set default cell attributes + m_defaultCellAttr->SetDefAttr(m_defaultCellAttr); m_defaultCellAttr->SetKind(wxGridCellAttr::Default); m_defaultCellAttr->SetFont(GetFont()); m_defaultCellAttr->SetAlignment(wxALIGN_LEFT, wxALIGN_TOP); m_defaultCellAttr->SetTextColour( - wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT)); + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); m_defaultCellAttr->SetBackgroundColour( - wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); m_defaultCellAttr->SetRenderer(new wxGridCellStringRenderer); m_defaultCellAttr->SetEditor(new wxGridCellTextEditor); @@ -3652,7 +3604,8 @@ void wxGrid::Create() // create the type registry m_typeRegistry = new wxGridTypeRegistry; - m_selection = 0; + m_selection = NULL; + // subwindow components that make up the wxGrid m_cornerLabelWin = new wxGridCornerLabelWindow( this, -1, @@ -3718,9 +3671,9 @@ bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership, if ( m_created ) { // RD: Actually, this should probably be allowed. I think it would be - // nice to be able to switch multiple Tables in and out of a single - // View at runtime. Is there anything in the implmentation that would - // prevent this? + // nice to be able to switch multiple Tables in and out of a single + // View at runtime. Is there anything in the implementation that + // would prevent this? // At least, you now have to cope with m_selection wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") ); @@ -3810,8 +3763,8 @@ void wxGrid::Init() m_selectingTopLeft = wxGridNoCellCoords; m_selectingBottomRight = wxGridNoCellCoords; - m_selectionBackground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT); - m_selectionForeground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); + m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); m_editable = TRUE; // default for whole grid @@ -3819,7 +3772,7 @@ void wxGrid::Init() m_batchCount = 0; m_extraWidth = - m_extraHeight = 50; + m_extraHeight = 0; } // ---------------------------------------------------------------------------- @@ -3904,9 +3857,9 @@ void wxGrid::CalcDimensions() int cw, ch; GetClientSize( &cw, &ch ); - if ( m_colLabelWin->IsShown() ) - cw -= m_rowLabelWidth; if ( m_rowLabelWin->IsShown() ) + cw -= m_rowLabelWidth; + if ( m_colLabelWin->IsShown() ) ch -= m_colLabelHeight; // grid total size @@ -3944,6 +3897,10 @@ void wxGrid::CalcDimensions() SetScrollbars( GRID_SCROLL_LINE_X, GRID_SCROLL_LINE_Y, GetScrollX(w), GetScrollY(h), x, y, GetBatchCount() != 0); + + // if our OnSize() hadn't been called (it would if we have scrollbars), we + // still must reposition the children + CalcWindowSizes(); } @@ -4021,7 +3978,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg ) // SetCurrentCell( 0, 0 ); } - m_selection->UpdateRows( pos, numRows ); + + if ( m_selection ) + m_selection->UpdateRows( pos, numRows ); wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider(); if (attrProvider) attrProvider->UpdateAttrRows( pos, numRows ); @@ -4104,7 +4063,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg ) if ( m_currentCellCoords.GetRow() >= m_numRows ) m_currentCellCoords.Set( 0, 0 ); } - m_selection->UpdateRows( pos, -((int)numRows) ); + + if ( m_selection ) + m_selection->UpdateRows( pos, -((int)numRows) ); wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider(); if (attrProvider) { attrProvider->UpdateAttrRows( pos, -((int)numRows) ); @@ -4158,7 +4119,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg ) // SetCurrentCell( 0, 0 ); } - m_selection->UpdateCols( pos, numCols ); + + if ( m_selection ) + m_selection->UpdateCols( pos, numCols ); wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider(); if (attrProvider) attrProvider->UpdateAttrCols( pos, numCols ); @@ -4240,7 +4203,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg ) if ( m_currentCellCoords.GetCol() >= m_numCols ) m_currentCellCoords.Set( 0, 0 ); } - m_selection->UpdateCols( pos, -((int)numCols) ); + + if ( m_selection ) + m_selection->UpdateCols( pos, -((int)numCols) ); wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider(); if (attrProvider) { attrProvider->UpdateAttrCols( pos, -((int)numCols) ); @@ -4304,7 +4269,7 @@ wxArrayInt wxGrid::CalcRowLabelsExposed( const wxRegion& reg ) // find the row labels within these bounds // int row; - for ( row = 0; row < m_numRows; row++ ) + for ( row = internalYToRow(top); row < m_numRows; row++ ) { if ( GetRowBottom(row) < top ) continue; @@ -4355,7 +4320,7 @@ wxArrayInt wxGrid::CalcColLabelsExposed( const wxRegion& reg ) // find the cells within these bounds // int col; - for ( col = 0; col < m_numCols; col++ ) + for ( col = internalXToCol(left); col < m_numCols; col++ ) { if ( GetColRight(col) < left ) continue; @@ -4406,7 +4371,7 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg ) // find the cells within these bounds // int row, col; - for ( row = 0; row < m_numRows; row++ ) + for ( row = internalYToRow(top); row < m_numRows; row++ ) { if ( GetRowBottom(row) <= top ) continue; @@ -4414,8 +4379,7 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg ) if ( GetRowTop(row) > bottom ) break; - - for ( col = 0; col < m_numCols; col++ ) + for ( col = internalXToCol(left); col < m_numCols; col++ ) { if ( GetColRight(col) <= left ) continue; @@ -4442,7 +4406,11 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) if ( event.Dragging() ) { - m_isDragging = TRUE; + if (!m_isDragging) + { + m_isDragging = TRUE; + m_rowLabelWin->CaptureMouse(); + } if ( event.LeftIsDown() ) { @@ -4472,11 +4440,14 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) case WXGRID_CURSOR_SELECT_ROW: if ( (row = YToRow( y )) >= 0 ) { - m_selection->SelectRow( row, - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + if ( m_selection ) + { + m_selection->SelectRow( row, + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } } // default label to suppress warnings about "enumeration value @@ -4488,8 +4459,14 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) return; } - m_isDragging = FALSE; + if ( m_isDragging && (event.Entering() || event.Leaving()) ) + return; + if (m_isDragging) + { + if (m_rowLabelWin->HasCapture()) m_rowLabelWin->ReleaseMouse(); + m_isDragging = FALSE; + } // ------------ Entering or leaving the window // @@ -4515,21 +4492,29 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) { if ( !event.ShiftDown() && !event.ControlDown() ) ClearSelection(); - if ( event.ShiftDown() ) - m_selection->SelectBlock( m_currentCellCoords.GetRow(), - 0, - row, - GetNumberCols() - 1, - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); - else - m_selection->SelectRow( row, - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + else if ( m_selection ) + { + if ( event.ShiftDown() ) + { + m_selection->SelectBlock( m_currentCellCoords.GetRow(), + 0, + row, + GetNumberCols() - 1, + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } + else + { + m_selection->SelectRow( row, + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } + } + ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW, m_rowLabelWin); } } @@ -4628,7 +4613,11 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) if ( event.Dragging() ) { - m_isDragging = TRUE; + if (!m_isDragging) + { + m_isDragging = TRUE; + m_colLabelWin->CaptureMouse(); + } if ( event.LeftIsDown() ) { @@ -4658,11 +4647,14 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) case WXGRID_CURSOR_SELECT_COL: if ( (col = XToCol( x )) >= 0 ) { - m_selection->SelectCol( col, - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + if ( m_selection ) + { + m_selection->SelectCol( col, + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } } // default label to suppress warnings about "enumeration value @@ -4674,8 +4666,14 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) return; } - m_isDragging = FALSE; + if ( m_isDragging && (event.Entering() || event.Leaving()) ) + return; + if (m_isDragging) + { + if (m_colLabelWin->HasCapture()) m_colLabelWin->ReleaseMouse(); + m_isDragging = FALSE; + } // ------------ Entering or leaving the window // @@ -4701,20 +4699,28 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) { if ( !event.ShiftDown() && !event.ControlDown() ) ClearSelection(); - if ( event.ShiftDown() ) - m_selection->SelectBlock( 0, - m_currentCellCoords.GetCol(), - GetNumberRows() - 1, col, - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); - else - m_selection->SelectCol( col, - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + if ( m_selection ) + { + if ( event.ShiftDown() ) + { + m_selection->SelectBlock( 0, + m_currentCellCoords.GetCol(), + GetNumberRows() - 1, col, + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } + else + { + m_selection->SelectCol( col, + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } + } + ChangeCursorMode(WXGRID_CURSOR_SELECT_COL, m_colLabelWin); } } @@ -4875,7 +4881,7 @@ void wxGrid::ChangeCursorMode(CursorMode mode, if ( m_winCapture ) { - m_winCapture->ReleaseMouse(); + if (m_winCapture->HasCapture()) m_winCapture->ReleaseMouse(); m_winCapture = (wxWindow *)NULL; } @@ -5046,14 +5052,17 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) ClearSelection(); if ( event.ShiftDown() ) { - m_selection->SelectBlock( m_currentCellCoords.GetRow(), - m_currentCellCoords.GetCol(), - coords.GetRow(), - coords.GetCol(), - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + if ( m_selection ) + { + m_selection->SelectBlock( m_currentCellCoords.GetRow(), + m_currentCellCoords.GetCol(), + coords.GetRow(), + coords.GetCol(), + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } } else if ( XToEdgeOfCol(x) < 0 && YToEdgeOfRow(y) < 0 ) @@ -5083,12 +5092,15 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) { if ( event.ControlDown() ) { - m_selection->ToggleCellSelection( coords.GetRow(), - coords.GetCol(), - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + if ( m_selection ) + { + m_selection->ToggleCellSelection( coords.GetRow(), + coords.GetCol(), + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } m_selectingTopLeft = wxGridNoCellCoords; m_selectingBottomRight = wxGridNoCellCoords; m_selectingKeyboard = coords; @@ -5096,9 +5108,14 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) else { SetCurrentCell( coords ); - if ( m_selection->GetSelectionMode() - != wxGrid::wxGridSelectCells) - HighlightBlock( coords, coords ); + if ( m_selection ) + { + if ( m_selection->GetSelectionMode() != + wxGrid::wxGridSelectCells ) + { + HighlightBlock( coords, coords ); + } + } } m_waitForSlowClick = TRUE; } @@ -5134,17 +5151,22 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) { if (m_winCapture) { - m_winCapture->ReleaseMouse(); + if (m_winCapture->HasCapture()) m_winCapture->ReleaseMouse(); m_winCapture = NULL; } - m_selection->SelectBlock( m_selectingTopLeft.GetRow(), - m_selectingTopLeft.GetCol(), - m_selectingBottomRight.GetRow(), - m_selectingBottomRight.GetCol(), - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + + if ( m_selection ) + { + m_selection->SelectBlock( m_selectingTopLeft.GetRow(), + m_selectingTopLeft.GetCol(), + m_selectingBottomRight.GetRow(), + m_selectingBottomRight.GetCol(), + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } + m_selectingTopLeft = wxGridNoCellCoords; m_selectingBottomRight = wxGridNoCellCoords; } @@ -5800,12 +5822,15 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) case WXK_SPACE: if ( event.ControlDown() ) { - m_selection->ToggleCellSelection( m_currentCellCoords.GetRow(), - m_currentCellCoords.GetCol(), - event.ControlDown(), - event.ShiftDown(), - event.AltDown(), - event.MetaDown() ); + if ( m_selection ) + { + m_selection->ToggleCellSelection( m_currentCellCoords.GetRow(), + m_currentCellCoords.GetCol(), + event.ControlDown(), + event.ShiftDown(), + event.AltDown(), + event.MetaDown() ); + } break; } if ( !IsEditable() ) @@ -5831,7 +5856,14 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) || editor->IsAcceptedKey(event) ) { EnableCellEditControl(); - editor->StartingKey(event); + + // the editor could be not shown for a variety of + // reasons (i.e. blocked by the app or whatever), so + // check if it really was created + if ( m_cellEditCtrlEnabled ) + { + editor->StartingKey(event); + } } else { @@ -5862,14 +5894,20 @@ void wxGrid::OnKeyUp( wxKeyEvent& event ) { if ( m_selectingTopLeft != wxGridNoCellCoords && m_selectingBottomRight != wxGridNoCellCoords ) - m_selection->SelectBlock( m_selectingTopLeft.GetRow(), - m_selectingTopLeft.GetCol(), - m_selectingBottomRight.GetRow(), - m_selectingBottomRight.GetCol(), - event.ControlDown(), - TRUE, - event.AltDown(), - event.MetaDown() ); + { + if ( m_selection ) + { + m_selection->SelectBlock( m_selectingTopLeft.GetRow(), + m_selectingTopLeft.GetCol(), + m_selectingBottomRight.GetRow(), + m_selectingBottomRight.GetCol(), + event.ControlDown(), + TRUE, + event.AltDown(), + event.MetaDown() ); + } + } + m_selectingTopLeft = wxGridNoCellCoords; m_selectingBottomRight = wxGridNoCellCoords; m_selectingKeyboard = wxGridNoCellCoords; @@ -5931,16 +5969,20 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo int temp; wxGridCellCoords updateTopLeft, updateBottomRight; - if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows ) + if ( m_selection ) { - leftCol = 0; - rightCol = GetNumberCols() - 1; - } - else if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns ) - { - topRow = 0; - bottomRow = GetNumberRows() - 1; + if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows ) + { + leftCol = 0; + rightCol = GetNumberCols() - 1; + } + else if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns ) + { + topRow = 0; + bottomRow = GetNumberRows() - 1; + } } + if ( topRow > bottomRow ) { temp = topRow; @@ -6348,7 +6390,7 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) // horizontal grid lines // int i; - for ( i = 0; i < m_numRows; i++ ) + for ( i = internalYToRow(top); i < m_numRows; i++ ) { int bot = GetRowBottom(i) - 1; @@ -6366,7 +6408,7 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) ) // vertical grid lines // - for ( i = 0; i < m_numCols; i++ ) + for ( i = internalXToCol(left); i < m_numCols; i++ ) { int colRight = GetColRight(i) - 1; if ( colRight > right ) @@ -6779,8 +6821,13 @@ void wxGrid::ShowCellEditControl() #endif // 0 // cell is shifted by one pixel - rect.x--; - rect.y--; + // However, don't allow x or y to become negative + // since the SetSize() method interprets that as + // "don't change." + if (rect.x > 0) + rect.x--; + if (rect.y > 0) + rect.y--; wxGridCellAttr* attr = GetCellAttr(row, col); wxGridCellEditor* editor = attr->GetEditor(this, row, col); @@ -6883,31 +6930,68 @@ void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords ) } -int wxGrid::YToRow( int y ) +// 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, bool maxOnOverflow) { - int i; + if (!defaultDist) + defaultDist = 1; + size_t i_max = coord / defaultDist, + i_min = 0; + if (BorderArray.IsEmpty()) + { + return i_max; + } - for ( i = 0; i < m_numRows; i++ ) + if ( i_max >= BorderArray.GetCount()) + i_max = BorderArray.GetCount() - 1; + else { - if ( y < GetRowBottom(i) ) - return i; + if ( coord >= BorderArray[i_max]) + { + i_min = i_max; + i_max = coord / minDist; + } + if ( i_max >= BorderArray.GetCount()) + i_max = BorderArray.GetCount() - 1; } + if ( coord >= BorderArray[i_max]) + return maxOnOverflow ? (int)i_max : -1; + if ( coord < BorderArray[0] ) + return 0; - return -1; + while ( i_max - i_min > 0 ) + { + 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; + } + return i_max; } - -int wxGrid::XToCol( int x ) +int wxGrid::YToRow( int y ) { - int i; + return CoordToRowOrCol(y, m_defaultRowHeight, + WXGRID_MIN_ROW_HEIGHT, m_rowBottoms, FALSE); +} - for ( i = 0; i < m_numCols; i++ ) - { - if ( x < GetColRight(i) ) - return i; - } - return -1; +int wxGrid::XToCol( int x ) +{ + return CoordToRowOrCol(x, m_defaultColWidth, + WXGRID_MIN_COL_WIDTH, m_colRights, FALSE); } @@ -6916,16 +7000,17 @@ int wxGrid::XToCol( int x ) // int wxGrid::YToEdgeOfRow( int y ) { - int i, d; + int i; + i = internalYToRow(y); - for ( i = 0; i < m_numRows; i++ ) + if ( GetRowHeight(i) > WXGRID_LABEL_EDGE_ZONE ) { - if ( GetRowHeight(i) > WXGRID_LABEL_EDGE_ZONE ) - { - d = abs( y - GetRowBottom(i) ); - if ( d < WXGRID_LABEL_EDGE_ZONE ) - return i; - } + // We know that we are in row i, test whether we are + // close enough to lower or upper border, respectively. + if ( abs(GetRowBottom(i) - y) < WXGRID_LABEL_EDGE_ZONE ) + return i; + else if( i > 0 && y - GetRowTop(i) < WXGRID_LABEL_EDGE_ZONE ) + return i - 1; } return -1; @@ -6937,16 +7022,17 @@ int wxGrid::YToEdgeOfRow( int y ) // int wxGrid::XToEdgeOfCol( int x ) { - int i, d; + int i; + i = internalXToCol(x); - for ( i = 0; i < m_numCols; i++ ) + if ( GetColWidth(i) > WXGRID_LABEL_EDGE_ZONE ) { - if ( GetColWidth(i) > WXGRID_LABEL_EDGE_ZONE ) - { - d = abs( x - GetColRight(i) ); - if ( d < WXGRID_LABEL_EDGE_ZONE ) - return i; - } + // We know that we are in column i, test whether we are + // close enough to right or left border, respectively. + if ( abs(GetColRight(i) - x) < WXGRID_LABEL_EDGE_ZONE ) + return i; + else if( i > 0 && x - GetColLeft(i) < WXGRID_LABEL_EDGE_ZONE ) + return i - 1; } return -1; @@ -8349,7 +8435,12 @@ void wxGrid::SetDefaultRowSize( int height, bool resizeExistingRows ) if ( resizeExistingRows ) { - InitRowHeights(); + // since we are resizing all rows to the default row size, + // we can simply clear the row heights and row bottoms + // arrays (which also allows us to take advantage of + // some speed optimisations) + m_rowHeights.Empty(); + m_rowBottoms.Empty(); if ( !GetBatchCount() ) CalcDimensions(); } @@ -8384,7 +8475,12 @@ void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols ) if ( resizeExistingCols ) { - InitColWidths(); + // since we are resizing all columns to the default column size, + // we can simply clear the col widths and col rights + // arrays (which also allows us to take advantage of + // some speed optimisations) + m_colWidths.Empty(); + m_colRights.Empty(); if ( !GetBatchCount() ) CalcDimensions(); } @@ -8725,7 +8821,8 @@ void wxGrid::SelectRow( int row, bool addToSelected ) if ( IsSelection() && !addToSelected ) ClearSelection(); - m_selection->SelectRow( row, FALSE, addToSelected ); + if ( m_selection ) + m_selection->SelectRow( row, FALSE, addToSelected ); } @@ -8734,7 +8831,8 @@ void wxGrid::SelectCol( int col, bool addToSelected ) if ( IsSelection() && !addToSelected ) ClearSelection(); - m_selection->SelectCol( col, FALSE, addToSelected ); + if ( m_selection ) + m_selection->SelectCol( col, FALSE, addToSelected ); } @@ -8744,15 +8842,19 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol, if ( IsSelection() && !addToSelected ) ClearSelection(); - m_selection->SelectBlock( topRow, leftCol, bottomRow, rightCol, - FALSE, addToSelected ); + if ( m_selection ) + m_selection->SelectBlock( topRow, leftCol, bottomRow, rightCol, + FALSE, addToSelected ); } void wxGrid::SelectAll() { if ( m_numRows > 0 && m_numCols > 0 ) - m_selection->SelectBlock( 0, 0, m_numRows-1, m_numCols-1 ); + { + if ( m_selection ) + m_selection->SelectBlock( 0, 0, m_numRows-1, m_numCols-1 ); + } } // @@ -8761,6 +8863,9 @@ void wxGrid::SelectAll() void wxGrid::DeselectRow( int row ) { + if ( !m_selection ) + return; + if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows ) { if ( m_selection->IsInSelection(row, 0 ) ) @@ -8779,6 +8884,9 @@ void wxGrid::DeselectRow( int row ) void wxGrid::DeselectCol( int col ) { + if ( !m_selection ) + return; + if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns ) { if ( m_selection->IsInSelection(0, col ) ) @@ -8797,31 +8905,32 @@ void wxGrid::DeselectCol( int col ) void wxGrid::DeselectCell( int row, int col ) { - if ( m_selection->IsInSelection(row, col) ) + if ( m_selection && m_selection->IsInSelection(row, col) ) m_selection->ToggleCellSelection(row, col); } bool wxGrid::IsSelection() { - return ( m_selection->IsSelection() || + return ( m_selection && (m_selection->IsSelection() || ( m_selectingTopLeft != wxGridNoCellCoords && - m_selectingBottomRight != wxGridNoCellCoords ) ); + m_selectingBottomRight != wxGridNoCellCoords) ) ); } bool wxGrid::IsInSelection( int row, int col ) { - return ( m_selection->IsInSelection( row, col ) || + return ( m_selection && (m_selection->IsInSelection( row, col ) || ( row >= m_selectingTopLeft.GetRow() && col >= m_selectingTopLeft.GetCol() && row <= m_selectingBottomRight.GetRow() && - col <= m_selectingBottomRight.GetCol() ) ); + col <= m_selectingBottomRight.GetCol() )) ); } void wxGrid::ClearSelection() { m_selectingTopLeft = wxGridNoCellCoords; m_selectingBottomRight = wxGridNoCellCoords; - m_selection->ClearSelection(); + if ( m_selection ) + m_selection->ClearSelection(); }