Merge branch 'dvc-getitemrect'

Make wxDataViewCtrl::GetIremRect() work under all platforms and improve
tests, documentation and fix a couple of other problems in the same code
area.

See https://github.com/wxWidgets/wxWidgets/pull/1015
This commit is contained in:
Vadim Zeitlin
2018-11-10 22:38:05 +01:00
10 changed files with 323 additions and 137 deletions

View File

@@ -149,6 +149,7 @@ wxGTK:
- Fix the build with glib < 2.32 (e.g. CentOS 6).
- Fix field widths in wxStatusBar showing a size grip.
- Fill column value in wxEVT_DATAVIEW_ITEM_ACTIVATED events.
- Implement wxDataViewCtrl::GetItemRect() (MrMeesek).
wxMSW:

View File

@@ -1446,8 +1446,14 @@ public:
int GetIndent() const;
/**
Returns item rectangle. Coordinates of the rectangle are specified in
wxDataViewCtrl client area coordinates.
Returns item rectangle.
If item is not currently visible, either because its parent is
collapsed or it is outside of the visible part of the control due to
the current vertical scrollbar position, return an empty rectangle.
Coordinates of the rectangle are specified in wxDataViewCtrl client
area coordinates.
@param item
A valid item.
@@ -1455,10 +1461,6 @@ public:
If non-@NULL, the rectangle returned corresponds to the
intersection of the item with the specified column. If @NULL, the
rectangle spans all the columns.
@note This method is currently not implemented at all in wxGTK and only
implemented for non-@NULL @a col argument in wxOSX. It is fully
implemented in the generic version of the control.
*/
virtual wxRect GetItemRect(const wxDataViewItem& item,
const wxDataViewColumn* col = NULL) const;
@@ -1556,6 +1558,9 @@ public:
/**
Return @true if the item is expanded.
@note When using the native macOS version this method has a bug which
may result in returning @true even for items without children.
*/
virtual bool IsExpanded(const wxDataViewItem& item) const;

View File

