1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        treelistctrl.cpp 
   3 // Purpose:     multi column tree control implementation 
   4 // Author:      Robert Roebling 
   5 // Maintainer:  Otto Wyss 
   8 // Copyright:   (c) 2004 Robert Roebling, Julian Smart, Alberto Griggio, 
   9 //              Vadim Zeitlin, Otto Wyss 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 // =========================================================================== 
  15 // =========================================================================== 
  17 // --------------------------------------------------------------------------- 
  19 // --------------------------------------------------------------------------- 
  21 #if defined(__GNUG__) && !defined(__APPLE__) 
  22   #pragma implementation "treelistctrl.h" 
  25 // For compilers that support precompilation, includes "wx.h". 
  26 #include "wx/wxprec.h" 
  33 #include <wx/treebase.h> 
  35 #include <wx/textctrl.h> 
  36 #include <wx/imaglist.h> 
  37 #include <wx/settings.h> 
  38 #include <wx/dcclient.h> 
  39 #include <wx/dcscreen.h> 
  40 #include <wx/scrolwin.h> 
  41 #if wxCHECK_VERSION(2, 7, 0) 
  42 #include <wx/renderer.h> 
  46 #include "wx/mac/private.h" 
  49 #include "wx/treelistctrl.h" 
  52 // --------------------------------------------------------------------------- 
  54 // --------------------------------------------------------------------------- 
  58 #if !wxCHECK_VERSION(2, 5, 0) 
  59 WX_DEFINE_ARRAY(wxTreeListItem 
*, wxArrayTreeListItems
); 
  61 WX_DEFINE_ARRAY_PTR(wxTreeListItem 
*, wxArrayTreeListItems
); 
  64 #include <wx/dynarray.h> 
  65 WX_DECLARE_OBJARRAY(wxTreeListColumnInfo
, wxArrayTreeListColumnInfo
); 
  66 #include <wx/arrimpl.cpp> 
  67 WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo
); 
  70 // -------------------------------------------------------------------------- 
  72 // -------------------------------------------------------------------------- 
  74 static const int NO_IMAGE 
= -1; 
  76 static const int LINEHEIGHT 
= 10; 
  77 static const int LINEATROOT 
= 5; 
  78 static const int MARGIN 
= 2; 
  79 static const int MININDENT 
= 16; 
  80 static const int BTNWIDTH 
= 9; 
  81 static const int BTNHEIGHT 
= 9; 
  82 static const int EXTRA_WIDTH 
= 4; 
  83 static const int EXTRA_HEIGHT 
= 4; 
  84 static const int HEADER_OFFSET_X 
= 1; 
  85 static const int HEADER_OFFSET_Y 
= 1; 
  87 static const int DRAG_TIMER_TICKS 
= 250; // minimum drag wait time in ms 
  88 static const int FIND_TIMER_TICKS 
= 500; // minimum find wait time in ms 
  89 static const int RENAME_TIMER_TICKS 
= 250; // minimum rename wait time in ms 
  91 const wxChar
* wxTreeListCtrlNameStr 
= _T("treelistctrl"); 
  93 static wxTreeListColumnInfo wxInvalidTreeListColumnInfo
; 
  96 // --------------------------------------------------------------------------- 
  98 // --------------------------------------------------------------------------- 
  99 //----------------------------------------------------------------------------- 
 100 //  wxTreeListHeaderWindow (internal) 
 101 //----------------------------------------------------------------------------- 
 103 class  wxTreeListHeaderWindow 
: public wxWindow
 
 106     wxTreeListMainWindow 
*m_owner
; 
 107     const wxCursor 
*m_currentCursor
; 
 108     const wxCursor 
*m_resizeCursor
; 
 111     // column being resized 
 114     // divider line position in logical (unscrolled) coords 
 117     // minimal position beyond which the divider line can't be dragged in 
 121     wxArrayTreeListColumnInfo m_columns
; 
 123     // total width of the columns 
 124     int m_total_col_width
; 
 126 #if wxCHECK_VERSION_FULL(2, 7, 0, 1) 
 127     // which col header is currently highlighted with mouse-over 
 131     void RefreshColLabel(int col
); 
 135     wxTreeListHeaderWindow(); 
 137     wxTreeListHeaderWindow( wxWindow 
*win
, 
 139                             wxTreeListMainWindow 
*owner
, 
 140                             const wxPoint 
&pos 
= wxDefaultPosition
, 
 141                             const wxSize 
&size 
= wxDefaultSize
, 
 143                             const wxString 
&name 
= _T("wxtreelistctrlcolumntitles") ); 
 145     virtual ~wxTreeListHeaderWindow(); 
 147     void DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
); 
 149     void AdjustDC(wxDC
& dc
); 
 151     void OnPaint( wxPaintEvent 
&event 
); 
 152     void OnMouse( wxMouseEvent 
&event 
); 
 153     void OnSetFocus( wxFocusEvent 
&event 
); 
 155     // total width of all columns 
 156     int GetWidth() const { return m_total_col_width
; } 
 158     // column manipulation 
 159     int GetColumnCount() const { return m_columns
.GetCount(); } 
 161     void AddColumn (const wxTreeListColumnInfo
& colInfo
); 
 163     void InsertColumn (int before
, const wxTreeListColumnInfo
& colInfo
); 
 165     void RemoveColumn (int column
); 
 167     // column information manipulation 
 168     const wxTreeListColumnInfo
