Simplify wxGridSelectionRange to provide only iterators
This class was a strange hybrid of a container/view/range and iterator, as it both provided begin()/end() container-like methods and iterator-like methods for dereferencing/advancing. Simplify this by removing the latter part and making this class really just a range, with its own iterator class in order to avoid leaking the exact type of the iterator used in the API. Note that while it's now completely trivial, it is still useful as it isolates the application code from the vector used to store the selected blocks currently and will allow to change internal representation in the future without breaking the existing code.
This commit is contained in:
@@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
#include "wx/scrolwin.h"
|
#include "wx/scrolwin.h"
|
||||||
|
|
||||||
|
#if wxUSE_STD_CONTAINERS_COMPATIBLY
|
||||||
|
#include <iterator>
|
||||||
|
#endif
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// constants
|
// constants
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -869,40 +873,45 @@ struct wxGridBlockDiffResult
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGridSelectionRange: the range of grid selection blocks
|
// wxGridSelectionRange: a range of grid blocks that can be iterated over
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class wxGridSelectionRange
|
class wxGridSelectionRange
|
||||||
{
|
{
|
||||||
|
typedef wxVector<wxGridBlockCoords>::const_iterator iterator_impl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef wxVector<wxGridBlockCoords>::const_iterator iterator;
|
class iterator
|
||||||
|
|
||||||
wxGridSelectionRange() :
|
|
||||||
m_begin(),
|
|
||||||
m_end(),
|
|
||||||
m_it()
|
|
||||||
{
|
{
|
||||||
}
|
public:
|
||||||
|
#if wxUSE_STD_CONTAINERS_COMPATIBLY
|
||||||
|
typedef std::forward_iterator_tag iterator_category;
|
||||||
|
#endif
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef wxGridBlockCoords value_type;
|
||||||
|
typedef const value_type& reference;
|
||||||
|
|
||||||
// Get the current selection block coordinates.
|
iterator() : m_it() { }
|
||||||
const wxGridBlockCoords& GetBlockCoords() const
|
|
||||||
{
|
|
||||||
static wxGridBlockCoords empty;
|
|
||||||
return Valid() ? *m_it : empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate to the next block.
|
reference operator*() const { return *m_it; }
|
||||||
void Next()
|
|
||||||
{
|
|
||||||
if ( Valid() )
|
|
||||||
++m_it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whether the iterator is valid.
|
iterator& operator++()
|
||||||
bool Valid() const
|
{ ++m_it; return *this; }
|
||||||
{
|
iterator operator++(int)
|
||||||
return m_it != m_end;
|
{ iterator tmp = *this; ++m_it; return tmp; }
|
||||||
}
|
|
||||||
|
bool operator==(const iterator& it) const
|
||||||
|
{ return m_it == it.m_it; }
|
||||||
|
bool operator!=(const iterator& it) const
|
||||||
|
{ return m_it != it.m_it; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit iterator(iterator_impl it) : m_it(it) { }
|
||||||
|
|
||||||
|
iterator_impl m_it;
|
||||||
|
|
||||||
|
friend class wxGridSelectionRange;
|
||||||
|
};
|
||||||
|
|
||||||
iterator begin() const
|
iterator begin() const
|
||||||
{
|
{
|
||||||
@@ -915,16 +924,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxGridSelectionRange(iterator begin, iterator end) :
|
wxGridSelectionRange() :
|
||||||
|
m_begin(),
|
||||||
|
m_end()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wxGridSelectionRange(iterator_impl begin, iterator_impl end) :
|
||||||
m_begin(begin),
|
m_begin(begin),
|
||||||
m_end(end),
|
m_end(end)
|
||||||
m_it(begin)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const iterator m_begin;
|
const iterator m_begin;
|
||||||
const iterator m_end;
|
const iterator m_end;
|
||||||
iterator m_it;
|
|
||||||
|
|
||||||
friend class wxGrid;
|
friend class wxGrid;
|
||||||
};
|
};
|
||||||
|
@@ -2006,7 +2006,29 @@ struct wxGridBlockDiffResult
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The range of grid selection blocks.
|
Represents a range of grid blocks that can be iterated over.
|
||||||
|
|
||||||
|
This class provides read-only access to the blocks making up the grid
|
||||||
|
selection in the most general case.
|
||||||
|
|
||||||
|
Note that objects of this class can only be returned by wxGrid, but not
|
||||||
|
constructed in the application code.
|
||||||
|
|
||||||
|
The preferable way to iterate over it is using C++11 range-for loop:
|
||||||
|
@code
|
||||||
|
for ( const auto block: grid->GetSelectionRange() ) {
|
||||||
|
... do something with block ...
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
When not using C++11, iteration has to be done manually:
|
||||||
|
@code
|
||||||
|
wxGridSelectionRange range = grid->GetSelectionRange();
|
||||||
|
for ( wxGridSelectionRange::iterator it = range.begin();
|
||||||
|
it != range.end();
|
||||||
|
++it ) {
|
||||||
|
... do something with *it ...
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
@since 3.1.4
|
@since 3.1.4
|
||||||
*/
|
*/
|
||||||
@@ -2014,34 +2036,30 @@ class wxGridSelectionRange
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Default constructor initializes the iterator.
|
Read-only forward iterator type.
|
||||||
*/
|
|
||||||
wxGridSelectionRange();
|
|
||||||
|
|
||||||
/**
|
This is an opaque type, which satisfies the forward iterator
|
||||||
* Get the current selection block coordinates.
|
requirements, i.e. provides all the expected operations, such as
|
||||||
|
comparison, dereference and pre- and post-increment.
|
||||||
*/
|
*/
|
||||||
const wxGridBlockCoords& GetBlockCoords() const;
|
class iterator
|
||||||
|
{
|
||||||
|
iterator();
|
||||||
|
|
||||||
/**
|
const wxGridBlockCoords& operator*() const;
|
||||||
* Iterate to the next block.
|
|
||||||
*/
|
|
||||||
void Next();
|
|
||||||
|
|
||||||
/**
|
iterator& operator++();
|
||||||
* Whether the iterator is valid.
|
iterator operator++(int);
|
||||||
*/
|
|
||||||
bool Valid();
|
|
||||||
|
|
||||||
/**
|
bool operator==(const iterator& it) const;
|
||||||
* The function to allow using range-based for.
|
bool operator!=(const iterator& it) const;
|
||||||
*/
|
};
|
||||||
wxGridBlockCoords *begin() const;
|
|
||||||
|
|
||||||
/**
|
/// Return iterator corresponding to the beginning of the range.
|
||||||
* The function to allow using range-based for.
|
iterator begin() const;
|
||||||
*/
|
|
||||||
wxGridBlockCoords *end() const;
|
/// Return iterator corresponding to the end of the range.
|
||||||
|
iterator end() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4648,7 +4666,15 @@ public:
|
|||||||
void DeselectCell( int row, int col );
|
void DeselectCell( int row, int col );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns an range of grid selection blocks.
|
Returns a range of grid selection blocks.
|
||||||
|
|
||||||
|
The returned range can be iterated over, e.g. with C++11 range-for loop:
|
||||||
|
@code
|
||||||
|
for ( const auto block: grid->GetSelectionRange() ) {
|
||||||
|
if ( block.Intersects(myBlock) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
@since 3.1.4
|
@since 3.1.4
|
||||||
*/
|
*/
|
||||||
|
@@ -524,18 +524,16 @@ TEST_CASE_METHOD(GridTestCase, "Grid::Selection", "[grid]")
|
|||||||
CHECK(!m_grid->IsInSelection(3, 0));
|
CHECK(!m_grid->IsInSelection(3, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_METHOD(GridTestCase, "Grid::SelectionIterator", "[grid]")
|
TEST_CASE_METHOD(GridTestCase, "Grid::SelectionRange", "[grid]")
|
||||||
{
|
{
|
||||||
CHECK(!m_grid->GetSelectionRange().Valid());
|
const wxGridSelectionRange empty = m_grid->GetSelectionRange();
|
||||||
|
CHECK( empty.begin() == empty.end() );
|
||||||
|
|
||||||
m_grid->SelectBlock(1, 0, 3, 1);
|
m_grid->SelectBlock(1, 0, 3, 1);
|
||||||
|
|
||||||
wxGridSelectionRange sel = m_grid->GetSelectionRange();
|
wxGridSelectionRange sel = m_grid->GetSelectionRange();
|
||||||
CHECK(sel.Valid());
|
REQUIRE( sel.begin() != sel.end() );
|
||||||
CHECK(sel.GetBlockCoords() == wxGridBlockCoords(1, 0, 3, 1));
|
CHECK( *sel.begin() == wxGridBlockCoords(1, 0, 3, 1) );
|
||||||
|
|
||||||
sel.Next();
|
|
||||||
CHECK(!sel.Valid());
|
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || wxCHECK_VISUALC_VERSION(10)
|
#if __cplusplus >= 201103L || wxCHECK_VISUALC_VERSION(10)
|
||||||
m_grid->SelectBlock(4, 0, 7, 1, true);
|
m_grid->SelectBlock(4, 0, 7, 1, true);
|
||||||
|
Reference in New Issue
Block a user