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:
@@ -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:
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user