& GetColumn (int column
) const{ 
 169         wxCHECK_MSG ((column 
>= 0) && (column 
< GetColumnCount()), 
 170                      wxInvalidTreeListColumnInfo
, _T("Invalid column")); 
 171         return m_columns
[column
]; 
 173     wxTreeListColumnInfo
& GetColumn (int column
) { 
 174         wxCHECK_MSG ((column 
>= 0) && (column 
< GetColumnCount()), 
 175                      wxInvalidTreeListColumnInfo
, _T("Invalid column")); 
 176         return m_columns
[column
]; 
 178     void SetColumn (int column
, const wxTreeListColumnInfo
& info
); 
 180     wxString 
GetColumnText (int column
) const { 
 181         wxCHECK_MSG ((column 
>= 0) && (column 
< GetColumnCount()), 
 182                      wxEmptyString
, _T("Invalid column")); 
 183         return m_columns
[column
].GetText(); 
 185     void SetColumnText (int column
, const wxString
& text
) { 
 186         wxCHECK_RET ((column 
>= 0) && (column 
< GetColumnCount()), 
 187                      _T("Invalid column")); 
 188         m_columns
[column
].SetText (text
); 
 191     int GetColumnAlignment (int column
) const { 
 192         wxCHECK_MSG ((column 
>= 0) && (column 
< GetColumnCount()), 
 193                      wxALIGN_LEFT
, _T("Invalid column")); 
 194         return m_columns
[column
].GetAlignment(); 
 196     void SetColumnAlignment (int column
, int flag
) { 
 197         wxCHECK_RET ((column 
>= 0) && (column 
< GetColumnCount()), 
 198                      _T("Invalid column")); 
 199         m_columns
[column
].SetAlignment (flag
); 
 202     int GetColumnWidth (int column
) const { 
 203         wxCHECK_MSG ((column 
>= 0) && (column 
< GetColumnCount()), 
 204                      -1, _T("Invalid column")); 
 205         return m_columns
[column
].GetWidth(); 
 207     void SetColumnWidth (int column
, int width
); 
 209     bool IsColumnEditable (int column
) const { 
 210         wxCHECK_MSG ((column 
>= 0) && (column 
< GetColumnCount()), 
 211                      false, _T("Invalid column")); 
 212         return m_columns
[column
].IsEditable(); 
 215     bool IsColumnShown (int column
) const { 
 216         wxCHECK_MSG ((column 
>= 0) && (column 
< GetColumnCount()), 
 217                      true, _T("Invalid column")); 
 218         return m_columns
[column
].IsShown(); 
 225     // common part of all ctors 
 228     void SendListEvent(wxEventType type
, wxPoint pos
); 
 230     DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow
) 
 231     DECLARE_EVENT_TABLE() 
 235 // this is the "true" control 
 236 class  wxTreeListMainWindow
: public wxScrolledWindow
 
 241     wxTreeListMainWindow() { Init(); } 
 243     wxTreeListMainWindow (wxTreeListCtrl 
*parent
, wxWindowID id 
= -1, 
 244                const wxPoint
& pos 
= wxDefaultPosition
, 
 245                const wxSize
& size 
= wxDefaultSize
, 
 246                long style 
= wxTR_DEFAULT_STYLE
, 
 247                const wxValidator 
&validator 
= wxDefaultValidator
, 
 248                const wxString
& name 
= _T("wxtreelistmainwindow")) 
 251         Create (parent
, id
, pos
, size
, style
, validator
, name
); 
 254     virtual ~wxTreeListMainWindow(); 
 256     bool Create(wxTreeListCtrl 
*parent
, wxWindowID id 
= -1, 
 257                 const wxPoint
& pos 
= wxDefaultPosition
, 
 258                 const wxSize
& size 
= wxDefaultSize
, 
 259                 long style 
= wxTR_DEFAULT_STYLE
, 
 260                 const wxValidator 
&validator 
= wxDefaultValidator
, 
 261                 const wxString
& name 
= _T("wxtreelistctrl")); 
 266     // return true if this is a virtual list control 
 267     bool IsVirtual() const { return HasFlag(wxTR_VIRTUAL
); } 
 269     // get the total number of items in the control 
 270     size_t GetCount() const; 
 272     // indent is the number of pixels the children are indented relative to 
 273     // the parents position. SetIndent() also redraws the control 
 275     unsigned int GetIndent() const { return m_indent
; } 
 276     void SetIndent(unsigned int indent
); 
 278     // see wxTreeListCtrl for the meaning 
 279     unsigned int GetLineSpacing() const { return m_linespacing
; } 
 280     void SetLineSpacing(unsigned int spacing
); 
 282     // image list: these functions allow to associate an image list with 
 283     // the control and retrieve it. Note that when assigned with 
 284     // SetImageList, the control does _not_ delete 
 285     // the associated image list when it's deleted in order to allow image 
 286     // lists to be shared between different controls. If you use 
 287     // AssignImageList, the control _does_ delete the image list. 
 289     // The normal image list is for the icons which correspond to the 
 290     // normal tree item state (whether it is selected or not). 
 291     // Additionally, the application might choose to show a state icon 
 292     // which corresponds to an app-defined item state (for example, 
 293     // checked/unchecked) which are taken from the state image list. 
 294     wxImageList 
*GetImageList() const { return m_imageListNormal
; } 
 295     wxImageList 
*GetStateImageList() const { return m_imageListState
; } 
 296     wxImageList 
*GetButtonsImageList() const { return m_imageListButtons
; } 
 298     void SetImageList(wxImageList 
*imageList
); 
 299     void SetStateImageList(wxImageList 
*imageList
); 
 300     void SetButtonsImageList(wxImageList 
*imageList
); 
 301     void AssignImageList(wxImageList 
*imageList
); 
 302     void AssignStateImageList(wxImageList 
*imageList
); 
 303     void AssignButtonsImageList(wxImageList 
*imageList
); 
 305     // Functions to work with tree ctrl items. 
 310     // retrieve item's label 
 311     wxString 
GetItemText (const wxTreeItemId
& item
) const 
 312     { return GetItemText (item
, GetMainColumn()); } 
 313     wxString 
GetItemText (const wxTreeItemId
& item
, int column
) const; 
 314     wxString 
GetItemText (wxTreeItemData
* item
, int column
) const; 
 316     // get one of the images associated with the item (normal by default) 
 317     int GetItemImage (const wxTreeItemId
& item
, 
 318                       wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const 
 319     { return GetItemImage (item
, GetMainColumn(), which
); } 
 320     int GetItemImage (const wxTreeItemId
& item
, int column
, 
 321                       wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const; 
 323     // get the data associated with the item 
 324     wxTreeItemData 
*GetItemData(const wxTreeItemId
& item
) const; 
 326     bool GetItemBold(const wxTreeItemId
& item
) const; 
 327     wxColour 
GetItemTextColour(const wxTreeItemId
& item
) const; 
 328     wxColour 
GetItemBackgroundColour(const wxTreeItemId
& item
) const; 
 329     wxFont 
GetItemFont(const wxTreeItemId
& item
) const; 
 335     void SetItemText (const wxTreeItemId
& item
, const wxString
& text
) 
 336     { SetItemText (item
, GetMainColumn(), text
); } 
 337     void SetItemText (const wxTreeItemId
& item
, int column
, const wxString
& text
); 
 339     // get one of the images associated with the item (normal by default) 
 340     void SetItemImage (const wxTreeItemId
& item
, int image
, 
 341                        wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) 
 342     { SetItemImage (item
, GetMainColumn(), image
, which
); } 
 343     void SetItemImage (const wxTreeItemId
& item
, int column
, int image
, 
 344                        wxTreeItemIcon which 
= wxTreeItemIcon_Normal
); 
 346     // associate some data with the item 
 347     void SetItemData(const wxTreeItemId
& item
, wxTreeItemData 
*data
); 
 349     // force appearance of [+] button near the item. This is useful to 
 350     // allow the user to expand the items which don't have any children now 
 351     // - but instead add them only when needed, thus minimizing memory 
 352     // usage and loading time. 
 353     void SetItemHasChildren(const wxTreeItemId
& item
, bool has 
= true); 
 355     // the item will be shown in bold 
 356     void SetItemBold(const wxTreeItemId
& item
, bool bold 
= true); 
 358     // set the item's text colour 
 359     void SetItemTextColour(const wxTreeItemId
& item
, const wxColour
& colour
); 
 361     // set the item's background colour 
 362     void SetItemBackgroundColour(const wxTreeItemId
& item
, const wxColour
& colour
); 
 364     // set the item's font (should be of the same height for all items) 
 365     void SetItemFont(const wxTreeItemId
& item
, const wxFont
& font
); 
 367     // set the window font 
 368     virtual bool SetFont( const wxFont 
&font 
); 
 370     // set the styles.  No need to specify a GetWindowStyle here since 
 371     // the base wxWindow member function will do it for us 
 372     void SetWindowStyle(const long styles
); 
 374     // item status inquiries 
 375     // --------------------- 
 377     // is the item visible (it might be outside the view or not expanded)? 
 378     bool IsVisible(const wxTreeItemId
& item
, bool fullRow
) const; 
 379     // does the item has any children? 
 380     bool HasChildren(const wxTreeItemId
& item
) const; 
 381     // is the item expanded (only makes sense if HasChildren())? 
 382     bool IsExpanded(const wxTreeItemId
& item
) const; 
 383     // is this item currently selected (the same as has focus)? 
 384     bool IsSelected(const wxTreeItemId
& item
) const; 
 385     // is item text in bold font? 
 386     bool IsBold(const wxTreeItemId
& item
) const; 
 387         // does the layout include space for a button? 
 389     // number of children 
 390     // ------------------ 
 392     // if 'recursively' is false, only immediate children count, otherwise 
 393     // the returned number is the number of all items in this branch 
 394     size_t GetChildrenCount(const wxTreeItemId
& item
, bool recursively 
= true); 
 399     // wxTreeItemId.IsOk() will return false if there is no such item 
 401     // get the root tree item 
 402     wxTreeItemId 
GetRootItem() const { return m_rootItem
; } 
 404     // get the item currently selected, only if a single item is selected 
 405     wxTreeItemId 
GetSelection() const { return m_selectItem
; } 
 407     // get all the items currently selected, return count of items 
 408     size_t GetSelections(wxArrayTreeItemIds
&) const; 
 410     // get the parent of this item (may return NULL if root) 
 411     wxTreeItemId 
GetItemParent(const wxTreeItemId
& item
) const; 
 413     // for this enumeration function you must pass in a "cookie" parameter 
 414     // which is opaque for the application but is necessary for the library 
 415     // to make these functions reentrant (i.e. allow more than one 
 416     // enumeration on one and the same object simultaneously). Of course, 
 417     // the "cookie" passed to GetFirstChild() and GetNextChild() should be 
 420     // get child of this item 
 421 #if !wxCHECK_VERSION(2, 5, 0) 
 422     wxTreeItemId 
GetFirstChild(const wxTreeItemId
& item
, long& cookie
) const; 
 423     wxTreeItemId 
GetNextChild(const wxTreeItemId
& item
, long& cookie
) const; 
 424     wxTreeItemId 
GetPrevChild(const wxTreeItemId
& item
, long& cookie
) const; 
 425     wxTreeItemId 
GetLastChild(const wxTreeItemId
& item
, long& cookie
) const; 
 427     wxTreeItemId 
GetFirstChild(const wxTreeItemId
& item
, wxTreeItemIdValue
& cookie
) const; 
 428     wxTreeItemId 
GetNextChild(const wxTreeItemId
& item
, wxTreeItemIdValue
& cookie
) const; 
 429     wxTreeItemId 
GetPrevChild(const wxTreeItemId
& item
, wxTreeItemIdValue
& cookie
) const; 
 430     wxTreeItemId 
GetLastChild(const wxTreeItemId
& item
, wxTreeItemIdValue
& cookie
) const; 
 433     // get sibling of this item 
 434     wxTreeItemId 
GetNextSibling(const wxTreeItemId
& item
) const; 
 435     wxTreeItemId 
GetPrevSibling(const wxTreeItemId
& item
) const; 
 437     // get item in the full tree (currently only for internal use) 
 438     wxTreeItemId 
GetNext(const wxTreeItemId
& item
, bool fulltree 
= true) const; 
 439     wxTreeItemId 
GetPrev(const wxTreeItemId
& item
, bool fulltree 
= true) const; 
 441     // get expanded item, see IsExpanded() 
 442     wxTreeItemId 
GetFirstExpandedItem() const; 
 443     wxTreeItemId 
GetNextExpanded(const wxTreeItemId
& item
) const; 
 444     wxTreeItemId 
GetPrevExpanded(const wxTreeItemId
& item
) const; 
 446     // get visible item, see IsVisible() 
 447     wxTreeItemId 
GetFirstVisibleItem(bool fullRow
) const; 
 448     wxTreeItemId 
GetNextVisible(const wxTreeItemId
& item
, bool fullRow
) const; 
 449     wxTreeItemId 
GetPrevVisible(const wxTreeItemId
& item
, bool fullRow
) const; 
 454     // add the root node to the tree 
 455     wxTreeItemId 
AddRoot (const wxString
& text
, 
 456                           int image 
= -1, int selectedImage 
= -1, 
 457                           wxTreeItemData 
*data 
= NULL
); 
 459     // insert a new item in as the first child of the parent 
 460     wxTreeItemId 
PrependItem(const wxTreeItemId
& parent
, 
 461                              const wxString
& text
, 
 462                              int image 
= -1, int selectedImage 
= -1, 
 463                              wxTreeItemData 
*data 
= NULL
); 
 465     // insert a new item after a given one 
 466     wxTreeItemId 
InsertItem(const wxTreeItemId
& parent
, 
 467                             const wxTreeItemId
& idPrevious
, 
 468                             const wxString
& text
, 
 469                             int image 
= -1, int selectedImage 
= -1, 
 470                             wxTreeItemData 
*data 
= NULL
); 
 472     // insert a new item before the one with the given index 
 473     wxTreeItemId 
InsertItem(const wxTreeItemId
& parent
, 
 475                             const wxString
& text
, 
 476                             int image 
= -1, int selectedImage 
= -1, 
 477                             wxTreeItemData 
*data 
= NULL
); 
 479     // insert a new item in as the last child of the parent 
 480     wxTreeItemId 
AppendItem(const wxTreeItemId
& parent
, 
 481                             const wxString
& text
, 
 482                             int image 
= -1, int selectedImage 
= -1, 
 483                             wxTreeItemData 
*data 
= NULL
); 
 485     // delete this item and associated data if any 
 486     void Delete(const wxTreeItemId
& item
); 
 487     // delete all children (but don't delete the item itself) 
 488     // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events 
 489     void DeleteChildren(const wxTreeItemId
& item
); 
 490     // delete the root and all its children from the tree 
 491     // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events 
 495     void Expand(const wxTreeItemId
& item
); 
 496     // expand this item and all subitems recursively 
 497     void ExpandAll(const wxTreeItemId
& item
); 
 498     // collapse the item without removing its children 
 499     void Collapse(const wxTreeItemId
& item
); 
 500     // collapse the item and remove all children 
 501     void CollapseAndReset(const wxTreeItemId
& item
); 
 502     // toggles the current state 
 503     void Toggle(const wxTreeItemId
& item
); 
 505     // remove the selection from currently selected item (if any) 
 509     void SelectItem(const wxTreeItemId
& item
, const wxTreeItemId
& prev 
= (wxTreeItemId
*)NULL
, 
 510                     bool unselect_others 
= true); 
 512     // make sure this item is visible (expanding the parent item and/or 
 513     // scrolling to this item if necessary) 
 514     void EnsureVisible(const wxTreeItemId
& item
); 
 515     // scroll to this item (but don't expand its parent) 
 516     void ScrollTo(const wxTreeItemId
& item
); 
 517     void AdjustMyScrollbars(); 
 519     // The first function is more portable (because easier to implement 
 520     // on other platforms), but the second one returns some extra info. 
 521     wxTreeItemId 
HitTest (const wxPoint
& point
) 
 522         { int flags
; int column
; return HitTest (point
, flags
, column
); } 
 523     wxTreeItemId 
HitTest (const wxPoint
& point
, int& flags
) 
 524         { int column
; return HitTest (point
, flags
, column
); } 
 525     wxTreeItemId 
HitTest (const wxPoint
& point
, int& flags
, int& column
); 
 528     // get the bounding rectangle of the item (or of its label only) 
 529     bool GetBoundingRect(const wxTreeItemId
& item
, 
 531                          bool textOnly 
= false) const; 
 533     // Start editing the item label: this (temporarily) replaces the item 
 534     // with a one line edit control. The item will be selected if it hadn't 
 536     void EditLabel (const wxTreeItemId
& item
, int column
); 
 539     // this function is called to compare 2 items and should return -1, 0 
 540     // or +1 if the first item is less than, equal to or greater than the 
 541     // second one. The base class version performs alphabetic comparaison 
 542     // of item labels (GetText) 
 543     virtual int OnCompareItems(const wxTreeItemId
& item1
, 
 544                                const wxTreeItemId
& item2
); 
 545     // sort the children of this item using OnCompareItems 
 547     // NB: this function is not reentrant and not MT-safe (FIXME)! 
 548     void SortChildren(const wxTreeItemId
& item
); 
 551     wxTreeItemId 
FindItem (const wxTreeItemId
& item
, const wxString
& str
, int mode 
= 0); 
 553     // implementation only from now on 
 555     // overridden base class virtuals 
 556     virtual bool SetBackgroundColour(const wxColour
& colour
); 
 557     virtual bool SetForegroundColour(const wxColour
& colour
); 
 560     void SetDragItem (const wxTreeItemId
& item 
= (wxTreeItemId
*)NULL
); 
 563     void OnPaint( wxPaintEvent 
&event 
); 
 564     void OnSetFocus( wxFocusEvent 
&event 
); 
 565     void OnKillFocus( wxFocusEvent 
&event 
); 
 566     void OnChar( wxKeyEvent 
&event 
); 
 567     void OnMouse( wxMouseEvent 
&event 
); 
 568     void OnIdle( wxIdleEvent 
&event 
); 
 569     void OnScroll(wxScrollWinEvent
& event
); 
 571     // implementation helpers 
 572     void SendDeleteEvent(wxTreeListItem 
*itemBeingDeleted
); 
 574     int GetColumnCount() const 
 575     { return m_owner
->GetHeaderWindow()->GetColumnCount(); } 
 577     void SetMainColumn (int column
) 
 578     { if ((column 
>= 0) && (column 
< GetColumnCount())) m_main_column 
= column
; } 
 580     int GetMainColumn() const { return m_main_column
; } 
 582     int GetBestColumnWidth (int column
, wxTreeItemId parent 
= wxTreeItemId()); 
 583     int GetItemWidth (int column
, wxTreeListItem 
*item
); 
 584     wxFont 
GetItemFont (wxTreeListItem 
*item
); 
 589     wxTreeListCtrl
* m_owner
; 
 593     friend class wxTreeListItem
; 
 594     friend class wxTreeListRenameTimer
; 
 595     friend class wxEditTextCtrl
; 
 600     wxTreeListItem       
*m_rootItem
; // root item 
 601     wxTreeListItem       
*m_curItem
; // current item, either selected or marked 
 602     wxTreeListItem       
*m_shiftItem
; // item, where the shift key was pressed 
 603     wxTreeListItem       
*m_editItem
; // item, which is currently edited 
 604     wxTreeListItem       
*m_selectItem
; // current selected item, not with wxTR_MULTIPLE 
 608     int                  m_btnWidth
, m_btnWidth2
; 
 609     int                  m_btnHeight
, m_btnHeight2
; 
 610     int                  m_imgWidth
, m_imgWidth2
; 
 611     int                  m_imgHeight
, m_imgHeight2
; 
 612     unsigned short       m_indent
; 
 614     unsigned short       m_linespacing
; 
 616     wxBrush             
*m_hilightBrush
, 
 617                         *m_hilightUnfocusedBrush
; 
 622     bool                 m_ownsImageListNormal
, 
 623                          m_ownsImageListState
, 
 624                          m_ownsImageListButtons
; 
 625     bool                 m_isDragging
; // true between BEGIN/END drag events 
 627     bool                 m_lastOnSame
;  // last click on the same item as prev 
 628     bool                 m_left_down_selection
; 
 630     wxImageList         
*m_imageListNormal
, 
 635     wxTimer             
*m_dragTimer
; 
 636     wxTreeListItem      
*m_dragItem
; 
 638     wxTimer             
*m_renameTimer
; 
 639     wxString             m_renameRes
; 
 642     wxTimer             
*m_findTimer
; 
 645     // the common part of all ctors 
 649     wxTreeItemId 
DoInsertItem(const wxTreeItemId
& parent
, 
 651                               const wxString
& text
, 
 652                               int image
, int selectedImage
, 
 653                               wxTreeItemData 
*data
); 
 654     bool HasButtons(void) const 
 655         { return (m_imageListButtons
) || HasFlag (wxTR_TWIST_BUTTONS
|wxTR_HAS_BUTTONS
); } 
 658     void CalculateLineHeight(); 
 659     int  GetLineHeight(wxTreeListItem 
*item
) const; 
 660     void PaintLevel( wxTreeListItem 
*item
, wxDC
& dc
, int level
, int &y
, 
 662     void PaintItem( wxTreeListItem 
*item
, wxDC
& dc
); 
 664     void CalculateLevel( wxTreeListItem 
*item
, wxDC 
&dc
, int level
, int &y
, 
 666     void CalculatePositions(); 
 667     void CalculateSize( wxTreeListItem 
*item
, wxDC 
&dc 
); 
 669     void RefreshSubtree (wxTreeListItem 
*item
); 
 670     void RefreshLine (wxTreeListItem 
*item
); 
 672     // redraw all selected items 
 673     void RefreshSelected(); 
 675     // RefreshSelected() recursive helper 
 676     void RefreshSelectedUnder (wxTreeListItem 
*item
); 
 678     void OnRenameTimer(); 
 679     void OnRenameAccept(); 
 681     void FillArray(wxTreeListItem
*, wxArrayTreeItemIds
&) const; 
 682     bool TagAllChildrenUntilLast (wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
); 
 683     bool TagNextChildren (wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
); 
 684     void UnselectAllChildren (wxTreeListItem 
*item 
); 
 687     DECLARE_EVENT_TABLE() 
 688     DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow
) 
 692 // timer used for enabling in-place edit 
 693 class  wxTreeListRenameTimer
: public wxTimer
 
 696     wxTreeListRenameTimer( wxTreeListMainWindow 
*owner 
); 
 701     wxTreeListMainWindow   
*m_owner
; 
 704 // control used for in-place edit 
 705 class  wxEditTextCtrl
: public wxTextCtrl
 
 708     wxEditTextCtrl (wxWindow 
*parent
, 
 712                     wxTreeListMainWindow 
*owner
, 
 713                     const wxString 
&value 
= wxEmptyString
, 
 714                     const wxPoint 
&pos 
= wxDefaultPosition
, 
 715                     const wxSize 
&size 
= wxDefaultSize
, 
 717                     const wxValidator
& validator 
= wxDefaultValidator
, 
 718                     const wxString 
&name 
= wxTextCtrlNameStr 
); 
 720     void OnChar( wxKeyEvent 
&event 
); 
 721     void OnKeyUp( wxKeyEvent 
&event 
); 
 722     void OnKillFocus( wxFocusEvent 
&event 
); 
 727     wxTreeListMainWindow  
*m_owner
; 
 728     wxString            m_startValue
; 
 731     DECLARE_EVENT_TABLE() 
 739     wxTreeListItem() { m_data 
= NULL
; } 
 740     wxTreeListItem( wxTreeListMainWindow 
*owner
, 
 741                     wxTreeListItem 
*parent
, 
 742                     const wxArrayString
& text
, 
 745                     wxTreeItemData 
*data 
); 
 750     wxArrayTreeListItems
& GetChildren() { return m_children
; } 
 752     const wxString 
GetText() const 
 756     const wxString 
GetText (int column
) const 
 758         if(m_text
.GetCount() > 0) 
 760             if( IsVirtual() )   return m_owner
->GetItemText( m_data
, column 
); 
 761             else                return m_text
[column
]; 
 763         return wxEmptyString
; 
 766     int GetImage (wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const 
 767         { return m_images
[which
]; } 
 768     int GetImage (int column
, wxTreeItemIcon which
=wxTreeItemIcon_Normal
) const 
 770         if(column 
== m_owner
->GetMainColumn()) return m_images
[which
]; 
 771         if(column 
< (int)m_col_images
.GetCount()) return m_col_images
[column
]; 
 775     wxTreeItemData 
*GetData() const { return m_data
; } 
 777     // returns the current image for the item (depending on its 
 778     // selected/expanded/whatever state) 
 779     int GetCurrentImage() const; 
 781     void SetText (const wxString 
&text 
); 
 782     void SetText (int column
, const wxString
& text
) 
 784         if (column 
< (int)m_text
.GetCount()) { 
 785             m_text
[column
] = text
; 
 786         }else if (column 
< m_owner
->GetColumnCount()) { 
 787             int howmany 
= m_owner
->GetColumnCount(); 
 788             for (int i 
= m_text
.GetCount(); i 
< howmany
; ++i
) m_text
.Add (wxEmptyString
); 
 789             m_text
[column
] = text
; 
 792     void SetImage (int image
, wxTreeItemIcon which
) { m_images
[which
] = image
; } 
 793     void SetImage (int column
, int image
, wxTreeItemIcon which
) 
 795         if (column 
== m_owner
->GetMainColumn()) { 
 796             m_images
[which
] = image
; 
 797         }else if (column 
< (int)m_col_images
.GetCount()) { 
 798             m_col_images
[column
] = image
; 
 799         }else if (column 
< m_owner
->GetColumnCount()) { 
 800             int howmany 
= m_owner
->GetColumnCount(); 
 801             for (int i 
= m_col_images
.GetCount(); i 
< howmany
; ++i
) m_col_images
.Add (NO_IMAGE
); 
 802             m_col_images
[column
] = image
; 
 806     void SetData(wxTreeItemData 
*data
) { m_data 
= data
; } 
 808     void SetHasPlus(bool has 
= true) { m_hasPlus 
= has
; } 
 810     void SetBold(bool bold
) { m_isBold 
= bold
; } 
 812     int GetX() const { return m_x
; } 
 813     int GetY() const { return m_y
; } 
 815     void SetX (int x
) { m_x 
= x
; } 
 816     void SetY (int y
) { m_y 
= y
; } 
 818     int  GetHeight() const { return m_height
; } 
 819     int  GetWidth()  const { return m_width
; } 
 821     void SetHeight (int height
) { m_height 
= height
; } 
 822     void SetWidth (int width
) { m_width 
= width
; } 
 824     int GetTextX() const { return m_text_x
; } 
 825     void SetTextX (int text_x
) { m_text_x 
= text_x
; } 
 827     wxTreeListItem 
*GetItemParent() const { return m_parent
; } 
 830     // deletes all children notifying the treectrl about it if !NULL 
 832     void DeleteChildren(wxTreeListMainWindow 
*tree 
= NULL
); 
 834     // get count of all children (and grand children if 'recursively') 
 835     size_t GetChildrenCount(bool recursively 
= true) const; 
 837     void Insert(wxTreeListItem 
*child
, size_t index
) 
 838     { m_children
.Insert(child
, index
); } 
 840     void GetSize( int &x
, int &y
, const wxTreeListMainWindow
* ); 
 842     // return the item at given position (or NULL if no item), onButton is 
 843     // true if the point belongs to the item's button, otherwise it lies 
 844     // on the button's label 
 845     wxTreeListItem 
*HitTest (const wxPoint
& point
, 
 846                              const wxTreeListMainWindow 
*, 
 847                              int &flags
, int& column
, int level
); 
 849     void Expand() { m_isCollapsed 
= false; } 
 850     void Collapse() { m_isCollapsed 
= true; } 
 852     void SetHilight( bool set 
= true ) { m_hasHilight 
= set
; } 
 855     bool HasChildren() const { return !m_children
.IsEmpty(); } 
 856     bool IsSelected()  const { return m_hasHilight 
!= 0; } 
 857     bool IsExpanded()  const { return !m_isCollapsed
; } 
 858     bool HasPlus()     const { return m_hasPlus 
|| HasChildren(); } 
 859     bool IsBold()      const { return m_isBold 
!= 0; } 
 860     bool IsVirtual()   const { return m_owner
->IsVirtual(); } 
 863     // get them - may be NULL 
 864     wxTreeItemAttr 
*GetAttributes() const { return m_attr
; } 
 865     // get them ensuring that the pointer is not NULL 
 866     wxTreeItemAttr
& Attr() 
 870             m_attr 
= new wxTreeItemAttr
; 
 876     void SetAttributes(wxTreeItemAttr 
*attr
) 
 878         if ( m_ownsAttr 
) delete m_attr
; 
 882     // set them and delete when done 
 883     void AssignAttributes(wxTreeItemAttr 
*attr
) 
 890     wxTreeListMainWindow  
*m_owner
;        // control the item belongs to 
 892     // since there can be very many of these, we save size by chosing 
 893     // the smallest representation for the elements and by ordering 
 894     // the members to avoid padding. 
 895     wxArrayString      m_text
;    // labels to be rendered for item 
 897     wxTreeItemData     
*m_data
;         // user-provided data 
 899     wxArrayTreeListItems m_children
; // list of children 
 900     wxTreeListItem  
*m_parent
;       // parent of this item 
 902     wxTreeItemAttr     
*m_attr
;         // attributes??? 
 904     // tree ctrl images for the normal, selected, expanded and 
 905     // expanded+selected states 
 906     short               m_images
[wxTreeItemIcon_Max
]; 
 907     wxArrayShort m_col_images
; // images for the various columns (!= main) 
 909     // main column item positions 
 910     wxCoord             m_x
;            // (virtual) offset from left (vertical line) 
 911     wxCoord             m_y
;            // (virtual) offset from top 
 912     wxCoord             m_text_x
;       // item offset from left 
 913     short               m_width
;        // width of this item 
 914     unsigned char       m_height
;       // height of this item 
 916     // use bitfields to save size 
 917     int                 m_isCollapsed 
:1; 
 918     int                 m_hasHilight  
:1; // same as focused 
 919     int                 m_hasPlus     
:1; // used for item which doesn't have 
 920                                           // children but has a [+] button 
 921     int                 m_isBold      
:1; // render the label in bold font 
 922     int                 m_ownsAttr    
:1; // delete attribute when done 
 925 // =========================================================================== 
 927 // =========================================================================== 
 929 // --------------------------------------------------------------------------- 
 930 // wxTreeListRenameTimer (internal) 
 931 // --------------------------------------------------------------------------- 
 933 wxTreeListRenameTimer::wxTreeListRenameTimer( wxTreeListMainWindow 
*owner 
) 
 938 void wxTreeListRenameTimer::Notify() 
 940     m_owner
->OnRenameTimer(); 
 943 //----------------------------------------------------------------------------- 
 944 // wxEditTextCtrl (internal) 
 945 //----------------------------------------------------------------------------- 
 947 BEGIN_EVENT_TABLE (wxEditTextCtrl
,wxTextCtrl
) 
 948     EVT_CHAR           (wxEditTextCtrl::OnChar
) 
 949     EVT_KEY_UP         (wxEditTextCtrl::OnKeyUp
) 
 950     EVT_KILL_FOCUS     (wxEditTextCtrl::OnKillFocus
) 
 953 wxEditTextCtrl::wxEditTextCtrl (wxWindow 
*parent
, 
 957                                 wxTreeListMainWindow 
*owner
, 
 958                                 const wxString 
&value
, 
 962                                 const wxValidator
& validator
, 
 963                                 const wxString 
&name
) 
 964     : wxTextCtrl (parent
, id
, value
, pos
, size
, style
|wxSIMPLE_BORDER
, validator
, name
) 
 970     (*m_res
) = wxEmptyString
; 
 971     m_startValue 
= value
; 
 975 void wxEditTextCtrl::OnChar( wxKeyEvent 
&event 
) 
 977     if (event
.GetKeyCode() == WXK_RETURN
) 
 980         (*m_res
) = GetValue(); 
 982         if ((*m_res
) != m_startValue
) 
 983             m_owner
->OnRenameAccept(); 
 985         if (!wxPendingDelete
.Member(this)) 
 986             wxPendingDelete
.Append(this); 
 989         m_owner
->SetFocus(); // This doesn't work. TODO. 
 993     if (event
.GetKeyCode() == WXK_ESCAPE
) 
 996         (*m_res
) = wxEmptyString
; 
 998         if (!wxPendingDelete
.Member(this)) 
 999             wxPendingDelete
.Append(this); 
1002         m_owner
->SetFocus(); // This doesn't work. TODO. 
1009 void wxEditTextCtrl::OnKeyUp( wxKeyEvent 
&event 
) 
1017     // auto-grow the textctrl: 
1018     wxSize parentSize 
= m_owner
->GetSize(); 
1019     wxPoint myPos 
= GetPosition(); 
1020     wxSize mySize 
= GetSize(); 
1022     GetTextExtent(GetValue() + _T("M"), &sx
, &sy
); 
1023     if (myPos
.x 
+ sx 
> parentSize
.x
) sx 
= parentSize
.x 
- myPos
.x
; 
1024     if (mySize
.x 
> sx
) sx 
= mySize
.x
; 
1030 void wxEditTextCtrl::OnKillFocus( wxFocusEvent 
&event 
) 
1038     if (!wxPendingDelete
.Member(this)) 
1039         wxPendingDelete
.Append(this); 
1042     (*m_res
) = GetValue(); 
1044     if ((*m_res
) != m_startValue
) 
1045         m_owner
->OnRenameAccept(); 
1048 //----------------------------------------------------------------------------- 
1049 //  wxTreeListHeaderWindow 
1050 //----------------------------------------------------------------------------- 
1052 IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow
,wxWindow
); 
1054 BEGIN_EVENT_TABLE(wxTreeListHeaderWindow
,wxWindow
) 
1055     EVT_PAINT         (wxTreeListHeaderWindow::OnPaint
) 
1056     EVT_MOUSE_EVENTS  (wxTreeListHeaderWindow::OnMouse
) 
1057     EVT_SET_FOCUS     (wxTreeListHeaderWindow::OnSetFocus
) 
1060 void wxTreeListHeaderWindow::Init() 
1062     m_currentCursor 
= (wxCursor 
*) NULL
; 
1063     m_isDragging 
= false; 
1065     m_total_col_width 
= 0; 
1069 wxTreeListHeaderWindow::wxTreeListHeaderWindow() 
1073     m_owner 
= (wxTreeListMainWindow 
*) NULL
; 
1074     m_resizeCursor 
= (wxCursor 
*) NULL
; 
1077 wxTreeListHeaderWindow::wxTreeListHeaderWindow( wxWindow 
*win
, 
1079                                                 wxTreeListMainWindow 
*owner
, 
1083                                                 const wxString 
&name 
) 
1084     : wxWindow( win
, id
, pos
, size
, style
, name 
) 
1089     m_resizeCursor 
= new wxCursor(wxCURSOR_SIZEWE
); 
1091 #if !wxCHECK_VERSION(2, 5, 0) 
1092     SetBackgroundColour (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNFACE
)); 
1094     SetBackgroundColour (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNFACE
)); 
1098 wxTreeListHeaderWindow::~wxTreeListHeaderWindow() 
1100     delete m_resizeCursor
; 
1103 void wxTreeListHeaderWindow::DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
) 
1105 #if !wxCHECK_VERSION(2, 5, 0) 
1106     wxPen 
pen (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNSHADOW 
), 1, wxSOLID
); 
1108     wxPen 
pen (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNSHADOW 
), 1, wxSOLID
); 
1111     const int m_corner 
= 1; 
1113     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1114 #if defined( __WXMAC__  ) 
1117     dc
->SetPen( *wxBLACK_PEN 
); 
1119     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
1120     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
1122 #if defined( __WXMAC__  ) 
1123     pen 
= wxPen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID 
); 
1126     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
1127     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
1129     dc
->SetPen( *wxWHITE_PEN 
); 
1130     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
1131     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
1132     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
1133     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
1136 // shift the DC origin to match the position of the main window horz 
1137 // scrollbar: this allows us to always use logical coords 
1138 void wxTreeListHeaderWindow::AdjustDC(wxDC
& dc
) 
1141     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1143     m_owner
->GetViewStart( &x
, NULL 
); 
1145     // account for the horz scrollbar offset 
1146     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1149 void wxTreeListHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1152     wxClientDC 
dc( this ); 
1154     wxPaintDC 
dc( this ); 
1160     int x 
= HEADER_OFFSET_X
; 
1162     // width and height of the entire header window 
1164     GetClientSize( &w
, &h 
); 
1165     m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1166     dc
.SetBackgroundMode(wxTRANSPARENT
); 
1168 #if wxCHECK_VERSION_FULL(2, 7, 0, 1) 
1169     int numColumns 
= GetColumnCount(); 
1170     for ( int i 
= 0; i 
< numColumns 
&& x 
< w
; i
++ ) 
1172         if (!IsColumnShown (i
)) continue; // do next column if not shown 
1174         wxHeaderButtonParams params
; 
1176         // TODO: columnInfo should have label colours... 
1177         params
.m_labelColour 
= wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
); 
1178         params
.m_labelFont 
= GetFont(); 
1180         wxTreeListColumnInfo
& column 
= GetColumn(i
); 
1181         int wCol 
= column
.GetWidth(); 
1183         wxRect 
rect(x
, 0, wCol
, h
); 
1186         if ( i 
== m_hotTrackCol
) 
1187             flags 
|= wxCONTROL_CURRENT
; 
1189         params
.m_labelText 
= column
.GetText(); 
1190         params
.m_labelAlignment 
= column
.GetAlignment(); 
1192         int image 
= column
.GetImage(); 
1193         wxImageList
* imageList 
= m_owner
->GetImageList(); 
1194         if ((image 
!= -1) && imageList
)  
1195             params
.m_labelBitmap 
= imageList
->GetBitmap(image
); 
1197         wxRendererNative::Get().DrawHeaderButton(this, dc
, rect
, flags
, 
1198                                                  wxHDR_SORT_ICON_NONE
, ¶ms
); 
1202         wxRect 
rect(x
, 0, w
-x
, h
); 
1203         wxRendererNative::Get().DrawHeaderButton(this, dc
, rect
); 
1206 #else  // not 2.7.0.1+ 
1208     dc
.SetFont( GetFont() ); 
1210     // do *not* use the listctrl colour for headers - one day we will have a 
1211     // function to set it separately 
1212     //dc.SetTextForeground( *wxBLACK ); 
1213 #if !wxCHECK_VERSION(2, 5, 0) 
1214     dc
.SetTextForeground (wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOWTEXT 
)); 
1216     dc
.SetTextForeground (wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT 
)); 
1219     int numColumns 
= GetColumnCount(); 
1220     for ( int i 
= 0; i 
< numColumns 
&& x 
< w
; i
++ ) 
1222         if (!IsColumnShown (i
)) continue; // do next column if not shown 
1224         wxTreeListColumnInfo
& column 
= GetColumn(i
); 
1225         int wCol 
= column
.GetWidth(); 
1227         // the width of the rect to draw: make it smaller to fit entirely 
1228         // inside the column rect 
1231 #if !wxCHECK_VERSION(2, 7, 0) 
1232         dc
.SetPen( *wxWHITE_PEN 
); 
1233         DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 ); 
1235         wxRect 
rect(x
, HEADER_OFFSET_Y
, cw
, h
-2); 
1236         wxRendererNative::GetDefault().DrawHeaderButton (this, dc
, rect
); 
1239         // if we have an image, draw it on the right of the label 
1240         int image 
= column
.GetImage(); //item.m_image; 
1241         int ix 
= -2, iy 
= 0; 
1242         wxImageList
* imageList 
= m_owner
->GetImageList(); 
1243         if ((image 
!= -1) && imageList
) { 
1244             imageList
->GetSize (image
, ix
, iy
); 
1247         // extra margins around the text label 
1250         int image_offset 
= cw 
- ix 
- 1; 
1252         switch(column
.GetAlignment()) { 
1254             text_x 
+= EXTRA_WIDTH
; 
1258             dc
.GetTextExtent (column
.GetText(), &text_width
, NULL
); 
1259             text_x 
+= cw 
- text_width 
- EXTRA_WIDTH 
- MARGIN
; 
1262         case wxALIGN_CENTER
: 
1263             dc
.GetTextExtent(column
.GetText(), &text_width
, NULL
); 
1264             text_x 
+= (cw 
- text_width
)/2 + ix 
+ 2; 
1265             image_offset 
= (cw 
- text_width 
- ix 
- 2)/2 - MARGIN
; 
1270         if ((image 
!= -1) && imageList
) { 
1271             imageList
->Draw (image
, dc
, x 
+ image_offset
/*cw - ix - 1*/, 
1272                              HEADER_OFFSET_Y 
+ (h 
- 4 - iy
)/2, 
1273                              wxIMAGELIST_DRAW_TRANSPARENT
); 
1276         // draw the text clipping it so that it doesn't overwrite the column boundary 
1277         wxDCClipper 
clipper(dc
, x
, HEADER_OFFSET_Y
, cw
, h 
- 4 ); 
1278         dc
.DrawText (column
.GetText(), text_x
, HEADER_OFFSET_Y 
+ EXTRA_HEIGHT 
); 
1284     int more_w 
= m_owner
->GetSize().x 
- x 
- HEADER_OFFSET_X
; 
1286 #if !wxCHECK_VERSION(2, 7, 0) 
1287         DoDrawRect (&dc
, x
, HEADER_OFFSET_Y
, more_w
, h
-2 ); 
1289         wxRect 
rect (x
, HEADER_OFFSET_Y
, more_w
, h
-2); 
1290         wxRendererNative::GetDefault().DrawHeaderButton (this, dc
, rect
); 
1296 void wxTreeListHeaderWindow::DrawCurrent() 
1298     int x1 
= m_currentX
; 
1300     ClientToScreen (&x1
, &y1
); 
1302     int x2 
= m_currentX
-1; 
1304     ++x2
; // but why ???? 
1307     m_owner
->GetClientSize( NULL
, &y2 
); 
1308     m_owner
->ClientToScreen( &x2
, &y2 
); 
1311     dc
.SetLogicalFunction (wxINVERT
); 
1312     dc
.SetPen (wxPen (*wxBLACK
, 2, wxSOLID
)); 
1313     dc
.SetBrush (*wxTRANSPARENT_BRUSH
); 
1316     dc
.DrawLine (x1
, y1
, x2
, y2
); 
1317     dc
.SetLogicalFunction (wxCOPY
); 
1318     dc
.SetPen (wxNullPen
); 
1319     dc
.SetBrush (wxNullBrush
); 
1322 #if wxCHECK_VERSION_FULL(2, 7, 0, 1) 
1323 int wxTreeListHeaderWindow::XToCol(int x
) 
1326     int numColumns 
= GetColumnCount(); 
1327     for ( int col 
= 0; col 
< numColumns
; col
++ ) 
1329         if (!IsColumnShown(col
)) continue;  
1330         wxTreeListColumnInfo
& column 
= GetColumn(col
); 
1332         if ( x 
< (colLeft 
+ column
.GetWidth()) ) 
1335         colLeft 
+= column
.GetWidth(); 
1341 void wxTreeListHeaderWindow::RefreshColLabel(int col
) 
1343     if ( col 
> GetColumnCount() ) 
1350         if (!IsColumnShown(idx
)) continue;  
1351         wxTreeListColumnInfo
& column 
= GetColumn(idx
); 
1353         width 
= column
.GetWidth(); 
1354     } while (++idx 
<= col
); 
1356     m_owner
->CalcScrolledPosition(x
, 0, &x
, NULL
); 
1357     RefreshRect(wxRect(x
, 0, width
, GetSize().GetHeight()));    
1362 void wxTreeListHeaderWindow::OnMouse (wxMouseEvent 
&event
) { 
1364     // we want to work with logical coords 
1366     m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
); 
1367     int y 
= event
.GetY(); 
1369 #if wxCHECK_VERSION_FULL(2, 7, 0, 1) 
1370     if ( event
.Moving() ) 
1372         int col 
= XToCol(x
); 
1373         if ( col 
!= m_hotTrackCol 
) 
1375             // Refresh the col header so it will be painted with hot tracking 
1376             // (if supported by the native renderer.) 
1377             RefreshColLabel(col
); 
1379             // Also refresh the old hot header 
1380             if ( m_hotTrackCol 
>= 0 ) 
1381                 RefreshColLabel(m_hotTrackCol
); 
1383             m_hotTrackCol 
= col
; 
1387     if ( event
.Leaving() && m_hotTrackCol 
>= 0 ) 
1389         // Leaving the window so clear any hot tracking indicator that may be present 
1390         RefreshColLabel(m_hotTrackCol
); 
1397         SendListEvent (wxEVT_COMMAND_LIST_COL_DRAGGING
, event
.GetPosition()); 
1399         // we don't draw the line beyond our window, but we allow dragging it 
1402         GetClientSize( &w
, NULL 
); 
1403         m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1406         // erase the line if it was drawn 
1407         if (m_currentX 
< w
) DrawCurrent(); 
1409         if (event
.ButtonUp()) { 
1410             m_isDragging 
= false; 
1411             if (HasCapture()) ReleaseMouse(); 
1413             SetColumnWidth (m_column
, m_currentX 
- m_minX
); 
1415             SendListEvent (wxEVT_COMMAND_LIST_COL_END_DRAG
, event
.GetPosition()); 
1417             m_currentX 
= wxMax (m_minX 
+ 7, x
); 
1419             // draw in the new location 
1420             if (m_currentX 
< w
) DrawCurrent(); 
1423     }else{ // not dragging 
1426         bool hit_border 
= false; 
1428         // end of the current column 
1431         // find the column where this event occured 
1432         int countCol 
= GetColumnCount(); 
1433         for (int column 
= 0; column 
< countCol
; column
++) { 
1434             if (!IsColumnShown (column
)) continue; // do next if not shown 
1436             xpos 
+= GetColumnWidth (column
); 
1438             if ((abs (x
-xpos
) < 3) && (y 
< 22)) { 
1439                 // near the column border 
1445                 // inside the column 
1452         if (event
.LeftDown() || event
.RightUp()) { 
1453             if (hit_border 
&& event
.LeftDown()) { 
1454                 m_isDragging 
= true; 
1458                 SendListEvent (wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
, event
.GetPosition()); 
1459             }else{ // click on a column 
1460                 wxEventType evt 
= event
.LeftDown()? wxEVT_COMMAND_LIST_COL_CLICK
: 
1461                                                     wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
; 
1462                 SendListEvent (evt
, event
.GetPosition()); 
1464         }else if (event
.LeftDClick() && hit_border
) { 
1465             SetColumnWidth (m_column
, m_owner
->GetBestColumnWidth (m_column
)); 
1468         }else if (event
.Moving()) { 
1471                 setCursor 
= m_currentCursor 
== wxSTANDARD_CURSOR
; 
1472                 m_currentCursor 
= m_resizeCursor
; 
1474                 setCursor 
= m_currentCursor 
!= wxSTANDARD_CURSOR
; 
1475                 m_currentCursor 
= wxSTANDARD_CURSOR
; 
1477             if (setCursor
) SetCursor (*m_currentCursor
); 
1483 void wxTreeListHeaderWindow::OnSetFocus (wxFocusEvent 
&WXUNUSED(event
)) { 
1484     m_owner
->SetFocus(); 
1487 void wxTreeListHeaderWindow::SendListEvent (wxEventType type
, wxPoint pos
) { 
1488     wxWindow 
*parent 
= GetParent(); 
1489     wxListEvent 
le (type
, parent
->GetId()); 
1490     le
.SetEventObject (parent
); 
1491     le
.m_pointDrag 
= pos
; 
1493     // the position should be relative to the parent window, not 
1494     // this one for compatibility with MSW and common sense: the 
1495     // user code doesn't know anything at all about this header 
1496     // window, so why should it get positions relative to it? 
1497     le
.m_pointDrag
.y 
-= GetSize().y
; 
1498     le
.m_col 
= m_column
; 
1499     parent
->GetEventHandler()->ProcessEvent (le
); 
1502 void wxTreeListHeaderWindow::AddColumn (const wxTreeListColumnInfo
& colInfo
) { 
1503     m_columns
.Add (colInfo
); 
1504     m_total_col_width 
+= colInfo
.GetWidth(); 
1505     m_owner
->AdjustMyScrollbars(); 
1506     m_owner
->m_dirty 
= true; 
1509 void wxTreeListHeaderWindow::SetColumnWidth (int column
, int width
) { 
1510     wxCHECK_RET ((column 
>= 0) && (column 
< GetColumnCount()), _T("Invalid column")); 
1511     m_total_col_width 
-= m_columns
[column
].GetWidth(); 
1512     m_columns
[column
].SetWidth(width
); 
1513     m_total_col_width 
+= width
; 
1514     m_owner
->AdjustMyScrollbars(); 
1515     m_owner
->m_dirty 
= true; 
1518 void wxTreeListHeaderWindow::InsertColumn (int before
, const wxTreeListColumnInfo
& colInfo
) { 
1519     wxCHECK_RET ((before 
>= 0) && (before 
< GetColumnCount()), _T("Invalid column")); 
1520     m_columns
.Insert (colInfo
, before
); 
1521     m_total_col_width 
+= colInfo
.GetWidth(); 
1522     m_owner
->AdjustMyScrollbars(); 
1523     m_owner
->m_dirty 
= true; 
1526 void wxTreeListHeaderWindow::RemoveColumn (int column
) { 
1527     wxCHECK_RET ((column 
>= 0) && (column 
< GetColumnCount()), _T("Invalid column")); 
1528     m_total_col_width 
-= m_columns
[column
].GetWidth(); 
1529     m_columns
.RemoveAt (column
); 
1530     m_owner
->AdjustMyScrollbars(); 
1531     m_owner
->m_dirty 
= true; 
1534 void wxTreeListHeaderWindow::SetColumn (int column
, const wxTreeListColumnInfo
& info
) { 
1535     wxCHECK_RET ((column 
>= 0) && (column 
< GetColumnCount()), _T("Invalid column")); 
1536     int w 
= m_columns
[column
].GetWidth(); 
1537     m_columns
[column
] = info
; 
1538     if (w 
!= info
.GetWidth()) { 
1539         m_total_col_width 
+= info
.GetWidth() - w
; 
1540         m_owner
->AdjustMyScrollbars(); 
1542     m_owner
->m_dirty 
= true; 
1545 // --------------------------------------------------------------------------- 
1547 // --------------------------------------------------------------------------- 
1549 wxTreeListItem::wxTreeListItem (wxTreeListMainWindow 
*owner
, 
1550                                 wxTreeListItem 
*parent
, 
1551                                 const wxArrayString
& text
, 
1552                                 int image
, int selImage
, 
1553                                 wxTreeItemData 
*data
) 
1556     m_images
[wxTreeItemIcon_Normal
] = image
; 
1557     m_images
[wxTreeItemIcon_Selected
] = selImage
; 
1558     m_images
[wxTreeItemIcon_Expanded
] = NO_IMAGE
; 
1559     m_images
[wxTreeItemIcon_SelectedExpanded
] = NO_IMAGE
; 
1566     m_isCollapsed 
= true; 
1567     m_hasHilight 
= false; 
1574     m_attr 
= (wxTreeItemAttr 
*)NULL
; 
1577     // We don't know the height here yet. 
1582 wxTreeListItem::~wxTreeListItem() { 
1584     if (m_ownsAttr
) delete m_attr
; 
1586     wxASSERT_MSG( m_children
.IsEmpty(), _T("please call DeleteChildren() before destructor")); 
1589 void wxTreeListItem::DeleteChildren (wxTreeListMainWindow 
*tree
) { 
1590     size_t count 
= m_children
.Count(); 
1591     for (size_t n 
= 0; n 
< count
; n
++) { 
1592         wxTreeListItem 
*child 
= m_children
[n
]; 
1594             tree
->SendDeleteEvent (child
); 
1595             if (tree
->m_selectItem 
== child
) tree
->m_selectItem 
= (wxTreeListItem
*)NULL
; 
1597         child
->DeleteChildren (tree
); 
1603 void wxTreeListItem::SetText (const wxString 
&text
) { 
1604     if (m_text
.GetCount() > 0) { 
1611 size_t wxTreeListItem::GetChildrenCount (bool recursively
) const { 
1612     size_t count 
= m_children
.Count(); 
1613     if (!recursively
) return count
; 
1615     size_t total 
= count
; 
1616     for (size_t n 
= 0; n 
< count
; ++n
) { 
1617         total 
+= m_children
[n
]->GetChildrenCount(); 
1622 void wxTreeListItem::GetSize (int &x
, int &y
, const wxTreeListMainWindow 
*theButton
) { 
1623     int bottomY 
= m_y 
+ theButton
->GetLineHeight (this); 
1624     if (y 
< bottomY
) y 
= bottomY
; 
1625     int width 
= m_x 
+  m_width
; 
1626     if ( x 
< width 
) x 
= width
; 
1629         size_t count 
= m_children
.Count(); 
1630         for (size_t n 
= 0; n 
< count
; ++n 
) { 
1631             m_children
[n
]->GetSize (x
, y
, theButton
); 
1636 wxTreeListItem 
*wxTreeListItem::HitTest (const wxPoint
& point
, 
1637                                          const wxTreeListMainWindow 
*theCtrl
, 
1638                                          int &flags
, int& column
, int level
) { 
1640     // for a hidden root node, don't evaluate it, but do evaluate children 
1641     if (!theCtrl
->HasFlag(wxTR_HIDE_ROOT
) || (level 
> 0)) { 
1643         // reset any previous hit infos 
1646         wxTreeListHeaderWindow
* header_win 
= theCtrl
->m_owner
->GetHeaderWindow(); 
1648         // check for right of all columns (outside) 
1649         if (point
.x 
> header_win
->GetWidth()) return (wxTreeListItem
*) NULL
; 
1651         // evaluate if y-pos is okay 
1652         int h 
= theCtrl
->GetLineHeight (this); 
1653         if ((point
.y 
>= m_y
) && (point
.y 
<= m_y 
+ h
)) { 
1655             int maincol 
= theCtrl
->GetMainColumn(); 
1657             // check for above/below middle 
1658             int y_mid 
= m_y 
+ h
/2; 
1659             if (point
.y 
< y_mid
) { 
1660                 flags 
|= wxTREE_HITTEST_ONITEMUPPERPART
; 
1662                 flags 
|= wxTREE_HITTEST_ONITEMLOWERPART
; 
1665             // check for button hit 
1666             if (HasPlus() && theCtrl
->HasButtons()) { 
1667                 int bntX 
= m_x 
- theCtrl
->m_btnWidth2
; 
1668                 int bntY 
= y_mid 
- theCtrl
->m_btnHeight2
; 
1669                 if ((point
.x 
>= bntX
) && (point
.x 
<= (bntX 
+ theCtrl
->m_btnWidth
)) && 
1670                     (point
.y 
>= bntY
) && (point
.y 
<= (bntY 
+ theCtrl
->m_btnHeight
))) { 
1671                     flags 
|= wxTREE_HITTEST_ONITEMBUTTON
; 
1677             // check for image hit 
1678             if (theCtrl
->m_imgWidth 
> 0) { 
1679                 int imgX 
= m_text_x 
- theCtrl
->m_imgWidth 
- MARGIN
; 
1680                 int imgY 
= y_mid 
- theCtrl
->m_imgHeight2
; 
1681                 if ((point
.x 
>= imgX
) && (point
.x 
<= (imgX 
+ theCtrl
->m_imgWidth
)) && 
1682                     (point
.y 
>= imgY
) && (point
.y 
<= (imgY 
+ theCtrl
->m_imgHeight
))) { 
1683                     flags 
|= wxTREE_HITTEST_ONITEMICON
; 
1689             // check for label hit 
1690             if ((point
.x 
>= m_text_x
) && (point
.x 
<= (m_text_x 
+ m_width
))) { 
1691                 flags 
|= wxTREE_HITTEST_ONITEMLABEL
; 
1696             // check for indent hit after button and image hit 
1697             if (point
.x 
< m_x
) { 
1698                 flags 
|= wxTREE_HITTEST_ONITEMINDENT
; 
1699                 column 
= -1; // considered not belonging to main column 
1703             // check for right of label 
1705             for (int i 
= 0; i 
<= maincol
; ++i
) end 
+= header_win
->GetColumnWidth (i
); 
1706             if ((point
.x 
> (m_text_x 
+ m_width
)) && (point
.x 
<= end
)) { 
1707                 flags 
|= wxTREE_HITTEST_ONITEMRIGHT
; 
1708                 column 
= -1; // considered not belonging to main column 
1712             // else check for each column except main 
1714             for (int j 
= 0; j 
< theCtrl
->GetColumnCount(); ++j
) { 
1715                 if (!header_win
->IsColumnShown(j
)) continue; 
1716                 int w 
= header_win
->GetColumnWidth (j
); 
1717                 if ((j 
!= maincol
) && (point
.x 
>= x 
&& point
.x 
< x
+w
)) { 
1718                     flags 
|= wxTREE_HITTEST_ONITEMCOLUMN
; 
1725             // no special flag or column found 
1730         // if children not expanded, return no item 
1731         if (!IsExpanded()) return (wxTreeListItem
*) NULL
; 
1734     // in any case evaluate children 
1735     wxTreeListItem 
*child
; 
1736     size_t count 
= m_children
.Count(); 
1737     for (size_t n 
= 0; n 
< count
; n
++) { 
1738         child 
= m_children
[n
]->HitTest (point
, theCtrl
, flags
, column
, level
+1); 
1739         if (child
) return child
; 
1743     return (wxTreeListItem
*) NULL
; 
1746 int wxTreeListItem::GetCurrentImage() const { 
1747     int image 
= NO_IMAGE
; 
1750             image 
= GetImage (wxTreeItemIcon_SelectedExpanded
); 
1752             image 
= GetImage (wxTreeItemIcon_Expanded
); 
1754     }else{ // not expanded 
1756             image 
= GetImage (wxTreeItemIcon_Selected
); 
1758             image 
= GetImage (wxTreeItemIcon_Normal
); 
1762     // maybe it doesn't have the specific image, try the default one instead 
1763     if (image 
== NO_IMAGE
) image 
= GetImage(); 
1768 // --------------------------------------------------------------------------- 
1769 // wxTreeListMainWindow implementation 
1770 // --------------------------------------------------------------------------- 
1772 IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow
, wxScrolledWindow
) 
1774 BEGIN_EVENT_TABLE(wxTreeListMainWindow
, wxScrolledWindow
) 
1775     EVT_PAINT          (wxTreeListMainWindow::OnPaint
) 
1776     EVT_MOUSE_EVENTS   (wxTreeListMainWindow::OnMouse
) 
1777     EVT_CHAR           (wxTreeListMainWindow::OnChar
) 
1778     EVT_SET_FOCUS      (wxTreeListMainWindow::OnSetFocus
) 
1779     EVT_KILL_FOCUS     (wxTreeListMainWindow::OnKillFocus
) 
1780     EVT_IDLE           (wxTreeListMainWindow::OnIdle
) 
1781     EVT_SCROLLWIN      (wxTreeListMainWindow::OnScroll
) 
1785 // --------------------------------------------------------------------------- 
1786 // construction/destruction 
1787 // --------------------------------------------------------------------------- 
1789 void wxTreeListMainWindow::Init() { 
1791     m_rootItem 
= (wxTreeListItem
*)NULL
; 
1792     m_curItem 
= (wxTreeListItem
*)NULL
; 
1793     m_shiftItem 
= (wxTreeListItem
*)NULL
; 
1794     m_editItem 
= (wxTreeListItem
*)NULL
; 
1795     m_selectItem 
= (wxTreeListItem
*)NULL
; 
1797     m_curColumn 
= -1; // no current column 
1802     m_lineHeight 
= LINEHEIGHT
; 
1803     m_indent 
= MININDENT
; // min. indent 
1806 #if !wxCHECK_VERSION(2, 5, 0) 
1807     m_hilightBrush 
= new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
); 
1808     m_hilightUnfocusedBrush 
= new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNSHADOW
), wxSOLID
); 
1810     m_hilightBrush 
= new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHT
), wxSOLID
); 
1811     m_hilightUnfocusedBrush 
= new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNSHADOW
), wxSOLID
); 
1814     m_imageListNormal 
= (wxImageList 
*) NULL
; 
1815     m_imageListButtons 
= (wxImageList 
*) NULL
; 
1816     m_imageListState 
= (wxImageList 
*) NULL
; 
1817     m_ownsImageListNormal 
= m_ownsImageListButtons 
= 
1818     m_ownsImageListState 
= false; 
1820     m_imgWidth 
= 0, m_imgWidth2 
= 0; 
1821     m_imgHeight 
= 0, m_imgHeight2 
= 0; 
1822     m_btnWidth 
= 0, m_btnWidth2 
= 0; 
1823     m_btnHeight 
= 0, m_btnHeight2 
= 0; 
1826     m_isDragging 
= false; 
1827     m_dragTimer 
= new wxTimer (this, -1); 
1828     m_dragItem 
= (wxTreeListItem
*)NULL
; 
1830     m_renameTimer 
= new wxTreeListRenameTimer (this); 
1831     m_lastOnSame 
= false; 
1832     m_left_down_selection 
= false; 
1834     m_findTimer 
= new wxTimer (this, -1); 
1836 #if defined( __WXMAC__ ) && defined(__WXMAC_CARBON__) 
1837     m_normalFont
.MacCreateThemeFont (kThemeViewsFont
); 
1839     m_normalFont 
= wxSystemSettings::GetFont (wxSYS_DEFAULT_GUI_FONT
); 
1841     m_boldFont 
= wxFont( m_normalFont
.GetPointSize(), 
1842                          m_normalFont
.GetFamily(), 
1843                          m_normalFont
.GetStyle(), 
1845                          m_normalFont
.GetUnderlined(), 
1846                          m_normalFont
.GetFaceName(), 
1847                          m_normalFont
.GetEncoding()); 
1850 bool wxTreeListMainWindow::Create (wxTreeListCtrl 
*parent
, 
1855                                    const wxValidator 
&validator
, 
1856                                    const wxString
& name
) { 
1859     if (style 
& wxTR_HAS_BUTTONS
) style 
|= wxTR_MAC_BUTTONS
; 
1860     if (style 
& wxTR_HAS_BUTTONS
) style 
&= ~wxTR_HAS_BUTTONS
; 
1861     style 
&= ~wxTR_LINES_AT_ROOT
; 
1862     style 
|= wxTR_NO_LINES
; 
1865     wxGetOsVersion( &major
, &minor 
); 
1866     if (major 
< 10) style 
|= wxTR_ROW_LINES
; 
1869     wxScrolledWindow::Create (parent
, id
, pos
, size
, style
|wxHSCROLL
|wxVSCROLL
, name
); 
1871 #if wxUSE_VALIDATORS 
1872     SetValidator(validator
); 
1875 #if !wxCHECK_VERSION(2, 5, 0) 
1876     SetBackgroundColour (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_LISTBOX
)); 
1878     SetBackgroundColour (wxSystemSettings::GetColour (wxSYS_COLOUR_LISTBOX
)); 
1886         bdc
.SelectObject(bmp
); 
1887         bdc
.SetPen(*wxGREY_PEN
); 
1888         bdc
.DrawRectangle(-1, -1, 10, 10); 
1889         for (i 
= 0; i 
< 8; i
++) { 
1890             for (j 
= 0; j 
< 8; j
++) { 
1891                 if (!((i 
+ j
) & 1)) { 
1892                     bdc
.DrawPoint(i
, j
); 
1897         m_dottedPen 
= wxPen(bmp
, 1); 
1900 //?    m_dottedPen = wxPen( *wxGREY_PEN, 1, wxDOT );  // too slow under XFree86 
1901     m_dottedPen 
= wxPen( _T("grey"), 0, 0 ); // Bitmap based pen is not supported by GTK! 
1910 wxTreeListMainWindow::~wxTreeListMainWindow() { 
1911     delete m_hilightBrush
; 
1912     delete m_hilightUnfocusedBrush
; 
1915     delete m_renameTimer
; 
1917     if (m_ownsImageListNormal
) delete m_imageListNormal
; 
1918     if (m_ownsImageListState
) delete m_imageListState
; 
1919     if (m_ownsImageListButtons
) delete m_imageListButtons
; 
1925 //----------------------------------------------------------------------------- 
1927 //----------------------------------------------------------------------------- 
1929 size_t wxTreeListMainWindow::GetCount() const { 
1930     return m_rootItem 
== NULL
? 0: m_rootItem
->GetChildrenCount(); 
1933 void wxTreeListMainWindow::SetIndent (unsigned int indent
) { 
1934     m_indent 
= wxMax ((unsigned)MININDENT
, indent
); 
1938 void wxTreeListMainWindow::SetLineSpacing (unsigned int spacing
) { 
1939     m_linespacing 
= spacing
; 
1941     CalculateLineHeight(); 
1944 size_t wxTreeListMainWindow::GetChildrenCount (const wxTreeItemId
& item
, 
1946     wxCHECK_MSG (item
.IsOk(), 0u, _T("invalid tree item")); 
1947     return ((wxTreeListItem
*)item
.m_pItem
)->GetChildrenCount (recursively
); 
1950 void wxTreeListMainWindow::SetWindowStyle (const long styles
) { 
1951     // right now, just sets the styles.  Eventually, we may 
1952     // want to update the inherited styles, but right now 
1953     // none of the parents has updatable styles 
1954     m_windowStyle 
= styles
; 
1958 //----------------------------------------------------------------------------- 
1959 // functions to work with tree items 
1960 //----------------------------------------------------------------------------- 
1962 int wxTreeListMainWindow::GetItemImage (const wxTreeItemId
& item
, int column
, 
1963                                         wxTreeItemIcon which
) const { 
1964     wxCHECK_MSG (item
.IsOk(), -1, _T("invalid tree item")); 
1965     return ((wxTreeListItem
*) item
.m_pItem
)->GetImage (column
, which
); 
1968 wxTreeItemData 
*wxTreeListMainWindow::GetItemData (const wxTreeItemId
& item
) const { 
1969     wxCHECK_MSG (item
.IsOk(), NULL
, _T("invalid tree item")); 
1970     return ((wxTreeListItem
*) item
.m_pItem
)->GetData(); 
1973 bool wxTreeListMainWindow::GetItemBold (const wxTreeItemId
& item
) const { 
1974     wxCHECK_MSG(item
.IsOk(), false, _T("invalid tree item")); 
1975     return ((wxTreeListItem 
*)item
.m_pItem
)->IsBold(); 
1978 wxColour 
wxTreeListMainWindow::GetItemTextColour (const wxTreeItemId
& item
) const { 
1979     wxCHECK_MSG (item
.IsOk(), wxNullColour
, _T("invalid tree item")); 
1980     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1981     return pItem
->Attr().GetTextColour(); 
1984 wxColour 
wxTreeListMainWindow::GetItemBackgroundColour (const wxTreeItemId
& item
) const { 
1985     wxCHECK_MSG (item
.IsOk(), wxNullColour
, _T("invalid tree item")); 
1986     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1987     return pItem
->Attr().GetBackgroundColour(); 
1990 wxFont 
wxTreeListMainWindow::GetItemFont (const wxTreeItemId
& item
) const { 
1991     wxCHECK_MSG (item
.IsOk(), wxNullFont
, _T("invalid tree item")); 
1992     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1993     return pItem
->Attr().GetFont(); 
1996 void wxTreeListMainWindow::SetItemImage (const wxTreeItemId
& item
, int column
, 
1997                                          int image
, wxTreeItemIcon which
) { 
1998     wxCHECK_RET (item
.IsOk(), _T("invalid tree item")); 
1999     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2000     pItem
->SetImage (column
, image
, which
); 
2001     wxClientDC 
dc (this); 
2002     CalculateSize (pItem
, dc
); 
2003     RefreshLine (pItem
); 
2006 void wxTreeListMainWindow::SetItemData (const wxTreeItemId
& item
, 
2007                                         wxTreeItemData 
*data
) { 
2008     wxCHECK_RET (item
.IsOk(), _T("invalid tree item")); 
2009     ((wxTreeListItem
*) item
.m_pItem
)->SetData(data
); 
2012 void wxTreeListMainWindow::SetItemHasChildren (const wxTreeItemId
& item
, 
2014     wxCHECK_RET (item
.IsOk(), _T("invalid tree item")); 
2015     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2016     pItem
->SetHasPlus (has
); 
2017     RefreshLine (pItem
); 
2020 void wxTreeListMainWindow::SetItemBold (const wxTreeItemId
& item
, bool bold
) { 
2021     wxCHECK_RET (item
.IsOk(), _T("invalid tree item")); 
2022     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2023     if (pItem
->IsBold() != bold
) { // avoid redrawing if no real change 
2024         pItem
->SetBold (bold
); 
2025         RefreshLine (pItem
); 
2029 void wxTreeListMainWindow::SetItemTextColour (const wxTreeItemId
& item
, 
2030                                               const wxColour
& colour
) { 
2031     wxCHECK_RET (item
.IsOk(), _T("invalid tree item")); 
2032     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2033     pItem
->Attr().SetTextColour (colour
); 
2034     RefreshLine (pItem
); 
2037 void wxTreeListMainWindow::SetItemBackgroundColour (const wxTreeItemId
& item
, 
2038                                                     const wxColour
& colour
) { 
2039     wxCHECK_RET (item
.IsOk(), _T("invalid tree item")); 
2040     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2041     pItem
->Attr().SetBackgroundColour (colour
); 
2042     RefreshLine (pItem
); 
2045 void wxTreeListMainWindow::SetItemFont (const wxTreeItemId
& item
, 
2046                                         const wxFont
& font
) { 
2047     wxCHECK_RET (item
.IsOk(), _T("invalid tree item")); 
2048     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2049     pItem
->Attr().SetFont (font
); 
2050     RefreshLine (pItem
); 
2053 bool wxTreeListMainWindow::SetFont (const wxFont 
&font
) { 
2054     wxScrolledWindow::SetFont (font
); 
2055     m_normalFont 
= font
; 
2056     m_boldFont 
= wxFont (m_normalFont
.GetPointSize(), 
2057                          m_normalFont
.GetFamily(), 
2058                          m_normalFont
.GetStyle(), 
2060                          m_normalFont
.GetUnderlined(), 
2061                          m_normalFont
.GetFaceName()); 
2062     CalculateLineHeight(); 
2067 // ---------------------------------------------------------------------------- 
2068 // item status inquiries 
2069 // ---------------------------------------------------------------------------- 
2071 bool wxTreeListMainWindow::IsVisible (const wxTreeItemId
& item
, bool fullRow
) const { 
2072     wxCHECK_MSG (item
.IsOk(), false, _T("invalid tree item")); 
2074     // An item is only visible if it's not a descendant of a collapsed item 
2075     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2076     wxTreeListItem
* parent 
= pItem
->GetItemParent(); 
2078         if (parent 
== m_rootItem 
&& HasFlag(wxTR_HIDE_ROOT
)) break; 
2079         if (!parent
->IsExpanded()) return false; 
2080         parent 
= parent
->GetItemParent(); 
2083     wxSize clientSize 
= GetClientSize(); 
2085     if ((!GetBoundingRect (item
, rect
)) || 
2086         ((!fullRow 
&& rect
.GetWidth() == 0) || rect
.GetHeight() == 0) || 
2087         (rect
.GetBottom() < 0 || rect
.GetTop() > clientSize
.y
) || 
2088         (!fullRow 
&& (rect
.GetRight() < 0 || rect
.GetLeft() > clientSize
.x
))) return false; 
2093 bool wxTreeListMainWindow::HasChildren (const wxTreeItemId
& item
) const { 
2094     wxCHECK_MSG (item
.IsOk(), false, _T("invalid tree item")); 
2096     // consider that the item does have children if it has the "+" button: it 
2097     // might not have them (if it had never been expanded yet) but then it 
2098     // could have them as well and it's better to err on this side rather than 
2099     // disabling some operations which are restricted to the items with 
2100     // children for an item which does have them 
2101     return ((wxTreeListItem
*) item
.m_pItem
)->HasPlus(); 
2104 bool wxTreeListMainWindow::IsExpanded (const wxTreeItemId
& item
) const { 
2105     wxCHECK_MSG (item
.IsOk(), false, _T("invalid tree item")); 
2106     return ((wxTreeListItem
*) item
.m_pItem
)->IsExpanded(); 
2109 bool wxTreeListMainWindow::IsSelected (const wxTreeItemId
& item
) const { 
2110     wxCHECK_MSG (item
.IsOk(), false, _T("invalid tree item")); 
2111     return ((wxTreeListItem
*) item
.m_pItem
)->IsSelected(); 
2114 bool wxTreeListMainWindow::IsBold (const wxTreeItemId
& item
) const { 
2115     wxCHECK_MSG (item
.IsOk(), false, _T("invalid tree item")); 
2116     return ((wxTreeListItem
*) item
.m_pItem
)->IsBold(); 
2119 // ---------------------------------------------------------------------------- 
2121 // ---------------------------------------------------------------------------- 
2123 wxTreeItemId 
wxTreeListMainWindow::GetItemParent (const wxTreeItemId
& item
) const { 
2124     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2125     return ((wxTreeListItem
*) item
.m_pItem
)->GetItemParent(); 
2128 #if !wxCHECK_VERSION(2, 5, 0) 
2129 wxTreeItemId 
wxTreeListMainWindow::GetFirstChild (const wxTreeItemId
& item
, 
2130                                                   long& cookie
) const { 
2132 wxTreeItemId 
wxTreeListMainWindow::GetFirstChild (const wxTreeItemId
& item
, 
2133                                                   wxTreeItemIdValue
& cookie
) const { 
2135     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2136     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2138     return (!children
.IsEmpty())? wxTreeItemId(children
.Item(0)): wxTreeItemId(); 
2141 #if !wxCHECK_VERSION(2, 5, 0) 
2142 wxTreeItemId 
wxTreeListMainWindow::GetNextChild (const wxTreeItemId
& item
, 
2143                                                  long& cookie
) const { 
2145 wxTreeItemId 
wxTreeListMainWindow::GetNextChild (const wxTreeItemId
& item
, 
2146                                                  wxTreeItemIdValue
& cookie
) const { 
2148     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2149     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2150     // it's ok to cast cookie to long, we never have indices which overflow "void*" 
2151     long *pIndex 
= ((long*)&cookie
); 
2152     return ((*pIndex
)+1 < (long)children
.Count())? wxTreeItemId(children
.Item(++(*pIndex
))): wxTreeItemId(); 
2155 #if !wxCHECK_VERSION(2, 5, 0) 
2156 wxTreeItemId 
wxTreeListMainWindow::GetPrevChild (const wxTreeItemId
& item
, 
2157                                                  long& cookie
) const { 
2159 wxTreeItemId 
wxTreeListMainWindow::GetPrevChild (const wxTreeItemId
& item
, 
2160                                                  wxTreeItemIdValue
& cookie
) const { 
2162     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2163     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2164     // it's ok to cast cookie to long, we never have indices which overflow "void*" 
2165     long *pIndex 
= (long*)&cookie
; 
2166     return ((*pIndex
)-1 >= 0)? wxTreeItemId(children
.Item(--(*pIndex
))): wxTreeItemId(); 
2169 #if !wxCHECK_VERSION(2, 5, 0) 
2170 wxTreeItemId 
wxTreeListMainWindow::GetLastChild (const wxTreeItemId
& item
, 
2171                                                  long& cookie
) const { 
2173 wxTreeItemId 
wxTreeListMainWindow::GetLastChild (const wxTreeItemId
& item
, 
2174                                                  wxTreeItemIdValue
& cookie
) const { 
2176     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2177     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2178     // it's ok to cast cookie to long, we never have indices which overflow "void*" 
2179     long *pIndex 
= ((long*)&cookie
); 
2180     (*pIndex
) = children
.Count(); 
2181     return (!children
.IsEmpty())? wxTreeItemId(children
.Last()): wxTreeItemId(); 
2184 wxTreeItemId 
wxTreeListMainWindow::GetNextSibling (const wxTreeItemId
& item
) const { 
2185     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2188     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2189     wxTreeListItem 
*parent 
= i
->GetItemParent(); 
2190     if (!parent
) return wxTreeItemId(); // root item doesn't have any siblings 
2193     wxArrayTreeListItems
& siblings 
= parent
->GetChildren(); 
2194     size_t index 
= siblings
.Index (i
); 
2195     wxASSERT (index 
!= (size_t)wxNOT_FOUND
); // I'm not a child of my parent? 
2196     return (index 
< siblings
.Count()-1)? wxTreeItemId(siblings
[index
+1]): wxTreeItemId(); 
2199 wxTreeItemId 
wxTreeListMainWindow::GetPrevSibling (const wxTreeItemId
& item
) const { 
2200     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2203     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2204     wxTreeListItem 
*parent 
= i
->GetItemParent(); 
2205     if (!parent
) return wxTreeItemId(); // root item doesn't have any siblings 
2208     wxArrayTreeListItems
& siblings 
= parent
->GetChildren(); 
2209     size_t index 
= siblings
.Index(i
); 
2210     wxASSERT (index 
!= (size_t)wxNOT_FOUND
); // I'm not a child of my parent? 
2211     return (index 
>= 1)? wxTreeItemId(siblings
[index
-1]): wxTreeItemId(); 
2214 // Only for internal use right now, but should probably be public 
2215 wxTreeItemId 
wxTreeListMainWindow::GetNext (const wxTreeItemId
& item
, bool fulltree
) const { 
2216     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2218     // if there are any children, return first child 
2219     if (fulltree 
|| ((wxTreeListItem
*)item
.m_pItem
)->IsExpanded()) { 
2220         wxArrayTreeListItems
& children 
= ((wxTreeListItem
*)item
.m_pItem
)->GetChildren(); 
2221         if (children
.GetCount() > 0) return children
.Item (0); 
2224     // get sibling of this item or of the ancestors instead 
2226     wxTreeItemId parent 
= item
; 
2228         next 
= GetNextSibling (parent
); 
2229         parent 
= GetItemParent (parent
); 
2230     } while (!next
.IsOk() && parent
.IsOk()); 
2234 // Only for internal use right now, but should probably be public 
2235 wxTreeItemId 
wxTreeListMainWindow::GetPrev (const wxTreeItemId
& item
, bool fulltree
) const { 
2236     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2238     // if there are any children, return last child 
2239     if (fulltree 
|| ((wxTreeListItem
*)item
.m_pItem
)->IsExpanded()) { 
2240         wxArrayTreeListItems
& children 
= ((wxTreeListItem
*)item
.m_pItem
)->GetChildren(); 
2241         if (children
.GetCount() > 0) return children
.Item (children
.GetCount()-1); 
2244     // get sibling of this item or of the ancestors instead 
2246     wxTreeItemId parent 
= item
; 
2248         next 
= GetPrevSibling (parent
); 
2249         parent 
= GetItemParent (parent
); 
2250     } while (!next
.IsOk() && parent
.IsOk()); 
2254 wxTreeItemId 
wxTreeListMainWindow::GetFirstExpandedItem() const { 
2255     return GetNextExpanded (GetRootItem()); 
2258 wxTreeItemId 
wxTreeListMainWindow::GetNextExpanded (const wxTreeItemId
& item
) const { 
2259     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2260     return GetNext (item
, false); 
2263 wxTreeItemId 
wxTreeListMainWindow::GetPrevExpanded (const wxTreeItemId
& item
) const { 
2264     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2265     return GetPrev (item
, false); 
2268 wxTreeItemId 
wxTreeListMainWindow::GetFirstVisibleItem (bool fullRow
) const { 
2269     return GetNextVisible (GetRootItem(), fullRow
); 
2272 wxTreeItemId 
wxTreeListMainWindow::GetNextVisible (const wxTreeItemId
& item
, bool fullRow
) const { 
2273     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2274     wxTreeItemId id 
= GetNext (item
, false); 
2276         if (IsVisible (id
, fullRow
)) return id
; 
2277         id 
= GetNext (id
, false); 
2279     return wxTreeItemId(); 
2282 wxTreeItemId 
wxTreeListMainWindow::GetPrevVisible (const wxTreeItemId
& item
, bool fullRow
) const { 
2283     wxCHECK_MSG (item
.IsOk(), wxTreeItemId(), _T("invalid tree item")); 
2284     wxTreeItemId id 
= GetPrev (item
, true); 
2286         if (IsVisible (id
, fullRow
)) return id
; 
2287         id 
= GetPrev(id
, true); 
2289     return wxTreeItemId(); 
2292 // ---------------------------------------------------------------------------- 
2294 // ---------------------------------------------------------------------------- 
2296 wxTreeItemId 
wxTreeListMainWindow::DoInsertItem (const wxTreeItemId
& parentId
, 
2298                                                  const wxString
& text
, 
2299                                                  int image
, int selImage
, 
2300                                                  wxTreeItemData 
*data
) { 
2301     wxTreeListItem 
*parent 
= (wxTreeListItem
*)parentId
.m_pItem
; 
2302     wxCHECK_MSG (parent
, wxTreeItemId(), _T("item must have a parent, at least root!") ); 
2303     m_dirty 
= true; // do this first so stuff below doesn't cause flicker 
2306     arr
.Alloc (GetColumnCount()); 
2307     for (int i 
= 0; i 
< (int)GetColumnCount(); ++i
) arr
.Add (wxEmptyString
); 
2308     arr
[m_main_column
] = text
; 
2309     wxTreeListItem 
*item 
= new wxTreeListItem (this, parent
, arr
, image
, selImage
, data
); 
2311 #if !wxCHECK_VERSION(2, 5, 0) 
2312         data
->SetId ((long)item
); 
2317     parent
->Insert (item
, previous
); 
2322 wxTreeItemId 
wxTreeListMainWindow::AddRoot (const wxString
& text
, 
2323                                             int image
, int selImage
, 
2324                                             wxTreeItemData 
*data
) { 
2325     wxCHECK_MSG(!m_rootItem
, wxTreeItemId(), _T("tree can have only one root")); 
2326     wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), _T("Add column(s) before adding the root item")); 
2327     m_dirty 
= true; // do this first so stuff below doesn't cause flicker 
2330     arr
.Alloc (GetColumnCount()); 
2331     for (int i 
= 0; i 
< (int)GetColumnCount(); ++i
) arr
.Add (wxEmptyString
); 
2332     arr
[m_main_column
] = text
; 
2333     m_rootItem 
= new wxTreeListItem (this, (wxTreeListItem 
*)NULL
, arr
, image
, selImage
, data
); 
2335 #if !wxCHECK_VERSION(2, 5, 0) 
2336         data
->SetId((long)m_rootItem
); 
2338         data
->SetId(m_rootItem
); 
2341     if (HasFlag(wxTR_HIDE_ROOT
)) { 
2342         // if we will hide the root, make sure children are visible 
2343         m_rootItem
->SetHasPlus(); 
2344         m_rootItem
->Expand(); 
2345 #if !wxCHECK_VERSION(2, 5, 0) 
2348         wxTreeItemIdValue cookie 
= 0; 
2350         m_curItem 
= (wxTreeListItem
*)GetFirstChild (m_rootItem
, cookie
).m_pItem
; 
2355 wxTreeItemId 
wxTreeListMainWindow::PrependItem (const wxTreeItemId
& parent
, 
2356                                                 const wxString
& text
, 
2357                                                 int image
, int selImage
, 
2358                                                 wxTreeItemData 
*data
) { 
2359     return DoInsertItem (parent
, 0u, text
, image
, selImage
, data
); 
2362 wxTreeItemId 
wxTreeListMainWindow::InsertItem (const wxTreeItemId
& parentId
, 
2363                                                const wxTreeItemId
& idPrevious
, 
2364                                                const wxString
& text
, 
2365                                                int image
, int selImage
, 
2366                                                wxTreeItemData 
*data
) { 
2367     wxTreeListItem 
*parent 
= (wxTreeListItem
*)parentId
.m_pItem
; 
2368     wxCHECK_MSG (parent
, wxTreeItemId(), _T("item must have a parent, at least root!") ); 
2370     int index 
= parent
->GetChildren().Index((wxTreeListItem
*) idPrevious
.m_pItem
); 
2371     wxASSERT_MSG( index 
!= wxNOT_FOUND
, 
2372                   _T("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") ); 
2374     return DoInsertItem (parentId
, ++index
, text
, image
, selImage
, data
); 
2377 wxTreeItemId 
wxTreeListMainWindow::InsertItem (const wxTreeItemId
& parentId
, 
2379                                                const wxString
& text
, 
2380                                                int image
, int selImage
, 
2381                                                wxTreeItemData 
*data
) { 
2382     wxTreeListItem 
*parent 
= (wxTreeListItem
*)parentId
.m_pItem
; 
2383     wxCHECK_MSG (parent
, wxTreeItemId(), _T("item must have a parent, at least root!") ); 
2385     return DoInsertItem (parentId
, before
, text
, image
, selImage
, data
); 
2388 wxTreeItemId 
wxTreeListMainWindow::AppendItem (const wxTreeItemId
& parentId
, 
2389                                                const wxString
& text
, 
2390                                                int image
, int selImage
, 
2391                                                wxTreeItemData 
*data
) { 
2392     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2393     wxCHECK_MSG (parent
, wxTreeItemId(), _T("item must have a parent, at least root!") ); 
2395     return DoInsertItem (parent
, parent
->GetChildren().Count(), text
, image
, selImage
, data
); 
2398 void wxTreeListMainWindow::SendDeleteEvent (wxTreeListItem 
*item
) { 
2399     // send event to user code 
2400     wxTreeEvent 
event (wxEVT_COMMAND_TREE_DELETE_ITEM
, m_owner
->GetId()); 
2401 #if !wxCHECK_VERSION(2, 5, 0) 
2402     event
.SetItem ((long)item
); 
2404     event
.SetItem (item
); 
2406     event
.SetEventObject (m_owner
); 
2407     m_owner
->ProcessEvent (event
); 
2410 void wxTreeListMainWindow::Delete (const wxTreeItemId
& itemId
) { 
2411     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2412     wxCHECK_RET (item 
!= m_rootItem
, _T("invalid item, root may not be deleted this way!")); 
2413     m_dirty 
= true; // do this first so stuff below doesn't cause flicker 
2415     // don't stay with invalid m_shiftItem or we will crash in the next call to OnChar() 
2416     bool changeKeyCurrent 
= false; 
2417     wxTreeListItem 
*itemKey 
= m_shiftItem
; 
2419         if (itemKey 
== item
) { // m_shiftItem is a descendant of the item being deleted 
2420             changeKeyCurrent 
= true; 
2423         itemKey 
= itemKey
->GetItemParent(); 
2426     wxTreeListItem 
*parent 
= item
->GetItemParent(); 
2428         parent
->GetChildren().Remove (item
);  // remove by value 
2430     if (changeKeyCurrent
)  m_shiftItem 
= parent
; 
2432     SendDeleteEvent (item
); 
2433     if (m_selectItem 
== item
) m_selectItem 
= (wxTreeListItem
*)NULL
; 
2434     item
->DeleteChildren (this); 
2438 void wxTreeListMainWindow::DeleteChildren (const wxTreeItemId
& itemId
) { 
2439     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2440     m_dirty 
= true; // do this first so stuff below doesn't cause flicker 
2442     item
->DeleteChildren (this); 
2445 void wxTreeListMainWindow::DeleteRoot() { 
2448         SendDeleteEvent (m_rootItem
); 
2449         m_curItem 
= (wxTreeListItem
*)NULL
; 
2450         m_selectItem
= (wxTreeListItem
*)NULL
; 
2451         m_rootItem
->DeleteChildren (this); 
2457 void wxTreeListMainWindow::Expand (const wxTreeItemId
& itemId
) { 
2458     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2459     wxCHECK_RET (item
, _T("invalid item in wxTreeListMainWindow::Expand") ); 
2461     if (!item
->HasPlus() || item
->IsExpanded()) return; 
2463     // send event to user code 
2464     wxTreeEvent 
event (wxEVT_COMMAND_TREE_ITEM_EXPANDING
, m_owner
->GetId()); 
2465 #if !wxCHECK_VERSION(2, 5, 0) 
2466     event
.SetItem ((long)item
); 
2468     event
.SetItem (item
); 
2470     event
.SetEventObject (m_owner
); 
2471     if (m_owner
->ProcessEvent (event
) && !event
.IsAllowed()) return; // expand canceled 
2476     // send event to user code 
2477     event
.SetEventType (wxEVT_COMMAND_TREE_ITEM_EXPANDED
); 
2478     m_owner
->ProcessEvent (event
); 
2481 void wxTreeListMainWindow::ExpandAll (const wxTreeItemId
& itemId
) { 
2483     if (!IsExpanded (itemId
)) return; 
2484 #if !wxCHECK_VERSION(2, 5, 0) 
2487     wxTreeItemIdValue cookie
; 
2489     wxTreeItemId child 
= GetFirstChild (itemId
, cookie
); 
2490     while (child
.IsOk()) { 
2492         child 
= GetNextChild (itemId
, cookie
); 
2496 void wxTreeListMainWindow::Collapse (const wxTreeItemId
& itemId
) { 
2497     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2498     wxCHECK_RET (item
, _T("invalid item in wxTreeListMainWindow::Collapse") ); 
2500     if (!item
->HasPlus() || !item
->IsExpanded()) return; 
2502     // send event to user code 
2503     wxTreeEvent 
event (wxEVT_COMMAND_TREE_ITEM_COLLAPSING
, m_owner
->GetId() ); 
2504 #if !wxCHECK_VERSION(2, 5, 0) 
2505     event
.SetItem ((long)item
); 
2507     event
.SetItem (item
); 
2509     event
.SetEventObject (m_owner
); 
2510     if (m_owner
->ProcessEvent (event
) && !event
.IsAllowed()) return; // collapse canceled 
2515     // send event to user code 
2516     event
.SetEventType (wxEVT_COMMAND_TREE_ITEM_COLLAPSED
); 
2517     ProcessEvent (event
); 
2520 void wxTreeListMainWindow::CollapseAndReset (const wxTreeItemId
& item
) { 
2522     DeleteChildren (item
); 
2525 void wxTreeListMainWindow::Toggle (const wxTreeItemId
& itemId
) { 
2526     if (IsExpanded (itemId
)) { 
2533 void wxTreeListMainWindow::Unselect() { 
2535         m_selectItem
->SetHilight (false); 
2536         RefreshLine (m_selectItem
); 
2537         m_selectItem 
= (wxTreeListItem
*)NULL
; 
2541 void wxTreeListMainWindow::UnselectAllChildren (wxTreeListItem 
*item
) { 
2542     if (item
->IsSelected()) { 
2543         item
->SetHilight (false); 
2545         if (item 
== m_selectItem
) m_selectItem 
= (wxTreeListItem
*)NULL
; 
2547     if (item
->HasChildren()) { 
2548         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2549         size_t count 
= children
.Count(); 
2550         for (size_t n 
= 0; n 
< count
; ++n
) { 
2551             UnselectAllChildren (children
[n
]); 
2556 void wxTreeListMainWindow::UnselectAll() { 
2557     UnselectAllChildren ((wxTreeListItem
*)GetRootItem().m_pItem
); 
2560 // Recursive function ! 
2561 // To stop we must have crt_item<last_item 
2563 // Tag all next children, when no more children, 
2564 // Move to parent (not to tag) 
2565 // Keep going... if we found last_item, we stop. 
2566 bool wxTreeListMainWindow::TagNextChildren (wxTreeListItem 
*crt_item
, 
2567                                             wxTreeListItem 
*last_item
) { 
2568     wxTreeListItem 
*parent 
= crt_item
->GetItemParent(); 
2570     if (!parent
) {// This is root item 
2571         return TagAllChildrenUntilLast (crt_item
, last_item
); 
2574     wxArrayTreeListItems
& children 
= parent
->GetChildren(); 
2575     int index 
= children
.Index(crt_item
); 
2576     wxASSERT (index 
!= wxNOT_FOUND
); // I'm not a child of my parent? 
2578     if ((parent
->HasChildren() && parent
->IsExpanded()) || 
2579         ((parent 
== (wxTreeListItem
*)GetRootItem().m_pItem
) && HasFlag(wxTR_HIDE_ROOT
))) { 
2580         size_t count 
= children
.Count(); 
2581         for (size_t n 
= (index
+1); n 
< count
; ++n
) { 
2582             if (TagAllChildrenUntilLast (children
[n
], last_item
)) return true; 
2586     return TagNextChildren (parent
, last_item
); 
2589 bool wxTreeListMainWindow::TagAllChildrenUntilLast (wxTreeListItem 
*crt_item
, 
2590                                                     wxTreeListItem 
*last_item
) { 
2591     crt_item
->SetHilight (true); 
2592     RefreshLine(crt_item
); 
2594     if (crt_item
==last_item
) return true; 
2596     if (crt_item
->HasChildren() && crt_item
->IsExpanded()) { 
2597         wxArrayTreeListItems
& children 
= crt_item
->GetChildren(); 
2598         size_t count 
= children
.Count(); 
2599         for (size_t n 
= 0; n 
< count
; ++n
) { 
2600             if (TagAllChildrenUntilLast (children
[n
], last_item
)) return true; 
2607 void wxTreeListMainWindow::SelectItem (const wxTreeItemId
& itemId
, 
2608                                        const wxTreeItemId
& lastId
, 
2609                                        bool unselect_others
) { 
2610     wxCHECK_RET (itemId
.IsOk(), _T("invalid tree item") ); 
2612     bool is_single 
= !HasFlag(wxTR_MULTIPLE
); 
2613     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2615     // single selection requires unselect others 
2616     if (is_single
) unselect_others 
= true; 
2618     // send event to the user code 
2619     wxTreeEvent 
event( wxEVT_COMMAND_TREE_SEL_CHANGING
, m_owner
->GetId() ); 
2620 #if !wxCHECK_VERSION(2, 5, 0) 
2621     event
.SetItem ((long)item
); 
2622     event
.SetOldItem ((long)m_curItem
); 
2624     event
.SetItem (item
); 
2625     event
.SetOldItem (m_curItem
); 
2627     event
.SetEventObject (m_owner
); 
2628     if (m_owner
->GetEventHandler()->ProcessEvent (event
) && !event
.IsAllowed()) return; 
2630     // unselect all if unselect other items 
2631     bool unselected 
= false; // see that UnselectAll is done only once 
2632     if (unselect_others
) { 
2634             Unselect(); // to speed up thing 
2641     // select item or item range 
2642     if (lastId
.IsOk() && (itemId 
!= lastId
)) { 
2644         if (!unselected
) UnselectAll(); 
2645         wxTreeListItem 
*last 
= (wxTreeListItem
*) lastId
.m_pItem
; 
2647         // ensure that the position of the item it calculated in any case 
2648         if (m_dirty
) CalculatePositions(); 
2650         // select item range according Y-position 
2651         if (last
->GetY() < item
->GetY()) { 
2652             if (!TagAllChildrenUntilLast (last
, item
)) { 
2653                 TagNextChildren (last
, item
); 
2656             if (!TagAllChildrenUntilLast (item
, last
)) { 
2657                 TagNextChildren (item
, last
); 
2663         // select item according its old selection 
2664         item
->SetHilight (!item
->IsSelected()); 
2666         if (unselect_others
) { 
2667             m_selectItem 
= (item
->IsSelected())? item
: (wxTreeListItem
*)NULL
; 
2672     // send event to user code 
2673     event
.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED
); 
2674     m_owner
->GetEventHandler()->ProcessEvent (event
); 
2677 void wxTreeListMainWindow::SelectAll() { 
2678     wxCHECK_RET (HasFlag(wxTR_MULTIPLE
), _T("invalid tree style")); 
2680     // send event to user code 
2681     wxTreeEvent 
event (wxEVT_COMMAND_TREE_SEL_CHANGING
, m_owner
->GetId()); 
2682     event
.SetItem (GetRootItem()); 
2683 #if !wxCHECK_VERSION(2, 5, 0) 
2684     event
.SetOldItem ((long)m_curItem
); 
2686     event
.SetOldItem (m_curItem
); 
2688     event
.SetEventObject (m_owner
); 
2689     if (m_owner
->GetEventHandler()->ProcessEvent (event
) && !event
.IsAllowed()) return; 
2691 #if !wxCHECK_VERSION(2, 5, 0) 
2694     wxTreeItemIdValue cookie 
= 0; 
2696     wxTreeItemId root 
= GetRootItem(); 
2697     wxTreeListItem 
*first 
= (wxTreeListItem 
*)GetFirstChild (root
, cookie
).m_pItem
; 
2698     wxTreeListItem 
*last 
= (wxTreeListItem 
*)GetLastChild (root
, cookie
).m_pItem
; 
2699     if (!TagAllChildrenUntilLast (first
, last
)) { 
2700         TagNextChildren (first
, last
); 
2703     // send event to user code 
2704     event
.SetEventType (wxEVT_COMMAND_TREE_SEL_CHANGED
); 
2705     m_owner
->GetEventHandler()->ProcessEvent (event
); 
2708 void wxTreeListMainWindow::FillArray (wxTreeListItem 
*item
, 
2709                                       wxArrayTreeItemIds 
&array
) const { 
2710     if (item
->IsSelected()) array
.Add (wxTreeItemId(item
)); 
2712     if (item
->HasChildren()) { 
2713         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2714         size_t count 
= children
.GetCount(); 
2715         for (size_t n 
= 0; n 
< count
; ++n
) FillArray (children
[n
], array
); 
2719 size_t wxTreeListMainWindow::GetSelections (wxArrayTreeItemIds 
&array
) const { 
2721     wxTreeItemId idRoot 
= GetRootItem(); 
2722     if (idRoot
.IsOk()) FillArray ((wxTreeListItem
*) idRoot
.m_pItem
, array
); 
2723     return array
.Count(); 
2726 void wxTreeListMainWindow::EnsureVisible (const wxTreeItemId
& item
) { 
2727     if (!item
.IsOk()) return; // do nothing if no item 
2729     // first expand all parent branches 
2730     wxTreeListItem 
*gitem 
= (wxTreeListItem
*) item
.m_pItem
; 
2731     wxTreeListItem 
*parent 
= gitem
->GetItemParent(); 
2734         parent 
= parent
->GetItemParent(); 
2738     RefreshLine (gitem
); 
2741 void wxTreeListMainWindow::ScrollTo (const wxTreeItemId 
&item
) { 
2742     if (!item
.IsOk()) return; // do nothing if no item 
2744     // ensure that the position of the item it calculated in any case 
2745     if (m_dirty
) CalculatePositions(); 
2747     wxTreeListItem 
*gitem 
= (wxTreeListItem
*) item
.m_pItem
; 
2749     // now scroll to the item 
2750     int item_y 
= gitem
->GetY(); 
2753     GetScrollPixelsPerUnit (&xUnit
, &yUnit
); 
2756     GetViewStart (&start_x
, &start_y
); 
2761     GetClientSize (&client_w
, &client_h
); 
2765     m_rootItem
->GetSize (x
, y
, this); 
2766     x 
= m_owner
->GetHeaderWindow()->GetWidth(); 
2767     y 
+= yUnit 
+ 2; // one more scrollbar unit + 2 pixels 
2768     int x_pos 
= GetScrollPos( wxHORIZONTAL 
); 
2770     if (item_y 
< start_y
+3) { 
2771         // going down, item should appear at top 
2772         SetScrollbars (xUnit
, yUnit
, xUnit 
? x
/xUnit 
: 0, yUnit 
? y
/yUnit 
: 0, x_pos
, yUnit 
? item_y
/yUnit 
: 0); 
2773     }else if (item_y
+GetLineHeight(gitem
) > start_y
+client_h
) { 
2774         // going up, item should appear at bottom 
2775         item_y 
+= yUnit 
+ 2; 
2776         SetScrollbars (xUnit
, yUnit
, xUnit 
? x
/xUnit 
: 0, yUnit 
? y
/yUnit 
: 0, x_pos
, yUnit 
? (item_y
+GetLineHeight(gitem
)-client_h
)/yUnit 
: 0 ); 
2780 // FIXME: tree sorting functions are not reentrant and not MT-safe! 
2781 static wxTreeListMainWindow 
*s_treeBeingSorted 
= NULL
; 
2783 static int LINKAGEMODE 
tree_ctrl_compare_func(wxTreeListItem 
**item1
, 
2784                                   wxTreeListItem 
**item2
) 
2786     wxCHECK_MSG (s_treeBeingSorted
, 0, _T("bug in wxTreeListMainWindow::SortChildren()") ); 
2788     return s_treeBeingSorted
->OnCompareItems(*item1
, *item2
); 
2791 int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId
& item1
, 
2792                                const wxTreeItemId
& item2
) 
2794     return m_owner
->OnCompareItems (item1
, item2
); 
2797 void wxTreeListMainWindow::SortChildren (const wxTreeItemId
& itemId
) { 
2798     wxCHECK_RET (itemId
.IsOk(), _T("invalid tree item")); 
2800     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2802     wxCHECK_RET (!s_treeBeingSorted
, 
2803                  _T("wxTreeListMainWindow::SortChildren is not reentrant") ); 
2805     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2806     if ( children
.Count() > 1 ) { 
2808         s_treeBeingSorted 
= this; 
2809         children
.Sort(tree_ctrl_compare_func
); 
2810         s_treeBeingSorted 
= NULL
; 
2814 wxTreeItemId 
wxTreeListMainWindow::FindItem (const wxTreeItemId
& item
, const wxString
& str
, int mode
) { 
2816     // determine start item 
2817     wxTreeItemId next 
= item
; 
2819         if (mode 
& wxTL_MODE_NAV_LEVEL
) { 
2820             next 
= GetNextSibling (next
); 
2821         }else if (mode 
& wxTL_MODE_NAV_VISIBLE
) { // 
2822             next 
= GetNextVisible (next
, false); 
2823         }else if (mode 
& wxTL_MODE_NAV_EXPANDED
) { 
2824             next 
= GetNextExpanded (next
); 
2825         }else{ // (mode & wxTL_MODE_NAV_FULLTREE) default 
2826             next 
= GetNext (next
, true); 
2830 #if !wxCHECK_VERSION(2, 5, 0) 
2833     wxTreeItemIdValue cookie 
= 0; 
2836         next 
= (wxTreeListItem
*)GetRootItem().m_pItem
; 
2837         if (HasFlag(wxTR_HIDE_ROOT
)) { 
2838             next 
= (wxTreeListItem
*)GetFirstChild (GetRootItem().m_pItem
, cookie
).m_pItem
; 
2841     if (!next
.IsOk()) return (wxTreeItemId
*)NULL
; 
2843     // start checking the next items 
2844     while (next
.IsOk() && (next 
!= item
)) { 
2845         if (mode 
& wxTL_MODE_FIND_PARTIAL
) { 
2846             itemText 
= GetItemText (next
).Mid (0, str
.Length()); 
2848             itemText 
= GetItemText (next
); 
2850         if (mode 
& wxTL_MODE_FIND_NOCASE
) { 
2851             if (itemText
.CmpNoCase (str
) == 0) return next
; 
2853             if (itemText
.Cmp (str
) == 0) return next
; 
2855         if (mode 
& wxTL_MODE_NAV_LEVEL
) { 
2856             next 
= GetNextSibling (next
); 
2857         }else if (mode 
& wxTL_MODE_NAV_VISIBLE
) { // 
2858             next 
= GetNextVisible (next
, false); 
2859         }else if (mode 
& wxTL_MODE_NAV_EXPANDED
) { 
2860             next 
= GetNextExpanded (next
); 
2861         }else{ // (mode & wxTL_MODE_NAV_FULLTREE) default 
2862             next 
= GetNext (next
, true); 
2864         if (!next
.IsOk() && item
.IsOk()) { 
2865             next 
= (wxTreeListItem
*)GetRootItem().m_pItem
; 
2866             if (HasFlag(wxTR_HIDE_ROOT
)) { 
2867                 next 
= (wxTreeListItem
*)GetNextChild (GetRootItem().m_pItem
, cookie
).m_pItem
; 
2871     return (wxTreeItemId
*)NULL
; 
2874 void wxTreeListMainWindow::SetDragItem (const wxTreeItemId
& item
) { 
2875     wxTreeListItem 
*prevItem 
= m_dragItem
; 
2876     m_dragItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2877     if (prevItem
) RefreshLine (prevItem
); 
2878     if (m_dragItem
) RefreshLine (m_dragItem
); 
2881 void wxTreeListMainWindow::CalculateLineHeight() { 
2882     wxClientDC 
dc (this); 
2883     dc
.SetFont (m_normalFont
); 
2884     m_lineHeight 
= (int)(dc
.GetCharHeight() + m_linespacing
); 
2886     if (m_imageListNormal
) { 
2887         // Calculate a m_lineHeight value from the normal Image sizes. 
2888         // May be toggle off. Then wxTreeListMainWindow will spread when 
2889         // necessary (which might look ugly). 
2890         int n 
= m_imageListNormal
->GetImageCount(); 
2891         for (int i 
= 0; i 
< n 
; i
++) { 
2892             int width 
= 0, height 
= 0; 
2893             m_imageListNormal
->GetSize(i
, width
, height
); 
2894             if (height 
> m_lineHeight
) m_lineHeight 
= height 
+ m_linespacing
; 
2898     if (m_imageListButtons
) { 
2899         // Calculate a m_lineHeight value from the Button image sizes. 
2900         // May be toggle off. Then wxTreeListMainWindow will spread when 
2901         // necessary (which might look ugly). 
2902         int n 
= m_imageListButtons
->GetImageCount(); 
2903         for (int i 
= 0; i 
< n 
; i
++) { 
2904             int width 
= 0, height 
= 0; 
2905             m_imageListButtons
->GetSize(i
, width
, height
); 
2906             if (height 
> m_lineHeight
) m_lineHeight 
= height 
+ m_linespacing
; 
2910     if (m_lineHeight 
< 30) { // add 10% space if greater than 30 pixels 
2911         m_lineHeight 
+= 2; // minimal 2 pixel space 
2913         m_lineHeight 
+= m_lineHeight 
/ 10; // otherwise 10% space 
2917 void wxTreeListMainWindow::SetImageList (wxImageList 
*imageList
) { 
2918     if (m_ownsImageListNormal
) delete m_imageListNormal
; 
2919     m_imageListNormal 
= imageList
; 
2920     m_ownsImageListNormal 
= false; 
2922     CalculateLineHeight(); 
2925 void wxTreeListMainWindow::SetStateImageList (wxImageList 
*imageList
) { 
2926     if (m_ownsImageListState
) delete m_imageListState
; 
2927     m_imageListState 
= imageList
; 
2928     m_ownsImageListState 
= false; 
2931 void wxTreeListMainWindow::SetButtonsImageList (wxImageList 
*imageList
) { 
2932     if (m_ownsImageListButtons
) delete m_imageListButtons
; 
2933     m_imageListButtons 
= imageList
; 
2934     m_ownsImageListButtons 
= false; 
2936     CalculateLineHeight(); 
2939 void wxTreeListMainWindow::AssignImageList (wxImageList 
*imageList
) { 
2940     SetImageList(imageList
); 
2941     m_ownsImageListNormal 
= true; 
2944 void wxTreeListMainWindow::AssignStateImageList (wxImageList 
*imageList
) { 
2945     SetStateImageList(imageList
); 
2946     m_ownsImageListState 
= true; 
2949 void wxTreeListMainWindow::AssignButtonsImageList (wxImageList 
*imageList
) { 
2950     SetButtonsImageList(imageList
); 
2951     m_ownsImageListButtons 
= true; 
2954 // ---------------------------------------------------------------------------- 
2956 // ---------------------------------------------------------------------------- 
2958 void wxTreeListMainWindow::AdjustMyScrollbars() { 
2961         GetScrollPixelsPerUnit (&xUnit
, &yUnit
); 
2962         if (xUnit 
== 0) xUnit 
= GetCharWidth(); 
2963         if (yUnit 
== 0) yUnit 
= m_lineHeight
; 
2965         m_rootItem
->GetSize (x
, y
, this); 
2966         y 
+= yUnit 
+ 2; // one more scrollbar unit + 2 pixels 
2967         int x_pos 
= GetScrollPos (wxHORIZONTAL
); 
2968         int y_pos 
= GetScrollPos (wxVERTICAL
); 
2969         x 
= m_owner
->GetHeaderWindow()->GetWidth() + 2; 
2970         if (x 
< GetClientSize().GetWidth()) x_pos 
= 0; 
2971         SetScrollbars (xUnit
, yUnit
, x
/xUnit
, y
/yUnit
, x_pos
, y_pos
); 
2973         SetScrollbars (0, 0, 0, 0); 
2977 int wxTreeListMainWindow::GetLineHeight (wxTreeListItem 
*item
) const { 
2978     if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT
) { 
2979         return item
->GetHeight(); 
2981         return m_lineHeight
; 
2985 void wxTreeListMainWindow::PaintItem (wxTreeListItem 
*item
, wxDC
& dc
) { 
2987     wxTreeItemAttr 
*attr 
= item
->GetAttributes(); 
2989     dc
.SetFont (GetItemFont (item
)); 
2992     if (attr 
&& attr
->HasTextColour()) { 
2993         colText 
= attr
->GetTextColour(); 
2995         colText 
= GetForegroundColour(); 
2997 #if !wxCHECK_VERSION(2, 5, 0) 
2998     wxColour colTextHilight 
= wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3000     wxColour colTextHilight 
= wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3003     int total_w 
= m_owner
->GetHeaderWindow()->GetWidth(); 
3004     int total_h 
= GetLineHeight(item
); 
3005     int off_h 
= HasFlag(wxTR_ROW_LINES
) ? 1 : 0; 
3006     int off_w 
= HasFlag(wxTR_COLUMN_LINES
) ? 1 : 0; 
3007     wxDCClipper 
clipper (dc
, 0, item
->GetY(), total_w
, total_h
); // only within line 
3009     int text_w 
= 0, text_h 
= 0; 
3010     dc
.GetTextExtent( item
->GetText(GetMainColumn()), &text_w
, &text_h 
); 
3012     // determine background and show it 
3014     if (attr 
&& attr
->HasBackgroundColour()) { 
3015         colBg 
= attr
->GetBackgroundColour(); 
3017         colBg 
= m_backgroundColour
; 
3019     dc
.SetBrush (wxBrush (colBg
, wxSOLID
)); 
3020     dc
.SetPen (*wxTRANSPARENT_PEN
); 
3021     if (HasFlag (wxTR_FULL_ROW_HIGHLIGHT
)) { 
3022         if (item 
== m_dragItem
) { 
3023             dc
.SetBrush (*m_hilightBrush
); 
3024 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color 
3025             dc
.SetPen ((item 
== m_dragItem
)? *wxBLACK_PEN
: *wxTRANSPARENT_PEN
); 
3026 #endif // !__WXMAC__ 
3027             dc
.SetTextForeground (colTextHilight
); 
3028         }else if (item
->IsSelected()) { 
3029             if (!m_isDragging 
&& m_hasFocus
) { 
3030                 dc
.SetBrush (*m_hilightBrush
); 
3031 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color 
3032                 dc
.SetPen (*wxBLACK_PEN
); 
3033 #endif // !__WXMAC__ 
3035                 dc
.SetBrush (*m_hilightUnfocusedBrush
); 
3036 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color 
3037                 dc
.SetPen (*wxTRANSPARENT_PEN
); 
3038 #endif // !__WXMAC__ 
3040             dc
.SetTextForeground (colTextHilight
); 
3041         }else if (item 
== m_curItem
) { 
3042             dc
.SetPen (m_hasFocus
? *wxBLACK_PEN
: *wxTRANSPARENT_PEN
); 
3044             dc
.SetTextForeground (colText
); 
3046         dc
.DrawRectangle (0, item
->GetY() + off_h
, total_w
, total_h 
- off_h
); 
3048         dc
.SetTextForeground (colText
); 
3051     int text_extraH 
= (total_h 
> text_h
) ? (total_h 
- text_h
)/2 : 0; 
3052     int img_extraH 
= (total_h 
> m_imgHeight
)? (total_h
-m_imgHeight
)/2: 0; 
3054     for (int i 
= 0; i 
< GetColumnCount(); ++i 
) { 
3055         if (!m_owner
->GetHeaderWindow()->IsColumnShown(i
)) continue; 
3057         int col_w 
= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
3058         wxDCClipper 
clipper (dc
, x_colstart
, item
->GetY(), col_w
, total_h
); // only within column 
3061         int image 
= NO_IMAGE
; 
3063         if(i 
== GetMainColumn()) { 
3064             x 
= item
->GetX() + MARGIN
; 
3066                 x 
+= (m_btnWidth
-m_btnWidth2
) + LINEATROOT
; 
3070             if (m_imageListNormal
) image 
= item
->GetCurrentImage(); 
3072             x 
= x_colstart 
+ MARGIN
; 
3073             image 
= item
->GetImage(i
); 
3075         if (image 
!= NO_IMAGE
) image_w 
= m_imgWidth 
+ MARGIN
; 
3077         // honor text alignment 
3078         wxString text 
= item
->GetText(i
); 
3080         switch ( m_owner
->GetHeaderWindow()->GetColumn(i
).GetAlignment() ) { 
3082             // nothing to do, already left aligned 
3085             dc
.GetTextExtent (text
, &text_w
, NULL
); 
3086             w 
= col_w 
- (image_w 
+ text_w 
+ off_w 
+ MARGIN
); 
3089         case wxALIGN_CENTER
: 
3090             dc
.GetTextExtent(text
, &text_w
, NULL
); 
3091             w 
= (col_w 
- (image_w 
+ text_w 
+ off_w 
+ MARGIN
))/2; 
3095         int text_x 
= x 
+ image_w
; 
3096         if (i 
== GetMainColumn()) item
->SetTextX (text_x
); 
3098         if (!HasFlag (wxTR_FULL_ROW_HIGHLIGHT
)) { 
3099             if (i 
== GetMainColumn()) { 
3100                 if (item 
== m_dragItem
) { 
3101                     dc
.SetBrush (*m_hilightBrush
); 
3102 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color 
3103                     dc
.SetPen ((item 
== m_dragItem
)? *wxBLACK_PEN
: *wxTRANSPARENT_PEN
); 
3104 #endif // !__WXMAC__ 
3105                     dc
.SetTextForeground (colTextHilight
); 
3106                 }else if (item
->IsSelected()) { 
3107                     if (!m_isDragging 
&& m_hasFocus
) { 
3108                         dc
.SetBrush (*m_hilightBrush
); 
3109 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color 
3110                         dc
.SetPen (*wxBLACK_PEN
); 
3111 #endif // !__WXMAC__ 
3113                         dc
.SetBrush (*m_hilightUnfocusedBrush
); 
3114 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color 
3115                       dc
.SetPen (*wxTRANSPARENT_PEN
); 
3116 #endif // !__WXMAC__ 
3118                     dc
.SetTextForeground (colTextHilight
); 
3119                 }else if (item 
== m_curItem
) { 
3120                     dc
.SetPen (m_hasFocus
? *wxBLACK_PEN
: *wxTRANSPARENT_PEN
); 
3122                     dc
.SetTextForeground (colText
); 
3124                 dc
.DrawRectangle (text_x
, item
->GetY() + off_h
, text_w
, total_h 
- off_h
); 
3126                 dc
.SetTextForeground (colText
); 
3130         if (HasFlag(wxTR_COLUMN_LINES
)) { // vertical lines between columns 
3131 #if !wxCHECK_VERSION(2, 5, 0) 
3132             wxPen 
pen (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_3DLIGHT 
), 1, wxSOLID
); 
3134             wxPen 
pen (wxSystemSettings::GetColour (wxSYS_COLOUR_3DLIGHT 
), 1, wxSOLID
); 
3136             dc
.SetPen ((GetBackgroundColour() == *wxWHITE
)? pen
: *wxWHITE_PEN
); 
3137             dc
.DrawLine (x_colstart
+col_w
-1, item
->GetY(), x_colstart
+col_w
-1, item
->GetY()+total_h
); 
3140         dc
.SetBackgroundMode (wxTRANSPARENT
); 
3142         if (image 
!= NO_IMAGE
) { 
3143             int y 
= item
->GetY() + img_extraH
; 
3144             m_imageListNormal
->Draw (image
, dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3146         int text_y 
= item
->GetY() + text_extraH
; 
3147         dc
.DrawText (text
, (wxCoord
)text_x
, (wxCoord
)text_y
); 
3149         x_colstart 
+= col_w
; 
3152     // restore normal font 
3153     dc
.SetFont( m_normalFont 
); 
3156 // Now y stands for the top of the item, whereas it used to stand for middle ! 
3157 void wxTreeListMainWindow::PaintLevel (wxTreeListItem 
*item
, wxDC 
&dc
, 
3158                                        int level
, int &y
, int x_maincol
) { 
3160     // Handle hide root (only level 0) 
3161     if (HasFlag(wxTR_HIDE_ROOT
) && (level 
== 0)) { 
3162         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
3163         for (size_t n 
= 0; n 
< children
.Count(); n
++) { 
3164             PaintLevel (children
[n
], dc
, 1, y
, x_maincol
); 
3166         // end after expanding root 
3170     // calculate position of vertical lines 
3171     int x 
= x_maincol 
+ MARGIN
; // start of column 
3172     if (HasFlag(wxTR_LINES_AT_ROOT
)) x 
+= LINEATROOT
; // space for lines at root 
3174         x 
+= (m_btnWidth
-m_btnWidth2
); // half button space 
3176         x 
+= (m_indent
-m_indent
/2); 
3178     if (HasFlag(wxTR_HIDE_ROOT
)) { 
3179         x 
+= m_indent 
* (level
-1); // indent but not level 1 
3181         x 
+= m_indent 
* level
; // indent according to level 
3184     // set position of vertical line 
3188     int h 
= GetLineHeight (item
); 
3190     int y_mid 
= y_top 
+ (h
/2); 
3193     int exposed_x 
= dc
.LogicalToDeviceX(0); 
3194     int exposed_y 
= dc
.LogicalToDeviceY(y_top
); 
3196     if (IsExposed(exposed_x
, exposed_y
, 10000, h
)) { // 10000 = very much 
3198         if (HasFlag(wxTR_ROW_LINES
)) { // horizontal lines between rows 
3199             //dc.DestroyClippingRegion(); 
3200             int total_width 
= m_owner
->GetHeaderWindow()->GetWidth(); 
3201             // if the background colour is white, choose a 
3202             // contrasting color for the lines 
3203 #if !wxCHECK_VERSION(2, 5, 0) 
3204             wxPen 
pen (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_3DLIGHT 
), 1, wxSOLID
); 
3206             wxPen 
pen (wxSystemSettings::GetColour (wxSYS_COLOUR_3DLIGHT 
), 1, wxSOLID
); 
3208             dc
.SetPen ((GetBackgroundColour() == *wxWHITE
)? pen
: *wxWHITE_PEN
); 
3209             dc
.DrawLine (0, y_top
, total_width
, y_top
); 
3210             dc
.DrawLine (0, y_top
+h
, total_width
, y_top
+h
); 
3214         PaintItem (item
, dc
); 
3216         // restore DC objects 
3217         dc
.SetBrush(*wxWHITE_BRUSH
); 
3218         dc
.SetPen(m_dottedPen
); 
3220         // clip to the column width 
3221         int clip_width 
= m_owner
->GetHeaderWindow()-> 
3222                             GetColumn(m_main_column
).GetWidth(); 
3223         wxDCClipper 
clipper(dc
, x_maincol
, y_top
, clip_width
, 10000); 
3225         if (!HasFlag(wxTR_NO_LINES
)) { // connection lines 
3227             // draw the horizontal line here 
3228             dc
.SetPen(m_dottedPen
); 
3229             int x2 
= x 
- m_indent
; 
3230             if (x2 
< (x_maincol 
+ MARGIN
)) x2 
= x_maincol 
+ MARGIN
; 
3231             int x3 
= x 
+ (m_btnWidth
-m_btnWidth2
); 
3233                 if (item
->HasPlus()) { 
3234                     dc
.DrawLine (x2
, y_mid
, x 
- m_btnWidth2
, y_mid
); 
3235                     dc
.DrawLine (x3
, y_mid
, x3 
+ LINEATROOT
, y_mid
); 
3237                     dc
.DrawLine (x2
, y_mid
, x3 
+ LINEATROOT
, y_mid
); 
3240                 dc
.DrawLine (x2
, y_mid
, x 
- m_indent
/2, y_mid
); 
3244         if (item
->HasPlus() && HasButtons()) { // should the item show a button? 
3246             if (m_imageListButtons
) { 
3248                 // draw the image button here 
3249                 int image 
= wxTreeItemIcon_Normal
; 
3250                 if (item
->IsExpanded()) image 
= wxTreeItemIcon_Expanded
; 
3251                 if (item
->IsSelected()) image 
+= wxTreeItemIcon_Selected 
- wxTreeItemIcon_Normal
; 
3252                 int xx 
= x 
- m_btnWidth2 
+ MARGIN
; 
3253                 int yy 
= y_mid 
- m_btnHeight2
; 
3254                 dc
.SetClippingRegion(xx
, yy
, m_btnWidth
, m_btnHeight
); 
3255                 m_imageListButtons
->Draw (image
, dc
, xx
, yy
, wxIMAGELIST_DRAW_TRANSPARENT
); 
3256                 dc
.DestroyClippingRegion(); 
3258             }else if (HasFlag (wxTR_TWIST_BUTTONS
)) { 
3260                 // draw the twisty button here 
3261                 dc
.SetPen(*wxBLACK_PEN
); 
3262                 dc
.SetBrush(*m_hilightBrush
); 
3264                 if (item
->IsExpanded()) { 
3265                     button
[0].x 
= x 
- (m_btnWidth2
+1); 
3266                     button
[0].y 
= y_mid 
- (m_btnHeight
/3); 
3267                     button
[1].x 
= x 
+ (m_btnWidth2
+1); 
3268                     button
[1].y 
= button
[0].y
; 
3270                     button
[2].y 
= button
[0].y 
+ (m_btnHeight2
+1); 
3272                     button
[0].x 
= x 
- (m_btnWidth
/3); 
3273                     button
[0].y 
= y_mid 
- (m_btnHeight2
+1); 
3274                     button
[1].x 
= button
[0].x
; 
3275                     button
[1].y 
= y_mid 
+ (m_btnHeight2
+1); 
3276                     button
[2].x 
= button
[0].x 
+ (m_btnWidth2
+1); 
3277                     button
[2].y 
= y_mid
; 
3279                 dc
.DrawPolygon(3, button
); 
3281             }else{ // if (HasFlag(wxTR_HAS_BUTTONS)) 
3283                 // draw the plus sign here 
3284 #if !wxCHECK_VERSION(2, 7, 0) 
3285                 dc
.SetPen(*wxGREY_PEN
); 
3286                 dc
.SetBrush(*wxWHITE_BRUSH
); 
3287                 dc
.DrawRectangle (x
-m_btnWidth2
, y_mid
-m_btnHeight2
, m_btnWidth
, m_btnHeight
); 
3288                 dc
.SetPen(*wxBLACK_PEN
); 
3289                 dc
.DrawLine (x
-(m_btnWidth2
-2), y_mid
, x
+(m_btnWidth2
-1), y_mid
); 
3290                 if (!item
->IsExpanded()) { // change "-" to "+" 
3291                     dc
.DrawLine (x
, y_mid
-(m_btnHeight2
-2), x
, y_mid
+(m_btnHeight2
-1)); 
3294                 wxRect 
rect (x
-m_btnWidth2
, y_mid
-m_btnHeight2
, m_btnWidth
, m_btnHeight
); 
3295                 int flag 
= item
->IsExpanded()? wxCONTROL_EXPANDED
: 0; 
3296                 wxRendererNative::GetDefault().DrawTreeItemButton (this, dc
, rect
, flag
); 
3305     // restore DC objects 
3306     dc
.SetBrush(*wxWHITE_BRUSH
); 
3307     dc
.SetPen(m_dottedPen
); 
3308     dc
.SetTextForeground(*wxBLACK
); 
3310     if (item
->IsExpanded()) 
3312         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
3314         // clip to the column width 
3315         int clip_width 
= m_owner
->GetHeaderWindow()-> 
3316                             GetColumn(m_main_column
).GetWidth(); 
3318         // process lower levels 
3320         if (m_imgWidth 
> 0) { 
3321             oldY 
= y_mid 
+ m_imgHeight2
; 
3326         for (size_t n 
= 0; n 
< children
.Count(); ++n
) { 
3329             PaintLevel (children
[n
], dc
, level
+1, y
, x_maincol
); 
3331             // draw vertical line 
3332             wxDCClipper 
clipper(dc
, x_maincol
, y_top
, clip_width
, 10000); 
3333             if (!HasFlag (wxTR_NO_LINES
)) { 
3335                 dc
.DrawLine (x
, oldY
, x
, y2
); 
3343 // ---------------------------------------------------------------------------- 
3344 // wxWindows callbacks 
3345 // ---------------------------------------------------------------------------- 
3347 void wxTreeListMainWindow::OnPaint (wxPaintEvent 
&WXUNUSED(event
)) { 
3349     wxPaintDC 
dc (this); 
3352     if (!m_rootItem 
|| (GetColumnCount() <= 0)) return; 
3354     // calculate button size 
3355     if (m_imageListButtons
) { 
3356         m_imageListButtons
->GetSize (0, m_btnWidth
, m_btnHeight
); 
3357     }else if (HasButtons()) { 
3358         m_btnWidth 
= BTNWIDTH
; 
3359         m_btnHeight 
= BTNHEIGHT
; 
3361     m_btnWidth2 
= m_btnWidth
/2; 
3362     m_btnHeight2 
= m_btnHeight
/2; 
3364     // calculate image size 
3365     if (m_imageListNormal
) { 
3366         m_imageListNormal
->GetSize (0, m_imgWidth
, m_imgHeight
); 
3368     m_imgWidth2 
= m_imgWidth
/2; 
3369     m_imgHeight2 
= m_imgHeight
/2; 
3371     // calculate indent size 
3372     if (m_imageListButtons
) { 
3373         m_indent 
= wxMax (MININDENT
, m_btnWidth 
+ MARGIN
); 
3374     }else if (HasButtons()) { 
3375         m_indent 
= wxMax (MININDENT
, m_btnWidth 
+ LINEATROOT
); 
3378     // set default values 
3379     dc
.SetFont( m_normalFont 
); 
3380     dc
.SetPen( m_dottedPen 
); 
3382     // calculate column start and paint 
3385     for (i 
= 0; i 
< (int)GetMainColumn(); ++i
) { 
3386         if (!m_owner
->GetHeaderWindow()->IsColumnShown(i
)) continue; 
3387         x_maincol 
+= m_owner
->GetHeaderWindow()->GetColumnWidth (i
); 
3390     PaintLevel (m_rootItem
, dc
, 0, y
, x_maincol
); 
3393 void wxTreeListMainWindow::OnSetFocus (wxFocusEvent 
&event
) { 
3397     if (m_curItem
) RefreshLine (m_curItem
); 
3401 void wxTreeListMainWindow::OnKillFocus( wxFocusEvent 
&event 
) 
3405     if (m_curItem
) RefreshLine (m_curItem
); 
3409 void wxTreeListMainWindow::OnChar (wxKeyEvent 
&event
) { 
3410     // send event to user code 
3411     wxTreeEvent 
nevent (wxEVT_COMMAND_TREE_KEY_DOWN
, m_owner
->GetId()); 
3412     nevent
.SetKeyEvent (event
); 
3413     nevent
.SetEventObject (m_owner
); 
3414     if (m_owner
->GetEventHandler()->ProcessEvent (nevent
)) return; // handled in user code 
3416     // determine first current if none 
3417     bool curItemSet 
= false; 
3419         m_curItem 
= (wxTreeListItem
*)GetRootItem().m_pItem
; 
3420         if (HasFlag(wxTR_HIDE_ROOT
)) { 
3421 #if !wxCHECK_VERSION(2, 5, 0) 
3424             wxTreeItemIdValue cookie 
= 0; 
3426             m_curItem 
= (wxTreeListItem
*)GetFirstChild (m_curItem
, cookie
).m_pItem
; 
3430     if (!m_curItem
) return; // do nothing if empty tree 
3432     // remember item at shift down 
3433     if (HasFlag(wxTR_MULTIPLE
) && event
.ShiftDown()) { 
3434         if (!m_shiftItem
) m_shiftItem 
= m_curItem
; 
3436         m_shiftItem 
= (wxTreeListItem
*)NULL
; 
3439     // process all cases 
3440     wxTreeItemId newItem 
= (wxTreeItemId
*)NULL
; 
3441     switch (event
.GetKeyCode()) { 
3443         // '+': Expand subtree 
3446             if (m_curItem
->HasPlus() && !IsExpanded (m_curItem
)) Expand (m_curItem
); 
3449         // '-': collapse subtree 
3451         case WXK_SUBTRACT
: { 
3452             if (m_curItem
->HasPlus() && IsExpanded (m_curItem
)) Collapse (m_curItem
); 
3455         // '*': expand/collapse all subtrees // TODO: Mak it more useful 
3457         case WXK_MULTIPLY
: { 
3458             if (m_curItem
->HasPlus() && !IsExpanded (m_curItem
)) { 
3459                 ExpandAll (m_curItem
); 
3460             }else if (m_curItem
->HasPlus()) { 
3461                 Collapse (m_curItem
); // TODO: CollapseAll 
3465         // ' ': toggle current item 
3467             SelectItem (m_curItem
, (wxTreeListItem
*)NULL
, false); 
3470         // <RETURN>: activate current item 
3472             wxTreeEvent 
aevent (wxEVT_COMMAND_TREE_ITEM_ACTIVATED
, m_owner
->GetId()); 
3473 #if !wxCHECK_VERSION(2, 5, 0) 
3474             aevent
.SetItem ((long)m_curItem
); 
3476             aevent
.SetItem (m_curItem
); 
3478             aevent
.SetEventObject (m_owner
); 
3479             m_owner
->GetEventHandler()->ProcessEvent (aevent
); 
3482         // <BKSP>: go to the parent without collapsing 
3484             newItem 
= GetItemParent (m_curItem
); 
3485             if ((newItem 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) { 
3486                 newItem 
= GetPrevSibling (m_curItem
); // get sibling instead of root 
3490         // <UP>: go to the previous sibling or to the last of its children, to the parent 
3492             newItem 
= GetPrevSibling (m_curItem
); 
3494 #if !wxCHECK_VERSION(2, 5, 0) 
3497                 wxTreeItemIdValue cookie 
= 0; 
3499                 while (IsExpanded (newItem
) && HasChildren (newItem
)) { 
3500                     newItem 
= GetLastChild (newItem
, cookie
); 
3503                 newItem 
= GetItemParent (m_curItem
); 
3504                 if ((newItem 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) { 
3505                     newItem 
= (wxTreeItemId
*)NULL
; // don't go to root if it is hidden 
3510         // <LEFT>: if expanded collapse subtree, else go to the parent 
3512             if (IsExpanded (m_curItem
)) { 
3513                 Collapse (m_curItem
); 
3515                 newItem 
= GetItemParent (m_curItem
); 
3516                 if ((newItem 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) { 
3517                     newItem 
= GetPrevSibling (m_curItem
); // go to sibling if it is hidden 
3522         // <RIGHT>: if possible expand subtree, else go go to the first child 
3524             if (m_curItem
->HasPlus() && !IsExpanded (m_curItem
)) { 
3527                 if (IsExpanded (m_curItem
) && HasChildren (m_curItem
)) { 
3528 #if !wxCHECK_VERSION(2, 5, 0) 
3531                     wxTreeItemIdValue cookie 
= 0; 
3533                     newItem 
= GetFirstChild (m_curItem
, cookie
); 
3538         // <DOWN>: if expanded go to the first child, else to the next sibling, ect 
3541                 newItem 
= m_curItem
; 
3543                 if (IsExpanded (m_curItem
) && HasChildren (m_curItem
)) { 
3544 #if !wxCHECK_VERSION(2, 5, 0) 
3547                     wxTreeItemIdValue cookie 
= 0; 
3549                     newItem 
= GetFirstChild( m_curItem
, cookie 
); 
3552                     wxTreeItemId parent 
= m_curItem
; 
3554                         newItem 
= GetNextSibling (parent
); 
3555                         parent 
= GetItemParent (parent
); 
3556                     } while (!newItem 
&& parent
); 
3561         // <END>: go to last item of the root 
3563 #if !wxCHECK_VERSION(2, 5, 0) 
3566             wxTreeItemIdValue cookie 
= 0; 
3568             newItem 
= GetLastChild (GetRootItem(), cookie
); 
3571         // <HOME>: go to root 
3573             newItem 
= GetRootItem(); 
3574             if (HasFlag(wxTR_HIDE_ROOT
)) { 
3575 #if !wxCHECK_VERSION(2, 5, 0) 
3578                 wxTreeItemIdValue cookie 
= 0; 
3580                 newItem 
= GetFirstChild (newItem
, cookie
); 
3584         // any char: go to the next matching string 
3586             if (event
.GetKeyCode() >= (int)' ') { 
3587                 if (!m_findTimer
->IsRunning()) m_findStr
.Clear(); 
3588                 m_findStr
.Append (event
.GetKeyCode()); 
3589                 m_findTimer
->Start (FIND_TIMER_TICKS
, wxTIMER_ONE_SHOT
); 
3590                 wxTreeItemId prev 
= m_curItem
? (wxTreeItemId
*)m_curItem
: (wxTreeItemId
*)NULL
; 
3592                     newItem 
= FindItem (prev
, m_findStr
, wxTL_MODE_NAV_EXPANDED 
| 
3593                                                          wxTL_MODE_FIND_PARTIAL 
| 
3594                                                          wxTL_MODE_FIND_NOCASE
); 
3595                     if (newItem 
|| (m_findStr
.Length() <= 1)) break; 
3596                     m_findStr
.RemoveLast(); 
3603     // select and show the new item 
3605         if (!event
.ControlDown()) { 
3606             bool unselect_others 
= !((event
.ShiftDown() || event
.ControlDown()) && 
3607                                       HasFlag(wxTR_MULTIPLE
)); 
3608             SelectItem (newItem
, m_shiftItem
, unselect_others
); 
3610         EnsureVisible (newItem
); 
3611         wxTreeListItem 
*oldItem 
= m_curItem
; 
3612         m_curItem 
= (wxTreeListItem
*)newItem
.m_pItem
; // make the new item the current item 
3613         RefreshLine (oldItem
); 
3618 wxTreeItemId 
wxTreeListMainWindow::HitTest (const wxPoint
& point
, int& flags
, int& column
) { 
3624     if (point
.x
<0) flags 
|= wxTREE_HITTEST_TOLEFT
; 
3625     if (point
.x
>w
) flags 
|= wxTREE_HITTEST_TORIGHT
; 
3626     if (point
.y
<0) flags 
|= wxTREE_HITTEST_ABOVE
; 
3627     if (point
.y
>h
) flags 
|= wxTREE_HITTEST_BELOW
; 
3628     if (flags
) return wxTreeItemId(); 
3631         flags 
= wxTREE_HITTEST_NOWHERE
; 
3633         return wxTreeItemId(); 
3636     wxTreeListItem 
*hit 
= m_rootItem
->HitTest (CalcUnscrolledPosition(point
), 
3637                                                this, flags
, column
, 0); 
3639         flags 
= wxTREE_HITTEST_NOWHERE
; 
3641         return wxTreeItemId(); 
3646 // get the bounding rectangle of the item (or of its label only) 
3647 bool wxTreeListMainWindow::GetBoundingRect (const wxTreeItemId
& itemId
, wxRect
& rect
, 
3648                                             bool WXUNUSED(textOnly
)) const { 
3649     wxCHECK_MSG (itemId
.IsOk(), false, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") ); 
3651     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
3654     GetScrollPixelsPerUnit (&xUnit
, &yUnit
); 
3656     GetViewStart(& startX
, & startY
); 
3658     rect
.x 
= item
->GetX() - startX 
* xUnit
; 
3659     rect
.y 
= item
->GetY() - startY 
* yUnit
; 
3660     rect
.width 
= item
->GetWidth(); 
3661     rect
.height 
= GetLineHeight (item
); 
3668 void wxTreeListMainWindow::EditLabel (const wxTreeItemId
& item
, int column
) { 
3669     if (!item
.IsOk()) return; 
3670     if (!((column 
>= 0) && (column 
< GetColumnCount()))) return; 
3672     m_editItem 
= (wxTreeListItem
*) item
.m_pItem
; 
3674     wxTreeEvent 
te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
, m_owner
->GetId() ); 
3675 #if !wxCHECK_VERSION(2, 5, 0) 
3676     te
.SetItem ((long)m_editItem
); 
3678     te
.SetItem (m_editItem
); 
3681     te
.SetEventObject (m_owner 
); 
3682     m_owner
->GetEventHandler()->ProcessEvent (te
); 
3684     if (!te
.IsAllowed()) return; 
3686     // ensure that the position of the item it calculated in any case 
3687     if (m_dirty
) CalculatePositions(); 
3689     wxTreeListHeaderWindow
* header_win 
= m_owner
->GetHeaderWindow(); 
3691     int y 
= m_editItem
->GetY() + 1; // wxTextCtrl needs 1 pixels above the text 
3693     int h 
= m_editItem
->GetHeight(); 
3695     if (column 
== GetMainColumn()) { 
3696         x 
+= m_editItem
->GetTextX() - 2; // wxTextCtrl needs 2 pixels before the text 
3697         w 
= wxMin (m_editItem
->GetWidth(), m_owner
->GetHeaderWindow()->GetWidth() - x
); 
3699         for (int i 
= 0; i 
< column
; ++i
) x 
+= header_win
->GetColumnWidth (i
); // start of column 
3700         switch (header_win
->GetColumnAlignment (column
)) { 
3701             case wxALIGN_LEFT
: {style 
= wxTE_LEFT
; break;} 
3702             case wxALIGN_RIGHT
: {style 
= wxTE_RIGHT
; break;} 
3703             case wxALIGN_CENTER
: {style 
= wxTE_CENTER
; break;} 
3705         w 
= header_win
->GetColumnWidth (column
); // width of column 
3708     wxClientDC 
dc (this); 
3710     x 
= dc
.LogicalToDeviceX (x
); 
3711     y 
= dc
.LogicalToDeviceY (y
); 
3713     wxEditTextCtrl 
*text 
= new wxEditTextCtrl (this, -1, &m_renameAccept
, &m_renameRes
, 
3714                                                this, m_editItem
->GetText (column
), 
3715                                                wxPoint (x
, y
), wxSize (w
, h
), style
); 
3719 void wxTreeListMainWindow::OnRenameTimer() { 
3720     EditLabel (m_curItem
, m_curColumn
); 
3723 void wxTreeListMainWindow::OnRenameAccept() { 
3725     // TODO if the validator fails this causes a crash 
3726     wxTreeEvent 
le( wxEVT_COMMAND_TREE_END_LABEL_EDIT
, m_owner
->GetId() ); 
3727 #if !wxCHECK_VERSION(2, 5, 0) 
3728     le
.SetItem((long)m_editItem
); 
3730     le
.SetItem(m_editItem
); 
3732     le
.SetEventObject( /*this*/m_owner 
); 
3733     le
.SetLabel( m_renameRes 
); 
3734     m_owner
->GetEventHandler()->ProcessEvent( le 
); 
3736     if (!le
.IsAllowed()) return; 
3738     SetItemText (m_editItem
, m_curColumn
, m_renameRes
); 
3741 void wxTreeListMainWindow::OnMouse (wxMouseEvent 
&event
) { 
3742     if (!m_rootItem
) return; 
3744     // we process left mouse up event (enables in-place edit), right down 
3745     // (pass to the user code), left dbl click (activate item) and 
3746     // dragging/moving events for items drag-and-drop 
3747     if (!(event
.LeftDown() || 
3749           event
.RightDown() || 
3751           event
.LeftDClick() || 
3753           (event
.GetWheelRotation() != 0 )/*? TODO || 
3754           event.Moving()?*/)) { 
3755         m_owner
->GetEventHandler()->ProcessEvent (event
); 
3759     // set focus if window clicked 
3760     if (event
.LeftDown() || event
.RightDown()) SetFocus(); 
3763     wxPoint p 
= wxPoint (event
.GetX(), event
.GetY()); 
3765     wxTreeListItem 
*item 
= m_rootItem
->HitTest (CalcUnscrolledPosition (p
), 
3766                                                 this, flags
, m_curColumn
, 0); 
3768     // we only process dragging here 
3769     if (event
.Dragging()){ 
3770         if (m_isDragging
) return; // nothing to do, already done 
3771         if (item 
== NULL
) return; // we need an item to dragging 
3773         // determine drag start 
3774         if (m_dragCount 
== 0) { 
3775             m_dragTimer
->Start (DRAG_TIMER_TICKS
, wxTIMER_ONE_SHOT
); 
3778         if (m_dragCount 
< 3) return; // minimum drag 3 pixel 
3779         if (m_dragTimer
->IsRunning()) return; 
3781         // we're going to drag 
3783         m_isDragging 
= true; 
3787         // send drag start event 
3788         wxEventType command 
= event
.LeftIsDown() 
3789                               ? wxEVT_COMMAND_TREE_BEGIN_DRAG
 
3790                               : wxEVT_COMMAND_TREE_BEGIN_RDRAG
; 
3791         wxTreeEvent 
nevent (command
, m_owner
->GetId()); 
3792         nevent
.SetEventObject (m_owner
); 
3793 #if !wxCHECK_VERSION(2, 5, 0) 
3794         nevent
.SetItem ((long)item
); // the item the drag is ended 
3796         nevent
.SetItem (item
); // the item the drag is ended 
3798         nevent
.Veto(); // dragging must be explicit allowed! 
3799         m_owner
->GetEventHandler()->ProcessEvent (nevent
); 
3801     }else if (m_isDragging
) { // any other event but not event.Dragging() 
3805         m_isDragging 
= false; 
3806         if (HasCapture()) ReleaseMouse(); 
3809         // send drag end event event 
3810         wxTreeEvent 
nevent (wxEVT_COMMAND_TREE_END_DRAG
, m_owner
->GetId()); 
3811         nevent
.SetEventObject (m_owner
); 
3812 #if !wxCHECK_VERSION(2, 5, 0) 
3813         nevent
.SetItem ((long)item
); // the item the drag is started 
3815         nevent
.SetItem (item
); // the item the drag is started 
3817         nevent
.SetPoint (p
); 
3818         m_owner
->GetEventHandler()->ProcessEvent (nevent
); 
3820     }else if (m_dragCount 
> 0) { // just in case dragging is initiated 
3827     // we process only the messages which happen on tree items 
3829         m_owner
->GetEventHandler()->ProcessEvent (event
); 
3833     // remember item at shift down 
3834     if (event
.ShiftDown())  { 
3835         if (!m_shiftItem
) m_shiftItem 
= m_curItem
; 
3837         m_shiftItem 
= (wxTreeListItem
*)NULL
; 
3840     if (event
.RightUp()) { 
3843         wxTreeEvent 
nevent (wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
, m_owner
->GetId()); 
3844         nevent
.SetEventObject (m_owner
); 
3845 #if !wxCHECK_VERSION(2, 5, 0) 
3846         nevent
.SetItem ((long)item
); // the item clicked 
3848         nevent
.SetItem (item
); // the item clicked 
3850         nevent
.SetInt (m_curColumn
); // the colum clicked 
3851         nevent
.SetPoint (p
); 
3852         m_owner
->GetEventHandler()->ProcessEvent (nevent
); 
3854     }else if (event
.LeftUp()) { 
3857             if ((item 
== m_curItem
) && (m_curColumn 
!= -1) && 
3858                 (m_owner
->GetHeaderWindow()->IsColumnEditable (m_curColumn
)) && 
3859                 (flags 
& (wxTREE_HITTEST_ONITEMLABEL 
| wxTREE_HITTEST_ONITEMCOLUMN
))){ 
3860                 m_renameTimer
->Start (RENAME_TIMER_TICKS
, wxTIMER_ONE_SHOT
); 
3862             m_lastOnSame 
= false; 
3865         if (((flags 
& wxTREE_HITTEST_ONITEMBUTTON
) || 
3866              (flags 
& wxTREE_HITTEST_ONITEMICON
)) && 
3867             HasButtons() && item
->HasPlus()) { 
3869             // only toggle the item for a single click, double click on 
3870             // the button doesn't do anything (it toggles the item twice) 
3871             if (event
.LeftDown()) Toggle (item
); 
3873             // don't select the item if the button was clicked 
3877         // determine the selection if not done by left down 
3878         if (!m_left_down_selection
) { 
3879             bool unselect_others 
= !((event
.ShiftDown() || event
.ControlDown()) && 
3880                                      HasFlag(wxTR_MULTIPLE
)); 
3881             SelectItem (item
, m_shiftItem
, unselect_others
); 
3882             EnsureVisible (item
); 
3883             m_curItem 
= item
; // make the new item the current item 
3885             m_left_down_selection 
= false; 
3888     }else if (event
.LeftDown() || event
.RightDown() || event
.LeftDClick()) { 
3890         if (event
.LeftDown() || event
.RightDown()) { 
3892             m_lastOnSame 
= item 
== m_curItem
; 
3895         if (((flags 
& wxTREE_HITTEST_ONITEMBUTTON
) || 
3896              (flags 
& wxTREE_HITTEST_ONITEMICON
)) && 
3899             // only toggle the item for a single click, double click on 
3900             // the button doesn't do anything (it toggles the item twice) 
3901             if (event
.LeftDown()) Toggle (item
); 
3903             // don't select the item if the button was clicked 
3907         // determine the selection if the current item is not selected 
3908         if (!item
->IsSelected()) { 
3909             bool unselect_others 
= !((event
.ShiftDown() || event
.ControlDown()) && 
3910                                      HasFlag(wxTR_MULTIPLE
)); 
3911             SelectItem (item
, m_shiftItem
, unselect_others
); 
3912             EnsureVisible (item
); 
3913             m_curItem 
= item
; // make the new item the current item 
3914             m_left_down_selection 
= true; 
3917         // For some reason, Windows isn't recognizing a left double-click, 
3918         // so we need to simulate it here.  Allow 200 milliseconds for now. 
3919         if (event
.LeftDClick()) { 
3921             // double clicking should not start editing the item label 
3922             m_renameTimer
->Stop(); 
3923             m_lastOnSame 
= false; 
3925             // send activate event first 
3926             wxTreeEvent 
nevent (wxEVT_COMMAND_TREE_ITEM_ACTIVATED
, m_owner
->GetId()); 
3927             nevent
.SetEventObject (m_owner
); 
3928 #if !wxCHECK_VERSION(2, 5, 0) 
3929             nevent
.SetItem ((long)item
); // the item clicked 
3931             nevent
.SetItem (item
); // the item clicked 
3933             nevent
.SetInt (m_curColumn
); // the colum clicked 
3934             nevent
.SetPoint (p
); 
3935             if (!m_owner
->GetEventHandler()->ProcessEvent (nevent
)) { 
3937                 // if the user code didn't process the activate event, 
3938                 // handle it ourselves by toggling the item when it is 
3940                 if (item
->HasPlus()) Toggle(item
); 
3944     }else{ // any other event skip just in case 
3951 void wxTreeListMainWindow::OnIdle (wxIdleEvent 
&WXUNUSED(event
)) { 
3952     /* after all changes have been done to the tree control, 
3953      * we actually redraw the tree when everything is over */ 
3955     if (!m_dirty
) return; 
3959     CalculatePositions(); 
3961     AdjustMyScrollbars(); 
3964 void wxTreeListMainWindow::OnScroll (wxScrollWinEvent
& event
) { 
3966 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) 
3967     wxScrolledWindow::OnScroll(event
); 
3969     HandleOnScroll( event 
); 
3972     if(event
.GetOrientation() == wxHORIZONTAL
) { 
3973         m_owner
->GetHeaderWindow()->Refresh(); 
3974         m_owner
->GetHeaderWindow()->Update(); 
3978 void wxTreeListMainWindow::CalculateSize (wxTreeListItem 
*item
, wxDC 
&dc
) { 
3982     dc
.SetFont (GetItemFont (item
)); 
3984     dc
.GetTextExtent (item
->GetText (m_main_column
), &text_w
, &text_h
); 
3986     // restore normal font 
3987     dc
.SetFont (m_normalFont
); 
3989     int total_h 
= (m_imgHeight 
> text_h
) ? m_imgHeight 
: text_h
; 
3990     if (total_h 
< 30) { // add 10% space if greater than 30 pixels 
3991         total_h 
+= 2; // minimal 2 pixel space 
3993         total_h 
+= total_h 
/ 10; // otherwise 10% space 
3996     item
->SetHeight (total_h
); 
3997     if (total_h 
> m_lineHeight
) m_lineHeight 
= total_h
; 
3998     item
->SetWidth(m_imgWidth 
+ text_w
+2); 
4001 // ----------------------------------------------------------------------------- 
4002 void wxTreeListMainWindow::CalculateLevel (wxTreeListItem 
*item
, wxDC 
&dc
, 
4003                                            int level
, int &y
, int x_colstart
) { 
4005     // calculate position of vertical lines 
4006     int x 
= x_colstart 
+ MARGIN
; // start of column 
4007     if (HasFlag(wxTR_LINES_AT_ROOT
)) x 
+= LINEATROOT
; // space for lines at root 
4009         x 
+= (m_btnWidth
-m_btnWidth2
); // half button space 
4011         x 
+= (m_indent
-m_indent
/2); 
4013     if (HasFlag(wxTR_HIDE_ROOT
)) { 
4014         x 
+= m_indent 
* (level
-1); // indent but not level 1 
4016         x 
+= m_indent 
* level
; // indent according to level 
4019     // a hidden root is not evaluated, but its children are always 
4020     if (HasFlag(wxTR_HIDE_ROOT
) && (level 
== 0)) goto Recurse
; 
4022     CalculateSize( item
, dc 
); 
4027     y 
+= GetLineHeight(item
); 
4029     // we don't need to calculate collapsed branches 
4030     if ( !item
->IsExpanded() ) return; 
4033     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
4034     long n
, count 
= (long)children
.Count(); 
4036     for (n 
= 0; n 
< count
; ++n
) { 
4037         CalculateLevel( children
[n
], dc
, level
, y
, x_colstart 
);  // recurse 
4041 void wxTreeListMainWindow::CalculatePositions() { 
4042     if ( !m_rootItem 
) return; 
4044     wxClientDC 
dc(this); 
4047     dc
.SetFont( m_normalFont 
); 
4049     dc
.SetPen( m_dottedPen 
); 
4050     //if(GetImageList() == NULL) 
4051     // m_lineHeight = (int)(dc.GetCharHeight() + 4); 
4055     for (int i 
= 0; i 
< (int)GetMainColumn(); ++i
) { 
4056         if (!m_owner
->GetHeaderWindow()->IsColumnShown(i
)) continue; 
4057         x_colstart 
+= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
4059     CalculateLevel( m_rootItem
, dc
, 0, y
, x_colstart 
); // start recursion 
4062 void wxTreeListMainWindow::RefreshSubtree (wxTreeListItem 
*item
) { 
4063     if (m_dirty
) return; 
4065     wxClientDC 
dc(this); 
4070     GetVirtualSize( &cw
, &ch 
); 
4073     rect
.x 
= dc
.LogicalToDeviceX( 0 ); 
4075     rect
.y 
= dc
.LogicalToDeviceY( item
->GetY() - 2 ); 
4078     Refresh (true, &rect 
); 
4079     AdjustMyScrollbars(); 
4082 void wxTreeListMainWindow::RefreshLine (wxTreeListItem 
*item
) { 
4083     if (m_dirty
) return; 
4085     wxClientDC 
dc(this); 
4090     GetVirtualSize( &cw
, &ch 
); 
4093     rect
.x 
= dc
.LogicalToDeviceX( 0 ); 
4094     rect
.y 
= dc
.LogicalToDeviceY( item
->GetY() ); 
4096     rect
.height 
= GetLineHeight(item
); //dc.GetCharHeight() + 6; 
4098     Refresh (true, &rect
); 
4101 void wxTreeListMainWindow::RefreshSelected() { 
4102     // TODO: this is awfully inefficient, we should keep the list of all 
4103     //       selected items internally, should be much faster 
4105         RefreshSelectedUnder (m_rootItem
); 
4109 void wxTreeListMainWindow::RefreshSelectedUnder (wxTreeListItem 
*item
) { 
4110     if (item
->IsSelected()) { 
4114     const wxArrayTreeListItems
& children 
= item
->GetChildren(); 
4115     long count 
= children
.GetCount(); 
4116     for (long n 
= 0; n 
< count
; n
++ ) { 
4117         RefreshSelectedUnder (children
[n
]); 
4121 // ---------------------------------------------------------------------------- 
4122 // changing colours: we need to refresh the tree control 
4123 // ---------------------------------------------------------------------------- 
4125 bool wxTreeListMainWindow::SetBackgroundColour (const wxColour
& colour
) { 
4126     if (!wxWindow::SetBackgroundColour(colour
)) return false; 
4132 bool wxTreeListMainWindow::SetForegroundColour (const wxColour
& colour
) { 
4133     if (!wxWindow::SetForegroundColour(colour
)) return false; 
4139 void wxTreeListMainWindow::SetItemText (const wxTreeItemId
& itemId
, int column
, 
4140                                         const wxString
& text
) { 
4141     wxCHECK_RET (itemId
.IsOk(), _T("invalid tree item")); 
4143     wxClientDC 
dc (this); 
4144     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
4145     item
->SetText (column
, text
); 
4146     CalculateSize (item
, dc
); 
4150 wxString 
wxTreeListMainWindow::GetItemText (const wxTreeItemId
& itemId
, 
4152     wxCHECK_MSG (itemId
.IsOk(), _T(""), _T("invalid tree item") ); 
4154     if( IsVirtual() )   return m_owner
->OnGetItemText(((wxTreeListItem
*) itemId
.m_pItem
)->GetData(),column
); 
4155     else                return ((wxTreeListItem
*) itemId
.m_pItem
)->GetText (column
); 
4158 wxString 
wxTreeListMainWindow::GetItemText (wxTreeItemData
* item
, 
4160    wxASSERT_MSG( IsVirtual(), _T("can be used only with virtual control") ); 
4161    return m_owner
->OnGetItemText(item
,column
); 
4164 void wxTreeListMainWindow::SetFocus() { 
4165     wxWindow::SetFocus(); 
4168 wxFont 
wxTreeListMainWindow::GetItemFont (wxTreeListItem 
*item
) { 
4169     wxTreeItemAttr 
*attr 
= item
->GetAttributes(); 
4171     if (attr 
&& attr
->HasFont()) { 
4172         return attr
->GetFont(); 
4173     }else if (item
->IsBold()) { 
4176         return m_normalFont
; 
4180 int wxTreeListMainWindow::GetItemWidth (int column
, wxTreeListItem 
*item
) { 
4181     if (!item
) return 0; 
4183     // determine item width 
4185     wxFont font 
= GetItemFont (item
); 
4186     GetTextExtent (item
->GetText (column
), &w
, &h
, NULL
, NULL
, font
.Ok()? &font
: NULL
); 
4190     int width 
= w 
+ 2*MARGIN
; 
4191     if (column 
== GetMainColumn()) { 
4193         if (HasFlag(wxTR_LINES_AT_ROOT
)) width 
+= LINEATROOT
; 
4194         if (HasButtons()) width 
+= m_btnWidth 
+ LINEATROOT
; 
4195         if (item
->GetCurrentImage() != NO_IMAGE
) width 
+= m_imgWidth
; 
4197         // count indent level 
4199         wxTreeListItem 
*parent 
= item
->GetItemParent(); 
4200         wxTreeListItem 
*root 
= (wxTreeListItem
*)GetRootItem().m_pItem
; 
4201         while (parent 
&& (!HasFlag(wxTR_HIDE_ROOT
) || (parent 
!= root
))) { 
4203             parent 
= parent
->GetItemParent(); 
4205         if (level
) width 
+= level 
* GetIndent(); 
4211 int wxTreeListMainWindow::GetBestColumnWidth (int column
, wxTreeItemId parent
) { 
4213     GetClientSize (&maxWidth
, &h
); 
4216     // get root if on item 
4217     if (!parent
.IsOk()) parent 
= GetRootItem(); 
4220     if (!HasFlag(wxTR_HIDE_ROOT
)) { 
4221         int w 
= GetItemWidth (column
, (wxTreeListItem
*)parent
.m_pItem
); 
4222         if (width 
< w
) width 
= w
; 
4223         if (width 
> maxWidth
) return maxWidth
; 
4226     wxTreeItemIdValue cookie 
= 0; 
4227     wxTreeItemId item 
= GetFirstChild (parent
, cookie
); 
4228     while (item
.IsOk()) { 
4229         int w 
= GetItemWidth (column
, (wxTreeListItem
*)item
.m_pItem
); 
4230         if (width 
< w
) width 
= w
; 
4231         if (width 
> maxWidth
) return maxWidth
; 
4233         // check the children of this item 
4234         if (((wxTreeListItem
*)item
.m_pItem
)->IsExpanded()) { 
4235             int w 
= GetBestColumnWidth (column
, item
); 
4236             if (width 
< w
) width 
= w
; 
4237             if (width 
> maxWidth
) return maxWidth
; 
4241         item 
= GetNextChild (parent
, cookie
); 
4248 //----------------------------------------------------------------------------- 
4250 //----------------------------------------------------------------------------- 
4252 IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl
, wxControl
); 
4254 BEGIN_EVENT_TABLE(wxTreeListCtrl
, wxControl
) 
4255     EVT_SIZE(wxTreeListCtrl::OnSize
) 
4258 bool wxTreeListCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
4261                             long style
, const wxValidator 
&validator
, 
4262                             const wxString
& name
) 
4264     long main_style 
= style 
& ~(wxSIMPLE_BORDER
|wxSUNKEN_BORDER
|wxDOUBLE_BORDER
| 
4265                                 wxRAISED_BORDER
|wxSTATIC_BORDER
); 
4266     long ctrl_style 
= style 
& ~(wxVSCROLL
|wxHSCROLL
); 
4268     if (!wxControl::Create(parent
, id
, pos
, size
, ctrl_style
, validator
, name
)) { 
4271     m_main_win 
= new wxTreeListMainWindow (this, -1, wxPoint(0, 0), size
, 
4272                                            main_style
, validator
); 
4273     m_header_win 
= new wxTreeListHeaderWindow (this, -1, m_main_win
, 
4274                                                wxPoint(0, 0), wxDefaultSize
, 
4276     CalculateAndSetHeaderHeight(); 
4280 void wxTreeListCtrl::CalculateAndSetHeaderHeight() 
4284 #if wxCHECK_VERSION_FULL(2, 7, 0, 1) 
4285         h 
= wxRendererNative::Get().GetHeaderButtonHeight(m_header_win
); 
4287         // we use 'g' to get the descent, too 
4289         m_header_win
->GetTextExtent(_T("Hg"), &w
, &h
, &d
); 
4290         h 
+= d 
+ 2 * HEADER_OFFSET_Y 
+ EXTRA_HEIGHT
; 
4292         // only update if changed 
4293         if (h 
!= m_headerHeight
) { 
4300 void wxTreeListCtrl::DoHeaderLayout() 
4303     GetClientSize(&w
, &h
); 
4305         m_header_win
->SetSize (0, 0, w
, m_headerHeight
); 
4306         m_header_win
->Refresh(); 
4309         m_main_win
->SetSize (0, m_headerHeight 
+ 1, w
, h 
- m_headerHeight 
- 1); 
4313 void wxTreeListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
4318 size_t wxTreeListCtrl::GetCount() const { return m_main_win
->GetCount(); } 
4320 unsigned int wxTreeListCtrl::GetIndent() const 
4321 { return m_main_win
->GetIndent(); } 
4323 void wxTreeListCtrl::SetIndent(unsigned int indent
) 
4324 { m_main_win
->SetIndent(indent
); } 
4326 unsigned int wxTreeListCtrl::GetLineSpacing() const 
4327 { return m_main_win
->GetLineSpacing(); } 
4329 void wxTreeListCtrl::SetLineSpacing(unsigned int spacing
) 
4330 { m_main_win
->SetLineSpacing(spacing
); } 
4332 wxImageList
* wxTreeListCtrl::GetImageList() const 
4333 { return m_main_win
->GetImageList(); } 
4335 wxImageList
* wxTreeListCtrl::GetStateImageList() const 
4336 { return m_main_win
->GetStateImageList(); } 
4338 wxImageList
* wxTreeListCtrl::GetButtonsImageList() const 
4339 { return m_main_win
->GetButtonsImageList(); } 
4341 void wxTreeListCtrl::SetImageList(wxImageList
* imageList
) 
4342 { m_main_win
->SetImageList(imageList
); } 
4344 void wxTreeListCtrl::SetStateImageList(wxImageList
* imageList
) 
4345 { m_main_win
->SetStateImageList(imageList
); } 
4347 void wxTreeListCtrl::SetButtonsImageList(wxImageList
* imageList
) 
4348 { m_main_win
->SetButtonsImageList(imageList
); } 
4350 void wxTreeListCtrl::AssignImageList(wxImageList
* imageList
) 
4351 { m_main_win
->AssignImageList(imageList
); } 
4353 void wxTreeListCtrl::AssignStateImageList(wxImageList
* imageList
) 
4354 { m_main_win
->AssignStateImageList(imageList
); } 
4356 void wxTreeListCtrl::AssignButtonsImageList(wxImageList
* imageList
) 
4357 { m_main_win
->AssignButtonsImageList(imageList
); } 
4359 wxString 
wxTreeListCtrl::GetItemText(const wxTreeItemId
& item
, int column
) const 
4360 { return m_main_win
->GetItemText (item
, column
); } 
4362 int wxTreeListCtrl::GetItemImage(const wxTreeItemId
& item
, int column
, 
4363                                  wxTreeItemIcon which
) const 
4364 { return m_main_win
->GetItemImage(item
, column
, which
); } 
4366 wxTreeItemData
* wxTreeListCtrl::GetItemData(const wxTreeItemId
& item
) const 
4367 { return m_main_win
->GetItemData(item
); } 
4369 bool wxTreeListCtrl::GetItemBold(const wxTreeItemId
& item
) const 
4370 { return m_main_win
->GetItemBold(item
); } 
4372 wxColour 
wxTreeListCtrl::GetItemTextColour(const wxTreeItemId
& item
) const 
4373 { return m_main_win
->GetItemTextColour(item
); } 
4375 wxColour 
wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId
& item
) 
4377 { return m_main_win
->GetItemBackgroundColour(item
); } 
4379 wxFont 
wxTreeListCtrl::GetItemFont(const wxTreeItemId
& item
) const 
4380 { return m_main_win
->GetItemFont(item
); } 
4383 void wxTreeListCtrl::SetItemText(const wxTreeItemId
& item
, int column
, 
4384                                  const wxString
& text
) 
4385 { m_main_win
->SetItemText (item
, column
, text
); } 
4387 void wxTreeListCtrl::SetItemImage(const wxTreeItemId
& item
, 
4390                                   wxTreeItemIcon which
) 
4391 { m_main_win
->SetItemImage(item
, column
, image
, which
); } 
4393 void wxTreeListCtrl::SetItemData(const wxTreeItemId
& item
, 
4394                                  wxTreeItemData
* data
) 
4395 { m_main_win
->SetItemData(item
, data
); } 
4397 void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId
& item
, bool has
) 
4398 { m_main_win
->SetItemHasChildren(item
, has
); } 
4400 void wxTreeListCtrl::SetItemBold(const wxTreeItemId
& item
, bool bold
) 
4401 { m_main_win
->SetItemBold(item
, bold
); } 
4403 void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId
& item
, 
4404                                        const wxColour
& colour
) 
4405 { m_main_win
->SetItemTextColour(item
, colour
); } 
4407 void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId
& item
, 
4408                                              const wxColour
& colour
) 
4409 { m_main_win
->SetItemBackgroundColour(item
, colour
); } 
4411 void wxTreeListCtrl::SetItemFont(const wxTreeItemId
& item
, 
4413 { m_main_win
->SetItemFont(item
, font
); } 
4415 bool wxTreeListCtrl::SetFont(const wxFont
& font
) 
4418         m_header_win
->SetFont(font
); 
4419         CalculateAndSetHeaderHeight(); 
4420         m_header_win
->Refresh(); 
4423         return m_main_win
->SetFont(font
); 
4429 void wxTreeListCtrl::SetWindowStyle(const long style
) 
4432         m_main_win
->SetWindowStyle(style
); 
4433     m_windowStyle 
= style
; 
4434     // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win 
4437 long wxTreeListCtrl::GetWindowStyle() const 
4439     long style 
= m_windowStyle
; 
4441         style 
|= m_main_win
->GetWindowStyle(); 
4445 bool wxTreeListCtrl::IsVisible(const wxTreeItemId
& item
, bool fullRow
) const 
4446 { return m_main_win
->IsVisible(item
, fullRow
); } 
4448 bool wxTreeListCtrl::HasChildren(const wxTreeItemId
& item
) const 
4449 { return m_main_win
->HasChildren(item
); } 
4451 bool wxTreeListCtrl::IsExpanded(const wxTreeItemId
& item
) const 
4452 { return m_main_win
->IsExpanded(item
); } 
4454 bool wxTreeListCtrl::IsSelected(const wxTreeItemId
& item
) const 
4455 { return m_main_win
->IsSelected(item
); } 
4457 bool wxTreeListCtrl::IsBold(const wxTreeItemId
& item
) const 
4458 { return m_main_win
->IsBold(item
); } 
4460 size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId
& item
, bool rec
) 
4461 { return m_main_win
->GetChildrenCount(item
, rec
); } 
4463 wxTreeItemId 
wxTreeListCtrl::GetRootItem() const 
4464 { return m_main_win
->GetRootItem(); } 
4466 wxTreeItemId 
wxTreeListCtrl::GetSelection() const 
4467 { return m_main_win
->GetSelection(); } 
4469 size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds
& arr
) const 
4470 { return m_main_win
->GetSelections(arr
); } 
4472 wxTreeItemId 
wxTreeListCtrl::GetItemParent(const wxTreeItemId
& item
) const 
4473 { return m_main_win
->GetItemParent(item
); } 
4475 #if !wxCHECK_VERSION(2, 5, 0) 
4476 wxTreeItemId 
wxTreeListCtrl::GetFirstChild (const wxTreeItemId
& item
, 
4479 wxTreeItemId 
wxTreeListCtrl::GetFirstChild (const wxTreeItemId
& item
, 
4480                                             wxTreeItemIdValue
& cookie
) const 
4482 { return m_main_win
->GetFirstChild(item
, cookie
); } 
4484 #if !wxCHECK_VERSION(2, 5, 0) 
4485 wxTreeItemId 
wxTreeListCtrl::GetNextChild (const wxTreeItemId
& item
, 
4488 wxTreeItemId 
wxTreeListCtrl::GetNextChild (const wxTreeItemId
& item
, 
4489                                            wxTreeItemIdValue
& cookie
) const 
4491 { return m_main_win
->GetNextChild(item
, cookie
); } 
4493 #if !wxCHECK_VERSION(2, 5, 0) 
4494 wxTreeItemId 
wxTreeListCtrl::GetPrevChild (const wxTreeItemId
& item
, 
4497 wxTreeItemId 
wxTreeListCtrl::GetPrevChild (const wxTreeItemId
& item
, 
4498                                            wxTreeItemIdValue
& cookie
) const 
4500 { return m_main_win
->GetPrevChild(item
, cookie
); } 
4502 #if !wxCHECK_VERSION(2, 5, 0) 
4503 wxTreeItemId 
wxTreeListCtrl::GetLastChild (const wxTreeItemId
& item
, 
4506 wxTreeItemId 
wxTreeListCtrl::GetLastChild (const wxTreeItemId
& item
, 
4507                                            wxTreeItemIdValue
& cookie
) const 
4509 { return m_main_win
->GetLastChild(item
, cookie
); } 
4512 wxTreeItemId 
wxTreeListCtrl::GetNextSibling(const wxTreeItemId
& item
) const 
4513 { return m_main_win
->GetNextSibling(item
); } 
4515 wxTreeItemId 
wxTreeListCtrl::GetPrevSibling(const wxTreeItemId
& item
) const 
4516 { return m_main_win
->GetPrevSibling(item
); } 
4518 wxTreeItemId 
wxTreeListCtrl::GetNext(const wxTreeItemId
& item
) const 
4519 { return m_main_win
->GetNext(item
, true); } 
4521 wxTreeItemId 
wxTreeListCtrl::GetPrev(const wxTreeItemId
& item
) const 
4522 { return m_main_win
->GetPrev(item
, true); } 
4524 wxTreeItemId 
wxTreeListCtrl::GetFirstExpandedItem() const 
4525 { return m_main_win
->GetFirstExpandedItem(); } 
4527 wxTreeItemId 
wxTreeListCtrl::GetNextExpanded(const wxTreeItemId
& item
) const 
4528 { return m_main_win
->GetNextExpanded(item
); } 
4530 wxTreeItemId 
wxTreeListCtrl::GetPrevExpanded(const wxTreeItemId
& item
) const 
4531 { return m_main_win
->GetPrevExpanded(item
); } 
4533 wxTreeItemId 
wxTreeListCtrl::GetFirstVisibleItem(bool fullRow
) const 
4534 { return m_main_win
->GetFirstVisibleItem(fullRow
); } 
4536 wxTreeItemId 
wxTreeListCtrl::GetNextVisible(const wxTreeItemId
& item
, bool fullRow
) const 
4537 { return m_main_win
->GetNextVisible(item
, fullRow
); } 
4539 wxTreeItemId 
wxTreeListCtrl::GetPrevVisible(const wxTreeItemId
& item
, bool fullRow
) const 
4540 { return m_main_win
->GetPrevVisible(item
, fullRow
); } 
4542 wxTreeItemId 
wxTreeListCtrl::AddRoot (const wxString
& text
, int image
, 
4543                                       int selectedImage
, wxTreeItemData
* data
) 
4544 { return m_main_win
->AddRoot (text
, image
, selectedImage
, data
); } 
4546 wxTreeItemId 
wxTreeListCtrl::PrependItem(const wxTreeItemId
& parent
, 
4547                                          const wxString
& text
, int image
, 
4549                                          wxTreeItemData
* data
) 
4550 { return m_main_win
->PrependItem(parent
, text
, image
, selectedImage
, data
); } 
4552 wxTreeItemId 
wxTreeListCtrl::InsertItem(const wxTreeItemId
& parent
, 
4553                                         const wxTreeItemId
& previous
, 
4554                                         const wxString
& text
, int image
, 
4556                                         wxTreeItemData
* data
) 
4558     return m_main_win
->InsertItem(parent
, previous
, text
, image
, 
4559                                   selectedImage
, data
); 
4562 wxTreeItemId 
wxTreeListCtrl::InsertItem(const wxTreeItemId
& parent
, 
4564                                         const wxString
& text
, int image
, 
4566                                         wxTreeItemData
* data
) 
4568     return m_main_win
->InsertItem(parent
, index
, text
, image
, 
4569                                   selectedImage
, data
); 
4572 wxTreeItemId 
wxTreeListCtrl::AppendItem(const wxTreeItemId
& parent
, 
4573                                         const wxString
& text
, int image
, 
4575                                         wxTreeItemData
* data
) 
4576 { return m_main_win
->AppendItem(parent
, text
, image
, selectedImage
, data
); } 
4578 void wxTreeListCtrl::Delete(const wxTreeItemId
& item
) 
4579 { m_main_win
->Delete(item
); } 
4581 void wxTreeListCtrl::DeleteChildren(const wxTreeItemId
& item
) 
4582 { m_main_win
->DeleteChildren(item
); } 
4584 void wxTreeListCtrl::DeleteRoot() 
4585 { m_main_win
->DeleteRoot(); } 
4587 void wxTreeListCtrl::Expand(const wxTreeItemId
& item
) 
4588 { m_main_win
->Expand(item
); } 
4590 void wxTreeListCtrl::ExpandAll(const wxTreeItemId
& item
) 
4591 { m_main_win
->ExpandAll(item
); } 
4593 void wxTreeListCtrl::Collapse(const wxTreeItemId
& item
) 
4594 { m_main_win
->Collapse(item
); } 
4596 void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId
& item
) 
4597 { m_main_win
->CollapseAndReset(item
); } 
4599 void wxTreeListCtrl::Toggle(const wxTreeItemId
& item
) 
4600 { m_main_win
->Toggle(item
); } 
4602 void wxTreeListCtrl::Unselect() 
4603 { m_main_win
->Unselect(); } 
4605 void wxTreeListCtrl::UnselectAll() 
4606 { m_main_win
->UnselectAll(); } 
4608 void wxTreeListCtrl::SelectItem(const wxTreeItemId
& item
, const wxTreeItemId
& last
, 
4609                                 bool unselect_others
) 
4610 { m_main_win
->SelectItem (item
, last
, unselect_others
); } 
4612 void wxTreeListCtrl::SelectAll() 
4613 { m_main_win
->SelectAll(); } 
4615 void wxTreeListCtrl::EnsureVisible(const wxTreeItemId
& item
) 
4616 { m_main_win
->EnsureVisible(item
); } 
4618 void wxTreeListCtrl::ScrollTo(const wxTreeItemId
& item
) 
4619 { m_main_win
->ScrollTo(item
); } 
4621 wxTreeItemId 
wxTreeListCtrl::HitTest(const wxPoint
& pos
, int& flags
, int& column
) 
4623     wxPoint p 
= m_main_win
->ScreenToClient (ClientToScreen (pos
)); 
4624     return m_main_win
->HitTest (p
, flags
, column
); 
4627 bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId
& item
, wxRect
& rect
, 
4628                                      bool textOnly
) const 
4629 { return m_main_win
->GetBoundingRect(item
, rect
, textOnly
); } 
4631 void wxTreeListCtrl::EditLabel (const wxTreeItemId
& item
, int column
) 
4632 { m_main_win
->EditLabel (item
, column
); } 
4634 int wxTreeListCtrl::OnCompareItems(const wxTreeItemId
& item1
, 
4635                                    const wxTreeItemId
& item2
) 
4637     // do the comparison here, and not delegate to m_main_win, in order 
4638     // to let the user override it 
4639     //return m_main_win->OnCompareItems(item1, item2); 
4640     return wxStrcmp(GetItemText(item1
), GetItemText(item2
)); 
4643 void wxTreeListCtrl::SortChildren(const wxTreeItemId
& item
) 
4644 { m_main_win
->SortChildren(item
); } 
4646 wxTreeItemId 
wxTreeListCtrl::FindItem (const wxTreeItemId
& item
, const wxString
& str
, int mode
) 
4647 { return m_main_win
->FindItem (item
, str
, mode
); } 
4649 void wxTreeListCtrl::SetDragItem (const wxTreeItemId
& item
) 
4650 { m_main_win
->SetDragItem (item
); } 
4652 bool wxTreeListCtrl::SetBackgroundColour(const wxColour
& colour
) 
4654     if (!m_main_win
) return false; 
4655     return m_main_win
->SetBackgroundColour(colour
); 
4658 bool wxTreeListCtrl::SetForegroundColour(const wxColour
& colour
) 
4660     if (!m_main_win
) return false; 
4661     return m_main_win
->SetForegroundColour(colour
); 
4664 int wxTreeListCtrl::GetColumnCount() const 
4665 { return m_main_win
->GetColumnCount(); } 
4667 void wxTreeListCtrl::SetColumnWidth(int column
, int width
) 
4669     m_header_win
->SetColumnWidth (column
, width
); 
4670     m_header_win
->Refresh(); 
4673 int wxTreeListCtrl::GetColumnWidth(int column
) const 
4674 { return m_header_win
->GetColumnWidth(column
); } 
4676 void wxTreeListCtrl::SetMainColumn(int column
) 
4677 { m_main_win
->SetMainColumn(column
); } 
4679 int wxTreeListCtrl::GetMainColumn() const 
4680 { return m_main_win
->GetMainColumn(); } 
4682 void wxTreeListCtrl::SetColumnText(int column
, const wxString
& text
) 
4684     m_header_win
->SetColumnText (column
, text
); 
4685     m_header_win
->Refresh(); 
4688 wxString 
wxTreeListCtrl::GetColumnText(int column
) const 
4689 { return m_header_win
->GetColumnText(column
); } 
4691 void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo
& colInfo
) 
4693     m_header_win
->AddColumn (colInfo
); 
4697 void wxTreeListCtrl::InsertColumn(int before
, const wxTreeListColumnInfo
& colInfo
) 
4699     m_header_win
->InsertColumn (before
, colInfo
); 
4700     m_header_win
->Refresh(); 
4703 void wxTreeListCtrl::RemoveColumn(int column
) 
4705     m_header_win
->RemoveColumn (column
); 
4706     m_header_win
->Refresh(); 
4709 void wxTreeListCtrl::SetColumn(int column
, const wxTreeListColumnInfo
& colInfo
) 
4711     m_header_win
->SetColumn (column
, colInfo
); 
4712     m_header_win
->Refresh(); 
4715 const wxTreeListColumnInfo
& wxTreeListCtrl::GetColumn(int column
) const 
4716 { return m_header_win
->GetColumn(column
); } 
4718 wxTreeListColumnInfo
& wxTreeListCtrl::GetColumn(int column
) 
4719 { return m_header_win
->GetColumn(column
); } 
4721 void wxTreeListCtrl::SetColumnImage(int column
, int image
) 
4723     m_header_win
->SetColumn (column
, GetColumn(column
).SetImage(image
)); 
4724     m_header_win
->Refresh(); 
4727 int wxTreeListCtrl::GetColumnImage(int column
) const 
4729     return m_header_win
->GetColumn(column
).GetImage(); 
4732 void wxTreeListCtrl::SetColumnEditable(int column
, bool shown
) 
4734     m_header_win
->SetColumn (column
, GetColumn(column
).SetEditable(shown
)); 
4737 void wxTreeListCtrl::SetColumnShown(int column
, bool shown
) 
4739     wxASSERT_MSG (column 
!= GetMainColumn(), _T("The main column may not be hidden") ); 
4740     m_header_win
->SetColumn (column
, GetColumn(column
).SetShown(GetMainColumn()==column
? true: shown
)); 
4741     m_header_win
->Refresh(); 
4744 bool wxTreeListCtrl::IsColumnEditable(int column
) const 
4746     return m_header_win
->GetColumn(column
).IsEditable(); 
4749 bool wxTreeListCtrl::IsColumnShown(int column
) const 
4751     return m_header_win
->GetColumn(column
).IsShown(); 
4754 void wxTreeListCtrl::SetColumnAlignment (int column
, int flag
) 
4756     m_header_win
->SetColumn(column
, GetColumn(column
).SetAlignment(flag
)); 
4757     m_header_win
->Refresh(); 
4760 int wxTreeListCtrl::GetColumnAlignment(int column
) const 
4762     return m_header_win
->GetColumn(column
).GetAlignment(); 
4765 void wxTreeListCtrl::Refresh(bool erase
, const wxRect
* rect
) 
4767     m_main_win
->Refresh (erase
, rect
); 
4768     m_header_win
->Refresh (erase
, rect
); 
4771 void wxTreeListCtrl::SetFocus() 
4772 { m_main_win
->SetFocus(); } 
4774 wxSize 
wxTreeListCtrl::DoGetBestSize() const 
4776     // something is better than nothing... 
4777     return wxSize (200,200); // but it should be specified values! FIXME 
4780 wxString 
wxTreeListCtrl::OnGetItemText( wxTreeItemData
* WXUNUSED(item
), long WXUNUSED(column
)) const 
4782     return wxEmptyString
;