@@ -3468,55 +3468,53 @@ int wxDataViewMainWindow::GetLineHeight( unsigned int row ) const
class RowToTreeNodeJob: public DoJob
{
public:
RowToTreeNodeJob( unsigned int row_ , int current_, wxDataViewTreeNode * node )
// Note that we initialize m_current to -1 because the first node passed to
// our operator() will be the root node, which doesn't appear in the window
// and so doesn't count as a real row.
explicit RowToTreeNodeJob(int row)
: m_row(row), m_current(-1), m_ret(NULL)
{
this->row = row_;
this->current = current_;
ret = NULL;
parent = node;
}
virtual int operator() ( wxDataViewTreeNode * node ) wxOVERRIDE
{
current ++;
if( current == static_cast<int>(row))
if( m_current == m_row)
{
ret = node;
m_ret = node;
return DoJob::DONE;
}
if( node->GetSubTreeCount() + current < static_cast<int>(row) )
if( node->GetSubTreeCount() + m_current < m_row )
{
current += node->GetSubTreeCount();
m_current += node->GetSubTreeCount() + 1;
return DoJob::SKIP_SUBTREE;
}
else
{
parent = node;
// If the current node has only leaf children, we can find the
// desired node directly. This can speed up finding the node
// in some cases, and will have a very good effect for list views.
if ( node->HasChildren() &&
(int)node->GetChildNodes().size() == node->GetSubTreeCount() )
{
const int index = static_cast<int>(row) - current - 1;
ret = node->GetChildNodes()[index];
const int index = m_row - m_current - 1;
m_ret = node->GetChildNodes()[index];
return DoJob::DONE;
}
m_current++;
return DoJob::CONTINUE;
}
}
wxDataViewTreeNode * GetResult() const
{ return ret; }
{ return m_ret; }
private:
unsigned int row;
int current;
wxDataViewTreeNode * ret;
wxDataViewTreeNode * parent;
const int m_row;
int m_current;
wxDataViewTreeNode* m_ret;
};
wxDataViewTreeNode * wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row) const
@@ -3526,7 +3524,7 @@ wxDataViewTreeNode * wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row) co
if ( row == (unsigned)-1 )
return NULL;
RowToTreeNodeJob job( row , -2, m_root );
RowToTreeNodeJob job(static_cast<int>(row));
Walker( m_root , job );
return job.GetResult();
}
@@ -3815,10 +3813,16 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item,
xpos = 0;
}
const int row = GetRowByItem(item);
if ( row == -1 )
{
// This means the row is currently not visible at all.
return wxRect();
}
// we have to take an expander column into account and compute its indentation
// to get the correct x position where the actual text is
int indent = 0;
int row = GetRowByItem(item);
if (!IsList() &&
(column == 0 || GetExpanderColumnOrFirstOne(GetOwner()) == column) )
{
@@ -3835,6 +3839,14 @@ wxRect wxDataViewMainWindow::GetItemRect( const wxDataViewItem & item,
GetOwner()->CalcScrolledPosition( itemRect.x, itemRect.y,
&itemRect.x, &itemRect.y );
// Check if the rectangle is completely outside of the currently visible
// area and, if so, return an empty rectangle to indicate that the item is
// not visible.
if ( itemRect.GetBottom() < 0 || itemRect.GetTop() > GetClientSize().y )
{
return wxRect();
}
return itemRect;
}
@@ -3856,43 +3868,49 @@ int wxDataViewMainWindow::RecalculateCount() const
class ItemToRowJob : public DoJob
{
public:
ItemToRowJob(const wxDataViewItem& item_, wxVector<wxDataViewItem>::reverse_iterator iter)
: m_iter(iter),
item(item_)
// As with RowToTreeNodeJob above, we initialize m_current to -1 because
// the first node passed to our operator() is the root node which is not
// visible on screen and so we should return 0 for its first child node and
// not for the root itself.
ItemToRowJob(const wxDataViewItem& item, wxVector<wxDataViewItem>::reverse_iterator iter)
: m_item(item), m_iter(iter), m_current(-1)
{
ret = -1;
}
// Maybe binary search will help to speed up this process
virtual int operator() ( wxDataViewTreeNode * node) wxOVERRIDE
{
ret ++;
if( node->GetItem() == item )
if( node->GetItem() == m_item )
{
return DoJob::DONE;
}
// Is this node the next (grand)parent of the item we're looking for?
if( node->GetItem() == *m_iter )
{
// Search for the next (grand)parent now and skip this item itself.
++m_iter;
++m_current;
return DoJob::CONTINUE;
}
else
{
ret += node->GetSubTreeCount();
// Skip this node and all its currently visible children.
m_current += node->GetSubTreeCount() + 1;
return DoJob::SKIP_SUBTREE;
}
}
// the row number is begin from zero
int GetResult() const
{ return ret -1; }
{ return m_current; }
private:
const wxDataViewItem m_item;
wxVector<wxDataViewItem>::reverse_iterator m_iter;
wxDataViewItem item;
int ret;
// The row corresponding to the last node seen in our operator().
int m_current;
};
@@ -3926,7 +3944,9 @@ int wxDataViewMainWindow::GetRowByItem(const wxDataViewItem & item) const
// the parent chain was created by adding the deepest parent first.
// so if we want to start at the root node, we have to iterate backwards through the vector
ItemToRowJob job( item, parentChain.rbegin() );
Walker( m_root, job );
if ( !Walker( m_root, job ) )
return -1;
return job.GetResult();
}
}
@@ -5841,8 +5861,11 @@ wxRect wxDataViewCtrl::GetItemRect( const wxDataViewItem & item,
// Convert position from the main window coordinates to the control coordinates.
// (They can be different due to the presence of the header.).
wxRect r = m_clientArea->GetItemRect(item, column);
const wxPoint ctrlPos = ScreenToClient(m_clientArea->ClientToScreen(r.GetPosition()));
r.SetPosition(ctrlPos);
if ( r.width || r.height )
{
const wxPoint ctrlPos = ScreenToClient(m_clientArea->ClientToScreen(r.GetPosition()));
r.SetPosition(ctrlPos);
}
return r;
}

View File

