1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        treelistctrl.cpp (derived by treectlg.h) 
   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) 1998 Robert Roebling, Julian Smart and Markus Holzem 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 // =========================================================================== 
  15 // =========================================================================== 
  17 // --------------------------------------------------------------------------- 
  19 // --------------------------------------------------------------------------- 
  21 #if defined(__GNUG__) && !defined(__APPLE__) 
  22   #pragma implementation "treelistctrl.h" 
  25 // For compilers that support precompilation, includes "wx.h". 
  26 #include "wx/wxprec.h" 
  33 #include <wx/treebase.h> 
  35 #include <wx/textctrl.h> 
  36 #include <wx/imaglist.h> 
  37 #include <wx/settings.h> 
  38 #include <wx/dcclient.h> 
  39 #include <wx/dcscreen.h> 
  40 #include <wx/scrolwin.h> 
  42 //#include "wx/gizmos/treelistctrl.h" 
  43 #include "treelistctrl.h" 
  48     #include <wx/gtk/win_gtk.h> 
  51 // --------------------------------------------------------------------------- 
  53 // --------------------------------------------------------------------------- 
  57 WX_DEFINE_ARRAY(wxTreeListItem 
*, wxArrayTreeListItems
); 
  59 #include <wx/dynarray.h> 
  60 WX_DECLARE_OBJARRAY(wxTreeListColumnInfo
, wxArrayTreeListColumnInfo
); 
  61 #include <wx/arrimpl.cpp> 
  62 WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo
); 
  64 #if !wxCHECK_VERSION(2, 3, 3) 
  65 WX_DEFINE_ARRAY(short, wxArrayShort
); 
  69 // -------------------------------------------------------------------------- 
  71 // -------------------------------------------------------------------------- 
  73 static const int NO_IMAGE 
= -1; 
  75 #define PIXELS_PER_UNIT 10 
  77 const wxChar
* wxTreeListCtrlNameStr 
= wxT("treelistctrl"); 
  79 static wxTreeListColumnInfo wxInvalidTreeListColumnInfo
; 
  82 // --------------------------------------------------------------------------- 
  84 // --------------------------------------------------------------------------- 
  85 //----------------------------------------------------------------------------- 
  86 //  wxTreeListHeaderWindow (internal) 
  87 //----------------------------------------------------------------------------- 
  89 class  wxTreeListHeaderWindow 
: public wxWindow
 
  92     wxTreeListMainWindow    
*m_owner
; 
  93     wxCursor          
*m_currentCursor
; 
  94     wxCursor          
*m_resizeCursor
; 
  97     // column being resized 
 100     // divider line position in logical (unscrolled) coords 
 103     // minimal position beyond which the divider line can't be dragged in 
 107     wxArrayTreeListColumnInfo m_columns
; 
 109     // total width of the columns 
 110     int m_total_col_width
; 
 114     wxTreeListHeaderWindow(); 
 116     wxTreeListHeaderWindow( wxWindow 
*win
, 
 118                         wxTreeListMainWindow 
*owner
, 
 119                         const wxPoint 
&pos 
= wxDefaultPosition
, 
 120                         const wxSize 
&size 
= wxDefaultSize
, 
 122                         const wxString 
&name 
= wxT("wxtreelistctrlcolumntitles") ); 
 124     virtual ~wxTreeListHeaderWindow(); 
 126     void DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
); 
 128     void AdjustDC(wxDC
& dc
); 
 130     void OnPaint( wxPaintEvent 
&event 
); 
 131     void OnMouse( wxMouseEvent 
&event 
); 
 132     void OnSetFocus( wxFocusEvent 
&event 
); 
 135     // columns manipulation 
 137     size_t GetColumnCount() const { return m_columns
.GetCount(); } 
 139     void AddColumn(const wxTreeListColumnInfo
& col
); 
 141     void InsertColumn(size_t before
, const wxTreeListColumnInfo
& col
); 
 143     void RemoveColumn(size_t column
); 
 145     void SetColumn(size_t column
, const wxTreeListColumnInfo
& info
); 
 146     const wxTreeListColumnInfo
& GetColumn(size_t column
) const 
 148         wxCHECK_MSG(column 
< GetColumnCount(), wxInvalidTreeListColumnInfo
, wxT("Invalid column")); 
 149         return m_columns
[column
]; 
 151     wxTreeListColumnInfo
& GetColumn(size_t column
) 
 153         wxCHECK_MSG(column 
< GetColumnCount(), wxInvalidTreeListColumnInfo
, wxT("Invalid column")); 
 154         return m_columns
[column
]; 
 157     void SetColumnWidth(size_t column
, size_t width
); 
 159     void SetColumnText(size_t column
, const wxString
& text
) 
 161         wxCHECK_RET(column 
< GetColumnCount(), wxT("Invalid column")); 
 162         m_columns
[column
].SetText(text
); 
 165     wxString 
GetColumnText(size_t column
) const 
 167         wxCHECK_MSG(column 
< GetColumnCount(), wxEmptyString
, wxT("Invalid column")); 
 168         return m_columns
[column
].GetText(); 
 171     int GetColumnWidth(size_t column
) const 
 173         wxCHECK_MSG(column 
< GetColumnCount(), -1, wxT("Invalid column")); 
 174         return m_columns
[column
].GetWidth(); 
 177     int GetWidth() const { return m_total_col_width
; } 
 183     // common part of all ctors 
 186     void SendListEvent(wxEventType type
, wxPoint pos
); 
 188     DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow
) 
 189     DECLARE_EVENT_TABLE() 
 193 // this is the "true" control 
 194 class  wxTreeListMainWindow
: public wxScrolledWindow
 
 199     wxTreeListMainWindow() { Init(); } 
 201     wxTreeListMainWindow(wxTreeListCtrl 
*parent
, wxWindowID id 
= -1, 
 202                const wxPoint
& pos 
= wxDefaultPosition
, 
 203                const wxSize
& size 
= wxDefaultSize
, 
 204                long style 
= wxTR_DEFAULT_STYLE
, 
 205                const wxValidator 
&validator 
= wxDefaultValidator
, 
 206                const wxString
& name 
= wxT("wxtreelistmainwindow")) 
 209         Create(parent
, id
, pos
, size
, style
, validator
, name
); 
 212     virtual ~wxTreeListMainWindow(); 
 214     bool Create(wxTreeListCtrl 
*parent
, wxWindowID id 
= -1, 
 215                 const wxPoint
& pos 
= wxDefaultPosition
, 
 216                 const wxSize
& size 
= wxDefaultSize
, 
 217                 long style 
= wxTR_DEFAULT_STYLE
, 
 218                 const wxValidator 
&validator 
= wxDefaultValidator
, 
 219                 const wxString
& name 
= wxT("wxtreelistctrl")); 
 224         // get the total number of items in the control 
 225     size_t GetCount() const; 
 227         // indent is the number of pixels the children are indented relative to 
 228         // the parents position. SetIndent() also redraws the control 
 230     unsigned int GetIndent() const { return m_indent
; } 
 231     void SetIndent(unsigned int indent
); 
 233         // spacing is the number of pixels between the start and the Text 
 234     unsigned int GetSpacing() const { return m_spacing
; } 
 235     void SetSpacing(unsigned int spacing
); 
 237     // see wxTreeListCtrl for the meaning 
 238     unsigned int GetLineSpacing() const { return m_linespacing
; } 
 239     void SetLineSpacing(unsigned int spacing
); 
 241         // image list: these functions allow to associate an image list with 
 242         // the control and retrieve it. Note that when assigned with 
 243         // SetImageList, the control does _not_ delete 
 244         // the associated image list when it's deleted in order to allow image 
 245         // lists to be shared between different controls. If you use 
 246         // AssignImageList, the control _does_ delete the image list. 
 248         // The normal image list is for the icons which correspond to the 
 249         // normal tree item state (whether it is selected or not). 
 250         // Additionally, the application might choose to show a state icon 
 251         // which corresponds to an app-defined item state (for example, 
 252         // checked/unchecked) which are taken from the state image list. 
 253     wxImageList 
*GetImageList() const; 
 254     wxImageList 
*GetStateImageList() const; 
 255     wxImageList 
*GetButtonsImageList() const; 
 257     void SetImageList(wxImageList 
*imageList
); 
 258     void SetStateImageList(wxImageList 
*imageList
); 
 259     void SetButtonsImageList(wxImageList 
*imageList
); 
 260     void AssignImageList(wxImageList 
*imageList
); 
 261     void AssignStateImageList(wxImageList 
*imageList
); 
 262     void AssignButtonsImageList(wxImageList 
*imageList
); 
 264     // Functions to work with tree ctrl items. 
 269         // retrieve item's label 
 270     wxString 
