1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        treelistctrl.cpp 
   3 // Purpose:     multi column tree control implementation 
   4 // Author:      Robert Roebling 
   6 // Modified:    Alberto Griggio, 2002 
   7 //              22/10/98 - almost total rewrite, simpler interface (VZ) 
   9 // Copyright:   (c) Robert Roebling, Julian Smart, Alberto Griggio, 
  10 //              Vadim Zeitlin, Otto Wyss 
  11 // Licence:     wxWindows licence 
  12 ///////////////////////////////////////////////////////////////////////////// 
  14 // =========================================================================== 
  16 // =========================================================================== 
  18 // --------------------------------------------------------------------------- 
  20 // --------------------------------------------------------------------------- 
  22 #if defined(__GNUG__) && !defined(__APPLE__) 
  23   #pragma implementation "treelistctrl.h" 
  26 // For compilers that support precompilation, includes "wx.h". 
  27 #include "wx/wxprec.h" 
  34 #include <wx/treebase.h> 
  36 #include <wx/textctrl.h> 
  37 #include <wx/imaglist.h> 
  38 #include <wx/settings.h> 
  39 #include <wx/dcclient.h> 
  40 #include <wx/dcscreen.h> 
  41 #include <wx/scrolwin.h> 
  42 #include <wx/renderer.h> 
  43 #include <wx/dcmemory.h> 
  45 #include "wx/treelistctrl.h" 
  49     #include <wx/gtk/win_gtk.h> 
  53     #include "wx/mac/private.h" 
  57 // --------------------------------------------------------------------------- 
  59 // --------------------------------------------------------------------------- 
  63 #if !wxCHECK_VERSION(2, 5, 0) 
  64 WX_DEFINE_ARRAY(wxTreeListItem 
*, wxArrayTreeListItems
); 
  66 WX_DEFINE_ARRAY_PTR(wxTreeListItem 
*, wxArrayTreeListItems
); 
  69 #include <wx/dynarray.h> 
  70 WX_DECLARE_OBJARRAY(wxTreeListColumnInfo
, wxArrayTreeListColumnInfo
); 
  71 #include <wx/arrimpl.cpp> 
  72 WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo
); 
  74 #if !wxCHECK_VERSION(2, 3, 3) 
  75 WX_DEFINE_ARRAY(short, wxArrayShort
); 
  79 // -------------------------------------------------------------------------- 
  81 // -------------------------------------------------------------------------- 
  83 static const int NO_IMAGE 
= -1; 
  85 const int LINEHEIGHT 
= 10; 
  86 const int PIXELS_PER_UNIT 
= 10; 
  87 const int LINEATROOT 
= 5; 
  89 const int MININDENT 
= 10; 
  90 const int BTNWIDTH 
= 9; //11; 
  91 const int BTNHEIGHT 
= 9; //11; 
  93 // extra margins around the text label 
  94 static const int EXTRA_WIDTH 
= 4; 
  95 static const int EXTRA_HEIGHT 
= 4; 
  97 // offset for the header window 
  98 static const int HEADER_OFFSET_X 
= 1; 
  99 static const int HEADER_OFFSET_Y 
= 1; 
 103 const wxChar
* wxTreeListCtrlNameStr 
= wxT("treelistctrl"); 
 105 static wxTreeListColumnInfo wxInvalidTreeListColumnInfo
; 
 108 // --------------------------------------------------------------------------- 
 110 // --------------------------------------------------------------------------- 
 111 //----------------------------------------------------------------------------- 
 112 //  wxTreeListHeaderWindow (internal) 
 113 //----------------------------------------------------------------------------- 
 115 class  wxTreeListHeaderWindow 
: public wxWindow
 
 118     wxTreeListMainWindow 
*m_owner
; 
 119     wxCursor             
*m_currentCursor
; 
 120     wxCursor             
*m_resizeCursor
; 
 123     // column being resized 
 126     // divider line position in logical (unscrolled) coords 
 129     // minimal position beyond which the divider line can't be dragged in 
 133     wxArrayTreeListColumnInfo m_columns
; 
 135     // total width of the columns 
 136     int m_total_col_width
; 
 140     wxTreeListHeaderWindow(); 
 142     wxTreeListHeaderWindow( wxWindow 
*win
, 
 144                             wxTreeListMainWindow 
*owner
, 
 145                             const wxPoint 
&pos 
= wxDefaultPosition
, 
 146                             const wxSize 
&size 
= wxDefaultSize
, 
 148                             const wxString 
&name 
= wxT("wxtreelistctrlcolumntitles") ); 
 150     virtual ~wxTreeListHeaderWindow(); 
 152     void DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
); 
 154     void AdjustDC(wxDC
& dc
); 
 156     void OnEraseBackground( wxEraseEvent
& event 
); 
 157     void OnPaint( wxPaintEvent 
&event 
); 
 158     void OnMouse( wxMouseEvent 
&event 
); 
 159     void OnSetFocus( wxFocusEvent 
&event 
); 
 162     // columns manipulation 
 164     size_t GetColumnCount() const { return m_columns
.GetCount(); } 
 166     void AddColumn(const wxTreeListColumnInfo
& col
); 
 168     void InsertColumn(size_t before
, const wxTreeListColumnInfo
& col
); 
 170     void RemoveColumn(size_t column
); 
 172     void SetColumn(size_t column
, const wxTreeListColumnInfo
& info
); 
 173     const wxTreeListColumnInfo
& GetColumn(size_t column
) const 
 175         wxCHECK_MSG(column 
< GetColumnCount(), wxInvalidTreeListColumnInfo
, wxT("Invalid column")); 
 176         return m_columns
[column
]; 
 178     wxTreeListColumnInfo
& GetColumn(size_t column
) 
 180         wxCHECK_MSG(column 
< GetColumnCount(), wxInvalidTreeListColumnInfo
, wxT("Invalid column")); 
 181         return m_columns
[column
]; 
 184     void SetColumnWidth(size_t column
, size_t width
); 
 186     void SetColumnText(size_t column
, const wxString
& text
) 
 188         wxCHECK_RET(column 
< GetColumnCount(), wxT("Invalid column")); 
 189         m_columns
[column
].SetText(text
); 
 192     void SetColumnShown(size_t column
, bool shown
) 
 194         wxCHECK_RET(column 
< GetColumnCount(), wxT("Invalid column")); 
 195         m_columns
[column
].SetShown(shown
); 
 198     wxString 
GetColumnText(size_t column
) const 
 200         wxCHECK_MSG(column 
< GetColumnCount(), wxEmptyString
, wxT("Invalid column")); 
 201         return m_columns
[column
].GetText(); 
 204     int GetColumnWidth(size_t column
) const 
 206         wxCHECK_MSG(column 
< GetColumnCount(), -1, wxT("Invalid column")); 
 207         return m_columns
[column
].GetWidth(); 
 210     int GetWidth() const { return m_total_col_width
; } 
 212     int GetColumnShown(size_t column
) const 
 214         wxCHECK_MSG(column 
< GetColumnCount(), -1, wxT("Invalid column")); 
 215         return m_columns
[column
].GetShown(); 
 222     // common part of all ctors 
 225     void SendListEvent(wxEventType type
, wxPoint pos
); 
 227     DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow
) 
 228     DECLARE_EVENT_TABLE() 
 232 // this is the "true" control 
 233 class  wxTreeListMainWindow
: public wxScrolledWindow
 
 238     wxTreeListMainWindow() { Init(); } 
 240     wxTreeListMainWindow(wxTreeListCtrl 
*parent
, wxWindowID id 
= -1, 
 241                const wxPoint
& pos 
= wxDefaultPosition
, 
 242                const wxSize
& size 
= wxDefaultSize
, 
 243                long style 
= wxTR_DEFAULT_STYLE
, 
 244                const wxValidator 
&validator 
= wxDefaultValidator
, 
 245                const wxString
& name 
= wxT("wxtreelistmainwindow")) 
 248         Create(parent
, id
, pos
, size
, style
, validator
, name
); 
 251     virtual ~wxTreeListMainWindow(); 
 253     bool Create(wxTreeListCtrl 
*parent
, wxWindowID id 
= -1, 
 254                 const wxPoint
& pos 
= wxDefaultPosition
, 
 255                 const wxSize
& size 
= wxDefaultSize
, 
 256                 long style 
= wxTR_DEFAULT_STYLE
, 
 257                 const wxValidator 
&validator 
= wxDefaultValidator
, 
 258                 const wxString
& name 
= wxT("wxtreelistctrl")); 
 263     // get the total number of items in the control 
 264     size_t GetCount() const; 
 266     // indent is the number of pixels the children are indented relative to 
 267     // the parents position. SetIndent() also redraws the control 
 269     unsigned int GetIndent() const { return m_indent
; } 
 270     void SetIndent(unsigned int indent
); 
 272     // see wxTreeListCtrl for the meaning 
 273     unsigned int GetLineSpacing() const { return m_linespacing
; } 
 274     void SetLineSpacing(unsigned int spacing
); 
 276     // image list: these functions allow to associate an image list with 
 277     // the control and retrieve it. Note that when assigned with 
 278     // SetImageList, the control does _not_ delete 
 279     // the associated image list when it's deleted in order to allow image 
 280     // lists to be shared between different controls. If you use 
 281     // AssignImageList, the control _does_ delete the image list. 
 283     // The normal image list is for the icons which correspond to the 
 284     // normal tree item state (whether it is selected or not). 
 285     // Additionally, the application might choose to show a state icon 
 286     // which corresponds to an app-defined item state (for example, 
 287     // checked/unchecked) which are taken from the state image list. 
 288     wxImageList 
*GetImageList() const; 
 289     wxImageList 
*GetStateImageList() const; 
 290     wxImageList 
*GetButtonsImageList() const; 
 292     void SetImageList(wxImageList 
*imageList
); 
 293     void SetStateImageList(wxImageList 
*imageList
); 
 294     void SetButtonsImageList(wxImageList 
*imageList
); 
 295     void AssignImageList(wxImageList 
*imageList
); 
 296     void AssignStateImageList(wxImageList 
*imageList
); 
 297     void AssignButtonsImageList(wxImageList 
*imageList
); 
 299     // Functions to work with tree ctrl items. 
 304     // retrieve item's label 
 305     wxString 