@@ -5289,10 +5289,71 @@ void wxDataViewCtrl::HitTest(const wxPoint& point,
}
wxRect
wxDataViewCtrl::GetItemRect(const wxDataViewItem& WXUNUSED(item),
const wxDataViewColumn *WXUNUSED(column)) const
wxDataViewCtrl::GetItemRect(const wxDataViewItem& item,
const wxDataViewColumn *column) const
{
return wxRect();
if ( !item )
return wxRect();
GtkTreeViewColumn *gcolumn = NULL ;
if (column)
gcolumn = GTK_TREE_VIEW_COLUMN(column->GetGtkHandle());
GtkTreeIter iter;
iter.user_data = item.GetID();
wxGtkTreePath path(m_internal->get_path( &iter ));
GdkRectangle item_rect;
gtk_tree_view_get_cell_area(GTK_TREE_VIEW(m_treeview), path, gcolumn, &item_rect);
// GTK returns rectangles with the position and height, but not width, for
// some reason, set to 0 if the item is not currently shown, so an explicit
// check is needed as this rectangle is not quite the empty rectangle we're
// supposed to return in this case.
if ( item_rect.height == 0 )
return wxRect();
// If column is NULL we compute the combined width of all the columns
if ( !column )
{
unsigned int cols = GetColumnCount();
int width = 0;
for (unsigned int i = 0; i < cols; ++i)
{
wxDataViewColumn * col = GetColumn(i);
if ( !col->IsHidden() )
width += col->GetWidth();
}
item_rect.width = width;
}
// We need to convert logical coordinates to physical ones, i.e. the
// rectangle of the topmost item should start at ~0, even if it's a 100th
// item shown on top only because the window is scrolled.
#if GTK_CHECK_VERSION(2, 12, 0)
if ( wx_is_at_least_gtk2(12) )
{
gtk_tree_view_convert_bin_window_to_widget_coords
(
GTK_TREE_VIEW(m_treeview),
item_rect.x, item_rect.y,
&item_rect.x, &item_rect.y
);
if ( item_rect.y > GetClientSize().y ||
item_rect.y + item_rect.height < 0 )
{
// If it turns out that the item is not visible at all, indicate it
// by returning an empty rectangle for it.
return wxRect();
}
}
//else: There doesn't seem to be anything reasonable to do here, so we'll
// just return wrong values with the very old GTK+ versions if the
// window is scrolled.
#endif // GTK+ 2.12+
return wxRectFromGDKRect(&item_rect);
}
bool wxDataViewCtrl::SetRowHeight(int rowHeight)

View File

