← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2814: Draw tree subitem texts

 

------------------------------------------------------------
revno: 2814
committer: Jacek Sieka <arnetheduck@xxxxxxxxx>
branch nick: dcplusplus
timestamp: Thu 2012-01-12 23:19:35 +0100
message:
  Draw tree subitem texts
modified:
  dwt/include/dwt/widgets/Header.h
  dwt/include/dwt/widgets/Tree.h
  dwt/src/widgets/Header.cpp
  dwt/src/widgets/Tree.cpp
  dwt/test/TreeTest.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/Header.h'
--- dwt/include/dwt/widgets/Header.h	2012-01-11 20:53:02 +0000
+++ dwt/include/dwt/widgets/Header.h	2012-01-12 22:19:35 +0000
@@ -74,6 +74,8 @@
 
 	int insert(const tstring& header, int width, LPARAM lParam = 0, int after = -1);
 
+	int getWidth(int i) const;
+
 	virtual Point getPreferredSize();
 
 protected:

=== modified file 'dwt/include/dwt/widgets/Tree.h'
--- dwt/include/dwt/widgets/Tree.h	2012-01-11 20:53:02 +0000
+++ dwt/include/dwt/widgets/Tree.h	2012-01-12 22:19:35 +0000
@@ -32,6 +32,9 @@
 #ifndef DWT_TREE_H
 #define DWT_TREE_H
 
+#include <map>
+#include <vector>
+
 #include "../Rectangle.h"
 #include "../resources/ImageList.h"
 #include "../aspects/Clickable.h"
@@ -224,7 +227,9 @@
 	/// Returns the text of a particular node
 	/** Returns the text of a particular node.
 	  */
-	tstring getText( HTREEITEM node );
+	tstring getText( HTREEITEM node, int column = 0);
+
+	void setText(HTREEITEM item, int column, const tstring& text);
 
 	/// Actually creates the TreeView
 	/** You should call WidgetFactory::createTreeView if you instantiate class
@@ -251,6 +256,8 @@
 	TreeViewPtr tree;
 	HeaderPtr header;
 
+	std::map<HTREEITEM, std::vector<tstring>> texts;
+
 	HeaderPtr getHeader();
 
 	// aspects::Data
@@ -288,6 +295,10 @@
 	void setColumnWidthImpl( unsigned column, int width );
 
 	LRESULT draw(NMTVCUSTOMDRAW& x);
+	LRESULT prePaint(NMTVCUSTOMDRAW &nmdc);
+	LRESULT prePaintItem(NMTVCUSTOMDRAW &nmcd);
+	LRESULT postPaintItem(NMTVCUSTOMDRAW &nmcd);
+	LRESULT postPaint(NMTVCUSTOMDRAW &nmcd);
 };
 
 inline HTREEITEM Tree::getNext( HTREEITEM node, unsigned flag ) {

=== modified file 'dwt/src/widgets/Header.cpp'
--- dwt/src/widgets/Header.cpp	2012-01-11 20:53:02 +0000
+++ dwt/src/widgets/Header.cpp	2012-01-12 22:19:35 +0000
@@ -94,4 +94,13 @@
 	Header_SetItem(handle(), idx, &item);
 }
 
+int Header::getWidth(int idx) const {
+	HDITEM item = { HDI_WIDTH };
+
+	if(!Header_GetItem(handle(), idx, &item)) {
+		return 0;
+	}
+	return item.cxy;
+}
+
 }

=== modified file 'dwt/src/widgets/Tree.cpp'
--- dwt/src/widgets/Tree.cpp	2012-01-12 16:14:38 +0000
+++ dwt/src/widgets/Tree.cpp	2012-01-12 22:19:35 +0000
@@ -30,11 +30,18 @@
 */
 
 #include <dwt/widgets/Tree.h>
+
+#include <boost/range/adaptor/map.hpp>
+#include <boost/range/algorithm/for_each.hpp>
+
 #include <dwt/widgets/Header.h>
 #include <dwt/WidgetCreator.h>
 
 namespace dwt {
 
+using boost::range::for_each;
+using boost::adaptors::map_values;
+
 const TCHAR Tree::TreeView::windowClass[] = WC_TREEVIEW;
 
 Tree::TreeView::TreeView(Widget* parent) : Control(parent, ChainingDispatcher::superClass<TreeView>()) { }
@@ -112,24 +119,43 @@
 	return getText(TreeView_GetSelection(treeHandle()));
 }
 
