linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #05193
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2810: Play with trees
------------------------------------------------------------
revno: 2810
committer: Jacek Sieka <arnetheduck@xxxxxxxxx>
branch nick: dcplusplus
timestamp: Wed 2012-01-11 21:53:02 +0100
message:
Play with trees
added:
dwt/include/dwt/widgets/Header.h
dwt/src/widgets/Header.cpp
dwt/test/TreeTest.cpp
modified:
dwt/include/dwt/forward.h
dwt/include/dwt/widgets/ModalDialog.h
dwt/include/dwt/widgets/ModelessDialog.h
dwt/include/dwt/widgets/Tree.h
dwt/src/widgets/ModalDialog.cpp
dwt/src/widgets/ModelessDialog.cpp
dwt/src/widgets/Tree.cpp
test/SConscript
win32/TypedTree.h
--
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/forward.h'
--- dwt/include/dwt/forward.h 2011-05-07 18:52:09 +0000
+++ dwt/include/dwt/forward.h 2012-01-11 20:53:02 +0000
@@ -66,6 +66,9 @@
class Container;
typedef Container* ContainerPtr;
+class Control;
+typedef Control* ControlPtr;
+
class CoolBar;
typedef CoolBar* CoolBarPtr;
@@ -89,6 +92,9 @@
class GroupBox;
typedef GroupBox* GroupBoxPtr;
+class Header;
+typedef Header* HeaderPtr;
+
class Icon;
typedef boost::intrusive_ptr<Icon> IconPtr;
=== added file 'dwt/include/dwt/widgets/Header.h'
--- dwt/include/dwt/widgets/Header.h 1970-01-01 00:00:00 +0000
+++ dwt/include/dwt/widgets/Header.h 2012-01-11 20:53:02 +0000
@@ -0,0 +1,129 @@
+/*
+ DC++ Widget Toolkit
+
+ Copyright (c) 2007-2011, Jacek Sieka
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the DWT nor SmartWin++ nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef DWT_HEADER_H_
+#define DWT_HEADER_H_
+
+#include "Control.h"
+
+#include "../aspects/Collection.h"
+#include "../aspects/Data.h"
+
+namespace dwt {
+
+/** Header control like the one used for Table */
+class Header :
+ public CommonControl,
+ public aspects::Collection<Header, int>,
+ public aspects::Data<Header, int>
+{
+ typedef CommonControl BaseType;
+
+ friend class WidgetCreator<Header>;
+ friend class aspects::Collection<Header, int>;
+ friend class aspects::Data<Header, int>;
+public:
+ /// Class type
+ typedef Header ThisType;
+
+ /// Object type
+ typedef ThisType* ObjectType;
+
+ /// Seed class
+ /** This class contains all of the values needed to create the widget. It also
+ * knows the type of the class whose seed values it contains. Every widget
+ * should define one of these.
+ */
+ struct Seed : public BaseType::Seed {
+ typedef ThisType WidgetType;
+
+ /// Fills with default parameters
+ Seed();
+ };
+
+ /// Actually creates the Header
+ void create( const Seed & cs = Seed() );
+
+ int insert(const tstring& header, int width, LPARAM lParam = 0, int after = -1);
+
+ virtual Point getPreferredSize();
+
+protected:
+ /// Constructor Taking pointer to parent
+ explicit Header( Widget * parent );
+
+ // Protected to avoid direct instantiation, you can inherit and use
+ // WidgetFactory class which is friend
+ virtual ~Header()
+ {}
+
+private:
+ friend class ChainingDispatcher;
+ static const TCHAR windowClass[];
+
+ // aspects::Collection
+ void eraseImpl(int row);
+ void clearImpl();
+ size_t sizeImpl() const;
+
+ // aspects::Data
+ int findDataImpl(LPARAM data, int start = -1);
+ LPARAM getDataImpl(int idx);
+ void setDataImpl(int i, LPARAM data);
+
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Implementation of class
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+inline Header::Header( Widget * parent )
+ : BaseType(parent, ChainingDispatcher::superClass<Header>())
+{
+}
+
+inline void Header::eraseImpl( int row ) {
+ Header_DeleteItem(handle(), row);
+}
+
+inline size_t Header::sizeImpl() const {
+ return Header_GetItemCount(handle());
+}
+
+inline void Header::clearImpl() {
+ for(size_t i = 0, iend = size(); i < iend; ++i) {
+ erase(0);
+ }
+}
+
+}
+
+#endif /* HEADER_H_ */
=== modified file 'dwt/include/dwt/widgets/ModalDialog.h'
--- dwt/include/dwt/widgets/ModalDialog.h 2011-11-07 22:11:39 +0000
+++ dwt/include/dwt/widgets/ModalDialog.h 2012-01-11 20:53:02 +0000
@@ -129,7 +129,7 @@
virtual void kill();
private:
friend class ChainingDispatcher;
- static LPCTSTR windowClass;
+ static const TCHAR* windowClass;
bool quit;
int ret;
=== modified file 'dwt/include/dwt/widgets/ModelessDialog.h'
--- dwt/include/dwt/widgets/ModelessDialog.h 2011-11-07 20:53:49 +0000
+++ dwt/include/dwt/widgets/ModelessDialog.h 2012-01-11 20:53:02 +0000
@@ -79,7 +79,7 @@
private:
friend class ChainingDispatcher;
- static LPCTSTR windowClass;
+ static const TCHAR *windowClass;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
=== modified file 'dwt/include/dwt/widgets/Tree.h'
--- dwt/include/dwt/widgets/Tree.h 2011-11-19 00:10:54 +0000
+++ dwt/include/dwt/widgets/Tree.h 2012-01-11 20:53:02 +0000
@@ -3,10 +3,6 @@
Copyright (c) 2007-2011, Jacek Sieka
- SmartWin++
-
- Copyright (c) 2005 Thomas Hansen
-
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@@ -33,13 +29,14 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef DWT_Tree_h
-#define DWT_Tree_h
+#ifndef DWT_TREE_H
+#define DWT_TREE_H
#include "../Rectangle.h"
#include "../resources/ImageList.h"
#include "../aspects/Clickable.h"
#include "../aspects/Collection.h"
+#include "../aspects/Columns.h"
#include "../aspects/CustomDraw.h"
#include "../aspects/Data.h"
#include "../aspects/Selection.h"
@@ -60,29 +57,48 @@
HTREEITEM handle;
};
-/// TreeView class
/** \ingroup WidgetControls
* \WidgetUsageInfo
- * \image html treeview.PNG
- * A Tree is a treview control, like for instance the documentation to
- * dwt which you are probably reading right now would ( in the web version )
- * have a tree view to the left. <br>
- * Another good example of a tree view is the Explorer of Windows, it has a tree
- * view to the left where you can see the different directories.
*/
class Tree :
- public CommonControl,
+ public Control,
public aspects::Clickable<Tree>,
public aspects::Collection<Tree, HTREEITEM>,
- public aspects::CustomDraw<Tree, NMTVCUSTOMDRAW>,
+ public aspects::Columns<Tree>,
public aspects::Data<Tree, HTREEITEM>,
public aspects::Selection<Tree, HTREEITEM>
{
- typedef CommonControl BaseType;
+ typedef Control BaseType;
+
+ class TreeView :
+ public Control,
+ public aspects::CustomDraw<TreeView, NMTVCUSTOMDRAW>
+ {
+ friend class WidgetCreator<TreeView>;
+ public:
+ typedef Tree::Seed Seed;
+ typedef Control BaseType;
+
+ /// Class type
+ typedef TreeView ThisType;
+
+ /// Object type
+ typedef ThisType* ObjectType;
+
+ static const TCHAR windowClass[];
+
+ TreeView(Widget* parent);
+
+ /// Returns true if handled, else false
+ virtual bool handleMessage(const MSG &msg, LRESULT &retVal);
+ };
+
+ typedef TreeView* TreeViewPtr;
protected:
friend class WidgetCreator<Tree>;
friend class aspects::Collection<Tree, HTREEITEM>;
+ friend class aspects::Columns<Tree>;
friend class aspects::Data<Tree, HTREEITEM>;
friend class aspects::Selection<Tree, HTREEITEM>;
friend class aspects::Clickable<Tree>;
@@ -109,21 +125,6 @@
};
/// Inserts a "node" into the TreeView
- /** The return value from a call to this function is a Node. <br>
- * If you later wish to inserts CHILDREN to that node, pass the return value
- * from the first call as the second parameter into this function. <br>
- * If you wish to insert a ( a TreeView can have several "root" nodes ) "root"
- * node then don't pass anything as the second parameter. ( or pass Node() )
- * <br>
- * The "param" parameter ( optionally ) is a unique unsigned integer which must
- * be higher than 0 and can later be used to retrieve unique identification of
- * which item was e.g. selected etc... <br>
- * Especially useful when text of nodes is not unique or text might change.
- * The "iconIndex" optionally specifies the icon index of the item in the
- * associated image list, if there is one. <br>
- * The "selectedIconIndex" optionally specifies the icon index of the item in the
- * selected state (if not specified or -1, it defaults to the iconIndex)
- */
HTREEITEM insert(const tstring& text, HTREEITEM parent = NULL, LPARAM param = 0, bool expanded = false, int iconIndex = - 1, int selectedIconIndex = - 1);
HTREEITEM getNext(HTREEITEM node, unsigned flag);
@@ -225,9 +226,6 @@
*/
tstring getText( HTREEITEM node );
- /// Returns true if fired, else false
- virtual bool handleMessage( const MSG & msg, LRESULT & retVal );
-
/// Actually creates the TreeView
/** You should call WidgetFactory::createTreeView if you instantiate class
* directly. <br>
@@ -235,6 +233,7 @@
*/
void create( const Seed & cs = Seed() );
+ virtual void layout();
protected:
// Constructor Taking pointer to parent
explicit Tree( Widget * parent );
@@ -244,13 +243,16 @@
virtual ~Tree()
{}
+ HWND treeHandle() const { return tree->handle(); }
private:
- friend class ChainingDispatcher;
- static const TCHAR windowClass[];
-
ImageListPtr itsNormalImageList;
ImageListPtr itsStateImageList;
+ TreeViewPtr tree;
+ HeaderPtr header;
+
+ HeaderPtr getHeader();
+
// aspects::Data
LPARAM getDataImpl(HTREEITEM item);
void setDataImpl(HTREEITEM item, LPARAM data);
@@ -273,81 +275,90 @@
static Message getClickMessage();
static Message getRightClickMessage();
static Message getDblClickMessage();
+
+ // aspects::Columns
+ int insertColumnImpl(const Column& column, int after);
+ void eraseColumnImpl(unsigned column);
+ unsigned getColumnCountImpl() const;
+ std::vector<Column> getColumnsImpl() const;
+ Column getColumnImpl(unsigned column) const;
+ std::vector<int> getColumnOrderImpl() const;
+ void setColumnOrderImpl(const std::vector<int>& columns);
+ std::vector<int> getColumnWidthsImpl() const;
+ void setColumnWidthImpl( unsigned column, int width );
+
+ LRESULT draw(NMTVCUSTOMDRAW& x);
};
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// Implementation of class
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
inline HTREEITEM Tree::getNext( HTREEITEM node, unsigned flag ) {
- return TreeView_GetNextItem( handle(), node, flag );
+ return TreeView_GetNextItem(treeHandle(), node, flag);
}
inline HTREEITEM Tree::getChild(HTREEITEM node) {
- return TreeView_GetChild(handle(), node);
+ return TreeView_GetChild(treeHandle(), node);
}
inline HTREEITEM Tree::getNextSibling(HTREEITEM node) {
- return TreeView_GetNextSibling(handle(), node);
+ return TreeView_GetNextSibling(treeHandle(), node);
}
inline HTREEITEM Tree::getParent(HTREEITEM node) {
- return TreeView_GetParent(handle(), node);
+ return TreeView_GetParent(treeHandle(), node);
}
inline HTREEITEM Tree::getRoot() {
- return TreeView_GetRoot(handle());
+ return TreeView_GetRoot(treeHandle());
}
inline HTREEITEM Tree::getFirst() {
- return TreeView_GetFirstVisible(handle());
+ return TreeView_GetFirstVisible(treeHandle());
}
inline HTREEITEM Tree::getLast() {
- return TreeView_GetLastVisible(handle());
+ return TreeView_GetLastVisible(treeHandle());
}
inline void Tree::setColorImpl(COLORREF text, COLORREF background) {
- TreeView_SetTextColor(handle(), text);
- TreeView_SetBkColor(handle(), background);
+ TreeView_SetTextColor(treeHandle(), text);
+ TreeView_SetBkColor(treeHandle(), background);
}
inline HTREEITEM Tree::hitTest(const ScreenCoordinate& pt) {
ClientCoordinate cc(pt, this);
TVHITTESTINFO tvhti = { cc.getPoint() };
- return TreeView_HitTest(handle(), &tvhti);
+ return TreeView_HitTest(treeHandle(), &tvhti);
}
inline bool Tree::isExpanded(HTREEITEM node) {
- return TreeView_GetItemState(handle(), node, TVIS_EXPANDED) & TVIS_EXPANDED;
+ return TreeView_GetItemState(treeHandle(), node, TVIS_EXPANDED) & TVIS_EXPANDED;
}
inline void Tree::expand(HTREEITEM node) {
- TreeView_Expand(handle(), node, TVE_EXPAND);
+ TreeView_Expand(treeHandle(), node, TVE_EXPAND);
}
inline void Tree::collapse(HTREEITEM node) {
- TreeView_Expand(handle(), node, TVE_COLLAPSE);
+ TreeView_Expand(treeHandle(), node, TVE_COLLAPSE);
}
inline void Tree::clearImpl() {
- TreeView_DeleteAllItems( handle() );
+ TreeView_DeleteAllItems(treeHandle());
}
inline void Tree::eraseImpl( HTREEITEM node ) {
- TreeView_DeleteItem( handle(), node );
+ TreeView_DeleteItem(treeHandle(), node);
}
inline size_t Tree::sizeImpl() const {
- return static_cast<size_t>(TreeView_GetCount(handle()));
+ return static_cast<size_t>(TreeView_GetCount(treeHandle()));
}
inline void Tree::editLabel( HTREEITEM node ) {
- static_cast<void>(TreeView_EditLabel( handle(), node ));
+ static_cast<void>(TreeView_EditLabel(treeHandle(), node));
}
inline void Tree::ensureVisible( HTREEITEM node ) {
- TreeView_EnsureVisible( handle(), node );
+ TreeView_EnsureVisible(treeHandle(), node);
}
inline void Tree::setHasButtons( bool value ) {
@@ -391,11 +402,11 @@
}
inline HTREEITEM Tree::getSelectedImpl() const {
- return TreeView_GetSelection( handle() );
+ return TreeView_GetSelection(treeHandle());
}
inline void Tree::setSelectedImpl(HTREEITEM item) {
- TreeView_SelectItem( handle(), item );
+ TreeView_SelectItem(treeHandle(), item );
}
inline size_t Tree::countSelectedImpl() const {
@@ -403,7 +414,7 @@
}
inline Tree::Tree( Widget * parent )
- : BaseType(parent, ChainingDispatcher::superClass<Tree>())
+ : BaseType(parent, NormalDispatcher::newClass<Tree>()), tree(nullptr), header(nullptr)
{
}
=== added file 'dwt/src/widgets/Header.cpp'
--- dwt/src/widgets/Header.cpp 1970-01-01 00:00:00 +0000
+++ dwt/src/widgets/Header.cpp 2012-01-11 20:53:02 +0000
@@ -0,0 +1,97 @@
+/*
+ DC++ Widget Toolkit
+
+ Copyright (c) 2007-2011, Jacek Sieka
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without modification,
+ are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the DWT nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <dwt/widgets/Header.h>
+
+namespace dwt {
+
+const TCHAR Header::windowClass[] = WC_HEADER;
+
+Header::Seed::Seed() :
+BaseType::Seed(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS)
+{
+}
+
+void Header::create( const Header::Seed & cs ) {
+ BaseType::create(cs);
+}
+
+Point Header::getPreferredSize() {
+ RECT rc = { 0, 0, ::GetSystemMetrics(SM_CXSCREEN), ::GetSystemMetrics(SM_CYSCREEN) };
+ WINDOWPOS wp = { 0 };
+ HDLAYOUT hl = { &rc, &wp };
+ if(Header_Layout(handle(), &hl)) {
+ return Point(wp.cx, wp.cy);
+ }
+
+ return Point(0, 0);
+}
+
+int Header::insert(const tstring& header, int width, LPARAM lParam, int after) {
+ if(after == -1) after = size();
+
+ HDITEM item = { HDI_FORMAT };
+ item.fmt = HDF_LEFT;// TODO
+ if(!header.empty()) {
+ item.mask |= HDI_TEXT;
+ item.pszText = const_cast<LPTSTR>(header.c_str());
+ }
+
+ if(width >= 0) {
+ item.mask |= HDI_WIDTH;
+ item.cxy = width;
+ }
+
+ return Header_InsertItem(handle(), after, &item);
+}
+
+int Header::findDataImpl(LPARAM data, int start) {
+ LVFINDINFO fi = { LVFI_PARAM, NULL, data };
+ return ListView_FindItem(handle(), start, &fi);
+}
+
+LPARAM Header::getDataImpl(int idx) {
+ HDITEM item = { HDI_LPARAM };
+
+ if(!Header_GetItem(handle(), idx, &item)) {
+ return 0;
+ }
+ return item.lParam;
+}
+
+void Header::setDataImpl(int idx, LPARAM data) {
+ LVITEM item = { HDI_LPARAM };
+ item.lParam = data;
+
+ Header_SetItem(handle(), idx, &item);
+}
+
+}
=== modified file 'dwt/src/widgets/ModalDialog.cpp'
--- dwt/src/widgets/ModalDialog.cpp 2011-07-05 12:16:32 +0000
+++ dwt/src/widgets/ModalDialog.cpp 2012-01-11 20:53:02 +0000
@@ -36,7 +36,7 @@
namespace dwt {
-LPCTSTR ModalDialog::windowClass = WC_DIALOG;
+const TCHAR* ModalDialog::windowClass = WC_DIALOG;
ModalDialog::Seed::Seed(const Point& size, DWORD styles_) :
BaseType::Seed(tstring(), styles_ | WS_POPUP | WS_CAPTION | WS_SYSMENU, WS_EX_CONTROLPARENT | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE)
=== modified file 'dwt/src/widgets/ModelessDialog.cpp'
--- dwt/src/widgets/ModelessDialog.cpp 2011-01-02 17:12:02 +0000
+++ dwt/src/widgets/ModelessDialog.cpp 2012-01-11 20:53:02 +0000
@@ -33,7 +33,7 @@
namespace dwt {
-LPCTSTR ModelessDialog::windowClass = WC_DIALOG;
+const TCHAR *ModelessDialog::windowClass = WC_DIALOG;
ModelessDialog::Seed::Seed(const Point& size, DWORD styles_) :
BaseType::Seed(tstring(), styles_ | DS_CONTROL | WS_CHILD, WS_EX_CONTROLPARENT)
=== modified file 'dwt/src/widgets/Tree.cpp'
--- dwt/src/widgets/Tree.cpp 2011-06-28 20:07:49 +0000
+++ dwt/src/widgets/Tree.cpp 2012-01-11 20:53:02 +0000
@@ -30,10 +30,33 @@
*/
#include <dwt/widgets/Tree.h>
+#include <dwt/widgets/Header.h>
+#include <dwt/WidgetCreator.h>
namespace dwt {
-const TCHAR Tree::windowClass[] = WC_TREEVIEW;
+const TCHAR Tree::TreeView::windowClass[] = WC_TREEVIEW;
+
+Tree::TreeView::TreeView(Widget* parent) : Control(parent, ChainingDispatcher::superClass<TreeView>()) { }
+
+bool Tree::TreeView::handleMessage(const MSG& msg, LRESULT &retVal) {
+ if(BaseType::handleMessage(msg, retVal)) {
+ return true;
+ }
+
+ if(msg.message == WM_NOTIFY) {
+ // Forward tree notifications
+ return getParent()->handleMessage(msg, retVal);
+ }
+
+ if(msg.message == WM_RBUTTONDOWN) {
+ // Tree view control does strange things to rbuttondown, preventing wm_contextmenu from reaching it
+ retVal = ::DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
+ return true;
+ }
+
+ return false;
+}
Tree::Seed::Seed() :
BaseType::Seed(WS_CHILD | WS_TABSTOP | TVS_DISABLEDRAGDROP | TVS_HASLINES | TVS_NONEVENHEIGHT | TVS_SHOWSELALWAYS),
@@ -43,8 +66,17 @@
void Tree::create( const Seed & cs )
{
- BaseType::create(cs);
+ Control::Seed mySeed(WS_CHILD);
+
+ BaseType::create(mySeed);
+ tree = WidgetCreator<TreeView>::create(this, cs);
+
+ onSized([&](const SizedEvent& e) { layout(); });
+
+ tree->onCustomDraw([=](NMTVCUSTOMDRAW& x) { return draw(x); });
+
setFont(cs.font);
+ layout();
}
HTREEITEM Tree::insert(const tstring& text, HTREEITEM parent, LPARAM param, bool expanded, int iconIndex, int selectedIconIndex) {
@@ -73,11 +105,11 @@
#else
tv.itemex = t;
#endif
- return TreeView_InsertItem(handle(), &tv);
+ return TreeView_InsertItem(treeHandle(), &tv);
}
tstring Tree::getSelectedText() {
- return getText(TreeView_GetSelection(handle()));
+ return getText(TreeView_GetSelection(treeHandle()));
}
tstring Tree::getText( HTREEITEM node )
@@ -91,7 +123,7 @@
buffer[0] = '\0';
item.cchTextMax = 1022;
item.pszText = buffer;
- if ( TreeView_GetItem(handle(), &item) )
+ if ( TreeView_GetItem(treeHandle(), &item) )
{
return buffer;
}
@@ -116,17 +148,17 @@
void Tree::setNormalImageList( ImageListPtr imageList ) {
itsNormalImageList = imageList;
- TreeView_SetImageList(handle(), imageList->getImageList(), TVSIL_NORMAL);
+ TreeView_SetImageList(treeHandle(), imageList->getImageList(), TVSIL_NORMAL);
}
void Tree::setStateImageList( ImageListPtr imageList ) {
itsStateImageList = imageList;
- TreeView_SetImageList(handle(), imageList->getImageList(), TVSIL_STATE);
+ TreeView_SetImageList(treeHandle(), imageList->getImageList(), TVSIL_STATE);
}
LPARAM Tree::getDataImpl(HTREEITEM item) {
TVITEM tvitem = { TVIF_PARAM | TVIF_HANDLE, item };
- if(!TreeView_GetItem(handle(), &tvitem)) {
+ if(!TreeView_GetItem(treeHandle(), &tvitem)) {
return 0;
}
return tvitem.lParam;
@@ -135,15 +167,15 @@
void Tree::setDataImpl(HTREEITEM item, LPARAM lParam) {
TVITEM tvitem = { TVIF_PARAM | TVIF_HANDLE, item };
tvitem.lParam = lParam;
- TreeView_SetItem(handle(), &tvitem);
+ TreeView_SetItem(treeHandle(), &tvitem);
}
int Tree::getItemHeight() {
- return TreeView_GetItemHeight(handle());
+ return TreeView_GetItemHeight(treeHandle());
}
void Tree::setItemHeight(int h) {
- TreeView_SetItemHeight(handle(), h);
+ TreeView_SetItemHeight(treeHandle(), h);
}
ScreenCoordinate Tree::getContextMenuPos() {
@@ -166,19 +198,105 @@
Rectangle Tree::getItemRect(HTREEITEM item) {
RECT rc;
- TreeView_GetItemRect(handle(), item, &rc, TRUE);
+ TreeView_GetItemRect(treeHandle(), item, &rc, TRUE);
return Rectangle(rc);
}
-/// Returns true if fired, else false
-bool Tree::handleMessage( const MSG & msg, LRESULT & retVal ) {
- bool handled = BaseType::handleMessage(msg, retVal);
- if(!handled && msg.message == WM_RBUTTONDOWN) {
- // Tree view control does strange things to rbuttondown, preventing wm_contextmenu from reaching it
- retVal = ::DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
- return true;
- }
- return handled;
+HeaderPtr Tree::getHeader() {
+ if(header == NULL) {
+ header = WidgetCreator<Header>::create(this);
+ layout();
+ }
+
+ return header;
+}
+
+void Tree::layout() {
+ auto client = getClientSize();
+ if(header) {
+ auto hsize = header->getPreferredSize();
+ header->resize(Rectangle(0, 0, client.x, hsize.y));
+ tree->resize(Rectangle(0, hsize.y, client.x, client.y - hsize.y));
+ } else {
+ tree->resize(Rectangle(client));
+ }
+}
+
+int Tree::insertColumnImpl(const Column& column, int after) {
+ auto h = getHeader();
+
+ return h->insert(column.header, column.width, 0, after);
+}
+
+void Tree::eraseColumnImpl(unsigned column) {
+ if(!header) {
+ return;
+ }
+
+ header->erase(column);
+ if(getColumnCount() == 0) {
+ header->close(false);
+ header = 0;
+
+ layout();
+ }
+}
+
+unsigned Tree::getColumnCountImpl() const {
+ return header ? header->size() : 0;
+}
+
+Column Tree::getColumnImpl(unsigned column) const {
+ if(!header) {
+ return Column();
+ }
+
+ HDITEM item = { HDI_FORMAT | HDI_TEXT | HDI_WIDTH };
+ TCHAR buf[1024] = { 0 };
+ item.pszText = buf;
+ item.cchTextMax = 1023;
+ Header_GetItem(header->handle(), column, &item);
+
+ return Column(item.pszText, item.cxy); // TODO fmt
+}
+
+std::vector<Column> Tree::getColumnsImpl() const {
+ std::vector<Column> ret;
+ if(!header) {
+ return ret;
+ }
+
+ ret.resize(getColumnCount());
+ for(size_t i = 0; i < ret.size(); ++i) {
+ ret[i] = getColumn(i);
+ }
+
+ return ret;
+}
+
+std::vector<int> Tree::getColumnOrderImpl() const {
+ return std::vector<int>(); // TODO
+}
+
+void Tree::setColumnOrderImpl(const std::vector<int>& columns) {
+ // TODO
+}
+
+std::vector<int> Tree::getColumnWidthsImpl() const {
+ return std::vector<int>(); // TODO
+}
+
+void Tree::setColumnWidthImpl(unsigned column, int width) {
+ // TODO
+}
+
+LRESULT Tree::draw(NMTVCUSTOMDRAW& x) {
+ if(getColumnCount() < 2) {
+ return CDRF_DODEFAULT;
+ }
+
+ //TODO
+ return CDRF_DODEFAULT;
}
}
=== added file 'dwt/test/TreeTest.cpp'
--- dwt/test/TreeTest.cpp 1970-01-01 00:00:00 +0000
+++ dwt/test/TreeTest.cpp 2012-01-11 20:53:02 +0000
@@ -0,0 +1,49 @@
+#include <dwt/widgets/Window.h>
+#include <dwt/widgets/Tree.h>
+#include <dwt/Texts.h>
+
+#include <iostream>
+
+namespace dwt {
+tstring Texts::get(Text text) { return _T("test"); }
+}
+
+using dwt::tstring;
+
+int dwtMain(dwt::Application& app)
+{
+ auto window = new dwt::Window();
+ window->create();
+ window->onClosing([] { return ::PostQuitMessage(0), true; });
+
+ auto tree = window->addChild(dwt::Tree::Seed());
+ //tree.setHeaderVisible(true);
+
+ tree->addColumn(_T("Column 1"), 200, dwt::Column::LEFT);
+ tree->addColumn(_T("Column 2"), 200, dwt::Column::CENTER);
+ tree->addColumn(_T("Column 3"), 200, dwt::Column::RIGHT);
+
+ for (int i = 0; i < 4; i++) {
+ tstring name(_T("item 1"));
+ name.back() += i;
+
+ auto item = tree->insert(name, NULL, 1);
+ 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->resize(dwt::Rectangle(window->getClientSize()));
+
+ app.run();
+
+ return 0;
+}
+
+
+
+
=== modified file 'test/SConscript'
--- test/SConscript 2012-01-10 18:45:17 +0000
+++ test/SConscript 2012-01-11 20:53:02 +0000
@@ -3,6 +3,11 @@
Import('dev source_path')
def runUnitTest(env,target,source):
+ import sys
+ if sys.platform != 'win32':
+ open(str(target[0]),'w').write("SKIPPED\n")
+ return
+
import subprocess
app = str(source[0].abspath)
if not subprocess.call(app):
=== modified file 'win32/TypedTree.h'
--- win32/TypedTree.h 2011-12-26 16:12:50 +0000
+++ win32/TypedTree.h 2012-01-11 20:53:02 +0000
@@ -77,7 +77,7 @@
}
HTREEITEM insert(TVINSERTSTRUCT* tvis) {
- return TreeView_InsertItem(this->handle(), tvis);
+ return TreeView_InsertItem(this->treeHandle(), tvis);
}
ContentType* getData(HTREEITEM item) {
@@ -85,7 +85,7 @@
}
void getItem(TVITEMEX* item) {
- TreeView_GetItem(this->handle(), item);
+ TreeView_GetItem(this->treeHandle(), item);
}
ContentType* getSelectedData() {
@@ -94,7 +94,7 @@
}
void setItemState(HTREEITEM item, int state, int mask) {
- TreeView_SetItemState(this->handle(), item, state, mask);
+ TreeView_SetItemState(this->treeHandle(), item, state, mask);
}
void clear() {