@@ -2295,8 +2295,33 @@ wxDataViewItem wxCocoaDataViewControl::GetTopItem() const
wxRect wxCocoaDataViewControl::GetRectangle(const wxDataViewItem& item, const wxDataViewColumn *columnPtr)
{
return wxFromNSRect([m_osxView superview],[m_OutlineView frameOfCellAtColumn:GetColumnPosition(columnPtr)
NSView* const parent = [m_osxView superview];
wxRect r = wxFromNSRect(parent, [m_OutlineView frameOfCellAtColumn:GetColumnPosition(columnPtr)
row:[m_OutlineView rowForItem:[m_DataSource getDataViewItemFromBuffer:item]]]);
// For hidden items, i.e. items not shown because their parent is
// collapsed, the native method returns rectangles with negative width, but
// we're supposed to just return an empty rectangle in this case. To be on
// the safe side, also check for the height as well, even if it seems to be
// always 0 in this case.
if ( r.width < 0 || r.height < 0 )
return wxRect();
// Also adjust the vertical coordinates to use physical window coordinates
// instead of the logical ones returned by frameOfCellAtColumn:row:
NSScrollView* const scrollView = [m_OutlineView enclosingScrollView];
const wxRect
visible = wxFromNSRect(parent, scrollView.contentView.visibleRect);
// We are also supposed to return empty rectangle if the item is not
// visible because it is scrolled out of view.
if ( r.GetBottom() < visible.GetTop() || r.GetTop() > visible.GetBottom() )
return wxRect();
r.y -= visible.y;
return r;
}
bool wxCocoaDataViewControl::IsExpanded(const wxDataViewItem& item) const

View File

@@ -547,10 +547,24 @@ wxDataViewColumn *wxDataViewCtrl::GetCurrentColumn() const
wxRect wxDataViewCtrl::GetItemRect(wxDataViewItem const& item, wxDataViewColumn const* columnPtr) const
{
if (item.IsOk() && (columnPtr != NULL))
return GetDataViewPeer()->GetRectangle(item,columnPtr);
else
return wxRect();
if ( !item.IsOk() )
return wxRect();
wxRect rect = GetDataViewPeer()->GetRectangle(item, columnPtr ? columnPtr : GetColumn(0));
if ( !columnPtr )
{
const unsigned columnCount = GetColumnCount();
if ( columnCount != 1 )
{
// Extend the rectangle to the rightmost part of the last column.
const wxRect rectLastCol = GetDataViewPeer()->GetRectangle(item, GetColumn(columnCount - 1));
rect.SetRight(rectLastCol.GetRight());
}
//else: We already have the rectangle we need.
}
return rect;
}
int wxDataViewCtrl::GetSelectedItemsCount() const

View File

@@ -67,3 +67,11 @@ std::ostream& operator<<(std::ostream& os, const wxPoint& p)
return os;
}
std::ostream& operator<<(std::ostream& os, const wxRect& r)
{
os << "{"
<< r.x << ", " << r.y << " " << r.width << "*" << r.height
<< "}";
return os;
}

View File

@@ -29,16 +29,12 @@ namespace wxTestPrivate
std::ostream& operator<<(std::ostream& os, const ColourChannel& cc);
} // wxTestPrivate namespace
// this operator is needed to use CPPUNIT_ASSERT_EQUAL with wxColour objects
// Operators used to show the values of the corresponding types when comparing
// them in the unit tests fails.
std::ostream& operator<<(std::ostream& os, const wxColour& c);
// this operator is needed to use CPPUNIT_ASSERT_EQUAL with wxSize objects
std::ostream& operator<<(std::ostream& os, const wxSize& s);
// this operator is needed to use CPPUNIT_ASSERT_EQUAL with wxFont objects
std::ostream& operator<<(std::ostream& os, const wxFont& f);
// this operator is needed to use CPPUNIT_ASSERT_EQUAL with wxPoint objects
std::ostream& operator<<(std::ostream& os, const wxPoint& p);
std::ostream& operator<<(std::ostream& os, const wxRect& r);
#endif

View File