-tstring Tree::getText( HTREEITEM node )
+tstring Tree::getText( HTREEITEM node, int column)
 {
 	if(node == NULL) {
 		return tstring();
 	}
 
-	TVITEMEX item = { TVIF_HANDLE | TVIF_TEXT, node };
-	TCHAR buffer[1024];
-	buffer[0] = '\0';
-	item.cchTextMax = 1022;
-	item.pszText = buffer;
-	if ( TreeView_GetItem(treeHandle(), &item) )
-	{
-		return buffer;
+	if(column == 0) {
+		TVITEMEX item = { TVIF_HANDLE | TVIF_TEXT, node };
+		TCHAR buffer[1024];
+		buffer[0] = '\0';
+		item.cchTextMax = 1022;
+		item.pszText = buffer;
+		if ( TreeView_GetItem(treeHandle(), &item) ) {
+			return buffer;
+		}
+	} else {
+		auto i = texts.find(node);
+		if(i != texts.end() && i->second.size() > column) {
+			return i->second[column];
+		}
 	}
+
 	return tstring();
 }
 
+void Tree::setText(HTREEITEM node, int column, const tstring& text) {
+	if(column == 0) {
+		TVITEMEX item = { TVIF_HANDLE | TVIF_TEXT, node };
+		item.pszText = const_cast<LPTSTR>(text.c_str());
+		TreeView_SetItem(treeHandle(), &item);
+	} else if(column < getColumnCount()) {
+		auto &v = texts[node];
+		if(v.size() <= column) v.resize(column + 1);
+		v[column] = text;
+	}
+}
+
 void Tree::eraseChildren( HTREEITEM node )
 {
 	HTREEITEM next_node, current_node;
@@ -240,6 +266,19 @@
 
 		layout();
 	}
+
+	if(column == 0 && getColumnCount() >= 1) {
+		for_each(texts, [&](const std::pair<HTREEITEM, std::vector<tstring>> & item) {
+			setText(item.first, 0, item.second.empty() ? tstring() : item.second[0]);
+		});
+
+	}
+
+	for_each(texts | map_values, [&](std::vector<tstring> & v) {
+		if(column < v.size()) {
+			v.erase(v.begin() + column);
+		}
+	});
 }
 
 unsigned Tree::getColumnCountImpl() const {
@@ -290,12 +329,89 @@
 	// TODO
 }
 
-LRESULT Tree::draw(NMTVCUSTOMDRAW& x) {
-	if(getColumnCount() < 2) {
+static const int INSET = 3;
+
+LRESULT Tree::prePaint(NMTVCUSTOMDRAW& nmcd) {
+	return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT;
+}
+
+LRESULT Tree::prePaintItem(NMTVCUSTOMDRAW& nmcd) {
+	// Clip the default item drawing to the column width
+	auto clipRect = nmcd.nmcd.rc;
+	auto w = header->getWidth(0);
+	clipRect.right = clipRect.left + w;
+
+	auto hRgn = ::CreateRectRgn (clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+	POINT pt = { 0 };
+
+	auto hDC = nmcd.nmcd.hdc;
+	::GetWindowOrgEx(hDC, &pt);
+	::OffsetRgn (hRgn, -pt.x, -pt.y);
+	::SelectClipRgn (hDC, hRgn);
+	::DeleteObject (hRgn);
+
+	::SaveDC(hDC);
+	return CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT;
+}
+
+LRESULT Tree::postPaintItem(NMTVCUSTOMDRAW& nmcd) {
+	auto hDC = nmcd.nmcd.hdc;
+	::RestoreDC (hDC, -1);
+
+	// Remove previously set clip region
+	::SelectClipRgn(hDC, NULL);
+
+	auto item = (HTREEITEM)nmcd.nmcd.dwItemSpec;
+
+	if (item == NULL) return CDRF_DODEFAULT;
+
+	auto clientSize = tree->getClientSize();
+
+	int x = header->getWidth(0);
+	auto columns = getColumnCount();
+
+	::SetTextColor(hDC, nmcd.clrText);
+	::SetBkColor(hDC, nmcd.clrTextBk);
+
+	for(size_t i = 1; i < columns; ++i) {
+		auto width = header->getWidth(i);
+
+		RECT rect = { x, nmcd.nmcd.rc.top, x + width, nmcd.nmcd.rc.bottom };
+
+		rect.left += INSET - 1;
+
+		if (rect.left < rect.right) {
+			auto text = getText(item, i);
+
+			if (!text.empty()) {
+				int flags = DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS;
+				::DrawText (hDC, text.c_str(), text.size (), &rect, flags);
+			}
+		}
+
+		x += width;
+		if (x > clientSize.x) break;
+	}
+
+	return CDRF_DODEFAULT;
+}
+
+LRESULT Tree::postPaint(NMTVCUSTOMDRAW& nmcd) {
+	return CDRF_DODEFAULT;
+}
+
+LRESULT Tree::draw(NMTVCUSTOMDRAW& nmcd) {
+	if(nmcd.nmcd.rc.left >= nmcd.nmcd.rc.right || nmcd.nmcd.rc.top >= nmcd.nmcd.rc.bottom || getColumnCount() < 2) {
 		return CDRF_DODEFAULT;
 	}
 
-	//TODO
+	switch(nmcd.nmcd.dwDrawStage) {
+	case CDDS_PREPAINT: return prePaint(nmcd);
+	case CDDS_ITEMPREPAINT: return prePaintItem(nmcd);
+	case CDDS_ITEMPOSTPAINT: return postPaintItem(nmcd);
+	case CDDS_POSTPAINT: return postPaint(nmcd);
+	}
+
 	return CDRF_DODEFAULT;
 }
 

=== modified file 'dwt/test/TreeTest.cpp'
--- dwt/test/TreeTest.cpp	2012-01-11 20:53:02 +0000
+++ dwt/test/TreeTest.cpp	2012-01-12 22:19:35 +0000
@@ -28,12 +28,14 @@
 		name.back() += i;
 
 		auto item = tree->insert(name, NULL, 1);
+		tree->setText(item, 1, _T("sub") + name);
+
 		assert(tree->getData(item) == 1);
 		for (int j = 0; j < 4; j++) {
 			tstring subname(_T("item 1"));
 			subname.back() += j;
 			auto subItem = tree->insert(subname, item);
-
+			tree->setText(subItem, 1, _T("sub") + subname);
 		}
 	}