GetItemText(const wxTreeItemId
& item
) const 
 271     { return GetItemText(item
, GetMainColumn()); } 
 272         // get one of the images associated with the item (normal by default) 
 273     int GetItemImage(const wxTreeItemId
& item
, 
 274                      wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const 
 275     { return GetItemImage(item
, GetMainColumn(), which
); } 
 277         // get the data associated with the item 
 278     wxTreeItemData 
*GetItemData(const wxTreeItemId
& item
) const; 
 280     bool GetItemBold(const wxTreeItemId
& item
) const; 
 281     wxColour 
GetItemTextColour(const wxTreeItemId
& item
) const; 
 282     wxColour 
GetItemBackgroundColour(const wxTreeItemId
& item
) const; 
 283     wxFont 
GetItemFont(const wxTreeItemId
& item
) const; 
 289     void SetItemText(const wxTreeItemId
& item
, const wxString
& text
) 
 290     { SetItemText(item
, GetMainColumn(), text
); } 
 292         // get one of the images associated with the item (normal by default) 
 293     void SetItemImage(const wxTreeItemId
& item
, int image
, 
 294                       wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) 
 295     { SetItemImage(item
, GetMainColumn(), image
, which
); } 
 297         // associate some data with the item 
 298     void SetItemData(const wxTreeItemId
& item
, wxTreeItemData 
*data
); 
 300         // force appearance of [+] button near the item. This is useful to 
 301         // allow the user to expand the items which don't have any children now 
 302         // - but instead add them only when needed, thus minimizing memory 
 303         // usage and loading time. 
 304     void SetItemHasChildren(const wxTreeItemId
& item
, bool has 
= TRUE
); 
 306         // the item will be shown in bold 
 307     void SetItemBold(const wxTreeItemId
& item
, bool bold 
= TRUE
); 
 309         // set the item's text colour 
 310     void SetItemTextColour(const wxTreeItemId
& item
, const wxColour
& col
); 
 312         // set the item's background colour 
 313     void SetItemBackgroundColour(const wxTreeItemId
& item
, 
 314                                  const wxColour
& col
); 
 316         // set the item's font (should be of the same height for all items) 
 317     void SetItemFont(const wxTreeItemId
& item
, const wxFont
& font
); 
 319         // set the window font 
 320     virtual bool SetFont( const wxFont 
&font 
); 
 322        // set the styles.  No need to specify a GetWindowStyle here since 
 323        // the base wxWindow member function will do it for us 
 324     void SetWindowStyle(const long styles
); 
 326     // item status inquiries 
 327     // --------------------- 
 329         // is the item visible (it might be outside the view or not expanded)? 
 330     bool IsVisible(const wxTreeItemId
& item
) const; 
 331         // does the item has any children? 
 332     bool HasChildren(const wxTreeItemId
& item
) const 
 333       { return ItemHasChildren(item
); } 
 334     bool ItemHasChildren(const wxTreeItemId
& item
) const; 
 335         // is the item expanded (only makes sense if HasChildren())? 
 336     bool IsExpanded(const wxTreeItemId
& item
) const; 
 337         // is this item currently selected (the same as has focus)? 
 338     bool IsSelected(const wxTreeItemId
& item
) const; 
 339         // is item text in bold font? 
 340     bool IsBold(const wxTreeItemId
& item
) const; 
 341         // does the layout include space for a button? 
 343     // number of children 
 344     // ------------------ 
 346         // if 'recursively' is FALSE, only immediate children count, otherwise 
 347         // the returned number is the number of all items in this branch 
 348     size_t GetChildrenCount(const wxTreeItemId
& item
, bool recursively 
= TRUE
); 
 353     // wxTreeItemId.IsOk() will return FALSE if there is no such item 
 355         // get the root tree item 
 356     wxTreeItemId 
GetRootItem() const { return m_anchor
; } 
 358         // get the item currently selected (may return NULL if no selection) 
 359     wxTreeItemId 
GetSelection() const { return m_current
; } 
 361         // get the items currently selected, return the number of such item 
 362     size_t GetSelections(wxArrayTreeItemIds
&) const; 
 364         // get the parent of this item (may return NULL if root) 
 365     wxTreeItemId 
GetParent(const wxTreeItemId
& item
) const; 
 367         // for this enumeration function you must pass in a "cookie" parameter 
 368         // which is opaque for the application but is necessary for the library 
 369         // to make these functions reentrant (i.e. allow more than one 
 370         // enumeration on one and the same object simultaneously). Of course, 
 371         // the "cookie" passed to GetFirstChild() and GetNextChild() should be 
 374         // get the first child of this item 
 375     wxTreeItemId 
GetFirstChild(const wxTreeItemId
& item
, long& cookie
) const; 
 376         // get the next child 
 377     wxTreeItemId 
GetNextChild(const wxTreeItemId
& item
, long& cookie
) const; 
 378         // get the last child of this item - this method doesn't use cookies 
 379     wxTreeItemId 
GetLastChild(const wxTreeItemId
& item
) const; 
 381         // get the next sibling of this item 
 382     wxTreeItemId 
GetNextSibling(const wxTreeItemId
& item
) const; 
 383         // get the previous sibling 
 384     wxTreeItemId 
GetPrevSibling(const wxTreeItemId
& item
) const; 
 386         // get first visible item 
 387     wxTreeItemId 
GetFirstVisibleItem() const; 
 388         // get the next visible item: item must be visible itself! 
 389         // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem() 
 390     wxTreeItemId 
GetNextVisible(const wxTreeItemId
& item
) const; 
 391         // get the previous visible item: item must be visible itself! 
 392     wxTreeItemId 
GetPrevVisible(const wxTreeItemId
& item
) const; 
 394         // Only for internal use right now, but should probably be public 
 395     wxTreeItemId 
GetNext(const wxTreeItemId
& item
) const; 
 400         // add the root node to the tree 
 401     wxTreeItemId 
AddRoot(const wxString
& text
, 
 402                          int image 
= -1, int selectedImage 
= -1, 
 403                          wxTreeItemData 
*data 
= NULL
); 
 405         // insert a new item in as the first child of the parent 
 406     wxTreeItemId 
PrependItem(const wxTreeItemId
& parent
, 
 407                              const wxString
& text
, 
 408                              int image 
= -1, int selectedImage 
= -1, 
 409                              wxTreeItemData 
*data 
= NULL
); 
 411         // insert a new item after a given one 
 412     wxTreeItemId 
InsertItem(const wxTreeItemId
& parent
, 
 413                             const wxTreeItemId
& idPrevious
, 
 414                             const wxString
& text
, 
 415                             int image 
= -1, int selectedImage 
= -1, 
 416                             wxTreeItemData 
*data 
= NULL
); 
 418         // insert a new item before the one with the given index 
 419     wxTreeItemId 
InsertItem(const wxTreeItemId
& parent
, 
 421                             const wxString
& text
, 
 422                             int image 
= -1, int selectedImage 
= -1, 
 423                             wxTreeItemData 
*data 
= NULL
); 
 425         // insert a new item in as the last child of the parent 
 426     wxTreeItemId 
AppendItem(const wxTreeItemId
& parent
, 
 427                             const wxString
& text
, 
 428                             int image 
= -1, int selectedImage 
= -1, 
 429                             wxTreeItemData 
*data 
= NULL
); 
 431         // delete this item and associated data if any 
 432     void Delete(const wxTreeItemId
& item
); 
 433         // delete all children (but don't delete the item itself) 
 434         // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events 
 435     void DeleteChildren(const wxTreeItemId
& item
); 
 436         // delete all items from the tree 
 437         // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events 
 438     void DeleteAllItems(); 
 441     void Expand(const wxTreeItemId
& item
); 
 442         // expand this item and all subitems recursively 
 443     void ExpandAll(const wxTreeItemId
& item
); 
 444         // collapse the item without removing its children 
 445     void Collapse(const wxTreeItemId
& item
); 
 446         // collapse the item and remove all children 
 447     void CollapseAndReset(const wxTreeItemId
& item
); 
 448         // toggles the current state 
 449     void Toggle(const wxTreeItemId
& item
); 
 451         // remove the selection from currently selected item (if any) 
 455     void SelectItem(const wxTreeItemId
& item
, bool unselect_others
=TRUE
, 
 456                     bool extended_select
=FALSE
); 
 457         // make sure this item is visible (expanding the parent item and/or 
 458         // scrolling to this item if necessary) 
 459     void EnsureVisible(const wxTreeItemId
& item
); 
 460         // scroll to this item (but don't expand its parent) 
 461     void ScrollTo(const wxTreeItemId
& item
); 
 462     void AdjustMyScrollbars(); 
 464         // The first function is more portable (because easier to implement 
 465         // on other platforms), but the second one returns some extra info. 
 466     wxTreeItemId 
HitTest(const wxPoint
& point
) 
 467         { int dummy
; return HitTest(point
, dummy
); } 
 468     wxTreeItemId 
HitTest(const wxPoint
& point
, int& flags
) 
 469     { int col
; return HitTest(point
, flags
, col
); } 
 471     wxTreeItemId 
HitTest(const wxPoint
& point
, int& flags
, int& column
); 
 474         // get the bounding rectangle of the item (or of its label only) 
 475     bool GetBoundingRect(const wxTreeItemId
& item
, 
 477                          bool textOnly 
= FALSE
) const; 
 479         // Start editing the item label: this (temporarily) replaces the item 
 480         // with a one line edit control. The item will be selected if it hadn't 
 482     void EditLabel( const wxTreeItemId
& item 
) { Edit( item 
); } 
 483     void Edit( const wxTreeItemId
& item 
); 
 486         // this function is called to compare 2 items and should return -1, 0 
 487         // or +1 if the first item is less than, equal to or greater than the 
 488         // second one. The base class version performs alphabetic comparaison 
 489         // of item labels (GetText) 
 490     virtual int OnCompareItems(const wxTreeItemId
& item1
, 
 491                                const wxTreeItemId
& item2
); 
 492         // sort the children of this item using OnCompareItems 
 494         // NB: this function is not reentrant and not MT-safe (FIXME)! 
 495     void SortChildren(const wxTreeItemId
& item
); 
 497     // deprecated functions: use Set/GetItemImage directly 
 498         // get the selected item image 
 499     int GetItemSelectedImage(const wxTreeItemId
& item
) const 
 500         { return GetItemImage(item
, wxTreeItemIcon_Selected
); } 
 501         // set the selected item image 
 502     void SetItemSelectedImage(const wxTreeItemId
& item
, int image
) 
 503         { SetItemImage(item
, image
, wxTreeItemIcon_Selected
); } 
 505     // implementation only from now on 
 507     // overridden base class virtuals 
 508     virtual bool SetBackgroundColour(const wxColour
& colour
); 
 509     virtual bool SetForegroundColour(const wxColour
& colour
); 
 512     void OnPaint( wxPaintEvent 
&event 
); 
 513     void OnSetFocus( wxFocusEvent 
&event 
); 
 514     void OnKillFocus( wxFocusEvent 
&event 
); 
 515     void OnChar( wxKeyEvent 
&event 
); 
 516     void OnMouse( wxMouseEvent 
&event 
); 
 517     void OnIdle( wxIdleEvent 
&event 
); 
 518     void OnSize(wxSizeEvent
& event
); // ALB 
 519     void OnScroll(wxScrollWinEvent
& event
); // ALB 
 521     // implementation helpers 
 522     void SendDeleteEvent(wxTreeListItem 
*itemBeingDeleted
); 
 524     void DrawBorder(const wxTreeItemId
& item
); 
 525     void DrawLine(const wxTreeItemId
& item
, bool below
); 
 527     size_t GetColumnCount() const 
 528     { return m_owner
->GetHeaderWindow()->GetColumnCount(); } 
 530     void SetMainColumn(size_t column
) 
 532         if(column 
< GetColumnCount()) 
 533             m_main_column 
= column
; 
 535     size_t GetMainColumn() const { return m_main_column
; } 
 537     void SetItemText(const wxTreeItemId
& item
, size_t column
, 
 538                      const wxString
& text
); 
 539     wxString 
GetItemText(const wxTreeItemId
& item
, size_t column
) const; 
 541     void SetItemImage(const wxTreeItemId
& item
, size_t column
, int image
, 
 542                       wxTreeItemIcon which 
= wxTreeItemIcon_Normal
); 
 543     int GetItemImage(const wxTreeItemId
& item
, size_t column
, 
 544                      wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const; 
 546     wxTreeListCtrl
* m_owner
; // ALB 
 548     size_t m_main_column
; // ALB 
 550     friend class wxTreeListItem
; 
 551     friend class wxTreeListRenameTimer
; 
 552     friend class wxTreeListTextCtrl
; 
 557     wxTreeListItem   
*m_anchor
; 
 558     wxTreeListItem   
*m_current
, *m_key_current
, *m_currentEdit
; 
 559     unsigned short       m_indent
; 
 560     unsigned short       m_spacing
; 
 562     unsigned short       m_linespacing
; 
 564     wxBrush             
*m_hilightBrush
, 
 565                         *m_hilightUnfocusedBrush
; 
 570     bool                 m_ownsImageListNormal
, 
 571                          m_ownsImageListState
, 
 572                          m_ownsImageListButtons
; 
 573     bool                 m_isDragging
; // true between BEGIN/END drag events 
 575     bool                 m_lastOnSame
;  // last click on the same item as prev 
 576     wxImageList         
*m_imageListNormal
, 
 582     wxTreeListItem   
*m_dropTarget
; 
 583     wxCursor             m_oldCursor
;  // cursor is changed while dragging 
 584     wxTreeListItem   
*m_oldSelection
; 
 586     wxTimer             
*m_renameTimer
; 
 587     wxString             m_renameRes
; 
 589     // the common part of all ctors 
 593     wxTreeItemId 
DoInsertItem(const wxTreeItemId
& parent
, 
 595                               const wxString
& text
, 
 596                               int image
, int selectedImage
, 
 597                               wxTreeItemData 
*data
); 
 598     bool HasButtons(void) const 
 599         { return (m_imageListButtons 
!= NULL
) 
 600               || HasFlag(wxTR_TWIST_BUTTONS
|wxTR_HAS_BUTTONS
); } 
 603     void CalculateLineHeight(); 
 604     int  GetLineHeight(wxTreeListItem 
*item
) const; 
 605     void PaintLevel( wxTreeListItem 
*item
, wxDC
& dc
, int level
, int &y
, 
 607     void PaintItem( wxTreeListItem 
*item
, wxDC
& dc
); 
 609     void CalculateLevel( wxTreeListItem 
*item
, wxDC 
&dc
, int level
, int &y
, 
 611     void CalculatePositions(); 
 612     void CalculateSize( wxTreeListItem 
*item
, wxDC 
&dc 
); 
 614     void RefreshSubtree( wxTreeListItem 
*item 
); 
 615     void RefreshLine( wxTreeListItem 
*item 
); 
 617     // redraw all selected items 
 618     void RefreshSelected(); 
 620     // RefreshSelected() recursive helper 
 621     void RefreshSelectedUnder(wxTreeListItem 
*item
); 
 623     void OnRenameTimer(); 
 624     void OnRenameAccept(); 
 626     void FillArray(wxTreeListItem
*, wxArrayTreeItemIds
&) const; 
 627     void SelectItemRange( wxTreeListItem 
*item1
, wxTreeListItem 
*item2 
); 
 628     bool TagAllChildrenUntilLast(wxTreeListItem 
*crt_item
, 
 629                                  wxTreeListItem 
*last_item
, bool select
); 
 630     bool TagNextChildren(wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
, 
 632     void UnselectAllChildren( wxTreeListItem 
*item 
); 
 634     void DrawDropEffect(wxTreeListItem 
*item
); 
 637     DECLARE_EVENT_TABLE() 
 638     DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow
) 
 642 // timer used for enabling in-place edit 
 643 class  wxTreeListRenameTimer
: public wxTimer
 
 646     wxTreeListRenameTimer( wxTreeListMainWindow 
*owner 
); 
 651     wxTreeListMainWindow   
*m_owner
; 
 654 // control used for in-place edit 
 655 class  wxTreeListTextCtrl
: public wxTextCtrl
 
 658     wxTreeListTextCtrl( wxWindow 
*parent
, 
 662                         wxTreeListMainWindow 
*owner
, 
 663                         const wxString 
&value 
= wxEmptyString
, 
 664                         const wxPoint 
&pos 
= wxDefaultPosition
, 
 665                         const wxSize 
&size 
= wxDefaultSize
, 
 666                         int style 
= wxSIMPLE_BORDER
, 
 667                         const wxValidator
& validator 
= wxDefaultValidator
, 
 668                         const wxString 
&name 
= wxTextCtrlNameStr 
); 
 670     void OnChar( wxKeyEvent 
&event 
); 
 671     void OnKeyUp( wxKeyEvent 
&event 
); 
 672     void OnKillFocus( wxFocusEvent 
&event 
); 
 677     wxTreeListMainWindow  
*m_owner
; 
 678     wxString            m_startValue
; 
 681     DECLARE_EVENT_TABLE() 
 689     wxTreeListItem() { m_data 
= NULL
; } 
 690     wxTreeListItem( wxTreeListMainWindow 
*owner
, 
 691                     wxTreeListItem 
*parent
, 
 692                     const wxArrayString
& text
, 
 695                     wxTreeItemData 
*data 
); 
 700     wxArrayTreeListItems
& GetChildren() { return m_children
; } 
 702     const wxString 
GetText() const 
 704         if(m_text
.GetCount() > 0) return m_text
[0]; 
 705         return wxEmptyString
; 
 707     const wxString 
GetText(size_t col
) const 
 709         if(m_text
.GetCount() > col
) return m_text
[col
]; 
 710         return wxEmptyString
; 
 712     int GetImage(wxTreeItemIcon which 
= wxTreeItemIcon_Normal
) const 
 713         { return m_images
[which
]; } 
 714     int GetImage(size_t col
, wxTreeItemIcon which
=wxTreeItemIcon_Normal
) const 
 716         if(col 
== m_owner
->GetMainColumn()) return m_images
[which
]; 
 717         if(col 
< m_col_images
.GetCount()) return m_col_images
[col
]; 
 720     wxTreeItemData 
*GetData() const { return m_data
; } 
 722     // returns the current image for the item (depending on its 
 723     // selected/expanded/whatever state) 
 724     int GetCurrentImage() const; 
 726     void SetText( const wxString 
&text 
); 
 727     void SetText(size_t col
, const wxString
& text
) // ALB 
 729         if(col 
< m_text
.GetCount()) 
 731         else if(col 
< m_owner
->GetColumnCount()) { 
 732             int howmany 
= m_owner
->GetColumnCount(); 
 733             for(int i 
= m_text
.GetCount(); i 
< howmany
; ++i
) 
 734                 m_text
.Add(wxEmptyString
); 
 738     void SetImage(int image
, wxTreeItemIcon which
) { m_images
[which
] = image
; } 
 739     void SetImage(size_t col
, int image
, wxTreeItemIcon which
) 
 741         if(col 
== m_owner
->GetMainColumn()) m_images
[which
] = image
; 
 742         else if(col 
< m_col_images
.GetCount()) 
 743             m_col_images
[col
] = image
; 
 744         else if(col 
< m_owner
->GetColumnCount()) { 
 745             int howmany 
= m_owner
->GetColumnCount(); 
 746             for(int i 
= m_col_images
.GetCount(); i 
< howmany
; ++i
) 
 747                 m_col_images
.Add(NO_IMAGE
); 
 748             m_col_images
[col
] = image
; 
 752     void SetData(wxTreeItemData 
*data
) { m_data 
= data
; } 
 754     void SetHasPlus(bool has 
= TRUE
) { m_hasPlus 
= has
; } 
 756     void SetBold(bool bold
) { m_isBold 
= bold
; } 
 758     int GetX() const { return m_x
; } 
 759     int GetY() const { return m_y
; } 
 761     void SetX(int x
) { m_x 
= x
; } 
 762     void SetY(int y
) { m_y 
= y
; } 
 764     int  GetHeight() const { return m_height
; } 
 765     int  GetWidth()  const { return m_width
; } 
 767     void SetHeight(int h
) { m_height 
= h
; } 
 768     void SetWidth(int w
) { m_width 
= w
; } 
 770     wxTreeListItem 
*GetParent() const { return m_parent
; } 
 773         // deletes all children notifying the treectrl about it if !NULL 
 775     void DeleteChildren(wxTreeListMainWindow 
*tree 
= NULL
); 
 777     // get count of all children (and grand children if 'recursively') 
 778     size_t GetChildrenCount(bool recursively 
= TRUE
) const; 
 780     void Insert(wxTreeListItem 
*child
, size_t index
) 
 781     { m_children
.Insert(child
, index
); } 
 783     void GetSize( int &x
, int &y
, const wxTreeListMainWindow
* ); 
 785         // return the item at given position (or NULL if no item), onButton is 
 786         // TRUE if the point belongs to the item's button, otherwise it lies 
 787         // on the button's label 
 788     wxTreeListItem 
*HitTest( const wxPoint
& point
, 
 789                              const wxTreeListMainWindow 
*, 
 792     wxTreeListItem 
*HitTest( const wxPoint
& point
, 
 793                              const wxTreeListMainWindow 
*, 
 794                              int &flags
, int& column 
/*ALB*/, 
 797     void Expand() { m_isCollapsed 
= FALSE
; } 
 798     void Collapse() { m_isCollapsed 
= TRUE
; } 
 800     void SetHilight( bool set 
= TRUE 
) { m_hasHilight 
= set
; } 
 803     bool HasChildren() const { return !m_children
.IsEmpty(); } 
 804     bool IsSelected()  const { return m_hasHilight 
!= 0; } 
 805     bool IsExpanded()  const { return !m_isCollapsed
; } 
 806     bool HasPlus()     const { return m_hasPlus 
|| HasChildren(); } 
 807     bool IsBold()      const { return m_isBold 
!= 0; } 
 810         // get them - may be NULL 
 811     wxTreeItemAttr 
*GetAttributes() const { return m_attr
; } 
 812         // get them ensuring that the pointer is not NULL 
 813     wxTreeItemAttr
& Attr() 
 817             m_attr 
= new wxTreeItemAttr
; 
 823     void SetAttributes(wxTreeItemAttr 
*attr
) 
 825         if ( m_ownsAttr 
) delete m_attr
; 
 829         // set them and delete when done 
 830     void AssignAttributes(wxTreeItemAttr 
*attr
) 
 837     wxTreeListMainWindow  
*m_owner
;        // control the item belongs to 
 839     // since there can be very many of these, we save size by chosing 
 840     // the smallest representation for the elements and by ordering 
 841     // the members to avoid padding. 
 842     wxArrayString      m_text
;    // labels to be rendered for item 
 844     wxTreeItemData     
*m_data
;         // user-provided data 
 846     wxArrayTreeListItems m_children
; // list of children 
 847     wxTreeListItem  
*m_parent
;       // parent of this item 
 849     wxTreeItemAttr     
*m_attr
;         // attributes??? 
 851     // tree ctrl images for the normal, selected, expanded and 
 852     // expanded+selected states 
 853     short               m_images
[wxTreeItemIcon_Max
]; 
 854     wxArrayShort m_col_images
; // images for the various columns (!= main) 
 856     wxCoord             m_x
;            // (virtual) offset from top 
 857     wxCoord             m_y
;            // (virtual) offset from left 
 858     short               m_width
;        // width of this item 
 859     unsigned char       m_height
;       // height of this item 
 861     // use bitfields to save size 
 862     int                 m_isCollapsed 
:1; 
 863     int                 m_hasHilight  
:1; // same as focused 
 864     int                 m_hasPlus     
:1; // used for item which doesn't have 
 865                                           // children but has a [+] button 
 866     int                 m_isBold      
:1; // render the label in bold font 
 867     int                 m_ownsAttr    
:1; // delete attribute when done 
 870 // =========================================================================== 
 872 // =========================================================================== 
 874 // ---------------------------------------------------------------------------- 
 876 // ---------------------------------------------------------------------------- 
 878 // translate the key or mouse event flags to the type of selection we're 
 880 static void EventFlagsToSelType(long style
, 
 884                                 bool &extended_select
, 
 885                                 bool &unselect_others
) 
 887     is_multiple 
= (style 
& wxTR_MULTIPLE
) != 0; 
 888     extended_select 
= shiftDown 
&& is_multiple
; 
 889     unselect_others 
= !(extended_select 
|| (ctrlDown 
&& is_multiple
)); 
 892 // --------------------------------------------------------------------------- 
 893 // wxTreeListRenameTimer (internal) 
 894 // --------------------------------------------------------------------------- 
 896 wxTreeListRenameTimer::wxTreeListRenameTimer( wxTreeListMainWindow 
*owner 
) 
 901 void wxTreeListRenameTimer::Notify() 
 903     m_owner
->OnRenameTimer(); 
 906 //----------------------------------------------------------------------------- 
 907 // wxTreeListTextCtrl (internal) 
 908 //----------------------------------------------------------------------------- 
 910 BEGIN_EVENT_TABLE(wxTreeListTextCtrl
,wxTextCtrl
) 
 911     EVT_CHAR           (wxTreeListTextCtrl::OnChar
) 
 912     EVT_KEY_UP         (wxTreeListTextCtrl::OnKeyUp
) 
 913     EVT_KILL_FOCUS     (wxTreeListTextCtrl::OnKillFocus
) 
 916 wxTreeListTextCtrl::wxTreeListTextCtrl( wxWindow 
*parent
, 
 920                                         wxTreeListMainWindow 
*owner
, 
 921                                         const wxString 
&value
, 
 925                                         const wxValidator
& validator
, 
 926                                         const wxString 
&name 
) 
 927     : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name 
) 
 933     (*m_res
) = wxEmptyString
; 
 934     m_startValue 
= value
; 
 938 void wxTreeListTextCtrl::OnChar( wxKeyEvent 
&event 
) 
 940     if (event
.m_keyCode 
== WXK_RETURN
) 
 943         (*m_res
) = GetValue(); 
 945         if ((*m_res
) != m_startValue
) 
 946             m_owner
->OnRenameAccept(); 
 948         if (!wxPendingDelete
.Member(this)) 
 949             wxPendingDelete
.Append(this); 
 952         m_owner
->SetFocus(); // This doesn't work. TODO. 
 956     if (event
.m_keyCode 
== WXK_ESCAPE
) 
 959         (*m_res
) = wxEmptyString
; 
 961         if (!wxPendingDelete
.Member(this)) 
 962             wxPendingDelete
.Append(this); 
 965         m_owner
->SetFocus(); // This doesn't work. TODO. 
 972 void wxTreeListTextCtrl::OnKeyUp( wxKeyEvent 
&event 
) 
 980     // auto-grow the textctrl: 
 981     wxSize parentSize 
= m_owner
->GetSize(); 
 982     wxPoint myPos 
= GetPosition(); 
 983     wxSize mySize 
= GetSize(); 
 985     GetTextExtent(GetValue() + _T("M"), &sx
, &sy
); 
 986     if (myPos
.x 
+ sx 
> parentSize
.x
) sx 
= parentSize
.x 
- myPos
.x
; 
 987     if (mySize
.x 
> sx
) sx 
= mySize
.x
; 
 993 void wxTreeListTextCtrl::OnKillFocus( wxFocusEvent 
&event 
) 
1001     if (!wxPendingDelete
.Member(this)) 
1002         wxPendingDelete
.Append(this); 
1005     (*m_res
) = GetValue(); 
1007     if ((*m_res
) != m_startValue
) 
1008         m_owner
->OnRenameAccept(); 
1011 //----------------------------------------------------------------------------- 
1012 //  wxTreeListHeaderWindow 
1013 //----------------------------------------------------------------------------- 
1015 IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow
,wxWindow
); 
1017 BEGIN_EVENT_TABLE(wxTreeListHeaderWindow
,wxWindow
) 
1018     EVT_PAINT         (wxTreeListHeaderWindow::OnPaint
) 
1019     EVT_MOUSE_EVENTS  (wxTreeListHeaderWindow::OnMouse
) 
1020     EVT_SET_FOCUS     (wxTreeListHeaderWindow::OnSetFocus
) 
1023 void wxTreeListHeaderWindow::Init() 
1025     m_currentCursor 
= (wxCursor 
*) NULL
; 
1026     m_isDragging 
= FALSE
; 
1028     m_total_col_width 
= 0; 
1031 wxTreeListHeaderWindow::wxTreeListHeaderWindow() 
1035     m_owner 
= (wxTreeListMainWindow 
*) NULL
; 
1036     m_resizeCursor 
= (wxCursor 
*) NULL
; 
1039 wxTreeListHeaderWindow::wxTreeListHeaderWindow( wxWindow 
*win
, 
1041                                                 wxTreeListMainWindow 
*owner
, 
1045                                                 const wxString 
&name 
) 
1046     : wxWindow( win
, id
, pos
, size
, style
, name 
) 
1051     m_resizeCursor 
= new wxCursor(wxCURSOR_SIZEWE
); 
1053     SetBackgroundColour(wxSystemSettings::GetSystemColour( 
1054                             wxSYS_COLOUR_BTNFACE
)); 
1057 wxTreeListHeaderWindow::~wxTreeListHeaderWindow() 
1059     delete m_resizeCursor
; 
1062 void wxTreeListHeaderWindow::DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
) 
1065     GtkStateType state 
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
 
1066                                                : GTK_STATE_INSENSITIVE
; 
1068     x 
= dc
->XLOG2DEV( x 
); 
1070     gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
, 
1071                    state
, GTK_SHADOW_OUT
, 
1072                    (GdkRectangle
*) NULL
, m_wxwindow
, "button", 
1073                    x
-1, y
-1, w
+2, h
+2); 
1074 #elif defined( __WXMAC__  ) 
1075     const int m_corner 
= 1; 
1077     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1079     dc
->SetPen( wxPen(wxSystemSettings::GetSystemColour( 
1080                           wxSYS_COLOUR_BTNSHADOW
), 1, wxSOLID
)); 
1081     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
1082     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
1084     wxPen 
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID 
); 
1087     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
1088     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
1090     dc
->SetPen( *wxWHITE_PEN 
); 
1091     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
1092     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
1093     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
1094     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
1096     const int m_corner 
= 1; 
1098     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1100     dc
->SetPen( *wxBLACK_PEN 
); 
1101     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
1102     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
1104     wxPen 
pen(wxSystemSettings::GetSystemColour( 
1105                   wxSYS_COLOUR_BTNSHADOW 
), 1, wxSOLID
); 
1108     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
1109     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
1111     dc
->SetPen( *wxWHITE_PEN 
); 
1112     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
1113     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
1114     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
1115     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
1119 // shift the DC origin to match the position of the main window horz 
1120 // scrollbar: this allows us to always use logical coords 
1121 void wxTreeListHeaderWindow::AdjustDC(wxDC
& dc
) 
1124     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1127     m_owner
->GetViewStart( &x
, NULL 
); 
1129     // account for the horz scrollbar offset 
1130     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1133 void wxTreeListHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1135     static const int HEADER_OFFSET_X 
= 1, HEADER_OFFSET_Y 
= 1; 
1137     wxClientDC 
dc( this ); 
1139     wxPaintDC 
dc( this ); 
1147     dc
.SetFont( GetFont() ); 
1149     // width and height of the entire header window 
1151     GetClientSize( &w
, &h 
); 
1152     m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1154     dc
.SetBackgroundMode(wxTRANSPARENT
); 
1156     // do *not* use the listctrl colour for headers - one day we will have a 
1157     // function to set it separately 
1158     //dc.SetTextForeground( *wxBLACK ); 
1159     dc
.SetTextForeground(wxSystemSettings:: 
1160                             GetSystemColour( wxSYS_COLOUR_WINDOWTEXT 
)); 
1162     int x 
= HEADER_OFFSET_X
; 
1164     int numColumns 
= GetColumnCount(); 
1165     for ( int i 
= 0; i 
< numColumns 
&& x 
< w
; i
++ ) 
1167         wxTreeListColumnInfo
& column 
= GetColumn(i
); 
1168         int wCol 
= column
.GetWidth(); 
1170         // the width of the rect to draw: make it smaller to fit entirely 
1171         // inside the column rect 
1174         dc
.SetPen( *wxWHITE_PEN 
); 
1176         DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 ); 
1178         // if we have an image, draw it on the right of the label 
1179         int image 
= column
.GetImage(); //item.m_image; 
1180         int ix 
= -2, iy 
= 0; 
1181         wxImageList
* imageList 
= m_owner
->GetImageList(); 
1184                 imageList
->GetSize(image
, ix
, iy
); 
1186             //else: ignore the column image 
1189         // extra margins around the text label 
1190         static const int EXTRA_WIDTH 
= 3; 
1191         static const int EXTRA_HEIGHT 
= 4; 
1195         int image_offset 
= cw 
- ix 
- 1; 
1197         switch(column
.GetAlignment()) { 
1198         case wxTL_ALIGN_LEFT
: 
1199             text_x 
+= EXTRA_WIDTH
; 
1202         case wxTL_ALIGN_RIGHT
: 
1203             dc
.GetTextExtent(column
.GetText(), &text_width
, NULL
); 
1204             text_x 
+= cw 
- text_width 
- EXTRA_WIDTH
; 
1207         case wxTL_ALIGN_CENTER
: 
1208             dc
.GetTextExtent(column
.GetText(), &text_width
, NULL
); 
1209             text_x 
+= (cw 
- text_width
)/2 + ix 
+ 2; 
1210             image_offset 
= (cw 
- text_width 
- ix 
- 2)/2; 
1215         if(image 
!= -1 && imageList
) { 
1216             imageList
->Draw(image
, dc
, x 
+ image_offset
/*cw - ix - 1*/, 
1217                             HEADER_OFFSET_Y 
+ (h 
- 4 - iy
)/2, 
1218                             wxIMAGELIST_DRAW_TRANSPARENT
); 
1221         // draw the text clipping it so that it doesn't overwrite the column 
1223         wxDCClipper 
clipper(dc
, x
, HEADER_OFFSET_Y
, cw
, h 
- 4 ); 
1225         dc
.DrawText( column
.GetText(), 
1226                      text_x
, HEADER_OFFSET_Y 
+ EXTRA_HEIGHT 
); 
1234 void wxTreeListHeaderWindow::DrawCurrent() 
1236     int x1 
= m_currentX
; 
1238     ClientToScreen( &x1
, &y1 
); 
1240     int x2 
= m_currentX
-1; 
1245     m_owner
->GetClientSize( NULL
, &y2 
); 
1246     m_owner
->ClientToScreen( &x2
, &y2 
); 
1249     dc
.SetLogicalFunction( wxINVERT 
); 
1250     dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID 
) ); 
1251     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
1255     dc
.DrawLine( x1
, y1
, x2
, y2 
); 
1257     dc
.SetLogicalFunction( wxCOPY 
); 
1259     dc
.SetPen( wxNullPen 
); 
1260     dc
.SetBrush( wxNullBrush 
); 
1263 void wxTreeListHeaderWindow::OnMouse( wxMouseEvent 
&event 
) 
1265     // we want to work with logical coords 
1267     m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
); 
1268     int y 
= event
.GetY(); 
1272         SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING
, 
1273                       event
.GetPosition()); 
1275         // we don't draw the line beyond our window, but we allow dragging it 
1278         GetClientSize( &w
, NULL 
); 
1279         m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1282         // erase the line if it was drawn 
1283         if ( m_currentX 
< w 
) 
1286         if (event
.ButtonUp()) 
1289             m_isDragging 
= FALSE
; 
1291             SetColumnWidth( m_column
, m_currentX 
- m_minX 
); 
1293             SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG
, 
1294                           event
.GetPosition()); 
1301                 m_currentX 
= m_minX 
+ 7; 
1303             // draw in the new location 
1304             if ( m_currentX 
< w 
) 
1308     else // not dragging 
1311         bool hit_border 
= FALSE
; 
1313         // end of the current column 
1316         // find the column where this event occured 
1317         int countCol 
= GetColumnCount(); 
1318         for (int col 
= 0; col 
< countCol
; col
++) 
1320             xpos 
+= GetColumnWidth( col 
); 
1323             if ( (abs(x
-xpos
) < 3) && (y 
< 22) ) 
1325                 // near the column border 
1332                 // inside the column 
1339         if (event
.LeftDown() || event
.RightUp()) 
1341             if (hit_border 
&& event
.LeftDown()) 
1343                 m_isDragging 
= TRUE
; 
1347                 SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
, 
1348                               event
.GetPosition()); 
1350             else // click on a column 
1352                 SendListEvent( event
.LeftDown() 
1353                                ? wxEVT_COMMAND_LIST_COL_CLICK
 
1354                                : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
, 
1355                                event
.GetPosition()); 
1358         else if (event
.Moving()) 
1363                 setCursor 
= m_currentCursor 
== wxSTANDARD_CURSOR
; 
1364                 m_currentCursor 
= m_resizeCursor
; 
1368                 setCursor 
= m_currentCursor 
!= wxSTANDARD_CURSOR
; 
1369                 m_currentCursor 
= wxSTANDARD_CURSOR
; 
1373                 SetCursor(*m_currentCursor
); 
1378 void wxTreeListHeaderWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1380     m_owner
->SetFocus(); 
1383 void wxTreeListHeaderWindow::SendListEvent(wxEventType type
, wxPoint pos
) 
1385     wxWindow 
*parent 
= GetParent(); 
1386     wxListEvent 
le( type
, parent
->GetId() ); 
1387     le
.SetEventObject( parent 
); 
1388     le
.m_pointDrag 
= pos
; 
1390     // the position should be relative to the parent window, not 
1391     // this one for compatibility with MSW and common sense: the 
1392     // user code doesn't know anything at all about this header 
1393     // window, so why should it get positions relative to it? 
1394     le
.m_pointDrag
.y 
-= GetSize().y
; 
1396     le
.m_col 
= m_column
; 
1397     parent
->GetEventHandler()->ProcessEvent( le 
); 
1401 void wxTreeListHeaderWindow::AddColumn(const wxTreeListColumnInfo
& col
) 
1404     m_total_col_width 
+= col
.GetWidth(); 
1405     //m_owner->GetHeaderWindow()->Refresh(); 
1407     m_owner
->AdjustMyScrollbars(); 
1408     m_owner
->m_dirty 
= TRUE
; 
1413 void wxTreeListHeaderWindow::SetColumnWidth(size_t column
, size_t width
) 
1415     if(column 
< GetColumnCount()) { 
1416         m_total_col_width 
-= m_columns
[column
].GetWidth(); 
1417         m_columns
[column
].SetWidth(width
); 
1418         m_total_col_width 
+= width
; 
1419         m_owner
->AdjustMyScrollbars(); 
1420         m_owner
->m_dirty 
= TRUE
; 
1428 void wxTreeListHeaderWindow::InsertColumn(size_t before
, 
1429                                           const wxTreeListColumnInfo
& col
) 
1431     wxCHECK_RET(before 
< GetColumnCount(), wxT("Invalid column index")); 
1432     m_columns
.Insert(col
, before
); 
1433     m_total_col_width 
+= col
.GetWidth(); 
1435     //m_owner->GetHeaderWindow()->Refresh(); 
1436     m_owner
->AdjustMyScrollbars(); 
1437     m_owner
->m_dirty 
= TRUE
; 
1442 void wxTreeListHeaderWindow::RemoveColumn(size_t column
) 
1444     wxCHECK_RET(column 
< GetColumnCount(), wxT("Invalid column")); 
1445     m_total_col_width 
-= m_columns
[column
].GetWidth(); 
1446     m_columns
.RemoveAt(column
); 
1448     m_owner
->AdjustMyScrollbars(); 
1449     m_owner
->m_dirty 
= TRUE
; 
1454 void wxTreeListHeaderWindow::SetColumn(size_t column
, 
1455                                        const wxTreeListColumnInfo
& info
) 
1457     wxCHECK_RET(column 
< GetColumnCount(), wxT("Invalid column")); 
1458     size_t w 
= m_columns
[column
].GetWidth(); 
1459     m_columns
[column
] = info
; 
1460     //m_owner->GetHeaderWindow()->Refresh(); 
1462     if(w 
!= info
.GetWidth()) { 
1463         m_total_col_width 
+= info
.GetWidth() - w
; 
1464         m_owner
->AdjustMyScrollbars(); 
1465         m_owner
->m_dirty 
= TRUE
; 
1470 // --------------------------------------------------------------------------- 
1472 // --------------------------------------------------------------------------- 
1474 wxTreeListItem::wxTreeListItem(wxTreeListMainWindow 
*owner
, 
1475                                      wxTreeListItem 
*parent
, 
1476                                      const wxArrayString
& text
, 
1477                                      int image
, int selImage
, 
1478                                      wxTreeItemData 
*data
) 
1481     m_images
[wxTreeItemIcon_Normal
] = image
; 
1482     m_images
[wxTreeItemIcon_Selected
] = selImage
; 
1483     m_images
[wxTreeItemIcon_Expanded
] = NO_IMAGE
; 
1484     m_images
[wxTreeItemIcon_SelectedExpanded
] = NO_IMAGE
; 
1489     m_isCollapsed 
= TRUE
; 
1490     m_hasHilight 
= FALSE
; 
1498     m_attr 
= (wxTreeItemAttr 
*)NULL
; 
1501     // We don't know the height here yet. 
1506 wxTreeListItem::~wxTreeListItem() 
1510     if (m_ownsAttr
) delete m_attr
; 
1512     wxASSERT_MSG( m_children
.IsEmpty(), 
1513                   wxT("please call DeleteChildren() before deleting the item") ); 
1516 void wxTreeListItem::DeleteChildren(wxTreeListMainWindow 
*tree
) 
1518     size_t count 
= m_children
.Count(); 
1519     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1521         wxTreeListItem 
*child 
= m_children
[n
]; 
1523             tree
->SendDeleteEvent(child
); 
1525         child
->DeleteChildren(tree
); 
1532 void wxTreeListItem::SetText( const wxString 
&text 
) 
1534     if(m_text
.GetCount() > 0) m_text
[0] = text
; 
1540 size_t wxTreeListItem::GetChildrenCount(bool recursively
) const 
1542     size_t count 
= m_children
.Count(); 
1546     size_t total 
= count
; 
1547     for (size_t n 
= 0; n 
< count
; ++n
) 
1549         total 
+= m_children
[n
]->GetChildrenCount(); 
1555 void wxTreeListItem::GetSize( int &x
, int &y
, 
1556                                  const wxTreeListMainWindow 
*theButton 
) 
1558     int bottomY
=m_y
+theButton
->GetLineHeight(this); 
1559     if ( y 
< bottomY 
) y 
= bottomY
; 
1560     int width 
= m_x 
+  m_width
; 
1561     if ( x 
< width 
) x 
= width
; 
1565         size_t count 
= m_children
.Count(); 
1566         for ( size_t n 
= 0; n 
< count
; ++n 
) 
1568             m_children
[n
]->GetSize( x
, y
, theButton 
); 
1573 wxTreeListItem 
*wxTreeListItem::HitTest(const wxPoint
& point
, 
1574                                         const wxTreeListMainWindow 
*theCtrl
, 
1578     // for a hidden root node, don't evaluate it, but do evaluate children 
1579     if ( !(level 
== 0 && theCtrl
->HasFlag(wxTR_HIDE_ROOT
)) ) 
1581         // evaluate the item 
1582         int h 
= theCtrl
->GetLineHeight(this); 
1583         if ((point
.y 
> m_y
) && (point
.y 
< m_y 
+ h
)) 
1585             int y_mid 
= m_y 
+ h
/2; 
1586             if (point
.y 
< y_mid 
) 
1587                 flags 
|= wxTREE_HITTEST_ONITEMUPPERPART
; 
1589                 flags 
|= wxTREE_HITTEST_ONITEMLOWERPART
; 
1591             // 5 is the size of the plus sign 
1592             int xCross 
= m_x 
- theCtrl
->GetSpacing(); 
1593             if ((point
.x 
> xCross
-5) && (point
.x 
< xCross
+5) && 
1594                 (point
.y 
> y_mid
-5) && (point
.y 
< y_mid
+5) && 
1595                 HasPlus() && theCtrl
->HasButtons() ) 
1597                 flags 
|= wxTREE_HITTEST_ONITEMBUTTON
; 
1601             if ((point
.x 
>= m_x
) && (point
.x 
<= m_x
+m_width
)) 
1606                 //assuming every image (normal and selected) has the same size! 
1607                 if ( (GetImage() != NO_IMAGE
) && theCtrl
->m_imageListNormal 
) 
1608                     theCtrl
->m_imageListNormal
->GetSize(GetImage(), 
1611                 if ((image_w 
!= -1) && (point
.x 
<= m_x 
+ image_w 
+ 1)) 
1612                     flags 
|= wxTREE_HITTEST_ONITEMICON
; 
1614                     flags 
|= wxTREE_HITTEST_ONITEMLABEL
; 
1620                 flags 
|= wxTREE_HITTEST_ONITEMINDENT
; 
1621             if (point
.x 
> m_x
+m_width
) 
1622                 flags 
|= wxTREE_HITTEST_ONITEMRIGHT
; 
1627         // if children are expanded, fall through to evaluate them 
1628         if (m_isCollapsed
) return (wxTreeListItem
*) NULL
; 
1631     // evaluate children 
1632     size_t count 
= m_children
.Count(); 
1633     for ( size_t n 
= 0; n 
< count
; n
++ ) 
1635         wxTreeListItem 
*res 
= m_children
[n
]->HitTest(point
, theCtrl
, 
1641     return (wxTreeListItem
*) NULL
; 
1645 wxTreeListItem 
*wxTreeListItem::HitTest(const wxPoint
& point
, 
1646                                         const wxTreeListMainWindow 
*theCtrl
, 
1647                                         int &flags
, int& column
, int level
) 
1650     wxTreeListItem
* res 
= HitTest(point
, theCtrl
, flags
, level
); 
1652     if(!res
) return res
; 
1653     if(flags 
& wxTREE_HITTEST_ONITEMINDENT
) { 
1655         for(size_t i 
= 0; i 
< theCtrl
->GetMainColumn(); ++i
) { 
1656             int w 
= theCtrl
->m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
1657             if(point
.x 
>= x 
&& point
.x 
< x
+w
) { 
1658                 flags 
^= wxTREE_HITTEST_ONITEMINDENT
; 
1659                 flags 
|= wxTREE_HITTEST_ONITEMCOLUMN
; 
1665     else if(flags 
& wxTREE_HITTEST_ONITEMRIGHT
) { 
1668         for(i 
= 0; i 
< theCtrl
->GetMainColumn()+1; ++i
) { 
1669             x 
+= theCtrl
->m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
1671         for(i 
= theCtrl
->GetMainColumn()+1; 
1672             i 
< theCtrl
->GetColumnCount(); ++i
) { 
1673             int w 
= theCtrl
->m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
1674             if(point
.x 
>= x 
&& point
.x 
< x
+w
) { 
1675                 flags 
^= wxTREE_HITTEST_ONITEMRIGHT
; 
1676                 flags 
|= wxTREE_HITTEST_ONITEMCOLUMN
; 
1687 int wxTreeListItem::GetCurrentImage() const 
1689     int image 
= NO_IMAGE
; 
1694             image 
= GetImage(wxTreeItemIcon_SelectedExpanded
); 
1697         if ( image 
== NO_IMAGE 
) 
1699             // we usually fall back to the normal item, but try just the 
1700             // expanded one (and not selected) first in this case 
1701             image 
= GetImage(wxTreeItemIcon_Expanded
); 
1704     else // not expanded 
1707             image 
= GetImage(wxTreeItemIcon_Selected
); 
1710     // maybe it doesn't have the specific image we want, 
1711     // try the default one instead 
1712     if ( image 
== NO_IMAGE 
) image 
= GetImage(); 
1717 // --------------------------------------------------------------------------- 
1718 // wxTreeListMainWindow implementation 
1719 // --------------------------------------------------------------------------- 
1721 IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow
, wxScrolledWindow
) 
1723 BEGIN_EVENT_TABLE(wxTreeListMainWindow
, wxScrolledWindow
) 
1724     EVT_PAINT          (wxTreeListMainWindow::OnPaint
) 
1725     EVT_MOUSE_EVENTS   (wxTreeListMainWindow::OnMouse
) 
1726     EVT_CHAR           (wxTreeListMainWindow::OnChar
) 
1727     EVT_SET_FOCUS      (wxTreeListMainWindow::OnSetFocus
) 
1728     EVT_KILL_FOCUS     (wxTreeListMainWindow::OnKillFocus
) 
1729     EVT_IDLE           (wxTreeListMainWindow::OnIdle
) 
1730     //EVT_SIZE           (wxTreeListMainWindow::OnSize) 
1731     EVT_SCROLLWIN      (wxTreeListMainWindow::OnScroll
) 
1735 // --------------------------------------------------------------------------- 
1736 // construction/destruction 
1737 // --------------------------------------------------------------------------- 
1739 void wxTreeListMainWindow::Init() 
1741     m_current 
= m_key_current 
= m_anchor 
= (wxTreeListItem 
*) NULL
; 
1750     m_hilightBrush 
= new wxBrush
 
1752                             wxSystemSettings::GetSystemColour
 
1754                                 wxSYS_COLOUR_HIGHLIGHT
 
1759     m_hilightUnfocusedBrush 
= new wxBrush
 
1761                                  wxSystemSettings::GetSystemColour
 
1763                                      wxSYS_COLOUR_BTNSHADOW
 
1768     m_imageListNormal 
= m_imageListButtons 
= 
1769     m_imageListState 
= (wxImageList 
*) NULL
; 
1770     m_ownsImageListNormal 
= m_ownsImageListButtons 
= 
1771     m_ownsImageListState 
= FALSE
; 
1774     m_isDragging 
= FALSE
; 
1775     m_dropTarget 
= m_oldSelection 
= (wxTreeListItem 
*)NULL
; 
1777     m_renameTimer 
= new wxTreeListRenameTimer( this ); 
1778     m_lastOnSame 
= FALSE
; 
1780     m_normalFont 
= wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT 
); 
1781     m_boldFont 
= wxFont( m_normalFont
.GetPointSize(), 
1782                          m_normalFont
.GetFamily(), 
1783                          m_normalFont
.GetStyle(), 
1785                          m_normalFont
.GetUnderlined()); 
1789 static const int HEADER_HEIGHT 
= 23; 
1791 bool wxTreeListMainWindow::Create(wxTreeListCtrl 
*parent
, 
1796                                   const wxValidator 
&validator
, 
1797                                   const wxString
& name 
) 
1801     wxGetOsVersion( &major
, &minor 
); 
1803     if (style 
& wxTR_HAS_BUTTONS
) style 
|= wxTR_MAC_BUTTONS
; 
1804     if (style 
& wxTR_HAS_BUTTONS
) style 
&= ~wxTR_HAS_BUTTONS
; 
1805     style 
&= ~wxTR_LINES_AT_ROOT
; 
1806     style 
|= wxTR_NO_LINES
; 
1808         style 
|= wxTR_ROW_LINES
; 
1811     wxScrolledWindow::Create( parent
, id
, pos
, size
, 
1812                               style
|wxHSCROLL
|wxVSCROLL
, name 
); 
1814         // If the tree display has no buttons, but does have 
1815         // connecting lines, we can use a narrower layout. 
1816         // It may not be a good idea to force this... 
1817     if (!HasButtons() && !HasFlag(wxTR_NO_LINES
)) 
1823 #if wxUSE_VALIDATORS 
1824     SetValidator( validator 
); 
1827     SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX 
) ); 
1830 //     m_dottedPen = wxPen( "black", 0, wxDOT );  // too slow under XFree86 
1832     m_dottedPen 
= wxPen( wxT("grey"), 0, 0 ); 
1842 wxTreeListMainWindow::~wxTreeListMainWindow() 
1844     delete m_hilightBrush
; 
1845     delete m_hilightUnfocusedBrush
; 
1849     delete m_renameTimer
; 
1850     if (m_ownsImageListNormal
) delete m_imageListNormal
; 
1851     if (m_ownsImageListState
) delete m_imageListState
; 
1852     if (m_ownsImageListButtons
) delete m_imageListButtons
; 
1857 //----------------------------------------------------------------------------- 
1859 //----------------------------------------------------------------------------- 
1862 size_t wxTreeListMainWindow::GetCount() const 
1864     return m_anchor 
== NULL 
? 0u : m_anchor
->GetChildrenCount(); 
1868 void wxTreeListMainWindow::SetIndent(unsigned int indent
) 
1875 void wxTreeListMainWindow::SetSpacing(unsigned int spacing
) 
1877     m_spacing 
= spacing
; 
1882 void wxTreeListMainWindow::SetLineSpacing(unsigned int spacing
) 
1884     m_linespacing 
= spacing
; 
1886     CalculateLineHeight(); 
1890 size_t wxTreeListMainWindow::GetChildrenCount(const wxTreeItemId
& item
, 
1893     wxCHECK_MSG( item
.IsOk(), 0u, wxT("invalid tree item") ); 
1895     return ((wxTreeListItem
*) item
.m_pItem
)->GetChildrenCount(recursively
); 
1898 void wxTreeListMainWindow::SetWindowStyle(const long styles
) 
1900         // right now, just sets the styles.  Eventually, we may 
1901         // want to update the inherited styles, but right now 
1902         // none of the parents has updatable styles 
1903     m_windowStyle 
= styles
; 
1907 //----------------------------------------------------------------------------- 
1908 // functions to work with tree items 
1909 //----------------------------------------------------------------------------- 
1912 int wxTreeListMainWindow::GetItemImage(const wxTreeItemId
& item
, size_t column
, 
1913                                        wxTreeItemIcon which
) const 
1915     wxCHECK_MSG( item
.IsOk(), -1, wxT("invalid tree item") ); 
1917     return ((wxTreeListItem
*) item
.m_pItem
)->GetImage(column
, which
); 
1921 wxTreeItemData 
*wxTreeListMainWindow::GetItemData(const wxTreeItemId
& item
) 
1924     wxCHECK_MSG( item
.IsOk(), NULL
, wxT("invalid tree item") ); 
1926     return ((wxTreeListItem
*) item
.m_pItem
)->GetData(); 
1930 bool wxTreeListMainWindow::GetItemBold(const wxTreeItemId
& item
) const 
1932     wxCHECK_MSG(item
.IsOk(), FALSE
, wxT("invalid tree item")); 
1933     return ((wxTreeListItem 
*)item
.m_pItem
)->IsBold(); 
1937 wxColour 
wxTreeListMainWindow::GetItemTextColour(const wxTreeItemId
& item
) 
1940     wxCHECK_MSG( item
.IsOk(), wxNullColour
, wxT("invalid tree item") ); 
1942     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1943     return pItem
->Attr().GetTextColour(); 
1947 wxColour 
wxTreeListMainWindow::GetItemBackgroundColour( 
1948     const wxTreeItemId
& item
) const 
1950     wxCHECK_MSG( item
.IsOk(), wxNullColour
, wxT("invalid tree item") ); 
1952     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1953     return pItem
->Attr().GetBackgroundColour(); 
1957 wxFont 
wxTreeListMainWindow::GetItemFont(const wxTreeItemId
& item
) const 
1959     wxCHECK_MSG( item
.IsOk(), wxNullFont
, wxT("invalid tree item") ); 
1961     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1962     return pItem
->Attr().GetFont(); 
1968 void wxTreeListMainWindow::SetItemImage(const wxTreeItemId
& item
, 
1970                                         int image
, wxTreeItemIcon which
) 
1972     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
1974     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1975     pItem
->SetImage(column
, image
, which
); 
1977     wxClientDC 
dc(this); 
1978     CalculateSize(pItem
, dc
); 
1983 void wxTreeListMainWindow::SetItemData(const wxTreeItemId
& item
, 
1984                                        wxTreeItemData 
*data
) 
1986     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
1988     ((wxTreeListItem
*) item
.m_pItem
)->SetData(data
); 
1992 void wxTreeListMainWindow::SetItemHasChildren(const wxTreeItemId
& item
, 
1995     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
1997     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
1998     pItem
->SetHasPlus(has
); 
2003 void wxTreeListMainWindow::SetItemBold(const wxTreeItemId
& item
, bool bold
) 
2005     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2007     // avoid redrawing the tree if no real change 
2008     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2009     if ( pItem
->IsBold() != bold 
) 
2011         pItem
->SetBold(bold
); 
2017 void wxTreeListMainWindow::SetItemTextColour(const wxTreeItemId
& item
, 
2018                                              const wxColour
& col
) 
2020     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2022     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2023     pItem
->Attr().SetTextColour(col
); 
2028 void wxTreeListMainWindow::SetItemBackgroundColour(const wxTreeItemId
& item
, 
2029                                                    const wxColour
& col
) 
2031     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2033     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2034     pItem
->Attr().SetBackgroundColour(col
); 
2039 void wxTreeListMainWindow::SetItemFont(const wxTreeItemId
& item
, 
2042     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
2044     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2045     pItem
->Attr().SetFont(font
); 
2050 bool wxTreeListMainWindow::SetFont( const wxFont 
&font 
) 
2052     wxScrolledWindow::SetFont(font
); 
2054     m_normalFont 
= font 
; 
2055     m_boldFont 
= wxFont( m_normalFont
.GetPointSize(), 
2056                             m_normalFont
.GetFamily(), 
2057                             m_normalFont
.GetStyle(), 
2059                             m_normalFont
.GetUnderlined()); 
2065 // ---------------------------------------------------------------------------- 
2066 // item status inquiries 
2067 // ---------------------------------------------------------------------------- 
2070 bool wxTreeListMainWindow::IsVisible(const wxTreeItemId
& item
) const 
2072     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2074     // An item is only visible if it's not a descendant of a collapsed item 
2075     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
2076     wxTreeListItem
* parent 
= pItem
->GetParent(); 
2079         if (!parent
->IsExpanded()) 
2081         parent 
= parent
->GetParent(); 
2085     GetViewStart(& startX
, & startY
); 
2087     wxSize clientSize 
= GetClientSize(); 
2090     if (!GetBoundingRect(item
, rect
)) 
2092     if (rect
.GetWidth() == 0 || rect
.GetHeight() == 0) 
2094     if (rect
.GetBottom() < 0 || rect
.GetTop() > clientSize
.y
) 
2096     if (rect
.GetRight() < 0 || rect
.GetLeft() > clientSize
.x
) 
2103 bool wxTreeListMainWindow::ItemHasChildren(const wxTreeItemId
& item
) const 
2105     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2107     // consider that the item does have children if it has the "+" button: it 
2108     // might not have them (if it had never been expanded yet) but then it 
2109     // could have them as well and it's better to err on this side rather than 
2110     // disabling some operations which are restricted to the items with 
2111     // children for an item which does have them 
2112     return ((wxTreeListItem
*) item
.m_pItem
)->HasPlus(); 
2116 bool wxTreeListMainWindow::IsExpanded(const wxTreeItemId
& item
) const 
2118     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2120     return ((wxTreeListItem
*) item
.m_pItem
)->IsExpanded(); 
2124 bool wxTreeListMainWindow::IsSelected(const wxTreeItemId
& item
) const 
2126     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2128     return ((wxTreeListItem
*) item
.m_pItem
)->IsSelected(); 
2132 bool wxTreeListMainWindow::IsBold(const wxTreeItemId
& item
) const 
2134     wxCHECK_MSG( item
.IsOk(), FALSE
, wxT("invalid tree item") ); 
2136     return ((wxTreeListItem
*) item
.m_pItem
)->IsBold(); 
2139 // ---------------------------------------------------------------------------- 
2141 // ---------------------------------------------------------------------------- 
2144 wxTreeItemId 
wxTreeListMainWindow::GetParent(const wxTreeItemId
& item
) const 
2146     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2148     return ((wxTreeListItem
*) item
.m_pItem
)->GetParent(); 
2152 wxTreeItemId 
wxTreeListMainWindow::GetFirstChild(const wxTreeItemId
& item
, 
2155     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2158     return GetNextChild(item
, cookie
); 
2162 wxTreeItemId 
wxTreeListMainWindow::GetNextChild(const wxTreeItemId
& item
, 
2165     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2167     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) 
2168                                       item
.m_pItem
)->GetChildren(); 
2169     if ( (size_t)cookie 
< children
.Count() ) 
2171         return children
.Item((size_t)cookie
++); 
2175         // there are no more of them 
2176         return wxTreeItemId(); 
2181 wxTreeItemId 
wxTreeListMainWindow::GetLastChild(const wxTreeItemId
& item
) const 
2183     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2185     wxArrayTreeListItems
& children 
= ((wxTreeListItem
*) item
.m_pItem
)->GetChildren(); 
2186     return (children
.IsEmpty() ? wxTreeItemId() : wxTreeItemId(children
.Last())); 
2190 wxTreeItemId 
wxTreeListMainWindow::GetNextSibling(const wxTreeItemId
& item
) const 
2192     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2194     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2195     wxTreeListItem 
*parent 
= i
->GetParent(); 
2196     if ( parent 
== NULL 
) 
2198         // root item doesn't have any siblings 
2199         return wxTreeItemId(); 
2202     wxArrayTreeListItems
& siblings 
= parent
->GetChildren(); 
2203     int index 
= siblings
.Index(i
); 
2204     wxASSERT( index 
!= wxNOT_FOUND 
); // I'm not a child of my parent? 
2206     size_t n 
= (size_t)(index 
+ 1); 
2207     return n 
== siblings
.Count() ? wxTreeItemId() : wxTreeItemId(siblings
[n
]); 
2211 wxTreeItemId 
wxTreeListMainWindow::GetPrevSibling(const wxTreeItemId
& item
) 
2214     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2216     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2217     wxTreeListItem 
*parent 
= i
->GetParent(); 
2218     if ( parent 
== NULL 
) 
2220         // root item doesn't have any siblings 
2221         return wxTreeItemId(); 
2224     wxArrayTreeListItems
& siblings 
= parent
->GetChildren(); 
2225     int index 
= siblings
.Index(i
); 
2226     wxASSERT( index 
!= wxNOT_FOUND 
); // I'm not a child of my parent? 
2228     return index 
== 0 ? wxTreeItemId() 
2229                       : wxTreeItemId(siblings
[(size_t)(index 
- 1)]); 
2232 // Only for internal use right now, but should probably be public 
2233 wxTreeItemId 
wxTreeListMainWindow::GetNext(const wxTreeItemId
& item
) const 
2235     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2237     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
2239     // First see if there are any children. 
2240     wxArrayTreeListItems
& children 
= i
->GetChildren(); 
2241     if (children
.GetCount() > 0) 
2243          return children
.Item(0); 
2247          // Try a sibling of this or ancestor instead 
2248          wxTreeItemId p 
= item
; 
2249          wxTreeItemId toFind
; 
2252               toFind 
= GetNextSibling(p
); 
2254          } while (p
.IsOk() && !toFind
.IsOk()); 
2260 wxTreeItemId 
wxTreeListMainWindow::GetFirstVisibleItem() const 
2262     wxTreeItemId id 
= GetRootItem(); 
2271     } while (id
.IsOk()); 
2273     return wxTreeItemId(); 
2277 wxTreeItemId 
wxTreeListMainWindow::GetNextVisible(const wxTreeItemId
& item
) 
2280     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2282     wxTreeItemId id 
= item
; 
2285         while (id 
= GetNext(id
), id
.IsOk()) 
2291     return wxTreeItemId(); 
2295 wxTreeItemId 
wxTreeListMainWindow::GetPrevVisible(const wxTreeItemId
& item
) 
2298     wxCHECK_MSG( item
.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); 
2300     wxFAIL_MSG(wxT("not implemented")); 
2302     return wxTreeItemId(); 
2305 // ---------------------------------------------------------------------------- 
2307 // ---------------------------------------------------------------------------- 
2309 wxTreeItemId 
wxTreeListMainWindow::DoInsertItem(const wxTreeItemId
& parentId
, 
2311                                       const wxString
& text
, 
2312                                       int image
, int selImage
, 
2313                                       wxTreeItemData 
*data
) 
2315     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2318         // should we give a warning here? 
2319         return AddRoot(text
, image
, selImage
, data
); 
2322     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2326     arr
.Alloc(GetColumnCount()); 
2327     for(size_t i 
= 0; i 
< GetColumnCount(); ++i
) { 
2328         arr
.Add(wxEmptyString
); 
2330     arr
[m_main_column
] = text
; 
2331     wxTreeListItem 
*item 
= 
2332         new wxTreeListItem( this, parent
, arr
, image
, selImage
, data 
); 
2336         data
->SetId((long)item
); 
2339     parent
->Insert( item
, previous 
); 
2344 wxTreeItemId 
wxTreeListMainWindow::AddRoot(const wxString
& text
, 
2345                                  int image
, int selImage
, 
2346                                  wxTreeItemData 
*data
) 
2348     wxCHECK_MSG(!m_anchor
, wxTreeItemId(), wxT("tree can have only one root")); 
2349     wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), wxT("Add column(s) before adding the root item")); 
2351     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2355     arr
.Alloc(GetColumnCount()); 
2356     for(size_t i 
= 0; i 
< GetColumnCount(); ++i
) { 
2357         arr
.Add(wxEmptyString
); 
2359     arr
[m_main_column
] = text
; 
2360     m_anchor 
= new wxTreeListItem( this, (wxTreeListItem 
*)NULL
, arr
, 
2361                                       image
, selImage
, data
); 
2362     if (HasFlag(wxTR_HIDE_ROOT
)) 
2364         // if root is hidden, make sure we can navigate 
2366         m_anchor
->SetHasPlus(); 
2371         data
->SetId((long)m_anchor
); 
2374     if (!HasFlag(wxTR_MULTIPLE
)) 
2376         m_current 
= m_key_current 
= m_anchor
; 
2377         m_current
->SetHilight( TRUE 
); 
2384 wxTreeItemId 
wxTreeListMainWindow::PrependItem(const wxTreeItemId
& parent
, 
2385                                      const wxString
& text
, 
2386                                      int image
, int selImage
, 
2387                                      wxTreeItemData 
*data
) 
2389     return DoInsertItem(parent
, 0u, text
, image
, selImage
, data
); 
2393 wxTreeItemId 
wxTreeListMainWindow::InsertItem(const wxTreeItemId
& parentId
, 
2394                                     const wxTreeItemId
& idPrevious
, 
2395                                     const wxString
& text
, 
2396                                     int image
, int selImage
, 
2397                                     wxTreeItemData 
*data
) 
2399     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2402         // should we give a warning here? 
2403         return AddRoot(text
, image
, selImage
, data
); 
2406     int index 
= parent
->GetChildren().Index((wxTreeListItem
*) idPrevious
.m_pItem
); 
2407     wxASSERT_MSG( index 
!= wxNOT_FOUND
, 
2408                   wxT("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") ); 
2410     return DoInsertItem(parentId
, (size_t)++index
, text
, image
, selImage
, data
); 
2414 wxTreeItemId 
wxTreeListMainWindow::InsertItem(const wxTreeItemId
& parentId
, 
2416                                     const wxString
& text
, 
2417                                     int image
, int selImage
, 
2418                                     wxTreeItemData 
*data
) 
2420     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2423         // should we give a warning here? 
2424         return AddRoot(text
, image
, selImage
, data
); 
2427     return DoInsertItem(parentId
, before
, text
, image
, selImage
, data
); 
2431 wxTreeItemId 
wxTreeListMainWindow::AppendItem(const wxTreeItemId
& parentId
, 
2432                                     const wxString
& text
, 
2433                                     int image
, int selImage
, 
2434                                     wxTreeItemData 
*data
) 
2436     wxTreeListItem 
*parent 
= (wxTreeListItem
*) parentId
.m_pItem
; 
2439         // should we give a warning here? 
2440         return AddRoot(text
, image
, selImage
, data
); 
2443     return DoInsertItem( parent
, parent
->GetChildren().Count(), text
, 
2444                          image
, selImage
, data
); 
2447 void wxTreeListMainWindow::SendDeleteEvent(wxTreeListItem 
*item
) 
2449     wxTreeEvent 
event( wxEVT_COMMAND_TREE_DELETE_ITEM
, m_owner
->GetId() ); 
2450     event
.SetItem((long) item
); 
2451     event
.SetEventObject( /*this*/m_owner 
); 
2452     m_owner
->ProcessEvent( event 
); 
2456 void wxTreeListMainWindow::DeleteChildren(const wxTreeItemId
& itemId
) 
2458     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2460     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2461     item
->DeleteChildren(this); 
2465 void wxTreeListMainWindow::Delete(const wxTreeItemId
& itemId
) 
2467     m_dirty 
= TRUE
;     // do this first so stuff below doesn't cause flicker 
2469     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2471     // don't stay with invalid m_key_current or we will crash in 
2472     // the next call to OnChar() 
2473     bool changeKeyCurrent 
= FALSE
; 
2474     wxTreeListItem 
*itemKey 
= m_key_current
; 
2477         if ( itemKey 
== item 
) 
2479             // m_key_current is a descendant of the item being deleted 
2480             changeKeyCurrent 
= TRUE
; 
2483         itemKey 
= itemKey
->GetParent(); 
2486     wxTreeListItem 
*parent 
= item
->GetParent(); 
2489         parent
->GetChildren().Remove( item 
);  // remove by value 
2492     if ( changeKeyCurrent 
) 
2494         // may be NULL or not 
2495         m_key_current 
= parent
; 
2498     item
->DeleteChildren(this); 
2499     SendDeleteEvent(item
); 
2504 void wxTreeListMainWindow::DeleteAllItems() 
2510         m_anchor
->DeleteChildren(this); 
2517 void wxTreeListMainWindow::Expand(const wxTreeItemId
& itemId
) 
2519     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2521     wxCHECK_RET( item
, _T("invalid item in wxTreeListMainWindow::Expand") ); 
2523     if ( !item
->HasPlus() ) 
2526     if ( item
->IsExpanded() ) 
2529     wxTreeEvent 
event( wxEVT_COMMAND_TREE_ITEM_EXPANDING
, m_owner
->GetId() ); 
2530     event
.SetItem( (long) item 
); 
2531     event
.SetEventObject( /*this*/m_owner 
); 
2533     if ( m_owner
->ProcessEvent( event 
) && !event
.IsAllowed() ) 
2535         // cancelled by program 
2540     CalculatePositions(); 
2542     RefreshSubtree(item
); 
2544     event
.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED
); 
2545     ProcessEvent( event 
); 
2548 void wxTreeListMainWindow::ExpandAll(const wxTreeItemId
& item
) 
2551     if ( IsExpanded(item
) ) 
2554         wxTreeItemId child 
= GetFirstChild(item
, cookie
); 
2555         while ( child
.IsOk() ) 
2559             child 
= GetNextChild(item
, cookie
); 
2564 void wxTreeListMainWindow::Collapse(const wxTreeItemId
& itemId
) 
2566     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2568     if ( !item
->IsExpanded() ) 
2571     wxTreeEvent 
event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING
, m_owner
->GetId() ); 
2572     event
.SetItem( (long) item 
); 
2573     event
.SetEventObject( /*this*/m_owner 
); 
2574     if ( m_owner
->ProcessEvent( event 
) && !event
.IsAllowed() ) 
2576         // cancelled by program 
2582 #if 0  // TODO why should items be collapsed recursively? 
2583     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2584     size_t count 
= children
.Count(); 
2585     for ( size_t n 
= 0; n 
< count
; n
++ ) 
2587         Collapse(children
[n
]); 
2591     CalculatePositions(); 
2593     RefreshSubtree(item
); 
2595     event
.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED
); 
2596     ProcessEvent( event 
); 
2599 void wxTreeListMainWindow::CollapseAndReset(const wxTreeItemId
& item
) 
2602     DeleteChildren(item
); 
2605 void wxTreeListMainWindow::Toggle(const wxTreeItemId
& itemId
) 
2607     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2609     if (item
->IsExpanded()) 
2615 void wxTreeListMainWindow::Unselect() 
2619         m_current
->SetHilight( FALSE 
); 
2620         RefreshLine( m_current 
); 
2624 void wxTreeListMainWindow::UnselectAllChildren(wxTreeListItem 
*item
) 
2626     if (item
->IsSelected()) 
2628         item
->SetHilight(FALSE
); 
2632     if (item
->HasChildren()) 
2634         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2635         size_t count 
= children
.Count(); 
2636         for ( size_t n 
= 0; n 
< count
; ++n 
) 
2638             UnselectAllChildren(children
[n
]); 
2643 void wxTreeListMainWindow::UnselectAll() 
2645     UnselectAllChildren((wxTreeListItem
*) GetRootItem().m_pItem
); 
2648 // Recursive function ! 
2649 // To stop we must have crt_item<last_item 
2651 // Tag all next children, when no more children, 
2652 // Move to parent (not to tag) 
2653 // Keep going... if we found last_item, we stop. 
2654 bool wxTreeListMainWindow::TagNextChildren(wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
, bool select
) 
2656     wxTreeListItem 
*parent 
= crt_item
->GetParent(); 
2658     if (parent 
== NULL
) // This is root item 
2659         return TagAllChildrenUntilLast(crt_item
, last_item
, select
); 
2661     wxArrayTreeListItems
& children 
= parent
->GetChildren(); 
2662     int index 
= children
.Index(crt_item
); 
2663     wxASSERT( index 
!= wxNOT_FOUND 
); // I'm not a child of my parent? 
2665     size_t count 
= children
.Count(); 
2666     for (size_t n
=(size_t)(index
+1); n
<count
; ++n
) 
2668         if (TagAllChildrenUntilLast(children
[n
], last_item
, select
)) return TRUE
; 
2671     return TagNextChildren(parent
, last_item
, select
); 
2674 bool wxTreeListMainWindow::TagAllChildrenUntilLast(wxTreeListItem 
*crt_item
, wxTreeListItem 
*last_item
, bool select
) 
2676     crt_item
->SetHilight(select
); 
2677     RefreshLine(crt_item
); 
2679     if (crt_item
==last_item
) 
2682     if (crt_item
->HasChildren()) 
2684         wxArrayTreeListItems
& children 
= crt_item
->GetChildren(); 
2685         size_t count 
= children
.Count(); 
2686         for ( size_t n 
= 0; n 
< count
; ++n 
) 
2688             if (TagAllChildrenUntilLast(children
[n
], last_item
, select
)) 
2696 void wxTreeListMainWindow::SelectItemRange(wxTreeListItem 
*item1
, wxTreeListItem 
*item2
) 
2698     // item2 is not necessary after item1 
2699     wxTreeListItem 
*first
=NULL
, *last
=NULL
; 
2701     // choice first' and 'last' between item1 and item2 
2702     if (item1
->GetY()<item2
->GetY()) 
2713     bool select 
= m_current
->IsSelected(); 
2715     if ( TagAllChildrenUntilLast(first
,last
,select
) ) 
2718     TagNextChildren(first
,last
,select
); 
2721 void wxTreeListMainWindow::SelectItem(const wxTreeItemId
& itemId
, 
2722                             bool unselect_others
, 
2723                             bool extended_select
) 
2725     wxCHECK_RET( itemId
.IsOk(), wxT("invalid tree item") ); 
2727     bool is_single
=!(GetWindowStyleFlag() & wxTR_MULTIPLE
); 
2728     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2730     //wxCHECK_RET( ( (!unselect_others) && is_single), 
2731     //           wxT("this is a single selection tree") ); 
2733     // to keep going anyhow !!! 
2736         if (item
->IsSelected()) 
2737             return; // nothing to do 
2738         unselect_others 
= TRUE
; 
2739         extended_select 
= FALSE
; 
2741     else if ( unselect_others 
&& item
->IsSelected() ) 
2743         // selection change if there is more than one item currently selected 
2744         wxArrayTreeItemIds selected_items
; 
2745         if ( GetSelections(selected_items
) == 1 ) 
2749     wxTreeEvent 
event( wxEVT_COMMAND_TREE_SEL_CHANGING
, m_owner
->GetId() ); 
2750     event
.SetItem( (long) item 
); 
2751     event
.SetOldItem( (long) m_current 
); 
2752     event
.SetEventObject( /*this*/m_owner 
); 
2753     // TODO : Here we don't send any selection mode yet ! 
2755     if(m_owner
->GetEventHandler()->ProcessEvent( event 
) && !event
.IsAllowed()) 
2758     wxTreeItemId parent 
= GetParent( itemId 
); 
2759     while (parent
.IsOk()) 
2761         if (!IsExpanded(parent
)) 
2764         parent 
= GetParent( parent 
); 
2767     EnsureVisible( itemId 
); 
2770     if (unselect_others
) 
2772         if (is_single
) Unselect(); // to speed up thing 
2777     if (extended_select
) 
2781             m_current 
= m_key_current 
= (wxTreeListItem
*) GetRootItem().m_pItem
; 
2784         // don't change the mark (m_current) 
2785         SelectItemRange(m_current
, item
); 
2789         bool select
=TRUE
; // the default 
2791         // Check if we need to toggle hilight (ctrl mode) 
2792         if (!unselect_others
) 
2793             select
=!item
->IsSelected(); 
2795         m_current 
= m_key_current 
= item
; 
2796         m_current
->SetHilight(select
); 
2797         RefreshLine( m_current 
); 
2800     event
.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED
); 
2801     GetEventHandler()->ProcessEvent( event 
); 
2804 void wxTreeListMainWindow::FillArray(wxTreeListItem 
*item
, 
2805                            wxArrayTreeItemIds 
&array
) const 
2807     if ( item
->IsSelected() ) 
2808         array
.Add(wxTreeItemId(item
)); 
2810     if ( item
->HasChildren() ) 
2812         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2813         size_t count 
= children
.GetCount(); 
2814         for ( size_t n 
= 0; n 
< count
; ++n 
) 
2815             FillArray(children
[n
], array
); 
2819 size_t wxTreeListMainWindow::GetSelections(wxArrayTreeItemIds 
&array
) const 
2822     wxTreeItemId idRoot 
= GetRootItem(); 
2823     if ( idRoot
.IsOk() ) 
2825         FillArray((wxTreeListItem
*) idRoot
.m_pItem
, array
); 
2827     //else: the tree is empty, so no selections 
2829     return array
.Count(); 
2832 void wxTreeListMainWindow::EnsureVisible(const wxTreeItemId
& item
) 
2834     if (!item
.IsOk()) return; 
2836     wxTreeListItem 
*gitem 
= (wxTreeListItem
*) item
.m_pItem
; 
2838     // first expand all parent branches 
2839     wxTreeListItem 
*parent 
= gitem
->GetParent(); 
2843         parent 
= parent
->GetParent(); 
2846     //if (parent) CalculatePositions(); 
2851 void wxTreeListMainWindow::ScrollTo(const wxTreeItemId 
&item
) 
2853     if (!item
.IsOk()) return; 
2855     // We have to call this here because the label in 
2856     // question might just have been added and no screen 
2857     // update taken place. 
2858     if (m_dirty
) wxYieldIfNeeded(); 
2860     wxTreeListItem 
*gitem 
= (wxTreeListItem
*) item
.m_pItem
; 
2862     // now scroll to the item 
2863     int item_y 
= gitem
->GetY(); 
2867     GetViewStart( &start_x
, &start_y 
); 
2868     start_y 
*= PIXELS_PER_UNIT
; 
2872     GetClientSize( &client_w
, &client_h 
); 
2874     if (item_y 
< start_y
+3) 
2879         m_anchor
->GetSize( x
, y
, this ); 
2880         x 
= m_owner
->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB 
2881         y 
+= PIXELS_PER_UNIT
+2; // one more scrollbar unit + 2 pixels 
2882         //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels 
2883         int x_pos 
= GetScrollPos( wxHORIZONTAL 
); 
2884         // Item should appear at top 
2885         SetScrollbars( PIXELS_PER_UNIT
, PIXELS_PER_UNIT
, x
/PIXELS_PER_UNIT
, y
/PIXELS_PER_UNIT
, x_pos
, item_y
/PIXELS_PER_UNIT 
); 
2887     else if (item_y
+GetLineHeight(gitem
) > start_y
+client_h
) 
2892         m_anchor
->GetSize( x
, y
, this ); 
2893         y 
+= PIXELS_PER_UNIT
+2; // one more scrollbar unit + 2 pixels 
2894         //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels 
2895         x 
= m_owner
->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB 
2896         item_y 
+= PIXELS_PER_UNIT
+2; 
2897         int x_pos 
= GetScrollPos( wxHORIZONTAL 
); 
2898         // Item should appear at bottom 
2899         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 
); 
2903 // FIXME: tree sorting functions are not reentrant and not MT-safe! 
2904 static wxTreeListMainWindow 
*s_treeBeingSorted 
= NULL
; 
2906 static int LINKAGEMODE 
tree_ctrl_compare_func(wxTreeListItem 
**item1
, 
2907                                   wxTreeListItem 
**item2
) 
2909     wxCHECK_MSG( s_treeBeingSorted
, 0, wxT("bug in wxTreeListMainWindow::SortChildren()") ); 
2911     return s_treeBeingSorted
->OnCompareItems(*item1
, *item2
); 
2914 int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId
& item1
, 
2915                                const wxTreeItemId
& item2
) 
2917     // ALB: delegate to m_owner, to let the user overrride the comparison 
2918     //return wxStrcmp(GetItemText(item1), GetItemText(item2)); 
2919     return m_owner
->OnCompareItems(item1
, item2
); 
2922 void wxTreeListMainWindow::SortChildren(const wxTreeItemId
& itemId
) 
2924     wxCHECK_RET( itemId
.IsOk(), wxT("invalid tree item") ); 
2926     wxTreeListItem 
*item 
= (wxTreeListItem
*) itemId
.m_pItem
; 
2928     wxCHECK_RET( !s_treeBeingSorted
, 
2929                  wxT("wxTreeListMainWindow::SortChildren is not reentrant") ); 
2931     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
2932     if ( children
.Count() > 1 ) 
2936         s_treeBeingSorted 
= this; 
2937         children
.Sort(tree_ctrl_compare_func
); 
2938         s_treeBeingSorted 
= NULL
; 
2940     //else: don't make the tree dirty as nothing changed 
2944 wxImageList 
*wxTreeListMainWindow::GetImageList() const 
2946     return m_imageListNormal
; 
2950 wxImageList 
*wxTreeListMainWindow::GetButtonsImageList() const 
2952     return m_imageListButtons
; 
2956 wxImageList 
*wxTreeListMainWindow::GetStateImageList() const 
2958     return m_imageListState
; 
2961 void wxTreeListMainWindow::CalculateLineHeight() 
2963     wxClientDC 
dc(this); 
2964     m_lineHeight 
= (int)(dc
.GetCharHeight() + m_linespacing
*2); 
2966     if ( m_imageListNormal 
) 
2968         // Calculate a m_lineHeight value from the normal Image sizes. 
2969         // May be toggle off. Then wxTreeListMainWindow will spread when 
2970         // necessary (which might look ugly). 
2971         int n 
= m_imageListNormal
->GetImageCount(); 
2972         for (int i 
= 0; i 
< n 
; i
++) 
2974             int width 
= 0, height 
= 0; 
2975             m_imageListNormal
->GetSize(i
, width
, height
); 
2976             if (height 
> m_lineHeight
) m_lineHeight 
= height
; 
2980     if (m_imageListButtons
) 
2982         // Calculate a m_lineHeight value from the Button image sizes. 
2983         // May be toggle off. Then wxTreeListMainWindow will spread when 
2984         // necessary (which might look ugly). 
2985         int n 
= m_imageListButtons
->GetImageCount(); 
2986         for (int i 
= 0; i 
< n 
; i
++) 
2988             int width 
= 0, height 
= 0; 
2989             m_imageListButtons
->GetSize(i
, width
, height
); 
2990             if (height 
> m_lineHeight
) m_lineHeight 
= height
; 
2994     if (m_lineHeight 
< 30) 
2995         m_lineHeight 
+= 2;                 // at least 2 pixels 
2997         m_lineHeight 
+= m_lineHeight
/10;   // otherwise 10% extra spacing 
3001 void wxTreeListMainWindow::SetImageList(wxImageList 
*imageList
) 
3003     if (m_ownsImageListNormal
) delete m_imageListNormal
; 
3004     m_imageListNormal 
= imageList
; 
3005     m_ownsImageListNormal 
= FALSE
; 
3007     CalculateLineHeight(); 
3011 void wxTreeListMainWindow::SetStateImageList(wxImageList 
*imageList
) 
3013     if (m_ownsImageListState
) delete m_imageListState
; 
3014     m_imageListState 
= imageList
; 
3015     m_ownsImageListState 
= FALSE
; 
3019 void wxTreeListMainWindow::SetButtonsImageList(wxImageList 
*imageList
) 
3021     if (m_ownsImageListButtons
) delete m_imageListButtons
; 
3022     m_imageListButtons 
= imageList
; 
3023     m_ownsImageListButtons 
= FALSE
; 
3025     CalculateLineHeight(); 
3029 void wxTreeListMainWindow::AssignImageList(wxImageList 
*imageList
) 
3031     SetImageList(imageList
); 
3032     m_ownsImageListNormal 
= TRUE
; 
3036 void wxTreeListMainWindow::AssignStateImageList(wxImageList 
*imageList
) 
3038     SetStateImageList(imageList
); 
3039     m_ownsImageListState 
= TRUE
; 
3043 void wxTreeListMainWindow::AssignButtonsImageList(wxImageList 
*imageList
) 
3045     SetButtonsImageList(imageList
); 
3046     m_ownsImageListButtons 
= TRUE
; 
3049 // ---------------------------------------------------------------------------- 
3051 // ---------------------------------------------------------------------------- 
3053 void wxTreeListMainWindow::AdjustMyScrollbars() 
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         int x_pos 
= GetScrollPos( wxHORIZONTAL 
); 
3062         int y_pos 
= GetScrollPos( wxVERTICAL 
); 
3063         x 
= m_owner
->GetHeaderWindow()->GetWidth() + 2; 
3064         if(x 
< GetClientSize().GetWidth()) x_pos 
= 0; 
3065         //m_total_col_width + 2; // ALB 
3066         SetScrollbars( PIXELS_PER_UNIT
, PIXELS_PER_UNIT
, x
/PIXELS_PER_UNIT
, 
3067                        y
/PIXELS_PER_UNIT
, x_pos
, y_pos 
); 
3071         SetScrollbars( 0, 0, 0, 0 ); 
3075 int wxTreeListMainWindow::GetLineHeight(wxTreeListItem 
*item
) const 
3077     if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT
) 
3078         return item
->GetHeight(); 
3080         return m_lineHeight
; 
3083 void wxTreeListMainWindow::PaintItem(wxTreeListItem 
*item
, wxDC
& dc
) 
3085     // TODO implement "state" icon on items 
3087     wxTreeItemAttr 
*attr 
= item
->GetAttributes(); 
3088     if ( attr 
&& attr
->HasFont() ) 
3089         dc
.SetFont(attr
->GetFont()); 
3090     else if (item
->IsBold()) 
3091         dc
.SetFont(m_boldFont
); 
3093     long text_w 
= 0, text_h 
= 0; 
3095     dc
.GetTextExtent( item
->GetText(GetMainColumn()), &text_w
, &text_h 
); 
3097     int total_h 
= GetLineHeight(item
); 
3099     if ( item
->IsSelected() ) 
3101         dc
.SetBrush(*(m_hasFocus 
? m_hilightBrush 
: m_hilightUnfocusedBrush
)); 
3106         if ( attr 
&& attr
->HasBackgroundColour() ) 
3107             colBg 
= attr
->GetBackgroundColour(); 
3109             colBg 
= m_backgroundColour
; 
3110         dc
.SetBrush(wxBrush(colBg
, wxSOLID
)); 
3113     int offset 
= HasFlag(wxTR_ROW_LINES
) ? 1 : 0; 
3115     dc
.DrawRectangle(0, item
->GetY()+offset
, 
3116                      m_owner
->GetHeaderWindow()->GetWidth(), 
3119     dc
.SetBackgroundMode(wxTRANSPARENT
); 
3120     int extraH 
= (total_h 
> text_h
) ? (total_h 
- text_h
)/2 : 0; 
3121     int extra_offset 
= 0; 
3122     for(size_t i 
= 0; i 
< GetColumnCount(); ++i
) { 
3123         int coord_x 
= extra_offset
, image_x 
= coord_x
; 
3124         int clip_width 
= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
3125         int image_h 
= 0, image_w 
= 0; //2; 
3126         int image 
= NO_IMAGE
; 
3128         if(i 
== GetMainColumn()) { 
3129             image 
= item
->GetCurrentImage(); 
3130             coord_x 
= item
->GetX(); 
3133             image 
= item
->GetImage(i
); 
3136         if(image 
!= NO_IMAGE
) { 
3137             if(m_imageListNormal
) { 
3138                 m_imageListNormal
->GetSize( image
, image_w
, image_h 
); 
3146         // honor text alignment 
3147         wxString text 
= item
->GetText(i
); 
3149         switch(m_owner
->GetHeaderWindow()->GetColumn(i
).GetAlignment()) { 
3150         case wxTL_ALIGN_LEFT
: 
3151             coord_x 
+= image_w 
+ 2; 
3152             image_x 
= coord_x 
- image_w
; 
3154         case wxTL_ALIGN_RIGHT
: 
3155             dc
.GetTextExtent(text
, &text_w
, NULL
); 
3156             coord_x 
+= clip_width 
- text_w 
- image_w 
- 2; 
3157             image_x 
= coord_x 
- image_w
; 
3159         case wxTL_ALIGN_CENTER
: 
3160             dc
.GetTextExtent(text
, &text_w
, NULL
); 
3161             //coord_x += (clip_width - text_w)/2 + image_w; 
3162             image_x 
+= (clip_width 
- text_w 
- image_w
)/2 + 2; 
3163             coord_x 
= image_x 
+ image_w
; 
3166         wxDCClipper 
clipper(dc
, /*coord_x,*/ extra_offset
, 
3167                             item
->GetY() + extraH
, clip_width
, 
3170         if(image 
!= NO_IMAGE
) { 
3171             m_imageListNormal
->Draw( image
, dc
, image_x
, 
3172                                      item
->GetY() +((total_h 
> image_h
)? 
3173                                                     ((total_h
-image_h
)/2):0), 
3174                                      wxIMAGELIST_DRAW_TRANSPARENT 
); 
3178                      (wxCoord
)(coord_x 
/*image_w + item->GetX()*/), 
3179                      (wxCoord
)(item
->GetY() + extraH
)); 
3180         extra_offset 
+= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
3183     // restore normal font 
3184     dc
.SetFont( m_normalFont 
); 
3187 // Now y stands for the top of the item, whereas it used to stand for middle ! 
3188 void wxTreeListMainWindow::PaintLevel( wxTreeListItem 
*item
, wxDC 
&dc
, 
3189                                     int level
, int &y
, int x_offset 
) 
3191     int x 
= level
*m_indent 
+ x_offset
; 
3192     if (!HasFlag(wxTR_HIDE_ROOT
)) 
3196     else if (level 
== 0) 
3198         // always expand hidden root 
3200         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
3201         int count 
= children
.Count(); 
3207                 PaintLevel(children
[n
], dc
, 1, y
, x_offset
); 
3208             } while (++n 
< count
); 
3210             if (!HasFlag(wxTR_NO_LINES
) && HasFlag(wxTR_LINES_AT_ROOT
) && 
3213                 // draw line down to last child 
3214                 origY 
+= GetLineHeight(children
[0])>>1; 
3215                 oldY 
+= GetLineHeight(children
[n
-1])>>1; 
3216                 dc
.DrawLine(3, origY
, 3, oldY
); 
3222     item
->SetX(x
+m_spacing
); 
3225     int h 
= GetLineHeight(item
); 
3227     int y_mid 
= y_top 
+ (h
>>1); 
3230     int exposed_x 
= dc
.LogicalToDeviceX(0); 
3231     int exposed_y 
= dc
.LogicalToDeviceY(y_top
); 
3233     if (IsExposed(exposed_x
, exposed_y
, 10000, h
))  // 10000 = very much 
3237             // don't draw rect outline if we already have the 
3238             // background color under Mac 
3239             (item
->IsSelected() && m_hasFocus
) ? wxBLACK_PEN 
: 
3240 #endif // !__WXMAC__ 
3244         if ( item
->IsSelected() ) 
3246             colText 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
3250             wxTreeItemAttr 
*attr 
= item
->GetAttributes(); 
3251             if (attr 
&& attr
->HasTextColour()) 
3252                 colText 
= attr
->GetTextColour(); 
3254                 //colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); 
3255                 colText 
= GetForegroundColour(); 
3259         dc
.SetTextForeground(colText
); 
3263         PaintItem(item
, dc
); 
3265         if (HasFlag(wxTR_ROW_LINES
)) 
3267             int total_width 
= m_owner
->GetHeaderWindow()->GetWidth(); 
3268             // if the background colour is white, choose a 
3269             // contrasting color for the lines 
3270             dc
.SetPen(*((GetBackgroundColour() == *wxWHITE
) 
3271                          ? wxMEDIUM_GREY_PEN 
: wxWHITE_PEN
)); 
3272             dc
.DrawLine(0, y_top
, total_width
, y_top
); 
3273             dc
.DrawLine(0, y
, total_width
, y
); 
3276         // restore DC objects 
3277         dc
.SetBrush(*wxWHITE_BRUSH
); 
3278         dc
.SetPen(m_dottedPen
); 
3279         dc
.SetTextForeground(*wxBLACK
); 
3281         size_t clip_width 
= m_owner
->GetHeaderWindow()->GetColumn( 
3282             m_main_column
).GetWidth(); 
3283             //m_columns[m_main_column].GetWidth(); 
3284         if (item
->HasPlus() && HasButtons())  // should the item show a button? 
3286             // clip to the column width 
3287             wxDCClipper 
clipper(dc
, x_offset
, y_top
, clip_width
, 10000); 
3289             if (!HasFlag(wxTR_NO_LINES
)) 
3291                 if (x 
> (signed)m_indent
) 
3292                     dc
.DrawLine(x 
- m_indent
, y_mid
, x 
- 5, y_mid
); 
3293                 else if (HasFlag(wxTR_LINES_AT_ROOT
)) 
3294                     dc
.DrawLine(3, y_mid
, x 
- 5, y_mid
); 
3295                 dc
.DrawLine(x 
+ 5, y_mid
, x 
+ m_spacing
, y_mid
); 
3298             if (m_imageListButtons 
!= NULL
) 
3300                 // draw the image button here 
3301                 int image_h 
= 0, image_w 
= 0, image 
= wxTreeItemIcon_Normal
; 
3302                 if (item
->IsExpanded()) image 
= wxTreeItemIcon_Expanded
; 
3303                 if (item
->IsSelected()) 
3304                     image 
+= wxTreeItemIcon_Selected 
- wxTreeItemIcon_Normal
; 
3305                 m_imageListButtons
->GetSize(image
, image_w
, image_h
); 
3306                 int xx 
= x 
- (image_w
>>1); 
3307                 int yy 
= y_mid 
- (image_h
>>1); 
3308                 dc
.SetClippingRegion(xx
, yy
, image_w
, image_h
); 
3309                 m_imageListButtons
->Draw(image
, dc
, xx
, yy
, 
3310                                          wxIMAGELIST_DRAW_TRANSPARENT
); 
3311                 dc
.DestroyClippingRegion(); 
3313             else if (HasFlag(wxTR_TWIST_BUTTONS
)) 
3315                 // draw the twisty button here 
3316                 dc
.SetPen(*wxBLACK_PEN
); 
3317                 dc
.SetBrush(*m_hilightBrush
); 
3321                 if (item
->IsExpanded()) 
3324                     button
[0].y 
= y_mid
-2; 
3326                     button
[1].y 
= y_mid
-2; 
3328                     button
[2].y 
= y_mid
+3; 
3332                     button
[0].y 
= y_mid
-5; 
3334                     button
[1].y 
= y_mid
+5; 
3336                     button
[2].y 
= y_mid
; 
3339                 dc
.DrawPolygon(3, button
); 
3341                 dc
.SetPen(m_dottedPen
); 
3343             else // if (HasFlag(wxTR_HAS_BUTTONS)) 
3345                 // draw the plus sign here 
3346                 dc
.SetPen(*wxGREY_PEN
); 
3347                 dc
.SetBrush(*wxWHITE_BRUSH
); 
3348                 dc
.DrawRectangle(x
-5, y_mid
-4, 11, 9); 
3349                 dc
.SetPen(*wxBLACK_PEN
); 
3350                 dc
.DrawLine(x
-2, y_mid
, x
+3, y_mid
); 
3351                 if (!item
->IsExpanded()) 
3352                     dc
.DrawLine(x
, y_mid
-2, x
, y_mid
+3); 
3353                 dc
.SetPen(m_dottedPen
); 
3356         else if (!HasFlag(wxTR_NO_LINES
))  // no button; maybe a line? 
3358             // clip to the column width 
3359             wxDCClipper 
clipper(dc
, x_offset
, y_top
, clip_width
, 10000); 
3360             // draw the horizontal line here 
3362             if (x 
> (signed)m_indent
) 
3363                 x_start 
-= m_indent
; 
3364             else if (HasFlag(wxTR_LINES_AT_ROOT
)) 
3366             dc
.DrawLine(x_start
, y_mid
, x 
+ m_spacing
, y_mid
); 
3370     if (item
->IsExpanded()) 
3372         wxArrayTreeListItems
& children 
= item
->GetChildren(); 
3373         int count 
= children
.Count(); 
3380                 PaintLevel(children
[n
], dc
, level
, y
, x_offset
); 
3381             } while (++n 
< count
); 
3383             if (!HasFlag(wxTR_NO_LINES
) && count 
> 0) 
3385                 size_t clip_width 
= m_owner
->GetHeaderWindow()->GetColumn( 
3386                     m_main_column
).GetWidth(); 
3387                     //m_columns[m_main_column].GetWidth(); 
3388                 // clip to the column width 
3389                 wxDCClipper 
clipper(dc
, x_offset
, y_top
, clip_width
, 10000); 
3390                 // draw line down to last child 
3391                 oldY 
+= GetLineHeight(children
[n
-1])>>1; 
3392                 if (HasButtons()) y_mid 
+= 5; 
3393                 dc
.DrawLine(x
, y_mid
, x
, oldY
); 
3399 void wxTreeListMainWindow::DrawDropEffect(wxTreeListItem 
*item
) 
3403         if ( item
->HasPlus() ) 
3405             // it's a folder, indicate it by a border 
3410             // draw a line under the drop target because the item will be 
3412             DrawLine(item
, TRUE 
/* below */); 
3415         SetCursor(wxCURSOR_BULLSEYE
); 
3420         SetCursor(wxCURSOR_NO_ENTRY
); 
3424 void wxTreeListMainWindow::DrawBorder(const wxTreeItemId 
&item
) 
3426     wxCHECK_RET( item
.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); 
3428     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
3430     wxClientDC 
dc(this); 
3432     dc
.SetLogicalFunction(wxINVERT
); 
3433     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
3435     int w 
= i
->GetWidth() + 2; 
3436     int h 
= GetLineHeight(i
) + 2; 
3438     dc
.DrawRectangle( i
->GetX() - 1, i
->GetY() - 1, w
, h
); 
3441 void wxTreeListMainWindow::DrawLine(const wxTreeItemId 
&item
, bool below
) 
3443     wxCHECK_RET( item
.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); 
3445     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
3447     wxClientDC 
dc(this); 
3449     dc
.SetLogicalFunction(wxINVERT
); 
3455         y 
+= GetLineHeight(i
) - 1; 
3458     dc
.DrawLine( x
, y
, x 
+ i
->GetWidth(), y
); 
3461 // ---------------------------------------------------------------------------- 
3462 // wxWindows callbacks 
3463 // ---------------------------------------------------------------------------- 
3465 void wxTreeListMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
3471     if(!GetColumnCount()) return; // ALB 
3476     dc
.SetFont( m_normalFont 
); 
3477     dc
.SetPen( m_dottedPen 
); 
3479     // this is now done dynamically 
3480     //if(GetImageList() == NULL) 
3481     // m_lineHeight = (int)(dc.GetCharHeight() + 4); 
3483     int y 
= 0; //HEADER_HEIGHT; //2; 
3485     for(size_t i 
= 0; i 
< GetMainColumn(); ++i
) { 
3486         x_offset 
+= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
3488     PaintLevel( m_anchor
, dc
, 0, y
, x_offset 
); 
3491 void wxTreeListMainWindow::OnSetFocus( wxFocusEvent 
&event 
) 
3500 void wxTreeListMainWindow::OnKillFocus( wxFocusEvent 
&event 
) 
3509 void wxTreeListMainWindow::OnChar( wxKeyEvent 
&event 
) 
3511     wxTreeEvent 
te( wxEVT_COMMAND_TREE_KEY_DOWN
, m_owner
->GetId() ); 
3512     te
.SetKeyEvent( event 
); 
3513     te
.SetEventObject( /*this*/m_owner 
); 
3514     if ( m_owner
->GetEventHandler()->ProcessEvent( te 
) ) 
3516         // intercepted by the user code 
3520     if ( (m_current 
== 0) || (m_key_current 
== 0) ) 
3526     // how should the selection work for this event? 
3527     bool is_multiple
, extended_select
, unselect_others
; 
3528     EventFlagsToSelType(GetWindowStyleFlag(), 
3530                         event
.ControlDown(), 
3531                         is_multiple
, extended_select
, unselect_others
); 
3533     // + : Expand (not on Win32) 
3534     // - : Collaspe (not on Win32) 
3535     // * : Expand all/Collapse all 
3536     // ' ' | return : activate 
3537     // up    : go up (not last children!) 
3539     // left  : go to parent (or collapse on Win32) 
3540     // right : open if parent and go next (or expand on Win32) 
3541     // home  : go to root 
3542     // end   : go to last item without opening parents 
3543     switch (event
.KeyCode()) 
3545 #ifndef __WXMSW__ // mimic the standard win32 tree ctrl 
3548             if (m_current
->HasPlus() && !IsExpanded(m_current
)) 
3557             if ( !IsExpanded(m_current
) ) 
3560                 ExpandAll(m_current
); 
3563             //else: fall through to Collapse() it 
3565 #ifndef __WXMSW__ // mimic the standard wxTreeCtrl behaviour 
3568             if (IsExpanded(m_current
)) 
3570                 Collapse(m_current
); 
3578                 wxTreeEvent 
event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED
, 
3580                 event
.SetItem( (long) m_current
); 
3581                 event
.SetEventObject( /*this*/m_owner 
); 
3582                 m_owner
->GetEventHandler()->ProcessEvent( event 
); 
3586             // up goes to the previous sibling or to the last 
3587             // of its children if it's expanded 
3590                 wxTreeItemId prev 
= GetPrevSibling( m_key_current 
); 
3593                     prev 
= GetParent( m_key_current 
); 
3594                     if ((prev 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) 
3596                         break;  // don't go to root if it is hidden 
3601                         wxTreeItemId current 
= m_key_current
; 
3602                         // TODO: Huh?  If we get here, we'd better be the first child of our parent.  How else could it be? 
3603                         if (current 
== GetFirstChild( prev
, cookie 
)) 
3605                             // otherwise we return to where we came from 
3606                             SelectItem( prev
, unselect_others
, extended_select 
); 
3607                             m_key_current
= (wxTreeListItem
*) prev
.m_pItem
; 
3608                             EnsureVisible( prev 
); 
3615                     while ( IsExpanded(prev
) && HasChildren(prev
) ) 
3617                         wxTreeItemId child 
= GetLastChild(prev
); 
3624                     SelectItem( prev
, unselect_others
, extended_select 
); 
3625                     m_key_current
=(wxTreeListItem
*) prev
.m_pItem
; 
3626                     EnsureVisible( prev 
); 
3631             // left arrow goes to the parent 
3633 #if defined(__WXMSW__) // mimic the standard win32 tree ctrl 
3634             if (IsExpanded(m_current
)) 
3636                 Collapse(m_current
); 
3641                 wxTreeItemId prev 
= GetParent( m_current 
); 
3642                 if ((prev 
== GetRootItem()) && HasFlag(wxTR_HIDE_ROOT
)) 
3644                     // don't go to root if it is hidden 
3645                     prev 
= GetPrevSibling( m_current 
); 
3649                     EnsureVisible( prev 
); 
3650                     SelectItem( prev
, unselect_others
, extended_select 
); 
3656 #if defined(__WXMSW__) // mimic the standard win32 tree ctrl 
3657             if (m_current
->HasPlus() && !IsExpanded(m_current
)) 
3664             // this works the same as the down arrow except that we 
3665             // also expand the item if it wasn't expanded yet 
3671                 if (IsExpanded(m_key_current
) && HasChildren(m_key_current
)) 
3674                     wxTreeItemId child 
= GetFirstChild( m_key_current
, cookie 
); 
3675                     SelectItem( child
, unselect_others
, extended_select 
); 
3676                     m_key_current
=(wxTreeListItem
*) child
.m_pItem
; 
3677                     EnsureVisible( child 
); 
3681                     wxTreeItemId next 
= GetNextSibling( m_key_current 
); 
3684                         wxTreeItemId current 
= m_key_current
; 
3685                         while (current 
&& !next
) 
3687                             current 
= GetParent( current 
); 
3688                             if (current
) next 
= GetNextSibling( current 
); 
3693                         SelectItem( next
, unselect_others
, extended_select 
); 
3694                         m_key_current
=(wxTreeListItem
*) next
.m_pItem
; 
3695                         EnsureVisible( next 
); 
3701             // <End> selects the last visible tree item 
3704                 wxTreeItemId last 
= GetRootItem(); 
3706                 while ( last
.IsOk() && IsExpanded(last
) ) 
3708                     wxTreeItemId lastChild 
= GetLastChild(last
); 
3710                     // it may happen if the item was expanded but then all of 
3711                     // its children have been deleted - so IsExpanded() returned 
3712                     // TRUE, but GetLastChild() returned invalid item 
3721                     EnsureVisible( last 
); 
3722                     SelectItem( last
, unselect_others
, extended_select 
); 
3727             // <Home> selects the root item 
3730                 wxTreeItemId prev 
= GetRootItem(); 
3732                 if (HasFlag(wxTR_HIDE_ROOT
)) 
3735                     prev 
= GetFirstChild(prev
, dummy
); 
3738                 EnsureVisible( prev 
); 
3739                 SelectItem( prev
, unselect_others
, extended_select 
); 
3748 wxTreeItemId 
wxTreeListMainWindow::HitTest(const wxPoint
& point
, int& flags
, 
3751     // JACS: removed wxYieldIfNeeded() because it can cause the window 
3752     // to be deleted from under us if a close window event is pending 
3757     if (point
.x
<0) flags 
|= wxTREE_HITTEST_TOLEFT
; 
3758     if (point
.x
>w
) flags 
|= wxTREE_HITTEST_TORIGHT
; 
3759     if (point
.y
<0) flags 
|= wxTREE_HITTEST_ABOVE
; 
3760     if (point
.y
>h
) flags 
|= wxTREE_HITTEST_BELOW
; 
3761     if (flags
) return wxTreeItemId(); 
3763     if (m_anchor 
== NULL
) 
3765         flags 
= wxTREE_HITTEST_NOWHERE
; 
3766         return wxTreeItemId(); 
3769     wxClientDC 
dc(this); 
3771     wxCoord x 
= dc
.DeviceToLogicalX( point
.x 
); 
3772     wxCoord y 
= dc
.DeviceToLogicalY( point
.y 
); 
3773     wxTreeListItem 
*hit 
= m_anchor
->HitTest(wxPoint(x
, y
), this, flags
, 
3777         flags 
= wxTREE_HITTEST_NOWHERE
; 
3778         return wxTreeItemId(); 
3783 // get the bounding rectangle of the item (or of its label only) 
3784 bool wxTreeListMainWindow::GetBoundingRect(const wxTreeItemId
& item
, 
3786                          bool WXUNUSED(textOnly
)) const 
3788     wxCHECK_MSG( item
.IsOk(), FALSE
, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") ); 
3790     wxTreeListItem 
*i 
= (wxTreeListItem
*) item
.m_pItem
; 
3793     GetViewStart(& startX
, & startY
); 
3795     rect
.x 
= i
->GetX() - startX
*PIXELS_PER_UNIT
; 
3796     rect
.y 
= i
->GetY() - startY
*PIXELS_PER_UNIT
; 
3797     rect
.width 
= i
->GetWidth(); 
3798     //rect.height = i->GetHeight(); 
3799     rect
.height 
= GetLineHeight(i
); 
3806 void wxTreeListMainWindow::Edit( const wxTreeItemId
& item 
) 
3808     if (!item
.IsOk()) return; 
3810     m_currentEdit 
= (wxTreeListItem
*) item
.m_pItem
; 
3812     wxTreeEvent 
te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT
, m_owner
->GetId() ); 
3813     te
.SetItem( (long) m_currentEdit
); 
3814     te
.SetEventObject( /*this*/m_owner 
); 
3815     m_owner
->GetEventHandler()->ProcessEvent( te 
); 
3817     if (!te
.IsAllowed()) return; 
3819     // We have to call this here because the label in 
3820     // question might just have been added and no screen 
3821     // update taken place. 
3822     if (m_dirty
) wxYieldIfNeeded(); 
3824     wxString s 
= m_currentEdit
->GetText(/*ALB*/m_main_column
); 
3825     int x 
= m_currentEdit
->GetX(); 
3826     int y 
= m_currentEdit
->GetY(); 
3827     int w 
= m_currentEdit
->GetWidth(); 
3828     int h 
= m_currentEdit
->GetHeight(); 
3833     int image 
= m_currentEdit
->GetCurrentImage(); 
3834     if ( image 
!= NO_IMAGE 
) 
3836         if ( m_imageListNormal 
) 
3838             m_imageListNormal
->GetSize( image
, image_w
, image_h 
); 
3843             wxFAIL_MSG(_T("you must create an image list to use images!")); 
3847     w 
-= image_w 
+ 4; // I don't know why +4 is needed 
3849     wxClientDC 
dc(this); 
3851     x 
= dc
.LogicalToDeviceX( x 
); 
3852     y 
= dc
.LogicalToDeviceY( y 
); 
3854     wxTreeListTextCtrl 
*text 
= new wxTreeListTextCtrl(this, -1, 
3864 void wxTreeListMainWindow::OnRenameTimer() 
3869 void wxTreeListMainWindow::OnRenameAccept() 
3871     // TODO if the validator fails this causes a crash 
3872     wxTreeEvent 
le( wxEVT_COMMAND_TREE_END_LABEL_EDIT
, m_owner
->GetId() ); 
3873     le
.SetItem( (long) m_currentEdit 
); 
3874     le
.SetEventObject( /*this*/m_owner 
); 
3875     le
.SetLabel( m_renameRes 
); 
3876     m_owner
->GetEventHandler()->ProcessEvent( le 
); 
3878     if (!le
.IsAllowed()) return; 
3880     SetItemText( m_currentEdit
, m_renameRes 
); 
3883 void wxTreeListMainWindow::OnMouse( wxMouseEvent 
&event 
) 
3885     if ( !m_anchor 
) return; 
3887     // we process left mouse up event (enables in-place edit), right down 
3888     // (pass to the user code), left dbl click (activate item) and 
3889     // dragging/moving events for items drag-and-drop 
3890     if ( !(event
.LeftDown() || 
3892            event
.RightDown() || 
3893            event
.LeftDClick() || 
3895            ((event
.Moving() || event
.RightUp()) && m_isDragging
)) ) 
3902     if ( event
.LeftDown() ) 
3905     wxClientDC 
dc(this); 
3907     wxCoord x 
= dc
.DeviceToLogicalX( event
.GetX() ); 
3908     wxCoord y 
= dc
.DeviceToLogicalY( event
.GetY() ); 
3911     wxTreeListItem 
*item 
= m_anchor
->HitTest(wxPoint(x
,y
), this, flags
, 0); 
3913     if ( event
.Dragging() && !m_isDragging 
) 
3915         if (m_dragCount 
== 0) 
3916             m_dragStart 
= wxPoint(x
,y
); 
3920         if (m_dragCount 
!= 3) 
3922             // wait until user drags a bit further... 
3926         wxEventType command 
= event
.RightIsDown() 
3927                               ? wxEVT_COMMAND_TREE_BEGIN_RDRAG
 
3928                               : wxEVT_COMMAND_TREE_BEGIN_DRAG
; 
3930         wxTreeEvent 
nevent( command
,/*ALB*/ m_owner
->GetId() ); 
3931         nevent
.SetItem( (long) m_current
); 
3932         nevent
.SetEventObject(/*this*/m_owner
); // ALB 
3934         // by default the dragging is not supported, the user code must 
3935         // explicitly allow the event for it to take place 
3938         if ( m_owner
->GetEventHandler()->ProcessEvent(nevent
) && 
3939              nevent
.IsAllowed() ) 
3941             // we're going to drag this item 
3942             m_isDragging 
= TRUE
; 
3944             // remember the old cursor because we will change it while 
3946             m_oldCursor 
= m_cursor
; 
3948             // in a single selection control, hide the selection temporarily 
3949             if ( !(GetWindowStyleFlag() & wxTR_MULTIPLE
) ) 
3951                 m_oldSelection 
= (wxTreeListItem
*) GetSelection().m_pItem
; 
3953                 if ( m_oldSelection 
) 
3955                     m_oldSelection
->SetHilight(FALSE
); 
3956                     RefreshLine(m_oldSelection
); 
3963     else if ( event
.Moving() ) 
3965         if ( item 
!= m_dropTarget 
) 
3967             // unhighlight the previous drop target 
3968             DrawDropEffect(m_dropTarget
); 
3970             m_dropTarget 
= item
; 
3972             // highlight the current drop target if any 
3973             DrawDropEffect(m_dropTarget
); 
3978     else if ( (event
.LeftUp() || event
.RightUp()) && m_isDragging 
) 
3980         // erase the highlighting 
3981         DrawDropEffect(m_dropTarget
); 
3983         if ( m_oldSelection 
) 
3985             m_oldSelection
->SetHilight(TRUE
); 
3986             RefreshLine(m_oldSelection
); 
3987             m_oldSelection 
= (wxTreeListItem 
*)NULL
; 
3990         // generate the drag end event 
3991         wxTreeEvent 
event(wxEVT_COMMAND_TREE_END_DRAG
,/*ALB*/m_owner
->GetId()); 
3993         event
.SetItem( (long) item 
); 
3994         event
.SetPoint( wxPoint(x
, y
) ); 
3995         event
.SetEventObject(/*this*/m_owner
); 
3997         (void)m_owner
->GetEventHandler()->ProcessEvent(event
); 
3999         m_isDragging 
= FALSE
; 
4000         m_dropTarget 
= (wxTreeListItem 
*)NULL
; 
4004         SetCursor(m_oldCursor
); 
4010         // here we process only the messages which happen on tree items 
4014         if (item 
== NULL
) return;  /* we hit the blank area */ 
4016         if ( event
.RightDown() ) 
4019             wxTreeEvent 
nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK
, 
4021             nevent
.SetItem( (long) item 
); 
4023             CalcScrolledPosition(x
, y
, &nx
, &ny
); 
4024             nevent
.SetPoint( wxPoint(nx
, ny
)); 
4025             nevent
.SetEventObject(/*this*/m_owner
); 
4026             m_owner
->GetEventHandler()->ProcessEvent(nevent
); 
4028         else if ( event
.LeftUp() ) 
4032                 if ( (item 
== m_current
) && 
4033                      (flags 
& wxTREE_HITTEST_ONITEMLABEL
) && 
4034                      HasFlag(wxTR_EDIT_LABELS
) ) 
4036                     if ( m_renameTimer
->IsRunning() ) 
4037                         m_renameTimer
->Stop(); 
4039                     m_renameTimer
->Start( 100, TRUE 
); 
4042                 m_lastOnSame 
= FALSE
; 
4045         else // !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick() 
4047             if ( event
.LeftDown() ) 
4050                 m_lastOnSame 
= item 
== m_current
; 
4053             if ( flags 
& wxTREE_HITTEST_ONITEMBUTTON 
) 
4055                 // only toggle the item for a single click, double click on 
4056                 // the button doesn't do anything (it toggles the item twice) 
4057                 if ( event
.LeftDown() ) 
4062                 // don't select the item if the button was clicked 
4066             // how should the selection work for this event? 
4067             bool is_multiple
, extended_select
, unselect_others
; 
4068             EventFlagsToSelType(GetWindowStyleFlag(), 
4070                                 event
.ControlDown(), 
4071                                 is_multiple
, extended_select
, unselect_others
); 
4073             SelectItem(item
, unselect_others
, extended_select
); 
4075             // For some reason, Windows isn't recognizing a left double-click, 
4076             // so we need to simulate it here.  Allow 200 milliseconds for now. 
4077             if ( event
.LeftDClick() ) 
4079                 // double clicking should not start editing the item label 
4080                 m_renameTimer
->Stop(); 
4081                 m_lastOnSame 
= FALSE
; 
4083                 // send activate event first 
4084                 wxTreeEvent 
nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED
, 
4086                 nevent
.SetItem( (long) item 
); 
4088                 CalcScrolledPosition(x
, y
, &nx
, &ny
); 
4089                 nevent
.SetPoint( wxPoint(nx
, ny
) ); 
4090                 nevent
.SetEventObject( /*this*/m_owner 
); 
4091                 if ( !m_owner
->GetEventHandler()->ProcessEvent( nevent 
) ) 
4093                     // if the user code didn't process the activate event, 
4094                     // handle it ourselves by toggling the item when it is 
4096                     if ( item
->HasPlus() ) 
4106 void wxTreeListMainWindow::OnIdle( wxIdleEvent 
&WXUNUSED(event
) ) 
4108     /* after all changes have been done to the tree control, 
4109      * we actually redraw the tree when everything is over */ 
4111     if (!m_dirty
) return; 
4115     CalculatePositions(); 
4117     AdjustMyScrollbars(); 
4120 void wxTreeListMainWindow::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
4123 //     GetClientSize(&w, &h); 
4124 //     m_header_win->SetSize(0, 0, w, HEADER_HEIGHT); 
4127 void wxTreeListMainWindow::OnScroll(wxScrollWinEvent
& event
) 
4130 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) 
4131     wxScrolledWindow::OnScroll(event
); 
4133     HandleOnScroll( event 
); 
4136     if(event
.GetOrientation() == wxHORIZONTAL
) 
4138         m_owner
->GetHeaderWindow()->Refresh(); 
4140         m_owner
->GetHeaderWindow()->MacUpdateImmediately(); 
4146 void wxTreeListMainWindow::CalculateSize( wxTreeListItem 
*item
, wxDC 
&dc 
) 
4152         dc
.SetFont(m_boldFont
); 
4154     dc
.GetTextExtent( item
->GetText(/*ALB*/m_main_column
), &text_w
, &text_h 
); 
4157     // restore normal font 
4158     dc
.SetFont( m_normalFont 
); 
4162     int image 
= item
->GetCurrentImage(); 
4163     if ( image 
!= NO_IMAGE 
) 
4165         if ( m_imageListNormal 
) 
4167             m_imageListNormal
->GetSize( image
, image_w
, image_h 
); 
4173     int total_h 
= (image_h 
> text_h
) ? image_h 
: text_h
; 
4175 //     if (total_h < 30) 
4176 //         total_h += 2;            // at least 2 pixels 
4178 //         total_h += total_h/10;   // otherwise 10% extra spacing 
4180     item
->SetHeight(total_h
); 
4181     if (total_h
>m_lineHeight
) 
4182         m_lineHeight
=total_h
; 
4184     item
->SetWidth(image_w
+text_w
+2); 
4187 // ----------------------------------------------------------------------------- 
4188 // for developper : y is now the top of the level 
4189 // not the middle of it ! 
4190 void wxTreeListMainWindow::CalculateLevel( wxTreeListItem 
*item
, wxDC 
&dc
, 
4191                                         int level
, int &y
, int x_offset 
) 
4193     int x 
= level
*m_indent 
+ x_offset
; 
4194     if (!HasFlag(wxTR_HIDE_ROOT
)) 
4198     else if (level 
== 0) 
4200         // a hidden root is not evaluated, but its 
4201         // children are always calculated 
4205     CalculateSize( item
, dc 
); 
4208     item
->SetX( x
+m_spacing 
); 
4210     y 
+= GetLineHeight(item
); 
4212     if ( !item
->IsExpanded() ) 
4214         // we don't need to calculate collapsed branches 
4219     wxArrayTreeListItems
& children 
= item
->GetChildren(); 
4220     size_t n
, count 
= children
.Count(); 
4222     for (n 
= 0; n 
< count
; ++n 
) 
4223         CalculateLevel( children
[n
], dc
, level
, y
, x_offset 
);  // recurse 
4226 void wxTreeListMainWindow::CalculatePositions() 
4228     if ( !m_anchor 
) return; 
4230     wxClientDC 
dc(this); 
4233     dc
.SetFont( m_normalFont 
); 
4235     dc
.SetPen( m_dottedPen 
); 
4236     //if(GetImageList() == NULL) 
4237     // m_lineHeight = (int)(dc.GetCharHeight() + 4); 
4241     for(size_t i 
= 0; i 
< GetMainColumn(); ++i
) { 
4242         x_offset 
+= m_owner
->GetHeaderWindow()->GetColumnWidth(i
); 
4244     CalculateLevel( m_anchor
, dc
, 0, y
, x_offset 
); // start recursion 
4247 void wxTreeListMainWindow::RefreshSubtree(wxTreeListItem 
*item
) 
4249     if (m_dirty
) return; 
4251     wxClientDC 
dc(this); 
4256     GetClientSize( &cw
, &ch 
); 
4259     rect
.x 
= dc
.LogicalToDeviceX( 0 ); 
4261     rect
.y 
= dc
.LogicalToDeviceY( item
->GetY() - 2 ); 
4264     Refresh( TRUE
, &rect 
); 
4266     AdjustMyScrollbars(); 
4269 void wxTreeListMainWindow::RefreshLine( wxTreeListItem 
*item 
) 
4271     if (m_dirty
) return; 
4273     wxClientDC 
dc(this); 
4278     GetClientSize( &cw
, &ch 
); 
4281     rect
.x 
= dc
.LogicalToDeviceX( 0 ); 
4282     rect
.y 
= dc
.LogicalToDeviceY( item
->GetY() ); 
4284     rect
.height 
= GetLineHeight(item
); //dc.GetCharHeight() + 6; 
4286     Refresh( TRUE
, &rect 
); 
4289 void wxTreeListMainWindow::RefreshSelected() 
4291     // TODO: this is awfully inefficient, we should keep the list of all 
4292     //       selected items internally, should be much faster 
4294         RefreshSelectedUnder(m_anchor
); 
4297 void wxTreeListMainWindow::RefreshSelectedUnder(wxTreeListItem 
*item
) 
4299     if ( item
->IsSelected() ) 
4302     const wxArrayTreeListItems
& children 
= item
->GetChildren(); 
4303     size_t count 
= children
.GetCount(); 
4304     for ( size_t n 
= 0; n 
< count
; n
++ ) 
4306         RefreshSelectedUnder(children
[n
]); 
4310 // ---------------------------------------------------------------------------- 
4311 // changing colours: we need to refresh the tree control 
4312 // ---------------------------------------------------------------------------- 
4314 bool wxTreeListMainWindow::SetBackgroundColour(const wxColour
& colour
) 
4316     if ( !wxWindow::SetBackgroundColour(colour
) ) 
4324 bool wxTreeListMainWindow::SetForegroundColour(const wxColour
& colour
) 
4326     if ( !wxWindow::SetForegroundColour(colour
) ) 
4334 //----------- ALB ------------- 
4336 void wxTreeListMainWindow::SetItemText(const wxTreeItemId
& item
, size_t column
, 
4337                                     const wxString
& text
) 
4339     wxCHECK_RET( item
.IsOk(), wxT("invalid tree item") ); 
4341     wxClientDC 
dc(this); 
4342     wxTreeListItem 
*pItem 
= (wxTreeListItem
*) item
.m_pItem
; 
4343     pItem
->SetText(column
, text
); 
4344     CalculateSize(pItem
, dc
); 
4349 wxString 
wxTreeListMainWindow::GetItemText(const wxTreeItemId
& item
, 
4350                                      size_t column
) const 
4352     wxCHECK_MSG( item
.IsOk(), wxT(""), wxT("invalid tree item") ); 
4354     return ((wxTreeListItem
*) item
.m_pItem
)->GetText(column
); 
4357 //----------------------------- 
4359 //----------------------------------------------------------------------------- 
4361 //----------------------------------------------------------------------------- 
4363 IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl
, wxControl
); 
4365 BEGIN_EVENT_TABLE(wxTreeListCtrl
, wxControl
) 
4366     EVT_SIZE(wxTreeListCtrl::OnSize
) 
4369 bool wxTreeListCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
4372                             long style
, const wxValidator 
&validator
, 
4373                             const wxString
& name
) 
4375     long main_style 
= style 
& ~(wxRAISED_BORDER
|wxSUNKEN_BORDER
 
4376                                 |wxSIMPLE_BORDER
|wxNO_BORDER
|wxDOUBLE_BORDER
 
4378     if(!wxControl::Create(parent
, id
, pos
, size
, style
, validator
, name
)) 
4381     m_main_win 
= new wxTreeListMainWindow(this, -1, wxPoint(0, 0), size
, 
4382                                           main_style
, validator
); 
4383     m_header_win 
= new wxTreeListHeaderWindow(this, -1, m_main_win
, 
4384                                               wxPoint(0, 0), wxDefaultSize
, 
4389 void wxTreeListCtrl::OnSize(wxSizeEvent
& event
) 
4392     GetClientSize(&w
, &h
); 
4394         m_header_win
->SetSize(0, 0, w
, HEADER_HEIGHT
); 
4396         m_main_win
->SetSize(0, HEADER_HEIGHT 
+ 1, w
, h 
- HEADER_HEIGHT 
- 1); 
4399 size_t wxTreeListCtrl::GetCount() const { return m_main_win
->GetCount(); } 
4401 unsigned int wxTreeListCtrl::GetIndent() const 
4402 { return m_main_win
->GetIndent(); } 
4404 void wxTreeListCtrl::SetIndent(unsigned int indent
) 
4405 { m_main_win
->SetIndent(indent
); } 
4407 unsigned int wxTreeListCtrl::GetSpacing() const 
4408 { return m_main_win
->GetSpacing(); } 
4410 void wxTreeListCtrl::SetSpacing(unsigned int spacing
) 
4411 { m_main_win
->SetSpacing(spacing
); } 
4413 unsigned int wxTreeListCtrl::GetLineSpacing() const 
4414 { return m_main_win
->GetLineSpacing(); } 
4416 void wxTreeListCtrl::SetLineSpacing(unsigned int spacing
) 
4417 { m_main_win
->SetLineSpacing(spacing
); } 
4419 wxImageList
* wxTreeListCtrl::GetImageList() const 
4420 { return m_main_win
->GetImageList(); } 
4422 wxImageList
* wxTreeListCtrl::GetStateImageList() const 
4423 { return m_main_win
->GetStateImageList(); } 
4425 wxImageList
* wxTreeListCtrl::GetButtonsImageList() const 
4426 { return m_main_win
->GetButtonsImageList(); } 
4428 void wxTreeListCtrl::SetImageList(wxImageList
* imageList
) 
4429 { m_main_win
->SetImageList(imageList
); } 
4431 void wxTreeListCtrl::SetStateImageList(wxImageList
* imageList
) 
4432 { m_main_win
->SetStateImageList(imageList
); } 
4434 void wxTreeListCtrl::SetButtonsImageList(wxImageList
* imageList
) 
4435 { m_main_win
->SetButtonsImageList(imageList
); } 
4437 void wxTreeListCtrl::AssignImageList(wxImageList
* imageList
) 
4438 { m_main_win
->AssignImageList(imageList
); } 
4440 void wxTreeListCtrl::AssignStateImageList(wxImageList
* imageList
) 
4441 { m_main_win
->AssignStateImageList(imageList
); } 
4443 void wxTreeListCtrl::AssignButtonsImageList(wxImageList
* imageList
) 
4444 { m_main_win
->AssignButtonsImageList(imageList
); } 
4446 wxString 
wxTreeListCtrl::GetItemText(const wxTreeItemId
& item
, size_t column
) 
4448 { return m_main_win
->GetItemText(item
, column
); } 
4450 int wxTreeListCtrl::GetItemImage(const wxTreeItemId
& item
, size_t column
, 
4451                                  wxTreeItemIcon which
) const 
4452 { return m_main_win
->GetItemImage(item
, column
, which
); } 
4454 wxTreeItemData
* wxTreeListCtrl::GetItemData(const wxTreeItemId
& item
) const 
4455 { return m_main_win
->GetItemData(item
); } 
4457 bool wxTreeListCtrl::GetItemBold(const wxTreeItemId
& item
) const 
4458 { return m_main_win
->GetItemBold(item
); } 
4460 wxColour 
wxTreeListCtrl::GetItemTextColour(const wxTreeItemId
& item
) const 
4461 { return m_main_win
->GetItemTextColour(item
); } 
4463 wxColour 
wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId
& item
) 
4465 { return m_main_win
->GetItemBackgroundColour(item
); } 
4467 wxFont 
wxTreeListCtrl::GetItemFont(const wxTreeItemId
& item
) const 
4468 { return m_main_win
->GetItemFont(item
); } 
4471 void wxTreeListCtrl::SetItemText(const wxTreeItemId
& item
, size_t column
, 
4472                                  const wxString
& text
) 
4473 { m_main_win
->SetItemText(item
, column
, text
); } 
4475 void wxTreeListCtrl::SetItemImage(const wxTreeItemId
& item
, 
4478                                   wxTreeItemIcon which
) 
4479 { m_main_win
->SetItemImage(item
, column
, image
, which
); } 
4481 void wxTreeListCtrl::SetItemData(const wxTreeItemId
& item
, 
4482                                  wxTreeItemData
* data
) 
4483 { m_main_win
->SetItemData(item
, data
); } 
4485 void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId
& item
, bool has
) 
4486 { m_main_win
->SetItemHasChildren(item
, has
); } 
4488 void wxTreeListCtrl::SetItemBold(const wxTreeItemId
& item
, bool bold
) 
4489 { m_main_win
->SetItemBold(item
, bold
); } 
4491 void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId
& item
, 
4492                                        const wxColour
& col
) 
4493 { m_main_win
->SetItemTextColour(item
, col
); } 
4495 void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId
& item
, 
4496                                              const wxColour
& col
) 
4497 { m_main_win
->SetItemBackgroundColour(item
, col
); } 
4499 void wxTreeListCtrl::SetItemFont(const wxTreeItemId
& item
, 
4501 { m_main_win
->SetItemFont(item
, font
); } 
4503 bool wxTreeListCtrl::SetFont(const wxFont
& font
) 
4505     if(m_header_win
) m_header_win
->SetFont(font
); 
4507         return m_main_win
->SetFont(font
); 
4511 void wxTreeListCtrl::SetWindowStyle(const long style
) 
4514         m_main_win
->SetWindowStyle(style
); 
4515     // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win 
4518 long wxTreeListCtrl::GetWindowStyle() const 
4520     long style 
= m_windowStyle
; 
4522         style 
|= m_main_win
->GetWindowStyle(); 
4526 bool wxTreeListCtrl::IsVisible(const wxTreeItemId
& item
) const 
4527 { return m_main_win
->IsVisible(item
); } 
4529 bool wxTreeListCtrl::ItemHasChildren(const wxTreeItemId
& item
) const 
4530 { return m_main_win
->ItemHasChildren(item
); } 
4532 bool wxTreeListCtrl::IsExpanded(const wxTreeItemId
& item
) const 
4533 { return m_main_win
->IsExpanded(item
); } 
4535 bool wxTreeListCtrl::IsSelected(const wxTreeItemId
& item
) const 
4536 { return m_main_win
->IsSelected(item
); } 
4538 bool wxTreeListCtrl::IsBold(const wxTreeItemId
& item
) const 
4539 { return m_main_win
->IsBold(item
); } 
4541 size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId
& item
, bool rec
) 
4542 { return m_main_win
->GetChildrenCount(item
, rec
); } 
4544 wxTreeItemId 
wxTreeListCtrl::GetRootItem() const 
4545 { return m_main_win
->GetRootItem(); } 
4547 wxTreeItemId 
wxTreeListCtrl::GetSelection() const 
4548 { return m_main_win
->GetSelection(); } 
4550 size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds
& arr
) const 
4551 { return m_main_win
->GetSelections(arr
); } 
4553 wxTreeItemId 
wxTreeListCtrl::GetParent(const wxTreeItemId
& item
) const 
4554 { return m_main_win
->GetParent(item
); } 
4556 wxTreeItemId 
wxTreeListCtrl::GetFirstChild(const wxTreeItemId
& item
, 
4558 { return m_main_win
->GetFirstChild(item
, cookie
); } 
4560 wxTreeItemId 
wxTreeListCtrl::GetNextChild(const wxTreeItemId
& item
, 
4562 { return m_main_win
->GetNextChild(item
, cookie
); } 
4564 wxTreeItemId 
wxTreeListCtrl::GetLastChild(const wxTreeItemId
& item
) const 
4565 { return m_main_win
->GetLastChild(item
); } 
4567 wxTreeItemId 
wxTreeListCtrl::GetNextSibling(const wxTreeItemId
& item
) const 
4568 { return m_main_win
->GetNextSibling(item
); } 
4570 wxTreeItemId 
wxTreeListCtrl::GetPrevSibling(const wxTreeItemId
& item
) const 
4571 { return m_main_win
->GetPrevSibling(item
); } 
4573 wxTreeItemId 
wxTreeListCtrl::GetFirstVisibleItem() const 
4574 { return m_main_win
->GetFirstVisibleItem(); } 
4576 wxTreeItemId 
wxTreeListCtrl::GetNextVisible(const wxTreeItemId
& item
) const 
4577 { return m_main_win
->GetNextVisible(item
); } 
4579 wxTreeItemId 
wxTreeListCtrl::GetPrevVisible(const wxTreeItemId
& item
) const 
4580 { return m_main_win
->GetPrevVisible(item
); } 
4582 wxTreeItemId 
wxTreeListCtrl::GetNext(const wxTreeItemId
& item
) const 
4583 { return m_main_win
->GetNext(item
); } 
4585 wxTreeItemId 
wxTreeListCtrl::AddRoot(const wxString
& text
, int image
, 
4586                                      int selectedImage
, wxTreeItemData
* data
) 
4587 { return m_main_win
->AddRoot(text
, image
, selectedImage
, data
); } 
4589 wxTreeItemId 
wxTreeListCtrl::PrependItem(const wxTreeItemId
& parent
, 
4590                                          const wxString
& text
, int image
, 
4592                                          wxTreeItemData
* data
) 
4593 { return m_main_win
->PrependItem(parent
, text
, image
, selectedImage
, data
); } 
4595 wxTreeItemId 
wxTreeListCtrl::InsertItem(const wxTreeItemId
& parent
, 
4596                                         const wxTreeItemId
& previous
, 
4597                                         const wxString
& text
, int image
, 
4599                                         wxTreeItemData
* data
) 
4601     return m_main_win
->InsertItem(parent
, previous
, text
, image
, 
4602                                   selectedImage
, data
); 
4605 wxTreeItemId 
wxTreeListCtrl::InsertItem(const wxTreeItemId
& parent
, 
4607                                         const wxString
& text
, int image
, 
4609                                         wxTreeItemData
* data
) 
4611     return m_main_win
->InsertItem(parent
, index
, text
, image
, 
4612                                   selectedImage
, data
); 
4615 wxTreeItemId 
wxTreeListCtrl::AppendItem(const wxTreeItemId
& parent
, 
4616                                         const wxString
& text
, int image
, 
4618                                         wxTreeItemData
* data
) 
4619 { return m_main_win
->AppendItem(parent
, text
, image
, selectedImage
, data
); } 
4621 void wxTreeListCtrl::Delete(const wxTreeItemId
& item
) 
4622 { m_main_win
->Delete(item
); } 
4624 void wxTreeListCtrl::DeleteChildren(const wxTreeItemId
& item
) 
4625 { m_main_win
->DeleteChildren(item
); } 
4627 void wxTreeListCtrl::DeleteAllItems() 
4628 { m_main_win
->DeleteAllItems(); } 
4630 void wxTreeListCtrl::Expand(const wxTreeItemId
& item
) 
4631 { m_main_win
->Expand(item
); } 
4633 void wxTreeListCtrl::ExpandAll(const wxTreeItemId
& item
) 
4634 { m_main_win
->ExpandAll(item
); } 
4636 void wxTreeListCtrl::Collapse(const wxTreeItemId
& item
) 
4637 { m_main_win
->Collapse(item
); } 
4639 void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId
& item
) 
4640 { m_main_win
->CollapseAndReset(item
); } 
4642 void wxTreeListCtrl::Toggle(const wxTreeItemId
& item
) 
4643 { m_main_win
->Toggle(item
); } 
4645 void wxTreeListCtrl::Unselect() 
4646 { m_main_win
->Unselect(); } 
4648 void wxTreeListCtrl::UnselectAll() 
4649 { m_main_win
->UnselectAll(); } 
4651 void wxTreeListCtrl::SelectItem(const wxTreeItemId
& item
, bool unselect_others
, 
4652                                 bool extended_select
) 
4653 { m_main_win
->SelectItem(item
, unselect_others
, extended_select
); } 
4655 void wxTreeListCtrl::EnsureVisible(const wxTreeItemId
& item
) 
4656 { m_main_win
->EnsureVisible(item
); } 
4658 void wxTreeListCtrl::ScrollTo(const wxTreeItemId
& item
) 
4659 { m_main_win
->ScrollTo(item
); } 
4661 wxTreeItemId 
wxTreeListCtrl::HitTest(const wxPoint
& pos
, int& flags
, 
4664     return m_main_win
->HitTest(m_main_win
->ScreenToClient(ClientToScreen(pos
)), 
4668 bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId
& item
, wxRect
& rect
, 
4669                                      bool textOnly
) const 
4670 { return m_main_win
->GetBoundingRect(item
, rect
, textOnly
); } 
4672 void wxTreeListCtrl::Edit(const wxTreeItemId
& item
) 
4673 { m_main_win
->Edit(item
); } 
4675 int wxTreeListCtrl::OnCompareItems(const wxTreeItemId
& item1
, 
4676                                    const wxTreeItemId
& item2
) 
4678     // ALB: do the comparison here, and not delegate to m_main_win, in order 
4679     // to let the user override it 
4680     //return m_main_win->OnCompareItems(item1, item2); 
4681     return wxStrcmp(GetItemText(item1
), GetItemText(item2
)); 
4684 void wxTreeListCtrl::SortChildren(const wxTreeItemId
& item
) 
4685 { m_main_win
->SortChildren(item
); } 
4687 bool wxTreeListCtrl::SetBackgroundColour(const wxColour
& colour
) 
4688 { return m_main_win
->SetBackgroundColour(colour
); } 
4690 bool wxTreeListCtrl::SetForegroundColour(const wxColour
& colour
) 
4691 { return m_main_win
->SetForegroundColour(colour
); } 
4693 size_t wxTreeListCtrl::GetColumnCount() const 
4694 { return m_main_win
->GetColumnCount(); } 
4696 void wxTreeListCtrl::SetColumnWidth(size_t column
, size_t width
) 
4697 { m_header_win
->SetColumnWidth(column
, width
); } 
4699 int wxTreeListCtrl::GetColumnWidth(size_t column
) const 
4700 { return m_header_win
->GetColumnWidth(column
); } 
4702 void wxTreeListCtrl::SetMainColumn(size_t column
) 
4703 { m_main_win
->SetMainColumn(column
); } 
4705 size_t wxTreeListCtrl::GetMainColumn() const 
4706 { return m_main_win
->GetMainColumn(); } 
4708 void wxTreeListCtrl::SetColumnText(size_t column
, const wxString
& text
) 
4710     m_header_win
->SetColumnText(column
, text
); 
4711     m_header_win
->Refresh(); 
4714 wxString 
wxTreeListCtrl::GetColumnText(size_t column
) const 
4715 { return m_header_win
->GetColumnText(column
); } 
4717 void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo
& col
) 
4718 { m_header_win
->AddColumn(col
); } 
4720 void wxTreeListCtrl::InsertColumn(size_t before
, 
4721                                   const wxTreeListColumnInfo
& col
) 
4722 { m_header_win
->InsertColumn(before
, col
); } 
4724 void wxTreeListCtrl::RemoveColumn(size_t column
) 
4725 { m_header_win
->RemoveColumn(column
); } 
4727 void wxTreeListCtrl::SetColumn(size_t column
, const wxTreeListColumnInfo
& col
) 
4728 { m_header_win
->SetColumn(column
, col
); } 
4730 const wxTreeListColumnInfo
& wxTreeListCtrl::GetColumn(size_t column
) const 
4731 { return m_header_win
->GetColumn(column
); } 
4733 wxTreeListColumnInfo
& wxTreeListCtrl::GetColumn(size_t column
) 
4734 { return m_header_win
->GetColumn(column
); } 
4736 void wxTreeListCtrl::SetColumnImage(size_t column
, int image
) 
4738     m_header_win
->SetColumn(column
, GetColumn(column
).SetImage(image
)); 
4741 int wxTreeListCtrl::GetColumnImage(size_t column
) const 
4743     return m_header_win
->GetColumn(column
).GetImage(); 
4746 void wxTreeListCtrl::SetColumnAlignment(size_t column
, 
4747                                         wxTreeListColumnAlign align
) 
4749     m_header_win
->SetColumn(column
, GetColumn(column
).SetAlignment(align
)); 
4752 wxTreeListColumnAlign 
wxTreeListCtrl::GetColumnAlignment(size_t column
) const 
4754     return m_header_win
->GetColumn(column
).GetAlignment(); 
4757 void wxTreeListCtrl::Refresh(bool erase
, const wxRect
* rect
) 
4759     m_main_win
->Refresh(erase
, rect
); 
4760     m_header_win
->Refresh(erase
, rect
); 
4763 void wxTreeListCtrl::SetFocus() 
4764 { m_main_win
->SetFocus(); }