← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2996: change the virtual tree list to a hashed container

 

------------------------------------------------------------
revno: 2996
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Fri 2012-07-13 20:01:50 +0200
message:
  change the virtual tree list to a hashed container
modified:
  dwt/include/dwt/widgets/VirtualTree.h
  dwt/src/widgets/VirtualTree.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dwt/include/dwt/widgets/VirtualTree.h'
--- dwt/include/dwt/widgets/VirtualTree.h	2012-07-12 21:32:03 +0000
+++ dwt/include/dwt/widgets/VirtualTree.h	2012-07-13 18:01:50 +0000
@@ -32,7 +32,7 @@
 #ifndef DWT_VIRTUALTREE_H
 #define DWT_VIRTUALTREE_H
 
-#include <list>
+#include <unordered_set>
 
 #include <boost/optional.hpp>
 
@@ -90,6 +90,8 @@
 		Item(TVINSERTSTRUCT& tvis);
 
 		HTREEITEM ptr() const;
+		struct Hash { size_t operator()(const Item& item) const; };
+		struct Equal { bool operator()(const Item& a, const Item& b) const; };
 
 		void insertBefore(Item* sibling);
 		void insertAfter(Item* sibling);
@@ -101,7 +103,7 @@
 		Item* nextVisible() const;
 	};
 
-	std::list<Item> items;
+	std::unordered_set<Item, Item::Hash, Item::Equal> items;
 	Item* root;
 	Item* selected;
 

=== modified file 'dwt/src/widgets/VirtualTree.cpp'
--- dwt/src/widgets/VirtualTree.cpp	2012-07-12 21:32:03 +0000
+++ dwt/src/widgets/VirtualTree.cpp	2012-07-13 18:01:50 +0000
@@ -174,6 +174,14 @@
 	return reinterpret_cast<HTREEITEM>(const_cast<Item*>(this));
 }
 
+size_t VirtualTree::Item::Hash::operator()(const Item& item) const {
+	return reinterpret_cast<size_t>(&item) / sizeof(Item);
+}
+
+bool VirtualTree::Item::Equal::operator()(const Item& a, const Item& b) const {
+	return &a == &b;
+}
+
 void VirtualTree::Item::insertBefore(Item* sibling) {
 	if(sibling) {
 		if(sibling->prev) {
@@ -364,8 +372,7 @@
 	if(tvis.hParent == TVI_ROOT || !tvis.hParent) {
 		tvis.hParent = root->ptr();
 	}
-	items.emplace_back(tvis);
-	auto& item = items.back();
+	auto& item = const_cast<Item&>(*items.emplace(tvis).first);
 	if(item.parent->firstChild == item.parent->lastChild) {
 		updateChildDisplay(item.parent);
 	}
@@ -401,29 +408,31 @@
 }
 
 void VirtualTree::addRoot() {
-	items.emplace_back();
-	root = &items.back();
+	root = const_cast<Item*>(&*items.emplace().first);
 }
 
 bool VirtualTree::validate(Item* item) const {
-	return item;
-	/* ideally one would check that the item does point to an element of the "items" list, but
-	iterating through the list takes too long when it's a large one. */
+	return item && items.find(*item) != items.cend();
 }
 
 VirtualTree::Item* VirtualTree::find(HTREEITEM handle) {
 	if(!handle) { return nullptr; }
-	for(auto& i: items) { if(i.handle == handle) { return &i; } }
+	for(auto& i: items) { if(i.handle == handle) { return const_cast<Item*>(&i); } }
 	return nullptr;
 }
 
 void VirtualTree::display(Item& item) {
+	// insert the item in the actual tree control.
 	if(item.handle) { return; }
+
 	if(item.parent != root && !item.parent->handle) { display(*item.parent); }
+
+	// don't insert items as expanded; instead expand them manually if they were expanded before.
+	auto expanded = item.expanded();
+	if(expanded) { item.state &= ~TVIS_EXPANDED; }
+
 	TVINSERTSTRUCT tvis = { item.parent->handle, item.prev ? item.prev->handle : item.next ? TVI_FIRST : TVI_LAST, { {
 		TVIF_CHILDREN | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT } } };
-	auto expanded = item.expanded();
-	if(expanded) { item.state &= ~TVIS_EXPANDED; }
 	tvis.itemex.state = item.state;
 	tvis.itemex.stateMask = item.state;
 	tvis.itemex.pszText = item.text ? const_cast<TCHAR*>(item.text->c_str()) : LPSTR_TEXTCALLBACK;
@@ -432,10 +441,12 @@
 	tvis.itemex.cChildren = item.firstChild ? 1 : 0;
 	tvis.itemex.lParam = item.lParam;
 	item.handle = reinterpret_cast<HTREEITEM>(sendTreeMsg(TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&tvis)));
+
 	if(expanded) { sendTreeMsg(TVM_EXPAND, TVE_EXPAND, reinterpret_cast<LPARAM>(item.handle)); }
 }
 
 void VirtualTree::hide(Item& item) {
+	// remove the item and its children from the actual tree control.
 	if(!item.handle) { return; }
 	auto child = item.firstChild;
 	while(child) {
@@ -464,12 +475,7 @@
 	if(item->prev) { item->prev->next = item->next; }
 	if(item->next) { item->next->prev = item->prev; }
 	if(item == selected) { selected = nullptr; }
-	for(auto i = items.begin(), iend = items.end(); i != iend; ++i) {
-		if(&*i == item) {
-			items.erase(i);
-			break;
-		}
-	}
+	items.erase(*item);
 }
 
 void VirtualTree::updateChildDisplay(Item* item) {