fixed sorting the items which have indirect data (i.e. images set for open/closed state) and made indirect data handling much simpler and more efficient as a side effect

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13164 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2001-12-23 01:00:32 +00:00
parent d6acfcb5f6
commit 502a2b1810
2 changed files with 58 additions and 32 deletions

View File

@ -433,14 +433,13 @@ private:
void DeleteTextCtrl();
// support for additional item images
friend class wxTreeItemIndirectData;
// support for additional item images which we implement using
// wxTreeItemIndirectData technique - see the comments in msw/treectrl.cpp
void SetIndirectItemData(const wxTreeItemId& item,
wxTreeItemIndirectData *data);
class wxTreeItemIndirectData *data);
bool HasIndirectData(const wxTreeItemId& item) const;
// the array storing all item ids which have indirect data
wxArrayTreeItemIds m_itemsWithIndirectData;
bool IsDataIndirect(wxTreeItemData *data) const
{ return data->GetId().m_pItem == 0; }
// the hash storing the items attributes (indexed by items ids)
wxHashTable m_attrs;
@ -454,6 +453,9 @@ private:
// the starting item for selection with Shift
WXHTREEITEM m_htSelStart;
friend class wxTreeItemIndirectData;
friend class wxTreeSortHelper;
DECLARE_DYNAMIC_CLASS(wxTreeCtrl)
};

View File

@ -401,11 +401,12 @@ private:
//
// There is only one problem with this: when we retrieve the item's data, we
// don't know whether we get a pointer to wxTreeItemData or
// wxTreeItemIndirectData. So we have to maintain a list of all items which
// have indirect data inside the listctrl itself.
// wxTreeItemIndirectData. So we always set the item id to an invalid value
// in this class and the code using the client data checks for it and retrieves
// the real client data in this case.
// ----------------------------------------------------------------------------
class wxTreeItemIndirectData
class wxTreeItemIndirectData : public wxTreeItemData
{
public:
// ctor associates this data with the item and the real item data becomes
@ -425,7 +426,7 @@ public:
}
// dtor deletes the associated data as well
~wxTreeItemIndirectData() { delete m_data; }
virtual ~wxTreeItemIndirectData() { delete m_data; }
// accessors
// get the real data associated with the item
@ -444,6 +445,7 @@ private:
// all the images associated with the item
int m_images[wxTreeItemIcon_Max];
// the real client data
wxTreeItemData *m_data;
};
@ -966,14 +968,13 @@ wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const
return NULL;
}
if ( HasIndirectData(item) )
wxTreeItemData *data = (wxTreeItemData *)tvItem.lParam;
if ( IsDataIndirect(data) )
{
return ((wxTreeItemIndirectData *)tvItem.lParam)->GetData();
}
else
{
return (wxTreeItemData *)tvItem.lParam;
data = ((wxTreeItemIndirectData *)data)->GetData();
}
return data;
}
void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data)
@ -1013,14 +1014,21 @@ void wxTreeCtrl::SetIndirectItemData(const wxTreeItemId& item,
// wxTreeItemIndirectData as well
wxASSERT_MSG( !HasIndirectData(item), wxT("setting indirect data twice?") );
SetItemData(item, (wxTreeItemData *)data);
m_itemsWithIndirectData.Add(item);
SetItemData(item, data);
}
bool wxTreeCtrl::HasIndirectData(const wxTreeItemId& item) const
{
return m_itemsWithIndirectData.Index(item) != wxNOT_FOUND;
// query the item itself
wxTreeViewItem tvItem(item, TVIF_PARAM);
if ( !DoGetItem(&tvItem) )
{
return FALSE;
}
wxTreeItemData *data = (wxTreeItemData *)tvItem.lParam;
return data && IsDataIndirect(data);
}
void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
@ -1738,14 +1746,37 @@ bool wxTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
// sorting stuff
// ----------------------------------------------------------------------------
static int CALLBACK TreeView_CompareCallback(wxTreeItemData *pItem1,
wxTreeItemData *pItem2,
wxTreeCtrl *tree)
// this is just a tiny namespace which is friend to wxTreeCtrl and so can use
// functions such as IsDataIndirect()
class wxTreeSortHelper
{
public:
static int CALLBACK Compare(LPARAM data1, LPARAM data2, LPARAM tree);
private:
static wxTreeItemId GetIdFromData(wxTreeCtrl *tree, LPARAM item)
{
wxTreeItemData *data = (wxTreeItemData *)item;
if ( tree->IsDataIndirect(data) )
{
data = ((wxTreeItemIndirectData *)data)->GetData();
}
return data->GetId();
}
};
int CALLBACK wxTreeSortHelper::Compare(LPARAM pItem1,
LPARAM pItem2,
LPARAM htree)
{
wxCHECK_MSG( pItem1 && pItem2, 0,
wxT("sorting tree without data doesn't make sense") );
return tree->OnCompareItems(pItem1->GetId(), pItem2->GetId());
wxTreeCtrl *tree = (wxTreeCtrl *)htree;
return tree->OnCompareItems(GetIdFromData(tree, pItem1),
GetIdFromData(tree, pItem2));
}
int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
@ -1767,7 +1798,7 @@ void wxTreeCtrl::SortChildren(const wxTreeItemId& item)
{
TV_SORTCB tvSort;
tvSort.hParent = HITEM(item);
tvSort.lpfnCompare = (PFNTVCOMPARE)TreeView_CompareCallback;
tvSort.lpfnCompare = wxTreeSortHelper::Compare;
tvSort.lParam = (LPARAM)this;
TreeView_SortChildrenCB(GetHwnd(), &tvSort, 0 /* reserved */);
}
@ -2335,13 +2366,6 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
wxTreeItemIndirectData *data = (wxTreeItemIndirectData *)
tv->itemOld.lParam;
delete data; // can't be NULL here
m_itemsWithIndirectData.Remove(item);
#if 0
int iIndex = m_itemsWithIndirectData.Index(item);
wxASSERT( iIndex != wxNOT_FOUND) ;
m_itemsWithIndirectData.wxBaseArray::RemoveAt((size_t)iIndex);
#endif
}
else
{