@@ -22,35 +22,19 @@
#include "wx/dataview.h"
#include "testableframe.h"
#include "asserthelper.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class DataViewCtrlTestCase : public CppUnit::TestCase
class DataViewCtrlTestCase
{
public:
DataViewCtrlTestCase() { }
virtual void setUp() wxOVERRIDE;
virtual void tearDown() wxOVERRIDE;
private:
CPPUNIT_TEST_SUITE( DataViewCtrlTestCase );
CPPUNIT_TEST( DeleteSelected );
CPPUNIT_TEST( DeleteNotSelected );
CPPUNIT_TEST( GetSelectionForMulti );
CPPUNIT_TEST( GetSelectionForSingle );
CPPUNIT_TEST_SUITE_END();
// Create wxDataViewTreeCtrl with the given style.
void Create(long style);
void DeleteSelected();
void DeleteNotSelected();
void GetSelectionForMulti();
void GetSelectionForSingle();
explicit DataViewCtrlTestCase(long style);
~DataViewCtrlTestCase();
protected:
void TestSelectionFor0and1();
// the dataview control itself
@@ -65,17 +49,29 @@ private:
wxDECLARE_NO_COPY_CLASS(DataViewCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( DataViewCtrlTestCase );
class SingleSelectDataViewCtrlTestCase : public DataViewCtrlTestCase
{
public:
SingleSelectDataViewCtrlTestCase()
: DataViewCtrlTestCase(wxDV_SINGLE)
{
}
};
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( DataViewCtrlTestCase, "DataViewCtrlTestCase" );
class MultiSelectDataViewCtrlTestCase : public DataViewCtrlTestCase
{
public:
MultiSelectDataViewCtrlTestCase()
: DataViewCtrlTestCase(wxDV_MULTIPLE)
{
}
};
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
void DataViewCtrlTestCase::Create(long style)
DataViewCtrlTestCase::DataViewCtrlTestCase(long style)
{
m_dvc = new wxDataViewTreeCtrl(wxTheApp->GetTopWindow(),
wxID_ANY,
@@ -88,33 +84,24 @@ void DataViewCtrlTestCase::Create(long style)
m_grandchild = m_dvc->AppendItem(m_child1, "grandchild");
m_child2 = m_dvc->AppendItem(m_root, "child2");
m_dvc->SetSize(400, 200);
m_dvc->ExpandAncestors(m_root);
m_dvc->Layout();
m_dvc->Expand(m_root);
m_dvc->Refresh();
m_dvc->Update();
}
void DataViewCtrlTestCase::setUp()
{
Create(wxDV_MULTIPLE);
}
void DataViewCtrlTestCase::tearDown()
DataViewCtrlTestCase::~DataViewCtrlTestCase()
{
delete m_dvc;
m_dvc = NULL;
m_root =
m_child1 =
m_child2 =
m_grandchild = wxDataViewItem();
}
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
void DataViewCtrlTestCase::DeleteSelected()
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::DeleteSelected",
"[wxDataViewCtrl][delete]")
{
wxDataViewItemArray sel;
sel.push_back(m_child1);
@@ -128,14 +115,18 @@ void DataViewCtrlTestCase::DeleteSelected()
m_dvc->GetSelections(sel);
// m_child1 and its children should be removed from the selection now
CPPUNIT_ASSERT_EQUAL( 1, sel.size() );
CPPUNIT_ASSERT( sel[0] == m_child2 );
REQUIRE( sel.size() == 1 );
CHECK( sel[0] == m_child2 );
}
void DataViewCtrlTestCase::DeleteNotSelected()
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::DeleteNotSelected",
"[wxDataViewCtrl][delete]")
{
// TODO not working on OS X as expected
#ifndef __WXOSX__
#ifdef __WXOSX__
WARN("Disabled under MacOS because this test currently fails");
#else
wxDataViewItemArray sel;
sel.push_back(m_child1);
sel.push_back(m_grandchild);
@@ -147,9 +138,9 @@ void DataViewCtrlTestCase::DeleteNotSelected()
m_dvc->GetSelections(sel);
// m_child1 and its children should be unaffected
CPPUNIT_ASSERT_EQUAL( 2, sel.size() );
CPPUNIT_ASSERT( sel[0] == m_child1 );
CPPUNIT_ASSERT( sel[1] == m_grandchild );
REQUIRE( sel.size() == 2 );
CHECK( sel[0] == m_child1 );
CHECK( sel[1] == m_grandchild );
#endif
}
@@ -158,44 +149,117 @@ void DataViewCtrlTestCase::TestSelectionFor0and1()
wxDataViewItemArray selections;
// Initially there is no selection.
CPPUNIT_ASSERT_EQUAL( 0, m_dvc->GetSelectedItemsCount() );
CPPUNIT_ASSERT( !m_dvc->HasSelection() );
CPPUNIT_ASSERT( !m_dvc->GetSelection().IsOk() );
CHECK( m_dvc->GetSelectedItemsCount() == 0 );
CHECK( !m_dvc->HasSelection() );
CHECK( !m_dvc->GetSelection().IsOk() );
CPPUNIT_ASSERT( !m_dvc->GetSelections(selections) );
CPPUNIT_ASSERT( selections.empty() );
CHECK( !m_dvc->GetSelections(selections) );
CHECK( selections.empty() );
// Select one item.
m_dvc->Select(m_child1);
CPPUNIT_ASSERT_EQUAL( 1, m_dvc->GetSelectedItemsCount() );
CPPUNIT_ASSERT( m_dvc->HasSelection() );
CPPUNIT_ASSERT( m_dvc->GetSelection().IsOk() );
CPPUNIT_ASSERT_EQUAL( 1, m_dvc->GetSelections(selections) );
CPPUNIT_ASSERT( selections[0] == m_child1 );
CHECK( m_dvc->GetSelectedItemsCount() == 1 );
CHECK( m_dvc->HasSelection() );
CHECK( m_dvc->GetSelection().IsOk() );
REQUIRE( m_dvc->GetSelections(selections) == 1 );
CHECK( selections[0] == m_child1 );
}
void DataViewCtrlTestCase::GetSelectionForMulti()
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::GetSelectionForMulti",
"[wxDataViewCtrl][select]")
{
wxDataViewItemArray selections;
TestSelectionFor0and1();
// Also test with more than one selected item.
m_dvc->Select(m_child2);
CPPUNIT_ASSERT_EQUAL( 2, m_dvc->GetSelectedItemsCount() );
CPPUNIT_ASSERT( m_dvc->HasSelection() );
CPPUNIT_ASSERT( !m_dvc->GetSelection().IsOk() );
CPPUNIT_ASSERT_EQUAL( 2, m_dvc->GetSelections(selections) );
CPPUNIT_ASSERT( selections[1] == m_child2 );
CHECK( m_dvc->GetSelectedItemsCount() == 2 );
CHECK( m_dvc->HasSelection() );
CHECK( !m_dvc->GetSelection().IsOk() );
REQUIRE( m_dvc->GetSelections(selections) == 2 );
CHECK( selections[1] == m_child2 );
}
void DataViewCtrlTestCase::GetSelectionForSingle()
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::SingleSelection",
"[wxDataViewCtrl][selection]")
{
delete m_dvc;
Create(0);
TestSelectionFor0and1();
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::IsExpanded",
"[wxDataViewCtrl][expand]")
{
CHECK( m_dvc->IsExpanded(m_root) );
CHECK( !m_dvc->IsExpanded(m_child1) );
// No idea why, but the native NSOutlineView isItemExpanded: method returns
// true for this item for some reason.
#ifdef __WXOSX__
WARN("Disabled under MacOS: IsExpanded() returns true for grand child");
#else
CHECK( !m_dvc->IsExpanded(m_grandchild) );
#endif
CHECK( !m_dvc->IsExpanded(m_child2) );
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::GetItemRect",
"[wxDataViewCtrl][item]")
{
#ifdef __WXGTK__
// We need to let the native control have some events to lay itself out.
wxYield();
#endif // __WXGTK__
const wxRect rect1 = m_dvc->GetItemRect(m_child1);
const wxRect rect2 = m_dvc->GetItemRect(m_child2);
CHECK( rect1 != wxRect() );
CHECK( rect2 != wxRect() );
CHECK( rect1.x == rect2.x );
CHECK( rect1.width == rect2.width );
CHECK( rect1.height == rect2.height );
{
INFO("First child: " << rect1 << ", second one: " << rect2);
CHECK( rect1.y < rect2.y );
}
const wxRect rectNotShown = m_dvc->GetItemRect(m_grandchild);
CHECK( rectNotShown == wxRect() );
// Append enough items to make the window scrollable.
for ( int i = 3; i < 100; ++i )
m_dvc->AppendItem(m_root, wxString::Format("child%d", i));
const wxDataViewItem last = m_dvc->AppendItem(m_root, "last");
// This should scroll the window to bring this item into view.
m_dvc->EnsureVisible(last);
#ifdef __WXGTK__
// And again to let it scroll the correct items into view.
wxYield();
#endif
// Check that this was indeed the case.
const wxDataViewItem top = m_dvc->GetTopItem();
CHECK( top != m_root );
// Verify that the coordinates are returned in physical coordinates of the
// window and not the logical coordinates affected by scrolling.
const wxRect rectScrolled = m_dvc->GetItemRect(top);
CHECK( rectScrolled.GetBottom() > 0 );
CHECK( rectScrolled.GetTop() <= m_dvc->GetClientSize().y );
// Also check that the root item is not currently visible (because it's
// scrolled off).
const wxRect rectRoot = m_dvc->GetItemRect(m_root);
CHECK( rectRoot == wxRect() );
}
#endif //wxUSE_DATAVIEWCTRL

View File

@@ -22,18 +22,7 @@
#include "wx/iosfwrap.h"
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
// this operator is needed to use CPPUNIT_ASSERT_EQUAL with wxRects
std::ostream& operator<<(std::ostream& os, const wxRect& r)
{
os << "{"
<< r.x << ", " << r.y << ", " << r.width << ", " << r.height
<< "}";
return os;
}
#include "asserthelper.h"
// ----------------------------------------------------------------------------
// test class