diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index df5b0c69b1..adb1e7b345 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -868,6 +868,66 @@ struct wxGridBlockDiffResult wxGridBlockCoords m_parts[4]; }; +// ---------------------------------------------------------------------------- +// wxGridSelectionRange: the range of grid selection blocks +// ---------------------------------------------------------------------------- + +class wxGridSelectionRange +{ +public: + typedef wxGridBlockCoords* iterator; + + wxGridSelectionRange() : + m_begin(NULL), + m_end(NULL), + m_it(NULL) + { + } + + // Get the current selection block coordinates. + const wxGridBlockCoords& GetBlockCoords() const + { + static wxGridBlockCoords empty; + return Valid() ? *m_it : empty; + } + + // Iterate to the next block. + void Next() + { + if ( Valid() ) + ++m_it; + } + + // Whether the iterator is valid. + bool Valid() const + { + return m_it != m_end; + } + + iterator begin() const + { + return m_begin; + } + + iterator end() const + { + return m_end; + } + +private: + wxGridSelectionRange(iterator begin, iterator end) : + m_begin(begin), + m_end(end), + m_it(begin) + { + } + + const iterator m_begin; + const iterator m_end; + iterator m_it; + + friend class wxGrid; +}; // For comparisons... // @@ -1918,6 +1978,7 @@ public: bool IsInSelection( const wxGridCellCoords& coords ) const { return IsInSelection( coords.GetRow(), coords.GetCol() ); } + wxGridSelectionRange GetSelectionRange() const; wxGridCellCoordsArray GetSelectedCells() const; wxGridCellCoordsArray GetSelectionBlockTopLeft() const; wxGridCellCoordsArray GetSelectionBlockBottomRight() const; diff --git a/include/wx/generic/gridsel.h b/include/wx/generic/gridsel.h index c5e5df7812..5d57e5e447 100644 --- a/include/wx/generic/gridsel.h +++ b/include/wx/generic/gridsel.h @@ -89,6 +89,8 @@ public: wxArrayInt GetRowSelection() const; wxArrayInt GetColSelection() const; + wxVectorGridBlockCoords& GetBlocks() { return m_selection; } + private: int BlockContain( int topRow1, int leftCol1, int bottomRow1, int rightCol1, diff --git a/interface/wx/grid.h b/interface/wx/grid.h index 52c966122b..dc17b2b9ae 100644 --- a/interface/wx/grid.h +++ b/interface/wx/grid.h @@ -2005,6 +2005,45 @@ struct wxGridBlockDiffResult wxGridBlockCoords m_parts[4]; }; +/** + The range of grid selection blocks. + + @since 3.1.4 + */ +class wxGridSelectionRange +{ +public: + /** + Default constructor initializes the iterator. + */ + wxGridSelectionRange(); + + /** + * Get the current selection block coordinates. + */ + const wxGridBlockCoords& GetBlockCoords() const; + + /** + * Iterate to the next block. + */ + void Next(); + + /** + * Whether the iterator is valid. + */ + bool Valid(); + + /** + * The function to allow using range-based for. + */ + wxGridBlockCoords *begin() const; + + /** + * The function to allow using range-based for. + */ + wxGridBlockCoords *end() const; +}; + /** @class wxGridTableBase @@ -4608,6 +4647,13 @@ public: */ void DeselectCell( int row, int col ); + /** + Returns an range of grid selection blocks. + + @since 3.1.4 + */ + wxGridSelectionRange GetSelectionRange() const; + /** Returns an array of individually selected cells. @@ -4623,6 +4669,9 @@ public: a grid with a million of columns, we don't want to create an array with a million of entries in this function, instead it returns an empty array and GetSelectedCols() returns an array containing one element). + + The function can be slow for the big grids, use GetSelectionRange() + in the new code. */ wxGridCellCoordsArray GetSelectedCells() const; @@ -4634,6 +4683,9 @@ public: individually selected but not those being part of the block selection or being selected in virtue of all of their cells being selected individually, please see GetSelectedCells() for more details. + + The function can be slow for the big grids, use GetSelectionRange() + in the new code. */ wxArrayInt GetSelectedCols() const; @@ -4645,6 +4697,9 @@ public: selected but not those being part of the block selection or being selected in virtue of all of their cells being selected individually, please see GetSelectedCells() for more details. + + The function can be slow for the big grids, use GetSelectionRange() + in the new code. */ wxArrayInt GetSelectedRows() const; @@ -4660,6 +4715,9 @@ public: Please see GetSelectedCells() for more information about the selection representation in wxGrid. + The function can be slow for the big grids, use GetSelectionRange() + in the new code. + @see GetSelectionBlockTopLeft() */ wxGridCellCoordsArray GetSelectionBlockBottomRight() const; @@ -4670,6 +4728,9 @@ public: Please see GetSelectedCells() for more information about the selection representation in wxGrid. + The function can be slow for the big grids, use GetSelectionRange() + in the new code. + @see GetSelectionBlockBottomRight() */ wxGridCellCoordsArray GetSelectionBlockTopLeft() const; diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 19c0bc4c2c..f24c68499e 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -10231,6 +10231,15 @@ bool wxGrid::IsInSelection( int row, int col ) const return m_selection && m_selection->IsInSelection(row, col); } +wxGridSelectionRange wxGrid::GetSelectionRange() const +{ + if ( !m_selection ) + return wxGridSelectionRange(); + + wxVectorGridBlockCoords& blocks = m_selection->GetBlocks(); + return wxGridSelectionRange(blocks.begin(), blocks.end()); +} + wxGridCellCoordsArray wxGrid::GetSelectedCells() const { if (!m_selection) diff --git a/tests/controls/gridtest.cpp b/tests/controls/gridtest.cpp index 6e57e1bc18..5159c12e50 100644 --- a/tests/controls/gridtest.cpp +++ b/tests/controls/gridtest.cpp @@ -524,6 +524,41 @@ TEST_CASE_METHOD(GridTestCase, "Grid::Selection", "[grid]") CHECK(!m_grid->IsInSelection(3, 0)); } +TEST_CASE_METHOD(GridTestCase, "Grid::SelectionIterator", "[grid]") +{ + CHECK(!m_grid->GetSelectionRange().Valid()); + + m_grid->SelectBlock(1, 0, 3, 1); + + wxGridSelectionRange sel = m_grid->GetSelectionRange(); + CHECK(sel.Valid()); + CHECK(sel.GetBlockCoords() == wxGridBlockCoords(1, 0, 3, 1)); + + sel.Next(); + CHECK(!sel.Valid()); + +#if __cplusplus >= 201103L || wxCHECK_VISUALC_VERSION(10) + m_grid->SelectBlock(4, 0, 7, 1, true); + int index = 0; + for ( const wxGridBlockCoords& block : m_grid->GetSelectionRange() ) + { + switch ( index ) + { + case 0: + CHECK(block == wxGridBlockCoords(1, 0, 3, 1)); + break; + case 1: + CHECK(block == wxGridBlockCoords(4, 0, 7, 1)); + break; + default: + FAIL("Unexpected iterations count"); + break; + } + ++index; + } +#endif +} + TEST_CASE_METHOD(GridTestCase, "Grid::SelectEmptyGrid", "[grid]") { for ( int i = 0; i < 2; ++i )