diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index d4e403e8eb..d753161100 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -2325,13 +2325,13 @@ protected: // this function is called to extend the block being currently selected // from mouse and keyboard event handlers - void UpdateBlockBeingSelected(int topRow, int leftCol, - int bottomRow, int rightCol); + void UpdateBlockBeingSelected(int blockStartRow, int blockStartCol, + int blockEndRow, int blockEndCol); - void UpdateBlockBeingSelected(const wxGridCellCoords& topLeft, - const wxGridCellCoords& bottomRight) - { UpdateBlockBeingSelected(topLeft.GetRow(), topLeft.GetCol(), - bottomRight.GetRow(), bottomRight.GetCol()); } + void UpdateBlockBeingSelected(const wxGridCellCoords& blockStart, + const wxGridCellCoords& blockEnd) + { UpdateBlockBeingSelected(blockStart.GetRow(), blockStart.GetCol(), + blockEnd.GetRow(), blockEnd.GetCol()); } virtual bool ShouldScrollToChildOnFocus(wxWindow* WXUNUSED(win)) wxOVERRIDE { return false; } diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 047c6f95f2..5ba42b6937 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -5563,15 +5563,80 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) break; case WXK_HOME: - GoToCell(event.ControlDown() ? 0 - : m_currentCellCoords.GetRow(), - 0); - break; - case WXK_END: - GoToCell(event.ControlDown() ? m_numRows - 1 - : m_currentCellCoords.GetRow(), - m_numCols - 1); + if ( m_currentCellCoords != wxGridNoCellCoords ) + { + const bool goToBeginning = event.GetKeyCode() == WXK_HOME; + + // Find the first or last visible row if we need to go to it + // (without Control, we keep the current row). + int row; + if ( event.ControlDown() ) + { + if ( goToBeginning ) + { + for ( row = 0; row < m_numRows; ++row ) + { + if ( IsRowShown(row) ) + break; + } + } + else + { + for ( row = m_numRows - 1; row >= 0; --row ) + { + if ( IsRowShown(row) ) + break; + } + } + } + else + { + // If we're selecting, continue in the same row, which + // may well be different from the one in which we + // started selecting. + if ( event.ShiftDown() && + m_selectedBlockCorner != wxGridNoCellCoords ) + { + row = m_selectedBlockCorner.GetRow(); + } + else // Just use the current row. + { + row = m_currentCellCoords.GetRow(); + } + } + + // Also find the last or first visible column in any case. + int col; + if ( goToBeginning ) + { + for ( col = 0; col < m_numCols; ++col ) + { + if ( IsColShown(GetColAt(col)) ) + break; + } + } + else + { + for ( col = m_numCols - 1; col >= 0; --col ) + { + if ( IsColShown(GetColAt(col)) ) + break; + } + } + + if ( event.ShiftDown() ) + { + UpdateBlockBeingSelected(m_currentCellCoords, + wxGridCellCoords(row, col)); + MakeCellVisible(row, col); + } + else + { + ClearSelection(); + GoToCell(row, GetColAt(col)); + } + } break; case WXK_PAGEUP: @@ -5822,11 +5887,16 @@ bool wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) } void -wxGrid::UpdateBlockBeingSelected(int topRow, int leftCol, - int bottomRow, int rightCol) +wxGrid::UpdateBlockBeingSelected(int blockStartRow, int blockStartCol, + int blockEndRow, int blockEndCol) { + m_selectedBlockCorner = wxGridCellCoords(blockEndRow, blockEndCol); MakeCellVisible(m_selectedBlockCorner); - m_selectedBlockCorner = wxGridCellCoords(bottomRow, rightCol); + + int topRow = wxMin(blockStartRow, blockEndRow); + int leftCol = wxMin(blockStartCol, blockEndCol); + int bottomRow = wxMax(blockStartRow, blockEndRow); + int rightCol = wxMax(blockStartCol, blockEndCol); if ( m_selection ) { @@ -5864,9 +5934,6 @@ wxGrid::UpdateBlockBeingSelected(int topRow, int leftCol, } } - EnsureFirstLessThanSecond(topRow, bottomRow); - EnsureFirstLessThanSecond(leftCol, rightCol); - wxGridCellCoords updateTopLeft = wxGridCellCoords(topRow, leftCol), updateBottomRight = wxGridCellCoords(bottomRow, rightCol); diff --git a/tests/controls/gridtest.cpp b/tests/controls/gridtest.cpp index f38c0c48bf..6d88a72d3c 100644 --- a/tests/controls/gridtest.cpp +++ b/tests/controls/gridtest.cpp @@ -73,6 +73,9 @@ private: WXUISIM_TEST( RangeSelect ); CPPUNIT_TEST( Cursor ); CPPUNIT_TEST( Selection ); + CPPUNIT_TEST( ScrollWhenSelect ); + WXUISIM_TEST( MoveGridCursorUsingEndKey ); + WXUISIM_TEST( SelectUsingEndKey ); CPPUNIT_TEST( AddRowCol ); CPPUNIT_TEST( DeleteAndAddRowCol ); CPPUNIT_TEST( ColumnOrder ); @@ -114,6 +117,9 @@ private: void RangeSelect(); void Cursor(); void Selection(); + void ScrollWhenSelect(); + void MoveGridCursorUsingEndKey(); + void SelectUsingEndKey(); void AddRowCol(); void DeleteAndAddRowCol(); void ColumnOrder(); @@ -594,6 +600,92 @@ void GridTestCase::Selection() CPPUNIT_ASSERT(!m_grid->IsInSelection(3, 0)); } +void GridTestCase::ScrollWhenSelect() +{ + m_grid->AppendCols(10); + + REQUIRE( m_grid->GetGridCursorCol() == 0 ); + REQUIRE( m_grid->GetGridCursorRow() == 0 ); + REQUIRE( m_grid->IsVisible(0, 0) ); + REQUIRE( !m_grid->IsVisible(0, 4) ); + + for ( int i = 0; i < 4; ++i ) + { + m_grid->MoveCursorRight(true); + } + CHECK( m_grid->IsVisible(0, 4) ); + + m_grid->ClearSelection(); + m_grid->SetGridCursor(1, 1); + for ( int i = 0; i < 5; ++i ) + { + m_grid->MoveCursorDown(true); + } + CHECK( m_grid->IsVisible(6, 1) ); +} + +void GridTestCase::MoveGridCursorUsingEndKey() +{ +#if wxUSE_UIACTIONSIMULATOR + wxUIActionSimulator sim; + + m_grid->AppendCols(10); + + REQUIRE( m_grid->GetGridCursorCol() == 0 ); + REQUIRE( m_grid->GetGridCursorRow() == 0 ); + REQUIRE( m_grid->IsVisible(0, 0) ); + + // Hide the last row. + m_grid->HideRow(9); + // Hide the last column. + m_grid->HideCol(11); + // Move the penult column. + m_grid->SetColPos(10, 5); + + m_grid->SetFocus(); + + sim.KeyDown(WXK_END, wxMOD_CONTROL); + sim.KeyUp(WXK_END, wxMOD_CONTROL); + wxYield(); + + CHECK( m_grid->GetGridCursorRow() == 8 ); + CHECK( m_grid->GetGridCursorCol() == 9 ); + CHECK( m_grid->IsVisible(8, 9) ); +#endif +} + +void GridTestCase::SelectUsingEndKey() +{ +#if wxUSE_UIACTIONSIMULATOR + wxUIActionSimulator sim; + + m_grid->AppendCols(10); + + REQUIRE( m_grid->GetGridCursorCol() == 0 ); + REQUIRE( m_grid->GetGridCursorRow() == 0 ); + REQUIRE( m_grid->IsVisible(0, 0) ); + + m_grid->SetFocus(); + + sim.KeyDown(WXK_END, wxMOD_CONTROL | wxMOD_SHIFT); + sim.KeyUp(WXK_END, wxMOD_CONTROL | wxMOD_SHIFT); + wxYield(); + + wxGridCellCoordsArray topleft = m_grid->GetSelectionBlockTopLeft(); + wxGridCellCoordsArray bottomright = m_grid->GetSelectionBlockBottomRight(); + + CHECK( topleft.Count() == 1 ); + CHECK( bottomright.Count() == 1 ); + + CHECK( topleft.Item(0).GetCol() == 0 ); + CHECK( topleft.Item(0).GetRow() == 0 ); + CHECK( bottomright.Item(0).GetCol() == 11 ); + CHECK( bottomright.Item(0).GetRow() == 9 ); + + CHECK( m_grid->IsVisible(8, 9) ); +#endif +} + void GridTestCase::AddRowCol() { CPPUNIT_ASSERT_EQUAL(10, m_grid->GetNumberRows());