From c360bf5bebfe57a93a5714ec386ef9175c02c821 Mon Sep 17 00:00:00 2001
From: Julian Smart <julian@anthemion.co.uk>
Date: Sun, 8 Feb 2004 13:02:01 +0000
Subject: [PATCH] Added wxTreeListCtrl: patch [ 883529 ] wxTreeListCltr Otto
 Wyss

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@25621 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 contrib/build/gizmos/gizmos.bkl            |    2 +
 contrib/docs/latex/gizmos/classes.tex      |    2 +
 contrib/docs/latex/gizmos/treelistctrl.tex | 1080 +++++
 contrib/include/wx/gizmos/treelistctrl.h   |  515 +++
 contrib/src/gizmos/treelistctrl.cpp        | 4804 ++++++++++++++++++++
 5 files changed, 6403 insertions(+)
 create mode 100644 contrib/docs/latex/gizmos/treelistctrl.tex
 create mode 100644 contrib/include/wx/gizmos/treelistctrl.h
 create mode 100644 contrib/src/gizmos/treelistctrl.cpp

diff --git a/contrib/build/gizmos/gizmos.bkl b/contrib/build/gizmos/gizmos.bkl
index 90752612bd..6ab57b2c54 100644
--- a/contrib/build/gizmos/gizmos.bkl
+++ b/contrib/build/gizmos/gizmos.bkl
@@ -12,6 +12,7 @@
         multicell.cpp
         splittree.cpp
         statpict.cpp
+<!--        treelistctrl.cpp -->
     </set>
 
     <headers template="wx_contrib_headers">
@@ -23,6 +24,7 @@
             wx/gizmos/splittree.h
             wx/gizmos/statpict.h
             wx/gizmos/gizmos.h
+<!--            wx/gizmos/treelistctrl.h -->
         </files>
     </headers>
 
diff --git a/contrib/docs/latex/gizmos/classes.tex b/contrib/docs/latex/gizmos/classes.tex
index 20edd1e691..0052d13573 100644
--- a/contrib/docs/latex/gizmos/classes.tex
+++ b/contrib/docs/latex/gizmos/classes.tex
@@ -17,3 +17,5 @@
 \input splitterscrolledwindow.tex
 \input thinsplitterwindow.tex
 \input treecompanionwindow.tex
