wxwidgets/tests/controls/dataviewctrltest.cpp
Vadim Zeitlin 4f4c5fcfdf Use nullptr instead of NULL in the code and documentation
This is a combination of running clang-tidy with modernize-use-nullptr
check for some ports (GTK, X11, OSX) and manual changes to the ports for
which it couldn't be used easily (MSW, DFB) and also manually updating
the docs.

Also replace NULL with null or nullptr in the comments as this is more
consistent with the use of nullptr in the code and makes it simpler to
grep for the remaining occurrences of NULL itself.

And also use null in the assert messages.

Only a few occurrences of "NULL" are still left in non-C files, mostly
corresponding to unclear comments or string output which it might not be
safe to change.
2022-10-18 01:25:25 +02:00

908 lines
26 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/dataviewctrltest.cpp
// Purpose: wxDataViewCtrl unit test
// Author: Vaclav Slavik
// Created: 2011-08-08
// Copyright: (c) 2011 Vaclav Slavik <vslavik@gmail.com>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_DATAVIEWCTRL
#include "wx/app.h"
#include "wx/dataview.h"
#include "wx/uiaction.h"
#ifdef __WXGTK__
#include "wx/stopwatch.h"
#endif // __WXGTK__
#include "testableframe.h"
#include "asserthelper.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class DataViewCtrlTestCase
{
public:
explicit DataViewCtrlTestCase(long style);
~DataViewCtrlTestCase();
protected:
void TestSelectionFor0and1();
// the dataview control itself
wxDataViewTreeCtrl *m_dvc;
// and some of its items
wxDataViewItem m_root,
m_child1,
m_child2,
m_grandchild;
wxDECLARE_NO_COPY_CLASS(DataViewCtrlTestCase);
};
class SingleSelectDataViewCtrlTestCase : public DataViewCtrlTestCase
{
public:
SingleSelectDataViewCtrlTestCase()
: DataViewCtrlTestCase(wxDV_SINGLE)
{
}
};
class MultiSelectDataViewCtrlTestCase : public DataViewCtrlTestCase
{
public:
MultiSelectDataViewCtrlTestCase()
: DataViewCtrlTestCase(wxDV_MULTIPLE)
{
}
};
class MultiColumnsDataViewCtrlTestCase
{
public:
MultiColumnsDataViewCtrlTestCase();
~MultiColumnsDataViewCtrlTestCase();
protected:
// the dataview control itself
wxDataViewListCtrl *m_dvc;
// constants
const wxSize m_size;
const int m_firstColumnWidth;
// and the columns
wxDataViewColumn* m_firstColumn;
wxDataViewColumn* m_lastColumn;
wxDECLARE_NO_COPY_CLASS(MultiColumnsDataViewCtrlTestCase);
};
class DataViewCtrlTestModel: public wxDataViewModel
{
public:
// Items of the model.
//
// wxTEST_ITEM_NULL
// |
// |-- wxTEST_ITEM_ROOT
// |
// |-- wxTEST_ITEM_CHILD
// |
// |-- wxTEST_ITEM_GRANDCHILD
// | |
// | |-- wxTEST_ITEM_LEAF
// | |
// | |-- wxTEST_ITEM_LEAF_HIDDEN
// |
// |-- wxTEST_ITEM_GRANDCHILD_HIDDEN
//
enum wxTestItem
{
wxTEST_ITEM_NULL,
wxTEST_ITEM_ROOT,
wxTEST_ITEM_CHILD,
wxTEST_ITEM_GRANDCHILD,
wxTEST_ITEM_LEAF,
wxTEST_ITEM_LEAF_HIDDEN,
wxTEST_ITEM_GRANDCHILD_HIDDEN
};
DataViewCtrlTestModel()
: m_root(wxTEST_ITEM_ROOT),
m_child(wxTEST_ITEM_CHILD),
m_grandChild(wxTEST_ITEM_GRANDCHILD),
m_leaf(wxTEST_ITEM_LEAF),
m_leafHidden(wxTEST_ITEM_LEAF_HIDDEN),
m_grandchildHidden(wxTEST_ITEM_GRANDCHILD_HIDDEN),
m_allItemsVisible(false)
{
}
wxDataViewItem GetDataViewItem(wxTestItem item) const
{
switch( item )
{
case wxTEST_ITEM_NULL:
return wxDataViewItem();
case wxTEST_ITEM_ROOT:
return wxDataViewItem(const_cast<wxTestItem*>(&m_root));
case wxTEST_ITEM_CHILD:
return wxDataViewItem(const_cast<wxTestItem*>(&m_child));
case wxTEST_ITEM_GRANDCHILD:
return wxDataViewItem(const_cast<wxTestItem*>(&m_grandChild));
case wxTEST_ITEM_LEAF:
return wxDataViewItem(const_cast<wxTestItem*>(&m_leaf));
case wxTEST_ITEM_LEAF_HIDDEN:
return wxDataViewItem(const_cast<wxTestItem*>(&m_leafHidden));
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
return wxDataViewItem(const_cast<wxTestItem*>(&m_grandchildHidden));
}
return wxDataViewItem();
}
// Overridden wxDataViewModel methods.
void GetValue(wxVariant &variant, const wxDataViewItem &item,
unsigned int WXUNUSED(col)) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
break;
case wxTEST_ITEM_ROOT:
variant = "root";
break;
case wxTEST_ITEM_CHILD:
variant = "child";
break;
case wxTEST_ITEM_GRANDCHILD:
variant = "grand child";
break;
case wxTEST_ITEM_LEAF:
variant = "leaf";
break;
case wxTEST_ITEM_LEAF_HIDDEN:
variant = "initially hidden leaf";
break;
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
variant = "initially hidden";
break;
}
}
bool SetValue(const wxVariant &WXUNUSED(variant),
const wxDataViewItem &WXUNUSED(item),
unsigned int WXUNUSED(col)) override
{
return false;
}
bool HasContainerColumns(const wxDataViewItem &WXUNUSED(item)) const override
{
// Always display all the columns, even for the containers.
return true;
}
wxDataViewItem GetParent(const wxDataViewItem &item) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
FAIL( "The item is the top most container" );
return wxDataViewItem();
case wxTEST_ITEM_ROOT:
return wxDataViewItem();
case wxTEST_ITEM_CHILD:
return GetDataViewItem(m_root);
case wxTEST_ITEM_GRANDCHILD:
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
return GetDataViewItem(m_child);
case wxTEST_ITEM_LEAF:
case wxTEST_ITEM_LEAF_HIDDEN:
return GetDataViewItem(m_grandChild);
}
return wxDataViewItem();
}
bool IsContainer(const wxDataViewItem &item) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
case wxTEST_ITEM_ROOT:
case wxTEST_ITEM_CHILD:
case wxTEST_ITEM_GRANDCHILD:
return true;
case wxTEST_ITEM_LEAF:
case wxTEST_ITEM_LEAF_HIDDEN:
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
return false;
}
return false;
}
unsigned int GetChildren(const wxDataViewItem &item,
wxDataViewItemArray &children) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
children.push_back(GetDataViewItem(m_root));
return 1;
case wxTEST_ITEM_ROOT:
children.push_back(GetDataViewItem(m_child));
return 1;
case wxTEST_ITEM_CHILD:
children.push_back(GetDataViewItem(m_grandChild));
if ( m_allItemsVisible )
{
children.push_back(GetDataViewItem(m_grandchildHidden));
return 2;
}
return 1;
case wxTEST_ITEM_GRANDCHILD:
children.push_back(GetDataViewItem(m_leaf));
if ( m_allItemsVisible )
{
children.push_back(GetDataViewItem(m_leafHidden));
return 2;
}
return 1;
case wxTEST_ITEM_LEAF:
case wxTEST_ITEM_LEAF_HIDDEN:
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
FAIL( "The item is not a container" );
return 0;
}
return 0;
}
enum wxItemsOrder
{
wxORDER_LEAF_THEN_GRANCHILD,
wxORDER_GRANCHILD_THEN_LEAF
};
void ShowChildren(wxItemsOrder order)
{
m_allItemsVisible = true;
switch ( order )
{
case wxORDER_LEAF_THEN_GRANCHILD:
ItemAdded(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden));
ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden));
break;
case wxORDER_GRANCHILD_THEN_LEAF:
ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden));
ItemAdded(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden));
break;
}
}
void HideChildren()
{
m_allItemsVisible = false;
ItemDeleted(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden));
ItemDeleted(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden));
}
private:
wxTestItem GetItemID(const wxDataViewItem &dataViewItem) const
{
if ( dataViewItem.GetID() == nullptr )
return wxTEST_ITEM_NULL;
return *static_cast<wxTestItem*>(dataViewItem.GetID());
}
wxTestItem m_root;
wxTestItem m_child;
wxTestItem m_grandChild;
wxTestItem m_leaf;
wxTestItem m_leafHidden;
wxTestItem m_grandchildHidden;
// Whether wxTEST_ITEM_GRANDCHILD_HIDDEN item should be visible or not.
bool m_allItemsVisible;
};
class DataViewCtrlWithCustomModelTestCase
{
public:
DataViewCtrlWithCustomModelTestCase();
~DataViewCtrlWithCustomModelTestCase();
protected:
enum wxItemExistence
{
wxITEM_APPEAR,
wxITEM_DISAPPEAR
};
void UpdateAndWaitForItem(const wxDataViewItem& item, wxItemExistence existence)
{
m_dvc->Refresh();
m_dvc->Update();
#ifdef __WXGTK__
// Unfortunately it's not enough to call wxYield() once, so wait up to
// 0.5 sec.
wxStopWatch sw;
while ( true )
{
wxYield();
const bool isItemRectEmpty = m_dvc->GetItemRect(item).IsEmpty();
switch ( existence )
{
case wxITEM_APPEAR:
if ( !isItemRectEmpty )
return;
break;
case wxITEM_DISAPPEAR:
if ( isItemRectEmpty )
return;
break;
}
if ( sw.Time() > 500 )
{
WARN("Timed out waiting for wxDataViewCtrl");
break;
}
}
#else // !__WXGTK__
wxUnusedVar(item);
wxUnusedVar(existence);
#endif // __WXGTK__
}
// The dataview control.
wxDataViewCtrl *m_dvc;
// The dataview model.
DataViewCtrlTestModel *m_model;
// Its items.
wxDataViewItem m_root,
m_child,
m_grandchild,
m_leaf,
m_leafHidden,
m_grandchildHidden;
wxDECLARE_NO_COPY_CLASS(DataViewCtrlWithCustomModelTestCase);
};
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
DataViewCtrlTestCase::DataViewCtrlTestCase(long style)
{
m_dvc = new wxDataViewTreeCtrl(wxTheApp->GetTopWindow(),
wxID_ANY,
wxDefaultPosition,
wxSize(400, 200),
style);
m_root = m_dvc->AppendContainer(wxDataViewItem(), "The root");
m_child1 = m_dvc->AppendContainer(m_root, "child1");
m_grandchild = m_dvc->AppendItem(m_child1, "grandchild");
m_child2 = m_dvc->AppendItem(m_root, "child2");
m_dvc->Layout();
m_dvc->Expand(m_root);
m_dvc->Refresh();
m_dvc->Update();
}
DataViewCtrlTestCase::~DataViewCtrlTestCase()
{
delete m_dvc;
}
MultiColumnsDataViewCtrlTestCase::MultiColumnsDataViewCtrlTestCase()
: m_size(200, 100),
m_firstColumnWidth(50)
{
m_dvc = new wxDataViewListCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
m_firstColumn =
m_dvc->AppendTextColumn(wxString(), wxDATAVIEW_CELL_INERT, m_firstColumnWidth);
m_lastColumn =
m_dvc->AppendTextColumn(wxString(), wxDATAVIEW_CELL_INERT);
// Set size after columns appending to extend size of the last column.
m_dvc->SetSize(m_size);
m_dvc->Layout();
m_dvc->Refresh();
m_dvc->Update();
}
MultiColumnsDataViewCtrlTestCase::~MultiColumnsDataViewCtrlTestCase()
{
delete m_dvc;
}
DataViewCtrlWithCustomModelTestCase::DataViewCtrlWithCustomModelTestCase()
{
m_dvc = new wxDataViewCtrl(wxTheApp->GetTopWindow(),
wxID_ANY,
wxDefaultPosition,
wxSize(400, 200),
wxDV_SINGLE);
m_model = new DataViewCtrlTestModel();
m_dvc->AssociateModel(m_model);
m_model->DecRef();
m_dvc->AppendColumn(
new wxDataViewColumn(
"Value",
new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT),
0,
m_dvc->FromDIP(200),
wxALIGN_LEFT,
wxDATAVIEW_COL_RESIZABLE));
m_root = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_ROOT);
m_child = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_CHILD);
m_grandchild =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD);
m_leaf =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_LEAF);
m_leafHidden =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_LEAF_HIDDEN);
m_grandchildHidden =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD_HIDDEN);
m_dvc->Layout();
m_dvc->Expand(m_root);
m_dvc->Refresh();
m_dvc->Update();
}
DataViewCtrlWithCustomModelTestCase::~DataViewCtrlWithCustomModelTestCase()
{
delete m_dvc;
}
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::Selection",
"[wxDataViewCtrl][select]")
{
// Check selection round-trip.
wxDataViewItemArray sel;
sel.push_back(m_child1);
sel.push_back(m_grandchild);
REQUIRE_NOTHROW( m_dvc->SetSelections(sel) );
wxDataViewItemArray sel2;
CHECK( m_dvc->GetSelections(sel2) == static_cast<int>(sel.size()) );
CHECK( sel2 == sel );
// Invalid items in GetSelections() input are supposed to be just skipped.
sel.clear();
sel.push_back(wxDataViewItem());
REQUIRE_NOTHROW( m_dvc->SetSelections(sel) );
CHECK( m_dvc->GetSelections(sel2) == 0 );
CHECK( sel2.empty() );
}
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::DeleteSelected",
"[wxDataViewCtrl][delete]")
{
#ifdef __WXGTK__
wxString useASAN;
if ( wxGetEnv("wxUSE_ASAN", &useASAN) && useASAN == "1" )
{
WARN("Skipping test resulting in a memory leak report with wxGTK");
return;
}
#endif // __WXGTK__
wxDataViewItemArray sel;
sel.push_back(m_child1);
sel.push_back(m_grandchild);
sel.push_back(m_child2);
m_dvc->SetSelections(sel);
// delete a selected item
m_dvc->DeleteItem(m_child1);
m_dvc->GetSelections(sel);
// m_child1 and its children should be removed from the selection now
REQUIRE( sel.size() == 1 );
CHECK( sel[0] == m_child2 );
}
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::DeleteNotSelected",
"[wxDataViewCtrl][delete]")
{
// TODO not working on OS X as expected
#ifdef __WXOSX__
WARN("Disabled under MacOS because this test currently fails");
#else
wxDataViewItemArray sel;
sel.push_back(m_child1);
sel.push_back(m_grandchild);
m_dvc->SetSelections(sel);
// delete unselected item
m_dvc->DeleteItem(m_child2);
m_dvc->GetSelections(sel);
// m_child1 and its children should be unaffected
REQUIRE( sel.size() == 2 );
CHECK( sel[0] == m_child1 );
CHECK( sel[1] == m_grandchild );
#endif
}
void DataViewCtrlTestCase::TestSelectionFor0and1()
{
wxDataViewItemArray selections;
// Initially there is no selection.
CHECK( m_dvc->GetSelectedItemsCount() == 0 );
CHECK( !m_dvc->HasSelection() );
CHECK( !m_dvc->GetSelection().IsOk() );
CHECK( !m_dvc->GetSelections(selections) );
CHECK( selections.empty() );
// Select one item.
m_dvc->Select(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 );
}
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::GetSelectionForMulti",
"[wxDataViewCtrl][select]")
{
wxDataViewItemArray selections;
TestSelectionFor0and1();
m_dvc->Select(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 );
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::SingleSelection",
"[wxDataViewCtrl][selection]")
{
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) );
m_dvc->Collapse(m_root);
CHECK( !m_dvc->IsExpanded(m_root) );
m_dvc->ExpandChildren(m_root);
CHECK( m_dvc->IsExpanded(m_root) );
CHECK( m_dvc->IsExpanded(m_child1) );
// Expanding an already expanded node must still expand all its children.
m_dvc->Collapse(m_child1);
CHECK( !m_dvc->IsExpanded(m_child1) );
m_dvc->ExpandChildren(m_root);
CHECK( m_dvc->IsExpanded(m_child1) );
}
TEST_CASE_METHOD(DataViewCtrlWithCustomModelTestCase,
"wxDVC::Expand",
"[wxDataViewCtrl][expand]")
{
CHECK( m_dvc->IsExpanded(m_root) );
CHECK( !m_dvc->IsExpanded(m_child) );
#ifdef __WXGTK__
// We need to let the native control have some events to lay itself out.
wxYield();
#endif // __WXGTK__
// Unfortunately we can't combine test options with SECTION() so use
// the additional enum variable.
enum
{
wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD,
wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD,
wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF,
wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF
} options wxDUMMY_INITIALIZE(wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD);
SECTION( "Was Expanded, Add The Leaf Then The Grandchild" )
{
options = wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD;
}
SECTION( "Was Not Expanded, Add The Leaf Then The Grandchild" )
{
options = wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD;
}
SECTION( "Was Expanded, Add The Grandchild Then The Leaf" )
{
options = wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF;
}
SECTION( "Was Not Expanded, Add The Grandchild Then The Leaf" )
{
options = wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF;
}
switch ( options )
{
case wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD:
case wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF:
CHECK( m_dvc->GetItemRect(m_grandchild).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
m_dvc->Expand(m_child);
m_dvc->Expand(m_grandchild);
UpdateAndWaitForItem(m_grandchild, wxITEM_APPEAR);
CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_leaf).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
m_dvc->Collapse(m_grandchild);
m_dvc->Collapse(m_child);
break;
case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD:
case wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF:
// Do nothing.
break;
}
// Check wxDataViewModel::ItemAdded().
switch ( options )
{
case wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD:
case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD:
m_model->ShowChildren(DataViewCtrlTestModel::wxORDER_LEAF_THEN_GRANCHILD);
break;
case wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF:
case wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF:
m_model->ShowChildren(DataViewCtrlTestModel::wxORDER_GRANCHILD_THEN_LEAF);
break;
}
m_dvc->Expand(m_child);
m_dvc->Expand(m_grandchild);
UpdateAndWaitForItem(m_leaf, wxITEM_APPEAR);
CHECK( m_dvc->IsExpanded(m_child) );
CHECK( m_dvc->IsExpanded(m_grandchild) );
CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_leaf).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
m_model->HideChildren();
UpdateAndWaitForItem(m_leafHidden, wxITEM_DISAPPEAR);
CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
// Check that the problem with nodes duplication in ItemAdded() fixed.
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
}
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 );
}
// This forces generic implementation to add m_grandchild to the tree, as
// it does it only on demand. We want the item to really be there to check
// that GetItemRect() returns an empty rectangle for collapsed items.
m_dvc->Expand(m_child1);
m_dvc->Collapse(m_child1);
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__
// Wait for the list control to be relaid out.
wxStopWatch sw;
while ( m_dvc->GetTopItem() == m_root )
{
if ( sw.Time() > 500 )
{
WARN("Timed out waiting for wxDataViewCtrl layout");
break;
}
wxYield();
}
#endif // __WXGTK__
// 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() );
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::DeleteAllItems",
"[wxDataViewCtrl][delete]")
{
// The invalid item corresponds to the root of tree store model, so it
// should have a single item (our m_root) initially.
CHECK( m_dvc->GetChildCount(wxDataViewItem()) == 1 );
m_dvc->DeleteAllItems();
// And none at all after deleting all the items.
CHECK( m_dvc->GetChildCount(wxDataViewItem()) == 0 );
}
TEST_CASE_METHOD(MultiColumnsDataViewCtrlTestCase,
"wxDVC::AppendTextColumn",
"[wxDataViewCtrl][column]")
{
#ifdef __WXGTK__
// Wait for the list control to be realized.
wxStopWatch sw;
while ( m_firstColumn->GetWidth() == 0 )
{
if ( sw.Time() > 500 )
{
WARN("Timed out waiting for wxDataViewListCtrl to be realized");
break;
}
wxYield();
}
#endif
// Check the width of the first column.
CHECK( m_firstColumn->GetWidth() == m_firstColumnWidth );
// Check that the last column was extended to fit client area.
const int lastColumnMaxWidth =
m_dvc->GetClientSize().GetWidth() - m_firstColumnWidth;
// In GTK and under Mac the width of the last column is less then
// a remaining client area.
const int lastColumnMinWidth = lastColumnMaxWidth - 10;
CHECK( m_lastColumn->GetWidth() <= lastColumnMaxWidth );
CHECK( m_lastColumn->GetWidth() >= lastColumnMinWidth );
}
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::KeyEvents",
"[wxDataViewCtrl][event]")
{
if ( !EnableUITests() )
return;
EventCounter keyEvents(m_dvc, wxEVT_KEY_DOWN);
m_dvc->SetFocus();
wxUIActionSimulator sim;
sim.Char(WXK_DOWN);
wxYield();
CHECK( keyEvents.GetCount() == 1 );
}
#endif // wxUSE_UIACTIONSIMULATOR
#endif //wxUSE_DATAVIEWCTRL