GetItemText(const wxTreeItemId
& item
) const 
 306     { return GetItemText(item
, GetMainColumn()); } 
 307     // get one of the images associated with the item (normal by default) 
 308     int GetItemImage(const wxTreeItemId
& item
, 
 309                      wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const 
 310     { return GetItemImage(item
, GetMainColumn(), which
); } 
 312     // get the data associated with the item 
 313     wxTreeItemData 
*GetItemData(const wxTreeItemId
& item
) const; 
 315     bool GetItemBold(const wxTreeItemId
& item
) const; 
 316     wxColour 
GetItemTextColour(const wxTreeItemId
& item
) const; 
 317     wxColour 
GetItemBackgroundColour(const wxTreeItemId
& item
) const; 
 318     wxFont 
GetItemFont(const wxTreeItemId
& item
) const; 
 324     void SetItemText(const wxTreeItemId
& item
, const wxString
& text
) 
 325     { SetItemText(item
, GetMainColumn(), text
); } 
 327     // get one of the images associated with the item (normal by default) 
 328     void SetItemImage(const wxTreeItemId
& item
, int image
, 
 329                       wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) 
 330     { SetItemImage(item
, GetMainColumn(), image
, which
); } 
 332     // associate some data with the item 
 333     void SetItemData(const wxTreeItemId
& item
, wxTreeItemData 
*data
); 
 335     // force appearance of [+] button near the item. This is useful to 
 336     // allow the user to expand the items which don't have any children now 
 337     // - but instead add them only when needed, thus minimizing memory 
 338     // usage and loading time. 
 339     void SetItemHasChildren(const wxTreeItemId
& item
, bool has 
= TRUE
); 
 341     // the item will be shown in bold 
 342     void SetItemBold(const wxTreeItemId
& item
, bool bold 
= TRUE
); 
 344     // set the item's text colour 
 345     void SetItemTextColour(const wxTreeItemId
& item
, const wxColour
& colour
); 
 347     // set the item's background colour 
 348     void SetItemBackgroundColour(const wxTreeItemId
& item
, const wxColour
& colour
); 
 350     // set the item's font (should be of the same height for all items) 
 351     void SetItemFont(const wxTreeItemId
& item
, const wxFont
& font
); 
 353     // set the window font 
 354     virtual bool SetFont( const wxFont 
&font 
); 
 356     // set the styles.  No need to specify a GetWindowStyle here since 
 357     // the base wxWindow member function will do it for us 
 358     void SetWindowStyle(const long styles
); 
 360     // item status inquiries 
 361     // --------------------- 
 363     // is the item visible (it might be outside the view or not expanded)? 
 364     bool IsVisible(const wxTreeItemId
& item
) const; 
 365     // does the item has any children? 
 366     bool HasChildren(const wxTreeItemId
& item
) const 
 367     { return ItemHasChildren(item
); } 
 368     bool ItemHasChildren(const wxTreeItemId
& item
) const; 
 369     // is the item expanded (only makes sense if HasChildren())? 
 370     bool IsExpanded(const wxTreeItemId
& item
) const; 
 371     // is this item currently selected (the same as has focus)? 
 372     bool IsSelected(const wxTreeItemId
& item
) const; 
 373     // is item text in bold font? 
 374     bool IsBold(const wxTreeItemId
& item
) const; 
 375         // does the layout include space for a button? 
 377     // number of children 
 378     // ------------------ 
 380     // if 'recursively' is FALSE, only immediate children count, otherwise 
 381     // the returned number is the number of all items in this branch 
 382     size_t GetChildrenCount(const wxTreeItemId
& item
, bool recursively 
= TRUE
); 
 387     // wxTreeItemId.IsOk() will return FALSE if there is no such item 
 389     // get the root tree item 
 390     wxTreeItemId 
GetRootItem() const { return m_anchor
; } 
 392     // get the item currently selected (may return NULL if no selection) 
 393     wxTreeItemId 
GetSelection() const { return m_current
; } 
 395     // get the items currently selected, return the number of such item 
 396     size_t GetSelections(wxArrayTreeItemIds
&) const; 
 398     // get the parent of this item (may return NULL if root) 
 399     wxTreeItemId 
GetItemParent(const wxTreeItemId
& item
) const; 
 401     // for this enumeration function you must pass in a "cookie" parameter 
 402     // which is opaque for the application but is necessary for the library 
 403     // to make these functions reentrant (i.e. allow more than one 
 404     // enumeration on one and the same object simultaneously). Of course, 
 405     // the "cookie" passed to GetFirstChild() and GetNextChild() should be 
 408     // get the first child of this item 
 409 #if !wxCHECK_VERSION(2, 5, 0) 
 410     wxTreeItemId 
GetFirstChild(const wxTreeItemId
& item
, long& cookie
) const; 
 412     wxTreeItemId 
GetFirstChild(const wxTreeItemId
& item
, wxTreeItemIdValue
& cookie
) const; 
 414     // get the next child 
 415 #if !wxCHECK_VERSION(2, 5, 0) 
 416     wxTreeItemId 
GetNextChild(const wxTreeItemId
& item
, long& cookie
) const; 
 418     wxTreeItemId 
GetNextChild(const wxTreeItemId
& item
, wxTreeItemIdValue
& cookie
) const; 
 420     // get the prev child 
 421 #if !wxCHECK_VERSION(2, 5, 0) 
 422     wxTreeItemId 
GetPrevChild(const wxTreeItemId
& item
, long& cookie
) const; 
 424     wxTreeItemId 
GetPrevChild(const wxTreeItemId
& item
, wxTreeItemIdValue
& cookie
) const; 
 426     // get the last child of this item - this method doesn't use cookies 
 427     wxTreeItemId 
GetLastChild(const wxTreeItemId
& item
) const; 
 429     // get the next sibling of this item 
 430     wxTreeItemId 
GetNextSibling(const wxTreeItemId
& item
) const; 
 431     // get the previous sibling 
 432     wxTreeItemId 
GetPrevSibling(const wxTreeItemId
& item
) const; 
 434     // get first visible item 
 435     wxTreeItemId 
GetFirstVisibleItem() const; 
 436     // get the next visible item: item must be visible itself! 
 437     // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem() 
 438     wxTreeItemId 
GetNextVisible(const wxTreeItemId
& item
) const; 
 439     // get the previous visible item: item must be visible itself! 
 440     wxTreeItemId 
GetPrevVisible(const wxTreeItemId
& item
) const; 
 442     // Only for internal use right now, but should probably be public 
 443     wxTreeItemId 
GetNext(const wxTreeItemId
& item
) const; 
 448     // add the root node to the tree 
 449     wxTreeItemId 
AddRoot(const wxString
& text
, 
 450                          int image 
= -1, int selectedImage 
= -1, 
 451                          wxTreeItemData 
*data 
= NULL
); 
 453     // insert a new item in as the first child of the parent 
 454     wxTreeItemId 
PrependItem(const wxTreeItemId
& parent
, 
 455                              const wxString
& text
, 
 456                              int image 
= -1, int selectedImage 
= -1, 
 457                              wxTreeItemData 
*data 
= NULL
); 
 459     // insert a new item after a given one 
 460     wxTreeItemId 
InsertItem(const wxTreeItemId
& parent
, 
 461                             const wxTreeItemId
& idPrevious
, 
 462                             const wxString
& text
, 
 463                             int image 
= -1, int selectedImage 
= -1, 
 464                             wxTreeItemData 
*data 
= NULL
); 
 466     // insert a new item before the one with the given index 
 467     wxTreeItemId 
InsertItem(const wxTreeItemId
& parent
, 
 469                             const wxString
& text
, 
 470                             int image 
= -1, int selectedImage 
= -1, 
 471                             wxTreeItemData 
*data 
= NULL
); 
 473     // insert a new item in as the last child of the parent 
 474     wxTreeItemId 
AppendItem(const wxTreeItemId
& parent
, 
 475                             const wxString
& text
, 
 476                             int image 
= -1, int selectedImage 
= -1, 
 477                             wxTreeItemData 
*data 
= NULL
); 
 479     // delete this item and associated data if any 
 480     void Delete(const wxTreeItemId
& item
); 
 481     // delete all children (but don't delete the item itself) 
 482     // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events 
 483     void DeleteChildren(const wxTreeItemId
& item
); 
 484     // delete all items from the tree 
 485     // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events 
 486     void DeleteAllItems(); 
 489     void Expand(const wxTreeItemId
& item
); 
 490     // expand this item and all subitems recursively 
 491     void ExpandAll(const wxTreeItemId
& item
); 
 492     // collapse the item without removing its children 
 493     void Collapse(const wxTreeItemId
& item
); 
 494     // collapse the item and remove all children 
 495     void CollapseAndReset(const wxTreeItemId
& item
); 
 496     // toggles the current state 
 497     void Toggle(const wxTreeItemId
& item
); 
 499     // remove the selection from currently selected item (if any) 
 503     void SelectItem(const wxTreeItemId
& item
, bool unselect_others
=TRUE
, 
 504                     bool extended_select
=FALSE
); 
 505     void SelectAll(bool extended_select
=FALSE
); 
 506     // make sure this item is visible (expanding the parent item and/or 
 507     // scrolling to this item if necessary) 
 508     void EnsureVisible(const wxTreeItemId
& item
); 
 509     // scroll to this item (but don't expand its parent) 
 510     void ScrollTo(const wxTreeItemId
& item
); 
 511     void AdjustMyScrollbars(); 
 513     // The first function is more portable (because easier to implement 
 514     // on other platforms), but the second one returns some extra info. 
 515     wxTreeItemId 
HitTest(const wxPoint
& point
) 
 516         { int dummy
; return HitTest(point
, dummy
); } 
 517     wxTreeItemId 
HitTest(const wxPoint
& point
, int& flags
) 
 518     { int col
; return HitTest(point
, flags
, col
); } 
 520     wxTreeItemId 
HitTest(const wxPoint
& point
, int& flags
, int& column
); 
 523     // get the bounding rectangle of the item (or of its label only) 
 524     bool GetBoundingRect(const wxTreeItemId
& item
, 
 526                          bool textOnly 
= FALSE
) const; 
 528     // Start editing the item label: this (temporarily) replaces the item 
 529     // with a one line edit control. The item will be selected if it hadn't 
 531     void EditLabel( const wxTreeItemId
& item 
) { Edit( item 
); } 
 532     void Edit( const wxTreeItemId
& item 
); 
 535     // this function is called to compare 2 items and should return -1, 0 
 536     // or +1 if the first item is less than, equal to or greater than the 
 537     // second one. The base class version performs alphabetic comparaison 
 538     // of item labels (GetText) 
 539     virtual int OnCompareItems(const wxTreeItemId
& item1
, 
 540                                const wxTreeItemId
& item2
); 
 541     // sort the children of this item using OnCompareItems 
 543     // NB: this function is not reentrant and not MT-safe (FIXME)! 
 544     void SortChildren(const wxTreeItemId
& item
); 
 547     wxTreeItemId 
FindItem (const wxTreeItemId
& item
, const wxString
& str
, int flags 
= 0); 
 549     // deprecated functions: use Set/GetItemImage directly 
 550     // get the selected item image 
 551     int GetItemSelectedImage(const wxTreeItemId
& item
) const 
 552         { return GetItemImage(item
, wxTreeItemIcon_Selected
); } 
 553     // set the selected item image 
 554     void SetItemSelectedImage(const wxTreeItemId
& item
, int image
) 
 555         { SetItemImage(item
, image
, wxTreeItemIcon_Selected
); } 
 557     // implementation only from now on 
 559     // overridden base class virtuals 
 560     virtual bool SetBackgroundColour(const wxColour
& colour
); 
 561     virtual bool SetForegroundColour(const wxColour
& colour
); 
 564     void OnPaint( wxPaintEvent 
&event 
); 
 565     void OnSetFocus( wxFocusEvent 
&event 
); 
 566     void OnKillFocus( wxFocusEvent 
&event 
); 
 567     void OnChar( wxKeyEvent 
&event 
); 
 568     void OnMouse( wxMouseEvent 
&event 
); 
 569     void OnIdle( wxIdleEvent 
&event 
); 
 570     void OnScroll(wxScrollWinEvent
& event
); // ALB 
 572     // implementation helpers 
 573     void SendDeleteEvent(wxTreeListItem 
*itemBeingDeleted
); 
 575     void DrawBorder(const wxTreeItemId
& item
); 
 576     void DrawLine(const wxTreeItemId
& item
, bool below
); 
 578     size_t GetColumnCount() const 
 579     { return m_owner
->GetHeaderWindow()->GetColumnCount(); } 
 581     void SetMainColumn(size_t column
) 
 583         if(column 
< GetColumnCount()) 
 584             m_main_column 
= column
; 
 586     size_t GetMainColumn() const { return m_main_column
; } 
 588     void SetItemText(const wxTreeItemId
& item
, size_t column
, 
 589                      const wxString
& text
); 
 590     wxString 
GetItemText(const wxTreeItemId
& item
, size_t column
) const; 
 592     void SetItemImage(const wxTreeItemId
& item
, size_t column
, int image
, 
 593                       wxTreeItemIcon which 
= wxTreeItemIcon_Normal
); 
 594     int GetItemImage(const wxTreeItemId
& item
, size_t column
, 
 595                      wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const; 
 600     wxTreeListCtrl
* m_owner
; // ALB 
 602     size_t m_main_column
; // ALB 
 604     friend class wxTreeListItem
; 
 605     friend class wxTreeListRenameTimer
; 
 606     friend class wxTreeListTextCtrl
; 
 611     wxTreeListItem   
*m_anchor
; 
 612     wxTreeListItem   
*m_current
, *m_key_current
, *m_currentEdit
; 
 613     int                  m_btnWidth
, m_btnWidth2
; 
 614     int                  m_btnHeight
, m_btnHeight2
; 
 615     int                  m_imgWidth
, m_imgWidth2
; 
 616     int                  m_imgHeight
, m_imgHeight2
; 
 617     unsigned short       m_indent
; 
 619     unsigned short       m_linespacing
; 
 621     wxBrush             
*m_hilightBrush
, 
 622                         *m_hilightUnfocusedBrush
; 
 627     bool                 m_ownsImageListNormal
, 
 628                          m_ownsImageListState
, 
 629                          m_ownsImageListButtons
; 
 630     bool                 m_isDragging
; // true between BEGIN/END drag events 
 632     bool                 m_lastOnSame
;  // last click on the same item as prev 
 633     wxImageList         
*m_imageListNormal
, 
 639     wxTreeListItem   
*m_dropTarget
; 
 640     wxCursor             m_oldCursor
;  // cursor is changed while dragging 
 641     wxTreeListItem   
*m_oldSelection
; 
 642     wxTreeListItem   
*m_underMouse
; // for visual effects 
 644     wxTimer             
*m_renameTimer
; 
 645     wxString             m_renameRes
; 
 648     wxTimer             
*m_findTimer
; 
 651     // the common part of all ctors 
 655     wxTreeItemId 
DoInsertItem(const wxTreeItemId
& parent
, 
 657                               const wxString
& text
, 
 658                               int image
, int selectedImage
, 
 659                               wxTreeItemData 
*data
); 
 660     bool HasButtons(void) const 
 661         { return (m_imageListButtons 
!= NULL
) || 
 662                   HasFlag (wxTR_TWIST_BUTTONS
|wxTR_HAS_BUTTONS
); } 
 665     void CalculateLineHeight(); 
 666     int  GetLineHeight(wxTreeListItem 
*item
) const; 
 667     void PaintLevel( wxTreeListItem 
*item
, wxDC
& dc
, int level
, int &y
, 
 669     void PaintItem( wxTreeListItem 
*item
, wxDC
& dc
); 
 671     void CalculateLevel( wxTreeListItem 
*item
, wxDC 
&dc
, int level
, int &y
, 
 673     void CalculatePositions(); 
 674     void CalculateSize( wxTreeListItem 
*item
, wxDC 
&dc 
); 
 676     void RefreshSubtree( wxTreeListItem 
*item 
); 
 677     void RefreshLine( wxTreeListItem 
*item 
); 
 679     // redraw all selected items 
 680     void RefreshSelected(); 
 682     // RefreshSelected() recursive helper 
 683     void RefreshSelectedUnder(wxTreeListItem 
*item
); 
 685     void OnRenameTimer(); 
 686     void OnRenameAccept(); 
 688     void FillArray(wxTreeListItem
*, wxArrayTreeItemIds
&) const; 
 689     void SelectItemRange( wxTreeListItem 
*item1
, wxTreeListItem 
*item2 
); 
 690     bool TagAllChildrenUntilLast(wxTreeListItem 
*crt_item
, 
 691                                  wxTreeListItem 
*last_item
, bool select
); 
 692     bool TagNextChildren(wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
, 
 694     void UnselectAllChildren( wxTreeListItem 
*item 
); 
 696     void DrawDropEffect(wxTreeListItem 
*item
); 
 699     DECLARE_EVENT_TABLE() 
 700     DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow
) 
 704 // timer used for enabling in-place edit 
 705 class  wxTreeListRenameTimer
: public wxTimer
 
 708     wxTreeListRenameTimer( wxTreeListMainWindow 
*owner 
); 
 713     wxTreeListMainWindow   
*m_owner
; 
 716 // control used for in-place edit 
 717 class  wxTreeListTextCtrl
: public wxTextCtrl
 
 720     wxTreeListTextCtrl( wxWindow 
*parent
, 
 724                         wxTreeListMainWindow 
*owner
, 
 725                         const wxString 
&value 
= wxEmptyString
, 
 726                         const wxPoint 
&pos 
= wxDefaultPosition
, 
 727                         const wxSize 
&size 
= wxDefaultSize
, 
 728                         int style 
= wxSIMPLE_BORDER
, 
 729                         const wxValidator
& validator 
= wxDefaultValidator
, 
 730                         const wxString 
&name 
= wxTextCtrlNameStr 
); 
 732     void OnChar( wxKeyEvent 
&event 
); 
 733     void OnKeyUp( wxKeyEvent 
&event 
); 
 734     void OnKillFocus( wxFocusEvent 
&event 
); 
 739     wxTreeListMainWindow  
*m_owner
; 
 740     wxString            m_startValue
; 
 743     DECLARE_EVENT_TABLE() 
 751     wxTreeListItem() { m_data 
= NULL
; } 
 752     wxTreeListItem( wxTreeListMainWindow 
*owner
, 
 753                     wxTreeListItem 
*parent
, 
 754                     const wxArrayString
& text
, 
 757                     wxTreeItemData 
*data 
); 
 762     wxArrayTreeListItems
& GetChildren() { return m_children
; } 
 764     const wxString 
GetText() const 
 766         if(m_text
.GetCount() > 0) return m_text
[0]; 
 767         return wxEmptyString
; 
 769     const wxString 
GetText(size_t col
) const 
 771         if(m_text
.GetCount() > col
) return m_text
[col
]; 
 772         return wxEmptyString
; 
 774     int GetImage(wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const 
 775         { return m_images
[which
]; } 
 776     int GetImage(size_t col
, wxTreeItemIcon which
=wxTreeItemIcon_Normal
) const 
 778         if(col 
== m_owner
->GetMainColumn()) return m_images
[which
]; 
 779         if(col 
< m_col_images
.GetCount()) return m_col_images
[col
]; 
 782     wxTreeItemData 
*GetData() const { return m_data
; } 
 784     // returns the current image for the item (depending on its 
 785     // selected/expanded/whatever state) 
 786     int GetCurrentImage() const; 
 788     void SetText( const wxString 
&text 
); 
 789     void SetText(size_t col
, const wxString
& text
) // ALB 
 791         if(col 
< m_text
.GetCount()) 
 793         else if(col 
< m_owner
->GetColumnCount()) { 
 794             int howmany 
= m_owner
->GetColumnCount(); 
 795             for(int i 
= m_text
.GetCount(); i 
< howmany
; ++i
) 
 796                 m_text
.Add(wxEmptyString
); 
 800     void SetImage(int image
, wxTreeItemIcon which
) { m_images
[which
] = image
; } 
 801     void SetImage(size_t col
, int image
, wxTreeItemIcon which
) 
 803         if(col 
== m_owner
->GetMainColumn()) m_images
[which
] = image
; 
 804         else if(col 
< m_col_images
.GetCount()) 
 805             m_col_images
[col
] = image
; 
 806         else if(col 
< m_owner
->GetColumnCount()) { 
 807             int howmany 
= m_owner
->GetColumnCount(); 
 808             for(int i 
= m_col_images
.GetCount(); i 
< howmany
; ++i
) 
 809                 m_col_images
.Add(NO_IMAGE
); 
 810             m_col_images
[col
] = image
; 
 814     void SetData(wxTreeItemData 
*data
) { m_data 
= data
; } 
 816     void SetHasPlus(bool has 
= TRUE
) { m_hasPlus 
= has
; } 
 818     void SetBold(bool bold
) { m_isBold 
= bold
; } 
 820     int GetX() const { return m_x
; } 
 821     int GetY() const { return m_y
; } 
 823     void SetX(int x
) { m_x 
= x
; } 
 824     void SetY(int y
) { m_y 
= y
; } 
 826     int  GetHeight() const { return m_height
; } 
 827     int  GetWidth()  const { return m_width
; } 
 829     void SetHeight(int h
) { m_height 
= h
; } 
 830     void SetWidth(int w
) { m_width 
= w
; } 
 832     wxTreeListItem 
*GetItemParent() const { return m_parent
; } 
 835     // deletes all children notifying the treectrl about it if !NULL 
 837     void DeleteChildren(wxTreeListMainWindow 
*tree 
= NULL
); 
 839     // get count of all children (and grand children if 'recursively') 
 840     size_t GetChildrenCount(bool recursively 
= TRUE
) const; 
 842     void Insert(wxTreeListItem 
*child
, size_t index
) 
 843     { m_children
.Insert(child
, index
); } 
 845     void GetSize( int &x
, int &y
, const wxTreeListMainWindow
* ); 
 847     // return the item at given position (or NULL if no item), onButton is 
 848     // TRUE if the point belongs to the item's button, otherwise it lies 
 849     // on the button's label 
 850     wxTreeListItem 
*HitTest( const wxPoint
& point
, 
 851                              const wxTreeListMainWindow 
*, 
 854     wxTreeListItem 
*HitTest( const wxPoint
& point
, 
 855                              const wxTreeListMainWindow 
*, 
 856                              int &flags
, int& column 
/*ALB*/, 
 859     void Expand() { m_isCollapsed 
= FALSE
; } 
 860     void Collapse() { m_isCollapsed 
= TRUE
; } 
 862     void SetHilight( bool set 
= TRUE 
) { m_hasHilight 
= set
; } 
 865     bool HasChildren() const { return !m_children
.IsEmpty(); } 
 866     bool IsSelected()  const { return m_hasHilight 
!= 0; } 
 867     bool IsExpanded()  const { return !m_isCollapsed
; } 
 868     bool HasPlus()     const { return m_hasPlus 
|| HasChildren(); } 
 869     bool IsBold()      const { return m_isBold 
!= 0; } 
 872     // get them - may be NULL 
 873     wxTreeItemAttr 
*GetAttributes() const { return m_attr
; } 
 874     // get them ensuring that the pointer is not NULL 
 875     wxTreeItemAttr
& Attr() 
 879             m_attr 
= new wxTreeItemAttr
; 
 885     void SetAttributes(wxTreeItemAttr 
*attr
) 
 887         if ( m_ownsAttr 
) delete m_attr
; 
 891     // set them and delete when done 
 892     void AssignAttributes(wxTreeItemAttr 
*attr
) 
 899     wxTreeListMainWindow  
*m_owner
;        // control the item belongs to 
 901     // since there can be very many of these, we save size by chosing 
 902     // the smallest representation for the elements and by ordering 
 903     // the members to avoid padding. 
 904     wxArrayString      m_text
;    // labels to be rendered for item 
 906     wxTreeItemData     
*m_data
;         // user-provided data 
 908     wxArrayTreeListItems m_children
; // list of children 
 909     wxTreeListItem  
*m_parent
;       // parent of this item 
 911     wxTreeItemAttr     
*m_attr
;         // attributes??? 
 913     // tree ctrl images for the normal, selected, expanded and 
 914     // expanded+selected states 
 915     short               m_images
[wxTreeItemIcon_Max
]; 
 916     wxArrayShort m_col_images
; // images for the various columns (!= main) 
 918     wxCoord             m_x
;            // (virtual) offset from top 
 919     wxCoord             m_y
;            // (virtual) offset from left 
 920     short               m_width
;        // width of this item 
 921     unsigned char       m_height
;       // height of this item 
 923     // use bitfields to save size 
 924     int                 m_isCollapsed 
:1; 
 925     int                 m_hasHilight  
:1; // same as focused 
 926     int                 m_hasPlus     
:1; // used for item which doesn't have 
 927                                           // children but has a [+] button 
 928     int                 m_isBold      
:1; // render the label in bold font 
 929     int                 m_ownsAttr    
:1; // delete attribute when done 
 932 // =========================================================================== 
 934 // =========================================================================== 
 936 // ---------------------------------------------------------------------------- 
 938 // ---------------------------------------------------------------------------- 
 940 // translate the key or mouse event flags to the type of selection we're 
 942 static void EventFlagsToSelType(long style
, 
 946                                 bool &extended_select
, 
 947                                 bool &unselect_others
) 
 949     is_multiple 
= (style 
& wxTR_MULTIPLE
) != 0; 
 950     extended_select 
= shiftDown 
&& is_multiple
; 
 951     unselect_others 
= !(extended_select 
|| (ctrlDown 
&& is_multiple
)); 
 954 // --------------------------------------------------------------------------- 
 955 // wxTreeListRenameTimer (internal) 
 956 // --------------------------------------------------------------------------- 
 958 wxTreeListRenameTimer::wxTreeListRenameTimer( wxTreeListMainWindow 
*owner 
) 
 963 void wxTreeListRenameTimer::Notify() 
 965     m_owner
->OnRenameTimer(); 
 968 //----------------------------------------------------------------------------- 
 969 // wxTreeListTextCtrl (internal) 
 970 //----------------------------------------------------------------------------- 
 972 BEGIN_EVENT_TABLE(wxTreeListTextCtrl
,wxTextCtrl
) 
 973     EVT_CHAR           (wxTreeListTextCtrl::OnChar
) 
 974     EVT_KEY_UP         (wxTreeListTextCtrl::OnKeyUp
) 
 975     EVT_KILL_FOCUS     (wxTreeListTextCtrl::OnKillFocus
) 
 978 wxTreeListTextCtrl::wxTreeListTextCtrl( wxWindow 
*parent
, 
 982                                         wxTreeListMainWindow 
*owner
, 
 983                                         const wxString 
&value
, 
 987                                         const wxValidator
& validator
, 
 988                                         const wxString 
&name 
) 
 989     : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name 
) 
 995     (*m_res
) = wxEmptyString
; 
 996     m_startValue 
= value
; 
1000 void wxTreeListTextCtrl::OnChar( wxKeyEvent 
&event 
) 
1002     if (event
.m_keyCode 
== WXK_RETURN
) 
1005         (*m_res
) = GetValue(); 
1007         if ((*m_res
) != m_startValue
) 
1008             m_owner
->OnRenameAccept(); 
1010         if (!wxPendingDelete
.Member(this)) 
1011             wxPendingDelete
.Append(this); 
1014         m_owner
->SetFocus(); // This doesn't work. TODO. 
1018     if (event
.m_keyCode 
== WXK_ESCAPE
) 
1020         (*m_accept
) = FALSE
; 
1021         (*m_res
) = wxEmptyString
; 
1023         if (!wxPendingDelete
.Member(this)) 
1024             wxPendingDelete
.Append(this); 
1027         m_owner
->SetFocus(); // This doesn't work. TODO. 
1034 void wxTreeListTextCtrl::OnKeyUp( wxKeyEvent 
&event 
) 
1042     // auto-grow the textctrl: 
1043     wxSize parentSize 
= m_owner
->GetSize(); 
1044     wxPoint myPos 
= GetPosition(); 
1045     wxSize mySize 
= GetSize(); 
1047     GetTextExtent(GetValue() + _T("M"), &sx
, &sy
); 
1048     if (myPos
.x 
+ sx 
> parentSize
.x
) sx 
= parentSize
.x 
- myPos
.x
; 
1049     if (mySize
.x 
> sx
) sx 
= mySize
.x
; 
1055 void wxTreeListTextCtrl::OnKillFocus( wxFocusEvent 
&event 
) 
1063     if (!wxPendingDelete
.Member(this)) 
1064         wxPendingDelete
.Append(this); 
1067     (*m_res
) = GetValue(); 
1069     if ((*m_res
) != m_startValue
) 
1070         m_owner
->OnRenameAccept(); 
1073 //----------------------------------------------------------------------------- 
1074 //  wxTreeListHeaderWindow 
1075 //----------------------------------------------------------------------------- 
1077 IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow
,wxWindow
); 
1079 BEGIN_EVENT_TABLE(wxTreeListHeaderWindow
,wxWindow
) 
1080     EVT_ERASE_BACKGROUND  (wxTreeListHeaderWindow::OnEraseBackground
) 
1081     EVT_PAINT             (wxTreeListHeaderWindow::OnPaint
) 
1082     EVT_MOUSE_EVENTS      (wxTreeListHeaderWindow::OnMouse
) 
1083     EVT_SET_FOCUS         (wxTreeListHeaderWindow::OnSetFocus
) 
1086 void wxTreeListHeaderWindow::Init() 
1088     m_currentCursor 
= (wxCursor 
*) NULL
; 
1089     m_isDragging 
= FALSE
; 
1091     m_total_col_width 
= 0; 
1094 wxTreeListHeaderWindow::wxTreeListHeaderWindow() 
1098     m_owner 
= (wxTreeListMainWindow 
*) NULL
; 
1099     m_resizeCursor 
= (wxCursor 
*) NULL
; 
1102 wxTreeListHeaderWindow::wxTreeListHeaderWindow( wxWindow 
*win
, 
1104                                                 wxTreeListMainWindow 
*owner
, 
1108                                                 const wxString 
&name 
) 
1109     : wxWindow( win
, id
, pos
, size
, style
, name 
) 
1114     m_resizeCursor 
= new wxCursor(wxCURSOR_SIZEWE
); 
1116     SetBackgroundColour(wxSystemSettings::GetColour( 
1117                             wxSYS_COLOUR_BTNFACE
)); 
1120 wxTreeListHeaderWindow::~wxTreeListHeaderWindow() 
1122     delete m_resizeCursor
; 
1125 void wxTreeListHeaderWindow::DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
) 
1128     GtkStateType state 
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
 
1129                                                : GTK_STATE_INSENSITIVE
; 
1131     x 
= dc
->XLOG2DEV( x 
); 
1133     gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
, 
1134                    state
, GTK_SHADOW_OUT
, 
1135                    (GdkRectangle
*) NULL
, m_wxwindow
, "button", 
1136                    x
-1, y
-1, w
+2, h
+2); 
1137 #elif defined( __WXMAC__  ) 
1138     const int m_corner 
= 1; 
1140     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1142     dc
->SetPen( wxPen(wxSystemSettings::GetColour( 
1143                           wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
)); 
1144     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
1145     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
1147     wxPen 
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID 
); 
1150     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
1151     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
1153     dc
->SetPen( *wxWHITE_PEN 
); 
1154     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
1155     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
1156     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
1157     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
1159     const int m_corner 
= 1; 
1161     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1163     dc
->SetPen( *wxBLACK_PEN 
); 
1164     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
1165     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
1167     wxPen 
pen(wxSystemSettings::GetColour( 
1168                   wxSYS_COLOUR_BTNSHADOW 
), 1, wxSOLID
); 
1171     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
1172     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
1174     dc
->SetPen( *wxWHITE_PEN 
); 
1175     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
1176     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
1177     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
1178     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
1182 // shift the DC origin to match the position of the main window horz 
1183 // scrollbar: this allows us to always use logical coords 
1184 void wxTreeListHeaderWindow::AdjustDC(wxDC
& dc
) 
1187     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1190     m_owner
->GetViewStart( &x
, NULL 
); 
1192     // account for the horz scrollbar offset 
1193     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1197 void wxTreeListHeaderWindow::OnEraseBackground( wxEraseEvent
& event 
) 
1201 void wxTreeListHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1204     wxClientDC 
real_dc( this ); 
1206     wxPaintDC 
real_dc( this ); 
1209     AdjustDC( real_dc 
); 
1211     // width and height of the entire header window 
1213     GetClientSize( &w
, &h 
); 
1214     m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1216     // Setup double buffering to eliminate the flicker 
1218     wxBitmap   
buffer(w
, h
); 
1219     dc
.SelectObject(buffer
); 
1220     dc
.SetBackground(wxBrush(GetBackgroundColour())); 
1224     dc
.SetFont( GetFont() ); 
1225     dc
.SetBackgroundMode(wxTRANSPARENT
); 
1227     // do *not* use the listctrl colour for headers - one day we will have a 
1228     // function to set it separately 
1229     //dc.SetTextForeground( *wxBLACK ); 
1230     dc
.SetTextForeground(wxSystemSettings:: 
1231                             GetColour( wxSYS_COLOUR_WINDOWTEXT 
)); 
1233     int x 
= HEADER_OFFSET_X
; 
1235     int numColumns 
= GetColumnCount(); 
1236     for ( int i 
= 0; i 
< numColumns 
&& x 
< w
; i
++ ) 
1238         if (!GetColumnShown (i
)) continue; 
1240         wxTreeListColumnInfo
& column 
= GetColumn(i
); 
1241         int wCol 
= column
.GetWidth(); 
1243         // the width of the rect to draw: make it smaller to fit entirely 
1244         // inside the column rect 
1247         dc
.SetPen( *wxWHITE_PEN 
); 
1249         //DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 ); 
1250         wxRendererNative::Get().DrawHeaderButton( 
1251             this, dc
, wxRect(x
, HEADER_OFFSET_Y
, cw
, h 
- 2), 
1252             m_parent
->IsEnabled() ? 0 : wxCONTROL_DISABLED
); 
1255         // if we have an image, draw it on the right of the label 
1256         int image 
= column
.GetImage(); //item.m_image; 
1257         int ix 
= -2, iy 
= 0; 
1258         wxImageList
* imageList 
= m_owner
->GetImageList(); 
1261                 imageList
->GetSize(image
, ix
, iy
); 
1263         //else: ignore the column image 
1268         int image_offset 
= cw 
- ix 
- 1; 
1270         switch(column
.GetAlignment()) { 
1271         case wxTL_ALIGN_LEFT
: 
1272             text_x 
+= EXTRA_WIDTH
; 
1275         case wxTL_ALIGN_RIGHT
: 
1276             dc
.GetTextExtent(column
.GetText(), &text_width
, NULL
); 
1277             text_x 
+= cw 
- text_width 
- EXTRA_WIDTH
; 
1280         case wxTL_ALIGN_CENTER
: 
1281             dc
.GetTextExtent(column
.GetText(), &text_width
, NULL
); 
1282             text_x 
+= (cw 
- text_width
)/2 + ix 
+ 2; 
1283             image_offset 
= (cw 
- text_width 
- ix 
- 2)/2; 
1288         if(image 
!= -1 && imageList
) { 
1289             imageList
->Draw(image
, dc
, x 
+ image_offset
/*cw - ix - 1*/, 
1290                             HEADER_OFFSET_Y 
+ (h 
- 4 - iy
)/2, 
1291                             wxIMAGELIST_DRAW_TRANSPARENT
); 
1294         // draw the text clipping it so that it doesn't overwrite the column 
1296         wxDCClipper 
clipper(dc
, x
, HEADER_OFFSET_Y
, cw
, h 
- 4 ); 
1298         dc
.DrawText( column
.GetText(), 
1299                      text_x
, HEADER_OFFSET_Y 
+ EXTRA_HEIGHT 
); 
1304     int more_w 
= m_owner
->GetSize().x 
- x 
-1; 
1307         //DoDrawRect( &dc, x, HEADER_OFFSET_Y, more_w, h-2 ); 
1308         wxRendererNative::Get().DrawHeaderButton( 
1309             this, dc
, wxRect(x
, HEADER_OFFSET_Y
, more_w
, h
-2), 
1310             m_parent
->IsEnabled() ? 0 : wxCONTROL_DISABLED
); 
1313     // Finish up by drawing the buffer to the real dc 
1315     dc
.SelectObject(wxNullBitmap
); 
1316     real_dc
.DrawBitmap(buffer
, 0, 0, false); 
1319 void wxTreeListHeaderWindow::DrawCurrent() 
1321     int x1 
= m_currentX
; 
1323     ClientToScreen( &x1
, &y1 
); 
1325     int x2 
= m_currentX
-1; 
1330     m_owner
->GetClientSize( NULL
, &y2 
); 
1331     m_owner
->ClientToScreen( &x2
, &y2 
); 
1334     dc
.SetLogicalFunction( wxINVERT 
); 
1335     dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID 
) ); 
1336     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
1340     dc
.DrawLine( x1
, y1
, x2
, y2 
); 
1342     dc
.SetLogicalFunction( wxCOPY 
); 
1344     dc
.SetPen( wxNullPen 
); 
1345     dc
.SetBrush( wxNullBrush 
); 
1348 void wxTreeListHeaderWindow::OnMouse( wxMouseEvent 
&event 
) 
1350     // we want to work with logical coords 
1352     m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
); 
1353     int y 
= event
.GetY(); 
1357         SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING
, 
1358                       event
.GetPosition()); 
1360         // we don't draw the line beyond our window, but we allow dragging it 
1363         GetClientSize( &w
, NULL 
); 
1364         m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1367         // erase the line if it was drawn 
1368         if ( m_currentX 
< w 
) 
1371         if (event
.ButtonUp()) 
1374             m_isDragging 
= FALSE
; 
1376             SetColumnWidth( m_column
, m_currentX 
- m_minX 
); 
1378             SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG
, 
1379                           event
.GetPosition()); 
1386                 m_currentX 
= m_minX 
+ 7; 
1388             // draw in the new location 
1389             if ( m_currentX 
< w 
) 
1393     else // not dragging 
1396         bool hit_border 
= FALSE
; 
1398         // end of the current column 
1401         // find the column where this event occured 
1402         int countCol 
= GetColumnCount(); 
1403         for (int col 
= 0; col 
< countCol
; col
++) 
1405             if (!GetColumnShown (col
)) continue; 
1406             xpos 
+= GetColumnWidth (col
); 
1409             if ( (abs(x
-xpos
) < 3) && (y 
< 22) ) 
1411                 // near the column border 
1418                 // inside the column 
1425         if (event
.LeftDown() || event
.RightUp()) 
1427             if (hit_border 
&& event
.LeftDown()) 
1429                 m_isDragging 
= TRUE
; 
1433                 SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
, 
1434                               event
.GetPosition()); 
1436             else // click on a column 
1438                 SendListEvent( event
.LeftDown() 
1439                                ? wxEVT_COMMAND_LIST_COL_CLICK
 
1440                                : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
, 
1441                                event
.GetPosition()); 
1444         else if (event
.Moving()) 
1449                 setCursor 
= m_currentCursor 
== wxSTANDARD_CURSOR
; 
1450                 m_currentCursor 
= m_resizeCursor
; 
1454                 setCursor 
= m_currentCursor 
!= wxSTANDARD_CURSOR
; 
1455                 m_currentCursor 
= wxSTANDARD_CURSOR
; 
1459                 SetCursor(*m_currentCursor
); 
1464 void wxTreeListHeaderWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1466     m_owner
->SetFocus(); 
1469 void wxTreeListHeaderWindow::SendListEvent(wxEventType type
, wxPoint pos
) 
1471     wxWindow 
*parent 
= GetParent(); 
1472     wxListEvent 
le( type
, parent
->GetId() ); 
1473     le
.SetEventObject( parent 
); 
1474     le
.m_pointDrag 
= pos
; 
1476     // the position should be relative to the parent window, not 
1477     // this one for compatibility with MSW and common sense: the 
1478     // user code doesn't know anything at all about this header 
1479     // window, so why should it get positions relative to it? 
1480     le
.m_pointDrag
.y 
-= GetSize().y
; 
1482     le
.m_col 
= m_column
; 
1483     parent
->GetEventHandler()->ProcessEvent( le 
); 
1486 void wxTreeListHeaderWindow::AddColumn(const wxTreeListColumnInfo
& col
) 
1489     m_total_col_width 
+= col
.GetWidth(); 
1490     //m_owner->GetHeaderWindow()->Refresh(); 
1492     m_owner
->AdjustMyScrollbars(); 
1493     m_owner
->m_dirty 
= TRUE
; 
1497 void wxTreeListHeaderWindow::SetColumnWidth(size_t column
, size_t width
) 
1499     if(column 
< GetColumnCount()) { 
1500         m_total_col_width 
-= m_columns
[column
].GetWidth(); 
1501         m_columns
[column
].SetWidth(width
); 
1502         m_total_col_width 
+= width
; 
1503         m_owner
->AdjustMyScrollbars(); 
1504         m_owner
->m_dirty 
= TRUE
; 
1511 void wxTreeListHeaderWindow::InsertColumn(size_t before
, 
1512                                           const wxTreeListColumnInfo
& col
) 
1514     wxCHECK_RET(before 
< GetColumnCount(), wxT("Invalid column index")); 
1515     m_columns
.Insert(col
, before
); 
1516     m_total_col_width 
+= col
.GetWidth(); 
1518     //m_owner->GetHeaderWindow()->Refresh(); 
1519     m_owner
->AdjustMyScrollbars(); 
1520     m_owner
->m_dirty 
= TRUE
; 
1524 void wxTreeListHeaderWindow::RemoveColumn(size_t column
) 
1526     wxCHECK_RET(column 
< GetColumnCount(), wxT("Invalid column")); 
1527     m_total_col_width 
-= m_columns
[column
].GetWidth(); 
1528     m_columns
.RemoveAt(column
); 
1530     m_owner
->AdjustMyScrollbars(); 
1531     m_owner
->m_dirty 
= TRUE
; 
1535 void wxTreeListHeaderWindow::SetColumn(size_t column
, 
1536                                        const wxTreeListColumnInfo
& info
) 
1538     wxCHECK_RET(column 
< GetColumnCount(), wxT("Invalid column")); 
1539     size_t w 
= m_columns
[column
].GetWidth(); 
1540     m_columns
[column
] = info
; 
1541     //m_owner->GetHeaderWindow()->Refresh(); 
1543     if(w 
!= info
.GetWidth()) { 
1544         m_total_col_width 
+= info
.GetWidth() - w
; 
1545         m_owner
->AdjustMyScrollbars(); 
1546         m_owner
->m_dirty 
= TRUE
; 
1551 // --------------------------------------------------------------------------- 
1553 // --------------------------------------------------------------------------- 
1555 wxTreeListItem::wxTreeListItem(wxTreeListMainWindow 
*owner
, 
1556                                      wxTreeListItem 
*parent
, 
1557                                      const wxArrayString
& text
, 
1558                                      int image
, int selImage
, 
1559                                      wxTreeItemData 
*data
) 
1562     m_images
[wxTreeItemIcon_Normal
] = image
; 
1563     m_images
[wxTreeItemIcon_Selected
] = selImage
; 
1564     m_images
[wxTreeItemIcon_Expanded
] = NO_IMAGE
; 
1565     m_images
[wxTreeItemIcon_SelectedExpanded
] = NO_IMAGE
; 
1570     m_isCollapsed 
= TRUE
; 
1571     m_hasHilight 
= FALSE
; 
1579     m_attr 
= (wxTreeItemAttr 
*)NULL
; 
1582     // We don't know the height here yet. 
1587 wxTreeListItem::~wxTreeListItem() 
1591     if (m_ownsAttr
) delete m_attr
; 
1593     wxASSERT_MSG( m_children
.IsEmpty(), 
1594                   wxT("please call DeleteChildren() before deleting the item") ); 
1597 void wxTreeListItem::DeleteChildren(wxTreeListMainWindow 
*tree
) 
1599     size_t count 
= m_children
.Count(); 
1600     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1602         wxTreeListItem 
*child 
= m_children
[n
]; 
1604             tree
->SendDeleteEvent(child
); 
1606         child
->DeleteChildren(tree
); 
1613 void wxTreeListItem::SetText( const wxString 
&text 
) 
1615     if(m_text
.GetCount() > 0) m_text
[0] = text
; 
1621 size_t wxTreeListItem::GetChildrenCount(bool recursively
) const 
1623     size_t count 
= m_children
.Count(); 
1627     size_t total 
= count
; 
1628     for (size_t n 
= 0; n 
< count
; ++n
) 
1630         total 
+= m_children
[n
]->GetChildrenCount(); 
1636 void wxTreeListItem::GetSize( int &x
, int &y
, 
1637                                  const wxTreeListMainWindow 
*theButton 
) 
1639     int bottomY
=m_y
+theButton
->GetLineHeight(this); 
1640     if ( y 
< bottomY 
) y 
= bottomY
; 
1641     int width 
= m_x 
+  m_width
; 
1642     if ( x 
< width 
) x 
= width
; 
1646         size_t count 
= m_children
.Count(); 
1647         for ( size_t n 
= 0; n 
< count
; ++n 
) 
1649             m_children
[n
]->GetSize( x
, y
, theButton 
); 
1654 wxTreeListItem 
*wxTreeListItem::HitTest(const wxPoint
& point
, 
1655                                         const wxTreeListMainWindow 
*theCtrl
, 
1659     // for a hidden root node, don't evaluate it, but do evaluate children 
1660     if (!(theCtrl
->HasFlag(wxTR_HIDE_ROOT
) && (level 
== 0))) 
1662         // evaluate the item 
1663         int h 
= theCtrl
->GetLineHeight(this); 
1664         if ((point
.y 
> m_y
) && (point
.y 
<= m_y 
+ h
)) 
1666             // check for above/below middle 
1667             int y_mid 
= m_y 
+ h
/2; 
1668             if (point
.y 
< y_mid 
) 
1669                 flags 
|= wxTREE_HITTEST_ONITEMUPPERPART
; 
1671                 flags 
|= wxTREE_HITTEST_ONITEMLOWERPART
; 
1673             // check for button hit 
1674             int xCross 
= m_x
; // - theCtrl->GetLineSpacing(); 
1676             // according to the drawing code the triangels are drawn 
1677             // at -4 , -4  from the position up to +10/+10 max 
1678             if ((point
.x 
> xCross
-4) && (point
.x 
< xCross
+10) && 
1679                 (point
.y 
> y_mid
-4) && (point
.y 
< y_mid
+10) && 
1680                 HasPlus() && theCtrl
->HasButtons() ) 
1682             // 5 is the size of the plus sign 
1683             if ((point
.x 
> xCross
-6) && (point
.x 
< xCross
+6) && 
1684                 (point
.y 
> y_mid
-6) && (point
.y 
< y_mid
+6) && 
1685                 HasPlus() && theCtrl
->HasButtons() ) 
1688                 flags 
|= wxTREE_HITTEST_ONITEMBUTTON
; 
1692             // check for image hit 
1693             if (theCtrl
->m_imgWidth 
> 0 && GetImage() != NO_IMAGE
) { 
1694                 int imgX 
= m_x 
- theCtrl
->m_imgWidth2
; 
1695                 if (HasPlus() && theCtrl
->HasButtons()) 
1696                     imgX 
+= theCtrl
->m_btnWidth 
+ LINEATROOT
; 
1697                 int imgY 
= y_mid 
- theCtrl
->m_imgHeight2
; 
1698                 if ((point
.x 
>= imgX
) && (point
.x 
<= (imgX 
+ theCtrl
->m_imgWidth
)) && 
1699                     (point
.y 
>= imgY
) && (point
.y 
<= (imgY 
+ theCtrl
->m_imgHeight
))) { 
1700                     flags 
|= wxTREE_HITTEST_ONITEMICON
; 
1705             // check for label hit 
1706             int lblX 
= m_x 
- theCtrl
->m_imgWidth2 
+ theCtrl
->m_imgWidth 
+ MARGIN
; 
1707             if ((point
.x 
>= lblX
) && (point
.x 
<= (m_x 
+ m_width
)) && 
1708                 (point
.y 
>= m_y
) && (point
.y 
<= (m_y 
+ h
))) { 
1709                 flags 
|= wxTREE_HITTEST_ONITEMLABEL
; 
1713             // else check for indent 
1714             if (point
.x 
< m_x
) { 
1715                 flags 
|= wxTREE_HITTEST_ONITEMINDENT
; 
1719             // else check for item right??? 
1720             if (point
.x 
> m_x 
+ m_width
) { 
1721                 flags 
|= wxTREE_HITTEST_ONITEMRIGHT
; 
1727         // if children are expanded, fall through to evaluate them 
1728         if (m_isCollapsed
) return (wxTreeListItem
*) NULL
; 
1731     // evaluate children 
1732     size_t count 
= m_children
.Count(); 
1733     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1735         wxTreeListItem 
*res 
= m_children
[n
]->HitTest(point
, theCtrl
, 
1741     return (wxTreeListItem
*) NULL
; 
1745 wxTreeListItem 
*wxTreeListItem::HitTest(const wxPoint
& point
, 
1746                                         const wxTreeListMainWindow 
*theCtrl
, 
1747                                         int &flags
, int& column
, int level
) 
1749     column 
= theCtrl
->GetMainColumn(); //-1; 
1751     wxTreeListItem
* res 
= HitTest(point
, theCtrl
, flags
, level
); 
1757     wxTreeListHeaderWindow
* header_win 
= theCtrl
->m_owner
->GetHeaderWindow(); 
1758     if (point
.x 
>= header_win
->GetWidth()) 
1760     else if(flags 
& wxTREE_HITTEST_ONITEMINDENT
) { 
1762         for(size_t i 
= 0; i 
< theCtrl
->GetMainColumn(); ++i
) { 
1763             if (!header_win
->GetColumnShown(i
)) continue; 
1764             int w 
= header_win
->GetColumnWidth(i
); 
1765             if(point
.x 
>= x 
&& point
.x 
< x
+w
) { 
1766                 flags 
^= wxTREE_HITTEST_ONITEMINDENT
; 
1767                 flags 
|= wxTREE_HITTEST_ONITEMCOLUMN
; 
1773     else if(flags 
& wxTREE_HITTEST_ONITEMRIGHT
) { 
1776         for(i 
= 0; i 
< theCtrl
->GetMainColumn()+1; ++i
) { 
1777             if (!header_win
->GetColumnShown(i
)) continue; 
1778             x 
+= header_win
->GetColumnWidth(i
); 
1780         for(i 
= theCtrl
->GetMainColumn()+1; i 
< theCtrl
->GetColumnCount(); ++i
) { 
1781             if (!header_win
->GetColumnShown(i
)) continue; 
1782             int w 
= header_win
->GetColumnWidth(i
); 
1783             if(point
.x 
>= x 
&& point
.x 
< x
+w
) { 
1784                 flags 
^= wxTREE_HITTEST_ONITEMRIGHT
; 
1785                 flags 
|= wxTREE_HITTEST_ONITEMCOLUMN
; 
1797 int wxTreeListItem::GetCurrentImage() const 
1799     int image 
= NO_IMAGE
; 
1804             image 
= GetImage(wxTreeItemIcon_SelectedExpanded
); 
1807         if ( image 
== NO_IMAGE 
) 
1809             // we usually fall back to the normal item, but try just the 
1810             // expanded one (and not selected) first in this case 
1811             image 
= GetImage(wxTreeItemIcon_Expanded
); 
1814     else // not expanded 
1817             image 
= GetImage(wxTreeItemIcon_Selected
); 
1820     // maybe it doesn't have the specific image we want, 
1821     // try the default one instead 
1822     if ( image 
== NO_IMAGE 
) image 
= GetImage(); 
1827 // --------------------------------------------------------------------------- 
1828 // wxTreeListMainWindow implementation 
1829 // --------------------------------------------------------------------------- 
1831 IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow
, wxScrolledWindow
) 
1833 BEGIN_EVENT_TABLE(wxTreeListMainWindow
, wxScrolledWindow
) 
1834     EVT_PAINT          (wxTreeListMainWindow::OnPaint
) 
1835     EVT_MOUSE_EVENTS   (wxTreeListMainWindow::OnMouse
) 
1836     EVT_CHAR           (wxTreeListMainWindow::OnChar
) 
1837     EVT_SET_FOCUS      (wxTreeListMainWindow::OnSetFocus
) 
1838     EVT_KILL_FOCUS     (wxTreeListMainWindow::OnKillFocus
) 
1839     EVT_IDLE           (wxTreeListMainWindow::OnIdle
) 
1840     EVT_SCROLLWIN      (wxTreeListMainWindow::OnScroll
) 
1844 // --------------------------------------------------------------------------- 
1845 // construction/destruction 
1846 // --------------------------------------------------------------------------- 
1848 void wxTreeListMainWindow::Init() 
1850     m_current 
= m_key_current 
= m_anchor 
= (wxTreeListItem 
*) NULL
; 
1854     m_lineHeight 
= LINEHEIGHT
; 
1855     m_indent 
= MININDENT
; // min. indent 
1857     m_imgWidth 
= 0, m_imgWidth2 
= 0; 
1858     m_imgHeight 
= 0, m_imgHeight2 
= 0; 
1860     m_hilightBrush 
= new wxBrush
 
1862                             wxSystemSettings::GetColour
 
1864                                 wxSYS_COLOUR_HIGHLIGHT
 
1869     m_hilightUnfocusedBrush 
= new wxBrush
 
1871                                  wxSystemSettings::GetColour
 
1873                                      wxSYS_COLOUR_BTNSHADOW
 
1878     m_imageListNormal 
= m_imageListButtons 
= 
1879     m_imageListState 
= (wxImageList 
*) NULL
; 
1880     m_ownsImageListNormal 
= m_ownsImageListButtons 
= 
1881     m_ownsImageListState 
= FALSE
; 
1884     m_isDragging 
= FALSE
; 
1885     m_dropTarget 
= m_oldSelection 
= (wxTreeListItem 
*)NULL
; 
1887     m_renameTimer 
= new wxTreeListRenameTimer( this ); 
1888     m_lastOnSame 
= FALSE
; 
1890     m_findTimer 
= new wxTimer (this, -1); 
1892     m_underMouse 
= NULL
; 
1894 #if defined( __WXMAC__ ) && defined(__WXMAC_CARBON__) 
1895     m_normalFont
.MacCreateThemeFont( kThemeViewsFont 
) ; 
1897     m_normalFont 
= wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT 
); 
1899     m_boldFont 
= wxFont( m_normalFont
.GetPointSize(), 
1900                          m_normalFont
.GetFamily(), 
1901                          m_normalFont
.GetStyle(), 
1903                          m_normalFont
.GetUnderlined(), 
1904                          m_normalFont
.GetFaceName(), 
1905                          m_normalFont
.GetEncoding()); 
1909 bool wxTreeListMainWindow::Create(wxTreeListCtrl 
*parent
, 
1914                                   const wxValidator 
&validator
, 
1915                                   const wxString
& name 
) 
1918     if ( !(style 
& wxTR_DONT_ADJUST_MAC
)) 
1921         wxGetOsVersion( &major
, &minor 
); 
1923         if (style 
& wxTR_HAS_BUTTONS
) style 
|= wxTR_TWIST_BUTTONS
; 
1924         if (style 
& wxTR_HAS_BUTTONS
) style 
&= ~wxTR_HAS_BUTTONS
; 
1925         style 
&= ~wxTR_LINES_AT_ROOT
; 
1926         style 
|= wxTR_NO_LINES
; 
1928             style 
|= wxTR_ROW_LINES
; 
1932     wxScrolledWindow::Create( parent
, id
, pos
, size
, 
1933                               style
|wxHSCROLL
|wxVSCROLL
, name 
); 
1935 #if wxUSE_VALIDATORS 
1936     SetValidator( validator 
); 
1939     SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_LISTBOX 
) ); 
1946         bdc
.SelectObject(bmp
); 
1947         bdc
.SetPen(*wxGREY_PEN
); 
1948         bdc
.DrawRectangle(-1, -1, 10, 10); 
1949         for (i 
= 0; i 
< 8; i
++) { 
1950             for (j 
= 0; j 
< 8; j
++) { 
1951                 if (!((i 
+ j
) & 1)) { 
1952                     bdc
.DrawPoint(i
, j
); 
1957         m_dottedPen 
= wxPen(bmp
, 1); 
1960     //m_dottedPen = wxPen( *wxGREY_PEN, 1, wxDOT );  // too slow under XFree86 
1961     m_dottedPen 
= wxPen( wxT("grey"), 0, 0 ); // Bitmap based pen is not supported by GTK! 
1971 wxTreeListMainWindow::~wxTreeListMainWindow() 
1973     delete m_hilightBrush
; 
1974     delete m_hilightUnfocusedBrush
; 
1978     delete m_renameTimer
; 
1980     if (m_ownsImageListNormal
) delete m_imageListNormal
; 
1981     if (m_ownsImageListState
) delete m_imageListState
; 
1982     if (m_ownsImageListButtons
) delete m_imageListButtons
; 
1987 //----------------------------------------------------------------------------- 
1989 //----------------------------------------------------------------------------- 
1991 size_t wxTreeListMainWindow::GetCount() const 
1993     return m_anchor 
== NULL 
? 0u : m_anchor
->GetChildrenCount(); 
1996 void wxTreeListMainWindow::SetIndent(unsigned int indent
) 
2002 void wxTreeListMainWindow::SetLineSpacing(unsigned int spacing
) 
2004     m_linespacing 
= spacing
; 
2006     CalculateLineHeight(); 
2009 size_t wxTreeListMainWindow::GetChildrenCount(const wxTreeItemId
& item
, 
2012     wxCHECK_MSG( item
.IsOk(), 0u, wxT("invalid tree item") ); 
2014     return ((wxTreeListItem
*) item
.m_pItem
)->GetChildrenCount(recursively
); 
2017 void wxTreeListMainWindow::SetWindowStyle(const long styles
) 
2019     // right now, just sets the styles.  Eventually, we may 
2020     // want to update the inherited styles, but right now 
2021     // none of the parents has updatable styles 
2022     m_windowStyle 
= styles
; 
2026 //----------------------------------------------------------------------------- 
2027 // functions to work with tree items 
2028 //----------------------------------------------------------------------------- 
2030 int wxTreeListMainWindow::GetItemImage(const wxTreeItemId
& item
, size_t column
, 
2031                                        wxTreeItemIcon which
) const 
2033     wxCHECK_MSG( item
.IsOk(), -1, wxT("invalid tree item") ); 
2035     return ((wxTreeListItem
*) item
.m_pItem
)->GetImage(column
, which
); 
2038 wxTreeItemData 
*wxTreeListMainWindow::GetItemData(const wxTreeItemId
& item
) 
2041     wxCHECK_MSG( item
.IsOk(), NULL
, wxT("invalid tree item") ); 
2043     return ((wxTreeListItem
*) item
.m_pItem
)->GetData(); 
2046 bool wxTreeListMainWindow::GetItemBold(const wxTreeItemId
& item
) const 
2048     wxCHECK_MSG(item
.IsOk(), FALSE
, wxT("invalid tree item")); 
2049     return ((wxTreeListItem 
*)item
.m_pItem
)->IsBold(); 
2052 wxColour 
wxTreeListMainWindow::GetItemTextColour(const wxTreeItemId
& item
) 
2055     wxCHECK_MSG( item
.IsOk(), wxNullColour
, wxT("invalid tree item") ); 
2057     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2058     return pItem
->Attr().GetTextColour(); 
2061 wxColour 
wxTreeListMainWindow::GetItemBackgroundColour( 
2062     const wxTreeItemId
& item
) const 
2064     wxCHECK_MSG( item
.IsOk(), wxNullColour
, wxT("invalid tree item") ); 
2066     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2067     return pItem
->Attr().GetBackgroundColour(); 
2070 wxFont 
wxTreeListMainWindow::GetItemFont(const wxTreeItemId
& item
) const 
2072     wxCHECK_MSG( item
.IsOk(), wxNullFont
, wxT("invalid tree item") ); 
2074     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2075     return pItem
->Attr().GetFont(); 
2080 void wxTreeListMainWindow::SetItemImage(const wxTreeItemId
& item
, 
2082                                         int image
, wxTreeItemIcon which
) 
2084     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2086     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2087     pItem
->SetImage(column
, image
, which
); 
2089     wxClientDC 
dc(this); 
2090     CalculateSize(pItem
, dc
); 
2094 void wxTreeListMainWindow::SetItemData(const wxTreeItemId
& item
, 
2095                                        wxTreeItemData 
*data
) 
2097     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2099     ((wxTreeListItem
*) item
.m_pItem
)->SetData(data
); 
2102 void wxTreeListMainWindow::SetItemHasChildren(const wxTreeItemId
& item
, 
2105     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2107     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2108     pItem
->SetHasPlus(has
); 
2112 void wxTreeListMainWindow::SetItemBold(const wxTreeItemId
& item
, bool bold
) 
2114     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2116     // avoid redrawing the tree if no real change 
2117     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2118     if ( pItem
->IsBold() != bold 
) 
2120         pItem
->SetBold(bold
); 
2125 void wxTreeListMainWindow::SetItemTextColour(const wxTreeItemId
& item
, 
2126                                              const wxColour
& col
) 
2128     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2130     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2131     pItem
->Attr().SetTextColour(col
); 
2135 void wxTreeListMainWindow::SetItemBackgroundColour(const wxTreeItemId
& item
, 
2136                                                    const wxColour
& col
) 
2138     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2140     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2141     pItem
->Attr().SetBackgroundColour(col
); 
2145 void wxTreeListMainWindow::SetItemFont(const wxTreeItemId
& item
, 
2148     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2150     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2151     pItem
->Attr().SetFont(font
); 
2155 bool wxTreeListMainWindow::SetFont( const wxFont 
&font 
) 
2157     wxScrolledWindow::SetFont(font
); 
2159     m_normalFont 
= font 
; 
2160     m_boldFont 
= wxFont( m_normalFont
.GetPointSize(), 
2161                             m_normalFont
.GetFamily(), 
2162                             m_normalFont
.GetStyle(), 
2164                             m_normalFont
.GetUnderlined()); 
2170 // ---------------------------------------------------------------------------- 
2171 // item status inquiries 
2172 // ---------------------------------------------------------------------------- 
2174 bool wxTreeListMainWindow::IsVisible(const wxTreeItemId
& item
) const 
2176     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2178     // An item is only visible if it's not a descendant of a collapsed item 
2179     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2180     wxTreeListItem
* parent 
= pItem
->GetItemParent(); 
2183         if (!parent
->IsExpanded()) 
2185         parent 
= parent
->GetItemParent(); 
2189     GetViewStart(& startX
, & startY
); 
2191     wxSize clientSize 
= GetClientSize(); 
2194     if (!GetBoundingRect(item
, rect
)) 
2196     if (rect
.GetWidth() == 0 || rect
.GetHeight() == 0) 
2198     if (rect
.GetBottom() < 0 || rect
.GetTop() > clientSize
.y
) 
2200     if (rect
.GetRight() < 0 || rect
.GetLeft() > clientSize
.x
) 
2206 bool wxTreeListMainWindow::ItemHasChildren(const wxTreeItemId
& item
) const 
2208     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2210     // consider that the item does have children if it has the "+" button: it 
2211     // might not have them (if it had never been expanded yet) but then it 
2212     // could have them as well and it's better to err on this side rather than 
2213     // disabling some operations which are restricted to the items with 
2214     // children for an item which does have them 
2215     return ((wxTreeListItem
*) item
.m_pItem
)->HasPlus(); 
2218 bool wxTreeListMainWindow::IsExpanded(const wxTreeItemId
& item
) const 
2220     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2222     return ((wxTreeListItem
*) item
.m_pItem
)->IsExpanded(); 
2225 bool wxTreeListMainWindow::IsSelected(const wxTreeItemId
& item
) const 
2227     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2229     return ((wxTreeListItem
*) item
.m_pItem
)->IsSelected(); 
2232 bool wxTreeListMainWindow::IsBold(const wxTreeItemId
& item
) const 
2234     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2236     return ((wxTreeListItem
*) item
.m_pItem
)->IsBold(); 
2239 // ---------------------------------------------------------------------------- 
2241 // ---------------------------------------------------------------------------- 
2243 wxTreeItemId 
wxTreeListMainWindow::GetItemParent(const wxTreeItemId
& item
) const 
2245     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2247     return ((wxTreeListItem
*) item
.m_pItem
)->GetItemParent(); 
2250 #if !wxCHECK_VERSION(2, 5, 0) 
2251 wxTreeItemId 
wxTreeListMainWindow::GetFirstChild(const wxTreeItemId
& item
, 
2254 wxTreeItemId 
wxTreeListMainWindow::GetFirstChild(const wxTreeItemId
& item
, 
2255                                                  wxTreeItemIdValue
& cookie
) const 
2258     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2261     return GetNextChild(item
, cookie
); 
2264 #if !wxCHECK_VERSION(2, 5, 0) 
2265 wxTreeItemId 
wxTreeListMainWindow::GetNextChild(const wxTreeItemId
& item
, 
2268 wxTreeItemId 
wxTreeListMainWindow::GetNextChild(const wxTreeItemId
& item
, 
2269                                                 wxTreeItemIdValue
& cookie
) const 
2272     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2274     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2276     // it's ok to cast cookie to size_t, we never have indices big enough to 
2277     // overflow "void *" 
2278     size_t *pIndex 
= (size_t *)&cookie
; 
2279     if ( *pIndex 
< children
.Count() ) 
2281         return children
.Item((*pIndex
)++); 
2285         // there are no more of them 
2286         return wxTreeItemId(); 
2290 #if !wxCHECK_VERSION(2, 5, 0) 
2291 wxTreeItemId 
wxTreeListMainWindow::GetPrevChild(const wxTreeItemId
& item
, 
2294 wxTreeItemId 
wxTreeListMainWindow::GetPrevChild(const wxTreeItemId
& item
, 
2295                                                 wxTreeItemIdValue
& cookie
) const 
2298     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2300     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2302     // it's ok to cast cookie to size_t, we never have indices big enough to 
2303     // overflow "void *" 
2304     size_t *pIndex 
= (size_t *)&cookie
; 
2307         return children
.Item(--(*pIndex
)); 
2311         // there are no more of them 
2312         return wxTreeItemId(); 
2316 wxTreeItemId 
wxTreeListMainWindow::GetLastChild(const wxTreeItemId
& item
) const 
2318     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2320     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2321     return (children
.IsEmpty() ? wxTreeItemId() : wxTreeItemId(children
.Last())); 
2324 wxTreeItemId 
wxTreeListMainWindow::GetNextSibling(const wxTreeItemId
& item
) const 
2326     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2328     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2329     wxTreeListItem 
*parent 
= i
->GetItemParent(); 
2330     if ( parent 
== NULL 
) 
2332         // root item doesn't have any siblings 
2333         return wxTreeItemId(); 
2336     wxArrayTreeListItems
& siblings 
= parent
->GetChildren(); 
2337     int index 
= siblings
.Index(i
); 
2338     wxASSERT( index 
!= wxNOT_FOUND 
); // I'm not a child of my parent? 
2340     size_t n 
= (size_t)(index 
+ 1); 
2341     return n 
== siblings
.Count() ? wxTreeItemId() : wxTreeItemId(siblings
[n
]); 
2344 wxTreeItemId 
wxTreeListMainWindow::GetPrevSibling(const wxTreeItemId
& item
) 
2347     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2349     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2350     wxTreeListItem 
*parent 
= i
->GetItemParent(); 
2351     if ( parent 
== NULL 
) 
2353         // root item doesn't have any siblings 
2354         return wxTreeItemId(); 
2357     wxArrayTreeListItems
& siblings 
= parent
->GetChildren(); 
2358     int index 
= siblings
.Index(i
); 
2359     wxASSERT( index 
!= wxNOT_FOUND 
); // I'm not a child of my parent? 
2361     return index 
== 0 ? wxTreeItemId() 
2362                       : wxTreeItemId(siblings
[(size_t)(index 
- 1)]); 
2365 // Only for internal use right now, but should probably be public 
2366 wxTreeItemId 
wxTreeListMainWindow::GetNext(const wxTreeItemId
& item
) const 
2368     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2370     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2372     // First see if there are any children. 
2373     wxArrayTreeListItems
& children 
= i
->GetChildren(); 
2374     if (children
.GetCount() > 0) 
2376          return children
.Item(0); 
2380          // Try a sibling of this or ancestor instead 
2381          wxTreeItemId p 
= item
; 
2382          wxTreeItemId toFind
; 
2385               toFind 
= GetNextSibling(p
); 
2386               p 
= GetItemParent(p
); 
2387          } while (p
.IsOk() && !toFind
.IsOk()); 
2392 wxTreeItemId 
wxTreeListMainWindow::GetFirstVisibleItem() const 
2394     wxTreeItemId id 
= GetRootItem(); 
2403     } while (id
.IsOk()); 
2405     return wxTreeItemId(); 
2408 wxTreeItemId 
wxTreeListMainWindow::GetNextVisible(const wxTreeItemId
& item
) 
2411     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2413     wxTreeItemId id 
= item
; 
2416         while (id 
= GetNext(id
), id
.IsOk()) 
2422     return wxTreeItemId(); 
2425 wxTreeItemId 
wxTreeListMainWindow::GetPrevVisible(const wxTreeItemId
& item
) 
2428     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2430     wxFAIL_MSG(wxT("not implemented")); 
2432     return wxTreeItemId(); 
2435 // ---------------------------------------------------------------------------- 
2437 // ---------------------------------------------------------------------------- 
2439 wxTreeItemId 
wxTreeListMainWindow::DoInsertItem(const wxTreeItemId
& parentId
, 
2441                                       const wxString
& text
, 
2442                                       int image
, int selImage
, 
2443                                       wxTreeItemData 
*data
) 
2445     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2448         // should we give a warning here? 
2449         return AddRoot(text
, image
, selImage
, data
); 
2452     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2456     arr
.Alloc(GetColumnCount()); 
2457     for(size_t i 
= 0; i 
< GetColumnCount(); ++i
) { 
2458         arr
.Add(wxEmptyString
); 
2460     arr
[m_main_column
] = text
; 
2461     wxTreeListItem 
*item 
= 
2462         new wxTreeListItem( this, parent
, arr
, image
, selImage
, data 
); 
2466         data
->SetId((long)item
); 
2469     parent
->Insert( item
, previous 
); 
2474 wxTreeItemId 
wxTreeListMainWindow::AddRoot(const wxString
& text
, 
2475                                  int image
, int selImage
, 
2476                                  wxTreeItemData 
*data
) 
2478     wxCHECK_MSG(!m_anchor
, wxTreeItemId(), wxT("tree can have only one root")); 
2479     wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), wxT("Add column(s) before adding the root item")); 
2481     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2485     arr
.Alloc(GetColumnCount()); 
2486     for(size_t i 
= 0; i 
< GetColumnCount(); ++i
) { 
2487         arr
.Add(wxEmptyString
); 
2489     arr
[m_main_column
] = text
; 
2490     m_anchor 
= new wxTreeListItem( this, (wxTreeListItem 
*)NULL
, arr
, 
2491                                       image
, selImage
, data
); 
2493     if (HasFlag(wxTR_HIDE_ROOT
)) 
2495         // if root is hidden, make sure we can navigate 
2497         m_anchor
->SetHasPlus(); 
2503         data
->SetId((long)m_anchor
); 
2506     if (!HasFlag(wxTR_MULTIPLE
)) 
2508         m_current 
= m_key_current 
= m_anchor
; 
2509         m_current
->SetHilight( TRUE 
); 
2515 wxTreeItemId 
wxTreeListMainWindow::PrependItem(const wxTreeItemId
& parent
, 
2516                                      const wxString
& text
, 
2517                                      int image
, int selImage
, 
2518                                      wxTreeItemData 
*data
) 
2520     return DoInsertItem(parent
, 0u, text
, image
, selImage
, data
); 
2523 wxTreeItemId 
wxTreeListMainWindow::InsertItem(const wxTreeItemId
& parentId
, 
2524                                     const wxTreeItemId
& idPrevious
, 
2525                                     const wxString
& text
, 
2526                                     int image
, int selImage
, 
2527                                     wxTreeItemData 
*data
) 
2529     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2532         // should we give a warning here? 
2533         return AddRoot(text
, image
, selImage
, data
); 
2536     int index 
= parent
->GetChildren().Index((wxTreeListItem
*) idPrevious
.m_pItem
); 
2537     wxASSERT_MSG( index 
!= wxNOT_FOUND
, 
2538                   wxT("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") ); 
2540     return DoInsertItem(parentId
, (size_t)++index
, text
, image
, selImage
, data
); 
2543 wxTreeItemId 
wxTreeListMainWindow::InsertItem(const wxTreeItemId
& parentId
, 
2545                                     const wxString
& text
, 
2546                                     int image
, int selImage
, 
2547                                     wxTreeItemData 
*data
) 
2549     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2552         // should we give a warning here? 
2553         return AddRoot(text
, image
, selImage
, data
); 
2556     return DoInsertItem(parentId
, before
, text
, image
, selImage
, data
); 
2559 wxTreeItemId 
wxTreeListMainWindow::AppendItem(const wxTreeItemId
& parentId
, 
2560                                     const wxString
& text
, 
2561                                     int image
, int selImage
, 
2562                                     wxTreeItemData 
*data
) 
2564     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2567         // should we give a warning here? 
2568         return AddRoot(text
, image
, selImage
, data
); 
2571     return DoInsertItem( parent
, parent
->GetChildren().Count(), text
, 
2572                          image
, selImage
, data
); 
2575 void wxTreeListMainWindow::SendDeleteEvent(wxTreeListItem 
*item
) 
2577     wxTreeEvent 
event( wxEVT_COMMAND_TREE_DELETE_ITEM
, m_owner
->GetId() ); 
2578     event
.SetItem((long) item
); 
2579     event
.SetEventObject( /*this*/m_owner 
); 
2580     m_owner
->ProcessEvent( event 
); 
2583 void wxTreeListMainWindow::DeleteChildren(const wxTreeItemId
& itemId
) 
2585     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2587     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2588     item
->DeleteChildren(this); 
2591 void wxTreeListMainWindow::Delete(const wxTreeItemId
& itemId
) 
2593     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2595     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2597     // don't stay with invalid m_key_current or we will crash in 
2598     // the next call to OnChar() 
2599     bool changeKeyCurrent 
= FALSE
; 
2600     wxTreeListItem 
*itemKey 
= m_key_current
; 
2603         if ( itemKey 
== item 
) 
2605             // m_key_current is a descendant of the item being deleted 
2606             changeKeyCurrent 
= TRUE
; 
2609         itemKey 
= itemKey
->GetItemParent(); 
2612     wxTreeListItem 
*parent 
= item
->GetItemParent(); 
2615         parent
->GetChildren().Remove( item 
);  // remove by value 
2618     if ( changeKeyCurrent 
) 
2620         // may be NULL or not 
2621         m_key_current 
= parent
; 
2624     item
->DeleteChildren(this); 
2625     SendDeleteEvent(item
); 
2629 void wxTreeListMainWindow::DeleteAllItems() 
2635         m_anchor
->DeleteChildren(this); 
2642 void wxTreeListMainWindow::Expand(const wxTreeItemId
& itemId
) 
2644     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2646     wxCHECK_RET( item
, _T("invalid item in wxTreeListMainWindow::Expand") ); 
2648     if ( !item
->HasPlus() ) 
2651     if ( item
->IsExpanded() ) 
2654     wxTreeEvent 
event( wxEVT_COMMAND_TREE_ITEM_EXPANDING
, m_owner
->GetId() ); 
2655     event
.SetItem( (long) item 
); 
2656     event
.SetEventObject( /*this*/m_owner 
); 
2658     if ( m_owner
->ProcessEvent( event 
) && !event
.IsAllowed() ) 
2660         // cancelled by program 
2665     CalculatePositions(); 
2667     RefreshSubtree(item
); 
2669     event
.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED
); 
2670     ProcessEvent( event 
); 
2673 void wxTreeListMainWindow::ExpandAll(const wxTreeItemId
& item
) 
2676     if ( IsExpanded(item
) ) 
2678 #if !wxCHECK_VERSION(2, 5, 0) 
2681         wxTreeItemIdValue cookie
; 
2683         wxTreeItemId child 
= GetFirstChild(item
, cookie
); 
2684         while ( child
.IsOk() ) 
2688             child 
= GetNextChild(item
, cookie
); 
2693 void wxTreeListMainWindow::Collapse(const wxTreeItemId
& itemId
) 
2695     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2697     if ( !item
->IsExpanded() ) 
2700     wxTreeEvent 
event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING
, m_owner
->GetId() ); 
2701     event
.SetItem( (long) item 
); 
2702     event
.SetEventObject( /*this*/m_owner 
); 
2703     if ( m_owner
->ProcessEvent( event 
) && !event
.IsAllowed() ) 
2705         // cancelled by program 
2711 #if 0  // TODO why should items be collapsed recursively? 
2712     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2713     size_t count 
= children
.Count(); 
2714     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2716         Collapse(children
[n
]); 
2720     CalculatePositions(); 
2722     RefreshSubtree(item
); 
2724     event
.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED
); 
2725     ProcessEvent( event 
); 
2728 void wxTreeListMainWindow::CollapseAndReset(const wxTreeItemId
& item
) 
2731     DeleteChildren(item
); 
2734 void wxTreeListMainWindow::Toggle(const wxTreeItemId
& itemId
) 
2736     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2738     if (item
->IsExpanded()) 
2744 void wxTreeListMainWindow::Unselect() 
2748         m_current
->SetHilight( FALSE 
); 
2749         RefreshLine( m_current 
); 
2753 void wxTreeListMainWindow::UnselectAllChildren(wxTreeListItem 
*item
) 
2755     if (item
->IsSelected()) 
2757         item
->SetHilight(FALSE
); 
2761     if (item
->HasChildren()) 
2763         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2764         size_t count 
= children
.Count(); 
2765         for ( size_t n 
= 0; n 
< count
; ++n 
) 
2767             UnselectAllChildren(children
[n
]); 
2772 void wxTreeListMainWindow::UnselectAll() 
2774     UnselectAllChildren((wxTreeListItem
*)GetRootItem().m_pItem
); 
2777 // Recursive function ! 
2778 // To stop we must have crt_item<last_item 
2780 // Tag all next children, when no more children, 
2781 // Move to parent (not to tag) 
2782 // Keep going... if we found last_item, we stop. 
2783 bool wxTreeListMainWindow::TagNextChildren(wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
, bool select
) 
2785     wxTreeListItem 
*parent 
= crt_item
->GetItemParent(); 
2787     if (parent 
== NULL
) // This is root item 
2788         return TagAllChildrenUntilLast(crt_item
, last_item
, select
); 
2790     wxArrayTreeListItems
& children 
= parent
->GetChildren(); 
2791     int index 
= children
.Index(crt_item
); 
2792     wxASSERT( index 
!= wxNOT_FOUND 
); // I'm not a child of my parent? 
2794     size_t count 
= children
.Count(); 
2795     for (size_t n
=(size_t)(index
+1); n
<count
; ++n
) 
2797         if (TagAllChildrenUntilLast(children
[n
], last_item
, select
)) return TRUE
; 
2800     return TagNextChildren(parent
, last_item
, select
); 
2803 bool wxTreeListMainWindow::TagAllChildrenUntilLast(wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
, bool select
) 
2805     crt_item
->SetHilight(select
); 
2806     RefreshLine(crt_item
); 
2808     if (crt_item
==last_item
) 
2811     if (crt_item
->HasChildren()) 
2813         wxArrayTreeListItems
& children 
= crt_item
->GetChildren(); 
2814         size_t count 
= children
.Count(); 
2815         for ( size_t n 
= 0; n 
< count
; ++n 
) 
2817             if (TagAllChildrenUntilLast(children
[n
], last_item
, select
)) 
2825 void wxTreeListMainWindow::SelectItemRange(wxTreeListItem 
*item1
, wxTreeListItem 
*item2
) 
2827     // item2 is not necessary after item1 
2828     wxTreeListItem 
*first
=NULL
, *last
=NULL
; 
2830     // choice first' and 'last' between item1 and item2 
2831     if (item1
->GetY()<item2
->GetY()) 
2842     bool select 
= m_current
->IsSelected(); 
2844     if ( TagAllChildrenUntilLast(first
,last
,select
) ) 
2847     TagNextChildren(first
,last
,select
); 
2850 void wxTreeListMainWindow::SelectItem(const wxTreeItemId
& itemId
, 
2851                             bool unselect_others
, 
2852                             bool extended_select
) 
2854     wxCHECK_RET( itemId
.IsOk(), wxT("invalid tree item") ); 
2856     bool is_single
=!(GetWindowStyleFlag() & wxTR_MULTIPLE
); 
2857     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2859     //wxCHECK_RET( ( (!unselect_others) && is_single), 
2860     //           wxT("this is a single selection tree") ); 
2862     // to keep going anyhow !!! 
2865         if (item
->IsSelected()) 
2866             return; // nothing to do 
2867         unselect_others 
= TRUE
; 
2868         extended_select 
= FALSE
; 
2870     else if ( unselect_others 
&& item
->IsSelected() ) 
2872         // selection change if there is more than one item currently selected 
2873         wxArrayTreeItemIds selected_items
; 
2874         if ( GetSelections(selected_items
) == 1 ) 
2878     wxTreeEvent 
event( wxEVT_COMMAND_TREE_SEL_CHANGING
, m_owner
->GetId() ); 
2879     event
.SetItem( (long) item 
); 
2880     event
.SetOldItem( (long) m_current 
); 
2881     event
.SetEventObject( /*this*/m_owner 
); 
2882     // TODO : Here we don't send any selection mode yet ! 
2884     if(m_owner
->GetEventHandler()->ProcessEvent( event 
) && !event
.IsAllowed()) 
2887     wxTreeItemId parent 
= GetItemParent( itemId 
); 
2888     while (parent
.IsOk()) 
2890         if (!IsExpanded(parent
)) 
2893         parent 
= GetItemParent( parent 
); 
2896     EnsureVisible( itemId 
); 
2899     if (unselect_others
) 
2901         if (is_single
) Unselect(); // to speed up thing 
2906     if (extended_select
) 
2910             m_current 
= m_key_current 
= (wxTreeListItem
*)GetRootItem().m_pItem
; 
2913         // don't change the mark (m_current) 
2914         SelectItemRange(m_current
, item
); 
2918         bool select
=TRUE
; // the default 
2920         // Check if we need to toggle hilight (ctrl mode) 
2921         if (!unselect_others
) 
2922             select
=!item
->IsSelected(); 
2924         m_current 
= m_key_current 
= item
; 
2925         m_current
->SetHilight(select
); 
2926         RefreshLine( m_current 
); 
2929     event
.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED
); 
2930     GetEventHandler()->ProcessEvent( event 
); 
2933 void wxTreeListMainWindow::SelectAll(bool extended_select
) 
2935     wxCHECK_RET( GetWindowStyleFlag() & wxTR_MULTIPLE
, wxT("invalid tree style") ); 
2937     wxTreeEvent 
event( wxEVT_COMMAND_TREE_SEL_CHANGING
, m_owner
->GetId() ); 
2938     event
.SetItem( GetRootItem() ); 
2939     event
.SetOldItem( (long) m_current 
); 
2940     event
.SetEventObject( /*this*/m_owner 
); 
2941     // TODO : Here we don't send any selection mode yet ! 
2943     if(m_owner
->GetEventHandler()->ProcessEvent( event 
) && !event
.IsAllowed()) 
2947     if (!extended_select
) 
2955 #if !wxCHECK_VERSION(2, 5, 0) 
2958     wxTreeItemIdValue cookie 
= 0; 
2960     wxTreeItemId root 
= GetRootItem(); 
2961     wxTreeListItem 
*first 
= (wxTreeListItem 
*)GetFirstChild (root
, cookie
).m_pItem
; 
2962     wxTreeListItem 
*last 
= (wxTreeListItem 
*)GetLastChild (GetRootItem()).m_pItem
; 
2963     if (TagAllChildrenUntilLast (first
, last
, true)) return; 
2964     TagNextChildren (first
, last
, true); 
2966     event
.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED
); 
2967     GetEventHandler()->ProcessEvent( event 
); 
2970 void wxTreeListMainWindow::FillArray(wxTreeListItem 
*item
, 
2971                            wxArrayTreeItemIds 
&array
) const 
2973     if ( item
->IsSelected() ) 
2974         array
.Add(wxTreeItemId(item
)); 
2976     if ( item
->HasChildren() ) 
2978         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2979         size_t count 
= children
.GetCount(); 
2980         for ( size_t n 
= 0; n 
< count
; ++n 
) 
2981             FillArray(children
[n
], array
); 
2985 size_t wxTreeListMainWindow::GetSelections(wxArrayTreeItemIds 
&array
) const 
2988     wxTreeItemId idRoot 
= GetRootItem(); 
2989     if ( idRoot
.IsOk() ) 
2991         FillArray((wxTreeListItem
*) idRoot
.m_pItem
, array
); 
2993     //else: the tree is empty, so no selections 
2995     return array
.Count(); 
2998 void wxTreeListMainWindow::EnsureVisible(const wxTreeItemId
& item
) 
3000     if (!item
.IsOk()) return; 
3002     wxTreeListItem 
*gitem 
= (wxTreeListItem
*) item
.m_pItem
; 
3004     // first expand all parent branches 
3005     wxTreeListItem 
*parent 
= gitem
->GetItemParent(); 
3009         parent 
= parent
->GetItemParent(); 
3012     //if (parent) CalculatePositions(); 
3017 void wxTreeListMainWindow::ScrollTo(const wxTreeItemId 
&item
) 
3019     if (!item
.IsOk()) return; 
3021     // We have to call this here because the label in 
3022     // question might just have been added and no screen 
3023     // update taken place. 
3024     if (m_dirty
) wxYieldIfNeeded(); 
3026     wxTreeListItem 
*gitem 
= (wxTreeListItem
*) item
.m_pItem
; 
3028     // now scroll to the item 
3029     int item_y 
= gitem
->GetY(); 
3033     GetViewStart( &start_x
, &start_y 
); 
3034     start_y 
*= PIXELS_PER_UNIT
; 
3038     GetClientSize( &client_w
, &client_h 
); 
3040     if (item_y 
< start_y
+3) 
3045         m_anchor
->GetSize( x
, y
, this ); 
3046         x 
= m_owner
->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB 
3047         y 
+= PIXELS_PER_UNIT
+2; // one more scrollbar unit + 2 pixels 
3048         //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels 
3049         int x_pos 
= GetScrollPos( wxHORIZONTAL 
); 
3050         // Item should appear at top 
3051         SetScrollbars( PIXELS_PER_UNIT
, PIXELS_PER_UNIT
, x
/PIXELS_PER_UNIT
, y
/PIXELS_PER_UNIT
, x_pos
, item_y
/PIXELS_PER_UNIT 
); 
3053     else if (item_y
+GetLineHeight(gitem
) > start_y
+client_h
) 
3058         m_anchor
->GetSize( x
, y
, this ); 
3059         y 
+= PIXELS_PER_UNIT
+2; // one more scrollbar unit + 2 pixels 
3060         //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels 
3061         x 
= m_owner
->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB 
3062         item_y 
+= PIXELS_PER_UNIT
+2; 
3063         int x_pos 
= GetScrollPos( wxHORIZONTAL 
); 
3064         // Item should appear at bottom 
3065         SetScrollbars( PIXELS_PER_UNIT
, PIXELS_PER_UNIT
, x
/PIXELS_PER_UNIT
, y
/PIXELS_PER_UNIT
, x_pos
, (item_y
+GetLineHeight(gitem
)-client_h
)/PIXELS_PER_UNIT 
); 
3069 // FIXME: tree sorting functions are not reentrant and not MT-safe! 
3070 static wxTreeListMainWindow 
*s_treeBeingSorted 
= NULL
; 
3072 static int LINKAGEMODE 
tree_ctrl_compare_func(wxTreeListItem 
**item1
, 
3073                                   wxTreeListItem 
**item2
) 
3075     wxCHECK_MSG( s_treeBeingSorted
, 0, wxT("bug in wxTreeListMainWindow::SortChildren()") ); 
3077     return s_treeBeingSorted
->OnCompareItems(*item1
, *item2
); 
3080 int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId
& item1
, 
3081                                const wxTreeItemId
& item2
) 
3083     // ALB: delegate to m_owner, to let the user overrride the comparison 
3084     //return wxStrcmp(GetItemText(item1), GetItemText(item2)); 
3085     return m_owner
->OnCompareItems(item1
, item2
); 
3088 void wxTreeListMainWindow::SortChildren(const wxTreeItemId
& itemId
) 
3090     wxCHECK_RET( itemId
.IsOk(), wxT("invalid tree item") ); 
3092     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
3094     wxCHECK_RET( !s_treeBeingSorted
, 
3095                  wxT("wxTreeListMainWindow::SortChildren is not reentrant") ); 
3097     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
3098     if ( children
.Count() > 1 ) 
3102         s_treeBeingSorted 
= this; 
3103         children
.Sort(tree_ctrl_compare_func
); 
3104         s_treeBeingSorted 
= NULL
; 
3106     //else: don't make the tree dirty as nothing changed 
3109 wxTreeItemId 
wxTreeListMainWindow::FindItem (const wxTreeItemId
& item
, const wxString
& str
, int flags
) { 
3110 #if !wxCHECK_VERSION(2, 5, 0) 
3113     wxTreeItemIdValue cookie 
= 0; 
3115     wxTreeItemId next 
= item
; 
3116     if (!next
.IsOk()) next 
= GetSelection(); 
3118         if (HasFlag(wxTR_HIDE_ROOT
)) { 
3119             next 
= (wxTreeListItem
*)GetFirstChild (GetRootItem().m_pItem
, cookie
).m_pItem
; 
3121             next 
= (wxTreeListItem
*)GetRootItem().m_pItem
; 
3124     if (!next
.IsOk()) return item
; 
3126     // start checking the next items 
3128     while (next
.IsOk()) { 
3129         itemText 
= GetItemText (next
); 
3130         if (flags 
& wxTL_SEARCH_LEVEL
) { 
3131             next 
= GetNextSibling (next
); 
3132         }else if (flags 
& wxTL_SEARCH_FULL
) { 
3133             wxTreeItemId n 
= GetFirstChild (next
, cookie
); 
3135                 n 
= GetNextSibling (next
); 
3137                 n 
= GetNextSibling (GetItemParent (next
)); 
3139         }else{ // wxTL_SEARCH_VISIBLE 
3140             next 
= GetNextVisible (next
); 
3142         if (!next
.IsOk()) break; // done 
3143         if (flags 
& wxTL_SEARCH_PARTIAL
) { 
3144             itemText 
= GetItemText (next
).Mid (0, str
.Length()); 
3146             itemText 
= GetItemText (next
); 
3148         if (flags 
& wxTL_SEARCH_NOCASE
) { 
3149             if (itemText
.CmpNoCase (str
) == 0) return next
; 
3151             if (itemText
.Cmp (str
) == 0) return next
; 
3157 wxImageList 
*wxTreeListMainWindow::GetImageList() const 
3159     return m_imageListNormal
; 
3162 wxImageList 
*wxTreeListMainWindow::GetButtonsImageList() const 
3164     return m_imageListButtons
; 
3167 wxImageList 
*wxTreeListMainWindow::GetStateImageList() const 
3169     return m_imageListState
; 
3172 void wxTreeListMainWindow::CalculateLineHeight() 
3174     wxClientDC 
dc(this); 
3175     dc
.SetFont( m_normalFont 
); 
3176     m_lineHeight 
= (int)(dc
.GetCharHeight() + m_linespacing
); 
3178     if ( m_imageListNormal 
) 
3180         // Calculate a m_lineHeight value from the normal Image sizes. 
3181         // May be toggle off. Then wxTreeListMainWindow will spread when 
3182         // necessary (which might look ugly). 
3183         int n 
= m_imageListNormal
->GetImageCount(); 
3184         for (int i 
= 0; i 
< n 
; i
++) 
3186             int width 
= 0, height 
= 0; 
3187             m_imageListNormal
->GetSize(i
, width
, height
); 
3188             if (height 
> m_lineHeight
) m_lineHeight 
= height 
+ m_linespacing
; 
3192     if (m_imageListButtons
) 
3194         // Calculate a m_lineHeight value from the Button image sizes. 
3195         // May be toggle off. Then wxTreeListMainWindow will spread when 
3196         // necessary (which might look ugly). 
3197         int n 
= m_imageListButtons
->GetImageCount(); 
3198         for (int i 
= 0; i 
< n 
; i
++) 
3200             int width 
= 0, height 
= 0; 
3201             m_imageListButtons
->GetSize(i
, width
, height
); 
3202             if (height 
> m_lineHeight
) m_lineHeight 
= height 
+ m_linespacing
; 
3206 /*? FIXME: Don't get what this code is for... Adding a line space is already done!!! 
3207     if (m_lineHeight < 30) 
3208         m_lineHeight += 2;                 // at least 2 pixels 
3210         m_lineHeight += m_lineHeight/10;   // otherwise 10% extra spacing 
3214 void wxTreeListMainWindow::SetImageList(wxImageList 
*imageList
) 
3216     if (m_ownsImageListNormal
) delete m_imageListNormal
; 
3217     m_imageListNormal 
= imageList
; 
3218     m_ownsImageListNormal 
= FALSE
; 
3220     CalculateLineHeight(); 
3223 void wxTreeListMainWindow::SetStateImageList(wxImageList 
*imageList
) 
3225     if (m_ownsImageListState
) delete m_imageListState
; 
3226     m_imageListState 
= imageList
; 
3227     m_ownsImageListState 
= FALSE
; 
3230 void wxTreeListMainWindow::SetButtonsImageList(wxImageList 
*imageList
) 
3232     if (m_ownsImageListButtons
) delete m_imageListButtons
; 
3233     m_imageListButtons 
= imageList
; 
3234     m_ownsImageListButtons 
= FALSE
; 
3236     CalculateLineHeight(); 
3239 void wxTreeListMainWindow::AssignImageList(wxImageList 
*imageList
) 
3241     SetImageList(imageList
); 
3242     m_ownsImageListNormal 
= TRUE
; 
3245 void wxTreeListMainWindow::AssignStateImageList(wxImageList 
*imageList
) 
3247     SetStateImageList(imageList
); 
3248     m_ownsImageListState 
= TRUE
; 
3251 void wxTreeListMainWindow::AssignButtonsImageList(wxImageList 
*imageList
) 
3253     SetButtonsImageList(imageList
); 
3254     m_ownsImageListButtons 
= TRUE
; 
3257 // ---------------------------------------------------------------------------- 
3259 // ---------------------------------------------------------------------------- 
3261 void wxTreeListMainWindow::AdjustMyScrollbars() 
3266         m_anchor
->GetSize( x
, y
, this ); 
3267         y 
+= PIXELS_PER_UNIT
+2; // one more scrollbar unit + 2 pixels 
3268         //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels 
3269         int x_pos 
= GetScrollPos( wxHORIZONTAL 
); 
3270         int y_pos 
= GetScrollPos( wxVERTICAL 
); 
3271         x 
= m_owner
->GetHeaderWindow()->GetWidth() + 2; 
3272         if(x 
< GetClientSize().GetWidth()) x_pos 
= 0; 
3273         //m_total_col_width + 2; // ALB 
3274         SetScrollbars( PIXELS_PER_UNIT
, PIXELS_PER_UNIT
, x
/PIXELS_PER_UNIT
, 
3275                        y
/PIXELS_PER_UNIT
, x_pos
, y_pos 
); 
3279         SetScrollbars( 0, 0, 0, 0 ); 
3283 int wxTreeListMainWindow::GetLineHeight(wxTreeListItem 
*item
) const 
3285     if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT
) 
3286         return item
->GetHeight(); 
3288         return m_lineHeight
; 
3291 void wxTreeListMainWindow::PaintItem(wxTreeListItem 
*item
, wxDC
& dc
) 
3293     wxTreeItemAttr 
*attr 
= item
->GetAttributes(); 
3294     if (attr 
&& attr
->HasFont()) { 
3295         dc
.SetFont(attr
->GetFont()); 
3296     }else if (item
->IsBold()) { 
3297         dc
.SetFont(m_boldFont
); 
3300     if (attr 
&& attr
->HasTextColour()) { 
3301         colText 
= attr
->GetTextColour(); 
3303         colText 
= GetForegroundColour(); 
3306     dc
.SetPen(*wxTRANSPARENT_PEN
); 
3308     long text_w 
= 0, text_h 
= 0; 
3310     dc
.GetTextExtent( item
->GetText(GetMainColumn()), &text_w
, &text_h 
); 
3312     int total_h 
= GetLineHeight(item
); 
3314     if (item
->IsSelected() && HasFlag(wxTR_FULL_ROW_HIGHLIGHT
)) { 
3315             dc
.SetBrush(*(m_hasFocus 
? m_hilightBrush 
: m_hilightUnfocusedBrush
)); 
3316             dc
.SetPen(*wxBLACK_PEN
); 
3317             colText 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3320         if (attr 
&& attr
->HasBackgroundColour()) { 
3321             colBg 
= attr
->GetBackgroundColour(); 
3323             colBg 
= GetBackgroundColour(); 
3325         dc
.SetBrush(wxBrush(colBg
, wxSOLID
)); 
3328     int offset 
= HasFlag(wxTR_ROW_LINES
) ? 1 : 0; 
3329     dc
.DrawRectangle(0, item
->GetY() + offset
, 
3330                      m_owner
->GetHeaderWindow()->GetWidth(), total_h
-offset
); 
3332     dc
.SetBackgroundMode(wxTRANSPARENT
); 
3333     int text_extraH 
= (total_h 
> text_h
) ? (total_h 
- text_h
)/2 : 0; 
3334     int img_extraH 
= (total_h 
> m_imgHeight
)? (total_h
-m_imgHeight
)/2: 0; 
3336     for ( size_t i 
= 0; i 
< GetColumnCount(); ++i 
) { 
3337         if (!m_owner
->GetHeaderWindow()->GetColumnShown(i
)) continue; 
3338         int colwidth 
= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
3342         if (i 
== GetMainColumn()) { 
3343             image 
= item
->GetCurrentImage(); 
3344             if (item
->HasPlus()) { 
3345                  image_x 
= item
->GetX() + (m_btnWidth
-m_btnWidth2
) + LINEATROOT
; 
3347                  image_x 
= item
->GetX() - m_imgWidth2
; 
3352             image 
= item
->GetImage(i
); 
3353             image_x 
= x_colstart 
+ MARGIN
; 
3355         if (image 
!= NO_IMAGE
) image_w 
= m_imgWidth 
+ MARGIN
; 
3357         // honor text alignment 
3358         wxString text 
= item
->GetText(i
); 
3359         switch ( m_owner
->GetHeaderWindow()->GetColumn(i
).GetAlignment() ) { 
3360         case wxTL_ALIGN_LEFT
: 
3361             // already left aligned 
3363         case wxTL_ALIGN_RIGHT
: 
3364             dc
.GetTextExtent(text
, &text_w
, NULL
); 
3365             image_x 
= x_colstart 
+ colwidth 
- (image_w 
+ text_w 
+ MARGIN
); 
3367         case wxTL_ALIGN_CENTER
: 
3368             dc
.GetTextExtent(text
, &text_w
, NULL
); 
3369             int w 
= colwidth 
- image_w 
- text_w
; 
3370             image_x 
= x_colstart 
+ (w 
> 0)? w
: 0; 
3373         int text_x 
= image_x 
+ image_w
; 
3375         if (item
->IsSelected() && (i
==GetMainColumn()) && !HasFlag(wxTR_FULL_ROW_HIGHLIGHT
)) 
3377             dc
.SetPen(*wxBLACK_PEN
); 
3378             dc
.SetBrush(*(m_hasFocus 
? m_hilightBrush 
: m_hilightUnfocusedBrush
)); 
3379             int offset 
= HasFlag (wxTR_ROW_LINES
) ? 1 : 0; 
3380             int width 
= wxMin(text_w
+2, colwidth 
- text_x 
- x_colstart
); 
3381             dc
.DrawRectangle(text_x
-1, item
->GetY() + offset
, width
, total_h
-offset
); 
3382             dc
.SetBackgroundMode(wxTRANSPARENT
); 
3383             dc
.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
)); 
3385             dc
.SetTextForeground(colText
); 
3388         wxDCClipper 
clipper (dc
, x_colstart
, item
->GetY(), colwidth
, total_h
); 
3389         if (image 
!= NO_IMAGE
) 
3391             int image_y 
= item
->GetY() + img_extraH
; 
3392             m_imageListNormal
->Draw ( image
, dc
, image_x
, image_y
, 
3393                                       wxIMAGELIST_DRAW_TRANSPARENT 
); 
3395         int text_y 
= item
->GetY() + text_extraH
; 
3396         dc
.DrawText ( text
, (wxCoord
)text_x
, (wxCoord
)text_y 
); 
3398         x_colstart 
+= colwidth
; 
3401     // restore normal font 
3402     dc
.SetFont( m_normalFont 
); 
3405 // Now y stands for the top of the item, whereas it used to stand for middle ! 
3406 void wxTreeListMainWindow::PaintLevel (wxTreeListItem 
*item
, wxDC 
&dc
, 
3407                                        int level
, int &y
, int x_colstart 
) 
3409     // Handle hide root (only level 0) 
3410     if (HasFlag(wxTR_HIDE_ROOT
) && (level 
== 0)) { 
3411         // always expand hidden root 
3412         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
3414         for (n 
= 0; n 
< (int)children
.Count(); n
++) { 
3415             PaintLevel (children
[n
], dc
, 1, y
, x_colstart
); 
3417         // end after expanding root 
3421     // calculate position of vertical lines 
3422     int x 
= x_colstart 
+ MARGIN
; // start of column 
3423     if (HasFlag (wxTR_LINES_AT_ROOT
)) x 
+= LINEATROOT
; // space for lines at root 
3425         x 
+= m_btnWidth2
; // middle of button 
3427         if (m_imgWidth 
> 0) x 
+= m_imgWidth2
; // middle of image 
3429     if (!HasFlag (wxTR_HIDE_ROOT
)) { 
3430         x 
+= m_indent 
* level
; // indent according to level 
3432         if (level 
> 0) x 
+= m_indent 
* (level
-1); // but not level 1 
3435     // handle column text 
3439     int h 
= GetLineHeight(item
); 
3441     int y_mid 
= y_top 
+ (h
/2); 
3444     int exposed_x 
= dc
.LogicalToDeviceX(0); 
3445     int exposed_y 
= dc
.LogicalToDeviceY(y_top
); 
3447     if (IsExposed(exposed_x
, exposed_y
, 10000, h
))  // 10000 = very much 
3450         PaintItem(item
, dc
); 
3452         if (HasFlag(wxTR_ROW_LINES
)) 
3454             //dc.DestroyClippingRegion(); 
3455             int total_width 
= m_owner
->GetHeaderWindow()->GetWidth(); 
3456             // if the background colour is white, choose a 
3457             // contrasting color for the lines 
3458             dc
.SetPen (*((GetBackgroundColour() == *wxWHITE
)? 
3459                         wxMEDIUM_GREY_PEN 
: wxWHITE_PEN
)); 
3460             dc
.DrawLine(0, y_top
, total_width
, y_top
); 
3461             dc
.DrawLine(0, y
, total_width
, y
); 
3464         // restore DC objects 
3465         dc
.SetBrush(*wxWHITE_BRUSH
); 
3466         dc
.SetPen(m_dottedPen
); 
3468         if (((level 
== 0) || ((level 
== 1) && HasFlag(wxTR_HIDE_ROOT
))) && 
3469             HasFlag(wxTR_LINES_AT_ROOT
) && !HasFlag(wxTR_NO_LINES
)) { 
3470             int rootPos 
= x_colstart 
+ MARGIN
; 
3471             dc
.DrawLine (rootPos
, y_mid
, rootPos
+LINEATROOT
, y_mid
); 
3474         size_t clip_width 
= m_owner
->GetHeaderWindow()-> 
3475                             GetColumn(m_main_column
).GetWidth(); 
3477         if (item
->HasPlus() && HasButtons())  // should the item show a button? 
3479             // clip to the column width 
3480             wxDCClipper 
clipper(dc
, x_colstart
, y_top
, clip_width
, 10000); 
3482             if ( !HasFlag(wxTR_NO_LINES
) ) 
3484                 // draw the horizontal line here 
3486                 if (x 
> (signed)m_indent
) 
3487                     x_start 
-= m_indent
; 
3488                 else if (HasFlag(wxTR_LINES_AT_ROOT
)) 
3490                 dc
.DrawLine(x_start
, y_mid
, x 
/*+ m_spacing*/, y_mid
); 
3493             if (m_imageListButtons 
!= NULL
) 
3495                 // draw the image button here 
3496                 int image 
= wxTreeItemIcon_Normal
; 
3497                 if (item
->IsExpanded()) image 
= wxTreeItemIcon_Expanded
; 
3498                 if (item
->IsSelected()) 
3499                     image 
+= wxTreeItemIcon_Selected 
- wxTreeItemIcon_Normal
; 
3500                 int xx 
= x 
+ m_btnWidth2
; 
3501                 int yy 
= y_mid 
- m_btnHeight2
; 
3502                 dc
.SetClippingRegion(xx
, yy
, m_btnWidth
, m_btnHeight
); 
3503                 m_imageListButtons
->Draw(image
, dc
, xx
, yy
, 
3504                                          wxIMAGELIST_DRAW_TRANSPARENT
); 
3505                 dc
.DestroyClippingRegion(); 
3507             else // no custom buttons 
3509                 static const int wImage 
= 9; 
3510                 static const int hImage 
= 9; 
3513                 if (item
->IsExpanded()) 
3514                     flag 
|= wxCONTROL_EXPANDED
; 
3515                 if (item 
== m_underMouse
) 
3516                     flag 
|= wxCONTROL_CURRENT
; 
3518                 wxRendererNative::Get().DrawTreeItemButton( 
3520                     wxRect(x 
- wImage
/2, y_mid 
- hImage
/2, wImage
, hImage
), 
3524             if (!HasFlag(wxTR_NO_LINES
)) { 
3525                 if (/*!(level == 0) &&*/ !((level 
== 1) && HasFlag(wxTR_HIDE_ROOT
))) { 
3526                     if (m_imgWidth 
> 0) { 
3527                         dc
.DrawLine(x
+m_btnWidth2
, y_mid
, x
+m_indent
-m_imgWidth2
, y_mid
); 
3529                         dc
.DrawLine(x
+m_btnWidth2
, y_mid
, x
+m_btnWidth2
+LINEATROOT
-MARGIN
, y_mid
); 
3534         else if (!HasFlag(wxTR_NO_LINES
))  // no button; maybe a line? 
3536             // clip to the column width 
3537             wxDCClipper 
clipper(dc
, x_colstart
, y_top
, clip_width
, 10000); 
3539             // draw the horizontal line here 
3540             if (/*!(level == 0) &&*/ !((level 
== 1) && HasFlag(wxTR_HIDE_ROOT
))) { 
3541                 int x2 
= x 
- m_indent
; 
3542                 if (m_imgWidth 
> 0) { 
3543                     dc
.DrawLine(x2
, y_mid
, x2
+m_indent
-m_imgWidth2
, y_mid
); 
3545                     dc
.DrawLine(x2
, y_mid
, x2
+m_btnWidth2
+LINEATROOT
+MARGIN
, y_mid
); 
3551     // restore DC objects 
3552     dc
.SetBrush(*wxWHITE_BRUSH
); 
3553     dc
.SetPen(m_dottedPen
); 
3554     dc
.SetTextForeground(*wxBLACK
); 
3556     if (item
->IsExpanded()) 
3558         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
3559         int count 
= children
.Count(); 
3562         // paint sublevel items first 
3563         for (n
=0; n
<count
; ++n
) { 
3565             PaintLevel(children
[n
], dc
, level
+1, y
, x_colstart
); 
3568         // then draw the connecting lines 
3569         if (!HasFlag(wxTR_NO_LINES
) && count 
> 0) 
3571             // clip to the column width 
3572             size_t clip_width 
= m_owner
->GetHeaderWindow()->GetColumn(m_main_column
).GetWidth(); 
3573             wxDCClipper 
clipper(dc
, x_colstart
, y_top
, clip_width
, 10000); 
3575             // draw line down to last child 
3576             oldY 
+= GetLineHeight(children
[n
-1]) >> 1; 
3577             if (HasButtons()) y_mid 
+= 5; 
3578             dc
.DrawLine(x
, y_mid
, x
, oldY
); 
3583 void wxTreeListMainWindow::DrawDropEffect(wxTreeListItem 
*item
) 
3587         if ( item
->HasPlus() ) 
3589             // it's a folder, indicate it by a border 
3594             // draw a line under the drop target because the item will be 
3596             DrawLine(item
, TRUE 
/* below */); 
3599         SetCursor(wxCURSOR_BULLSEYE
); 
3604         SetCursor(wxCURSOR_NO_ENTRY
); 
3608 void wxTreeListMainWindow::DrawBorder(const wxTreeItemId 
&item
) 
3610     wxCHECK_RET( item
.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); 
3612     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
3614     wxClientDC 
dc(this); 
3616     dc
.SetLogicalFunction(wxINVERT
); 
3617     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
3619     int w 
= i
->GetWidth() + 2; 
3620     int h 
= GetLineHeight(i
) + 2; 
3622     dc
.DrawRectangle( i
->GetX() - 1, i
->GetY() - 1, w
, h
); 
3625 void wxTreeListMainWindow::DrawLine(const wxTreeItemId 
&item
, bool below
) 
3627     wxCHECK_RET( item
.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); 
3629     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
3631     wxClientDC 
dc(this); 
3633     dc
.SetLogicalFunction(wxINVERT
); 
3639         y 
+= GetLineHeight(i
) - 1; 
3642     dc
.DrawLine( x
, y
, x 
+ i
->GetWidth(), y
); 
3645 // ---------------------------------------------------------------------------- 
3646 // wxWindows callbacks 
3647 // ---------------------------------------------------------------------------- 
3649 void wxTreeListMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3655     if(!GetColumnCount()) return; // ALB 
3660     // calculate button size 
3661     m_btnWidth 
= 0, m_btnWidth2 
= 0; 
3662     m_btnHeight 
= 0, m_btnHeight2 
= 0; 
3663     if (m_imageListButtons
) { 
3664         m_imageListButtons
->GetSize (0, m_btnWidth
, m_btnHeight
); 
3665     }else if (HasButtons()) { 
3666         m_btnWidth 
= BTNWIDTH
; 
3667         m_btnHeight 
= BTNHEIGHT
; 
3669     m_btnWidth2 
= m_btnWidth
/2; 
3670     m_btnHeight2 
= m_btnHeight
/2; 
3672     // calculate image size 
3673     m_imgWidth 
= 0, m_imgWidth2 
= 0; 
3674     m_imgHeight 
= 0, m_imgHeight2 
= 0; 
3675     if (m_imageListNormal
) { 
3676         m_imageListNormal
->GetSize (0, m_imgWidth
, m_imgHeight
); 
3677         m_imgWidth 
+= 4; //? ToDo: Why + 4? 
3679     m_imgWidth2 
= m_imgWidth
/2; 
3680     m_imgHeight2 
= m_imgHeight
/2; 
3682     // calculate indent size 
3683     int btnIndent 
= HasButtons()? m_btnWidth 
+ LINEATROOT
: 0; 
3684     m_indent 
= wxMax (MININDENT
, wxMax (m_imgWidth
, btnIndent
)) + MARGIN
; 
3686     // set default values 
3687     dc
.SetFont( m_normalFont 
); 
3688     dc
.SetPen( m_dottedPen 
); 
3690     // this is now done dynamically 
3691     //if(GetImageList() == NULL) 
3692     // m_lineHeight = (int)(dc.GetCharHeight() + 4); 
3694     // calculate column start and paint 
3697     for (i 
= 0; i 
< (int)GetMainColumn(); ++i
) { 
3698         if (!m_owner
->GetHeaderWindow()->GetColumnShown(i
)) continue; 
3699         x_colstart 
+= m_owner
->GetHeaderWindow()->GetColumnWidth (i
); 
3702     PaintLevel ( m_anchor
, dc
, 0, y
, x_colstart 
); 
3705 void wxTreeListMainWindow::OnSetFocus( wxFocusEvent 
&event 
) 
3714 void wxTreeListMainWindow::OnKillFocus( wxFocusEvent 
&event 
) 
3723 void wxTreeListMainWindow::OnChar( wxKeyEvent 
&event 
) 
3725     wxTreeEvent 
te( wxEVT_COMMAND_TREE_KEY_DOWN
, m_owner
->GetId() ); 
3726     te
.SetKeyEvent( event 
); 
3727     te
.SetEventObject( /*this*/m_owner 
); 
3728     if ( m_owner
->GetEventHandler()->ProcessEvent( te 
) ) 
3730         // intercepted by the user code 
3736         if (HasFlag(wxTR_HIDE_ROOT
)) { 
3737 #if !wxCHECK_VERSION(2, 5, 0) 
3740             wxTreeItemIdValue cookie 
= 0; 
3742             m_current 
= m_key_current 
= (wxTreeListItem
*)GetFirstChild (GetRootItem().m_pItem
, cookie
).m_pItem
; 
3746             m_current 
= m_key_current 
= (wxTreeListItem
*)GetRootItem().m_pItem
; 
3750     // how should the selection work for this event? 
3751     bool is_multiple
, extended_select
, unselect_others
; 
3752     EventFlagsToSelType(GetWindowStyleFlag(), 
3754                         event
.ControlDown(), 
3755                         is_multiple
, extended_select
, unselect_others
); 
3757     // + : Expand (not on Win32) 
3758     // - : Collaspe (not on Win32) 
3759     // * : Expand all/Collapse all 
3760     // ' ' | return : activate 
3761     // up    : go up (not last children!) 
3763     // left  : go to parent (or collapse on Win32) 
3764     // right : open if parent and go next (or expand on Win32) 
3765     // home  : go to root 
3766     // end   : go to last item without opening parents 
3767     switch (event
.GetKeyCode()) 
3769 #ifndef __WXMSW__ // mimic the standard win32 tree ctrl 
3772             if (m_current
->HasPlus() && !IsExpanded(m_current
)) 
3781             if ( !IsExpanded(m_current
) ) 
3784                 ExpandAll (m_current
); 
3787             //else: fall through to Collapse() it 
3789 #ifndef __WXMSW__ // mimic the standard wxTreeCtrl behaviour 
3792             if (IsExpanded(m_current
)) 
3794                 Collapse (m_current
); 
3802                 wxTreeEvent 
event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED
, 
3804                 event
.SetItem( (long) m_current
); 
3805                 event
.SetEventObject( /*this*/m_owner 
); 
3806                 m_owner
->GetEventHandler()->ProcessEvent( event 
); 
3810         // backspace goes to the parent, sends "root" activation 
3813                 wxTreeItemId prev 
= GetItemParent( m_current 
); 
3814                 if ((prev 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) 
3816                     // don't go to root if it is hidden 
3817                     prev 
= GetPrevSibling( m_current 
); 
3821                     SelectItem( prev
, unselect_others
, extended_select 
); 
3822                     EnsureVisible( prev 
); 
3827         // up goes to the previous sibling or to the last 
3828         // of its children if it's expanded 
3831                 wxTreeItemId prev 
= GetPrevSibling( m_key_current 
); 
3834                     prev 
= GetItemParent( m_key_current 
); 
3835                     if ((prev 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) 
3837                         break;  // don't go to root if it is hidden 
3841 #if !wxCHECK_VERSION(2, 5, 0) 
3844                         wxTreeItemIdValue cookie 
= 0; 
3846                         wxTreeItemId current 
= m_key_current
; 
3847                         // TODO: Huh?  If we get here, we'd better be the first child of our parent.  How else could it be? 
3848                         if (current 
== GetFirstChild( prev
, cookie 
)) 
3850                             // otherwise we return to where we came from 
3851                             SelectItem( prev
, unselect_others
, extended_select 
); 
3852                             m_key_current
= (wxTreeListItem
*) prev
.m_pItem
; 
3853                             EnsureVisible( prev 
); 
3860                     while ( IsExpanded(prev
) && HasChildren(prev
) ) 
3862                         wxTreeItemId child 
= GetLastChild(prev
); 
3870                     SelectItem( prev
, unselect_others
, extended_select 
); 
3871                     m_key_current
=(wxTreeListItem
*) prev
.m_pItem
; 
3872                     EnsureVisible( prev 
); 
3877         // left arrow goes to the parent 
3879             if (IsExpanded(m_current
)) 
3881                 Collapse(m_current
); 
3885                 wxTreeItemId prev 
= GetItemParent( m_current 
); 
3886                 if ((prev 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) 
3888                     // don't go to root if it is hidden 
3889                     prev 
= GetPrevSibling( m_current 
); 
3893                     SelectItem( prev
, unselect_others
, extended_select 
); 
3894                     EnsureVisible( prev 
); 
3900 #if defined(__WXMSW__) // mimic the standard win32 tree ctrl 
3901             if (m_current
->HasPlus() && !IsExpanded(m_current
)) 
3908             // this works the same as the down arrow except that we 
3909             // also expand the item if it wasn't expanded yet 
3915                 if (IsExpanded(m_key_current
) && HasChildren(m_key_current
)) 
3917 #if !wxCHECK_VERSION(2, 5, 0) 
3920                     wxTreeItemIdValue cookie 
= 0; 
3922                     wxTreeItemId child 
= GetFirstChild( m_key_current
, cookie 
); 
3924                         SelectItem( child
, unselect_others
, extended_select 
); 
3925                         m_key_current
=(wxTreeListItem
*) child
.m_pItem
; 
3926                         EnsureVisible( child 
); 
3930                 wxTreeItemId next 
= GetNextSibling( m_key_current 
); 
3933                     wxTreeItemId current 
= m_key_current
; 
3934                     while (current 
&& !next
) 
3936                         current 
= GetItemParent( current 
); 
3937                         if (current
) next 
= GetNextSibling( current 
); 
3942                     SelectItem( next
, unselect_others
, extended_select 
); 
3943                     m_key_current
=(wxTreeListItem
*) next
.m_pItem
; 
3944                     EnsureVisible( next 
); 
3949         // <End> selects the last visible tree item 
3952                 wxTreeItemId last 
= GetRootItem(); 
3954                 while ( last
.IsOk() && IsExpanded(last
) ) 
3956                     wxTreeItemId lastChild 
= GetLastChild(last
); 
3958                     // it may happen if the item was expanded but then all of 
3959                     // its children have been deleted - so IsExpanded() returned 
3960                     // TRUE, but GetLastChild() returned invalid item 
3969                     SelectItem( last
, unselect_others
, extended_select 
); 
3970                     EnsureVisible( last 
); 
3975         // <Home> selects the root item 
3978                 wxTreeItemId prev 
= GetRootItem(); 
3980                 if (HasFlag(wxTR_HIDE_ROOT
)) 
3982 #if !wxCHECK_VERSION(2, 5, 0) 
3985                     wxTreeItemIdValue cookie 
= 0; 
3987                     prev 
= GetFirstChild(prev
, cookie
); 
3990                 SelectItem( prev
, unselect_others
, extended_select 
); 
3991                 EnsureVisible( prev 
); 
3996             if (event
.m_keyCode 
>= (int)' ') { 
3997                 if (!m_findTimer
->IsRunning()) m_findStr
.Clear(); 
3998                 m_findStr
.Append (event
.m_keyCode
); 
3999                 m_findTimer
->Start (500, wxTIMER_ONE_SHOT
); 
4000                 wxTreeItemId dummy 
= (wxTreeItemId
*)NULL
; 
4001                 wxTreeItemId item 
= FindItem (dummy
, m_findStr
, wxTL_SEARCH_VISIBLE 
| 
4002                                                                 wxTL_SEARCH_PARTIAL 
| 
4003                                                                 wxTL_SEARCH_NOCASE
); 
4005                     EnsureVisible (item
); 
4013 wxTreeItemId 
wxTreeListMainWindow::HitTest(const wxPoint
& point
, int& flags
, 
4016     // JACS: removed wxYieldIfNeeded() because it can cause the window 
4017     // to be deleted from under us if a close window event is pending 
4023     if (point
.x
<0) flags 
|= wxTREE_HITTEST_TOLEFT
; 
4024     if (point
.x
>w
) flags 
|= wxTREE_HITTEST_TORIGHT
; 
4025     if (point
.y
<0) flags 
|= wxTREE_HITTEST_ABOVE
; 
4026     if (point
.y
>h
) flags 
|= wxTREE_HITTEST_BELOW
; 
4027     if (flags
) return wxTreeItemId(); 
4029     if (m_anchor 
== NULL
) 
4031         flags 
= wxTREE_HITTEST_NOWHERE
; 
4032         return wxTreeItemId(); 
4035     wxTreeListItem 
*hit 
= m_anchor
->HitTest(CalcUnscrolledPosition(point
), 
4036                                             this, flags
, column
, 0); 
4039         flags 
= wxTREE_HITTEST_NOWHERE
; 
4040         return wxTreeItemId(); 
4045 // get the bounding rectangle of the item (or of its label only) 
4046 bool wxTreeListMainWindow::GetBoundingRect(const wxTreeItemId
& item
, 
4048                          bool WXUNUSED(textOnly
)) const 
4050     wxCHECK_MSG( item
.IsOk(), FALSE
, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") ); 
4052     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
4055     GetViewStart(& startX
, & startY
); 
4057     rect
.x 
= i
->GetX() - startX
*PIXELS_PER_UNIT
; 
4058     rect
.y 
= i
->GetY() - startY
*PIXELS_PER_UNIT
; 
4059     rect
.width 
= i
->GetWidth(); 
4060     //rect.height = i->GetHeight(); 
4061     rect
.height 
= GetLineHeight(i
); 
4068 void wxTreeListMainWindow::Edit( const wxTreeItemId
& item 
) 
4070     if (!item
.IsOk()) return; 
4072     m_currentEdit 
= (wxTreeListItem
*) item
.m_pItem
; 
4074     wxTreeEvent 
te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
, m_owner
->GetId() ); 
4075     te
.SetItem( (long) m_currentEdit
); 
4076     te
.SetEventObject( /*this*/m_owner 
); 
4077     m_owner
->GetEventHandler()->ProcessEvent( te 
); 
4079     if (!te
.IsAllowed()) return; 
4081     // We have to call this here because the label in 
4082     // question might just have been added and no screen 
4083     // update taken place. 
4084     if (m_dirty
) wxYieldIfNeeded(); 
4086     wxString s 
= m_currentEdit
->GetText(/*ALB*/m_main_column
); 
4087     int x 
= m_currentEdit
->GetX() + m_imgWidth2
; 
4088     int y 
= m_currentEdit
->GetY(); 
4089     int w 
= wxMin (m_currentEdit
->GetWidth(), 
4090                    m_owner
->GetHeaderWindow()->GetWidth()) - m_imgWidth2
; 
4091     int h 
= m_currentEdit
->GetHeight() + 2; 
4092     wxClientDC 
dc(this); 
4094     x 
= dc
.LogicalToDeviceX( x 
); 
4095     y 
= dc
.LogicalToDeviceY( y 
); 
4097     wxTreeListTextCtrl 
*text 
= new wxTreeListTextCtrl(this, -1, 
4107 void wxTreeListMainWindow::OnRenameTimer() 
4112 void wxTreeListMainWindow::OnRenameAccept() 
4114     // TODO if the validator fails this causes a crash 
4115     wxTreeEvent 
le( wxEVT_COMMAND_TREE_END_LABEL_EDIT
, m_owner
->GetId() ); 
4116     le
.SetItem( (long) m_currentEdit 
); 
4117     le
.SetEventObject( /*this*/m_owner 
); 
4118     le
.SetLabel( m_renameRes 
); 
4119     m_owner
->GetEventHandler()->ProcessEvent( le 
); 
4121     if (!le
.IsAllowed()) return; 
4123     SetItemText( m_currentEdit
, m_renameRes 
); 
4126 void wxTreeListMainWindow::OnMouse( wxMouseEvent 
&event 
) 
4128     if ( !m_anchor 
) return; 
4130     wxPoint pt 
= CalcUnscrolledPosition(event
.GetPosition()); 
4132     // Is the mouse over a tree item button? 
4134     wxTreeListItem 
*item 
= m_anchor
->HitTest(pt
, this, flags
, 0); 
4135     wxTreeListItem 
*underMouse 
= item
; 
4137     bool underMouseChanged 
= (underMouse 
!= m_underMouse
) ; 
4138 #endif // wxUSE_TOOLTIPS 
4140     if (underMouse 
&& (flags 
& wxTREE_HITTEST_ONITEMBUTTON
) && 
4141         !event
.LeftIsDown() && !m_isDragging 
&& 
4142         (!m_renameTimer 
|| !m_renameTimer
->IsRunning())) 
4150     if (underMouse 
!= m_underMouse
) 
4154             // unhighlight old item 
4155             wxTreeListItem 
*tmp 
= m_underMouse
; 
4156             m_underMouse 
= NULL
; 
4160          m_underMouse 
= underMouse
; 
4162             RefreshLine( m_underMouse 
); 
4166     // Determines what item we are hovering over and need a tooltip for 
4167     wxTreeItemId hoverItem 
= item
; 
4169     // We do not want a tooltip if we are dragging, or if the rename timer is running 
4170     if (underMouseChanged 
&& hoverItem
.IsOk() && !m_isDragging 
&& (!m_renameTimer 
|| !m_renameTimer
->IsRunning())) 
4172         // Ask the tree control what tooltip (if any) should be shown 
4173         wxTreeEvent 
hevent(wxEVT_COMMAND_TREE_ITEM_GETTOOLTIP
, GetId()); 
4174         hevent
.SetItem(hoverItem
); 
4175         hevent
.SetEventObject(this); 
4177         if ( GetEventHandler()->ProcessEvent(hevent
) && hevent
.IsAllowed() ) 
4179             SetToolTip(hevent
.GetLabel()); 
4184     // we process left mouse up event (enables in-place edit), right down 
4185     // (pass to the user code), left dbl click (activate item) and 
4186     // dragging/moving events for items drag-and-drop 
4187     if ( !(event
.LeftDown() || 
4189            event
.RightDown() || 
4190            event
.LeftDClick() || 
4192            ((event
.Moving() || event
.RightUp()) && m_isDragging
)) ) 
4198     if ( event
.LeftDown() ) 
4201 //     wxClientDC dc(this); 
4203 //     wxCoord x = dc.DeviceToLogicalX( event.GetX() ); 
4204 //     wxCoord y = dc.DeviceToLogicalY( event.GetY() ); 
4208     if ( event
.Dragging() && !m_isDragging 
) 
4210         if (m_dragCount 
== 0) 
4211             m_dragStart 
= wxPoint(x
,y
); 
4215         if (m_dragCount 
!= 3) 
4217             // wait until user drags a bit further... 
4221         wxEventType command 
= event
.RightIsDown() 
4222                               ? wxEVT_COMMAND_TREE_BEGIN_RDRAG
 
4223                               : wxEVT_COMMAND_TREE_BEGIN_DRAG
; 
4225         wxTreeEvent 
nevent( command
,/*ALB*/ m_owner
->GetId() ); 
4226         nevent
.SetItem( (long) m_current
); 
4227         nevent
.SetEventObject(/*this*/m_owner
); // ALB 
4228         nevent
.SetPoint(pt
); 
4230         // by default the dragging is not supported, the user code must 
4231         // explicitly allow the event for it to take place 
4234         if ( m_owner
->GetEventHandler()->ProcessEvent(nevent
) && 
4235              nevent
.IsAllowed() ) 
4237             // we're going to drag this item 
4238             m_isDragging 
= TRUE
; 
4240             // remember the old cursor because we will change it while 
4242             m_oldCursor 
= m_cursor
; 
4244             // in a single selection control, hide the selection temporarily 
4245             if ( !(GetWindowStyleFlag() & wxTR_MULTIPLE
) ) 
4247                 m_oldSelection 
= (wxTreeListItem
*) GetSelection().m_pItem
; 
4249                 if ( m_oldSelection 
) 
4251                     m_oldSelection
->SetHilight(FALSE
); 
4252                     RefreshLine(m_oldSelection
); 
4259     else if ( event
.Moving() ) 
4261         if ( item 
!= m_dropTarget 
) 
4263             // unhighlight the previous drop target 
4264             DrawDropEffect(m_dropTarget
); 
4266             m_dropTarget 
= item
; 
4268             // highlight the current drop target if any 
4269             DrawDropEffect(m_dropTarget
); 
4274     else if ( (event
.LeftUp() || event
.RightUp()) && m_isDragging 
) 
4276         // erase the highlighting 
4277         DrawDropEffect(m_dropTarget
); 
4279         if ( m_oldSelection 
) 
4281             m_oldSelection
->SetHilight(TRUE
); 
4282             RefreshLine(m_oldSelection
); 
4283             m_oldSelection 
= (wxTreeListItem 
*)NULL
; 
4286         // generate the drag end event 
4287         wxTreeEvent 
event(wxEVT_COMMAND_TREE_END_DRAG
,/*ALB*/m_owner
->GetId()); 
4289         event
.SetItem( (long) item 
); 
4290         event
.SetPoint( wxPoint(x
, y
) ); 
4291         event
.SetEventObject(/*this*/m_owner
); 
4293         (void)m_owner
->GetEventHandler()->ProcessEvent(event
); 
4295         m_isDragging 
= FALSE
; 
4296         m_dropTarget 
= (wxTreeListItem 
*)NULL
; 
4300         SetCursor(m_oldCursor
); 
4306         // here we process only the messages which happen on tree items 
4310         if ( item 
== NULL 
) return;  /* we hit the blank area */ 
4312         if ( event
.RightDown() ) 
4315             wxTreeEvent 
nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
, 
4317             nevent
.SetItem( (long) item 
); 
4319             CalcScrolledPosition(x
, y
, &nx
, &ny
); 
4320             nevent
.SetPoint( wxPoint(nx
, ny
)); 
4321             nevent
.SetEventObject(/*this*/m_owner
); 
4322             m_owner
->GetEventHandler()->ProcessEvent(nevent
); 
4324         else if ( event
.LeftUp() ) 
4328                 if ( ( item 
== m_current 
) && 
4329                      ( flags 
& wxTREE_HITTEST_ONITEMLABEL 
) && 
4330                      HasFlag(wxTR_EDIT_LABELS 
) ) 
4332                     if ( m_renameTimer
->IsRunning() ) 
4333                         m_renameTimer
->Stop(); 
4335                     m_renameTimer
->Start( 100, TRUE 
); 
4338                 m_lastOnSame 
= FALSE
; 
4341         else // !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick() 
4343             if ( event
.LeftDown() ) 
4346                 m_lastOnSame 
= item 
== m_current
; 
4349             if ((flags 
& wxTREE_HITTEST_ONITEMBUTTON
) || 
4350                 ((flags 
& wxTREE_HITTEST_ONITEMICON
)) && 
4351                  !HasButtons() && item
->HasPlus()) 
4353                 // only toggle the item for a single click, double click on 
4354                 // the button doesn't do anything (it toggles the item twice) 
4355                 if ( event
.LeftDown() ) 
4360                 // don't select the item if the button was clicked 
4364             // how should the selection work for this event? 
4365             bool is_multiple
, extended_select
, unselect_others
; 
4366             EventFlagsToSelType(GetWindowStyleFlag(), 
4368                                 event
.ControlDown(), 
4369                                 is_multiple
, extended_select
, unselect_others
); 
4371             SelectItem (item
, unselect_others
, extended_select
); 
4373             // For some reason, Windows isn't recognizing a left double-click, 
4374             // so we need to simulate it here.  Allow 200 milliseconds for now. 
4375             if ( event
.LeftDClick() ) 
4377                 // double clicking should not start editing the item label 
4378                 m_renameTimer
->Stop(); 
4379                 m_lastOnSame 
= FALSE
; 
4381                 // send activate event first 
4382                 wxTreeEvent 
nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED
, 
4384                 nevent
.SetItem( (long) item 
); 
4386                 CalcScrolledPosition(x
, y
, &nx
, &ny
); 
4387                 nevent
.SetPoint( wxPoint(nx
, ny
) ); 
4388                 nevent
.SetEventObject( /*this*/m_owner 
); 
4389                 if ( !m_owner
->GetEventHandler()->ProcessEvent( nevent 
) ) 
4391                     // if the user code didn't process the activate event, 
4392                     // handle it ourselves by toggling the item when it is 
4394                     if ( item
->HasPlus() ) 
4404 void wxTreeListMainWindow::OnIdle( wxIdleEvent 
&WXUNUSED(event
) ) 
4406     /* after all changes have been done to the tree control, 
4407      * we actually redraw the tree when everything is over */ 
4409     if (!m_dirty
) return; 
4413     CalculatePositions(); 
4415     AdjustMyScrollbars(); 
4418 void wxTreeListMainWindow::OnScroll(wxScrollWinEvent
& event
) 
4421 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) 
4422     wxScrolledWindow::OnScroll(event
); 
4424     HandleOnScroll( event 
); 
4427     if(event
.GetOrientation() == wxHORIZONTAL
) 
4429         m_owner
->GetHeaderWindow()->Refresh(); 
4430         m_owner
->GetHeaderWindow()->Update(); 
4435 void wxTreeListMainWindow::CalculateSize( wxTreeListItem 
*item
, wxDC 
&dc 
) 
4441         dc
.SetFont(m_boldFont
); 
4443     dc
.GetTextExtent( item
->GetText(/*ALB*/m_main_column
), &text_w
, &text_h 
); 
4446     // restore normal font 
4447     dc
.SetFont( m_normalFont 
); 
4449     int total_h 
= (m_imgHeight 
> text_h
) ? m_imgHeight 
: text_h
; 
4451     item
->SetHeight(total_h
); 
4452     if (total_h
>m_lineHeight
) 
4453         m_lineHeight
=total_h
; 
4455     item
->SetWidth(m_imgWidth 
+ text_w
+2); 
4458 // ----------------------------------------------------------------------------- 
4459 // for developper : y is now the top of the level 
4460 // not the middle of it ! 
4461 void wxTreeListMainWindow::CalculateLevel( wxTreeListItem 
*item
, wxDC 
&dc
, 
4462                                         int level
, int &y
, int x_colstart 
) 
4464     // calculate position of vertical lines 
4465     int x 
= x_colstart 
+ MARGIN
; // start of column 
4466     if (HasFlag(wxTR_LINES_AT_ROOT
)) x 
+= LINEATROOT
; // space for lines at root 
4467     if (HasButtons()) x 
+= m_btnWidth2
; // space for buttons etc. 
4468     if (!HasFlag(wxTR_HIDE_ROOT
)) x 
+= m_indent
; // indent root as well 
4469     x 
+= m_indent 
* level
; // indent according to level 
4471     // a hidden root is not evaluated, but its children are always 
4472     if (HasFlag(wxTR_HIDE_ROOT
) && (level 
== 0)) goto Recurse
; 
4474     CalculateSize( item
, dc 
); 
4479     y 
+= GetLineHeight(item
); 
4481     // we don't need to calculate collapsed branches 
4482     if ( !item
->IsExpanded() ) return; 
4485     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
4486     size_t n
, count 
= children
.Count(); 
4488     for (n 
= 0; n 
< count
; ++n 
) 
4489         CalculateLevel( children
[n
], dc
, level
, y
, x_colstart 
);  // recurse 
4492 void wxTreeListMainWindow::CalculatePositions() 
4494     if ( !m_anchor 
) return; 
4496     wxClientDC 
dc(this); 
4499     dc
.SetFont( m_normalFont 
); 
4501     dc
.SetPen( m_dottedPen 
); 
4502     //if(GetImageList() == NULL) 
4503     // m_lineHeight = (int)(dc.GetCharHeight() + 4); 
4507     for(size_t i 
= 0; i 
< GetMainColumn(); ++i
) { 
4508         if (!m_owner
->GetHeaderWindow()->GetColumnShown(i
)) continue; 
4509         x_colstart 
+= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
4511     CalculateLevel( m_anchor
, dc
, 0, y
, x_colstart 
); // start recursion 
4514 void wxTreeListMainWindow::RefreshSubtree(wxTreeListItem 
*item
) 
4516     if (m_dirty
) return; 
4518     wxClientDC 
dc(this); 
4523     GetVirtualSize( &cw
, &ch 
);  
4526     rect
.x 
= dc
.LogicalToDeviceX( 0 ); 
4528     rect
.y 
= dc
.LogicalToDeviceY( item
->GetY() - 2 ); 
4531     Refresh( TRUE
, &rect 
); 
4533     AdjustMyScrollbars(); 
4536 void wxTreeListMainWindow::RefreshLine( wxTreeListItem 
*item 
) 
4538     if (m_dirty
) return; 
4540     wxClientDC 
dc(this); 
4545     GetVirtualSize( &cw
, &ch 
);   
4548     rect
.x 
= dc
.LogicalToDeviceX( 0 ); 
4549     rect
.y 
= dc
.LogicalToDeviceY( item
->GetY() ); 
4551     rect
.height 
= GetLineHeight(item
); //dc.GetCharHeight() + 6; 
4553     Refresh( TRUE
, &rect 
); 
4556 void wxTreeListMainWindow::RefreshSelected() 
4558     // TODO: this is awfully inefficient, we should keep the list of all 
4559     //       selected items internally, should be much faster 
4561         RefreshSelectedUnder(m_anchor
); 
4564 void wxTreeListMainWindow::RefreshSelectedUnder(wxTreeListItem 
*item
) 
4566     if ( item
->IsSelected() ) 
4569     const wxArrayTreeListItems
& children 
= item
->GetChildren(); 
4570     size_t count 
= children
.GetCount(); 
4571     for ( size_t n 
= 0; n 
< count
; n
++ ) 
4573         RefreshSelectedUnder(children
[n
]); 
4577 // ---------------------------------------------------------------------------- 
4578 // changing colours: we need to refresh the tree control 
4579 // ---------------------------------------------------------------------------- 
4581 bool wxTreeListMainWindow::SetBackgroundColour(const wxColour
& colour
) 
4583     if ( !wxWindow::SetBackgroundColour(colour
) ) 
4591 bool wxTreeListMainWindow::SetForegroundColour(const wxColour
& colour
) 
4593     if ( !wxWindow::SetForegroundColour(colour
) ) 
4601 //----------- ALB ------------- 
4602 void wxTreeListMainWindow::SetItemText(const wxTreeItemId
& item
, size_t column
, 
4603                                     const wxString
& text
) 
4605     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
4607     wxClientDC 
dc(this); 
4608     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
4609     pItem
->SetText(column
, text
); 
4610     CalculateSize(pItem
, dc
); 
4614 wxString 
wxTreeListMainWindow::GetItemText(const wxTreeItemId
& item
, 
4615                                      size_t column
) const 
4617     wxCHECK_MSG( item
.IsOk(), wxT(""), wxT("invalid tree item") ); 
4619     return ((wxTreeListItem
*) item
.m_pItem
)->GetText(column
); 
4622 void wxTreeListMainWindow::SetFocus() 
4624     wxWindow::SetFocus(); 
4628 //----------------------------------------------------------------------------- 
4630 //----------------------------------------------------------------------------- 
4632 IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl
, wxControl
); 
4634 BEGIN_EVENT_TABLE(wxTreeListCtrl
, wxControl
) 
4635     EVT_SIZE(wxTreeListCtrl::OnSize
) 
4636     EVT_TREE_ITEM_GETTOOLTIP(wxID_ANY
, wxTreeListCtrl::OnGetToolTip
) 
4639 bool wxTreeListCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
4642                             long style
, const wxValidator 
&validator
, 
4643                             const wxString
& name
) 
4645     long main_style 
= style 
& ~(wxRAISED_BORDER
|wxSUNKEN_BORDER
 
4646                                 |wxSIMPLE_BORDER
|wxNO_BORDER
|wxDOUBLE_BORDER
 
4648     long ctrl_style 
= style 
& ~(wxVSCROLL
|wxHSCROLL
); 
4650     if (!wxControl::Create(parent
, id
, pos
, size
, ctrl_style
, validator
, name
)) { 
4653     m_main_win 
= new wxTreeListMainWindow(this, -1, wxPoint(0, 0), size
, 
4654                                           main_style
, validator
); 
4655     m_header_win 
= new wxTreeListHeaderWindow(this, -1, m_main_win
, 
4656                                               wxPoint(0, 0), wxDefaultSize
, 
4658     CalculateAndSetHeaderHeight(); 
4662 void wxTreeListCtrl::CalculateAndSetHeaderHeight() 
4666         // we use 'g' to get the descent, too 
4668         m_header_win
->GetTextExtent(wxT("Hg"), &w
, &h
, &d
); 
4669         h 
+= d 
+ 2 * HEADER_OFFSET_Y 
+ EXTRA_HEIGHT
; 
4671         // only update if changed 
4672         if ( h 
!= (int)m_headerHeight 
) 
4674             m_headerHeight 
= (size_t)h
; 
4675             m_header_win
->SetSize(m_header_win
->GetSize().x
, m_headerHeight
); 
4680 void wxTreeListCtrl::DoHeaderLayout() 
4683     GetClientSize(&w
, &h
); 
4686         m_header_win
->SetSize(0, 0, w
, m_headerHeight
); 
4687         m_header_win
->Refresh(false); 
4690         m_main_win
->SetSize(0, m_headerHeight 
+ 1, w
, h 
- m_headerHeight 
- 1); 
4693 void wxTreeListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
4699 size_t wxTreeListCtrl::GetCount() const { return m_main_win
->GetCount(); } 
4701 unsigned int wxTreeListCtrl::GetIndent() const 
4702 { return m_main_win
->GetIndent(); } 
4704 void wxTreeListCtrl::SetIndent(unsigned int indent
) 
4705 { m_main_win
->SetIndent(indent
); } 
4707 unsigned int wxTreeListCtrl::GetLineSpacing() const 
4708 { return m_main_win
->GetLineSpacing(); } 
4710 void wxTreeListCtrl::SetLineSpacing(unsigned int spacing
) 
4711 { m_main_win
->SetLineSpacing(spacing
); } 
4713 wxImageList
* wxTreeListCtrl::GetImageList() const 
4714 { return m_main_win
->GetImageList(); } 
4716 wxImageList
* wxTreeListCtrl::GetStateImageList() const 
4717 { return m_main_win
->GetStateImageList(); } 
4719 wxImageList
* wxTreeListCtrl::GetButtonsImageList() const 
4720 { return m_main_win
->GetButtonsImageList(); } 
4722 void wxTreeListCtrl::SetImageList(wxImageList
* imageList
) 
4723 { m_main_win
->SetImageList(imageList
); } 
4725 void wxTreeListCtrl::SetStateImageList(wxImageList
* imageList
) 
4726 { m_main_win
->SetStateImageList(imageList
); } 
4728 void wxTreeListCtrl::SetButtonsImageList(wxImageList
* imageList
) 
4729 { m_main_win
->SetButtonsImageList(imageList
); } 
4731 void wxTreeListCtrl::AssignImageList(wxImageList
* imageList
) 
4732 { m_main_win
->AssignImageList(imageList
); } 
4734 void wxTreeListCtrl::AssignStateImageList(wxImageList
* imageList
) 
4735 { m_main_win
->AssignStateImageList(imageList
); } 
4737 void wxTreeListCtrl::AssignButtonsImageList(wxImageList
* imageList
) 
4738 { m_main_win
->AssignButtonsImageList(imageList
); } 
4740 wxString 
wxTreeListCtrl::GetItemText(const wxTreeItemId
& item
, size_t column
) 
4742 { return m_main_win
->GetItemText(item
, column
); } 
4744 int wxTreeListCtrl::GetItemImage(const wxTreeItemId
& item
, size_t column
, 
4745                                  wxTreeItemIcon which
) const 
4746 { return m_main_win
->GetItemImage(item
, column
, which
); } 
4748 wxTreeItemData
* wxTreeListCtrl::GetItemData(const wxTreeItemId
& item
) const 
4749 { return m_main_win
->GetItemData(item
); } 
4751 bool wxTreeListCtrl::GetItemBold(const wxTreeItemId
& item
) const 
4752 { return m_main_win
->GetItemBold(item
); } 
4754 wxColour 
wxTreeListCtrl::GetItemTextColour(const wxTreeItemId
& item
) const 
4755 { return m_main_win
->GetItemTextColour(item
); } 
4757 wxColour 
wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId
& item
) 
4759 { return m_main_win
->GetItemBackgroundColour(item
); } 
4761 wxFont 
wxTreeListCtrl::GetItemFont(const wxTreeItemId
& item
) const 
4762 { return m_main_win
->GetItemFont(item
); } 
4765 void wxTreeListCtrl::SetItemText(const wxTreeItemId
& item
, size_t column
, 
4766                                  const wxString
& text
) 
4767 { m_main_win
->SetItemText(item
, column
, text
); } 
4769 void wxTreeListCtrl::SetItemImage(const wxTreeItemId
& item
, 
4772                                   wxTreeItemIcon which
) 
4773 { m_main_win
->SetItemImage(item
, column
, image
, which
); } 
4775 void wxTreeListCtrl::SetItemData(const wxTreeItemId
& item
, 
4776                                  wxTreeItemData
* data
) 
4777 { m_main_win
->SetItemData(item
, data
); } 
4779 void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId
& item
, bool has
) 
4780 { m_main_win
->SetItemHasChildren(item
, has
); } 
4782 void wxTreeListCtrl::SetItemBold(const wxTreeItemId
& item
, bool bold
) 
4783 { m_main_win
->SetItemBold(item
, bold
); } 
4785 void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId
& item
, 
4786                                        const wxColour
& col
) 
4787 { m_main_win
->SetItemTextColour(item
, col
); } 
4789 void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId
& item
, 
4790                                              const wxColour
& col
) 
4791 { m_main_win
->SetItemBackgroundColour(item
, col
); } 
4793 void wxTreeListCtrl::SetItemFont(const wxTreeItemId
& item
, 
4795 { m_main_win
->SetItemFont(item
, font
); } 
4797 bool wxTreeListCtrl::SetFont(const wxFont
& font
) 
4801         m_header_win
->SetFont(font
); 
4802         CalculateAndSetHeaderHeight(); 
4805         return m_main_win
->SetFont(font
); 
4809 void wxTreeListCtrl::SetWindowStyle(const long style
) 
4812         m_main_win
->SetWindowStyle(style
); 
4813     // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win 
4816 long wxTreeListCtrl::GetWindowStyle() const 
4818     long style 
= m_windowStyle
; 
4820         style 
|= m_main_win
->GetWindowStyle(); 
4824 bool wxTreeListCtrl::IsVisible(const wxTreeItemId
& item
) const 
4825 { return m_main_win
->IsVisible(item
); } 
4827 bool wxTreeListCtrl::ItemHasChildren(const wxTreeItemId
& item
) const 
4828 { return m_main_win
->ItemHasChildren(item
); } 
4830 bool wxTreeListCtrl::IsExpanded(const wxTreeItemId
& item
) const 
4831 { return m_main_win
->IsExpanded(item
); } 
4833 bool wxTreeListCtrl::IsSelected(const wxTreeItemId
& item
) const 
4834 { return m_main_win
->IsSelected(item
); } 
4836 bool wxTreeListCtrl::IsBold(const wxTreeItemId
& item
) const 
4837 { return m_main_win
->IsBold(item
); } 
4839 size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId
& item
, bool rec
) 
4840 { return m_main_win
->GetChildrenCount(item
, rec
); } 
4842 wxTreeItemId 
wxTreeListCtrl::GetRootItem() const 
4843 { return m_main_win
->GetRootItem(); } 
4845 wxTreeItemId 
wxTreeListCtrl::GetSelection() const 
4846 { return m_main_win
->GetSelection(); } 
4848 size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds
& arr
) const 
4849 { return m_main_win
->GetSelections(arr
); } 
4851 wxTreeItemId 
wxTreeListCtrl::GetItemParent(const wxTreeItemId
& item
) const 
4852 { return m_main_win
->GetItemParent(item
); } 
4854 #if !wxCHECK_VERSION(2, 5, 0) 
4855 wxTreeItemId 
wxTreeListCtrl::GetFirstChild(const wxTreeItemId
& item
, 
4858 wxTreeItemId 
wxTreeListCtrl::GetFirstChild(const wxTreeItemId
& item
, 
4859                                            wxTreeItemIdValue
& cookie
) const 
4861 { return m_main_win
->GetFirstChild(item
, cookie
); } 
4863 #if !wxCHECK_VERSION(2, 5, 0) 
4864 wxTreeItemId 
wxTreeListCtrl::GetNextChild(const wxTreeItemId
& item
, 
4867 wxTreeItemId 
wxTreeListCtrl::GetNextChild(const wxTreeItemId
& item
, 
4868                                           wxTreeItemIdValue
& cookie
) const 
4870 { return m_main_win
->GetNextChild(item
, cookie
); } 
4872 #if !wxCHECK_VERSION(2, 5, 0) 
4873 wxTreeItemId 
wxTreeListCtrl::GetPrevChild(const wxTreeItemId
& item
, 
4876 wxTreeItemId 
wxTreeListCtrl::GetPrevChild(const wxTreeItemId
& item
, 
4877                                           wxTreeItemIdValue
& cookie
) const 
4879 { return m_main_win
->GetPrevChild(item
, cookie
); } 
4881 wxTreeItemId 
wxTreeListCtrl::GetLastChild(const wxTreeItemId
& item
) const 
4882 { return m_main_win
->GetLastChild(item
); } 
4884 wxTreeItemId 
wxTreeListCtrl::GetNextSibling(const wxTreeItemId
& item
) const 
4885 { return m_main_win
->GetNextSibling(item
); } 
4887 wxTreeItemId 
wxTreeListCtrl::GetPrevSibling(const wxTreeItemId
& item
) const 
4888 { return m_main_win
->GetPrevSibling(item
); } 
4890 wxTreeItemId 
wxTreeListCtrl::GetFirstVisibleItem() const 
4891 { return m_main_win
->GetFirstVisibleItem(); } 
4893 wxTreeItemId 
wxTreeListCtrl::GetNextVisible(const wxTreeItemId
& item
) const 
4894 { return m_main_win
->GetNextVisible(item
); } 
4896 wxTreeItemId 
wxTreeListCtrl::GetPrevVisible(const wxTreeItemId
& item
) const 
4897 { return m_main_win
->GetPrevVisible(item
); } 
4899 wxTreeItemId 
wxTreeListCtrl::GetNext(const wxTreeItemId
& item
) const 
4900 { return m_main_win
->GetNext(item
); } 
4902 wxTreeItemId 
wxTreeListCtrl::AddRoot(const wxString
& text
, int image
, 
4903                                      int selectedImage
, wxTreeItemData
* data
) 
4904 { return m_main_win
->AddRoot(text
, image
, selectedImage
, data
); } 
4906 wxTreeItemId 
wxTreeListCtrl::PrependItem(const wxTreeItemId
& parent
, 
4907                                          const wxString
& text
, int image
, 
4909                                          wxTreeItemData
* data
) 
4910 { return m_main_win
->PrependItem(parent
, text
, image
, selectedImage
, data
); } 
4912 wxTreeItemId 
wxTreeListCtrl::InsertItem(const wxTreeItemId
& parent
, 
4913                                         const wxTreeItemId
& previous
, 
4914                                         const wxString
& text
, int image
, 
4916                                         wxTreeItemData
* data
) 
4918     return m_main_win
->InsertItem(parent
, previous
, text
, image
, 
4919                                   selectedImage
, data
); 
4922 wxTreeItemId 
wxTreeListCtrl::InsertItem(const wxTreeItemId
& parent
, 
4924                                         const wxString
& text
, int image
, 
4926                                         wxTreeItemData
* data
) 
4928     return m_main_win
->InsertItem(parent
, index
, text
, image
, 
4929                                   selectedImage
, data
); 
4932 wxTreeItemId 
wxTreeListCtrl::AppendItem(const wxTreeItemId
& parent
, 
4933                                         const wxString
& text
, int image
, 
4935                                         wxTreeItemData
* data
) 
4936 { return m_main_win
->AppendItem(parent
, text
, image
, selectedImage
, data
); } 
4938 void wxTreeListCtrl::Delete(const wxTreeItemId
& item
) 
4939 { m_main_win
->Delete(item
); } 
4941 void wxTreeListCtrl::DeleteChildren(const wxTreeItemId
& item
) 
4942 { m_main_win
->DeleteChildren(item
); } 
4944 void wxTreeListCtrl::DeleteAllItems() 
4945 { m_main_win
->DeleteAllItems(); } 
4947 void wxTreeListCtrl::Expand(const wxTreeItemId
& item
) 
4948 { m_main_win
->Expand(item
); } 
4950 void wxTreeListCtrl::ExpandAll(const wxTreeItemId
& item
) 
4951 { m_main_win
->ExpandAll(item
); } 
4953 void wxTreeListCtrl::Collapse(const wxTreeItemId
& item
) 
4954 { m_main_win
->Collapse(item
); } 
4956 void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId
& item
) 
4957 { m_main_win
->CollapseAndReset(item
); } 
4959 void wxTreeListCtrl::Toggle(const wxTreeItemId
& item
) 
4960 { m_main_win
->Toggle(item
); } 
4962 void wxTreeListCtrl::Unselect() 
4963 { m_main_win
->Unselect(); } 
4965 void wxTreeListCtrl::UnselectAll() 
4966 { m_main_win
->UnselectAll(); } 
4968 void wxTreeListCtrl::SelectItem(const wxTreeItemId
& item
, bool unselect_others
, 
4969                                 bool extended_select
) 
4970 { m_main_win
->SelectItem(item
, unselect_others
, extended_select
); } 
4972 void wxTreeListCtrl::SelectAll(bool extended_select
) 
4973 { m_main_win
->SelectAll(extended_select
); } 
4975 void wxTreeListCtrl::EnsureVisible(const wxTreeItemId
& item
) 
4976 { m_main_win
->EnsureVisible(item
); } 
4978 void wxTreeListCtrl::ScrollTo(const wxTreeItemId
& item
) 
4979 { m_main_win
->ScrollTo(item
); } 
4981 wxTreeItemId 
wxTreeListCtrl::HitTest(const wxPoint
& pos
, int& flags
, 
4984     return m_main_win
->HitTest(pos
, flags
, column
); 
4987 bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId
& item
, wxRect
& rect
, 
4988                                      bool textOnly
) const 
4989 { return m_main_win
->GetBoundingRect(item
, rect
, textOnly
); } 
4991 void wxTreeListCtrl::Edit(const wxTreeItemId
& item
) 
4992 { m_main_win
->Edit(item
); } 
4994 int wxTreeListCtrl::OnCompareItems(const wxTreeItemId
& item1
, 
4995                                    const wxTreeItemId
& item2
) 
4997     // ALB: do the comparison here, and not delegate to m_main_win, in order 
4998     // to let the user override it 
4999     //return m_main_win->OnCompareItems(item1, item2); 
5000     return wxStrcmp(GetItemText(item1
), GetItemText(item2
)); 
5003 void wxTreeListCtrl::SortChildren(const wxTreeItemId
& item
) 
5004 { m_main_win
->SortChildren(item
); } 
5006 wxTreeItemId 
wxTreeListCtrl::FindItem (const wxTreeItemId
& item
, const wxString
& str
, int flags
) 
5007 { return m_main_win
->FindItem (item
, str
, flags
); } 
5009 bool wxTreeListCtrl::SetBackgroundColour(const wxColour
& colour
) 
5011     if (!m_main_win
) return false; 
5012     return m_main_win
->SetBackgroundColour(colour
);  
5015 bool wxTreeListCtrl::SetForegroundColour(const wxColour
& colour
) 
5017     if (!m_main_win
) return false; 
5018     return m_main_win
->SetForegroundColour(colour
);  
5021 size_t wxTreeListCtrl::GetColumnCount() const 
5022 { return m_main_win
->GetColumnCount(); } 
5024 void wxTreeListCtrl::SetColumnWidth(size_t column
, size_t width
) 
5025 { m_header_win
->SetColumnWidth(column
, width
); } 
5027 int wxTreeListCtrl::GetColumnWidth(size_t column
) const 
5028 { return m_header_win
->GetColumnWidth(column
); } 
5030 void wxTreeListCtrl::SetMainColumn(size_t column
) 
5031 { m_main_win
->SetMainColumn(column
); } 
5033 size_t wxTreeListCtrl::GetMainColumn() const 
5034 { return m_main_win
->GetMainColumn(); } 
5036 void wxTreeListCtrl::SetColumnText(size_t column
, const wxString
& text
) 
5038     m_header_win
->SetColumnText(column
, text
); 
5039     m_header_win
->Refresh(); 
5042 wxString 
wxTreeListCtrl::GetColumnText(size_t column
) const 
5043 { return m_header_win
->GetColumnText(column
); } 
5045 void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo
& col
) 
5047     m_header_win
->AddColumn(col
); 
5051 void wxTreeListCtrl::InsertColumn(size_t before
, 
5052                                   const wxTreeListColumnInfo
& col
) 
5053 { m_header_win
->InsertColumn(before
, col
); } 
5055 void wxTreeListCtrl::RemoveColumn(size_t column
) 
5056 { m_header_win
->RemoveColumn(column
); } 
5058 void wxTreeListCtrl::SetColumn(size_t column
, const wxTreeListColumnInfo
& col
) 
5059 { m_header_win
->SetColumn(column
, col
); } 
5061 const wxTreeListColumnInfo
& wxTreeListCtrl::GetColumn(size_t column
) const 
5062 { return m_header_win
->GetColumn(column
); } 
5064 wxTreeListColumnInfo
& wxTreeListCtrl::GetColumn(size_t column
) 
5065 { return m_header_win
->GetColumn(column
); } 
5067 void wxTreeListCtrl::SetColumnImage(size_t column
, int image
) 
5069     m_header_win
->SetColumn(column
, GetColumn(column
).SetImage(image
)); 
5072 int wxTreeListCtrl::GetColumnImage(size_t column
) const 
5074     return m_header_win
->GetColumn(column
).GetImage(); 
5077 void wxTreeListCtrl::ShowColumn(size_t column
, bool shown
) 
5079     wxASSERT_MSG( column 
!= GetMainColumn(), 
5080                   wxT("The main column may not be hidden") ); 
5081     m_header_win
->SetColumn(column
, GetColumn(column
).SetShown(GetMainColumn()? true: shown
)); 
5084 bool wxTreeListCtrl::IsColumnShown(size_t column
) const 
5086     return m_header_win
->GetColumn(column
).GetShown(); 
5089 void wxTreeListCtrl::SetColumnAlignment(size_t column
, 
5090                                         wxTreeListColumnAlign align
) 
5092     m_header_win
->SetColumn(column
, GetColumn(column
).SetAlignment(align
)); 
5095 wxTreeListColumnAlign 
wxTreeListCtrl::GetColumnAlignment(size_t column
) const 
5097     return m_header_win
->GetColumn(column
).GetAlignment(); 
5100 void wxTreeListCtrl::Refresh(bool erase
, const wxRect
* rect
) 
5102     m_main_win
->Refresh(erase
, rect
); 
5103     m_header_win
->Refresh(erase
, rect
); 
5106 void wxTreeListCtrl::SetFocus() 
5107 { m_main_win
->SetFocus(); } 
5110 wxSize 
wxTreeListCtrl::DoGetBestSize() const 
5112     // something is better than nothing... 
5113     return wxSize(100,80); 
5116 // Process the tooltip event, to speed up event processing. 
5117 // Doesn't actually get a tooltip. 
5118 void wxTreeListCtrl::OnGetToolTip( wxTreeEvent 
&event 
)