+% Uncomment this when treelistctrl.text has been debugged
+%\input treelistctrl.tex
diff --git a/contrib/docs/latex/gizmos/treelistctrl.tex b/contrib/docs/latex/gizmos/treelistctrl.tex
new file mode 100644
index 0000000000..0f9d736cbc
--- /dev/null
+++ b/contrib/docs/latex/gizmos/treelistctrl.tex
@@ -0,0 +1,1080 @@
+\section{\class{wxTreeListCtrl}}\label{wxtreelistctrl}
+
+A tree list control presents information as a hierarchy, with items that may be expanded
+to show further items. Items in a tree list control are referenced by wxTreeItemId handles,
+which may be tested for validity by calling wxTreeItemId::IsOk.
+
+To intercept events from a tree list control, use the event table macros described in \helpref{wxTreeEvent}{wxtreeevent}.
+
+\wxheading{Derived from}
+
+\helpref{wxControl}{wxcontrol}\\
+wxListCtrl\\
+wxTreeCtrl\\
+\helpref{wxWindow}{wxwindow}\\
+\helpref{wxEvtHandler}{wxevthandler}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Include files}
+
+<wx/treelistctrl.h>
+
+\wxheading{Window styles}
+
+\twocolwidtha{5cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{\windowstyle{wxTR\_EDIT\_LABELS}}{Use this style
+if you wish the user to be able to edit labels in the tree list control.}
+\twocolitem{\windowstyle{wxTR\_NO\_BUTTONS}}{For convenience
+to document that no buttons are to be drawn.}
+\twocolitem{\windowstyle{wxTR\_HAS\_BUTTONS}}{Use this style
+to show + and - buttons to the left of parent items.}
+\twocolitem{\windowstyle{wxTR\_TWIST\_BUTTONS}}{Use this style
+to show Mac-style twister buttons to the left of parent items.
+If both wxTR\_HAS\_BUTTONS and wxTR\_TWIST\_BUTTONS are given,
+twister buttons are generated.  Generic only.}
+\twocolitem{\windowstyle{wxTR\_NO\_LINES}}{Use this style
+to hide vertical level connectors.}
+\twocolitem{\windowstyle{wxTR\_FULL\_ROW\_HIGHLIGHT}}{Use this style to have the background
+colour and the selection highlight extend over the entire horizontal
+row of the tree list control window. (This flag is ignored under Windows unless you
+specify wxTR\_NO\_LINES as well.) }
+\twocolitem{\windowstyle{wxTR\_LINES\_AT\_ROOT}}{Use this style
+to show lines between root nodes.
+Only applicable if wxTR\_HIDE\_ROOT is set and wxTR\_NO\_LINES is not set.}
+\twocolitem{\windowstyle{wxTR\_HIDE\_ROOT}}{Use this style
+to suppress the display of the root node,
+effectively causing the first-level nodes
+to appear as a series of root nodes.}
+\twocolitem{\windowstyle{wxTR\_ROW\_LINES}}{Use this style
+to draw a contrasting border between displayed rows.}
+\twocolitem{\windowstyle{wxTR\_HAS\_VARIABLE\_ROW\_HEIGHT}}{Use this style
+to cause row heights to be just big enough to fit the content.
+If not set, all rows use the largest row height.
+The default is that this flag is unset.
+Generic only.}
+\twocolitem{\windowstyle{wxTR\_SINGLE}}{For convenience
+to document that only one item may be selected at a time.
+Selecting another item causes the current selection, if any,
+to be deselected.  This is the default.}
+\twocolitem{\windowstyle{wxTR\_MULTIPLE}}{Use this style
+to allow a range of items to be selected.
+If a second range is selected, the current range, if any, is deselected.}
+\twocolitem{\windowstyle{wxTR\_EXTENDED}}{Use this style
+to allow disjoint items to be selected.  (Only partially implemented; may not work in all cases.)}
+\twocolitem{\windowstyle{wxTR\_DEFAULT\_STYLE}}{The set of flags that are
+closest to the defaults for the native control for a particular toolkit.}
+\end{twocollist}
+
+See also \helpref{window styles overview}{windowstyles}.
+
+\wxheading{Event handling}
+
+To process input from a tree list control, use these event handler macros to direct input to member
+functions that take a \helpref{wxTreeEvent}{wxtreeevent} argument.
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_TREE\_BEGIN\_DRAG(id, func)}}{Begin dragging with the left mouse button.}
+\twocolitem{{\bf EVT\_TREE\_BEGIN\_RDRAG(id, func)}}{Begin dragging with the right mouse button.}
+\twocolitem{{\bf EVT\_TREE\_BEGIN\_LABEL\_EDIT(id, func)}}{Begin editing a label. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.}
+\twocolitem{{\bf EVT\_TREE\_END\_LABEL\_EDIT(id, func)}}{Finish editing a label. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.}
+\twocolitem{{\bf EVT\_TREE\_DELETE\_ITEM(id, func)}}{Delete an item.}
+\twocolitem{{\bf EVT\_TREE\_GET\_INFO(id, func)}}{Request information from the application.}
+\twocolitem{{\bf EVT\_TREE\_SET\_INFO(id, func)}}{Information is being supplied.}
+\twocolitem{{\bf EVT\_TREE\_ITEM\_ACTIVATED(id, func)}}{The item has been activated, i.e. chosen by double clicking it with mouse or from keyboard}
+\twocolitem{{\bf EVT\_TREE\_ITEM\_COLLAPSED(id, func)}}{The item has been collapsed.}
+\twocolitem{{\bf EVT\_TREE\_ITEM\_COLLAPSING(id, func)}}{The item is being collapsed. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.}
+\twocolitem{{\bf EVT\_TREE\_ITEM\_EXPANDED(id, func)}}{The item has been expanded.}
+\twocolitem{{\bf EVT\_TREE\_ITEM\_EXPANDING(id, func)}}{The item is being expanded. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.}
+\twocolitem{{\bf EVT\_TREE\_SEL\_CHANGED(id, func)}}{Selection has changed.}
+\twocolitem{{\bf EVT\_TREE\_SEL\_CHANGING(id, func)}}{Selection is changing. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.}
+\twocolitem{{\bf EVT\_TREE\_KEY\_DOWN(id, func)}}{A key has been pressed.}
+\end{twocollist}
+
+\wxheading{See also}
+
+wxTreeItemData, wxListBox, wxListCtrl,\rtfsp
+wxImageList, wxTreeEvent
+
+\wxheading{Win32 notes}
+
+wxTreeListCtrl class uses the standard common treeview control under Win32
+implemented in the system library {\tt comctl32.dll}. Some versions of this
+library are known to have bugs with handling the tree list control colours: the
+usual symptom is that the expanded items leave black (or otherwise incorrectly
+coloured) background behind them, especially for the controls using non
+default background colour. The recommended solution is to upgrade the {\tt comctl32.dll}
+to a newer version: see
+\urlref{http://www.microsoft.com/msdownload/ieplatform/ie/comctrlx86.asp}{http://www.microsoft.com/msdownload/ieplatform/ie/comctrlx86.asp}.
+
+\latexignore{\rtfignore{\wxheading{Members (tree specific}}}
+
+\membersection{wxTreeListCtrl::wxTreeListCtrl}\label{wxtreelistctrlconstr}
+
+\func{}{wxTreeListCtrl}{\void}
+
+Default constructor.
+
+\func{}{wxTreeListCtrl}{\param{wxWindow*}{ parent}, \param{wxWindowID}{ id = -1},\rtfsp
+\param{const wxPoint\&}{ pos = wxDefaultPosition}, \param{const wxSize\&}{ size = wxDefaultSize},\rtfsp
+\param{long}{ style = wxTR\_DEFAULT\_STYLE}, \param{const wxValidator\& }{validator = wxDefaultValidator}, \param{const wxString\& }{name = ``treelistctrl"}}
+
+Constructor, creating and showing a tree list control.
+
+\wxheading{Parameters}
+
+\docparam{parent}{Parent window. Must not be NULL.}
+
+\docparam{id}{Window identifier. A value of -1 indicates a default value.}
+
+\docparam{pos}{Window position.}
+
+\docparam{size}{Window size. If the default size (-1, -1) is specified then the window is sized
+appropriately.}
+
+\docparam{style}{Window style. See \helpref{wxTreeListCtrl}{wxtreelistctrl}.}
+
+\docparam{validator}{Window validator.}
+
+\docparam{name}{Window name.}
+
+\wxheading{See also}
+
+\helpref{wxTreeListCtrl::Create}{wxtreelistctrlcreate}, \helpref{wxValidator}{wxvalidator}
+
+\membersection{wxTreeListCtrl::\destruct{wxTreeListCtrl}}
+
+\func{void}{\destruct{wxTreeListCtrl}}{\void}
+
+Destructor, destroying the list control.
+
+\membersection{wxTreeListCtrl::AddRoot}\label{wxtreelistctrladdroot}
+
+\func{wxTreeItemId}{AddRoot}{\param{const wxString\&}{ text},
+ \param{int}{ image = -1}, \param{int}{ selImage = -1}, \param{wxTreeItemData*}{ data = NULL}}
+
+Adds the root node to the tree, returning the new item.
+
+The {\it image} and {\it selImage} parameters are an index within
+the normal image list specifying the image to use for unselected and
+selected items, respectively.
+If {\it image} > -1 and {\it selImage} is -1, the same image is used for
+both selected and unselected items.
+
+\membersection{wxTreeListCtrl::AppendItem}\label{wxtreelistctrlappenditem}
+
+\func{wxTreeItemId}{AppendItem}{\param{const wxTreeItemId\& }{parent}, \param{const wxString\&}{ text},
+ \param{int}{ image = -1}, \param{int}{ selImage = -1}, \param{wxTreeItemData*}{ data = NULL}}
+
+Appends an item to the end of the branch identified by {\it parent}, return a new item id.
+
+The {\it image} and {\it selImage} parameters are an index within
+the normal image list specifying the image to use for unselected and
+selected items, respectively.
+If {\it image} > -1 and {\it selImage} is -1, the same image is used for
+both selected and unselected items.
+
+\membersection{wxTreeListCtrl::AssignButtonsImageList}\label{wxtreelistctrlassignbuttonsimagelist}
+
+\func{void}{AssignButtonsImageList}{\param{wxImageList*}{ imageList}}
+
+Sets the buttons image list. The button images assigned with this method will
+be automatically deleted by wxTreeListCtrl as appropriate
+(i.e. it takes ownership of the list).
+
+Setting or assigning the button image list enables the display of image buttons.
+Once enabled, the only way to disable the display of button images is to set
+the button image list to NULL.
+
+This function is only available in the generic version.
+
+See also \helpref{SetButtonsImageList}{wxtreelistctrlsetbuttonsimagelist}.
+
+\membersection{wxTreeListCtrl::AssignImageList}\label{wxtreelistctrlassignimagelist}
+
+\func{void}{AssignImageList}{\param{wxImageList*}{ imageList}}
+
+Sets the normal image list. Image list assigned with this method will
+be automatically deleted by wxTreeListCtrl as appropriate
+(i.e. it takes ownership of the list).
+
+See also \helpref{SetImageList}{wxtreelistctrlsetimagelist}.
+
+\membersection{wxTreeListCtrl::AssignStateImageList}\label{wxtreelistctrlassignstateimagelist}
+
+\func{void}{AssignStateImageList}{\param{wxImageList*}{ imageList}}
+
+Sets the state image list. Image list assigned with this method will
+be automatically deleted by wxTreeListCtrl as appropriate
+(i.e. it takes ownership of the list).
+
+See also \helpref{SetStateImageList}{wxtreelistctrlsetstateimagelist}.
+
+
+\membersection{wxTreeListCtrl::Collapse}\label{wxtreelistctrlcollapse}
+
+\func{void}{Collapse}{\param{const wxTreeItemId\&}{ item}}
+
+Collapses the given item.
+
+\membersection{wxTreeListCtrl::CollapseAndReset}\label{wxtreelistctrlcollapseandreset}
+
+\func{void}{CollapseAndReset}{\param{const wxTreeItemId\&}{ item}}
+
+Collapses the given item and removes all children.
+
+\membersection{wxTreeListCtrl::Create}\label{wxtreelistctrlcreate}
+
+\func{bool}{wxTreeListCtrl}{\param{wxWindow*}{ parent}, \param{wxWindowID}{ id = -1},\rtfsp
+\param{const wxPoint\&}{ pos = wxDefaultPosition}, \param{const wxSize\&}{ size = wxDefaultSize},\rtfsp
+\param{long}{ style = wxTR\_DEFAULT\_STYLE}, \param{const wxValidator\& }{validator = wxDefaultValidator}, \param{const wxString\& }{name = ``listCtrl"}}
+
+Creates the tree list control. See \helpref{wxTreeListCtrl::wxTreeListCtrl}{wxtreelistctrlconstr} for further details.
+
+\membersection{wxTreeListCtrl::Delete}\label{wxtreelistctrldelete}
+
+\func{void}{Delete}{\param{const wxTreeItemId\&}{ item}}
+
+Deletes the specified item. A {\tt EVT\_TREE\_DELETE\_ITEM} event will be
+generated.
+
+This function may cause a subsequent call to GetNextChild to fail.
+
+\membersection{wxTreeListCtrl::DeleteAllItems}\label{wxtreelistctrldeleteallitems}
+
+\func{void}{DeleteAllItems}{\void}
+
+Deletes all the items in the control. Note that this will {\bf not} generate
+any events unlike \helpref{Delete}{wxtreelistctrldelete} method.
+
+\membersection{wxTreeListCtrl::DeleteChildren}\label{wxtreelistctrldeletechildren}
+
+\func{void}{DeleteChildren}{\param{const wxTreeItemId\& }{item}}
+
+Deletes all children of the given item (but not the item itself). Note that
+this will {\bf not} generate any events unlike
+\helpref{Delete}{wxtreelistctrldelete} method.
+
+If you have called \helpref{wxTreeListCtrl::SetItemHasChildren}{wxtreelistctrlsetitemhaschildren}, you
+may need to call it again since {\it DeleteChildren} does not automatically
+clear the setting.
+
+\membersection{wxTreeListCtrl::Edit}\label{wxtreelistctrledit}
+
+\func{void}{Edit}{\param{const wxTreeItemId\&}{ item}}
+
+The same as \helpref{EditLabel}{wxtreelistctrleditlabel}.
+
+\membersection{wxTreeListCtrl::EditLabel}\label{wxtreelistctrleditlabel}
+
+\func{void}{EditLabel}{\param{const wxTreeItemId\&}{ item}}
+
+Starts editing the label of the given item. This function generates a
+EVT\_TREE\_BEGIN\_LABEL\_EDIT event which can be vetoed so that no
+text control will appear for in-place editing.
+
+If the user changed the label, i.e. s/he does not press ESC or leave
+the text control without changes, a EVT\_TREE\_END\_LABEL\_EDIT event
+will be sent which can be vetoed as well.
+
+\wxheading{See also}
+
+\helpref{wxTreeEvent}{wxtreeevent}
+
+\membersection{wxTreeListCtrl::EnsureVisible}\label{wxtreelistctrlensurevisible}
+
+\func{void}{EnsureVisible}{\param{const wxTreeItemId\&}{ item}}
+
+Scrolls and/or expands items to ensure that the given item is visible.
+
+\membersection{wxTreeListCtrl::Expand}\label{wxtreelistctrlexpand}
+
+\func{void}{Expand}{\param{const wxTreeItemId\&}{ item}}
+
+Expands the given item.
+
+\membersection{wxTreeListCtrl::ExpandAll}\label{wxtreelistctrlexpandall}
+
+\func{void}{ExpandAll}{\param{const wxTreeItemId\&}{ item}}
+
+Expands the given item and all subitems recursively.
+
+\membersection{wxTreeListCtrl::GetBoundingRect}\label{wxtreelistctrlgetitemrect}
+
+\constfunc{bool}{GetBoundingRect}{\param{const wxTreeItemId\&}{ item}, \param{wxRect\& }{rect}, \param{bool }{textOnly = FALSE}}
+
+Retrieves the rectangle bounding the {\it item}. If {\it textOnly} is TRUE,
+only the rectangle around the item's label will be returned, otherwise the
+item's image is also taken into account.
+
+The return value is TRUE if the rectangle was successfully retrieved or FALSE
+if it was not (in this case {\it rect} is not changed) - for example, if the
+item is currently invisible.
+
+\pythonnote{The wxPython version of this method requires only the
+{\tt item} and {\tt textOnly} parameters.  The return value is either a
+{\tt wxRect} object or {\tt None}.}
+
+\perlnote{In wxPerl this method only takes the parameters {\tt item} and
+  {\tt textOnly}, and returns a Wx::Rect ( or undef ).}
+
+\membersection{wxTreeListCtrl::GetButtonsImageList}\label{wxtreelistctrlgetbuttonsimagelist}
+
+\constfunc{wxImageList*}{GetButtonsImageList}{\void}
+
+Returns the buttons image list (from which application-defined button images are taken).
+
+This function is only available in the generic version.
+
+\membersection{wxTreeListCtrl::GetChildrenCount}\label{wxtreelistctrlgetchildrencount}
+
+\constfunc{size\_t}{GetChildrenCount}{\param{const wxTreeItemId\&}{ item}, \param{bool}{ recursively = TRUE}}
+
+Returns the number of items in the branch. If {\it recursively} is TRUE, returns the total number
+of descendants, otherwise only one level of children is counted.
+
+\membersection{wxTreeListCtrl::GetCount}\label{wxtreelistctrlgetcount}
+
+\constfunc{int}{GetCount}{\void}
+
+Returns the number of items in the control.
+
+\membersection{wxTreeListCtrl::GetFirstChild}\label{wxtreelistctrlgetfirstchild}
+
+\constfunc{wxTreeItemId}{GetFirstChild}{\param{const wxTreeItemId\&}{ item}, \param{long\& }{cookie}}
+
+Returns the first child; call \helpref{wxTreeListCtrl::GetNextChild}{wxtreelistctrlgetnextchild} for the next child.
+
+For this enumeration function you must pass in a `cookie' parameter
+which is opaque for the application but is necessary for the library
+to make these functions reentrant (i.e. allow more than one
+enumeration on one and the same object simultaneously). The cookie passed to
+GetFirstChild and GetNextChild should be the same variable.
+
+Returns an invalid tree item if there are no further children.
+
+\wxheading{See also}
+
+\membersection{wxTreeListCtrl::GetHeaderWindow}\label{wxtreelistctrlgetheaderwindow}
+
+\constfunc{wxTreeListHeaderWindow*}{GetHeaderWindow}{\void}
+
+Returns the pointer to the header window.
+
+\membersection{wxTreeListCtrl::GetMainWindow}\label{wxtreelistctrlgetmainwindow}
+
+\constfunc{wxTreeListMainWindow*}{GetMainWindow}{\void}
+
+Returns the pointer to the main window.
+
+\helpref{wxTreeListCtrl::GetNextChild}{wxtreelistctrlgetnextchild},
+\helpref{wxTreeListCtrl::GetNextSibling}{wxtreelistctrlgetnextsibling}
+
+\pythonnote{In wxPython the returned wxTreeItemId and the new cookie
+value are both returned as a tuple containing the two values.}
+
+\perlnote{In wxPerl this method only takes the {\tt item} parameter, and
+  returns a 2-element list {\tt ( item, cookie )}.}
+
+\membersection{wxTreeListCtrl::GetFirstVisibleItem}\label{wxtreelistctrlgetfirstvisibleitem}
+
+\constfunc{wxTreeItemId}{GetFirstVisibleItem}{\void}
+
+Returns the first visible item.
+
+\membersection{wxTreeListCtrl::GetImageList}\label{wxtreelistctrlgetimagelist}
+
+\constfunc{wxImageList*}{GetImageList}{\void}
+
+Returns the normal image list.
+
+\membersection{wxTreeListCtrl::GetIndent}\label{wxtreelistctrlgetindent}
+
+\constfunc{int}{GetIndent}{\void}
+
+Returns the current tree list control indentation.
+
+\membersection{wxTreeListCtrl::GetItemBackgroundColour}\label{wxtreelistctrlgetitembackgroundcolour}
+
+\constfunc{wxColour}{GetItemBackgroundColour}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the background colour of the item.
+
+\membersection{wxTreeListCtrl::GetItemData}\label{wxtreelistctrlgetitemdata}
+
+\constfunc{wxTreeItemData*}{GetItemData}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the tree item data associated with the item.
+
+\wxheading{See also}
+
+\helpref{wxTreeItemData}{wxtreeitemdata}
+
+\pythonnote{wxPython provides the following shortcut method:
+
+\indented{2cm}{\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf GetPyData(item)}}{Returns the Python Object
+associated with the wxTreeItemData for the given item Id.}
+\end{twocollist}}
+}
+
+\perlnote{wxPerl provides the following shortcut method:
+\indented{2cm}{
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf GetPlData( item )}}{Returns the Perl data
+associated with the Wx::TreeItemData ( it is just the same as
+tree->GetItemData( item )->GetData(); ).}
+\end{twocollist}}
+}
+
+\membersection{wxTreeListCtrl::GetItemFont}\label{wxtreelistctrlgetitemfont}
+
+\constfunc{wxFont}{GetItemFont}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the font of the item label.
+
+\membersection{wxTreeListCtrl::GetItemImage}\label{wxtreelistctrlgetitemimage}
+
+\constfunc{int}{GetItemImage}{\param{const wxTreeItemId\&}{ item},
+ \param{wxTreeItemIcon}{ which = wxTreeItemIcon_Normal}}
+
+Gets the specified item image of the main column.
+
+\constfunc{int}{GetItemImage}{\param{const wxTreeItemId\&}{ item}, \param{size_t}{ column},
+ \param{wxTreeItemIcon}{ which = wxTreeItemIcon_Normal}}
+
+Gets the specified item image of the entered column.
+
+The value of {\it which} may be:
+
+\begin{itemize}\itemsep=0pt
+\item{wxTreeItemIcon\_Normal} to get the normal item image
+\item{wxTreeItemIcon\_Selected} to get the selected item image (i.e. the image
+which is shown when the item is currently selected)
+\item{wxTreeItemIcon\_Expanded} to get the expanded image (this only
+makes sense for items which have children - then this image is shown when the
+item is expanded and the normal image is shown when it is collapsed)
+\item{wxTreeItemIcon\_SelectedExpanded} to get the selected expanded image
+(which is shown when an expanded item is currently selected)
+\end{itemize}
+
+\membersection{wxTreeListCtrl::GetItemText}\label{wxtreelistctrlgetitemtext}
+
+\constfunc{wxString}{GetItemText}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the item text of the main column.
+
+\constfunc{wxString}{GetItemText}{\param{const wxTreeItemId\&}{ item}, \param{size_t}{ column}}
+
+Returns the item text of the entered column.
+
+\membersection{wxTreeListCtrl::GetItemTextColour}\label{wxtreelistctrlgetitemtextcolour}
+
+\constfunc{wxColour}{GetItemTextColour}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the colour of the item label.
+
+\membersection{wxTreeListCtrl::GetLastChild}\label{wxtreelistctrlgetlastchild}
+
+\constfunc{wxTreeItemId}{GetLastChild}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the last child of the item (or an invalid tree item if this item has no children).
+
+\wxheading{See also}
+
+\helpref{GetFirstChild}{wxtreelistctrlgetfirstchild},
+\helpref{wxTreeListCtrl::GetNextSibling}{wxtreelistctrlgetnextsibling},
+\helpref{GetLastChild}{wxtreelistctrlgetlastchild}
+
+\membersection{wxTreeListCtrl::GetLineSpacing}\label{wxtreelistctrlgetlinespacing}
+
+\constfunc{int}{GetLineSpacing}{\void}
+
+Returns the space above and below the text on each line.
+
+\membersection{wxTreeListCtrl::GetNextChild}\label{wxtreelistctrlgetnextchild}
+
+\constfunc{wxTreeItemId}{GetNextChild}{\param{const wxTreeItemId\&}{ item}, \param{long\& }{cookie}}
+
+Returns the next child; call \helpref{wxTreeListCtrl::GetFirstChild}{wxtreelistctrlgetfirstchild} for the first child.
+
+For this enumeration function you must pass in a `cookie' parameter
+which is opaque for the application but is necessary for the library
+to make these functions reentrant (i.e. allow more than one
+enumeration on one and the same object simultaneously). The cookie passed to
+GetFirstChild and GetNextChild should be the same.
+
+Returns an invalid tree item if there are no further children.
+
+\wxheading{See also}
+
+\helpref{wxTreeListCtrl::GetFirstChild}{wxtreelistctrlgetfirstchild}
+
+\pythonnote{In wxPython the returned wxTreeItemId and the new cookie
+value are both returned as a tuple containing the two values.}
+
+\perlnote{In wxPerl this method returns a 2-element list
+  {\tt ( item, cookie )}, instead of modifying its parameters.}
+
+\membersection{wxTreeListCtrl::GetNextSibling}\label{wxtreelistctrlgetnextsibling}
+
+\constfunc{wxTreeItemId}{GetNextSibling}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the next sibling of the specified item; call \helpref{wxTreeListCtrl::GetPrevSibling}{wxtreelistctrlgetprevsibling} for the previous sibling.
+
+Returns an invalid tree item if there are no further siblings.
+
+\wxheading{See also}
+
+\helpref{wxTreeListCtrl::GetPrevSibling}{wxtreelistctrlgetprevsibling}
+
+\membersection{wxTreeListCtrl::GetNextVisible}\label{wxtreelistctrlgetnextvisible}
+
+\constfunc{wxTreeItemId}{GetNextVisible}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the next visible item.
+
+\membersection{wxTreeListCtrl::GetItemParent}\label{wxtreelistctrlgetitemparent}
+
+\constfunc{wxTreeItemId}{GetItemParent}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the item's parent.
+
+\membersection{wxTreeListCtrl::GetPrevSibling}\label{wxtreelistctrlgetprevsibling}
+
+\constfunc{wxTreeItemId}{GetPrevSibling}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the previous sibling of the specified item; call \helpref{wxTreeListCtrl::GetNextSibling}{wxtreelistctrlgetnextsibling} for the next sibling.
+
+Returns an invalid tree item if there are no further children.
+
+\wxheading{See also}
+
+\helpref{wxTreeListCtrl::GetNextSibling}{wxtreelistctrlgetnextsibling}
+
+\membersection{wxTreeListCtrl::GetPrevVisible}\label{wxtreelistctrlgetprevvisible}
+
+\constfunc{wxTreeItemId}{GetPrevVisible}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the previous visible item.
+
+\membersection{wxTreeListCtrl::GetRootItem}\label{wxtreelistctrlgetrootitem}
+
+\constfunc{wxTreeItemId}{GetRootItem}{\void}
+
+Returns the root item for the tree list control.
+
+\membersection{wxTreeListCtrl::GetSelection}\label{wxtreelistctrlgetselection}
+
+\constfunc{wxTreeItemId}{GetSelection}{\void}
+
+Returns the selection, or an invalid item if there is no selection.
+This function only works with the controls without wxTR\_MULTIPLE style, use
+\helpref{GetSelections}{wxtreelistctrlgetselections} for the controls which do have
+this style.
+
+\membersection{wxTreeListCtrl::GetSelections}\label{wxtreelistctrlgetselections}
+
+\constfunc{size\_t}{GetSelections}{\param{wxArrayTreeItemIds\& }{selection}}
+
+Fills the array of tree items passed in with the currently selected items. This
+function can be called only if the control has the wxTR\_MULTIPLE style.
+
+Returns the number of selected items.
+
+\pythonnote{The wxPython version of this method accepts no parameters
+and returns a Python list of {\tt wxTreeItemId}s.}
+
+\perlnote{In wxPerl this method takes no parameters and returns a list of
+ {\tt Wx::TreeItemId}s.}
+
+\membersection{wxTreeListCtrl::GetStateImageList}\label{wxtreelistctrlgetstateimagelist}
+
+\constfunc{wxImageList*}{GetStateImageList}{\void}
+
+Returns the state image list (from which application-defined state images are taken).
+
+\membersection{wxTreeListCtrl::GetWindowStyle}\label{wxtreelistctrlgetwindowstyle}
+
+\constfunc{long}{GetWindowStyle}{\void}
+
+???
+
+\membersection{wxTreeListCtrl::GetWindowStyleFlag}\label{wxtreelistctrlgetwindowstyleflag}
+
+\constfunc{long}{GetWindowStyleFlag}{\void}
+
+???
+
+\membersection{wxTreeListCtrl::HitTest}\label{wxtreelistctrlhittest}
+
+\func{wxTreeItemId}{HitTest}{\param{const wxPoint\& }{point}}
+
+\func{wxTreeItemId}{HitTest}{\param{const wxPoint\& }{point}, \param{int\& }{flags}}
+
+\func{wxTreeItemId}{HitTest}{\param{const wxPoint\& }{point}, \param{int\& }{flags},
+ \param{int\& }{column}}
+
+Calculates which (if any) item is under the given point, returning the tree item
+id at this point plus extra information {\it flags}. {\it flags} is a bitlist of the following:
+
+\twocolwidtha{5cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{wxTREE\_HITTEST\_ABOVE}{Above the client area.}
+\twocolitem{wxTREE\_HITTEST\_BELOW}{Below the client area.}
+\twocolitem{wxTREE\_HITTEST\_NOWHERE}{In the client area but below the last item.}
+\twocolitem{wxTREE\_HITTEST\_ONITEMBUTTON}{On the button associated with an item.}
+\twocolitem{wxTREE\_HITTEST\_ONITEMICON}{On the bitmap associated with an item.}
+\twocolitem{wxTREE\_HITTEST\_ONITEMINDENT}{In the indentation associated with an item.}
+\twocolitem{wxTREE\_HITTEST\_ONITEMLABEL}{On the label (string) associated with an item.}
+\twocolitem{wxTREE\_HITTEST\_ONITEMRIGHT}{In the area to the right of an item.}
+\twocolitem{wxTREE\_HITTEST\_ONITEMSTATEICON}{On the state icon for a tree view item that is in a user-defined state.}
+\twocolitem{wxTREE\_HITTEST\_TOLEFT}{To the right of the client area.}
+\twocolitem{wxTREE\_HITTEST\_TORIGHT}{To the left of the client area.}
+\end{twocollist}
+
+\pythonnote{in wxPython both the wxTreeItemId and the flags are
+returned as a tuple.}
+
+\perlnote{In wxPerl this method only takes the {\tt point} parameter
+  and returns a 2-element list {\tt ( item, flags )}.}
+
+\membersection{wxTreeListCtrl::InsertItem}\label{wxtreelistctrlinsertitem}
+
+\func{wxTreeItemId}{InsertItem}{\param{const wxTreeItemId\& }{parent}, \param{const wxTreeItemId\& }{previous}, \param{const wxString\&}{ text},
+ \param{int}{ image = -1}, \param{int}{ selImage = -1}, \param{wxTreeItemData*}{ data = NULL}}
+
+\func{wxTreeItemId}{InsertItem}{\param{const wxTreeItemId\& }{parent}, \param{size\_t}{ before}, \param{const wxString\&}{ text},
+ \param{int}{ image = -1}, \param{int}{ selImage = -1}, \param{wxTreeItemData*}{ data = NULL}}
+
+Inserts an item after a given one ({\it previous}) or before one identified by its position ({\it before}).
+{\it before} must be less than the number of children.
+
+The {\it image} and {\it selImage} parameters are an index within
+the normal image list specifying the image to use for unselected and
+selected items, respectively.
+If {\it image} > -1 and {\it selImage} is -1, the same image is used for
+both selected and unselected items.
+
+\pythonnote{The second form of this method is called
+{\tt InsertItemBefore} in wxPython.}
+
+\membersection{wxTreeListCtrl::IsBold}\label{wxtreelistctrlisbold}
+
+\constfunc{bool}{IsBold}{\param{const wxTreeItemId\& }{item}}
+
+Returns TRUE if the given item is in bold state.
+
+See also: \helpref{SetItemBold}{wxtreelistctrlsetitembold}
+
+\membersection{wxTreeListCtrl::IsExpanded}\label{wxtreelistctrlisexpanded}
+
+\constfunc{bool}{IsExpanded}{\param{const wxTreeItemId\&}{ item}}
+
+Returns TRUE if the item is expanded (only makes sense if it has children).
+
+\membersection{wxTreeListCtrl::IsSelected}\label{wxtreelistctrlisselected}
+
+\constfunc{bool}{IsSelected}{\param{const wxTreeItemId\&}{ item}}
+
+Returns TRUE if the item is selected.
+
+\membersection{wxTreeListCtrl::IsVisible}\label{wxtreelistctrlisvisible}
+
+\constfunc{bool}{IsVisible}{\param{const wxTreeItemId\&}{ item}}
+
+Returns TRUE if the item is visible (it might be outside the view, or not expanded).
+
+\membersection{wxTreeListCtrl::HasChildren}\label{wxtreelistctrlhaschildren}
+
+\constfunc{bool}{HasChildren}{\param{const wxTreeItemId\&}{ item}}
+
+Returns TRUE if the item has children.???
+
+\membersection{wxTreeListCtrl::ItemHasChildren}\label{wxtreelistctrlitemhaschildren}
+
+\constfunc{bool}{ItemHasChildren}{\param{const wxTreeItemId\&}{ item}}
+
+Returns TRUE if the item has children.
+
+\membersection{wxTreeListCtrl::OnCompareItems}\label{wxtreelistctrloncompareitems}
+
+\func{int}{OnCompareItems}{\param{const wxTreeItemId\& }{item1}, \param{const wxTreeItemId\& }{item2}}
+
+Override this function in the derived class to change the sort order of the
+items in the tree list control. The function should return a negative, zero or
+positive value if the first item is less than, equal to or greater than the
+second one.
+
+The base class version compares items alphabetically.
+
+See also: \helpref{SortChildren}{wxtreelistctrlsortchildren}
+
+\membersection{wxTreeListCtrl::PrependItem}\label{wxtreelistctrlprependitem}
+
+\func{wxTreeItemId}{PrependItem}{\param{const wxTreeItemId\& }{parent}, \param{const wxString\&}{ text},
+ \param{int}{ image = -1}, \param{int}{ selImage = -1}, \param{wxTreeItemData*}{ data = NULL}}
+
+Appends an item as the first child of {\it parent}, return a new item id.
+
+The {\it image} and {\it selImage} parameters are an index within
+the normal image list specifying the image to use for unselected and
+selected items, respectively.
+If {\it image} > -1 and {\it selImage} is -1, the same image is used for
+both selected and unselected items.
+
+\membersection{wxTreeListCtrl::Refresh}\label{wxtreelistctrlrefresh}
+
+\func{bool}{Refresh}{\param{bool}{ erase=TRUE}, \param{wxRect*}{ rect=NULL}}
+
+Description???
+
+Parameter???
+
+\membersection{wxTreeListCtrl::SetBackgroundColour}\label{wxtreelistctrlsetbackgroundcolour}
+
+\func{void}{SetBackgroundColour}{\param{const wxColour\&}{ colour}}
+
+???
+
+\membersection{wxTreeListCtrl::SetFocus}\label{wxtreelistctrlsetfocus}
+
+\func{void}{SetFocus}{\void}
+
+???
+
+\membersection{wxTreeListCtrl::SetFont}\label{wxtreelistctrlsetfont}
+
+\func{void}{SetFont}{\param{const wxFont\&}{ font}}
+
+???
+
+\membersection{wxTreeListCtrl::SetForegroundColour}\label{wxtreelistctrlsetforegroundcolour}
+
+\func{void}{SetForegroundColour}{\param{const wxColour\&}{ colour}}
+
+???
+
+\membersection{wxTreeListCtrl::SetWindowStyle}\label{wxtreelistctrlsetwindowstyle}
+
+\func{void}{SetWindowStyle}{\param{const long}{ styles}}
+
+???
+
+\membersection{wxTreeListCtrl::ScrollTo}\label{wxtreelistctrlscrollto}
+
+\func{void}{ScrollTo}{\param{const wxTreeItemId\&}{ item}}
+
+Scrolls the specified item into view.
+
+\membersection{wxTreeListCtrl::SelectItem}\label{wxtreelistctrlselectitem}
+
+\func{bool}{SelectItem}{\param{const wxTreeItemId\&}{ item}, \param{bool}{ unselect_others=TRUE},
+ \param{bool}{ extended_select=FALSE}}
+
+Selects the given item.
+
+Parameter???
+
+\membersection{wxTreeListCtrl::SetButtonsImageList}\label{wxtreelistctrlsetbuttonsimagelist}
+
+\func{void}{SetButtonsImageList}{\param{wxImageList*}{ imageList}}
+
+Sets the buttons image list (from which application-defined button images are taken).
+The button images assigned with this method will
+{\bf not} be deleted by wxTreeListCtrl's destructor, you must delete it yourself.
+
+Setting or assigning the button image list enables the display of image buttons.
+Once enabled, the only way to disable the display of button images is to set
+the button image list to NULL.
+
+This function is only available in the generic version.
+
+See also \helpref{AssignButtonsImageList}{wxtreelistctrlassignbuttonsimagelist}.
+
+\membersection{wxTreeListCtrl::SetImageList}\label{wxtreelistctrlsetimagelist}
+
+\func{void}{SetImageList}{\param{wxImageList*}{ imageList}}
+
+Sets the normal image list. Image list assigned with this method will
+{\bf not} be deleted by wxTreeListCtrl's destructor, you must delete it yourself.
+
+See also \helpref{AssignImageList}{wxtreelistctrlassignimagelist}.
+
+\membersection{wxTreeListCtrl::SetIndent}\label{wxtreelistctrlsetindent}
+
+\func{void}{SetIndent}{\param{int}{ indent}}
+
+Sets the indentation for the tree list control.
+
+\membersection{wxTreeListCtrl::SetItemBackgroundColour}\label{wxtreelistctrlsetitembackgroundcolour}
+
+\func{void}{SetItemBackgroundColour}{\param{const wxTreeItemId\&}{ item}, \param{const wxColour\& }{colour}}
+
+Sets the colour of the item's background.
+
+\membersection{wxTreeListCtrl::SetItemBold}\label{wxtreelistctrlsetitembold}
+
+\func{void}{SetItemBold}{\param{const wxTreeItemId\& }{item}, \param{bool}{ bold = TRUE}}
+
+Makes item appear in bold font if {\it bold} parameter is TRUE or resets it to
+the normal state.
+
+See also: \helpref{IsBold}{wxtreelistctrlisbold}
+
+\membersection{wxTreeListCtrl::SetItemData}\label{wxtreelistctrlsetitemdata}
+
+\func{void}{SetItemData}{\param{const wxTreeItemId\&}{ item}, \param{wxTreeItemData* }{data}}
+
+Sets the item client data.
+
+\pythonnote{wxPython provides the following shortcut method:\par
+\indented{2cm}{\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf SetPyData(item, obj)}}{Associate the given Python
+Object with the wxTreeItemData for the given item Id.}
+\end{twocollist}}
+}
+
+\perlnote{wxPerl provides the following shortcut method:
+\indented{2cm}{
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf SetPlData( item, data )}}{Sets the Perl data
+associated with the Wx::TreeItemData ( it is just the same as
+tree->GetItemData( item )->SetData( data ); ).}
+\end{twocollist}}
+}
+
+\membersection{wxTreeListCtrl::SetItemFont}\label{wxtreelistctrlsetitemfont}
+
+\func{void}{SetItemFont}{\param{const wxTreeItemId\&}{ item}, \param{const wxFont\& }{font}}
+
+Sets the item's font. All items in the tree should have the same height to avoid
+text clipping, so the fonts height should be the same for all of them,
+although font attributes may vary.
+
+\wxheading{See also}
+
+\helpref{SetItemBold}{wxtreelistctrlsetitembold}
+
+\membersection{wxTreeListCtrl::SetItemHasChildren}\label{wxtreelistctrlsetitemhaschildren}
+
+\func{void}{SetItemHasChildren}{\param{const wxTreeItemId\&}{ item}, \param{bool}{ has = TRUE}}
+
+Force appearance of the button next to the item. This is useful to
+allow the user to expand the items which don't have any children now,
+but instead adding them only when needed, thus minimizing memory
+usage and loading time.
+
+\membersection{wxTreeListCtrl::SetItemImage}\label{wxtreelistctrlsetitemimage}
+
+\func{void}{SetItemImage}{\param{const wxTreeItemId\&}{ item}, \param{int}{ image},
+ \param{wxTreeItemIcon}{ which = wxTreeItemIcon_Normal}}
+
+Sets the specified item image of the main column. See \helpref{GetItemImage}{wxtreelistctrlgetitemimage}
+for the description of the {\it which} parameter.
+
+\func{void}{SetItemImage}{\param{const wxTreeItemId\&}{ item}, \param{size_t}{ column}, \param{int}{ image},
+ \param{wxTreeItemIcon}{ which = wxTreeItemIcon_Normal}}
+
+Sets the specified item image of the entered column. See \helpref{GetItemImage}{wxtreelistctrlgetitemimage}
+for the description of the {\it which} parameter.
+
+\membersection{wxTreeListCtrl::SetItemText}\label{wxtreelistctrlsetitemtext}
+
+\func{void}{SetItemText}{\param{const wxTreeItemId\&}{ item}, \param{const wxString\&}{ text}}
+
+Sets the item text of the main column.
+
+\func{void}{SetItemText}{\param{const wxTreeItemId\&}{ item}, \param{size_t}{ column}, \param{const wxString\&}{ text}}
+
+Sets the item text of the entered column.
+
+\membersection{wxTreeListCtrl::SetItemTextColour}\label{wxtreelistctrlsetitemtextcolour}
+
+\func{void}{SetItemTextColour}{\param{const wxTreeItemId\&}{ item}, \param{const wxColour\&}{ colour}}
+
+Sets the colour of the item's text.
+
+\membersection{wxTreeListCtrl::SetLineSpacing}\label{wxtreelistctrlsetindent}
+
+\func{void}{SetLineSpacing}{\param{unsigned int}{ spacing}}
+
+Sets the space above and below the text on each line.
+
+\membersection{wxTreeListCtrl::SetStateImageList}\label{wxtreelistctrlsetstateimagelist}
+
+\func{void}{SetStateImageList}{\param{wxImageList*}{ imageList}}
+
+Sets the state image list (from which application-defined state images are taken).
+Image list assigned with this method will
+{\bf not} be deleted by wxTreeListCtrl's destructor, you must delete it yourself.
+
+See also \helpref{AssignStateImageList}{wxtreelistctrlassignstateimagelist}.
+
+\func{void}{SetWindowStyle}{\param{long}{styles}}
+
+Sets the mode flags associated with the display of the tree list control.
+The new mode takes effect immediately.
+(Generic only; MSW ignores changes.)
+
+\membersection{wxTreeListCtrl::SortChildren}\label{wxtreelistctrlsortchildren}
+
+\func{void}{SortChildren}{\param{const wxTreeItemId\&}{ item}}
+
+Sorts the children of the given item using
+\helpref{OnCompareItems}{wxtreelistctrloncompareitems} method of wxTreeListCtrl. You
+should override that method to change the sort order (the default is ascending
+case-sensitive alphabetical order).
+
+\wxheading{See also}
+
+wxTreeItemData, \helpref{OnCompareItems}{wxtreelistctrloncompareitems}
+
+\membersection{wxTreeListCtrl::Toggle}\label{wxtreelistctrltoggle}
+
+\func{void}{Toggle}{\param{const wxTreeItemId\&}{ item}}
+
+Toggles the given item between collapsed and expanded states.
+
+\membersection{wxTreeListCtrl::Unselect}\label{wxtreelistctrlunselect}
+
+\func{void}{Unselect}{\void}
+
+Removes the selection from the currently selected item (if any).
+
+\membersection{wxTreeListCtrl::UnselectAll}\label{wxtreelistctrlunselectall}
+
+\func{void}{UnselectAll}{\void}
+
+This function either behaves the same as \helpref{Unselect}{wxtreelistctrlunselect}
+if the control doesn't have wxTR\_MULTIPLE style, or removes the selection from
+all items if it does have this style.
+
+\latexignore{\rtfignore{\wxheading{Members (column specific}}}
+
+\membersection{wxTreeListCtrl::AddColumn}\label{wxtreelistctrladdcolumn}
+
+\func{void}{AddColumn}{\param{const wxString\&}{ text}}
+
+\func{void}{AddColumn}{\param{const wxString\&}{ text}, \param{size_t}{ width}, \param{wxTreeListColumnAlign}{ alignment = wxTL_ALIGN_LEFT}}
+
+\func{void}{AddColumn}{\param{const wxTreeListColumnInfo\&}{ col}}
+
+Adds a column.
+
+\membersection{wxTreeListCtrl::GetColumn}\label{wxtreelistctrlgetcolumn}
+
+\func{wxTreeListColumnInfo\&}{GetColumn}{\param{size_t}{ column}}
+
+\constfunc{wxTreeListColumnInfo\&}{GetColumn}{\param{size_t}{ column}}
+
+Returns the infos of the columns.
+
+\membersection{wxTreeListCtrl::GetColumnAlignment}\label{wxtreelistctrlgetcolumnalignment}
+
+\constfunc{wxTreeListColumnAlign}{GetColumnAlignment}{\param{size_t}{ column}}
+
+Returns the alignment of the columns.
+
+\membersection{wxTreeListCtrl::GetColumnCount}\label{wxtreelistctrlgetcolumncount}
+
+\constfunc{size_t}{GetColumnCount}{\void}
+
+Returns the number of columns.
+
+\membersection{wxTreeListCtrl::GetColumnImage}\label{wxtreelistctrlgetcolumnimage}
+
+\constfunc{int}{GetColumnImage}{\param{size_t}{ column}}
+
+Returns the image of the columns.
+
+\membersection{wxTreeListCtrl::GetColumnText}\label{wxtreelistctrlgetcolumntext}
+
+\constfunc{wxString}{GetColumnText}{\param{size_t}{ column}}
+
+Returns the text of the columns.
+
+\membersection{wxTreeListCtrl::GetColumnWidth}\label{wxtreelistctrlgetcolumnwidth}
+
+\constfunc{size_t}{GetColumnWidth}{\param{size_t}{ column}}
+
+Returns the width of the columns.
+
+\membersection{wxTreeListCtrl::GetMainColumn}\label{wxtreelistctrlgetmaincolumn}
+
+\constfunc{size_t}{GetMainColumn}{\void}
+
+Returns the number of the main column.
+
+\membersection{wxTreeListCtrl::InsertColumn}\label{wxtreelistctrlinsertcolumn}
+
+\func{void}{InsertColumn}{\param{size_t}{ before}, \param{const wxString\&}{ text}}
+
+\func{void}{InsertColumn}{\param{size_t}{ before}, \param{const wxString\&}{ text}, \param{size_t}{ width},
+ \param{wxTreeListColumnAlign}{ alignment = wxTL_ALIGN_LEFT}}
+
+Inserts a column before(???) the entered column.
+
+\membersection{wxTreeListCtrl::IsColumnShown}\label{wxtreelistctrliscolumnshown}
+
+\constfunc{bool}{IsColumnShown}{\param{size_t}{ column}}
+
+Returns if the columns is shown.
+
+\membersection{wxTreeListCtrl::RemoveColumn}\label{wxtreelistctrlremovecolumn}
+
+\func{void}{RemoveColumn}{\param{size_t}{ column}}
+
+Removes the entered column.
+
+\membersection{wxTreeListCtrl::SetColumn}\label{wxtreelistctrlsetcolumn}
+
+\func{void}{SetColumn}{\param{size_t}{ column}, \param{const wxTreeListColumnInfo\&}{ info}}
+
+Sets the infos of the column.
+
+\membersection{wxTreeListCtrl::SetColumnAlignment}\label{wxtreelistctrlsetcolumnalignment}
+
+\func{void}{SetColumnAlignment}{\param{size_t}{ column}, \param{const wxTreeListColumnAlign}{ align}}
+
+Sets the alignment of the column.
+
+\membersection{wxTreeListCtrl::SetColumnImage}\label{wxtreelistctrlsetcolumnimage}
+
+\func{void}{SetColumnImage}{\param{size_t}{ column}, \param{int}{ image}}
+
+Sets the image of the column.
+
+\membersection{wxTreeListCtrl::SetColumnText}\label{wxtreelistctrlsetcolumntext}
+
+\func{void}{SetColumnText}{\param{size_t}{ column}, \param{const wxString\&}{ text}}
+
+Sets the text of the column.
+
+\membersection{wxTreeListCtrl::SetColumnWidth}\label{wxtreelistctrlsetcolumnwidth}
+
+\func{void}{SetColumnWidth}{\param{size_t}{ column}, \param{size_t}{ width}}
+
+Sets the width of the column.
+
+\membersection{wxTreeListCtrl::SetMainColumn}\label{wxtreelistctrlsetmaincolumn}
+
+\func{void}{SetMainColumn}{\param{size_t}{ column}}
+
+Set the main column.
+
+\membersection{wxTreeListCtrl::ShowColumn}\label{wxtreelistctrlshowcolumn}
+
+\func{void}{ShowColumn}{\param{size_t}{ column}, \param{bool}{ shown}}
+
+Shows/hides the column.
+
+\latexignore{\rtfignore{\wxheading{Members (item specific}}}
+
+\membersection{wxTreeListCtrl::GetItemBold}\label{wxtreelistctrlgetitembold}
+
+\constfunc{bool}{GetItemBold}{\param{const wxTreeItemId\&}{ item}}
+
+Returns the item bold status.
+
diff --git a/contrib/include/wx/gizmos/treelistctrl.h b/contrib/include/wx/gizmos/treelistctrl.h
new file mode 100644
index 0000000000..8b89663a85
--- /dev/null
+++ b/contrib/include/wx/gizmos/treelistctrl.h
@@ -0,0 +1,515 @@
+// -*- C++ -*- //////////////////////////////////////////////////////////////
+// Name:        treelistctrl.h (derived by wx/treectrlg.h)
+// Purpose:     wxTreeListCtrl class
+// Author:      Robert Roebling
+// Modified by: Alberto Griggio, 2002
+// Created:     01/02/97
+// RCS-ID:      $Id$
+// Copyright:   (c) Robert Roebling, Julian Smart, Alberto Griggio,
+//              Vadim Zeitlin, Otto Wyss
+// Licence:     wxWindows license
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef TREELISTCTRL_H
+#define TREELISTCTRL_H
+
+#if defined(__GNUG__) && !defined(__APPLE__)
+    #pragma interface "treelistctrl.h"
+#endif
+
+#include <wx/treectrl.h>
+#include <wx/control.h>
+#include <wx/pen.h>
+#include <wx/listctrl.h> // for wxListEvent
+
+#ifdef GIZMOISDLL
+#define GIZMODLLEXPORT WXDLLEXPORT
+#else
+#define GIZMODLLEXPORT
+#endif
+
+
+class GIZMODLLEXPORT wxTreeListItem;
+class GIZMODLLEXPORT wxTreeListHeaderWindow;
+class GIZMODLLEXPORT wxTreeListMainWindow;
+
+//-----------------------------------------------------------------------------
+// wxTreeListColumnAttrs
+//-----------------------------------------------------------------------------
+
+enum wxTreeListColumnAlign {
+    wxTL_ALIGN_LEFT,
+    wxTL_ALIGN_RIGHT,
+    wxTL_ALIGN_CENTER
+};
+
+
+class GIZMODLLEXPORT wxTreeListColumnInfo: public wxObject {
+public:
+    enum { DEFAULT_COL_WIDTH = 100 };
+
+    wxTreeListColumnInfo(const wxString &text = wxT(""),
+                         int image = -1,
+                         size_t width = DEFAULT_COL_WIDTH,
+                         bool shown = true,
+                         wxTreeListColumnAlign alignment = wxTL_ALIGN_LEFT)
+    {
+        m_image = image;
+        m_selected_image = -1;
+        m_text = text;
+        m_width = width;
+    	m_shown = shown;
+        m_alignment = alignment;
+    }
+
+    wxTreeListColumnInfo(const wxTreeListColumnInfo& other)
+    {
+        m_image = other.m_image;
+        m_selected_image = other.m_selected_image;
+        m_text = other.m_text;
+        m_width = other.m_width;
+    	m_shown = other.m_shown;
+        m_alignment = other.m_alignment;
+    }
+
+    ~wxTreeListColumnInfo() {}
+
+    // getters
+    bool GetShown() const { return m_shown; }
+    wxTreeListColumnAlign GetAlignment() const { return m_alignment; }
+    wxString GetText() const { return m_text; }
+    int GetImage() const { return m_image; }
+    int GetSelectedImage() const { return m_selected_image; }
+    size_t GetWidth() const { return m_width; }
+
+    // setters
+    wxTreeListColumnInfo& SetShown(bool shown)
+    { m_shown = shown; return *this; }
+
+    wxTreeListColumnInfo& SetAlignment(wxTreeListColumnAlign alignment)
+    { m_alignment = alignment; return *this; }
+
+    wxTreeListColumnInfo& SetText(const wxString& text)
+    { m_text = text; return *this; }
+
+    wxTreeListColumnInfo& SetImage(int image)
+    { m_image = image; return *this; }
+
+    wxTreeListColumnInfo& SetSelectedImage(int image)
+    { m_selected_image = image; return *this; }
+
+    wxTreeListColumnInfo& SetWidth(size_t with)
+    { m_width = with; return *this; }
+
+private:
+    bool m_shown;
+    wxTreeListColumnAlign m_alignment;
+    wxString m_text;
+    int m_image;
+    int m_selected_image;
+    size_t m_width;
+};
+
+//----------------------------------------------------------------------------
+// wxTreeListCtrl - the multicolumn tree control
+//----------------------------------------------------------------------------
+
+// additional flag for HitTest
+const int wxTREE_HITTEST_ONITEMCOLUMN = 0x2000;
+extern GIZMODLLEXPORT const wxChar* wxTreeListCtrlNameStr;
+
+
+class GIZMODLLEXPORT wxTreeListCtrl : public wxControl
+{
+public:
+    // creation
+    // --------
+    wxTreeListCtrl() {}
+
+    wxTreeListCtrl(wxWindow *parent, wxWindowID id = -1,
+               const wxPoint& pos = wxDefaultPosition,
+               const wxSize& size = wxDefaultSize,
+               long style = wxTR_DEFAULT_STYLE,
+               const wxValidator &validator = wxDefaultValidator,
+               const wxString& name = wxTreeListCtrlNameStr )
+        : m_header_win(0), m_main_win(0)
+    {
+        Create(parent, id, pos, size, style, validator, name);
+    }
+
+    virtual ~wxTreeListCtrl() {}
+
+    bool Create(wxWindow *parent, wxWindowID id = -1,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxTR_DEFAULT_STYLE,
+                const wxValidator &validator = wxDefaultValidator,
+                const wxString& name = wxTreeListCtrlNameStr );
+
+    void Refresh(bool erase=TRUE, const wxRect* rect=NULL);
+    void SetFocus();
+    // accessors
+    // ---------
+
+    // get the total number of items in the control
+    size_t GetCount() const;
+
+    // indent is the number of pixels the children are indented relative to
+    // the parents position. SetIndent() also redraws the control
+    // immediately.
+    unsigned int GetIndent() const;
+    void SetIndent(unsigned int indent);
+
+    // line spacing is the space above and below the text on each line
+    unsigned int GetLineSpacing() const;
+    void SetLineSpacing(unsigned int spacing);
+
+    // image list: these functions allow to associate an image list with
+    // the control and retrieve it. Note that when assigned with
+    // SetImageList, the control does _not_ delete
+    // the associated image list when it's deleted in order to allow image
+    // lists to be shared between different controls. If you use
+    // AssignImageList, the control _does_ delete the image list.
+    //
+    // The normal image list is for the icons which correspond to the
+    // normal tree item state (whether it is selected or not).
+    // Additionally, the application might choose to show a state icon
+    // which corresponds to an app-defined item state (for example,
+    // checked/unchecked) which are taken from the state image list.
+    wxImageList *GetImageList() const;
+    wxImageList *GetStateImageList() const;
+    wxImageList *GetButtonsImageList() const;
+
+    void SetImageList(wxImageList *imageList);
+    void SetStateImageList(wxImageList *imageList);
+    void SetButtonsImageList(wxImageList *imageList);
+    void AssignImageList(wxImageList *imageList);
+    void AssignStateImageList(wxImageList *imageList);
+    void AssignButtonsImageList(wxImageList *imageList);
+
+
+    // Functions to work with tree list ctrl columns
+
+    // adds a column
+    void AddColumn(const wxString& text)
+        { AddColumn(wxTreeListColumnInfo(text)); }
+    void AddColumn(const wxString& text,
+                   size_t width,
+                   wxTreeListColumnAlign alignment = wxTL_ALIGN_LEFT)
+        { AddColumn(wxTreeListColumnInfo(text,
+                                         -1,
+                                         width,
+                                         true,
+                                         alignment)); }
+    void AddColumn(const wxTreeListColumnInfo& col);
+
+    // inserts a column before the given one
+    void InsertColumn(size_t before, const wxString& text)
+    { InsertColumn(before, wxTreeListColumnInfo(text)); }
+    void InsertColumn(size_t before, const wxTreeListColumnInfo& col);
+
+    // deletes the given column - does not delete the corresponding column
+    // of each item
+    void RemoveColumn(size_t column);
+
+    // returns the number of columns in the ctrl
+    size_t GetColumnCount() const;
+
+    void SetColumnWidth(size_t column, size_t width);
+    int GetColumnWidth(size_t column) const;
+
+    // tells which column is the "main" one, i.e. the "threaded" one
+    void SetMainColumn(size_t column);
+    size_t GetMainColumn() const;
+
+    void SetColumnText(size_t column, const wxString& text);
+    wxString GetColumnText(size_t column) const;
+
+    void SetColumn(size_t column, const wxTreeListColumnInfo& info);
+    wxTreeListColumnInfo& GetColumn(size_t column);
+    const wxTreeListColumnInfo& GetColumn(size_t column) const;
+
+    // other column-related methods
+    void SetColumnAlignment(size_t column, wxTreeListColumnAlign align);
+    wxTreeListColumnAlign GetColumnAlignment(size_t column) const;
+
+    void SetColumnImage(size_t column, int image);
+    int GetColumnImage(size_t column) const;
+
+    void ShowColumn(size_t column, bool shown);
+    bool IsColumnShown(size_t column) const;
+
+    // Functions to work with tree list ctrl items.
+
+    // accessors
+    // ---------
+
+    // retrieve item's label (of the main column)
+    wxString GetItemText(const wxTreeItemId& item) const
+        { return GetItemText(item, GetMainColumn()); }
+    // retrieves item's label of the given column
+    wxString GetItemText(const wxTreeItemId& item, size_t column) const;
+
+    // get one of the images associated with the item (normal by default)
+    int GetItemImage(const wxTreeItemId& item,
+                     wxTreeItemIcon which = wxTreeItemIcon_Normal) const
+    { return GetItemImage(item, GetMainColumn(), which); }
+    int GetItemImage(const wxTreeItemId& item, size_t column,
+                     wxTreeItemIcon which = wxTreeItemIcon_Normal) const;
+
+    // get the data associated with the item
+    wxTreeItemData *GetItemData(const wxTreeItemId& item) const;
+
+    bool GetItemBold(const wxTreeItemId& item) const;
+    wxColour GetItemTextColour(const wxTreeItemId& item) const;
+    wxColour GetItemBackgroundColour(const wxTreeItemId& item) const;
+    wxFont GetItemFont(const wxTreeItemId& item) const;
+
+    // modifiers
+    // ---------
+
+    // set item's label
+    void SetItemText(const wxTreeItemId& item, const wxString& text)
+    { SetItemText(item, GetMainColumn(), text); }
+    void SetItemText(const wxTreeItemId& item, size_t column,
+                     const wxString& text);
+
+    // get one of the images associated with the item (normal by default)
+    void SetItemImage(const wxTreeItemId& item, int image,
+                      wxTreeItemIcon which = wxTreeItemIcon_Normal)
+    { SetItemImage(item, GetMainColumn(), image, which); }
+    // the which parameter is ignored for all columns but the main one
+    void SetItemImage(const wxTreeItemId& item, size_t column, int image,
+                      wxTreeItemIcon which = wxTreeItemIcon_Normal);
+
+    // associate some data with the item
+    void SetItemData(const wxTreeItemId& item, wxTreeItemData *data);
+
+    // force appearance of [+] button near the item. This is useful to
+    // allow the user to expand the items which don't have any children now
+    // - but instead add them only when needed, thus minimizing memory
+    // usage and loading time.
+    void SetItemHasChildren(const wxTreeItemId& item, bool has = TRUE);
+
+    // the item will be shown in bold
+    void SetItemBold(const wxTreeItemId& item, bool bold = TRUE);
+
+    // set the item's text colour
+    void SetItemTextColour(const wxTreeItemId& item, const wxColour& colour);
+
+    // set the item's background colour
+    void SetItemBackgroundColour(const wxTreeItemId& item, const wxColour& colour);
+
+    // set the item's font (should be of the same height for all items)
+    void SetItemFont(const wxTreeItemId& item, const wxFont& font);
+
+    // set the window font
+    virtual bool SetFont( const wxFont &font );
+
+    // set the styles.
+    void SetWindowStyle(const long styles);
+    long GetWindowStyle() const;
+    long GetWindowStyleFlag() const { return GetWindowStyle(); }
+
+    // item status inquiries
+    // ---------------------
+
+    // is the item visible (it might be outside the view or not expanded)?
+    bool IsVisible(const wxTreeItemId& item) const;
+    // does the item has any children?
+    bool HasChildren(const wxTreeItemId& item) const
+      { return ItemHasChildren(item); }
+    bool ItemHasChildren(const wxTreeItemId& item) const;
+    // is the item expanded (only makes sense if HasChildren())?
+    bool IsExpanded(const wxTreeItemId& item) const;
+    // is this item currently selected (the same as has focus)?
+    bool IsSelected(const wxTreeItemId& item) const;
+    // is item text in bold font?
+    bool IsBold(const wxTreeItemId& item) const;
+    // does the layout include space for a button?
+
+    // number of children
+    // ------------------
+
+    // if 'recursively' is FALSE, only immediate children count, otherwise
+    // the returned number is the number of all items in this branch
+    size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE);
+
+    // navigation
+    // ----------
+
+    // wxTreeItemId.IsOk() will return FALSE if there is no such item
+
+    // get the root tree item
+    wxTreeItemId GetRootItem() const;
+
+    // get the item currently selected (may return NULL if no selection)
+    wxTreeItemId GetSelection() const;
+
+    // get the items currently selected, return the number of such item
+    size_t GetSelections(wxArrayTreeItemIds&) const;
+
+    // get the parent of this item (may return NULL if root)
+    wxTreeItemId GetItemParent(const wxTreeItemId& item) const;
+
+    // for this enumeration function you must pass in a "cookie" parameter
+    // which is opaque for the application but is necessary for the library
+    // to make these functions reentrant (i.e. allow more than one
+    // enumeration on one and the same object simultaneously). Of course,
+    // the "cookie" passed to GetFirstChild() and GetNextChild() should be
+    // the same!
+
+    // get the first child of this item
+    wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const;
+    // get the next child
+    wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const;
+    // get the last child of this item - this method doesn't use cookies
+    wxTreeItemId GetLastChild(const wxTreeItemId& item) const;
+
+    // get the next sibling of this item
+    wxTreeItemId GetNextSibling(const wxTreeItemId& item) const;
+    // get the previous sibling
+    wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const;
+
+    // get first visible item
+    wxTreeItemId GetFirstVisibleItem() const;
+    // get the next visible item: item must be visible itself!
+    // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem()
+    wxTreeItemId GetNextVisible(const wxTreeItemId& item) const;
+    // get the previous visible item: item must be visible itself!
+    wxTreeItemId GetPrevVisible(const wxTreeItemId& item) const;
+
+    // Only for internal use right now, but should probably be public
+    wxTreeItemId GetNext(const wxTreeItemId& item) const;
+
+    // operations
+    // ----------
+
+    // add the root node to the tree
+    wxTreeItemId AddRoot(const wxString& text,
+                         int image = -1, int selectedImage = -1,
+                         wxTreeItemData *data = NULL);
+
+    // insert a new item in as the first child of the parent
+    wxTreeItemId PrependItem(const wxTreeItemId& parent,
+                             const wxString& text,
+                             int image = -1, int selectedImage = -1,
+                             wxTreeItemData *data = NULL);
+
+    // insert a new item after a given one
+    wxTreeItemId InsertItem(const wxTreeItemId& parent,
+                            const wxTreeItemId& idPrevious,
+                            const wxString& text,
+                            int image = -1, int selectedImage = -1,
+                            wxTreeItemData *data = NULL);
+
+    // insert a new item before the one with the given index
+    wxTreeItemId InsertItem(const wxTreeItemId& parent,
+                            size_t index,
+                            const wxString& text,
+                            int image = -1, int selectedImage = -1,
+                            wxTreeItemData *data = NULL);
+
+    // insert a new item in as the last child of the parent
+    wxTreeItemId AppendItem(const wxTreeItemId& parent,
+                            const wxString& text,
+                            int image = -1, int selectedImage = -1,
+                            wxTreeItemData *data = NULL);
+
+    // delete this item and associated data if any
+    void Delete(const wxTreeItemId& item);
+    // delete all children (but don't delete the item itself)
+    // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
+    void DeleteChildren(const wxTreeItemId& item);
+    // delete all items from the tree
+    // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
+    void DeleteAllItems();
+
+    // expand this item
+    void Expand(const wxTreeItemId& item);
+    // expand this item and all subitems recursively
+    void ExpandAll(const wxTreeItemId& item);
+    // collapse the item without removing its children
+    void Collapse(const wxTreeItemId& item);
+    // collapse the item and remove all children
+    void CollapseAndReset(const wxTreeItemId& item);
+    // toggles the current state
+    void Toggle(const wxTreeItemId& item);
+
+    // remove the selection from currently selected item (if any)
+    void Unselect();
+    void UnselectAll();
+    // select this item
+    void SelectItem(const wxTreeItemId& item, bool unselect_others=TRUE,
+                    bool extended_select=FALSE);
+    // make sure this item is visible (expanding the parent item and/or
+    // scrolling to this item if necessary)
+    void EnsureVisible(const wxTreeItemId& item);
+    // scroll to this item (but don't expand its parent)
+    void ScrollTo(const wxTreeItemId& item);
+    //void AdjustMyScrollbars();
+
+    // The first function is more portable (because easier to implement
+    // on other platforms), but the second one returns some extra info.
+    wxTreeItemId HitTest(const wxPoint& point)
+        { int dummy; return HitTest(point, dummy); }
+    wxTreeItemId HitTest(const wxPoint& point, int& flags)
+    { int col; return HitTest(point, flags, col); }
+    wxTreeItemId HitTest(const wxPoint& point, int& flags, int& column);
+
+    // get the bounding rectangle of the item (or of its label only)
+    bool GetBoundingRect(const wxTreeItemId& item,
+                         wxRect& rect,
+                         bool textOnly = FALSE) const;
+
+    // Start editing the item label: this (temporarily) replaces the item
+    // with a one line edit control. The item will be selected if it hadn't
+    // been before.
+    void EditLabel( const wxTreeItemId& item ) { Edit( item ); }
+    void Edit( const wxTreeItemId& item );
+
+    // sorting
+    // this function is called to compare 2 items and should return -1, 0
+    // or +1 if the first item is less than, equal to or greater than the
+    // second one. The base class version performs alphabetic comparaison
+    // of item labels (GetText)
+    virtual int OnCompareItems(const wxTreeItemId& item1,
+                               const wxTreeItemId& item2);
+    // sort the children of this item using OnCompareItems
+    //
+    // NB: this function is not reentrant and not MT-safe (FIXME)!
+    void SortChildren(const wxTreeItemId& item);
+
+    // overridden base class virtuals
+    virtual bool SetBackgroundColour(const wxColour& colour);
+    virtual bool SetForegroundColour(const wxColour& colour);
+
+
+    wxTreeListHeaderWindow* GetHeaderWindow() const
+    { return m_header_win; }
+
+    wxTreeListMainWindow* GetMainWindow() const
+    { return m_main_win; }
+
+protected:
+    // header window, responsible for column visualization and manipulation
+    wxTreeListHeaderWindow* m_header_win;
+    // main window, the "true" tree ctrl
+    wxTreeListMainWindow*   m_main_win;
+
+//     // the common part of all ctors
+//     void Init();
+
+    void OnSize(wxSizeEvent& event);
+
+
+private:
+    size_t fill_column;
+
+    DECLARE_EVENT_TABLE()
+    DECLARE_DYNAMIC_CLASS(wxTreeListCtrl)
+};
+
+#endif // TREELISTCTRL_H
+
diff --git a/contrib/src/gizmos/treelistctrl.cpp b/contrib/src/gizmos/treelistctrl.cpp
new file mode 100644
index 0000000000..bee20336b4
--- /dev/null
+++ b/contrib/src/gizmos/treelistctrl.cpp
@@ -0,0 +1,4804 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        treelistctrl.cpp (derived by treectlg.h)
+// Purpose:     multi column tree control implementation
+// Author:      Robert Roebling
+// Created:     01/02/97
+// Modified:    Alberto Griggio, 2002
+//              22/10/98 - almost total rewrite, simpler interface (VZ)
+// Id:          $Id$
+// Copyright:   (c) Robert Roebling, Julian Smart, Alberto Griggio,
+//              Vadim Zeitlin, Otto Wyss
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ===========================================================================
+// declarations
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// headers
+// ---------------------------------------------------------------------------
+
+#if defined(__GNUG__) && !defined(__APPLE__)
+  #pragma implementation "treelistctrl.h"
+#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+    #pragma hdrstop
+#endif
+
+
+#include <wx/treebase.h>
+#include <wx/timer.h>
+#include <wx/textctrl.h>
+#include <wx/imaglist.h>
+#include <wx/settings.h>
+#include <wx/dcclient.h>
+#include <wx/dcscreen.h>
+#include <wx/scrolwin.h>
+
+#include "wx/gizmos/treelistctrl.h"
+//#include "treelistctrl.h"
+
+
+#ifdef __WXGTK__
+    #include <gtk/gtk.h>
+    #include <wx/gtk/win_gtk.h>
+#endif
+
+// ---------------------------------------------------------------------------
+// array types
+// ---------------------------------------------------------------------------
+
+class  wxTreeListItem;
+
+WX_DEFINE_ARRAY(wxTreeListItem *, wxArrayTreeListItems);
+
+#include <wx/dynarray.h>
+WX_DECLARE_OBJARRAY(wxTreeListColumnInfo, wxArrayTreeListColumnInfo);
+#include <wx/arrimpl.cpp>
+WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo);
+
+#if !wxCHECK_VERSION(2, 3, 3)
+WX_DEFINE_ARRAY(short, wxArrayShort);
+#endif
+
+
+// --------------------------------------------------------------------------
+// constants
+// --------------------------------------------------------------------------
+
+static const int NO_IMAGE = -1;
+
+const int LINEHEIGHT = 10;
+const int PIXELS_PER_UNIT = 10;
+const int LINEATROOT = 5;
+const int MARGIN = 2;
+const int MININDENT = 10;
+const int BTNWIDTH = 11;
+const int BTNHEIGHT = 11;
+
+const wxChar* wxTreeListCtrlNameStr = wxT("treelistctrl");
+
+static wxTreeListColumnInfo wxInvalidTreeListColumnInfo;
+
+
+// ---------------------------------------------------------------------------
+// private classes
+// ---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//  wxTreeListHeaderWindow (internal)
+//-----------------------------------------------------------------------------
+
+class  wxTreeListHeaderWindow : public wxWindow
+{
+protected:
+    wxTreeListMainWindow    *m_owner;
+    wxCursor          *m_currentCursor;
+    wxCursor          *m_resizeCursor;
+    bool               m_isDragging;
+
+    // column being resized
+    int m_column;
+
+    // divider line position in logical (unscrolled) coords
+    int m_currentX;
+
+    // minimal position beyond which the divider line can't be dragged in
+    // logical coords
+    int m_minX;
+
+    wxArrayTreeListColumnInfo m_columns;
+
+    // total width of the columns
+    int m_total_col_width;
+
+
+public:
+    wxTreeListHeaderWindow();
+
+    wxTreeListHeaderWindow( wxWindow *win,
+                        wxWindowID id,
+                        wxTreeListMainWindow *owner,
+                        const wxPoint &pos = wxDefaultPosition,
+                        const wxSize &size = wxDefaultSize,
+                        long style = 0,
+                        const wxString &name = wxT("wxtreelistctrlcolumntitles") );
+
+    virtual ~wxTreeListHeaderWindow();
+
+    void DoDrawRect( wxDC *dc, int x, int y, int w, int h );
+    void DrawCurrent();
+    void AdjustDC(wxDC& dc);
+
+    void OnPaint( wxPaintEvent &event );
+    void OnMouse( wxMouseEvent &event );
+    void OnSetFocus( wxFocusEvent &event );
+
+
+    // columns manipulation
+
+    size_t GetColumnCount() const { return m_columns.GetCount(); }
+
+    void AddColumn(const wxTreeListColumnInfo& col);
+
+    void InsertColumn(size_t before, const wxTreeListColumnInfo& col);
+
+    void RemoveColumn(size_t column);
+
+    void SetColumn(size_t column, const wxTreeListColumnInfo& info);
+    const wxTreeListColumnInfo& GetColumn(size_t column) const
+    {
+        wxCHECK_MSG(column < GetColumnCount(), wxInvalidTreeListColumnInfo, wxT("Invalid column"));
+        return m_columns[column];
+    }
+    wxTreeListColumnInfo& GetColumn(size_t column)
+    {
+        wxCHECK_MSG(column < GetColumnCount(), wxInvalidTreeListColumnInfo, wxT("Invalid column"));
+        return m_columns[column];
+    }
+
+    void SetColumnWidth(size_t column, size_t width);
+
+    void SetColumnText(size_t column, const wxString& text)
+    {
+        wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column"));
+        m_columns[column].SetText(text);
+    }
+
+    void SetColumnShown(size_t column, bool shown)
+    {
+        wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column"));
+        m_columns[column].SetShown(shown);
+    }
+
+    wxString GetColumnText(size_t column) const
+    {
+        wxCHECK_MSG(column < GetColumnCount(), wxEmptyString, wxT("Invalid column"));
+        return m_columns[column].GetText();
+    }
+
+    int GetColumnWidth(size_t column) const
+    {
+        wxCHECK_MSG(column < GetColumnCount(), -1, wxT("Invalid column"));
+        return m_columns[column].GetWidth();
+    }
+
+    int GetWidth() const { return m_total_col_width; }
+
+    int GetColumnShown(size_t column) const
+    {
+        wxCHECK_MSG(column < GetColumnCount(), -1, wxT("Invalid column"));
+        return m_columns[column].GetShown();
+    }
+
+    // needs refresh
+    bool m_dirty;
+
+private:
+    // common part of all ctors
+    void Init();
+
+    void SendListEvent(wxEventType type, wxPoint pos);
+
+    DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow)
+    DECLARE_EVENT_TABLE()
+};
+
+
+// this is the "true" control
+class  wxTreeListMainWindow: public wxScrolledWindow
+{
+public:
+    // creation
+    // --------
+    wxTreeListMainWindow() { Init(); }
+
+    wxTreeListMainWindow(wxTreeListCtrl *parent, wxWindowID id = -1,
+               const wxPoint& pos = wxDefaultPosition,
+               const wxSize& size = wxDefaultSize,
+               long style = wxTR_DEFAULT_STYLE,
+               const wxValidator &validator = wxDefaultValidator,
+               const wxString& name = wxT("wxtreelistmainwindow"))
+    {
+        Init();
+        Create(parent, id, pos, size, style, validator, name);
+    }
+
+    virtual ~wxTreeListMainWindow();
+
+    bool Create(wxTreeListCtrl *parent, wxWindowID id = -1,
+                const wxPoint& pos = wxDefaultPosition,
+                const wxSize& size = wxDefaultSize,
+                long style = wxTR_DEFAULT_STYLE,
+                const wxValidator &validator = wxDefaultValidator,
+                const wxString& name = wxT("wxtreelistctrl"));
+
+    // accessors
+    // ---------
+
+        // get the total number of items in the control
+    size_t GetCount() const;
+
+        // indent is the number of pixels the children are indented relative to
+        // the parents position. SetIndent() also redraws the control
+        // immediately.
+    unsigned int GetIndent() const { return m_indent; }
+    void SetIndent(unsigned int indent);
+
+    // see wxTreeListCtrl for the meaning
+    unsigned int GetLineSpacing() const { return m_linespacing; }
+    void SetLineSpacing(unsigned int spacing);
+
+        // image list: these functions allow to associate an image list with
+        // the control and retrieve it. Note that when assigned with
+        // SetImageList, the control does _not_ delete
+        // the associated image list when it's deleted in order to allow image
+        // lists to be shared between different controls. If you use
+        // AssignImageList, the control _does_ delete the image list.
+        //
+        // The normal image list is for the icons which correspond to the
+        // normal tree item state (whether it is selected or not).
+        // Additionally, the application might choose to show a state icon
+        // which corresponds to an app-defined item state (for example,
+        // checked/unchecked) which are taken from the state image list.
+    wxImageList *GetImageList() const;
+    wxImageList *GetStateImageList() const;
+    wxImageList *GetButtonsImageList() const;
+
+    void SetImageList(wxImageList *imageList);
+    void SetStateImageList(wxImageList *imageList);
+    void SetButtonsImageList(wxImageList *imageList);
+    void AssignImageList(wxImageList *imageList);
+    void AssignStateImageList(wxImageList *imageList);
+    void AssignButtonsImageList(wxImageList *imageList);
+
+    // Functions to work with tree ctrl items.
+
+    // accessors
+    // ---------
+
+        // retrieve item's label
+    wxString GetItemText(const wxTreeItemId& item) const
+    { return GetItemText(item, GetMainColumn()); }
+        // get one of the images associated with the item (normal by default)
+    int GetItemImage(const wxTreeItemId& item,
+                     wxTreeItemIcon which = wxTreeItemIcon_Normal) const
+    { return GetItemImage(item, GetMainColumn(), which); }
+
+        // get the data associated with the item
+    wxTreeItemData *GetItemData(const wxTreeItemId& item) const;
+
+    bool GetItemBold(const wxTreeItemId& item) const;
+    wxColour GetItemTextColour(const wxTreeItemId& item) const;
+    wxColour GetItemBackgroundColour(const wxTreeItemId& item) const;
+    wxFont GetItemFont(const wxTreeItemId& item) const;
+
+    // modifiers
+    // ---------
+
+        // set item's label
+    void SetItemText(const wxTreeItemId& item, const wxString& text)
+    { SetItemText(item, GetMainColumn(), text); }
+
+        // get one of the images associated with the item (normal by default)
+    void SetItemImage(const wxTreeItemId& item, int image,
+                      wxTreeItemIcon which = wxTreeItemIcon_Normal)
+    { SetItemImage(item, GetMainColumn(), image, which); }
+
+        // associate some data with the item
+    void SetItemData(const wxTreeItemId& item, wxTreeItemData *data);
+
+        // force appearance of [+] button near the item. This is useful to
+        // allow the user to expand the items which don't have any children now
+        // - but instead add them only when needed, thus minimizing memory
+        // usage and loading time.
+    void SetItemHasChildren(const wxTreeItemId& item, bool has = TRUE);
+
+        // the item will be shown in bold
+    void SetItemBold(const wxTreeItemId& item, bool bold = TRUE);
+
+        // set the item's text colour
+    void SetItemTextColour(const wxTreeItemId& item, const wxColour& colour);
+
+        // set the item's background colour
+    void SetItemBackgroundColour(const wxTreeItemId& item, const wxColour& colour);
+
+        // set the item's font (should be of the same height for all items)
+    void SetItemFont(const wxTreeItemId& item, const wxFont& font);
+
+        // set the window font
+    virtual bool SetFont( const wxFont &font );
+
+       // set the styles.  No need to specify a GetWindowStyle here since
+       // the base wxWindow member function will do it for us
+    void SetWindowStyle(const long styles);
+
+    // item status inquiries
+    // ---------------------
+
+        // is the item visible (it might be outside the view or not expanded)?
+    bool IsVisible(const wxTreeItemId& item) const;
+        // does the item has any children?
+    bool HasChildren(const wxTreeItemId& item) const
+      { return ItemHasChildren(item); }
+    bool ItemHasChildren(const wxTreeItemId& item) const;
+        // is the item expanded (only makes sense if HasChildren())?
+    bool IsExpanded(const wxTreeItemId& item) const;
+        // is this item currently selected (the same as has focus)?
+    bool IsSelected(const wxTreeItemId& item) const;
+        // is item text in bold font?
+    bool IsBold(const wxTreeItemId& item) const;
+        // does the layout include space for a button?
+
+    // number of children
+    // ------------------
+
+        // if 'recursively' is FALSE, only immediate children count, otherwise
+        // the returned number is the number of all items in this branch
+    size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE);
+
+    // navigation
+    // ----------
+
+    // wxTreeItemId.IsOk() will return FALSE if there is no such item
+
+        // get the root tree item
+    wxTreeItemId GetRootItem() const { return m_anchor; }
+
+        // get the item currently selected (may return NULL if no selection)
+    wxTreeItemId GetSelection() const { return m_current; }
+
+        // get the items currently selected, return the number of such item
+    size_t GetSelections(wxArrayTreeItemIds&) const;
+
+        // get the parent of this item (may return NULL if root)
+    wxTreeItemId GetItemParent(const wxTreeItemId& item) const;
+
+        // for this enumeration function you must pass in a "cookie" parameter
+        // which is opaque for the application but is necessary for the library
+        // to make these functions reentrant (i.e. allow more than one
+        // enumeration on one and the same object simultaneously). Of course,
+        // the "cookie" passed to GetFirstChild() and GetNextChild() should be
+        // the same!
+
+        // get the first child of this item
+    wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const;
+        // get the next child
+    wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const;
+        // get the last child of this item - this method doesn't use cookies
+    wxTreeItemId GetLastChild(const wxTreeItemId& item) const;
+
+        // get the next sibling of this item
+    wxTreeItemId GetNextSibling(const wxTreeItemId& item) const;
+        // get the previous sibling
+    wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const;
+
+        // get first visible item
+    wxTreeItemId GetFirstVisibleItem() const;
+        // get the next visible item: item must be visible itself!
+        // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem()
+    wxTreeItemId GetNextVisible(const wxTreeItemId& item) const;
+        // get the previous visible item: item must be visible itself!
+    wxTreeItemId GetPrevVisible(const wxTreeItemId& item) const;
+
+        // Only for internal use right now, but should probably be public
+    wxTreeItemId GetNext(const wxTreeItemId& item) const;
+
+    // operations
+    // ----------
+
+        // add the root node to the tree
+    wxTreeItemId AddRoot(const wxString& text,
+                         int image = -1, int selectedImage = -1,
+                         wxTreeItemData *data = NULL);
+
+        // insert a new item in as the first child of the parent
+    wxTreeItemId PrependItem(const wxTreeItemId& parent,
+                             const wxString& text,
+                             int image = -1, int selectedImage = -1,
+                             wxTreeItemData *data = NULL);
+
+        // insert a new item after a given one
+    wxTreeItemId InsertItem(const wxTreeItemId& parent,
+                            const wxTreeItemId& idPrevious,
+                            const wxString& text,
+                            int image = -1, int selectedImage = -1,
+                            wxTreeItemData *data = NULL);
+
+        // insert a new item before the one with the given index
+    wxTreeItemId InsertItem(const wxTreeItemId& parent,
+                            size_t index,
+                            const wxString& text,
+                            int image = -1, int selectedImage = -1,
+                            wxTreeItemData *data = NULL);
+
+        // insert a new item in as the last child of the parent
+    wxTreeItemId AppendItem(const wxTreeItemId& parent,
+                            const wxString& text,
+                            int image = -1, int selectedImage = -1,
+                            wxTreeItemData *data = NULL);
+
+        // delete this item and associated data if any
+    void Delete(const wxTreeItemId& item);
+        // delete all children (but don't delete the item itself)
+        // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
+    void DeleteChildren(const wxTreeItemId& item);
+        // delete all items from the tree
+        // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
+    void DeleteAllItems();
+
+        // expand this item
+    void Expand(const wxTreeItemId& item);
+        // expand this item and all subitems recursively
+    void ExpandAll(const wxTreeItemId& item);
+        // collapse the item without removing its children
+    void Collapse(const wxTreeItemId& item);
+        // collapse the item and remove all children
+    void CollapseAndReset(const wxTreeItemId& item);
+        // toggles the current state
+    void Toggle(const wxTreeItemId& item);
+
+        // remove the selection from currently selected item (if any)
+    void Unselect();
+    void UnselectAll();
+        // select this item
+    void SelectItem(const wxTreeItemId& item, bool unselect_others=TRUE,
+                    bool extended_select=FALSE);
+        // make sure this item is visible (expanding the parent item and/or
+        // scrolling to this item if necessary)
+    void EnsureVisible(const wxTreeItemId& item);
+        // scroll to this item (but don't expand its parent)
+    void ScrollTo(const wxTreeItemId& item);
+    void AdjustMyScrollbars();
+
+        // The first function is more portable (because easier to implement
+        // on other platforms), but the second one returns some extra info.
+    wxTreeItemId HitTest(const wxPoint& point)
+        { int dummy; return HitTest(point, dummy); }
+    wxTreeItemId HitTest(const wxPoint& point, int& flags)
+    { int col; return HitTest(point, flags, col); }
+    // ALB
+    wxTreeItemId HitTest(const wxPoint& point, int& flags, int& column);
+
+
+        // get the bounding rectangle of the item (or of its label only)
+    bool GetBoundingRect(const wxTreeItemId& item,
+                         wxRect& rect,
+                         bool textOnly = FALSE) const;
+
+        // Start editing the item label: this (temporarily) replaces the item
+        // with a one line edit control. The item will be selected if it hadn't
+        // been before.
+    void EditLabel( const wxTreeItemId& item ) { Edit( item ); }
+    void Edit( const wxTreeItemId& item );
+
+    // sorting
+        // this function is called to compare 2 items and should return -1, 0
+        // or +1 if the first item is less than, equal to or greater than the
+        // second one. The base class version performs alphabetic comparaison
+        // of item labels (GetText)
+    virtual int OnCompareItems(const wxTreeItemId& item1,
+                               const wxTreeItemId& item2);
+        // sort the children of this item using OnCompareItems
+        //
+        // NB: this function is not reentrant and not MT-safe (FIXME)!
+    void SortChildren(const wxTreeItemId& item);
+
+    // deprecated functions: use Set/GetItemImage directly
+        // get the selected item image
+    int GetItemSelectedImage(const wxTreeItemId& item) const
+        { return GetItemImage(item, wxTreeItemIcon_Selected); }
+        // set the selected item image
+    void SetItemSelectedImage(const wxTreeItemId& item, int image)
+        { SetItemImage(item, image, wxTreeItemIcon_Selected); }
+
+    // implementation only from now on
+
+    // overridden base class virtuals
+    virtual bool SetBackgroundColour(const wxColour& colour);
+    virtual bool SetForegroundColour(const wxColour& colour);
+
+    // callbacks
+    void OnPaint( wxPaintEvent &event );
+    void OnSetFocus( wxFocusEvent &event );
+    void OnKillFocus( wxFocusEvent &event );
+    void OnChar( wxKeyEvent &event );
+    void OnMouse( wxMouseEvent &event );
+    void OnIdle( wxIdleEvent &event );
+    void OnSize(wxSizeEvent& event); // ALB
+    void OnScroll(wxScrollWinEvent& event); // ALB
+
+    // implementation helpers
+    void SendDeleteEvent(wxTreeListItem *itemBeingDeleted);
+
+    void DrawBorder(const wxTreeItemId& item);
+    void DrawLine(const wxTreeItemId& item, bool below);
+
+    size_t GetColumnCount() const
+    { return m_owner->GetHeaderWindow()->GetColumnCount(); }
+
+    void SetMainColumn(size_t column)
+    {
+        if(column < GetColumnCount())
+            m_main_column = column;
+    }
+    size_t GetMainColumn() const { return m_main_column; }
+
+    void SetItemText(const wxTreeItemId& item, size_t column,
+                     const wxString& text);
+    wxString GetItemText(const wxTreeItemId& item, size_t column) const;
+
+    void SetItemImage(const wxTreeItemId& item, size_t column, int image,
+                      wxTreeItemIcon which = wxTreeItemIcon_Normal);
+    int GetItemImage(const wxTreeItemId& item, size_t column,
+                     wxTreeItemIcon which = wxTreeItemIcon_Normal) const;
+protected:
+    wxTreeListCtrl* m_owner; // ALB
+
+    size_t m_main_column; // ALB
+
+    friend class wxTreeListItem;
+    friend class wxTreeListRenameTimer;
+    friend class wxTreeListTextCtrl;
+
+    wxFont               m_normalFont;
+    wxFont               m_boldFont;
+
+    wxTreeListItem   *m_anchor;
+    wxTreeListItem   *m_current, *m_key_current, *m_currentEdit;
+    int                  m_btnWidth, m_btnWidth2;
+    int                  m_btnHeight, m_btnHeight2;
+    int                  m_imgWidth, m_imgWidth2;
+    int                  m_imgHeight, m_imgHeight2;
+    unsigned short       m_indent;
+    int                  m_lineHeight;
+    unsigned short       m_linespacing;
+    wxPen                m_dottedPen;
+    wxBrush             *m_hilightBrush,
+                        *m_hilightUnfocusedBrush;
+    bool                 m_hasFocus;
+public:
+    bool                 m_dirty;
+protected:
+    bool                 m_ownsImageListNormal,
+                         m_ownsImageListState,
+                         m_ownsImageListButtons;
+    bool                 m_isDragging; // true between BEGIN/END drag events
+    bool                 m_renameAccept;
+    bool                 m_lastOnSame;  // last click on the same item as prev
+    wxImageList         *m_imageListNormal,
+                        *m_imageListState,
+                        *m_imageListButtons;
+
+    int                  m_dragCount;
+    wxPoint              m_dragStart;
+    wxTreeListItem   *m_dropTarget;
+    wxCursor             m_oldCursor;  // cursor is changed while dragging
+    wxTreeListItem   *m_oldSelection;
+
+    wxTimer             *m_renameTimer;
+    wxString             m_renameRes;
+
+    // the common part of all ctors
+    void Init();
+
+    // misc helpers
+    wxTreeItemId DoInsertItem(const wxTreeItemId& parent,
+                              size_t previous,
+                              const wxString& text,
+                              int image, int selectedImage,
+                              wxTreeItemData *data);
+    bool HasButtons(void) const
+        { return (m_imageListButtons != NULL) ||
+                  HasFlag (wxTR_TWIST_BUTTONS|wxTR_HAS_BUTTONS); }
+
+protected:
+    void CalculateLineHeight();
+    int  GetLineHeight(wxTreeListItem *item) const;
+    void PaintLevel( wxTreeListItem *item, wxDC& dc, int level, int &y,
+                     int x_colstart);
+    void PaintItem( wxTreeListItem *item, wxDC& dc);
+
+    void CalculateLevel( wxTreeListItem *item, wxDC &dc, int level, int &y,
+                         int x_colstart);
+    void CalculatePositions();
+    void CalculateSize( wxTreeListItem *item, wxDC &dc );
+
+    void RefreshSubtree( wxTreeListItem *item );
+    void RefreshLine( wxTreeListItem *item );
+
+    // redraw all selected items
+    void RefreshSelected();
+
+    // RefreshSelected() recursive helper
+    void RefreshSelectedUnder(wxTreeListItem *item);
+
+    void OnRenameTimer();
+    void OnRenameAccept();
+
+    void FillArray(wxTreeListItem*, wxArrayTreeItemIds&) const;
+    void SelectItemRange( wxTreeListItem *item1, wxTreeListItem *item2 );
+    bool TagAllChildrenUntilLast(wxTreeListItem *crt_item,
+                                 wxTreeListItem *last_item, bool select);
+    bool TagNextChildren(wxTreeListItem *crt_item, wxTreeListItem *last_item,
+                         bool select);
+    void UnselectAllChildren( wxTreeListItem *item );
+
+    void DrawDropEffect(wxTreeListItem *item);
+
+private:
+    DECLARE_EVENT_TABLE()
+    DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow)
+};
+
+
+// timer used for enabling in-place edit
+class  wxTreeListRenameTimer: public wxTimer
+{
+public:
+    wxTreeListRenameTimer( wxTreeListMainWindow *owner );
+
+    void Notify();
+
+private:
+    wxTreeListMainWindow   *m_owner;
+};
+
+// control used for in-place edit
+class  wxTreeListTextCtrl: public wxTextCtrl
+{
+public:
+    wxTreeListTextCtrl( wxWindow *parent,
+                        const wxWindowID id,
+                        bool *accept,
+                        wxString *res,
+                        wxTreeListMainWindow *owner,
+                        const wxString &value = wxEmptyString,
+                        const wxPoint &pos = wxDefaultPosition,
+                        const wxSize &size = wxDefaultSize,
+                        int style = wxSIMPLE_BORDER,
+                        const wxValidator& validator = wxDefaultValidator,
+                        const wxString &name = wxTextCtrlNameStr );
+
+    void OnChar( wxKeyEvent &event );
+    void OnKeyUp( wxKeyEvent &event );
+    void OnKillFocus( wxFocusEvent &event );
+
+private:
+    bool               *m_accept;
+    wxString           *m_res;
+    wxTreeListMainWindow  *m_owner;
+    wxString            m_startValue;
+    bool                m_finished;
+
+    DECLARE_EVENT_TABLE()
+};
+
+// a tree item
+class  wxTreeListItem
+{
+public:
+    // ctors & dtor
+    wxTreeListItem() { m_data = NULL; }
+    wxTreeListItem( wxTreeListMainWindow *owner,
+                    wxTreeListItem *parent,
+                    const wxArrayString& text,
+                    int image,
+                    int selImage,
+                    wxTreeItemData *data );
+
+    ~wxTreeListItem();
+
+    // trivial accessors
+    wxArrayTreeListItems& GetChildren() { return m_children; }
+
+    const wxString GetText() const
+    {
+        if(m_text.GetCount() > 0) return m_text[0];
+        return wxEmptyString;
+    }
+    const wxString GetText(size_t col) const
+    {
+        if(m_text.GetCount() > col) return m_text[col];
+        return wxEmptyString;
+    }
+    int GetImage(wxTreeItemIcon which = wxTreeItemIcon_Normal) const
+        { return m_images[which]; }
+    int GetImage(size_t col, wxTreeItemIcon which=wxTreeItemIcon_Normal) const
+    {
+        if(col == m_owner->GetMainColumn()) return m_images[which];
+        if(col < m_col_images.GetCount()) return m_col_images[col];
+        return NO_IMAGE;
+    }
+    wxTreeItemData *GetData() const { return m_data; }
+
+    // returns the current image for the item (depending on its
+    // selected/expanded/whatever state)
+    int GetCurrentImage() const;
+
+    void SetText( const wxString &text );
+    void SetText(size_t col, const wxString& text) // ALB
+    {
+        if(col < m_text.GetCount())
+            m_text[col] = text;
+        else if(col < m_owner->GetColumnCount()) {
+            int howmany = m_owner->GetColumnCount();
+            for(int i = m_text.GetCount(); i < howmany; ++i)
+                m_text.Add(wxEmptyString);
+            m_text[col] = text;
+        }
+    }
+    void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; }
+    void SetImage(size_t col, int image, wxTreeItemIcon which)
+    {
+        if(col == m_owner->GetMainColumn()) m_images[which] = image;
+        else if(col < m_col_images.GetCount())
+            m_col_images[col] = image;
+        else if(col < m_owner->GetColumnCount()) {
+            int howmany = m_owner->GetColumnCount();
+            for(int i = m_col_images.GetCount(); i < howmany; ++i)
+                m_col_images.Add(NO_IMAGE);
+            m_col_images[col] = image;
+        }
+    }
+
+    void SetData(wxTreeItemData *data) { m_data = data; }
+
+    void SetHasPlus(bool has = TRUE) { m_hasPlus = has; }
+
+    void SetBold(bool bold) { m_isBold = bold; }
+
+    int GetX() const { return m_x; }
+    int GetY() const { return m_y; }
+
+    void SetX(int x) { m_x = x; }
+    void SetY(int y) { m_y = y; }
+
+    int  GetHeight() const { return m_height; }
+    int  GetWidth()  const { return m_width; }
+
+    void SetHeight(int h) { m_height = h; }
+    void SetWidth(int w) { m_width = w; }
+
+    wxTreeListItem *GetItemParent() const { return m_parent; }
+
+    // operations
+        // deletes all children notifying the treectrl about it if !NULL
+        // pointer given
+    void DeleteChildren(wxTreeListMainWindow *tree = NULL);
+
+    // get count of all children (and grand children if 'recursively')
+    size_t GetChildrenCount(bool recursively = TRUE) const;
+
+    void Insert(wxTreeListItem *child, size_t index)
+    { m_children.Insert(child, index); }
+
+    void GetSize( int &x, int &y, const wxTreeListMainWindow* );
+
+        // return the item at given position (or NULL if no item), onButton is
+        // TRUE if the point belongs to the item's button, otherwise it lies
+        // on the button's label
+    wxTreeListItem *HitTest( const wxPoint& point,
+                             const wxTreeListMainWindow *,
+                             int &flags,
+                             int level );
+    wxTreeListItem *HitTest( const wxPoint& point,
+                             const wxTreeListMainWindow *,
+                             int &flags, int& column /*ALB*/,
+                             int level );
+
+    void Expand() { m_isCollapsed = FALSE; }
+    void Collapse() { m_isCollapsed = TRUE; }
+
+    void SetHilight( bool set = TRUE ) { m_hasHilight = set; }
+
+    // status inquiries
+    bool HasChildren() const { return !m_children.IsEmpty(); }
+    bool IsSelected()  const { return m_hasHilight != 0; }
+    bool IsExpanded()  const { return !m_isCollapsed; }
+    bool HasPlus()     const { return m_hasPlus || HasChildren(); }
+    bool IsBold()      const { return m_isBold != 0; }
+
+    // attributes
+        // get them - may be NULL
+    wxTreeItemAttr *GetAttributes() const { return m_attr; }
+        // get them ensuring that the pointer is not NULL
+    wxTreeItemAttr& Attr()
+    {
+        if ( !m_attr )
+        {
+            m_attr = new wxTreeItemAttr;
+            m_ownsAttr = TRUE;
+        }
+        return *m_attr;
+    }
+        // set them
+    void SetAttributes(wxTreeItemAttr *attr)
+    {
+        if ( m_ownsAttr ) delete m_attr;
+        m_attr = attr;
+        m_ownsAttr = FALSE;
+    }
+        // set them and delete when done
+    void AssignAttributes(wxTreeItemAttr *attr)
+    {
+        SetAttributes(attr);
+        m_ownsAttr = TRUE;
+    }
+
+private:
+    wxTreeListMainWindow  *m_owner;        // control the item belongs to
+
+    // since there can be very many of these, we save size by chosing
+    // the smallest representation for the elements and by ordering
+    // the members to avoid padding.
+    wxArrayString      m_text;    // labels to be rendered for item
+
+    wxTreeItemData     *m_data;         // user-provided data
+
+    wxArrayTreeListItems m_children; // list of children
+    wxTreeListItem  *m_parent;       // parent of this item
+
+    wxTreeItemAttr     *m_attr;         // attributes???
+
+    // tree ctrl images for the normal, selected, expanded and
+    // expanded+selected states
+    short               m_images[wxTreeItemIcon_Max];
+    wxArrayShort m_col_images; // images for the various columns (!= main)
+
+    wxCoord             m_x;            // (virtual) offset from top
+    wxCoord             m_y;            // (virtual) offset from left
+    short               m_width;        // width of this item
+    unsigned char       m_height;       // height of this item
+
+    // use bitfields to save size
+    int                 m_isCollapsed :1;
+    int                 m_hasHilight  :1; // same as focused
+    int                 m_hasPlus     :1; // used for item which doesn't have
+                                          // children but has a [+] button
+    int                 m_isBold      :1; // render the label in bold font
+    int                 m_ownsAttr    :1; // delete attribute when done
+};
+
+// ===========================================================================
+// implementation
+// ===========================================================================
+
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+// translate the key or mouse event flags to the type of selection we're
+// dealing with
+static void EventFlagsToSelType(long style,
+                                bool shiftDown,
+                                bool ctrlDown,
+                                bool &is_multiple,
+                                bool &extended_select,
+                                bool &unselect_others)
+{
+    is_multiple = (style & wxTR_MULTIPLE) != 0;
+    extended_select = shiftDown && is_multiple;
+    unselect_others = !(extended_select || (ctrlDown && is_multiple));
+}
+
+// ---------------------------------------------------------------------------
+// wxTreeListRenameTimer (internal)
+// ---------------------------------------------------------------------------
+
+wxTreeListRenameTimer::wxTreeListRenameTimer( wxTreeListMainWindow *owner )
+{
+    m_owner = owner;
+}
+
+void wxTreeListRenameTimer::Notify()
+{
+    m_owner->OnRenameTimer();
+}
+
+//-----------------------------------------------------------------------------
+// wxTreeListTextCtrl (internal)
+//-----------------------------------------------------------------------------
+
+BEGIN_EVENT_TABLE(wxTreeListTextCtrl,wxTextCtrl)
+    EVT_CHAR           (wxTreeListTextCtrl::OnChar)
+    EVT_KEY_UP         (wxTreeListTextCtrl::OnKeyUp)
+    EVT_KILL_FOCUS     (wxTreeListTextCtrl::OnKillFocus)
+END_EVENT_TABLE()
+
+wxTreeListTextCtrl::wxTreeListTextCtrl( wxWindow *parent,
+                                        const wxWindowID id,
+                                        bool *accept,
+                                        wxString *res,
+                                        wxTreeListMainWindow *owner,
+                                        const wxString &value,
+                                        const wxPoint &pos,
+                                        const wxSize &size,
+                                        int style,
+                                        const wxValidator& validator,
+                                        const wxString &name )
+    : wxTextCtrl( parent, id, value, pos, size, style, validator, name )
+{
+    m_res = res;
+    m_accept = accept;
+    m_owner = owner;
+    (*m_accept) = FALSE;
+    (*m_res) = wxEmptyString;
+    m_startValue = value;
+    m_finished = FALSE;
+}
+
+void wxTreeListTextCtrl::OnChar( wxKeyEvent &event )
+{
+    if (event.m_keyCode == WXK_RETURN)
+    {
+        (*m_accept) = TRUE;
+        (*m_res) = GetValue();
+
+        if ((*m_res) != m_startValue)
+            m_owner->OnRenameAccept();
+
+        if (!wxPendingDelete.Member(this))
+            wxPendingDelete.Append(this);
+
+        m_finished = TRUE;
+        m_owner->SetFocus(); // This doesn't work. TODO.
+
+        return;
+    }
+    if (event.m_keyCode == WXK_ESCAPE)
+    {
+        (*m_accept) = FALSE;
+        (*m_res) = wxEmptyString;
+
+        if (!wxPendingDelete.Member(this))
+            wxPendingDelete.Append(this);
+
+        m_finished = TRUE;
+        m_owner->SetFocus(); // This doesn't work. TODO.
+
+        return;
+    }
+    event.Skip();
+}
+
+void wxTreeListTextCtrl::OnKeyUp( wxKeyEvent &event )
+{
+    if (m_finished)
+    {
+        event.Skip();
+        return;
+    }
+
+    // auto-grow the textctrl:
+    wxSize parentSize = m_owner->GetSize();
+    wxPoint myPos = GetPosition();
+    wxSize mySize = GetSize();
+    int sx, sy;
+    GetTextExtent(GetValue() + _T("M"), &sx, &sy);
+    if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x;
+    if (mySize.x > sx) sx = mySize.x;
+    SetSize(sx, -1);
+
+    event.Skip();
+}
+
+void wxTreeListTextCtrl::OnKillFocus( wxFocusEvent &event )
+{
+    if (m_finished)
+    {
+        event.Skip();
+        return;
+    }
+
+    if (!wxPendingDelete.Member(this))
+        wxPendingDelete.Append(this);
+
+    (*m_accept) = TRUE;
+    (*m_res) = GetValue();
+
+    if ((*m_res) != m_startValue)
+        m_owner->OnRenameAccept();
+}
+
+//-----------------------------------------------------------------------------
+//  wxTreeListHeaderWindow
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow,wxWindow);
+
+BEGIN_EVENT_TABLE(wxTreeListHeaderWindow,wxWindow)
+    EVT_PAINT         (wxTreeListHeaderWindow::OnPaint)
+    EVT_MOUSE_EVENTS  (wxTreeListHeaderWindow::OnMouse)
+    EVT_SET_FOCUS     (wxTreeListHeaderWindow::OnSetFocus)
+END_EVENT_TABLE()
+
+void wxTreeListHeaderWindow::Init()
+{
+    m_currentCursor = (wxCursor *) NULL;
+    m_isDragging = FALSE;
+    m_dirty = FALSE;
+    m_total_col_width = 0;
+}
+
+wxTreeListHeaderWindow::wxTreeListHeaderWindow()
+{
+    Init();
+
+    m_owner = (wxTreeListMainWindow *) NULL;
+    m_resizeCursor = (wxCursor *) NULL;
+}
+
+wxTreeListHeaderWindow::wxTreeListHeaderWindow( wxWindow *win,
+                                                wxWindowID id,
+                                                wxTreeListMainWindow *owner,
+                                                const wxPoint& pos,
+                                                const wxSize& size,
+                                                long style,
+                                                const wxString &name )
+    : wxWindow( win, id, pos, size, style, name )
+{
+    Init();
+
+    m_owner = owner;
+    m_resizeCursor = new wxCursor(wxCURSOR_SIZEWE);
+
+    SetBackgroundColour(wxSystemSettings::GetSystemColour(
+                            wxSYS_COLOUR_BTNFACE));
+}
+
+wxTreeListHeaderWindow::~wxTreeListHeaderWindow()
+{
+    delete m_resizeCursor;
+}
+
+void wxTreeListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
+{
+#ifdef __WXGTK__
+    GtkStateType state = m_parent->IsEnabled() ? GTK_STATE_NORMAL
+                                               : GTK_STATE_INSENSITIVE;
+
+    x = dc->XLOG2DEV( x );
+
+    gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window,
+                   state, GTK_SHADOW_OUT,
+                   (GdkRectangle*) NULL, m_wxwindow, "button",
+                   x-1, y-1, w+2, h+2);
+#elif defined( __WXMAC__  )
+    const int m_corner = 1;
+
+    dc->SetBrush( *wxTRANSPARENT_BRUSH );
+
+    dc->SetPen( wxPen(wxSystemSettings::GetSystemColour(
+                          wxSYS_COLOUR_BTNSHADOW), 1, wxSOLID));
+    dc->DrawLine( x+w-m_corner+1, y, x+w, y+h );  // right (outer)
+    dc->DrawRectangle( x, y+h, w+1, 1 );          // bottom (outer)
+
+    wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID );
+
+    dc->SetPen( pen );
+    dc->DrawLine( x+w-m_corner, y, x+w-1, y+h );  // right (inner)
+    dc->DrawRectangle( x+1, y+h-1, w-2, 1 );      // bottom (inner)
+
+    dc->SetPen( *wxWHITE_PEN );
+    dc->DrawRectangle( x, y, w-m_corner+1, 1 );   // top (outer)
+    dc->DrawRectangle( x, y, 1, h );              // left (outer)
+    dc->DrawLine( x, y+h-1, x+1, y+h-1 );
+    dc->DrawLine( x+w-1, y, x+w-1, y+1 );
+#else // !GTK, !Mac
+    const int m_corner = 1;
+
+    dc->SetBrush( *wxTRANSPARENT_BRUSH );
+
+    dc->SetPen( *wxBLACK_PEN );
+    dc->DrawLine( x+w-m_corner+1, y, x+w, y+h );  // right (outer)
+    dc->DrawRectangle( x, y+h, w+1, 1 );          // bottom (outer)
+
+    wxPen pen(wxSystemSettings::GetSystemColour(
+                  wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID);
+
+    dc->SetPen( pen );
+    dc->DrawLine( x+w-m_corner, y, x+w-1, y+h );  // right (inner)
+    dc->DrawRectangle( x+1, y+h-1, w-2, 1 );      // bottom (inner)
+
+    dc->SetPen( *wxWHITE_PEN );
+    dc->DrawRectangle( x, y, w-m_corner+1, 1 );   // top (outer)
+    dc->DrawRectangle( x, y, 1, h );              // left (outer)
+    dc->DrawLine( x, y+h-1, x+1, y+h-1 );
+    dc->DrawLine( x+w-1, y, x+w-1, y+1 );
+#endif
+}
+
+// shift the DC origin to match the position of the main window horz
+// scrollbar: this allows us to always use logical coords
+void wxTreeListHeaderWindow::AdjustDC(wxDC& dc)
+{
+    int xpix;
+    m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
+
+    int x;
+    m_owner->GetViewStart( &x, NULL );
+
+    // account for the horz scrollbar offset
+    dc.SetDeviceOrigin( -x * xpix, 0 );
+}
+
+void wxTreeListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
+{
+    static const int HEADER_OFFSET_X = 1, HEADER_OFFSET_Y = 1;
+#ifdef __WXGTK__
+    wxClientDC dc( this );
+#else
+    wxPaintDC dc( this );
+#endif
+
+    PrepareDC( dc );
+    AdjustDC( dc );
+
+    dc.BeginDrawing();
+
+    dc.SetFont( GetFont() );
+
+    // width and height of the entire header window
+    int w, h;
+    GetClientSize( &w, &h );
+    m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
+
+    dc.SetBackgroundMode(wxTRANSPARENT);
+
+    // do *not* use the listctrl colour for headers - one day we will have a
+    // function to set it separately
+    //dc.SetTextForeground( *wxBLACK );
+    dc.SetTextForeground(wxSystemSettings::
+                            GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
+
+    int x = HEADER_OFFSET_X;
+
+    int numColumns = GetColumnCount();
+    for ( int i = 0; i < numColumns && x < w; i++ )
+    {
+        wxTreeListColumnInfo& column = GetColumn(i);
+        int wCol = column.GetWidth();
+
+        // the width of the rect to draw: make it smaller to fit entirely
+        // inside the column rect
+        int cw = wCol - 2;
+
+        dc.SetPen( *wxWHITE_PEN );
+
+        DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 );
+
+        // if we have an image, draw it on the right of the label
+        int image = column.GetImage(); //item.m_image;
+        int ix = -2, iy = 0;
+        wxImageList* imageList = m_owner->GetImageList();
+        if(image != -1) {
+            if(imageList) {
+                imageList->GetSize(image, ix, iy);
+            }
+            //else: ignore the column image
+        }
+
+        // extra margins around the text label
+        static const int EXTRA_WIDTH = 3;
+        static const int EXTRA_HEIGHT = 4;
+
+        int text_width = 0;
+        int text_x = x;
+        int image_offset = cw - ix - 1;
+
+        switch(column.GetAlignment()) {
+        case wxTL_ALIGN_LEFT:
+            text_x += EXTRA_WIDTH;
+            cw -= ix + 2;
+            break;
+        case wxTL_ALIGN_RIGHT:
+            dc.GetTextExtent(column.GetText(), &text_width, NULL);
+            text_x += cw - text_width - EXTRA_WIDTH;
+            image_offset = 0;
+            break;
+        case wxTL_ALIGN_CENTER:
+            dc.GetTextExtent(column.GetText(), &text_width, NULL);
+            text_x += (cw - text_width)/2 + ix + 2;
+            image_offset = (cw - text_width - ix - 2)/2;
+            break;
+        }
+
+        // draw the image
+        if(image != -1 && imageList) {
+            imageList->Draw(image, dc, x + image_offset/*cw - ix - 1*/,
+                            HEADER_OFFSET_Y + (h - 4 - iy)/2,
+                            wxIMAGELIST_DRAW_TRANSPARENT);
+        }
+
+        // draw the text clipping it so that it doesn't overwrite the column
+        // boundary
+        wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 );
+
+        dc.DrawText( column.GetText(),
+                     text_x, HEADER_OFFSET_Y + EXTRA_HEIGHT );
+
+        x += wCol;
+    }
+
+    int more_w = m_owner->GetSize().x - x;
+    if (more_w > 0)
+    {
+        DoDrawRect( &dc, x, HEADER_OFFSET_Y, more_w, h-2 );
+    }
+
+
+    dc.EndDrawing();
+}
+
+void wxTreeListHeaderWindow::DrawCurrent()
+{
+    int x1 = m_currentX;
+    int y1 = 0;
+    ClientToScreen( &x1, &y1 );
+
+    int x2 = m_currentX-1;
+#ifdef __WXMSW__
+    ++x2; // but why ?
+#endif
+    int y2 = 0;
+    m_owner->GetClientSize( NULL, &y2 );
+    m_owner->ClientToScreen( &x2, &y2 );
+
+    wxScreenDC dc;
+    dc.SetLogicalFunction( wxINVERT );
+    dc.SetPen( wxPen( *wxBLACK, 2, wxSOLID ) );
+    dc.SetBrush( *wxTRANSPARENT_BRUSH );
+
+    AdjustDC(dc);
+
+    dc.DrawLine( x1, y1, x2, y2 );
+
+    dc.SetLogicalFunction( wxCOPY );
+
+    dc.SetPen( wxNullPen );
+    dc.SetBrush( wxNullBrush );
+}
+
+void wxTreeListHeaderWindow::OnMouse( wxMouseEvent &event )
+{
+    // we want to work with logical coords
+    int x;
+    m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
+    int y = event.GetY();
+
+    if (m_isDragging)
+    {
+        SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING,
+                      event.GetPosition());
+
+        // we don't draw the line beyond our window, but we allow dragging it
+        // there
+        int w = 0;
+        GetClientSize( &w, NULL );
+        m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
+        w -= 6;
+
+        // erase the line if it was drawn
+        if ( m_currentX < w )
+            DrawCurrent();
+
+        if (event.ButtonUp())
+        {
+            ReleaseMouse();
+            m_isDragging = FALSE;
+            m_dirty = TRUE;
+            SetColumnWidth( m_column, m_currentX - m_minX );
+            Refresh();
+            SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG,
+                          event.GetPosition());
+        }
+        else
+        {
+            if (x > m_minX + 7)
+                m_currentX = x;
+            else
+                m_currentX = m_minX + 7;
+
+            // draw in the new location
+            if ( m_currentX < w )
+                DrawCurrent();
+        }
+    }
+    else // not dragging
+    {
+        m_minX = 0;
+        bool hit_border = FALSE;
+
+        // end of the current column
+        int xpos = 0;
+
+        // find the column where this event occured
+        int countCol = GetColumnCount();
+        for (int col = 0; col < countCol; col++)
+        {
+            if (!GetColumnShown (col)) continue;
+            xpos += GetColumnWidth (col);
+            m_column = col;
+
+            if ( (abs(x-xpos) < 3) && (y < 22) )
+            {
+                // near the column border
+                hit_border = TRUE;
+                break;
+            }
+
+            if ( x < xpos )
+            {
+                // inside the column
+                break;
+            }
+
+            m_minX = xpos;
+        }
+
+        if (event.LeftDown() || event.RightUp())
+        {
+            if (hit_border && event.LeftDown())
+            {
+                m_isDragging = TRUE;
+                m_currentX = x;
+                DrawCurrent();
+                CaptureMouse();
+                SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG,
+                              event.GetPosition());
+            }
+            else // click on a column
+            {
+                SendListEvent( event.LeftDown()
+                               ? wxEVT_COMMAND_LIST_COL_CLICK
+                               : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK,
+                               event.GetPosition());
+            }
+        }
+        else if (event.Moving())
+        {
+            bool setCursor;
+            if (hit_border)
+            {
+                setCursor = m_currentCursor == wxSTANDARD_CURSOR;
+                m_currentCursor = m_resizeCursor;
+            }
+            else
+            {
+                setCursor = m_currentCursor != wxSTANDARD_CURSOR;
+                m_currentCursor = wxSTANDARD_CURSOR;
+            }
+
+            if ( setCursor )
+                SetCursor(*m_currentCursor);
+        }
+    }
+}
+
+void wxTreeListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) )
+{
+    m_owner->SetFocus();
+}
+
+void wxTreeListHeaderWindow::SendListEvent(wxEventType type, wxPoint pos)
+{
+    wxWindow *parent = GetParent();
+    wxListEvent le( type, parent->GetId() );
+    le.SetEventObject( parent );
+    le.m_pointDrag = pos;
+
+    // the position should be relative to the parent window, not
+    // this one for compatibility with MSW and common sense: the
+    // user code doesn't know anything at all about this header
+    // window, so why should it get positions relative to it?
+    le.m_pointDrag.y -= GetSize().y;
+
+    le.m_col = m_column;
+    parent->GetEventHandler()->ProcessEvent( le );
+}
+
+inline
+void wxTreeListHeaderWindow::AddColumn(const wxTreeListColumnInfo& col)
+{
+    m_columns.Add(col);
+    m_total_col_width += col.GetWidth();
+    //m_owner->GetHeaderWindow()->Refresh();
+    //m_dirty = TRUE;
+    m_owner->AdjustMyScrollbars();
+    m_owner->m_dirty = TRUE;
+    Refresh();
+}
+
+inline
+void wxTreeListHeaderWindow::SetColumnWidth(size_t column, size_t width)
+{
+    if(column < GetColumnCount()) {
+        m_total_col_width -= m_columns[column].GetWidth();
+        m_columns[column].SetWidth(width);
+        m_total_col_width += width;
+        m_owner->AdjustMyScrollbars();
+        m_owner->m_dirty = TRUE;
+        //m_dirty = TRUE;
+        Refresh();
+    }
+}
+
+
+inline
+void wxTreeListHeaderWindow::InsertColumn(size_t before,
+                                          const wxTreeListColumnInfo& col)
+{
+    wxCHECK_RET(before < GetColumnCount(), wxT("Invalid column index"));
+    m_columns.Insert(col, before);
+    m_total_col_width += col.GetWidth();
+    //m_dirty = TRUE;
+    //m_owner->GetHeaderWindow()->Refresh();
+    m_owner->AdjustMyScrollbars();
+    m_owner->m_dirty = TRUE;
+    Refresh();
+}
+
+inline
+void wxTreeListHeaderWindow::RemoveColumn(size_t column)
+{
+    wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column"));
+    m_total_col_width -= m_columns[column].GetWidth();
+    m_columns.RemoveAt(column);
+    //m_dirty = TRUE;
+    m_owner->AdjustMyScrollbars();
+    m_owner->m_dirty = TRUE;
+    Refresh();
+}
+
+inline
+void wxTreeListHeaderWindow::SetColumn(size_t column,
+                                       const wxTreeListColumnInfo& info)
+{
+    wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column"));
+    size_t w = m_columns[column].GetWidth();
+    m_columns[column] = info;
+    //m_owner->GetHeaderWindow()->Refresh();
+    //m_dirty = TRUE;
+    if(w != info.GetWidth()) {
+        m_total_col_width += info.GetWidth() - w;
+        m_owner->AdjustMyScrollbars();
+        m_owner->m_dirty = TRUE;
+    }
+    Refresh();
+}
+
+// ---------------------------------------------------------------------------
+// wxTreeListItem
+// ---------------------------------------------------------------------------
+
+wxTreeListItem::wxTreeListItem(wxTreeListMainWindow *owner,
+                                     wxTreeListItem *parent,
+                                     const wxArrayString& text,
+                                     int image, int selImage,
+                                     wxTreeItemData *data)
+                 : m_text(text)
+{
+    m_images[wxTreeItemIcon_Normal] = image;
+    m_images[wxTreeItemIcon_Selected] = selImage;
+    m_images[wxTreeItemIcon_Expanded] = NO_IMAGE;
+    m_images[wxTreeItemIcon_SelectedExpanded] = NO_IMAGE;
+
+    m_data = data;
+    m_x = m_y = 0;
+
+    m_isCollapsed = TRUE;
+    m_hasHilight = FALSE;
+    m_hasPlus = FALSE;
+    m_isBold = FALSE;
+
+    m_owner = owner;
+
+    m_parent = parent;
+
+    m_attr = (wxTreeItemAttr *)NULL;
+    m_ownsAttr = FALSE;
+
+    // We don't know the height here yet.
+    m_width = 0;
+    m_height = 0;
+}
+
+wxTreeListItem::~wxTreeListItem()
+{
+    delete m_data;
+
+    if (m_ownsAttr) delete m_attr;
+
+    wxASSERT_MSG( m_children.IsEmpty(),
+                  wxT("please call DeleteChildren() before deleting the item") );
+}
+
+void wxTreeListItem::DeleteChildren(wxTreeListMainWindow *tree)
+{
+    size_t count = m_children.Count();
+    for ( size_t n = 0; n < count; n++ )
+    {
+        wxTreeListItem *child = m_children[n];
+        if (tree)
+            tree->SendDeleteEvent(child);
+
+        child->DeleteChildren(tree);
+        delete child;
+    }
+
+    m_children.Empty();
+}
+
+void wxTreeListItem::SetText( const wxString &text )
+{
+    if(m_text.GetCount() > 0) m_text[0] = text;
+    else {
+        m_text.Add(text);
+    }
+}
+
+size_t wxTreeListItem::GetChildrenCount(bool recursively) const
+{
+    size_t count = m_children.Count();
+    if ( !recursively )
+        return count;
+
+    size_t total = count;
+    for (size_t n = 0; n < count; ++n)
+    {
+        total += m_children[n]->GetChildrenCount();
+    }
+
+    return total;
+}
+
+void wxTreeListItem::GetSize( int &x, int &y,
+                                 const wxTreeListMainWindow *theButton )
+{
+    int bottomY=m_y+theButton->GetLineHeight(this);
+    if ( y < bottomY ) y = bottomY;
+    int width = m_x +  m_width;
+    if ( x < width ) x = width;
+
+    if (IsExpanded())
+    {
+        size_t count = m_children.Count();
+        for ( size_t n = 0; n < count; ++n )
+        {
+            m_children[n]->GetSize( x, y, theButton );
+        }
+    }
+}
+
+wxTreeListItem *wxTreeListItem::HitTest(const wxPoint& point,
+                                        const wxTreeListMainWindow *theCtrl,
+                                        int &flags,
+                                        int level)
+{
+    // for a hidden root node, don't evaluate it, but do evaluate children
+    if (!(theCtrl->HasFlag(wxTR_HIDE_ROOT) && (level == 0)))
+    {
+        // evaluate the item
+        int h = theCtrl->GetLineHeight(this);
+        if ((point.y > m_y) && (point.y < m_y + h))
+        {
+            // check for above/below middle
+            int y_mid = m_y + h/2;
+            if (point.y < y_mid )
+                flags |= wxTREE_HITTEST_ONITEMUPPERPART;
+            else
+                flags |= wxTREE_HITTEST_ONITEMLOWERPART;
+
+            // check for button hit
+            if (HasPlus() && theCtrl->HasButtons()) {
+                int bntX = m_x - theCtrl->GetIndent() - theCtrl->m_btnWidth2;
+                int bntY = y_mid - theCtrl->m_btnHeight2;
+                if ((point.x > bntX) && (point.x < (bntX + theCtrl->m_btnWidth)) &&
+                    (point.y > bntY) && (point.y < (bntY + theCtrl->m_btnHeight))) {
+                    flags |= wxTREE_HITTEST_ONITEMBUTTON;
+                    return this;
+                }
+            }
+
+            // check for image hit
+            int imgX = m_x - theCtrl->m_imgWidth2;
+            int imgY = y_mid - theCtrl->m_imgHeight2;
+            if ((point.x >= imgX) && (point.x <= (imgX + theCtrl->m_imgWidth)) &&
+                (point.y >= imgY) && (point.y <= (imgY + theCtrl->m_imgHeight))) {
+                flags |= wxTREE_HITTEST_ONITEMICON;
+                return this;
+            }
+
+            // check for label hit
+            int lblX = m_x - theCtrl->m_imgWidth2 + theCtrl->m_imgWidth + MARGIN;
+            if ((point.x >= lblX) && (point.x <= (m_x + m_width)) &&
+                (point.y >= m_y) && (point.y <= (m_y + h))) {
+                flags |= wxTREE_HITTEST_ONITEMLABEL;
+                return this;
+            }
+
+            // else check for indent
+            if (point.x < m_x) {
+                flags |= wxTREE_HITTEST_ONITEMINDENT;
+                return this;
+            }
+
+            // else check for item right???
+            if (point.x > m_x + m_width) {
+                flags |= wxTREE_HITTEST_ONITEMRIGHT;
+                return this;
+            }
+
+        }
+
+        // if children are expanded, fall through to evaluate them
+        if (m_isCollapsed) return (wxTreeListItem*) NULL;
+    }
+
+    // evaluate children
+    size_t count = m_children.Count();
+    for ( size_t n = 0; n < count; n++ )
+    {
+        wxTreeListItem *res = m_children[n]->HitTest(point, theCtrl,
+                                                     flags, level + 1);
+        if ( res != NULL )
+            return res;
+    }
+
+    return (wxTreeListItem*) NULL;
+}
+
+// ALB
+wxTreeListItem *wxTreeListItem::HitTest(const wxPoint& point,
+                                        const wxTreeListMainWindow *theCtrl,
+                                        int &flags, int& column, int level)
+{
+    column = theCtrl->GetMainColumn(); //-1;
+
+    wxTreeListItem* res = HitTest(point, theCtrl, flags, level);
+    if(!res) {
+        column = -1;
+        return res;
+    }
+
+	wxTreeListHeaderWindow* header_win = theCtrl->m_owner->GetHeaderWindow();
+    if (point.x >= header_win->GetWidth())
+        column = -1;
+    else if(flags & wxTREE_HITTEST_ONITEMINDENT) {
+        int x = 0;
+        for(size_t i = 0; i < theCtrl->GetMainColumn(); ++i) {
+    	    if (!header_win->GetColumnShown(i)) continue;
+            int w = header_win->GetColumnWidth(i);
+            if(point.x >= x && point.x < x+w) {
+                flags ^= wxTREE_HITTEST_ONITEMINDENT;
+                flags |= wxTREE_HITTEST_ONITEMCOLUMN;
+                column = i;
+                return res;
+            }
+        }
+    }
+    else if(flags & wxTREE_HITTEST_ONITEMRIGHT) {
+        int x = 0;
+        size_t i;
+        for(i = 0; i < theCtrl->GetMainColumn()+1; ++i) {
+	        if (!header_win->GetColumnShown(i)) continue;
+            x += header_win->GetColumnWidth(i);
+        }
+        for(i = theCtrl->GetMainColumn()+1; i < theCtrl->GetColumnCount(); ++i) {
+	        if (!header_win->GetColumnShown(i)) continue;
+            int w = header_win->GetColumnWidth(i);
+            if(point.x >= x && point.x < x+w) {
+                flags ^= wxTREE_HITTEST_ONITEMRIGHT;
+                flags |= wxTREE_HITTEST_ONITEMCOLUMN;
+                column = i;
+                return res;
+            }
+        }
+    }
+
+    return res;
+}
+
+
+int wxTreeListItem::GetCurrentImage() const
+{
+    int image = NO_IMAGE;
+    if ( IsExpanded() )
+    {
+        if ( IsSelected() )
+        {
+            image = GetImage(wxTreeItemIcon_SelectedExpanded);
+        }
+
+        if ( image == NO_IMAGE )
+        {
+            // we usually fall back to the normal item, but try just the
+            // expanded one (and not selected) first in this case
+            image = GetImage(wxTreeItemIcon_Expanded);
+        }
+    }
+    else // not expanded
+    {
+        if ( IsSelected() )
+            image = GetImage(wxTreeItemIcon_Selected);
+    }
+
+    // maybe it doesn't have the specific image we want,
+    // try the default one instead
+    if ( image == NO_IMAGE ) image = GetImage();
+
+    return image;
+}
+
+// ---------------------------------------------------------------------------
+// wxTreeListMainWindow implementation
+// ---------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow, wxScrolledWindow)
+
+BEGIN_EVENT_TABLE(wxTreeListMainWindow, wxScrolledWindow)
+    EVT_PAINT          (wxTreeListMainWindow::OnPaint)
+    EVT_MOUSE_EVENTS   (wxTreeListMainWindow::OnMouse)
+    EVT_CHAR           (wxTreeListMainWindow::OnChar)
+    EVT_SET_FOCUS      (wxTreeListMainWindow::OnSetFocus)
+    EVT_KILL_FOCUS     (wxTreeListMainWindow::OnKillFocus)
+    EVT_IDLE           (wxTreeListMainWindow::OnIdle)
+    //EVT_SIZE           (wxTreeListMainWindow::OnSize)
+    EVT_SCROLLWIN      (wxTreeListMainWindow::OnScroll)
+END_EVENT_TABLE()
+
+
+// ---------------------------------------------------------------------------
+// construction/destruction
+// ---------------------------------------------------------------------------
+
+void wxTreeListMainWindow::Init()
+{
+    m_current = m_key_current = m_anchor = (wxTreeListItem *) NULL;
+    m_hasFocus = FALSE;
+    m_dirty = FALSE;
+
+    m_lineHeight = LINEHEIGHT;
+    m_indent = MININDENT; // min. indent
+    m_linespacing = 4;
+
+    m_hilightBrush = new wxBrush
+                         (
+                            wxSystemSettings::GetSystemColour
+                            (
+                                wxSYS_COLOUR_HIGHLIGHT
+                            ),
+                            wxSOLID
+                         );
+
+    m_hilightUnfocusedBrush = new wxBrush
+                              (
+                                 wxSystemSettings::GetSystemColour
+                                 (
+                                     wxSYS_COLOUR_BTNSHADOW
+                                 ),
+                                 wxSOLID
+                              );
+
+    m_imageListNormal = m_imageListButtons =
+    m_imageListState = (wxImageList *) NULL;
+    m_ownsImageListNormal = m_ownsImageListButtons =
+    m_ownsImageListState = FALSE;
+
+    m_dragCount = 0;
+    m_isDragging = FALSE;
+    m_dropTarget = m_oldSelection = (wxTreeListItem *)NULL;
+
+    m_renameTimer = new wxTreeListRenameTimer( this );
+    m_lastOnSame = FALSE;
+
+    m_normalFont = wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT );
+    m_boldFont = wxFont( m_normalFont.GetPointSize(),
+                         m_normalFont.GetFamily(),
+                         m_normalFont.GetStyle(),
+                         wxBOLD,
+                         m_normalFont.GetUnderlined());
+}
+
+
+static const int HEADER_HEIGHT = 23;
+
+bool wxTreeListMainWindow::Create(wxTreeListCtrl *parent,
+                                  wxWindowID id,
+                                  const wxPoint& pos,
+                                  const wxSize& size,
+                                  long style,
+                                  const wxValidator &validator,
+                                  const wxString& name )
+{
+#ifdef __WXMAC__
+    int major,minor;
+    wxGetOsVersion( &major, &minor );
+
+    if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS;
+    if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS;
+    style &= ~wxTR_LINES_AT_ROOT;
+    style |= wxTR_NO_LINES;
+    if (major < 10)
+        style |= wxTR_ROW_LINES;
+#endif
+
+    wxScrolledWindow::Create( parent, id, pos, size,
+                              style|wxHSCROLL|wxVSCROLL, name );
+
+#if wxUSE_VALIDATORS
+    SetValidator( validator );
+#endif
+
+    SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) );
+
+#ifdef __WXMSW__
+    {
+        int i, j;
+        wxBitmap bmp(8, 8);
+        wxMemoryDC bdc;
+        bdc.SelectObject(bmp);
+        bdc.SetPen(*wxGREY_PEN);
+        bdc.DrawRectangle(-1, -1, 10, 10);
+        for (i = 0; i < 8; i++) {
+            for (j = 0; j < 8; j++) {
+                if (!((i + j) & 1)) {
+                    bdc.DrawPoint(i, j);
+                }
+            }
+        }
+
+        m_dottedPen = wxPen(bmp, 1);
+    }
+#else
+    //m_dottedPen = wxPen( *wxGREY_PEN, 1, wxDOT );  // too slow under XFree86
+    m_dottedPen = wxPen( wxT("grey"), 0, 0 ); // Bitmap based pen is not supported by GTK!
+#endif
+
+    // ALB
+    m_owner = parent;
+    m_main_column = 0;
+
+    return TRUE;
+}
+
+wxTreeListMainWindow::~wxTreeListMainWindow()
+{
+    delete m_hilightBrush;
+    delete m_hilightUnfocusedBrush;
+
+    DeleteAllItems();
+
+    delete m_renameTimer;
+    if (m_ownsImageListNormal) delete m_imageListNormal;
+    if (m_ownsImageListState) delete m_imageListState;
+    if (m_ownsImageListButtons) delete m_imageListButtons;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// accessors
+//-----------------------------------------------------------------------------
+
+inline
+size_t wxTreeListMainWindow::GetCount() const
+{
+    return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount();
+}
+
+inline
+void wxTreeListMainWindow::SetIndent(unsigned int indent)
+{
+    m_indent = indent;
+    m_dirty = TRUE;
+}
+
+inline
+void wxTreeListMainWindow::SetLineSpacing(unsigned int spacing)
+{
+    m_linespacing = spacing;
+    m_dirty = TRUE;
+    CalculateLineHeight();
+}
+
+inline
+size_t wxTreeListMainWindow::GetChildrenCount(const wxTreeItemId& item,
+                                              bool recursively)
+{
+    wxCHECK_MSG( item.IsOk(), 0u, wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->GetChildrenCount(recursively);
+}
+
+void wxTreeListMainWindow::SetWindowStyle(const long styles)
+{
+        // right now, just sets the styles.  Eventually, we may
+        // want to update the inherited styles, but right now
+        // none of the parents has updatable styles
+    m_windowStyle = styles;
+    m_dirty = TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// functions to work with tree items
+//-----------------------------------------------------------------------------
+
+inline
+int wxTreeListMainWindow::GetItemImage(const wxTreeItemId& item, size_t column,
+                                       wxTreeItemIcon which) const
+{
+    wxCHECK_MSG( item.IsOk(), -1, wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->GetImage(column, which);
+}
+
+inline
+wxTreeItemData *wxTreeListMainWindow::GetItemData(const wxTreeItemId& item)
+    const
+{
+    wxCHECK_MSG( item.IsOk(), NULL, wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->GetData();
+}
+
+inline
+bool wxTreeListMainWindow::GetItemBold(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG(item.IsOk(), FALSE, wxT("invalid tree item"));
+    return ((wxTreeListItem *)item.m_pItem)->IsBold();
+}
+
+inline
+wxColour wxTreeListMainWindow::GetItemTextColour(const wxTreeItemId& item)
+    const
+{
+    wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    return pItem->Attr().GetTextColour();
+}
+
+inline
+wxColour wxTreeListMainWindow::GetItemBackgroundColour(
+    const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    return pItem->Attr().GetBackgroundColour();
+}
+
+inline
+wxFont wxTreeListMainWindow::GetItemFont(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), wxNullFont, wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    return pItem->Attr().GetFont();
+}
+
+
+
+inline
+void wxTreeListMainWindow::SetItemImage(const wxTreeItemId& item,
+                                        size_t column,
+                                        int image, wxTreeItemIcon which)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    pItem->SetImage(column, image, which);
+
+    wxClientDC dc(this);
+    CalculateSize(pItem, dc);
+    RefreshLine(pItem);
+}
+
+inline
+void wxTreeListMainWindow::SetItemData(const wxTreeItemId& item,
+                                       wxTreeItemData *data)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    ((wxTreeListItem*) item.m_pItem)->SetData(data);
+}
+
+inline
+void wxTreeListMainWindow::SetItemHasChildren(const wxTreeItemId& item,
+                                              bool has)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    pItem->SetHasPlus(has);
+    RefreshLine(pItem);
+}
+
+inline
+void wxTreeListMainWindow::SetItemBold(const wxTreeItemId& item, bool bold)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    // avoid redrawing the tree if no real change
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    if ( pItem->IsBold() != bold )
+    {
+        pItem->SetBold(bold);
+        RefreshLine(pItem);
+    }
+}
+
+inline
+void wxTreeListMainWindow::SetItemTextColour(const wxTreeItemId& item,
+                                             const wxColour& col)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    pItem->Attr().SetTextColour(col);
+    RefreshLine(pItem);
+}
+
+inline
+void wxTreeListMainWindow::SetItemBackgroundColour(const wxTreeItemId& item,
+                                                   const wxColour& col)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    pItem->Attr().SetBackgroundColour(col);
+    RefreshLine(pItem);
+}
+
+inline
+void wxTreeListMainWindow::SetItemFont(const wxTreeItemId& item,
+                                       const wxFont& font)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    pItem->Attr().SetFont(font);
+    RefreshLine(pItem);
+}
+
+inline
+bool wxTreeListMainWindow::SetFont( const wxFont &font )
+{
+    wxScrolledWindow::SetFont(font);
+
+    m_normalFont = font ;
+    m_boldFont = wxFont( m_normalFont.GetPointSize(),
+                            m_normalFont.GetFamily(),
+                            m_normalFont.GetStyle(),
+                            wxBOLD,
+                            m_normalFont.GetUnderlined());
+
+    return TRUE;
+}
+
+
+// ----------------------------------------------------------------------------
+// item status inquiries
+// ----------------------------------------------------------------------------
+
+inline
+bool wxTreeListMainWindow::IsVisible(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+
+    // An item is only visible if it's not a descendant of a collapsed item
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    wxTreeListItem* parent = pItem->GetItemParent();
+    while (parent)
+    {
+        if (!parent->IsExpanded())
+            return FALSE;
+        parent = parent->GetItemParent();
+    }
+
+    int startX, startY;
+    GetViewStart(& startX, & startY);
+
+    wxSize clientSize = GetClientSize();
+
+    wxRect rect;
+    if (!GetBoundingRect(item, rect))
+        return FALSE;
+    if (rect.GetWidth() == 0 || rect.GetHeight() == 0)
+        return FALSE;
+    if (rect.GetBottom() < 0 || rect.GetTop() > clientSize.y)
+        return FALSE;
+    if (rect.GetRight() < 0 || rect.GetLeft() > clientSize.x)
+        return FALSE;
+
+    return TRUE;
+}
+
+inline
+bool wxTreeListMainWindow::ItemHasChildren(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+
+    // consider that the item does have children if it has the "+" button: it
+    // might not have them (if it had never been expanded yet) but then it
+    // could have them as well and it's better to err on this side rather than
+    // disabling some operations which are restricted to the items with
+    // children for an item which does have them
+    return ((wxTreeListItem*) item.m_pItem)->HasPlus();
+}
+
+inline
+bool wxTreeListMainWindow::IsExpanded(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->IsExpanded();
+}
+
+inline
+bool wxTreeListMainWindow::IsSelected(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->IsSelected();
+}
+
+inline
+bool wxTreeListMainWindow::IsBold(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->IsBold();
+}
+
+// ----------------------------------------------------------------------------
+// navigation
+// ----------------------------------------------------------------------------
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetItemParent(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->GetItemParent();
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetFirstChild(const wxTreeItemId& item,
+                                                 long& cookie) const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    cookie = 0;
+    return GetNextChild(item, cookie);
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetNextChild(const wxTreeItemId& item,
+                                                long& cookie) const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    wxArrayTreeListItems& children = ((wxTreeListItem*)
+                                      item.m_pItem)->GetChildren();
+    if ( (size_t)cookie < children.Count() )
+    {
+        return children.Item((size_t)cookie++);
+    }
+    else
+    {
+        // there are no more of them
+        return wxTreeItemId();
+    }
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetLastChild(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
+    return (children.IsEmpty() ? wxTreeItemId() : wxTreeItemId(children.Last()));
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetNextSibling(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
+    wxTreeListItem *parent = i->GetItemParent();
+    if ( parent == NULL )
+    {
+        // root item doesn't have any siblings
+        return wxTreeItemId();
+    }
+
+    wxArrayTreeListItems& siblings = parent->GetChildren();
+    int index = siblings.Index(i);
+    wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent?
+
+    size_t n = (size_t)(index + 1);
+    return n == siblings.Count() ? wxTreeItemId() : wxTreeItemId(siblings[n]);
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetPrevSibling(const wxTreeItemId& item)
+    const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
+    wxTreeListItem *parent = i->GetItemParent();
+    if ( parent == NULL )
+    {
+        // root item doesn't have any siblings
+        return wxTreeItemId();
+    }
+
+    wxArrayTreeListItems& siblings = parent->GetChildren();
+    int index = siblings.Index(i);
+    wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent?
+
+    return index == 0 ? wxTreeItemId()
+                      : wxTreeItemId(siblings[(size_t)(index - 1)]);
+}
+
+// Only for internal use right now, but should probably be public
+wxTreeItemId wxTreeListMainWindow::GetNext(const wxTreeItemId& item) const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
+
+    // First see if there are any children.
+    wxArrayTreeListItems& children = i->GetChildren();
+    if (children.GetCount() > 0)
+    {
+         return children.Item(0);
+    }
+    else
+    {
+         // Try a sibling of this or ancestor instead
+         wxTreeItemId p = item;
+         wxTreeItemId toFind;
+         do
+         {
+              toFind = GetNextSibling(p);
+              p = GetItemParent(p);
+         } while (p.IsOk() && !toFind.IsOk());
+         return toFind;
+    }
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetFirstVisibleItem() const
+{
+    wxTreeItemId id = GetRootItem();
+    if (!id.IsOk())
+        return id;
+
+    do
+    {
+        if (IsVisible(id))
+              return id;
+        id = GetNext(id);
+    } while (id.IsOk());
+
+    return wxTreeItemId();
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetNextVisible(const wxTreeItemId& item)
+    const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    wxTreeItemId id = item;
+    if (id.IsOk())
+    {
+        while (id = GetNext(id), id.IsOk())
+        {
+            if (IsVisible(id))
+                return id;
+        }
+    }
+    return wxTreeItemId();
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::GetPrevVisible(const wxTreeItemId& item)
+    const
+{
+    wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") );
+
+    wxFAIL_MSG(wxT("not implemented"));
+
+    return wxTreeItemId();
+}
+
+// ----------------------------------------------------------------------------
+// operations
+// ----------------------------------------------------------------------------
+
+wxTreeItemId wxTreeListMainWindow::DoInsertItem(const wxTreeItemId& parentId,
+                                      size_t previous,
+                                      const wxString& text,
+                                      int image, int selImage,
+                                      wxTreeItemData *data)
+{
+    wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem;
+    if ( !parent )
+    {
+        // should we give a warning here?
+        return AddRoot(text, image, selImage, data);
+    }
+
+    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+
+    // ALB
+    wxArrayString arr;
+    arr.Alloc(GetColumnCount());
+    for(size_t i = 0; i < GetColumnCount(); ++i) {
+        arr.Add(wxEmptyString);
+    }
+    arr[m_main_column] = text;
+    wxTreeListItem *item =
+        new wxTreeListItem( this, parent, arr, image, selImage, data );
+
+    if ( data != NULL )
+    {
+        data->SetId((long)item);
+    }
+
+    parent->Insert( item, previous );
+
+    return item;
+}
+
+wxTreeItemId wxTreeListMainWindow::AddRoot(const wxString& text,
+                                 int image, int selImage,
+                                 wxTreeItemData *data)
+{
+    wxCHECK_MSG(!m_anchor, wxTreeItemId(), wxT("tree can have only one root"));
+    wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), wxT("Add column(s) before adding the root item"));
+
+    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+
+    // ALB
+    wxArrayString arr;
+    arr.Alloc(GetColumnCount());
+    for(size_t i = 0; i < GetColumnCount(); ++i) {
+        arr.Add(wxEmptyString);
+    }
+    arr[m_main_column] = text;
+    m_anchor = new wxTreeListItem( this, (wxTreeListItem *)NULL, arr,
+                                      image, selImage, data);
+#if 0
+    if (HasFlag(wxTR_HIDE_ROOT))
+    {
+        // if root is hidden, make sure we can navigate
+        // into children
+        m_anchor->SetHasPlus();
+        Expand(m_anchor);
+    }
+#endif
+    if ( data != NULL )
+    {
+        data->SetId((long)m_anchor);
+    }
+
+    if (!HasFlag(wxTR_MULTIPLE))
+    {
+        m_current = m_key_current = m_anchor;
+        m_current->SetHilight( TRUE );
+    }
+
+    return m_anchor;
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::PrependItem(const wxTreeItemId& parent,
+                                     const wxString& text,
+                                     int image, int selImage,
+                                     wxTreeItemData *data)
+{
+    return DoInsertItem(parent, 0u, text, image, selImage, data);
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::InsertItem(const wxTreeItemId& parentId,
+                                    const wxTreeItemId& idPrevious,
+                                    const wxString& text,
+                                    int image, int selImage,
+                                    wxTreeItemData *data)
+{
+    wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem;
+    if ( !parent )
+    {
+        // should we give a warning here?
+        return AddRoot(text, image, selImage, data);
+    }
+
+    int index = parent->GetChildren().Index((wxTreeListItem*) idPrevious.m_pItem);
+    wxASSERT_MSG( index != wxNOT_FOUND,
+                  wxT("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") );
+
+    return DoInsertItem(parentId, (size_t)++index, text, image, selImage, data);
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::InsertItem(const wxTreeItemId& parentId,
+                                    size_t before,
+                                    const wxString& text,
+                                    int image, int selImage,
+                                    wxTreeItemData *data)
+{
+    wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem;
+    if ( !parent )
+    {
+        // should we give a warning here?
+        return AddRoot(text, image, selImage, data);
+    }
+
+    return DoInsertItem(parentId, before, text, image, selImage, data);
+}
+
+inline
+wxTreeItemId wxTreeListMainWindow::AppendItem(const wxTreeItemId& parentId,
+                                    const wxString& text,
+                                    int image, int selImage,
+                                    wxTreeItemData *data)
+{
+    wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem;
+    if ( !parent )
+    {
+        // should we give a warning here?
+        return AddRoot(text, image, selImage, data);
+    }
+
+    return DoInsertItem( parent, parent->GetChildren().Count(), text,
+                         image, selImage, data);
+}
+
+void wxTreeListMainWindow::SendDeleteEvent(wxTreeListItem *item)
+{
+    wxTreeEvent event( wxEVT_COMMAND_TREE_DELETE_ITEM, m_owner->GetId() );
+    event.SetItem((long) item);
+    event.SetEventObject( /*this*/m_owner );
+    m_owner->ProcessEvent( event );
+}
+
+inline
+void wxTreeListMainWindow::DeleteChildren(const wxTreeItemId& itemId)
+{
+    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+
+    wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
+    item->DeleteChildren(this);
+}
+
+inline
+void wxTreeListMainWindow::Delete(const wxTreeItemId& itemId)
+{
+    m_dirty = TRUE;     // do this first so stuff below doesn't cause flicker
+
+    wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
+
+    // don't stay with invalid m_key_current or we will crash in
+    // the next call to OnChar()
+    bool changeKeyCurrent = FALSE;
+    wxTreeListItem *itemKey = m_key_current;
+    while ( itemKey )
+    {
+        if ( itemKey == item )
+        {
+            // m_key_current is a descendant of the item being deleted
+            changeKeyCurrent = TRUE;
+            break;
+        }
+        itemKey = itemKey->GetItemParent();
+    }
+
+    wxTreeListItem *parent = item->GetItemParent();
+    if ( parent )
+    {
+        parent->GetChildren().Remove( item );  // remove by value
+    }
+
+    if ( changeKeyCurrent )
+    {
+        // may be NULL or not
+        m_key_current = parent;
+    }
+
+    item->DeleteChildren(this);
+    SendDeleteEvent(item);
+    delete item;
+}
+
+inline
+void wxTreeListMainWindow::DeleteAllItems()
+{
+    if ( m_anchor )
+    {
+        m_dirty = TRUE;
+
+        m_anchor->DeleteChildren(this);
+        delete m_anchor;
+
+        m_anchor = NULL;
+    }
+}
+
+void wxTreeListMainWindow::Expand(const wxTreeItemId& itemId)
+{
+    wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
+
+    wxCHECK_RET( item, _T("invalid item in wxTreeListMainWindow::Expand") );
+
+    if ( !item->HasPlus() )
+        return;
+
+    if ( item->IsExpanded() )
+        return;
+
+    wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, m_owner->GetId() );
+    event.SetItem( (long) item );
+    event.SetEventObject( /*this*/m_owner );
+
+    if ( m_owner->ProcessEvent( event ) && !event.IsAllowed() )
+    {
+        // cancelled by program
+        return;
+    }
+
+    item->Expand();
+    CalculatePositions();
+
+    RefreshSubtree(item);
+
+    event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED);
+    ProcessEvent( event );
+}
+
+void wxTreeListMainWindow::ExpandAll(const wxTreeItemId& item)
+{
+    Expand(item);
+    if ( IsExpanded(item) )
+    {
+        long cookie;
+        wxTreeItemId child = GetFirstChild(item, cookie);
+        while ( child.IsOk() )
+        {
+            ExpandAll(child);
+
+            child = GetNextChild(item, cookie);
+        }
+    }
+}
+
+void wxTreeListMainWindow::Collapse(const wxTreeItemId& itemId)
+{
+    wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
+
+    if ( !item->IsExpanded() )
+        return;
+
+    wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, m_owner->GetId() );
+    event.SetItem( (long) item );
+    event.SetEventObject( /*this*/m_owner );
+    if ( m_owner->ProcessEvent( event ) && !event.IsAllowed() )
+    {
+        // cancelled by program
+        return;
+    }
+
+    item->Collapse();
+
+#if 0  // TODO why should items be collapsed recursively?
+    wxArrayTreeListItems& children = item->GetChildren();
+    size_t count = children.Count();
+    for ( size_t n = 0; n < count; n++ )
+    {
+        Collapse(children[n]);
+    }
+#endif
+
+    CalculatePositions();
+
+    RefreshSubtree(item);
+
+    event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED);
+    ProcessEvent( event );
+}
+
+void wxTreeListMainWindow::CollapseAndReset(const wxTreeItemId& item)
+{
+    Collapse(item);
+    DeleteChildren(item);
+}
+
+void wxTreeListMainWindow::Toggle(const wxTreeItemId& itemId)
+{
+    wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
+
+    if (item->IsExpanded())
+        Collapse(itemId);
+    else
+        Expand(itemId);
+}
+
+void wxTreeListMainWindow::Unselect()
+{
+    if (m_current)
+    {
+        m_current->SetHilight( FALSE );
+        RefreshLine( m_current );
+    }
+}
+
+void wxTreeListMainWindow::UnselectAllChildren(wxTreeListItem *item)
+{
+    if (item->IsSelected())
+    {
+        item->SetHilight(FALSE);
+        RefreshLine(item);
+    }
+
+    if (item->HasChildren())
+    {
+        wxArrayTreeListItems& children = item->GetChildren();
+        size_t count = children.Count();
+        for ( size_t n = 0; n < count; ++n )
+        {
+            UnselectAllChildren(children[n]);
+        }
+    }
+}
+
+void wxTreeListMainWindow::UnselectAll()
+{
+    UnselectAllChildren((wxTreeListItem*) GetRootItem().m_pItem);
+}
+
+// Recursive function !
+// To stop we must have crt_item<last_item
+// Algorithm :
+// Tag all next children, when no more children,
+// Move to parent (not to tag)
+// Keep going... if we found last_item, we stop.
+bool wxTreeListMainWindow::TagNextChildren(wxTreeListItem *crt_item, wxTreeListItem *last_item, bool select)
+{
+    wxTreeListItem *parent = crt_item->GetItemParent();
+
+    if (parent == NULL) // This is root item
+        return TagAllChildrenUntilLast(crt_item, last_item, select);
+
+    wxArrayTreeListItems& children = parent->GetChildren();
+    int index = children.Index(crt_item);
+    wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent?
+
+    size_t count = children.Count();
+    for (size_t n=(size_t)(index+1); n<count; ++n)
+    {
+        if (TagAllChildrenUntilLast(children[n], last_item, select)) return TRUE;
+    }
+
+    return TagNextChildren(parent, last_item, select);
+}
+
+bool wxTreeListMainWindow::TagAllChildrenUntilLast(wxTreeListItem *crt_item, wxTreeListItem *last_item, bool select)
+{
+    crt_item->SetHilight(select);
+    RefreshLine(crt_item);
+
+    if (crt_item==last_item)
+        return TRUE;
+
+    if (crt_item->HasChildren())
+    {
+        wxArrayTreeListItems& children = crt_item->GetChildren();
+        size_t count = children.Count();
+        for ( size_t n = 0; n < count; ++n )
+        {
+            if (TagAllChildrenUntilLast(children[n], last_item, select))
+                return TRUE;
+        }
+    }
+
+  return FALSE;
+}
+
+void wxTreeListMainWindow::SelectItemRange(wxTreeListItem *item1, wxTreeListItem *item2)
+{
+    // item2 is not necessary after item1
+    wxTreeListItem *first=NULL, *last=NULL;
+
+    // choice first' and 'last' between item1 and item2
+    if (item1->GetY()<item2->GetY())
+    {
+        first=item1;
+        last=item2;
+    }
+    else
+    {
+        first=item2;
+        last=item1;
+    }
+
+    bool select = m_current->IsSelected();
+
+    if ( TagAllChildrenUntilLast(first,last,select) )
+        return;
+
+    TagNextChildren(first,last,select);
+}
+
+void wxTreeListMainWindow::SelectItem(const wxTreeItemId& itemId,
+                            bool unselect_others,
+                            bool extended_select)
+{
+    wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") );
+
+    bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE);
+    wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
+
+    //wxCHECK_RET( ( (!unselect_others) && is_single),
+    //           wxT("this is a single selection tree") );
+
+    // to keep going anyhow !!!
+    if (is_single)
+    {
+        if (item->IsSelected())
+            return; // nothing to do
+        unselect_others = TRUE;
+        extended_select = FALSE;
+    }
+    else if ( unselect_others && item->IsSelected() )
+    {
+        // selection change if there is more than one item currently selected
+        wxArrayTreeItemIds selected_items;
+        if ( GetSelections(selected_items) == 1 )
+            return;
+    }
+
+    wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() );
+    event.SetItem( (long) item );
+    event.SetOldItem( (long) m_current );
+    event.SetEventObject( /*this*/m_owner );
+    // TODO : Here we don't send any selection mode yet !
+
+    if(m_owner->GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed())
+        return;
+
+    wxTreeItemId parent = GetItemParent( itemId );
+    while (parent.IsOk())
+    {
+        if (!IsExpanded(parent))
+            Expand( parent );
+
+        parent = GetItemParent( parent );
+    }
+
+    EnsureVisible( itemId );
+
+    // ctrl press
+    if (unselect_others)
+    {
+        if (is_single) Unselect(); // to speed up thing
+        else UnselectAll();
+    }
+
+    // shift press
+    if (extended_select)
+    {
+        if ( !m_current )
+        {
+            m_current = m_key_current = (wxTreeListItem*) GetRootItem().m_pItem;
+        }
+
+        // don't change the mark (m_current)
+        SelectItemRange(m_current, item);
+    }
+    else
+    {
+        bool select=TRUE; // the default
+
+        // Check if we need to toggle hilight (ctrl mode)
+        if (!unselect_others)
+            select=!item->IsSelected();
+
+        m_current = m_key_current = item;
+        m_current->SetHilight(select);
+        RefreshLine( m_current );
+    }
+
+    event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
+    GetEventHandler()->ProcessEvent( event );
+}
+
+void wxTreeListMainWindow::FillArray(wxTreeListItem *item,
+                           wxArrayTreeItemIds &array) const
+{
+    if ( item->IsSelected() )
+        array.Add(wxTreeItemId(item));
+
+    if ( item->HasChildren() )
+    {
+        wxArrayTreeListItems& children = item->GetChildren();
+        size_t count = children.GetCount();
+        for ( size_t n = 0; n < count; ++n )
+            FillArray(children[n], array);
+    }
+}
+
+size_t wxTreeListMainWindow::GetSelections(wxArrayTreeItemIds &array) const
+{
+    array.Empty();
+    wxTreeItemId idRoot = GetRootItem();
+    if ( idRoot.IsOk() )
+    {
+        FillArray((wxTreeListItem*) idRoot.m_pItem, array);
+    }
+    //else: the tree is empty, so no selections
+
+    return array.Count();
+}
+
+void wxTreeListMainWindow::EnsureVisible(const wxTreeItemId& item)
+{
+    if (!item.IsOk()) return;
+
+    wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem;
+
+    // first expand all parent branches
+    wxTreeListItem *parent = gitem->GetItemParent();
+    while ( parent )
+    {
+        Expand(parent);
+        parent = parent->GetItemParent();
+    }
+
+    //if (parent) CalculatePositions();
+
+    ScrollTo(item);
+}
+
+void wxTreeListMainWindow::ScrollTo(const wxTreeItemId &item)
+{
+    if (!item.IsOk()) return;
+
+    // We have to call this here because the label in
+    // question might just have been added and no screen
+    // update taken place.
+    if (m_dirty) wxYieldIfNeeded();
+
+    wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem;
+
+    // now scroll to the item
+    int item_y = gitem->GetY();
+
+    int start_x = 0;
+    int start_y = 0;
+    GetViewStart( &start_x, &start_y );
+    start_y *= PIXELS_PER_UNIT;
+
+    int client_h = 0;
+    int client_w = 0;
+    GetClientSize( &client_w, &client_h );
+
+    if (item_y < start_y+3)
+    {
+        // going down
+        int x = 0;
+        int y = 0;
+        m_anchor->GetSize( x, y, this );
+        x = m_owner->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB
+        y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+        //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+        int x_pos = GetScrollPos( wxHORIZONTAL );
+        // Item should appear at top
+        SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, item_y/PIXELS_PER_UNIT );
+    }
+    else if (item_y+GetLineHeight(gitem) > start_y+client_h)
+    {
+        // going up
+        int x = 0;
+        int y = 0;
+        m_anchor->GetSize( x, y, this );
+        y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+        //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+        x = m_owner->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB
+        item_y += PIXELS_PER_UNIT+2;
+        int x_pos = GetScrollPos( wxHORIZONTAL );
+        // Item should appear at bottom
+        SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, (item_y+GetLineHeight(gitem)-client_h)/PIXELS_PER_UNIT );
+    }
+}
+
+// FIXME: tree sorting functions are not reentrant and not MT-safe!
+static wxTreeListMainWindow *s_treeBeingSorted = NULL;
+
+static int LINKAGEMODE tree_ctrl_compare_func(wxTreeListItem **item1,
+                                  wxTreeListItem **item2)
+{
+    wxCHECK_MSG( s_treeBeingSorted, 0, wxT("bug in wxTreeListMainWindow::SortChildren()") );
+
+    return s_treeBeingSorted->OnCompareItems(*item1, *item2);
+}
+
+int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId& item1,
+                               const wxTreeItemId& item2)
+{
+    // ALB: delegate to m_owner, to let the user overrride the comparison
+    //return wxStrcmp(GetItemText(item1), GetItemText(item2));
+    return m_owner->OnCompareItems(item1, item2);
+}
+
+void wxTreeListMainWindow::SortChildren(const wxTreeItemId& itemId)
+{
+    wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") );
+
+    wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
+
+    wxCHECK_RET( !s_treeBeingSorted,
+                 wxT("wxTreeListMainWindow::SortChildren is not reentrant") );
+
+    wxArrayTreeListItems& children = item->GetChildren();
+    if ( children.Count() > 1 )
+    {
+        m_dirty = TRUE;
+
+        s_treeBeingSorted = this;
+        children.Sort(tree_ctrl_compare_func);
+        s_treeBeingSorted = NULL;
+    }
+    //else: don't make the tree dirty as nothing changed
+}
+
+inline
+wxImageList *wxTreeListMainWindow::GetImageList() const
+{
+    return m_imageListNormal;
+}
+
+inline
+wxImageList *wxTreeListMainWindow::GetButtonsImageList() const
+{
+    return m_imageListButtons;
+}
+
+inline
+wxImageList *wxTreeListMainWindow::GetStateImageList() const
+{
+    return m_imageListState;
+}
+
+void wxTreeListMainWindow::CalculateLineHeight()
+{
+    wxClientDC dc(this);
+    dc.SetFont( m_normalFont );
+    m_lineHeight = (int)(dc.GetCharHeight() + m_linespacing);
+
+    if ( m_imageListNormal )
+    {
+        // Calculate a m_lineHeight value from the normal Image sizes.
+        // May be toggle off. Then wxTreeListMainWindow will spread when
+        // necessary (which might look ugly).
+        int n = m_imageListNormal->GetImageCount();
+        for (int i = 0; i < n ; i++)
+        {
+            int width = 0, height = 0;
+            m_imageListNormal->GetSize(i, width, height);
+            if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
+        }
+    }
+
+    if (m_imageListButtons)
+    {
+        // Calculate a m_lineHeight value from the Button image sizes.
+        // May be toggle off. Then wxTreeListMainWindow will spread when
+        // necessary (which might look ugly).
+        int n = m_imageListButtons->GetImageCount();
+        for (int i = 0; i < n ; i++)
+        {
+            int width = 0, height = 0;
+            m_imageListButtons->GetSize(i, width, height);
+            if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
+        }
+    }
+
+/*? FIXME: Don't get what this code is for... Adding a line space is already done!!!
+    if (m_lineHeight < 30)
+        m_lineHeight += 2;                 // at least 2 pixels
+    else
+        m_lineHeight += m_lineHeight/10;   // otherwise 10% extra spacing
+?*/
+}
+
+inline
+void wxTreeListMainWindow::SetImageList(wxImageList *imageList)
+{
+    if (m_ownsImageListNormal) delete m_imageListNormal;
+    m_imageListNormal = imageList;
+    m_ownsImageListNormal = FALSE;
+    m_dirty = TRUE;
+    CalculateLineHeight();
+}
+
+inline
+void wxTreeListMainWindow::SetStateImageList(wxImageList *imageList)
+{
+    if (m_ownsImageListState) delete m_imageListState;
+    m_imageListState = imageList;
+    m_ownsImageListState = FALSE;
+}
+
+inline
+void wxTreeListMainWindow::SetButtonsImageList(wxImageList *imageList)
+{
+    if (m_ownsImageListButtons) delete m_imageListButtons;
+    m_imageListButtons = imageList;
+    m_ownsImageListButtons = FALSE;
+    m_dirty = TRUE;
+    CalculateLineHeight();
+}
+
+inline
+void wxTreeListMainWindow::AssignImageList(wxImageList *imageList)
+{
+    SetImageList(imageList);
+    m_ownsImageListNormal = TRUE;
+}
+
+inline
+void wxTreeListMainWindow::AssignStateImageList(wxImageList *imageList)
+{
+    SetStateImageList(imageList);
+    m_ownsImageListState = TRUE;
+}
+
+inline
+void wxTreeListMainWindow::AssignButtonsImageList(wxImageList *imageList)
+{
+    SetButtonsImageList(imageList);
+    m_ownsImageListButtons = TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// helpers
+// ----------------------------------------------------------------------------
+
+void wxTreeListMainWindow::AdjustMyScrollbars()
+{
+    if (m_anchor)
+    {
+        int x = 0, y = 0;
+        m_anchor->GetSize( x, y, this );
+        y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+        //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
+        int x_pos = GetScrollPos( wxHORIZONTAL );
+        int y_pos = GetScrollPos( wxVERTICAL );
+        x = m_owner->GetHeaderWindow()->GetWidth() + 2;
+        if(x < GetClientSize().GetWidth()) x_pos = 0;
+        //m_total_col_width + 2; // ALB
+        SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT,
+                       y/PIXELS_PER_UNIT, x_pos, y_pos );
+    }
+    else
+    {
+        SetScrollbars( 0, 0, 0, 0 );
+    }
+}
+
+int wxTreeListMainWindow::GetLineHeight(wxTreeListItem *item) const
+{
+    if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT)
+        return item->GetHeight();
+    else
+        return m_lineHeight;
+}
+
+void wxTreeListMainWindow::PaintItem(wxTreeListItem *item, wxDC& dc)
+{
+    // TODO implement "state" icon on items
+
+    wxTreeItemAttr *attr = item->GetAttributes();
+    if ( attr && attr->HasFont() )
+        dc.SetFont(attr->GetFont());
+    else if (item->IsBold())
+        dc.SetFont(m_boldFont);
+
+    long text_w = 0, text_h = 0;
+
+    dc.GetTextExtent( item->GetText(GetMainColumn()), &text_w, &text_h );
+
+    int total_h = GetLineHeight(item);
+
+    if ( item->IsSelected() )
+    {
+        dc.SetBrush(*(m_hasFocus ? m_hilightBrush : m_hilightUnfocusedBrush));
+        int offset = HasFlag(wxTR_ROW_LINES) ? 1 : 0;
+        dc.DrawRectangle (0, item->GetY() + offset,
+                          m_owner->GetHeaderWindow()->GetWidth(), total_h-offset);
+    }
+#if 0 // this code is probably not needed
+    else
+    {
+        wxColour colBg;
+        if ( attr && attr->HasBackgroundColour() )
+            colBg = attr->GetBackgroundColour();
+        else
+            colBg = m_backgroundColour;
+        dc.SetBrush(wxBrush(colBg, wxTRANSPARENT));
+    }
+#endif
+
+    dc.SetBackgroundMode(wxTRANSPARENT);
+    int text_extraH = (total_h > text_h) ? (total_h - text_h)/2 : 0;
+    int img_extraH = (total_h > m_imgHeight)? (total_h-m_imgHeight)/2: 0;
+    int x_colstart = 0;
+    for ( size_t i = 0; i < GetColumnCount(); ++i ) {
+        if (!m_owner->GetHeaderWindow()->GetColumnShown(i)) continue;
+        int colwidth = m_owner->GetHeaderWindow()->GetColumnWidth(i);
+        int image;
+        int image_x = x_colstart + MARGIN;
+        int image_w = 0;
+        if(i == GetMainColumn()) {
+            image = item->GetCurrentImage();
+            image_x = item->GetX() - m_imgWidth2;
+            image_w = m_imgWidth + MARGIN;
+        }
+        else
+        {
+            image = item->GetImage(i);
+            if (image != NO_IMAGE) image_w = m_imgWidth + MARGIN;
+        }
+
+        // honor text alignment
+        wxString text = item->GetText(i);
+        switch ( m_owner->GetHeaderWindow()->GetColumn(i).GetAlignment() ) {
+        case wxTL_ALIGN_LEFT:
+            // already left aligned
+            break;
+        case wxTL_ALIGN_RIGHT:
+            dc.GetTextExtent(text, &text_w, NULL);
+            image_x = x_colstart + colwidth - (image_w + text_w + MARGIN);
+            break;
+        case wxTL_ALIGN_CENTER:
+            dc.GetTextExtent(text, &text_w, NULL);
+            int w = colwidth - image_w - text_w;
+            image_x = x_colstart + (w > 0)? w: 0;
+            break;
+        }
+        int text_x = image_x + image_w;
+
+        wxDCClipper clipper (dc, x_colstart, item->GetY(), colwidth, total_h);
+        if (image != NO_IMAGE)
+        {
+            int image_y = item->GetY() + img_extraH;
+            m_imageListNormal->Draw ( image, dc, image_x, image_y,
+                                      wxIMAGELIST_DRAW_TRANSPARENT );
+        }
+        int text_y = item->GetY() + text_extraH;
+        dc.DrawText ( text, (wxCoord)text_x, (wxCoord)text_y );
+
+        x_colstart += colwidth;
+    }
+
+    // restore normal font
+    dc.SetFont( m_normalFont );
+}
+
+// Now y stands for the top of the item, whereas it used to stand for middle !
+void wxTreeListMainWindow::PaintLevel (wxTreeListItem *item, wxDC &dc,
+                                       int level, int &y, int x_colstart )
+{
+    // Handle hide root (only level 0)
+    if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) {
+        // always expand hidden root
+        wxArrayTreeListItems& children = item->GetChildren();
+        int n;
+        for (n = 0; n < (int)children.Count(); n++) {
+            PaintLevel (children[n], dc, 1, y, x_colstart);
+        }
+        // end after expanding root
+        return;
+    }
+
+    // calculate position of vertical lines
+    int x = x_colstart + MARGIN; // start of column
+    if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
+    if (HasButtons()) x += m_btnWidth2; // space for buttons etc.
+    if (!HasFlag(wxTR_HIDE_ROOT)) x += m_indent; // indent root as well
+    x += m_indent * level; // indent according to level
+
+    // handle column text
+    item->SetX (x);
+    item->SetY (y);
+
+    int h = GetLineHeight(item);
+    int y_top = y;
+    int y_mid = y_top + (h/2);
+    y += h;
+
+    int exposed_x = dc.LogicalToDeviceX(0);
+    int exposed_y = dc.LogicalToDeviceY(y_top);
+
+    if (IsExposed(exposed_x, exposed_y, 10000, h))  // 10000 = very much
+    {
+        if (HasFlag(wxTR_ROW_LINES))
+        {
+            //dc.DestroyClippingRegion();
+            int total_width = m_owner->GetHeaderWindow()->GetWidth();
+            // if the background colour is white, choose a
+            // contrasting color for the lines
+            dc.SetPen (*((GetBackgroundColour() == *wxWHITE)?
+                        wxMEDIUM_GREY_PEN : wxWHITE_PEN));
+            dc.DrawLine(0, y_top, total_width, y_top);
+            dc.DrawLine(0, y, total_width, y);
+        }
+
+        // restore DC objects
+        dc.SetBrush(*wxWHITE_BRUSH);
+        dc.SetPen(m_dottedPen);
+        dc.SetTextForeground(*wxBLACK);
+
+        if (((level == 0) || ((level == 1) && HasFlag(wxTR_HIDE_ROOT))) &&
+            HasFlag(wxTR_LINES_AT_ROOT) && !HasFlag(wxTR_NO_LINES)) {
+            int rootPos = x_colstart + MARGIN;
+            dc.DrawLine (rootPos, y_mid, rootPos+LINEATROOT, y_mid);
+        }
+
+        size_t clip_width = m_owner->GetHeaderWindow()->
+                            GetColumn(m_main_column).GetWidth();
+        //m_columns[m_main_column].GetWidth();
+
+        if (item->HasPlus() && HasButtons())  // should the item show a button?
+        {
+            if (!HasFlag(wxTR_NO_LINES)) {
+                int lineOffset = m_indent - m_btnWidth2;
+                dc.DrawLine(x-lineOffset, y_mid, x-m_imgWidth2, y_mid);
+            }
+
+            // clip to the column width
+            wxDCClipper clipper(dc, x_colstart, y_top, clip_width, 10000);
+
+            if (m_imageListButtons != NULL)
+            {
+                // draw the image button here
+                int image = wxTreeItemIcon_Normal;
+                if (item->IsExpanded()) image = wxTreeItemIcon_Expanded;
+                if (item->IsSelected())
+                    image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal;
+                int xx = x + m_btnWidth2;
+                int yy = y_mid - m_btnHeight2;
+                dc.SetClippingRegion(xx, yy, m_btnWidth, m_btnHeight);
+                m_imageListButtons->Draw(image, dc, xx, yy,
+                                         wxIMAGELIST_DRAW_TRANSPARENT);
+                dc.DestroyClippingRegion();
+            }
+            else if (HasFlag(wxTR_TWIST_BUTTONS))
+            {
+                // draw the twisty button here
+                dc.SetPen(*wxBLACK_PEN);
+                dc.SetBrush(*m_hilightBrush);
+
+                wxPoint button[3];
+
+                if (item->IsExpanded())
+                {
+                    button[0].x = (x-m_indent) - m_btnWidth2;
+                    button[0].y = y_mid - (m_btnHeight/3-1);
+                    button[1].x = button[0].x + m_btnWidth;
+                    button[1].y = button[0].y;
+                    button[2].x = x;
+                    button[2].y = y_mid + (m_btnHeight/3);
+                }
+                else
+                {
+                    button[0].x = (x-m_indent) - (m_btnWidth/3-1);
+                    button[0].y = y_mid-m_btnHeight2;
+                    button[1].x = button[0].x;
+                    button[1].y = button[0].y + m_btnHeight;
+                    button[2].x = button[0].x + (m_btnWidth/3);
+                    button[2].y = y_mid;
+                }
+                dc.DrawPolygon(3, button);
+
+                dc.SetPen(m_dottedPen);
+            }
+            else // if (HasFlag(wxTR_HAS_BUTTONS))
+            {
+                // draw the plus sign here
+                dc.SetPen(*wxGREY_PEN);
+                dc.SetBrush(*wxWHITE_BRUSH);
+                int xpos = x - m_indent;
+                dc.DrawRectangle (xpos-m_btnWidth2, y_mid-m_btnHeight2,
+                                  m_btnWidth, m_btnHeight);
+                dc.SetPen(*wxBLACK_PEN);
+                dc.DrawLine (xpos-(m_btnWidth2-3), y_mid,
+                             xpos+(m_btnWidth2-2), y_mid);
+                if (!item->IsExpanded())
+                    dc.DrawLine (xpos, y_mid-(m_btnHeight2-2),
+                                 xpos, y_mid+(m_btnHeight2-1));
+                dc.SetPen(m_dottedPen);
+            }
+        }
+        else if (!HasFlag(wxTR_NO_LINES))  // no button; maybe a line?
+        {
+            // clip to the column width
+            wxDCClipper clipper(dc, x_colstart, y_top, clip_width, 10000);
+
+            // draw the horizontal line here
+            if (!(level == 0) && !((level == 1) && HasFlag(wxTR_HIDE_ROOT))) {
+                dc.DrawLine(x-m_indent, y_mid, x-m_imgWidth2, y_mid);
+            }
+        }
+
+        wxPen *pen =
+#ifndef __WXMAC__
+            // don't draw rect outline if we already have the
+            // background color under Mac
+            (item->IsSelected() && m_hasFocus) ? wxBLACK_PEN :
+#endif // !__WXMAC__
+            wxTRANSPARENT_PEN;
+
+        wxColour colText;
+        if ( item->IsSelected() )
+        {
+            colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
+        }
+        else
+        {
+            wxTreeItemAttr *attr = item->GetAttributes();
+            if (attr && attr->HasTextColour())
+                colText = attr->GetTextColour();
+            else
+                //colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT);
+                colText = GetForegroundColour();
+        }
+
+        // prepare to draw
+        dc.SetTextForeground(colText);
+        dc.SetPen(*pen);
+
+        // draw
+        PaintItem(item, dc);
+    }
+
+    // restore DC objects
+    dc.SetBrush(*wxWHITE_BRUSH);
+    dc.SetPen(m_dottedPen);
+    dc.SetTextForeground(*wxBLACK);
+
+    if (item->IsExpanded())
+    {
+        wxArrayTreeListItems& children = item->GetChildren();
+
+        // clip to the column width
+        size_t clip_width = m_owner->GetHeaderWindow()->
+                            GetColumn(m_main_column).GetWidth();
+        wxDCClipper clipper(dc, x_colstart, y_top, clip_width, 10000);
+
+        // process lower levels
+        int oldY = y_mid + m_imgHeight2;
+        int y2;
+        int n;
+        for (n = 0; n < (int)children.Count(); n++) {
+
+            if (!HasFlag(wxTR_NO_LINES))
+            {
+                // draw line down to last child
+                if (children[n]->HasPlus() && HasButtons()) {
+                    y2 = y + h/2 - m_btnHeight2;
+                    dc.DrawLine(x, oldY, x, y2);
+                    oldY = y2 + m_btnHeight;
+                }else{
+                    y2 = y + h/2;
+                    dc.DrawLine(x, oldY, x, y2);
+                    oldY = y2;
+                }
+            }
+
+            PaintLevel (children[n], dc, level+1, y, x_colstart);
+        }
+    }
+}
+
+void wxTreeListMainWindow::DrawDropEffect(wxTreeListItem *item)
+{
+    if ( item )
+    {
+        if ( item->HasPlus() )
+        {
+            // it's a folder, indicate it by a border
+            DrawBorder(item);
+        }
+        else
+        {
+            // draw a line under the drop target because the item will be
+            // dropped there
+            DrawLine(item, TRUE /* below */);
+        }
+
+        SetCursor(wxCURSOR_BULLSEYE);
+    }
+    else
+    {
+        // can't drop here
+        SetCursor(wxCURSOR_NO_ENTRY);
+    }
+}
+
+void wxTreeListMainWindow::DrawBorder(const wxTreeItemId &item)
+{
+    wxCHECK_RET( item.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") );
+
+    wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
+
+    wxClientDC dc(this);
+    PrepareDC( dc );
+    dc.SetLogicalFunction(wxINVERT);
+    dc.SetBrush(*wxTRANSPARENT_BRUSH);
+
+    int w = i->GetWidth() + 2;
+    int h = GetLineHeight(i) + 2;
+
+    dc.DrawRectangle( i->GetX() - 1, i->GetY() - 1, w, h);
+}
+
+void wxTreeListMainWindow::DrawLine(const wxTreeItemId &item, bool below)
+{
+    wxCHECK_RET( item.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") );
+
+    wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
+
+    wxClientDC dc(this);
+    PrepareDC( dc );
+    dc.SetLogicalFunction(wxINVERT);
+
+    int x = i->GetX(),
+        y = i->GetY();
+    if ( below )
+    {
+        y += GetLineHeight(i) - 1;
+    }
+
+    dc.DrawLine( x, y, x + i->GetWidth(), y);
+}
+
+// ----------------------------------------------------------------------------
+// wxWindows callbacks
+// ----------------------------------------------------------------------------
+
+void wxTreeListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
+{
+    wxPaintDC dc(this);
+
+    PrepareDC( dc );
+
+    if(!GetColumnCount()) return; // ALB
+
+    if ( !m_anchor)
+        return;
+
+    // calculate button size
+    m_btnWidth = 0, m_btnWidth2 = 0;
+    m_btnHeight = 0, m_btnHeight2 = 0;
+    if (m_imageListButtons) {
+        m_imageListButtons->GetSize (0, m_btnWidth, m_btnHeight);
+    }else if (HasButtons()) {
+        m_btnWidth = BTNWIDTH;
+        m_btnHeight = BTNHEIGHT;
+    }
+    m_btnWidth2 = m_btnWidth/2;
+    m_btnHeight2 = m_btnHeight/2;
+
+    // calculate image size
+    m_imgWidth = 0, m_imgWidth2 = 0;
+    m_imgHeight = 0, m_imgHeight2 = 0;
+    if (m_imageListNormal) {
+        m_imageListNormal->GetSize (0, m_imgWidth, m_imgHeight);
+        m_imgWidth += 4; //? ToDo: Why + 4?
+    }
+    m_imgWidth2 = m_imgWidth/2;
+    m_imgHeight2 = m_imgHeight/2;
+
+    // calculate indent size
+    int btnIndent = HasButtons()? m_btnWidth + LINEATROOT: 0;
+    m_indent = wxMax (MININDENT, wxMax (m_imgWidth, btnIndent)) + MARGIN;
+
+    // set default values
+    dc.SetFont( m_normalFont );
+    dc.SetPen( m_dottedPen );
+
+    // this is now done dynamically
+    //if(GetImageList() == NULL)
+    // m_lineHeight = (int)(dc.GetCharHeight() + 4);
+
+    // calculate column start and paint
+    int x_colstart = 0;
+    int i = 0;
+    for (i = 0; i < (int)GetMainColumn(); ++i) {
+        if (!m_owner->GetHeaderWindow()->GetColumnShown(i)) continue;
+        x_colstart += m_owner->GetHeaderWindow()->GetColumnWidth (i);
+    }
+    int y = 0;
+    PaintLevel ( m_anchor, dc, 0, y, x_colstart );
+}
+
+void wxTreeListMainWindow::OnSetFocus( wxFocusEvent &event )
+{
+    m_hasFocus = TRUE;
+
+    RefreshSelected();
+
+    event.Skip();
+}
+
+void wxTreeListMainWindow::OnKillFocus( wxFocusEvent &event )
+{
+    m_hasFocus = FALSE;
+
+    RefreshSelected();
+
+    event.Skip();
+}
+
+void wxTreeListMainWindow::OnChar( wxKeyEvent &event )
+{
+    wxTreeEvent te( wxEVT_COMMAND_TREE_KEY_DOWN, m_owner->GetId() );
+    te.SetKeyEvent( event );
+    te.SetEventObject( /*this*/m_owner );
+    if ( m_owner->GetEventHandler()->ProcessEvent( te ) )
+    {
+        // intercepted by the user code
+        return;
+    }
+
+    if ( (m_current == 0) || (m_key_current == 0) )
+    {
+        event.Skip();
+        return;
+    }
+
+    // how should the selection work for this event?
+    bool is_multiple, extended_select, unselect_others;
+    EventFlagsToSelType(GetWindowStyleFlag(),
+                        event.ShiftDown(),
+                        event.ControlDown(),
+                        is_multiple, extended_select, unselect_others);
+
+    // + : Expand (not on Win32)
+    // - : Collaspe (not on Win32)
+    // * : Expand all/Collapse all
+    // ' ' | return : activate
+    // up    : go up (not last children!)
+    // down  : go down
+    // left  : go to parent (or collapse on Win32)
+    // right : open if parent and go next (or expand on Win32)
+    // home  : go to root
+    // end   : go to last item without opening parents
+    switch (event.KeyCode())
+    {
+#ifndef __WXMSW__ // mimic the standard win32 tree ctrl
+        case '+':
+        case WXK_ADD:
+            if (m_current->HasPlus() && !IsExpanded(m_current))
+            {
+                Expand(m_current);
+            }
+            break;
+#endif // __WXMSW__
+
+        case '*':
+        case WXK_MULTIPLY:
+            if ( !IsExpanded(m_current) )
+            {
+                // expand all
+                ExpandAll(m_current);
+                break;
+            }
+            //else: fall through to Collapse() it
+
+#ifndef __WXMSW__ // mimic the standard wxTreeCtrl behaviour
+        case '-':
+        case WXK_SUBTRACT:
+            if (IsExpanded(m_current))
+            {
+                Collapse(m_current);
+            }
+            break;
+#endif // __WXMSW__
+
+        case ' ':
+        case WXK_RETURN:
+            {
+                wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
+                                   m_owner->GetId() );
+                event.SetItem( (long) m_current);
+                event.SetEventObject( /*this*/m_owner );
+                m_owner->GetEventHandler()->ProcessEvent( event );
+            }
+            break;
+
+            // up goes to the previous sibling or to the last
+            // of its children if it's expanded
+        case WXK_UP:
+            {
+                wxTreeItemId prev = GetPrevSibling( m_key_current );
+                if (!prev)
+                {
+                    prev = GetItemParent( m_key_current );
+                    if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT))
+                    {
+                        break;  // don't go to root if it is hidden
+                    }
+                    if (prev)
+                    {
+                        long cookie = 0;
+                        wxTreeItemId current = m_key_current;
+                        // TODO: Huh?  If we get here, we'd better be the first child of our parent.  How else could it be?
+                        if (current == GetFirstChild( prev, cookie ))
+                        {
+                            // otherwise we return to where we came from
+                            SelectItem( prev, unselect_others, extended_select );
+                            m_key_current= (wxTreeListItem*) prev.m_pItem;
+                            EnsureVisible( prev );
+                            break;
+                        }
+                    }
+                }
+                if (prev)
+                {
+                    while ( IsExpanded(prev) && HasChildren(prev) )
+                    {
+                        wxTreeItemId child = GetLastChild(prev);
+                        if ( child )
+                        {
+                            prev = child;
+                        }
+                    }
+
+                    SelectItem( prev, unselect_others, extended_select );
+                    m_key_current=(wxTreeListItem*) prev.m_pItem;
+                    EnsureVisible( prev );
+                }
+            }
+            break;
+
+            // left arrow goes to the parent
+        case WXK_LEFT:
+#if defined(__WXMSW__) // mimic the standard win32 tree ctrl
+            if (IsExpanded(m_current))
+            {
+                Collapse(m_current);
+            }
+            else
+#endif // __WXMSW__
+            {
+                wxTreeItemId prev = GetItemParent( m_current );
+                if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT))
+                {
+                    // don't go to root if it is hidden
+                    prev = GetPrevSibling( m_current );
+                }
+                if (prev)
+                {
+                    EnsureVisible( prev );
+                    SelectItem( prev, unselect_others, extended_select );
+                }
+            }
+            break;
+
+        case WXK_RIGHT:
+#if defined(__WXMSW__) // mimic the standard win32 tree ctrl
+            if (m_current->HasPlus() && !IsExpanded(m_current))
+            {
+                Expand(m_current);
+                break;
+            }
+#endif // __WXMSW__
+
+            // this works the same as the down arrow except that we
+            // also expand the item if it wasn't expanded yet
+            Expand(m_current);
+            // fall through
+
+        case WXK_DOWN:
+            {
+                if (IsExpanded(m_key_current) && HasChildren(m_key_current))
+                {
+                    long cookie = 0;
+                    wxTreeItemId child = GetFirstChild( m_key_current, cookie );
+                    SelectItem( child, unselect_others, extended_select );
+                    m_key_current=(wxTreeListItem*) child.m_pItem;
+                    EnsureVisible( child );
+                }
+                else
+                {
+                    wxTreeItemId next = GetNextSibling( m_key_current );
+                    if (!next)
+                    {
+                        wxTreeItemId current = m_key_current;
+                        while (current && !next)
+                        {
+                            current = GetItemParent( current );
+                            if (current) next = GetNextSibling( current );
+                        }
+                    }
+                    if (next)
+                    {
+                        SelectItem( next, unselect_others, extended_select );
+                        m_key_current=(wxTreeListItem*) next.m_pItem;
+                        EnsureVisible( next );
+                    }
+                }
+            }
+            break;
+
+            // <End> selects the last visible tree item
+        case WXK_END:
+            {
+                wxTreeItemId last = GetRootItem();
+
+                while ( last.IsOk() && IsExpanded(last) )
+                {
+                    wxTreeItemId lastChild = GetLastChild(last);
+
+                    // it may happen if the item was expanded but then all of
+                    // its children have been deleted - so IsExpanded() returned
+                    // TRUE, but GetLastChild() returned invalid item
+                    if ( !lastChild )
+                        break;
+
+                    last = lastChild;
+                }
+
+                if ( last.IsOk() )
+                {
+                    EnsureVisible( last );
+                    SelectItem( last, unselect_others, extended_select );
+                }
+            }
+            break;
+
+            // <Home> selects the root item
+        case WXK_HOME:
+            {
+                wxTreeItemId prev = GetRootItem();
+                if (!prev) break;
+                if (HasFlag(wxTR_HIDE_ROOT))
+                {
+                    long dummy;
+                    prev = GetFirstChild(prev, dummy);
+                    if (!prev) break;
+                }
+                EnsureVisible( prev );
+                SelectItem( prev, unselect_others, extended_select );
+            }
+            break;
+
+        default:
+            event.Skip();
+    }
+}
+
+wxTreeItemId wxTreeListMainWindow::HitTest(const wxPoint& point, int& flags,
+                                           int& column)
+{
+    // JACS: removed wxYieldIfNeeded() because it can cause the window
+    // to be deleted from under us if a close window event is pending
+
+    int w, h;
+    GetSize(&w, &h);
+    flags=0;
+    column = -1;
+    if (point.x<0) flags |= wxTREE_HITTEST_TOLEFT;
+    if (point.x>w) flags |= wxTREE_HITTEST_TORIGHT;
+    if (point.y<0) flags |= wxTREE_HITTEST_ABOVE;
+    if (point.y>h) flags |= wxTREE_HITTEST_BELOW;
+    if (flags) return wxTreeItemId();
+
+    if (m_anchor == NULL)
+    {
+        flags = wxTREE_HITTEST_NOWHERE;
+        return wxTreeItemId();
+    }
+
+    wxClientDC dc(this);
+    PrepareDC(dc);
+    wxCoord x = dc.DeviceToLogicalX( point.x );
+    wxCoord y = dc.DeviceToLogicalY( point.y );
+    wxTreeListItem *hit = m_anchor->HitTest(wxPoint(x, y), this, flags,
+                                            column, 0);
+    if (hit == NULL)
+    {
+        flags = wxTREE_HITTEST_NOWHERE;
+        return wxTreeItemId();
+    }
+    return hit;
+}
+
+// get the bounding rectangle of the item (or of its label only)
+bool wxTreeListMainWindow::GetBoundingRect(const wxTreeItemId& item,
+                         wxRect& rect,
+                         bool WXUNUSED(textOnly)) const
+{
+    wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") );
+
+    wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
+
+    int startX, startY;
+    GetViewStart(& startX, & startY);
+
+    rect.x = i->GetX() - startX*PIXELS_PER_UNIT;
+    rect.y = i->GetY() - startY*PIXELS_PER_UNIT;
+    rect.width = i->GetWidth();
+    //rect.height = i->GetHeight();
+    rect.height = GetLineHeight(i);
+
+    return TRUE;
+}
+
+/* **** */
+
+void wxTreeListMainWindow::Edit( const wxTreeItemId& item )
+{
+    if (!item.IsOk()) return;
+
+    m_currentEdit = (wxTreeListItem*) item.m_pItem;
+
+    wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, m_owner->GetId() );
+    te.SetItem( (long) m_currentEdit);
+    te.SetEventObject( /*this*/m_owner );
+    m_owner->GetEventHandler()->ProcessEvent( te );
+
+    if (!te.IsAllowed()) return;
+
+    // We have to call this here because the label in
+    // question might just have been added and no screen
+    // update taken place.
+    if (m_dirty) wxYieldIfNeeded();
+
+    wxString s = m_currentEdit->GetText(/*ALB*/m_main_column);
+    int x = m_currentEdit->GetX();
+    int y = m_currentEdit->GetY();
+    int w = m_currentEdit->GetWidth();
+    int h = m_currentEdit->GetHeight();
+
+    int image = m_currentEdit->GetCurrentImage();
+    x += m_imgWidth;
+    w -= m_imgWidth + 4; // I don't know why +4 is needed
+
+    wxClientDC dc(this);
+    PrepareDC( dc );
+    x = dc.LogicalToDeviceX( x );
+    y = dc.LogicalToDeviceY( y );
+
+    wxTreeListTextCtrl *text = new wxTreeListTextCtrl(this, -1,
+                                              &m_renameAccept,
+                                              &m_renameRes,
+                                              this,
+                                              s,
+                                              wxPoint(x-4,y-4),
+                                              wxSize(w+11,h+8));
+    text->SetFocus();
+}
+
+void wxTreeListMainWindow::OnRenameTimer()
+{
+    Edit( m_current );
+}
+
+void wxTreeListMainWindow::OnRenameAccept()
+{
+    // TODO if the validator fails this causes a crash
+    wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, m_owner->GetId() );
+    le.SetItem( (long) m_currentEdit );
+    le.SetEventObject( /*this*/m_owner );
+    le.SetLabel( m_renameRes );
+    m_owner->GetEventHandler()->ProcessEvent( le );
+
+    if (!le.IsAllowed()) return;
+
+    SetItemText( m_currentEdit, m_renameRes );
+}
+
+void wxTreeListMainWindow::OnMouse( wxMouseEvent &event )
+{
+    if ( !m_anchor ) return;
+
+    // we process left mouse up event (enables in-place edit), right down
+    // (pass to the user code), left dbl click (activate item) and
+    // dragging/moving events for items drag-and-drop
+    if ( !(event.LeftDown() ||
+           event.LeftUp() ||
+           event.RightDown() ||
+           event.LeftDClick() ||
+           event.Dragging() ||
+           ((event.Moving() || event.RightUp()) && m_isDragging)) )
+    {
+        event.Skip();
+        return;
+    }
+
+    if ( event.LeftDown() )
+        SetFocus();
+
+    wxClientDC dc(this);
+    PrepareDC(dc);
+    wxCoord x = dc.DeviceToLogicalX( event.GetX() );
+    wxCoord y = dc.DeviceToLogicalY( event.GetY() );
+
+    int flags = 0;
+    wxTreeListItem *item = m_anchor->HitTest(wxPoint(x,y), this, flags, 0);
+
+    if ( event.Dragging() && !m_isDragging )
+    {
+        if (m_dragCount == 0)
+            m_dragStart = wxPoint(x,y);
+
+        m_dragCount++;
+
+        if (m_dragCount != 3)
+        {
+            // wait until user drags a bit further...
+            return;
+        }
+
+        wxEventType command = event.RightIsDown()
+                              ? wxEVT_COMMAND_TREE_BEGIN_RDRAG
+                              : wxEVT_COMMAND_TREE_BEGIN_DRAG;
+
+        wxTreeEvent nevent( command,/*ALB*/ m_owner->GetId() );
+        nevent.SetItem( (long) m_current);
+        nevent.SetEventObject(/*this*/m_owner); // ALB
+
+        // by default the dragging is not supported, the user code must
+        // explicitly allow the event for it to take place
+        nevent.Veto();
+
+        if ( m_owner->GetEventHandler()->ProcessEvent(nevent) &&
+             nevent.IsAllowed() )
+        {
+            // we're going to drag this item
+            m_isDragging = TRUE;
+
+            // remember the old cursor because we will change it while
+            // dragging
+            m_oldCursor = m_cursor;
+
+            // in a single selection control, hide the selection temporarily
+            if ( !(GetWindowStyleFlag() & wxTR_MULTIPLE) )
+            {
+                m_oldSelection = (wxTreeListItem*) GetSelection().m_pItem;
+
+                if ( m_oldSelection )
+                {
+                    m_oldSelection->SetHilight(FALSE);
+                    RefreshLine(m_oldSelection);
+                }
+            }
+
+            CaptureMouse();
+        }
+    }
+    else if ( event.Moving() )
+    {
+        if ( item != m_dropTarget )
+        {
+            // unhighlight the previous drop target
+            DrawDropEffect(m_dropTarget);
+
+            m_dropTarget = item;
+
+            // highlight the current drop target if any
+            DrawDropEffect(m_dropTarget);
+
+            wxYieldIfNeeded();
+        }
+    }
+    else if ( (event.LeftUp() || event.RightUp()) && m_isDragging )
+    {
+        // erase the highlighting
+        DrawDropEffect(m_dropTarget);
+
+        if ( m_oldSelection )
+        {
+            m_oldSelection->SetHilight(TRUE);
+            RefreshLine(m_oldSelection);
+            m_oldSelection = (wxTreeListItem *)NULL;
+        }
+
+        // generate the drag end event
+        wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG,/*ALB*/m_owner->GetId());
+
+        event.SetItem( (long) item );
+        event.SetPoint( wxPoint(x, y) );
+        event.SetEventObject(/*this*/m_owner);
+
+        (void)m_owner->GetEventHandler()->ProcessEvent(event);
+
+        m_isDragging = FALSE;
+        m_dropTarget = (wxTreeListItem *)NULL;
+
+        ReleaseMouse();
+
+        SetCursor(m_oldCursor);
+
+        wxYieldIfNeeded();
+    }
+    else
+    {
+        // here we process only the messages which happen on tree items
+
+        m_dragCount = 0;
+
+        if ( item == NULL ) return;  /* we hit the blank area */
+
+        if ( event.RightDown() )
+        {
+            SetFocus();
+            wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK,
+                               m_owner->GetId());
+            nevent.SetItem( (long) item );
+            int nx, ny;
+            CalcScrolledPosition(x, y, &nx, &ny);
+            nevent.SetPoint( wxPoint(nx, ny));
+            nevent.SetEventObject(/*this*/m_owner);
+            m_owner->GetEventHandler()->ProcessEvent(nevent);
+        }
+        else if ( event.LeftUp() )
+        {
+            if ( m_lastOnSame )
+            {
+                if ( ( item == m_current ) &&
+                     ( flags & wxTREE_HITTEST_ONITEMLABEL ) &&
+                     HasFlag(wxTR_EDIT_LABELS ) )
+                {
+                    if ( m_renameTimer->IsRunning() )
+                        m_renameTimer->Stop();
+
+                    m_renameTimer->Start( 100, TRUE );
+                }
+
+                m_lastOnSame = FALSE;
+            }
+        }
+        else // !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick()
+        {
+            if ( event.LeftDown() )
+            {
+                SetFocus();
+                m_lastOnSame = item == m_current;
+            }
+
+            if ((flags & wxTREE_HITTEST_ONITEMBUTTON) ||
+                ((flags & wxTREE_HITTEST_ONITEMICON)) &&
+                 !HasButtons() && item->HasPlus())
+            {
+                // only toggle the item for a single click, double click on
+                // the button doesn't do anything (it toggles the item twice)
+                if ( event.LeftDown() )
+                {
+                    Toggle( item );
+                }
+
+                // don't select the item if the button was clicked
+                return;
+            }
+
+            // how should the selection work for this event?
+            bool is_multiple, extended_select, unselect_others;
+            EventFlagsToSelType(GetWindowStyleFlag(),
+                                event.ShiftDown(),
+                                event.ControlDown(),
+                                is_multiple, extended_select, unselect_others);
+
+            SelectItem (item, unselect_others, extended_select);
+
+            // For some reason, Windows isn't recognizing a left double-click,
+            // so we need to simulate it here.  Allow 200 milliseconds for now.
+            if ( event.LeftDClick() )
+            {
+                // double clicking should not start editing the item label
+                m_renameTimer->Stop();
+                m_lastOnSame = FALSE;
+
+                // send activate event first
+                wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED,
+                                    m_owner->GetId() );
+                nevent.SetItem( (long) item );
+                int nx, ny;
+                CalcScrolledPosition(x, y, &nx, &ny);
+                nevent.SetPoint( wxPoint(nx, ny) );
+                nevent.SetEventObject( /*this*/m_owner );
+                if ( !m_owner->GetEventHandler()->ProcessEvent( nevent ) )
+                {
+                    // if the user code didn't process the activate event,
+                    // handle it ourselves by toggling the item when it is
+                    // double clicked
+                    if ( item->HasPlus() )
+                    {
+                        Toggle(item);
+                    }
+                }
+            }
+        }
+    }
+}
+
+void wxTreeListMainWindow::OnIdle( wxIdleEvent &WXUNUSED(event) )
+{
+    /* after all changes have been done to the tree control,
+     * we actually redraw the tree when everything is over */
+
+    if (!m_dirty) return;
+
+    m_dirty = FALSE;
+
+    CalculatePositions();
+    Refresh();
+    AdjustMyScrollbars();
+}
+
+void wxTreeListMainWindow::OnSize(wxSizeEvent& WXUNUSED(event))
+{
+//     int w, h;
+//     GetClientSize(&w, &h);
+//     m_header_win->SetSize(0, 0, w, HEADER_HEIGHT);
+}
+
+void wxTreeListMainWindow::OnScroll(wxScrollWinEvent& event)
+{
+    // FIXME
+#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
+    wxScrolledWindow::OnScroll(event);
+#else
+    HandleOnScroll( event );
+#endif
+
+    if(event.GetOrientation() == wxHORIZONTAL)
+    {
+        m_owner->GetHeaderWindow()->Refresh();
+#ifdef __WXMAC__
+        m_owner->GetHeaderWindow()->MacUpdateImmediately();
+#endif
+    }
+}
+
+
+void wxTreeListMainWindow::CalculateSize( wxTreeListItem *item, wxDC &dc )
+{
+    wxCoord text_w = 0;
+    wxCoord text_h = 0;
+
+    if (item->IsBold())
+        dc.SetFont(m_boldFont);
+
+    dc.GetTextExtent( item->GetText(/*ALB*/m_main_column), &text_w, &text_h );
+    text_h+=2;
+
+    // restore normal font
+    dc.SetFont( m_normalFont );
+
+    int image = item->GetCurrentImage();
+    int total_h = (m_imgHeight > text_h) ? m_imgHeight : text_h;
+
+    item->SetHeight(total_h);
+    if (total_h>m_lineHeight)
+        m_lineHeight=total_h;
+
+    item->SetWidth(m_imgWidth + text_w+2);
+}
+
+// -----------------------------------------------------------------------------
+// for developper : y is now the top of the level
+// not the middle of it !
+void wxTreeListMainWindow::CalculateLevel( wxTreeListItem *item, wxDC &dc,
+                                        int level, int &y, int x_colstart )
+{
+    // calculate position of vertical lines
+    int x = x_colstart + MARGIN; // start of column
+    if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
+    if (HasButtons()) x += m_btnWidth2; // space for buttons etc.
+    if (!HasFlag(wxTR_HIDE_ROOT)) x += m_indent; // indent root as well
+    x += m_indent * level; // indent according to level
+
+    // a hidden root is not evaluated, but its children are always
+    if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) goto Recurse;
+
+    CalculateSize( item, dc );
+
+    // set its position
+    item->SetX (x);
+    item->SetY (y);
+    y += GetLineHeight(item);
+
+        // we don't need to calculate collapsed branches
+    if ( !item->IsExpanded() ) return;
+
+Recurse:
+    wxArrayTreeListItems& children = item->GetChildren();
+    size_t n, count = children.Count();
+    ++level;
+    for (n = 0; n < count; ++n )
+        CalculateLevel( children[n], dc, level, y, x_colstart );  // recurse
+}
+
+void wxTreeListMainWindow::CalculatePositions()
+{
+    if ( !m_anchor ) return;
+
+    wxClientDC dc(this);
+    PrepareDC( dc );
+
+    dc.SetFont( m_normalFont );
+
+    dc.SetPen( m_dottedPen );
+    //if(GetImageList() == NULL)
+    // m_lineHeight = (int)(dc.GetCharHeight() + 4);
+
+    int y = 2;
+    int x_colstart = 0;
+    for(size_t i = 0; i < GetMainColumn(); ++i) {
+        if (!m_owner->GetHeaderWindow()->GetColumnShown(i)) continue;
+        x_colstart += m_owner->GetHeaderWindow()->GetColumnWidth(i);
+    }
+    CalculateLevel( m_anchor, dc, 0, y, x_colstart ); // start recursion
+}
+
+void wxTreeListMainWindow::RefreshSubtree(wxTreeListItem *item)
+{
+    if (m_dirty) return;
+
+    wxClientDC dc(this);
+    PrepareDC(dc);
+
+    int cw = 0;
+    int ch = 0;
+    GetClientSize( &cw, &ch );
+
+    wxRect rect;
+    rect.x = dc.LogicalToDeviceX( 0 );
+    rect.width = cw;
+    rect.y = dc.LogicalToDeviceY( item->GetY() - 2 );
+    rect.height = ch;
+
+    Refresh( TRUE, &rect );
+
+    AdjustMyScrollbars();
+}
+
+void wxTreeListMainWindow::RefreshLine( wxTreeListItem *item )
+{
+    if (m_dirty) return;
+
+    wxClientDC dc(this);
+    PrepareDC( dc );
+
+    int cw = 0;
+    int ch = 0;
+    GetClientSize( &cw, &ch );
+
+    wxRect rect;
+    rect.x = dc.LogicalToDeviceX( 0 );
+    rect.y = dc.LogicalToDeviceY( item->GetY() );
+    rect.width = cw;
+    rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6;
+
+    Refresh( TRUE, &rect );
+}
+
+void wxTreeListMainWindow::RefreshSelected()
+{
+    // TODO: this is awfully inefficient, we should keep the list of all
+    //       selected items internally, should be much faster
+    if ( m_anchor )
+        RefreshSelectedUnder(m_anchor);
+}
+
+void wxTreeListMainWindow::RefreshSelectedUnder(wxTreeListItem *item)
+{
+    if ( item->IsSelected() )
+        RefreshLine(item);
+
+    const wxArrayTreeListItems& children = item->GetChildren();
+    size_t count = children.GetCount();
+    for ( size_t n = 0; n < count; n++ )
+    {
+        RefreshSelectedUnder(children[n]);
+    }
+}
+
+// ----------------------------------------------------------------------------
+// changing colours: we need to refresh the tree control
+// ----------------------------------------------------------------------------
+
+bool wxTreeListMainWindow::SetBackgroundColour(const wxColour& colour)
+{
+    if ( !wxWindow::SetBackgroundColour(colour) )
+        return FALSE;
+
+    Refresh();
+
+    return TRUE;
+}
+
+bool wxTreeListMainWindow::SetForegroundColour(const wxColour& colour)
+{
+    if ( !wxWindow::SetForegroundColour(colour) )
+        return FALSE;
+
+    Refresh();
+
+    return TRUE;
+}
+
+//----------- ALB -------------
+inline
+void wxTreeListMainWindow::SetItemText(const wxTreeItemId& item, size_t column,
+                                    const wxString& text)
+{
+    wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
+
+    wxClientDC dc(this);
+    wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
+    pItem->SetText(column, text);
+    CalculateSize(pItem, dc);
+    RefreshLine(pItem);
+}
+
+inline
+wxString wxTreeListMainWindow::GetItemText(const wxTreeItemId& item,
+                                     size_t column) const
+{
+    wxCHECK_MSG( item.IsOk(), wxT(""), wxT("invalid tree item") );
+
+    return ((wxTreeListItem*) item.m_pItem)->GetText(column);
+}
+
+//-----------------------------
+
+//-----------------------------------------------------------------------------
+//  wxTreeListCtrl
+//-----------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl, wxControl);
+
+BEGIN_EVENT_TABLE(wxTreeListCtrl, wxControl)
+    EVT_SIZE(wxTreeListCtrl::OnSize)
+END_EVENT_TABLE();
+
+bool wxTreeListCtrl::Create(wxWindow *parent, wxWindowID id,
+                            const wxPoint& pos,
+                            const wxSize& size,
+                            long style, const wxValidator &validator,
+                            const wxString& name)
+{
+    long main_style = style & ~(wxRAISED_BORDER|wxSUNKEN_BORDER
+                                |wxSIMPLE_BORDER|wxNO_BORDER|wxDOUBLE_BORDER
+                                |wxSTATIC_BORDER);
+    long ctrl_style = style & ~(wxVSCROLL|wxHSCROLL);
+
+    if (!wxControl::Create(parent, id, pos, size, ctrl_style, validator, name)) {
+       return false;
+    }
+    m_main_win = new wxTreeListMainWindow(this, -1, wxPoint(0, 0), size,
+                                          main_style, validator);
+    m_header_win = new wxTreeListHeaderWindow(this, -1, m_main_win,
+                                              wxPoint(0, 0), wxDefaultSize,
+                                              wxTAB_TRAVERSAL);
+    return TRUE;
+}
+
+void wxTreeListCtrl::OnSize(wxSizeEvent& event)
+{
+    int w, h;
+    GetClientSize(&w, &h);
+    if(m_header_win)
+        m_header_win->SetSize(0, 0, w, HEADER_HEIGHT);
+    if(m_main_win)
+        m_main_win->SetSize(0, HEADER_HEIGHT + 1, w, h - HEADER_HEIGHT - 1);
+}
+
+
+size_t wxTreeListCtrl::GetCount() const { return m_main_win->GetCount(); }
+
+unsigned int wxTreeListCtrl::GetIndent() const
+{ return m_main_win->GetIndent(); }
+
+void wxTreeListCtrl::SetIndent(unsigned int indent)
+{ m_main_win->SetIndent(indent); }
+
+unsigned int wxTreeListCtrl::GetLineSpacing() const
+{ return m_main_win->GetLineSpacing(); }
+
+void wxTreeListCtrl::SetLineSpacing(unsigned int spacing)
+{ m_main_win->SetLineSpacing(spacing); }
+
+wxImageList* wxTreeListCtrl::GetImageList() const
+{ return m_main_win->GetImageList(); }
+
+wxImageList* wxTreeListCtrl::GetStateImageList() const
+{ return m_main_win->GetStateImageList(); }
+
+wxImageList* wxTreeListCtrl::GetButtonsImageList() const
+{ return m_main_win->GetButtonsImageList(); }
+
+void wxTreeListCtrl::SetImageList(wxImageList* imageList)
+{ m_main_win->SetImageList(imageList); }
+
+void wxTreeListCtrl::SetStateImageList(wxImageList* imageList)
+{ m_main_win->SetStateImageList(imageList); }
+
+void wxTreeListCtrl::SetButtonsImageList(wxImageList* imageList)
+{ m_main_win->SetButtonsImageList(imageList); }
+
+void wxTreeListCtrl::AssignImageList(wxImageList* imageList)
+{ m_main_win->AssignImageList(imageList); }
+
+void wxTreeListCtrl::AssignStateImageList(wxImageList* imageList)
+{ m_main_win->AssignStateImageList(imageList); }
+
+void wxTreeListCtrl::AssignButtonsImageList(wxImageList* imageList)
+{ m_main_win->AssignButtonsImageList(imageList); }
+
+wxString wxTreeListCtrl::GetItemText(const wxTreeItemId& item, size_t column)
+    const
+{ return m_main_win->GetItemText(item, column); }
+
+int wxTreeListCtrl::GetItemImage(const wxTreeItemId& item, size_t column,
+                                 wxTreeItemIcon which) const
+{ return m_main_win->GetItemImage(item, column, which); }
+
+wxTreeItemData* wxTreeListCtrl::GetItemData(const wxTreeItemId& item) const
+{ return m_main_win->GetItemData(item); }
+
+bool wxTreeListCtrl::GetItemBold(const wxTreeItemId& item) const
+{ return m_main_win->GetItemBold(item); }
+
+wxColour wxTreeListCtrl::GetItemTextColour(const wxTreeItemId& item) const
+{ return m_main_win->GetItemTextColour(item); }
+
+wxColour wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId& item)
+    const
+{ return m_main_win->GetItemBackgroundColour(item); }
+
+wxFont wxTreeListCtrl::GetItemFont(const wxTreeItemId& item) const
+{ return m_main_win->GetItemFont(item); }
+
+
+void wxTreeListCtrl::SetItemText(const wxTreeItemId& item, size_t column,
+                                 const wxString& text)
+{ m_main_win->SetItemText(item, column, text); }
+
+void wxTreeListCtrl::SetItemImage(const wxTreeItemId& item,
+                                  size_t column,
+                                  int image,
+                                  wxTreeItemIcon which)
+{ m_main_win->SetItemImage(item, column, image, which); }
+
+void wxTreeListCtrl::SetItemData(const wxTreeItemId& item,
+                                 wxTreeItemData* data)
+{ m_main_win->SetItemData(item, data); }
+
+void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
+{ m_main_win->SetItemHasChildren(item, has); }
+
+void wxTreeListCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
+{ m_main_win->SetItemBold(item, bold); }
+
+void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId& item,
+                                       const wxColour& col)
+{ m_main_win->SetItemTextColour(item, col); }
+
+void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId& item,
+                                             const wxColour& col)
+{ m_main_win->SetItemBackgroundColour(item, col); }
+
+void wxTreeListCtrl::SetItemFont(const wxTreeItemId& item,
+                                 const wxFont& font)
+{ m_main_win->SetItemFont(item, font); }
+
+bool wxTreeListCtrl::SetFont(const wxFont& font)
+{
+    if(m_header_win) m_header_win->SetFont(font);
+    if(m_main_win)
+        return m_main_win->SetFont(font);
+    else return FALSE;
+}
+
+void wxTreeListCtrl::SetWindowStyle(const long style)
+{
+    if(m_main_win)
+        m_main_win->SetWindowStyle(style);
+    // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win
+}
+
+long wxTreeListCtrl::GetWindowStyle() const
+{
+    long style = m_windowStyle;
+    if(m_main_win)
+        style |= m_main_win->GetWindowStyle();
+    return style;
+}
+
+bool wxTreeListCtrl::IsVisible(const wxTreeItemId& item) const
+{ return m_main_win->IsVisible(item); }
+
+bool wxTreeListCtrl::ItemHasChildren(const wxTreeItemId& item) const
+{ return m_main_win->ItemHasChildren(item); }
+
+bool wxTreeListCtrl::IsExpanded(const wxTreeItemId& item) const
+{ return m_main_win->IsExpanded(item); }
+
+bool wxTreeListCtrl::IsSelected(const wxTreeItemId& item) const
+{ return m_main_win->IsSelected(item); }
+
+bool wxTreeListCtrl::IsBold(const wxTreeItemId& item) const
+{ return m_main_win->IsBold(item); }
+
+size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId& item, bool rec)
+{ return m_main_win->GetChildrenCount(item, rec); }
+
+wxTreeItemId wxTreeListCtrl::GetRootItem() const
+{ return m_main_win->GetRootItem(); }
+
+wxTreeItemId wxTreeListCtrl::GetSelection() const
+{ return m_main_win->GetSelection(); }
+
+size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds& arr) const
+{ return m_main_win->GetSelections(arr); }
+
+wxTreeItemId wxTreeListCtrl::GetItemParent(const wxTreeItemId& item) const
+{ return m_main_win->GetItemParent(item); }
+
+wxTreeItemId wxTreeListCtrl::GetFirstChild(const wxTreeItemId& item,
+                                           long& cookie) const
+{ return m_main_win->GetFirstChild(item, cookie); }
+
+wxTreeItemId wxTreeListCtrl::GetNextChild(const wxTreeItemId& item,
+                                          long& cookie) const
+{ return m_main_win->GetNextChild(item, cookie); }
+
+wxTreeItemId wxTreeListCtrl::GetLastChild(const wxTreeItemId& item) const
+{ return m_main_win->GetLastChild(item); }
+
+wxTreeItemId wxTreeListCtrl::GetNextSibling(const wxTreeItemId& item) const
+{ return m_main_win->GetNextSibling(item); }
+
+wxTreeItemId wxTreeListCtrl::GetPrevSibling(const wxTreeItemId& item) const
+{ return m_main_win->GetPrevSibling(item); }
+
+wxTreeItemId wxTreeListCtrl::GetFirstVisibleItem() const
+{ return m_main_win->GetFirstVisibleItem(); }
+
+wxTreeItemId wxTreeListCtrl::GetNextVisible(const wxTreeItemId& item) const
+{ return m_main_win->GetNextVisible(item); }
+
+wxTreeItemId wxTreeListCtrl::GetPrevVisible(const wxTreeItemId& item) const
+{ return m_main_win->GetPrevVisible(item); }
+
+wxTreeItemId wxTreeListCtrl::GetNext(const wxTreeItemId& item) const
+{ return m_main_win->GetNext(item); }
+
+wxTreeItemId wxTreeListCtrl::AddRoot(const wxString& text, int image,
+                                     int selectedImage, wxTreeItemData* data)
+{ return m_main_win->AddRoot(text, image, selectedImage, data); }
+
+wxTreeItemId wxTreeListCtrl::PrependItem(const wxTreeItemId& parent,
+                                         const wxString& text, int image,
+                                         int selectedImage,
+                                         wxTreeItemData* data)
+{ return m_main_win->PrependItem(parent, text, image, selectedImage, data); }
+
+wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
+                                        const wxTreeItemId& previous,
+                                        const wxString& text, int image,
+                                        int selectedImage,
+                                        wxTreeItemData* data)
+{
+    return m_main_win->InsertItem(parent, previous, text, image,
+                                  selectedImage, data);
+}
+
+wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
+                                        size_t index,
+                                        const wxString& text, int image,
+                                        int selectedImage,
+                                        wxTreeItemData* data)
+{
+    return m_main_win->InsertItem(parent, index, text, image,
+                                  selectedImage, data);
+}
+
+wxTreeItemId wxTreeListCtrl::AppendItem(const wxTreeItemId& parent,
+                                        const wxString& text, int image,
+                                        int selectedImage,
+                                        wxTreeItemData* data)
+{ return m_main_win->AppendItem(parent, text, image, selectedImage, data); }
+
+void wxTreeListCtrl::Delete(const wxTreeItemId& item)
+{ m_main_win->Delete(item); }
+
+void wxTreeListCtrl::DeleteChildren(const wxTreeItemId& item)
+{ m_main_win->DeleteChildren(item); }
+
+void wxTreeListCtrl::DeleteAllItems()
+{ m_main_win->DeleteAllItems(); }
+
+void wxTreeListCtrl::Expand(const wxTreeItemId& item)
+{ m_main_win->Expand(item); }
+
+void wxTreeListCtrl::ExpandAll(const wxTreeItemId& item)
+{ m_main_win->ExpandAll(item); }
+
+void wxTreeListCtrl::Collapse(const wxTreeItemId& item)
+{ m_main_win->Collapse(item); }
+
+void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId& item)
+{ m_main_win->CollapseAndReset(item); }
+
+void wxTreeListCtrl::Toggle(const wxTreeItemId& item)
+{ m_main_win->Toggle(item); }
+
+void wxTreeListCtrl::Unselect()
+{ m_main_win->Unselect(); }
+
+void wxTreeListCtrl::UnselectAll()
+{ m_main_win->UnselectAll(); }
+
+void wxTreeListCtrl::SelectItem(const wxTreeItemId& item, bool unselect_others,
+                                bool extended_select)
+{ m_main_win->SelectItem(item, unselect_others, extended_select); }
+
+void wxTreeListCtrl::EnsureVisible(const wxTreeItemId& item)
+{ m_main_win->EnsureVisible(item); }
+
+void wxTreeListCtrl::ScrollTo(const wxTreeItemId& item)
+{ m_main_win->ScrollTo(item); }
+
+wxTreeItemId wxTreeListCtrl::HitTest(const wxPoint& pos, int& flags,
+                                     int& column)
+{
+    return m_main_win->HitTest(m_main_win->ScreenToClient(ClientToScreen(pos)),
+                               flags, column);
+}
+
+bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId& item, wxRect& rect,
+                                     bool textOnly) const
+{ return m_main_win->GetBoundingRect(item, rect, textOnly); }
+
+void wxTreeListCtrl::Edit(const wxTreeItemId& item)
+{ m_main_win->Edit(item); }
+
+int wxTreeListCtrl::OnCompareItems(const wxTreeItemId& item1,
+                                   const wxTreeItemId& item2)
+{
+    // ALB: do the comparison here, and not delegate to m_main_win, in order
+    // to let the user override it
+    //return m_main_win->OnCompareItems(item1, item2);
+    return wxStrcmp(GetItemText(item1), GetItemText(item2));
+}
+
+void wxTreeListCtrl::SortChildren(const wxTreeItemId& item)
+{ m_main_win->SortChildren(item); }
+
+bool wxTreeListCtrl::SetBackgroundColour(const wxColour& colour)
+{ return m_main_win->SetBackgroundColour(colour); }
+
+bool wxTreeListCtrl::SetForegroundColour(const wxColour& colour)
+{ return m_main_win->SetForegroundColour(colour); }
+
+size_t wxTreeListCtrl::GetColumnCount() const
+{ return m_main_win->GetColumnCount(); }
+
+void wxTreeListCtrl::SetColumnWidth(size_t column, size_t width)
+{ m_header_win->SetColumnWidth(column, width); }
+
+int wxTreeListCtrl::GetColumnWidth(size_t column) const
+{ return m_header_win->GetColumnWidth(column); }
+
+void wxTreeListCtrl::SetMainColumn(size_t column)
+{ m_main_win->SetMainColumn(column); }
+
+size_t wxTreeListCtrl::GetMainColumn() const
+{ return m_main_win->GetMainColumn(); }
+
+void wxTreeListCtrl::SetColumnText(size_t column, const wxString& text)
+{
+    m_header_win->SetColumnText(column, text);
+    m_header_win->Refresh();
+}
+
+wxString wxTreeListCtrl::GetColumnText(size_t column) const
+{ return m_header_win->GetColumnText(column); }
+
+void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo& col)
+{ m_header_win->AddColumn(col); }
+
+void wxTreeListCtrl::InsertColumn(size_t before,
+                                  const wxTreeListColumnInfo& col)
+{ m_header_win->InsertColumn(before, col); }
+
+void wxTreeListCtrl::RemoveColumn(size_t column)
+{ m_header_win->RemoveColumn(column); }
+
+void wxTreeListCtrl::SetColumn(size_t column, const wxTreeListColumnInfo& col)
+{ m_header_win->SetColumn(column, col); }
+
+const wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(size_t column) const
+{ return m_header_win->GetColumn(column); }
+
+wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(size_t column)
+{ return m_header_win->GetColumn(column); }
+
+void wxTreeListCtrl::SetColumnImage(size_t column, int image)
+{
+    m_header_win->SetColumn(column, GetColumn(column).SetImage(image));
+}
+
+int wxTreeListCtrl::GetColumnImage(size_t column) const
+{
+    return m_header_win->GetColumn(column).GetImage();
+}
+
+void wxTreeListCtrl::ShowColumn(size_t column, bool shown)
+{
+    m_header_win->SetColumn(column, GetColumn(column).SetShown(shown));
+}
+
+bool wxTreeListCtrl::IsColumnShown(size_t column) const
+{
+    return m_header_win->GetColumn(column).GetShown();
+}
+
+void wxTreeListCtrl::SetColumnAlignment(size_t column,
+                                        wxTreeListColumnAlign align)
+{
+    m_header_win->SetColumn(column, GetColumn(column).SetAlignment(align));
+}
+
+wxTreeListColumnAlign wxTreeListCtrl::GetColumnAlignment(size_t column) const
+{
+    return m_header_win->GetColumn(column).GetAlignment();
+}
+
+void wxTreeListCtrl::Refresh(bool erase, const wxRect* rect)
+{
+    m_main_win->Refresh(erase, rect);
+    m_header_win->Refresh(erase, rect);
+}
+
+void wxTreeListCtrl::SetFocus()
+{ m_main_win->SetFocus(); }
-- 
2.50.0

