From d455c5b99e99705e816ddcebc23d33320c93895e Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Tue, 28 Jan 2020 23:40:21 +0700 Subject: [PATCH 1/8] Fix making the wrong wxGrid cell visible when selecting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should make visible the cell of the corner of the current selected block. Also fix names of the wxGrid::UpdateBlockBeingSelected parameters because actually passed сщщквы are of any opposite selection block corners. --- include/wx/generic/grid.h | 12 ++++++------ src/generic/grid.cpp | 14 ++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-) 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 c1dbb96548..97a493056e 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -5822,11 +5822,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 +5869,6 @@ wxGrid::UpdateBlockBeingSelected(int topRow, int leftCol, } } - EnsureFirstLessThanSecond(topRow, bottomRow); - EnsureFirstLessThanSecond(leftCol, rightCol); - wxGridCellCoords updateTopLeft = wxGridCellCoords(topRow, leftCol), updateBottomRight = wxGridCellCoords(bottomRow, rightCol); From bf5be68510dc827ef18b1f1ecd95998b8ce2f0a8 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Tue, 28 Jan 2020 23:53:26 +0700 Subject: [PATCH 2/8] Test wxGrid scrolling when selecting cells. --- tests/controls/gridtest.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/controls/gridtest.cpp b/tests/controls/gridtest.cpp index f38c0c48bf..e9489adde4 100644 --- a/tests/controls/gridtest.cpp +++ b/tests/controls/gridtest.cpp @@ -73,6 +73,7 @@ private: WXUISIM_TEST( RangeSelect ); CPPUNIT_TEST( Cursor ); CPPUNIT_TEST( Selection ); + CPPUNIT_TEST( ScrollWhenSelect ); CPPUNIT_TEST( AddRowCol ); CPPUNIT_TEST( DeleteAndAddRowCol ); CPPUNIT_TEST( ColumnOrder ); @@ -114,6 +115,7 @@ private: void RangeSelect(); void Cursor(); void Selection(); + void ScrollWhenSelect(); void AddRowCol(); void DeleteAndAddRowCol(); void ColumnOrder(); @@ -594,6 +596,30 @@ 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::AddRowCol() { CPPUNIT_ASSERT_EQUAL(10, m_grid->GetNumberRows()); From 68ccc77e2041f9149a3e6e4c5b85b76aa7bccefa Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Tue, 28 Jan 2020 01:37:12 +0700 Subject: [PATCH 3/8] Fix wxGrid Home and End keys handling Take into account that rows and columns may be hidden and columns also can be reordered. --- src/generic/grid.cpp | 62 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 97a493056e..b48715d05d 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -5563,15 +5563,65 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) break; case WXK_HOME: - GoToCell(event.ControlDown() ? 0 - : m_currentCellCoords.GetRow(), - 0); + { + if ( m_currentCellCoords == wxGridNoCellCoords ) + break; + + int row = m_currentCellCoords.GetRow(); + if ( event.ControlDown() ) + { + row = 0; + + // Find visible row. + for ( ; row < m_numRows; ++row ) + { + if ( IsRowShown(row) ) + break; + } + } + + int col = 0; + // Find visible column. + for ( ; col < m_numCols; ++col ) + { + if ( IsColShown(GetColAt(col)) ) + break; + } + + ClearSelection(); + GoToCell(row, GetColAt(col)); + } break; case WXK_END: - GoToCell(event.ControlDown() ? m_numRows - 1 - : m_currentCellCoords.GetRow(), - m_numCols - 1); + { + if ( m_currentCellCoords == wxGridNoCellCoords ) + break; + + int row = m_currentCellCoords.GetRow(); + if ( event.ControlDown() ) + { + row = m_numRows - 1; + + // Find visible row. + for ( ; row >= 0; --row ) + { + if ( IsRowShown(row) ) + break; + } + } + + int col = m_numCols - 1; + // Find visible column. + for ( ; col >= 0; --col ) + { + if ( IsColShown(GetColAt(col)) ) + break; + } + + ClearSelection(); + GoToCell(row, GetColAt(col)); + } break; case WXK_PAGEUP: From 677b9d21ea41dcacfe7856a43fac1a1e888b5e05 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Wed, 29 Jan 2020 01:31:40 +0700 Subject: [PATCH 4/8] Test moving the grid cursor using End key for wxGrid --- tests/controls/gridtest.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/controls/gridtest.cpp b/tests/controls/gridtest.cpp index e9489adde4..80dfee0285 100644 --- a/tests/controls/gridtest.cpp +++ b/tests/controls/gridtest.cpp @@ -74,6 +74,7 @@ private: CPPUNIT_TEST( Cursor ); CPPUNIT_TEST( Selection ); CPPUNIT_TEST( ScrollWhenSelect ); + WXUISIM_TEST( MoveGridCursorUsingEndKey ); CPPUNIT_TEST( AddRowCol ); CPPUNIT_TEST( DeleteAndAddRowCol ); CPPUNIT_TEST( ColumnOrder ); @@ -116,6 +117,7 @@ private: void Cursor(); void Selection(); void ScrollWhenSelect(); + void MoveGridCursorUsingEndKey(); void AddRowCol(); void DeleteAndAddRowCol(); void ColumnOrder(); @@ -620,6 +622,36 @@ void GridTestCase::ScrollWhenSelect() 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::AddRowCol() { CPPUNIT_ASSERT_EQUAL(10, m_grid->GetNumberRows()); From 6e6eb799c88c1f6dd07636a032510c8e3f06d8b6 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Tue, 28 Jan 2020 02:42:27 +0700 Subject: [PATCH 5/8] Implement wxGrid cells selection for Home and End keys Select cells if Shift is pressed when handling Home and End keys --- src/generic/grid.cpp | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index b48715d05d..4fbe07fb69 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -5567,7 +5567,10 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) if ( m_currentCellCoords == wxGridNoCellCoords ) break; - int row = m_currentCellCoords.GetRow(); + const bool useSelectedBlockCorner = + event.ShiftDown() && m_selectedBlockCorner != wxGridNoCellCoords; + int row = useSelectedBlockCorner ? m_selectedBlockCorner.GetRow() + : m_currentCellCoords.GetRow(); if ( event.ControlDown() ) { row = 0; @@ -5588,8 +5591,17 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) break; } - ClearSelection(); - GoToCell(row, GetColAt(col)); + if ( event.ShiftDown() ) + { + UpdateBlockBeingSelected(m_currentCellCoords, + wxGridCellCoords(row, col)); + MakeCellVisible(row, col); + } + else + { + ClearSelection(); + GoToCell(row, GetColAt(col)); + } } break; @@ -5598,7 +5610,10 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) if ( m_currentCellCoords == wxGridNoCellCoords ) break; - int row = m_currentCellCoords.GetRow(); + const bool useSelectedBlockCorner = + event.ShiftDown() && m_selectedBlockCorner != wxGridNoCellCoords; + int row = useSelectedBlockCorner ? m_selectedBlockCorner.GetRow() + : m_currentCellCoords.GetRow(); if ( event.ControlDown() ) { row = m_numRows - 1; @@ -5619,8 +5634,17 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) break; } - ClearSelection(); - GoToCell(row, GetColAt(col)); + if ( event.ShiftDown() ) + { + UpdateBlockBeingSelected(m_currentCellCoords, + wxGridCellCoords(row, col)); + MakeCellVisible(row, col); + } + else + { + ClearSelection(); + GoToCell(row, GetColAt(col)); + } } break; From 7fa9416fb461668875720693d1f15c52f16f9d47 Mon Sep 17 00:00:00 2001 From: Ilya Sinitsyn Date: Wed, 29 Jan 2020 01:49:51 +0700 Subject: [PATCH 6/8] Test wxGrid cells selection using End key --- tests/controls/gridtest.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/controls/gridtest.cpp b/tests/controls/gridtest.cpp index 80dfee0285..6d88a72d3c 100644 --- a/tests/controls/gridtest.cpp +++ b/tests/controls/gridtest.cpp @@ -75,6 +75,7 @@ private: CPPUNIT_TEST( Selection ); CPPUNIT_TEST( ScrollWhenSelect ); WXUISIM_TEST( MoveGridCursorUsingEndKey ); + WXUISIM_TEST( SelectUsingEndKey ); CPPUNIT_TEST( AddRowCol ); CPPUNIT_TEST( DeleteAndAddRowCol ); CPPUNIT_TEST( ColumnOrder ); @@ -118,6 +119,7 @@ private: void Selection(); void ScrollWhenSelect(); void MoveGridCursorUsingEndKey(); + void SelectUsingEndKey(); void AddRowCol(); void DeleteAndAddRowCol(); void ColumnOrder(); @@ -652,6 +654,38 @@ void GridTestCase::MoveGridCursorUsingEndKey() #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()); From c7707a16c7f854514268940695ccca44ef52e02f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 1 Feb 2020 01:57:04 +0100 Subject: [PATCH 7/8] Simplify check for current cell in Home/End handling code Prefer to just test whether we have it instead of breaking out of the case if we don't, this is slightly more straightforward. No real changes. --- src/generic/grid.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 4fbe07fb69..19359643e7 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -5563,10 +5563,8 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) break; case WXK_HOME: + if ( m_currentCellCoords != wxGridNoCellCoords ) { - if ( m_currentCellCoords == wxGridNoCellCoords ) - break; - const bool useSelectedBlockCorner = event.ShiftDown() && m_selectedBlockCorner != wxGridNoCellCoords; int row = useSelectedBlockCorner ? m_selectedBlockCorner.GetRow() @@ -5606,10 +5604,8 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) break; case WXK_END: + if ( m_currentCellCoords != wxGridNoCellCoords ) { - if ( m_currentCellCoords == wxGridNoCellCoords ) - break; - const bool useSelectedBlockCorner = event.ShiftDown() && m_selectedBlockCorner != wxGridNoCellCoords; int row = useSelectedBlockCorner ? m_selectedBlockCorner.GetRow() From 5b797618a1a5d11fd2934a5e96987e20d8c7c151 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 1 Feb 2020 02:23:05 +0100 Subject: [PATCH 8/8] Merge WXK_HOME and WXK_END handling in a single case There are more commonalities than differences between the handling of these 2 keys and it's better to have a single version of this code. No changes in behaviour. --- src/generic/grid.cpp | 105 +++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 55 deletions(-) diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 19359643e7..570f8a776c 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -5563,71 +5563,66 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) break; case WXK_HOME: - if ( m_currentCellCoords != wxGridNoCellCoords ) - { - const bool useSelectedBlockCorner = - event.ShiftDown() && m_selectedBlockCorner != wxGridNoCellCoords; - int row = useSelectedBlockCorner ? m_selectedBlockCorner.GetRow() - : m_currentCellCoords.GetRow(); - if ( event.ControlDown() ) - { - row = 0; - - // Find visible row. - for ( ; row < m_numRows; ++row ) - { - if ( IsRowShown(row) ) - break; - } - } - - int col = 0; - // Find visible column. - for ( ; col < m_numCols; ++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_END: if ( m_currentCellCoords != wxGridNoCellCoords ) { - const bool useSelectedBlockCorner = - event.ShiftDown() && m_selectedBlockCorner != wxGridNoCellCoords; - int row = useSelectedBlockCorner ? m_selectedBlockCorner.GetRow() - : m_currentCellCoords.GetRow(); + 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() ) { - row = m_numRows - 1; - - // Find visible row. - for ( ; row >= 0; --row ) + if ( goToBeginning ) { - if ( IsRowShown(row) ) - break; + 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(); } } - int col = m_numCols - 1; - // Find visible column. - for ( ; col >= 0; --col ) + // Also find the last or first visible column in any case. + int col; + if ( goToBeginning ) { - if ( IsColShown(GetColAt(col)) ) - break; + 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() )