Merge branch 'dvc-add-item-error' of https://github.com/thesiv/wxWidgets
Fix adding items to collapsed nodes of wxDataViewCtrl in wxGTK too. See #22228.
This commit is contained in:
@@ -959,7 +959,13 @@ private:
|
|||||||
// Return false only if the event was vetoed by its handler.
|
// Return false only if the event was vetoed by its handler.
|
||||||
bool SendExpanderEvent(wxEventType type, const wxDataViewItem& item);
|
bool SendExpanderEvent(wxEventType type, const wxDataViewItem& item);
|
||||||
|
|
||||||
wxDataViewTreeNode * FindNode( const wxDataViewItem & item );
|
struct FindNodeResult
|
||||||
|
{
|
||||||
|
wxDataViewTreeNode * m_node;
|
||||||
|
bool m_subtreeRealized;
|
||||||
|
};
|
||||||
|
|
||||||
|
FindNodeResult FindNode( const wxDataViewItem & item );
|
||||||
|
|
||||||
wxDataViewColumn *FindColumnForEditing(const wxDataViewItem& item, wxDataViewCellMode mode) const;
|
wxDataViewColumn *FindColumnForEditing(const wxDataViewItem& item, wxDataViewCellMode mode) const;
|
||||||
|
|
||||||
@@ -3089,8 +3095,15 @@ bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxData
|
|||||||
// specific position (row) is unclear, so clear whole height cache
|
// specific position (row) is unclear, so clear whole height cache
|
||||||
ClearRowHeightCache();
|
ClearRowHeightCache();
|
||||||
|
|
||||||
wxDataViewTreeNode *parentNode = FindNode(parent);
|
const FindNodeResult findResult = FindNode(parent);
|
||||||
|
wxDataViewTreeNode *parentNode = findResult.m_node;
|
||||||
|
|
||||||
|
// If one of parents is not realized yet (has children but was never
|
||||||
|
// expanded). Return as nodes will be initialized in Expand().
|
||||||
|
if ( !findResult.m_subtreeRealized )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// The parent node was not found.
|
||||||
if ( !parentNode )
|
if ( !parentNode )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -3197,7 +3210,13 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
|
|||||||
}
|
}
|
||||||
else // general case
|
else // general case
|
||||||
{
|
{
|
||||||
wxDataViewTreeNode *parentNode = FindNode(parent);
|
const FindNodeResult findResult = FindNode(parent);
|
||||||
|
wxDataViewTreeNode *parentNode = findResult.m_node;
|
||||||
|
|
||||||
|
// One of parents of the parent node has children but was never
|
||||||
|
// expanded, so the tree was not built and we have nothing to delete.
|
||||||
|
if ( !findResult.m_subtreeRealized )
|
||||||
|
return true;
|
||||||
|
|
||||||
// Notice that it is possible that the item being deleted is not in the
|
// Notice that it is possible that the item being deleted is not in the
|
||||||
// tree at all, for example we could be deleting a never shown (because
|
// tree at all, for example we could be deleting a never shown (because
|
||||||
@@ -3316,7 +3335,10 @@ bool wxDataViewMainWindow::DoItemChanged(const wxDataViewItem & item, int view_c
|
|||||||
// column but also falls back to other values for comparison. To ensure
|
// column but also falls back to other values for comparison. To ensure
|
||||||
// consistency it is better to treat a value change as if it was an item
|
// consistency it is better to treat a value change as if it was an item
|
||||||
// change.
|
// change.
|
||||||
wxDataViewTreeNode* const node = FindNode(item);
|
const FindNodeResult findResult = FindNode(item);
|
||||||
|
wxDataViewTreeNode* const node = findResult.m_node;
|
||||||
|
if ( !findResult.m_subtreeRealized )
|
||||||
|
return true;
|
||||||
wxCHECK_MSG( node, false, "invalid item" );
|
wxCHECK_MSG( node, false, "invalid item" );
|
||||||
node->PutInSortOrder(this);
|
node->PutInSortOrder(this);
|
||||||
}
|
}
|
||||||
@@ -4084,14 +4106,22 @@ void wxDataViewMainWindow::Collapse(unsigned int row)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item )
|
wxDataViewMainWindow::FindNodeResult
|
||||||
|
wxDataViewMainWindow::FindNode( const wxDataViewItem & item )
|
||||||
{
|
{
|
||||||
|
FindNodeResult result;
|
||||||
|
result.m_node = NULL;
|
||||||
|
result.m_subtreeRealized = true;
|
||||||
|
|
||||||
const wxDataViewModel * model = GetModel();
|
const wxDataViewModel * model = GetModel();
|
||||||
if( model == NULL )
|
if( model == NULL )
|
||||||
return NULL;
|
return result;
|
||||||
|
|
||||||
if (!item.IsOk())
|
if (!item.IsOk())
|
||||||
return m_root;
|
{
|
||||||
|
result.m_node = m_root;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// Compose the parent-chain for the item we are looking for
|
// Compose the parent-chain for the item we are looking for
|
||||||
wxVector<wxDataViewItem> parentChain;
|
wxVector<wxDataViewItem> parentChain;
|
||||||
@@ -4112,9 +4142,9 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item
|
|||||||
if( node->GetChildNodes().empty() )
|
if( node->GetChildNodes().empty() )
|
||||||
{
|
{
|
||||||
// Even though the item is a container, it doesn't have any
|
// Even though the item is a container, it doesn't have any
|
||||||
// child nodes in the control's representation yet. We have
|
// child nodes in the control's representation yet.
|
||||||
// to realize its subtree now.
|
result.m_subtreeRealized = false;
|
||||||
::BuildTreeHelper(this, model, node->GetItem(), node);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxDataViewTreeNodes& nodes = node->GetChildNodes();
|
const wxDataViewTreeNodes& nodes = node->GetChildNodes();
|
||||||
@@ -4126,7 +4156,10 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item
|
|||||||
if (currentNode->GetItem() == parentChain[iter])
|
if (currentNode->GetItem() == parentChain[iter])
|
||||||
{
|
{
|
||||||
if (currentNode->GetItem() == item)
|
if (currentNode->GetItem() == item)
|
||||||
return currentNode;
|
{
|
||||||
|
result.m_node = currentNode;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
node = currentNode;
|
node = currentNode;
|
||||||
found = true;
|
found = true;
|
||||||
@@ -4134,15 +4167,15 @@ wxDataViewTreeNode * wxDataViewMainWindow::FindNode( const wxDataViewItem & item
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
return NULL;
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return NULL;
|
return result;
|
||||||
|
|
||||||
if ( !iter )
|
if ( !iter )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return NULL;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDataViewMainWindow::HitTest( const wxPoint & point, wxDataViewItem & item,
|
void wxDataViewMainWindow::HitTest( const wxPoint & point, wxDataViewItem & item,
|
||||||
|
|||||||
@@ -275,11 +275,22 @@ public:
|
|||||||
|
|
||||||
void OnInternalIdle();
|
void OnInternalIdle();
|
||||||
|
|
||||||
|
enum wxFindNodeMode
|
||||||
|
{
|
||||||
|
// return NULL from FindNode() of a subtree was not realized
|
||||||
|
wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED,
|
||||||
|
|
||||||
|
// call BuildBranch() from FindNode() to realize a subtree
|
||||||
|
wxFIND_NODE_BUILD_SUBTREE,
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InitTree();
|
void InitTree();
|
||||||
void ScheduleRefresh();
|
void ScheduleRefresh();
|
||||||
|
|
||||||
wxGtkTreeModelNode *FindNode( const wxDataViewItem &item );
|
wxGtkTreeModelNode *FindNode( const wxDataViewItem &item,
|
||||||
|
wxFindNodeMode mode =
|
||||||
|
wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED );
|
||||||
wxGtkTreeModelNode *FindNode( GtkTreeIter *iter );
|
wxGtkTreeModelNode *FindNode( GtkTreeIter *iter );
|
||||||
wxGtkTreeModelNode *FindParentNode( const wxDataViewItem &item );
|
wxGtkTreeModelNode *FindParentNode( const wxDataViewItem &item );
|
||||||
wxGtkTreeModelNode *FindParentNode( GtkTreeIter *iter );
|
wxGtkTreeModelNode *FindParentNode( GtkTreeIter *iter );
|
||||||
@@ -3959,7 +3970,7 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa
|
|||||||
{
|
{
|
||||||
if (!m_wx_model->IsVirtualListModel())
|
if (!m_wx_model->IsVirtualListModel())
|
||||||
{
|
{
|
||||||
wxGtkTreeModelNode *parent_node = FindNode( parent );
|
wxGtkTreeModelNode *parent_node = FindNode( parent, wxFIND_NODE_BUILD_SUBTREE );
|
||||||
wxCHECK_MSG(parent_node, false,
|
wxCHECK_MSG(parent_node, false,
|
||||||
"Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
|
"Did you forget a call to ItemAdded()? The parent node is unknown to the wxGtkTreeModel");
|
||||||
|
|
||||||
@@ -3973,6 +3984,17 @@ bool wxDataViewCtrlInternal::ItemAdded( const wxDataViewItem &parent, const wxDa
|
|||||||
const wxGtkTreeModelChildren& nodeSiblings = parent_node->GetChildren();
|
const wxGtkTreeModelChildren& nodeSiblings = parent_node->GetChildren();
|
||||||
const int nodeSiblingsSize = nodeSiblings.size();
|
const int nodeSiblingsSize = nodeSiblings.size();
|
||||||
|
|
||||||
|
if ( nodeSiblingsSize == 0 )
|
||||||
|
{
|
||||||
|
BuildBranch( parent_node );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( parent_node->FindChildByItem(item) != wxNOT_FOUND )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int nodePos = 0;
|
int nodePos = 0;
|
||||||
|
|
||||||
if ( posInModel == modelSiblingsSize - 1 )
|
if ( posInModel == modelSiblingsSize - 1 )
|
||||||
@@ -4398,10 +4420,13 @@ int wxDataViewCtrlInternal::GetIndexOf( const wxDataViewItem &parent, const wxDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static wxGtkTreeModelNode*
|
wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item,
|
||||||
wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
|
wxFindNodeMode mode )
|
||||||
{
|
{
|
||||||
if( model == NULL )
|
if ( !item.IsOk() )
|
||||||
|
return m_root;
|
||||||
|
|
||||||
|
if( m_wx_model == NULL )
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ItemList list;
|
ItemList list;
|
||||||
@@ -4412,14 +4437,25 @@ wxDataViewCtrlInternal_FindNode( wxDataViewModel * model, wxGtkTreeModelNode *tr
|
|||||||
{
|
{
|
||||||
wxDataViewItem * pItem = new wxDataViewItem( it );
|
wxDataViewItem * pItem = new wxDataViewItem( it );
|
||||||
list.Insert( pItem );
|
list.Insert( pItem );
|
||||||
it = model->GetParent( it );
|
it = m_wx_model->GetParent( it );
|
||||||
}
|
}
|
||||||
|
|
||||||
wxGtkTreeModelNode * node = treeNode;
|
wxGtkTreeModelNode * node = m_root;
|
||||||
for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
|
for( ItemList::compatibility_iterator n = list.GetFirst(); n; n = n->GetNext() )
|
||||||
{
|
{
|
||||||
if( node && node->GetNodes().GetCount() != 0 )
|
if( node && node->GetNodes().GetCount() != 0 )
|
||||||
{
|
{
|
||||||
|
switch ( mode )
|
||||||
|
{
|
||||||
|
case wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED:
|
||||||
|
// Do nothing and a subtree will not built.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxFIND_NODE_BUILD_SUBTREE:
|
||||||
|
BuildBranch( node );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
int len = node->GetNodes().GetCount();
|
int len = node->GetNodes().GetCount();
|
||||||
wxGtkTreeModelNodes &nodes = node->GetNodes();
|
wxGtkTreeModelNodes &nodes = node->GetNodes();
|
||||||
int j = 0;
|
int j = 0;
|
||||||
@@ -4450,10 +4486,9 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter )
|
|||||||
return m_root;
|
return m_root;
|
||||||
|
|
||||||
wxDataViewItem item( (void*) iter->user_data );
|
wxDataViewItem item( (void*) iter->user_data );
|
||||||
if (!item.IsOk())
|
|
||||||
return m_root;
|
|
||||||
|
|
||||||
wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
|
const wxFindNodeMode mode = wxFIND_NODE_RETURN_IF_SUBTREE_NOT_REALIZED;
|
||||||
|
wxGtkTreeModelNode *result = FindNode( item, mode );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (!result)
|
if (!result)
|
||||||
@@ -4468,26 +4503,6 @@ wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( GtkTreeIter *iter )
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxGtkTreeModelNode *wxDataViewCtrlInternal::FindNode( const wxDataViewItem &item )
|
|
||||||
{
|
|
||||||
if (!item.IsOk())
|
|
||||||
return m_root;
|
|
||||||
|
|
||||||
wxGtkTreeModelNode *result = wxDataViewCtrlInternal_FindNode( m_wx_model, m_root, item );
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (!result)
|
|
||||||
{
|
|
||||||
wxLogDebug( "Not found %p", item.GetID() );
|
|
||||||
char *crash = NULL;
|
|
||||||
*crash = 0;
|
|
||||||
}
|
|
||||||
// TODO: remove this code
|
|
||||||
*/
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static wxGtkTreeModelNode*
|
static wxGtkTreeModelNode*
|
||||||
wxDataViewCtrlInternal_FindParentNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
|
wxDataViewCtrlInternal_FindParentNode( wxDataViewModel * model, wxGtkTreeModelNode *treeNode, const wxDataViewItem &item )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ public:
|
|||||||
// |-- wxTEST_ITEM_CHILD
|
// |-- wxTEST_ITEM_CHILD
|
||||||
// |
|
// |
|
||||||
// |-- wxTEST_ITEM_GRANDCHILD
|
// |-- wxTEST_ITEM_GRANDCHILD
|
||||||
|
// | |
|
||||||
|
// | |-- wxTEST_ITEM_LEAF
|
||||||
|
// | |
|
||||||
|
// | |-- wxTEST_ITEM_LEAF_HIDDEN
|
||||||
// |
|
// |
|
||||||
// |-- wxTEST_ITEM_GRANDCHILD_HIDDEN
|
// |-- wxTEST_ITEM_GRANDCHILD_HIDDEN
|
||||||
//
|
//
|
||||||
@@ -111,15 +115,19 @@ public:
|
|||||||
wxTEST_ITEM_ROOT,
|
wxTEST_ITEM_ROOT,
|
||||||
wxTEST_ITEM_CHILD,
|
wxTEST_ITEM_CHILD,
|
||||||
wxTEST_ITEM_GRANDCHILD,
|
wxTEST_ITEM_GRANDCHILD,
|
||||||
wxTEST_ITEM_GRANDCHILD_HIDDEN,
|
wxTEST_ITEM_LEAF,
|
||||||
|
wxTEST_ITEM_LEAF_HIDDEN,
|
||||||
|
wxTEST_ITEM_GRANDCHILD_HIDDEN
|
||||||
};
|
};
|
||||||
|
|
||||||
DataViewCtrlTestModel()
|
DataViewCtrlTestModel()
|
||||||
: m_root(wxTEST_ITEM_ROOT),
|
: m_root(wxTEST_ITEM_ROOT),
|
||||||
m_child(wxTEST_ITEM_CHILD),
|
m_child(wxTEST_ITEM_CHILD),
|
||||||
m_grandChild(wxTEST_ITEM_GRANDCHILD),
|
m_grandChild(wxTEST_ITEM_GRANDCHILD),
|
||||||
m_grandChildHidden(wxTEST_ITEM_GRANDCHILD_HIDDEN),
|
m_leaf(wxTEST_ITEM_LEAF),
|
||||||
m_secondGrandchildVisible(false)
|
m_leafHidden(wxTEST_ITEM_LEAF_HIDDEN),
|
||||||
|
m_grandchildHidden(wxTEST_ITEM_GRANDCHILD_HIDDEN),
|
||||||
|
m_allItemsVisible(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,8 +147,14 @@ public:
|
|||||||
case wxTEST_ITEM_GRANDCHILD:
|
case wxTEST_ITEM_GRANDCHILD:
|
||||||
return wxDataViewItem(const_cast<wxTestItem*>(&m_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:
|
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
||||||
return wxDataViewItem(const_cast<wxTestItem*>(&m_grandChildHidden));
|
return wxDataViewItem(const_cast<wxTestItem*>(&m_grandchildHidden));
|
||||||
}
|
}
|
||||||
return wxDataViewItem();
|
return wxDataViewItem();
|
||||||
}
|
}
|
||||||
@@ -177,6 +191,14 @@ public:
|
|||||||
variant = "grand child";
|
variant = "grand child";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case wxTEST_ITEM_LEAF:
|
||||||
|
variant = "leaf";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case wxTEST_ITEM_LEAF_HIDDEN:
|
||||||
|
variant = "initially hidden leaf";
|
||||||
|
break;
|
||||||
|
|
||||||
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
||||||
variant = "initially hidden";
|
variant = "initially hidden";
|
||||||
break;
|
break;
|
||||||
@@ -213,6 +235,10 @@ public:
|
|||||||
case wxTEST_ITEM_GRANDCHILD:
|
case wxTEST_ITEM_GRANDCHILD:
|
||||||
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
||||||
return GetDataViewItem(m_child);
|
return GetDataViewItem(m_child);
|
||||||
|
|
||||||
|
case wxTEST_ITEM_LEAF:
|
||||||
|
case wxTEST_ITEM_LEAF_HIDDEN:
|
||||||
|
return GetDataViewItem(m_grandChild);
|
||||||
}
|
}
|
||||||
return wxDataViewItem();
|
return wxDataViewItem();
|
||||||
}
|
}
|
||||||
@@ -224,9 +250,11 @@ public:
|
|||||||
case wxTEST_ITEM_NULL:
|
case wxTEST_ITEM_NULL:
|
||||||
case wxTEST_ITEM_ROOT:
|
case wxTEST_ITEM_ROOT:
|
||||||
case wxTEST_ITEM_CHILD:
|
case wxTEST_ITEM_CHILD:
|
||||||
|
case wxTEST_ITEM_GRANDCHILD:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case wxTEST_ITEM_GRANDCHILD:
|
case wxTEST_ITEM_LEAF:
|
||||||
|
case wxTEST_ITEM_LEAF_HIDDEN:
|
||||||
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -249,15 +277,27 @@ public:
|
|||||||
case wxTEST_ITEM_CHILD:
|
case wxTEST_ITEM_CHILD:
|
||||||
children.push_back(GetDataViewItem(m_grandChild));
|
children.push_back(GetDataViewItem(m_grandChild));
|
||||||
|
|
||||||
if ( m_secondGrandchildVisible )
|
if ( m_allItemsVisible )
|
||||||
{
|
{
|
||||||
children.push_back(GetDataViewItem(m_grandChildHidden));
|
children.push_back(GetDataViewItem(m_grandchildHidden));
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case wxTEST_ITEM_GRANDCHILD:
|
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:
|
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
|
||||||
FAIL( "The item is not a container" );
|
FAIL( "The item is not a container" );
|
||||||
return 0;
|
return 0;
|
||||||
@@ -265,10 +305,34 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowSecondGrandChild()
|
enum wxItemsOrder
|
||||||
{
|
{
|
||||||
m_secondGrandchildVisible = true;
|
wxORDER_LEAF_THEN_GRANCHILD,
|
||||||
ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandChildHidden));
|
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:
|
private:
|
||||||
@@ -282,10 +346,12 @@ private:
|
|||||||
wxTestItem m_root;
|
wxTestItem m_root;
|
||||||
wxTestItem m_child;
|
wxTestItem m_child;
|
||||||
wxTestItem m_grandChild;
|
wxTestItem m_grandChild;
|
||||||
wxTestItem m_grandChildHidden;
|
wxTestItem m_leaf;
|
||||||
|
wxTestItem m_leafHidden;
|
||||||
|
wxTestItem m_grandchildHidden;
|
||||||
|
|
||||||
// Whether wxTEST_ITEM_GRANDCHILD_HIDDEN item should be visible or not.
|
// Whether wxTEST_ITEM_GRANDCHILD_HIDDEN item should be visible or not.
|
||||||
bool m_secondGrandchildVisible;
|
bool m_allItemsVisible;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -296,6 +362,51 @@ public:
|
|||||||
~DataViewCtrlWithCustomModelTestCase();
|
~DataViewCtrlWithCustomModelTestCase();
|
||||||
|
|
||||||
protected:
|
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.
|
// The dataview control.
|
||||||
wxDataViewCtrl *m_dvc;
|
wxDataViewCtrl *m_dvc;
|
||||||
|
|
||||||
@@ -303,7 +414,12 @@ protected:
|
|||||||
DataViewCtrlTestModel *m_model;
|
DataViewCtrlTestModel *m_model;
|
||||||
|
|
||||||
// Its items.
|
// Its items.
|
||||||
wxDataViewItem m_root, m_child, m_grandchild, m_grandchildHidden;
|
wxDataViewItem m_root,
|
||||||
|
m_child,
|
||||||
|
m_grandchild,
|
||||||
|
m_leaf,
|
||||||
|
m_leafHidden,
|
||||||
|
m_grandchildHidden;
|
||||||
|
|
||||||
wxDECLARE_NO_COPY_CLASS(DataViewCtrlWithCustomModelTestCase);
|
wxDECLARE_NO_COPY_CLASS(DataViewCtrlWithCustomModelTestCase);
|
||||||
};
|
};
|
||||||
@@ -384,6 +500,10 @@ DataViewCtrlWithCustomModelTestCase::DataViewCtrlWithCustomModelTestCase()
|
|||||||
m_child = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_CHILD);
|
m_child = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_CHILD);
|
||||||
m_grandchild =
|
m_grandchild =
|
||||||
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_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_grandchildHidden =
|
||||||
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD_HIDDEN);
|
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD_HIDDEN);
|
||||||
|
|
||||||
@@ -566,53 +686,94 @@ TEST_CASE_METHOD(DataViewCtrlWithCustomModelTestCase,
|
|||||||
wxYield();
|
wxYield();
|
||||||
#endif // __WXGTK__
|
#endif // __WXGTK__
|
||||||
|
|
||||||
SECTION( "Was Expanded" )
|
// 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;
|
||||||
|
|
||||||
|
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_grandchild).IsEmpty() );
|
||||||
|
CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
|
||||||
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
|
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
|
||||||
|
|
||||||
m_dvc->Expand(m_child);
|
m_dvc->Expand(m_child);
|
||||||
|
m_dvc->Expand(m_grandchild);
|
||||||
#ifdef __WXGTK__
|
UpdateAndWaitForItem(m_grandchild, wxITEM_APPEAR);
|
||||||
wxYield();
|
|
||||||
#endif // __WXGTK__
|
|
||||||
|
|
||||||
CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() );
|
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() );
|
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
|
||||||
|
|
||||||
|
m_dvc->Collapse(m_grandchild);
|
||||||
m_dvc->Collapse(m_child);
|
m_dvc->Collapse(m_child);
|
||||||
}
|
break;
|
||||||
|
|
||||||
SECTION( "Was Not Expanded" )
|
case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD:
|
||||||
{
|
case wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check wxDataViewModel::ItemAdded().
|
// Check wxDataViewModel::ItemAdded().
|
||||||
m_model->ShowSecondGrandChild();
|
switch ( options )
|
||||||
|
|
||||||
m_dvc->Expand(m_child);
|
|
||||||
m_dvc->Refresh();
|
|
||||||
m_dvc->Update();
|
|
||||||
CHECK( m_dvc->IsExpanded(m_child) );
|
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
|
||||||
// Unfortunately it's not enough to call wxYield() once, so wait up to
|
|
||||||
// 0.5 sec.
|
|
||||||
wxStopWatch sw;
|
|
||||||
while ( m_dvc->GetItemRect(m_grandchild).IsEmpty() )
|
|
||||||
{
|
{
|
||||||
if ( sw.Time() > 500 )
|
case wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD:
|
||||||
{
|
case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD:
|
||||||
WARN("Timed out waiting for wxDataViewCtrl");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
wxYield();
|
|
||||||
}
|
|
||||||
#endif // __WXGTK__
|
|
||||||
|
|
||||||
|
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_grandchild).IsEmpty() );
|
||||||
|
CHECK( !m_dvc->GetItemRect(m_leaf).IsEmpty() );
|
||||||
|
CHECK( !m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
|
||||||
CHECK( !m_dvc->GetItemRect(m_grandchildHidden).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,
|
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
|
||||||
|
|||||||
Reference in New Issue
Block a user