]> Creatis software - creaImageIO.git/blob - src/treelistctrl.cpp
start!
[creaImageIO.git] / src / treelistctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        treelistctrl.cpp
3 // Purpose:     multi column tree control implementation
4 // Author:      Robert Roebling
5 // Maintainer:  Otto Wyss
6 // Created:     01/02/97
7 // RCS-ID:      $Id: treelistctrl.cpp,v 1.1.1.1 2008/09/26 14:15:48 guigues Exp $
8 // Copyright:   (c) 2004 Robert Roebling, Julian Smart, Alberto Griggio,
9 //              Vadim Zeitlin, Otto Wyss
10 // Licence:     wxWindows
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ===========================================================================
14 // declarations
15 // ===========================================================================
16
17 // ---------------------------------------------------------------------------
18 // headers
19 // ---------------------------------------------------------------------------
20
21
22
23
24 #if defined(__GNUG__) && !defined(__APPLE__)
25   #pragma implementation "treelistctrl.h"
26 #endif
27
28 // For compilers that support precompilation, includes "wx.h".
29 #include "wx/wxprec.h"
30
31 #ifdef __BORLANDC__
32     #pragma hdrstop
33 #endif
34
35
36 #include <wx/treebase.h>
37 #include <wx/timer.h>
38 #include <wx/textctrl.h>
39 #include <wx/imaglist.h>
40 #include <wx/settings.h>
41 #include <wx/dcclient.h>
42 #include <wx/dcscreen.h>
43 #include <wx/scrolwin.h>
44
45
46
47
48 //#include "wx/treelistctrl.h"
49 #include "treelistctrl.h"
50
51 #ifdef __WXMAC__
52     #include "wx/mac/private.h"
53 #endif
54
55
56 // ---------------------------------------------------------------------------
57 // array types
58 // ---------------------------------------------------------------------------
59
60 class  wxTreeListItem;
61
62 #if !wxCHECK_VERSION(2, 5, 0)
63 WX_DEFINE_ARRAY(wxTreeListItem *, wxArrayTreeListItems);
64 #else
65 WX_DEFINE_ARRAY_PTR(wxTreeListItem *, wxArrayTreeListItems);
66 #endif
67
68 #include <wx/dynarray.h>
69 WX_DECLARE_OBJARRAY(wxTreeListColumnInfo, wxArrayTreeListColumnInfo);
70 #include <wx/arrimpl.cpp>
71 WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo);
72
73 #if !wxCHECK_VERSION(2, 3, 3)
74 WX_DEFINE_ARRAY(short, wxArrayShort);
75 #endif
76
77
78 // --------------------------------------------------------------------------
79 // constants
80 // --------------------------------------------------------------------------
81
82 static const int NO_IMAGE = -1;
83
84 static const int LINEHEIGHT = 10;
85 static const int LINEATROOT = 5;
86 static const int MARGIN = 2;
87 static const int MININDENT = 16;
88 static const int BTNWIDTH = 9;
89 static const int BTNHEIGHT = 9;
90 static const int EXTRA_WIDTH = 4;
91 static const int EXTRA_HEIGHT = 4;
92 static const int HEADER_OFFSET_X = 1;
93 static const int HEADER_OFFSET_Y = 1;
94
95 static const int DRAG_TIMER_TICKS = 250; // minimum drag wait time in ms
96 static const int FIND_TIMER_TICKS = 500; // minimum find wait time in ms
97 static const int RENAME_TIMER_TICKS = 250; // minimum rename wait time in ms
98
99 const  wxChar* wxTreeListCtrlNameStr = _T("treelistctrl");
100
101 static wxTreeListColumnInfo wxInvalidTreeListColumnInfo;
102
103
104 // ---------------------------------------------------------------------------
105 // private classes
106 // ---------------------------------------------------------------------------
107 //-----------------------------------------------------------------------------
108 //  wxTreeListHeaderWindow (internal)
109 //-----------------------------------------------------------------------------
110
111 class  CREAIMAGEIO_EXPORT wxTreeListHeaderWindow : public wxWindow
112 {
113 protected:
114     wxTreeListMainWindow *m_owner;
115     const wxCursor *m_currentCursor;
116     const wxCursor *m_resizeCursor;
117     bool m_isDragging;
118
119     // column being resized
120     int m_column;
121
122     // divider line position in logical (unscrolled) coords
123     int m_currentX;
124
125     // minimal position beyond which the divider line can't be dragged in
126     // logical coords
127     int m_minX;
128
129     wxArrayTreeListColumnInfo m_columns;
130
131     // total width of the columns
132     int m_total_col_width;
133
134
135 public:
136     wxTreeListHeaderWindow();
137
138     wxTreeListHeaderWindow( wxWindow *win,
139                             wxWindowID id,
140                             wxTreeListMainWindow *owner,
141                             const wxPoint &pos = wxDefaultPosition,
142                             const wxSize &size = wxDefaultSize,
143                             long style = 0,
144                             const wxString &name = _T("wxtreelistctrlcolumntitles") );
145
146     virtual ~wxTreeListHeaderWindow();
147
148     void DoDrawRect( wxDC *dc, int x, int y, int w, int h );
149     void DrawCurrent();
150     void AdjustDC(wxDC& dc);
151
152     void OnPaint( wxPaintEvent &event );
153     void OnMouse( wxMouseEvent &event );
154     void OnSetFocus( wxFocusEvent &event );
155
156     // total width of all columns
157     int GetWidth() const { return m_total_col_width; }
158
159     // column manipulation
160     int GetColumnCount() const { return m_columns.GetCount(); }
161
162     void AddColumn (const wxTreeListColumnInfo& colInfo);
163
164     void InsertColumn (int before, const wxTreeListColumnInfo& colInfo);
165
166     void RemoveColumn (int column);
167
168     // column information manipulation
169     const wxTreeListColumnInfo& GetColumn (int column) const{
170         wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
171                      wxInvalidTreeListColumnInfo, _T("Invalid column"));
172         return m_columns[column];
173     }
174     wxTreeListColumnInfo& GetColumn (int column) {
175         wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
176                      wxInvalidTreeListColumnInfo, _T("Invalid column"));
177         return m_columns[column];
178     }
179     void SetColumn (int column, const wxTreeListColumnInfo& info);
180
181     wxString GetColumnText (int column) const {
182         wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
183                      wxEmptyString, _T("Invalid column"));
184         return m_columns[column].GetText();
185     }
186     void SetColumnText (int column, const wxString& text) {
187         wxCHECK_RET ((column >= 0) && (column < GetColumnCount()),
188                      _T("Invalid column"));
189         m_columns[column].SetText (text);
190     }
191
192     int GetColumnAlignment (int column) const {
193         wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
194                      wxALIGN_LEFT, _T("Invalid column"));
195         return m_columns[column].GetAlignment();
196     }
197     void SetColumnAlignment (int column, int flag) {
198         wxCHECK_RET ((column >= 0) && (column < GetColumnCount()),
199                      _T("Invalid column"));
200         m_columns[column].SetAlignment (flag);
201     }
202
203     int GetColumnWidth (int column) const {
204         wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
205                      -1, _T("Invalid column"));
206         return m_columns[column].GetWidth();
207     }
208     void SetColumnWidth (int column, int width);
209
210     bool IsColumnEditable (int column) const {
211         wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
212                      false, _T("Invalid column"));
213         return m_columns[column].IsEditable();
214     }
215
216     bool IsColumnShown (int column) const {
217         wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
218                      true, _T("Invalid column"));
219         return m_columns[column].IsShown();
220     }
221
222     // needs refresh
223     bool m_dirty;
224
225 private:
226     // common part of all ctors
227     void Init();
228
229     void SendListEvent(wxEventType type, wxPoint pos);
230
231 //EED
232 //    DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow)
233     DECLARE_CLASS(wxTreeListHeaderWindow)
234     DECLARE_EVENT_TABLE()
235 };
236
237
238 // this is the "true" control
239 class  wxTreeListMainWindow: public wxScrolledWindow
240 {
241 public:
242     // creation
243     // --------
244     wxTreeListMainWindow() { Init(); }
245
246     wxTreeListMainWindow (wxTreeListCtrl *parent, wxWindowID id = -1,
247                const wxPoint& pos = wxDefaultPosition,
248                const wxSize& size = wxDefaultSize,
249                long style = wxTR_DEFAULT_STYLE,
250                const wxValidator &validator = wxDefaultValidator,
251                const wxString& name = _T("wxtreelistmainwindow"))
252     {
253         Init();
254         Create (parent, id, pos, size, style, validator, name);
255     }
256
257     virtual ~wxTreeListMainWindow();
258
259     bool Create(wxTreeListCtrl *parent, wxWindowID id = -1,
260                 const wxPoint& pos = wxDefaultPosition,
261                 const wxSize& size = wxDefaultSize,
262                 long style = wxTR_DEFAULT_STYLE,
263                 const wxValidator &validator = wxDefaultValidator,
264                 const wxString& name = _T("wxtreelistctrl"));
265
266     // accessors
267     // ---------
268
269     // return true if this is a virtual list control
270     bool IsVirtual() const { return HasFlag(wxTR_VIRTUAL); }
271
272     // get the total number of items in the control
273     size_t GetCount() const;
274
275     // indent is the number of pixels the children are indented relative to
276     // the parents position. SetIndent() also redraws the control
277     // immediately.
278     unsigned int GetIndent() const { return m_indent; }
279     void SetIndent(unsigned int indent);
280
281     // see wxTreeListCtrl for the meaning
282     unsigned int GetLineSpacing() const { return m_linespacing; }
283     void SetLineSpacing(unsigned int spacing);
284
285     // image list: these functions allow to associate an image list with
286     // the control and retrieve it. Note that when assigned with
287     // SetImageList, the control does _not_ delete
288     // the associated image list when it's deleted in order to allow image
289     // lists to be shared between different controls. If you use
290     // AssignImageList, the control _does_ delete the image list.
291
292     // The normal image list is for the icons which correspond to the
293     // normal tree item state (whether it is selected or not).
294     // Additionally, the application might choose to show a state icon
295     // which corresponds to an app-defined item state (for example,
296     // checked/unchecked) which are taken from the state image list.
297     wxImageList *GetImageList() const { return m_imageListNormal; }
298     wxImageList *GetStateImageList() const { return m_imageListState; }
299     wxImageList *GetButtonsImageList() const { return m_imageListButtons; }
300
301     void SetImageList(wxImageList *imageList);
302     void SetStateImageList(wxImageList *imageList);
303     void SetButtonsImageList(wxImageList *imageList);
304     void AssignImageList(wxImageList *imageList);
305     void AssignStateImageList(wxImageList *imageList);
306     void AssignButtonsImageList(wxImageList *imageList);
307
308     // Functions to work with tree ctrl items.
309
310     // accessors
311     // ---------
312
313     // retrieve item's label
314     wxString GetItemText (const wxTreeItemId& item) const
315     { return GetItemText (item, GetMainColumn()); }
316     wxString GetItemText (const wxTreeItemId& item, int column) const;
317     wxString GetItemText (wxTreeItemData* item, int column) const;
318
319     // get one of the images associated with the item (normal by default)
320     int GetItemImage (const wxTreeItemId& item,
321                       wxTreeItemIcon which = wxTreeItemIcon_Normal) const
322     { return GetItemImage (item, GetMainColumn(), which); }
323     int GetItemImage (const wxTreeItemId& item, int column,
324                       wxTreeItemIcon which = wxTreeItemIcon_Normal) const;
325
326     // get the data associated with the item
327     wxTreeItemData *GetItemData(const wxTreeItemId& item) const;
328
329     bool GetItemBold(const wxTreeItemId& item) const;
330     wxColour GetItemTextColour(const wxTreeItemId& item) const;
331     wxColour GetItemBackgroundColour(const wxTreeItemId& item) const;
332     wxFont GetItemFont(const wxTreeItemId& item) const;
333
334     // modifiers
335     // ---------
336
337     // set item's label
338     void SetItemText (const wxTreeItemId& item, const wxString& text)
339     { SetItemText (item, GetMainColumn(), text); }
340     void SetItemText (const wxTreeItemId& item, int column, const wxString& text);
341
342     // get one of the images associated with the item (normal by default)
343     void SetItemImage (const wxTreeItemId& item, int image,
344                        wxTreeItemIcon which = wxTreeItemIcon_Normal)
345     { SetItemImage (item, GetMainColumn(), image, which); }
346     void SetItemImage (const wxTreeItemId& item, int column, int image,
347                        wxTreeItemIcon which = wxTreeItemIcon_Normal);
348
349     // associate some data with the item
350     void SetItemData(const wxTreeItemId& item, wxTreeItemData *data);
351
352     // force appearance of [+] button near the item. This is useful to
353     // allow the user to expand the items which don't have any children now
354     // - but instead add them only when needed, thus minimizing memory
355     // usage and loading time.
356     void SetItemHasChildren(const wxTreeItemId& item, bool has = true);
357
358     // the item will be shown in bold
359     void SetItemBold(const wxTreeItemId& item, bool bold = true);
360
361     // set the item's text colour
362     void SetItemTextColour(const wxTreeItemId& item, const wxColour& colour);
363
364     // set the item's background colour
365     void SetItemBackgroundColour(const wxTreeItemId& item, const wxColour& colour);
366
367     // set the item's font (should be of the same height for all items)
368     void SetItemFont(const wxTreeItemId& item, const wxFont& font);
369
370     // set the window font
371     virtual bool SetFont( const wxFont &font );
372
373     // set the styles.  No need to specify a GetWindowStyle here since
374     // the base wxWindow member function will do it for us
375     void SetWindowStyle(const long styles);
376
377     // item status inquiries
378     // ---------------------
379
380     // is the item visible (it might be outside the view or not expanded)?
381     bool IsVisible(const wxTreeItemId& item, bool fullRow) const;
382     // does the item has any children?
383     bool HasChildren(const wxTreeItemId& item) const;
384     // is the item expanded (only makes sense if HasChildren())?
385     bool IsExpanded(const wxTreeItemId& item) const;
386     // is this item currently selected (the same as has focus)?
387     bool IsSelected(const wxTreeItemId& item) const;
388     // is item text in bold font?
389     bool IsBold(const wxTreeItemId& item) const;
390         // does the layout include space for a button?
391
392     // number of children
393     // ------------------
394
395     // if 'recursively' is false, only immediate children count, otherwise
396     // the returned number is the number of all items in this branch
397     size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = true);
398
399     // navigation
400     // ----------
401
402     // wxTreeItemId.IsOk() will return false if there is no such item
403
404     // get the root tree item
405     wxTreeItemId GetRootItem() const { return m_rootItem; }
406
407     // get the item currently selected, only if a single item is selected
408   //    wxTreeItemId GetSelection() const { return m_selectItem; }
409   wxTreeItemId GetCurrent() const { return m_curItem; }
410
411     // get all the items currently selected, return count of items
412     size_t GetSelections(wxArrayTreeItemIds&) const;
413
414     // get the parent of this item (may return NULL if root)
415     wxTreeItemId GetItemParent(const wxTreeItemId& item) const;
416
417     // for this enumeration function you must pass in a "cookie" parameter
418     // which is opaque for the application but is necessary for the library
419     // to make these functions reentrant (i.e. allow more than one
420     // enumeration on one and the same object simultaneously). Of course,
421     // the "cookie" passed to GetFirstChild() and GetNextChild() should be
422     // the same!
423
424     // get child of this item
425 #if !wxCHECK_VERSION(2, 5, 0)
426     wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const;
427     wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const;
428     wxTreeItemId GetPrevChild(const wxTreeItemId& item, long& cookie) const;
429     wxTreeItemId GetLastChild(const wxTreeItemId& item, long& cookie) const;
430 #else
431     wxTreeItemId GetFirstChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
432     wxTreeItemId GetNextChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
433     wxTreeItemId GetPrevChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
434     wxTreeItemId GetLastChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
435 #endif
436
437     // get sibling of this item
438     wxTreeItemId GetNextSibling(const wxTreeItemId& item) const;
439     wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const;
440
441     // get item in the full tree (currently only for internal use)
442     wxTreeItemId GetNext(const wxTreeItemId& item, bool fulltree = true) const;
443     wxTreeItemId GetPrev(const wxTreeItemId& item, bool fulltree = true) const;
444
445     // get expanded item, see IsExpanded()
446     wxTreeItemId GetFirstExpandedItem() const;
447     wxTreeItemId GetNextExpanded(const wxTreeItemId& item) const;
448     wxTreeItemId GetPrevExpanded(const wxTreeItemId& item) const;
449
450     // get visible item, see IsVisible()
451     wxTreeItemId GetFirstVisibleItem(bool fullRow) const;
452     wxTreeItemId GetNextVisible(const wxTreeItemId& item, bool fullRow) const;
453     wxTreeItemId GetPrevVisible(const wxTreeItemId& item, bool fullRow) const;
454
455     // operations
456     // ----------
457
458     // add the root node to the tree
459     wxTreeItemId AddRoot (const wxString& text,
460                           int image = -1, int selectedImage = -1,
461                           wxTreeItemData *data = NULL);
462
463     // insert a new item in as the first child of the parent
464     wxTreeItemId PrependItem(const wxTreeItemId& parent,
465                              const wxString& text,
466                              int image = -1, int selectedImage = -1,
467                              wxTreeItemData *data = NULL);
468
469     // insert a new item after a given one
470     wxTreeItemId InsertItem(const wxTreeItemId& parent,
471                             const wxTreeItemId& idPrevious,
472                             const wxString& text,
473                             int image = -1, int selectedImage = -1,
474                             wxTreeItemData *data = NULL);
475
476     // insert a new item before the one with the given index
477     wxTreeItemId InsertItem(const wxTreeItemId& parent,
478                             size_t index,
479                             const wxString& text,
480                             int image = -1, int selectedImage = -1,
481                             wxTreeItemData *data = NULL);
482
483     // insert a new item in as the last child of the parent
484     wxTreeItemId AppendItem(const wxTreeItemId& parent,
485                             const wxString& text,
486                             int image = -1, int selectedImage = -1,
487                             wxTreeItemData *data = NULL);
488
489     // delete this item and associated data if any
490     void Delete(const wxTreeItemId& item);
491     // delete all children (but don't delete the item itself)
492     // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
493     void DeleteChildren(const wxTreeItemId& item);
494     // delete the root and all its children from the tree
495     // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
496     void DeleteRoot();
497
498     // expand this item
499     void Expand(const wxTreeItemId& item);
500     // expand this item and all subitems recursively
501     void ExpandAll(const wxTreeItemId& item);
502     // collapse the item without removing its children
503     void Collapse(const wxTreeItemId& item);
504     // collapse the item and remove all children
505     void CollapseAndReset(const wxTreeItemId& item);
506     // toggles the current state
507     void Toggle(const wxTreeItemId& item);
508
509   // remove the selection from currently selected item (if any)
510   //  void Unselect(wxTreeListItem* item);
511   //  void Unselect();
512     void UnselectAll();
513     // select this item
514     void SelectItem(const wxTreeItemId& item, const wxTreeItemId& prev = (wxTreeItemId*)NULL,
515                     bool unselect_others = true);
516     void SelectAll();
517   void RemoveFromSelection( wxTreeListItem *item );
518   void AddToSelection( wxTreeListItem *item );
519
520     // make sure this item is visible (expanding the parent item and/or
521     // scrolling to this item if necessary)
522     void EnsureVisible(const wxTreeItemId& item);
523     // scroll to this item (but don't expand its parent)
524     void ScrollTo(const wxTreeItemId& item);
525     void AdjustMyScrollbars();
526
527     // The first function is more portable (because easier to implement
528     // on other platforms), but the second one returns some extra info.
529     wxTreeItemId HitTest (const wxPoint& point)
530         { int flags; int column; return HitTest (point, flags, column); }
531     wxTreeItemId HitTest (const wxPoint& point, int& flags)
532         { int column; return HitTest (point, flags, column); }
533     wxTreeItemId HitTest (const wxPoint& point, int& flags, int& column);
534
535
536     // get the bounding rectangle of the item (or of its label only)
537     bool GetBoundingRect(const wxTreeItemId& item,
538                          wxRect& rect,
539                          bool textOnly = false) const;
540
541     // Start editing the item label: this (temporarily) replaces the item
542     // with a one line edit control. The item will be selected if it hadn't
543     // been before.
544     void EditLabel (const wxTreeItemId& item, int column);
545
546     // sorting
547     // this function is called to compare 2 items and should return -1, 0
548     // or +1 if the first item is less than, equal to or greater than the
549     // second one. The base class version performs alphabetic comparaison
550     // of item labels (GetText)
551     virtual int OnCompareItems(const wxTreeItemId& item1,
552                                const wxTreeItemId& item2);
553     // sort the children of this item using OnCompareItems
554     //
555     // NB: this function is not reentrant and not MT-safe (FIXME)!
556     void SortChildren(const wxTreeItemId& item);
557
558     // searching
559     wxTreeItemId FindItem (const wxTreeItemId& item, const wxString& str, int mode = 0);
560
561     // implementation only from now on
562
563     // overridden base class virtuals
564     virtual bool SetBackgroundColour(const wxColour& colour);
565     virtual bool SetForegroundColour(const wxColour& colour);
566
567     // drop over item
568     void SetDragItem (const wxTreeItemId& item = (wxTreeItemId*)NULL);
569
570     // callbacks
571     void OnPaint( wxPaintEvent &event );
572     void OnSetFocus( wxFocusEvent &event );
573     void OnKillFocus( wxFocusEvent &event );
574     void OnChar( wxKeyEvent &event );
575     void OnMouse( wxMouseEvent &event );
576     void OnIdle( wxIdleEvent &event );
577     void OnScroll(wxScrollWinEvent& event);
578
579     // implementation helpers
580     void SendDeleteEvent(wxTreeListItem *itemBeingDeleted);
581
582     int GetColumnCount() const
583     { return m_owner->GetHeaderWindow()->GetColumnCount(); }
584
585     void SetMainColumn (int column)
586     { if ((column >= 0) && (column < GetColumnCount())) m_main_column = column; }
587
588     int GetMainColumn() const { return m_main_column; }
589
590     int GetBestColumnWidth (int column, wxTreeItemId parent = wxTreeItemId());
591     int GetItemWidth (int column, wxTreeListItem *item);
592     wxFont GetItemFont (wxTreeListItem *item);
593
594     void SetFocus();
595
596 protected:
597     wxTreeListCtrl* m_owner;
598
599     int m_main_column;
600
601     friend class wxTreeListItem;
602     friend class wxTreeListRenameTimer;
603     friend class wxEditTextCtrl;
604
605     wxFont               m_normalFont;
606     wxFont               m_boldFont;
607
608     wxTreeListItem       *m_rootItem; // root item
609     wxTreeListItem       *m_curItem; // current item, either selected or marked
610     wxTreeListItem       *m_shiftItem; // item, where the shift key was pressed
611     wxTreeListItem       *m_editItem; // item, which is currently edited
612   //    wxTreeListItem       *m_selectItem; // current selected item, not with wxTR_MULTIPLE
613   // LG  
614   wxArrayTreeListItems   m_selected; // currently selected items
615
616     int                  m_curColumn;
617
618     int                  m_btnWidth, m_btnWidth2;
619     int                  m_btnHeight, m_btnHeight2;
620     int                  m_imgWidth, m_imgWidth2;
621     int                  m_imgHeight, m_imgHeight2;
622     unsigned short       m_indent;
623     int                  m_lineHeight;
624     unsigned short       m_linespacing;
625     wxPen                m_dottedPen;
626     wxBrush             *m_hilightBrush,
627                         *m_hilightUnfocusedBrush;
628     bool                 m_hasFocus;
629 public:
630     bool                 m_dirty;
631 protected:
632     bool                 m_ownsImageListNormal,
633                          m_ownsImageListState,
634                          m_ownsImageListButtons;
635     bool                 m_isDragging; // true between BEGIN/END drag events
636     bool                 m_renameAccept;
637     bool                 m_lastOnSame;  // last click on the same item as prev
638     bool                 m_left_down_selection;
639
640     wxImageList         *m_imageListNormal,
641                         *m_imageListState,
642                         *m_imageListButtons;
643
644     int                  m_dragCount;
645     wxTimer             *m_dragTimer;
646     wxTreeListItem      *m_dragItem;
647
648     wxTimer             *m_renameTimer;
649     wxString             m_renameRes;
650
651     // char navigation
652     wxTimer             *m_findTimer;
653     wxString             m_findStr;
654
655     // the common part of all ctors
656     void Init();
657
658     // misc helpers
659     wxTreeItemId DoInsertItem(const wxTreeItemId& parent,
660                               size_t previous,
661                               const wxString& text,
662                               int image, int selectedImage,
663                               wxTreeItemData *data);
664     bool HasButtons(void) const
665         { return (m_imageListButtons) || HasFlag (wxTR_TWIST_BUTTONS|wxTR_HAS_BUTTONS); }
666
667 protected:
668     void CalculateLineHeight();
669     int  GetLineHeight(wxTreeListItem *item) const;
670     void PaintLevel( wxTreeListItem *item, wxDC& dc, int level, int &y,
671                      int x_maincol);
672     void PaintItem( wxTreeListItem *item, wxDC& dc);
673
674     void CalculateLevel( wxTreeListItem *item, wxDC &dc, int level, int &y,
675                          int x_maincol);
676     void CalculatePositions();
677     void CalculateSize( wxTreeListItem *item, wxDC &dc );
678
679     void RefreshSubtree (wxTreeListItem *item);
680     void RefreshLine (wxTreeListItem *item);
681
682     // redraw all selected items
683     void RefreshSelected();
684
685     // RefreshSelected() recursive helper
686     void RefreshSelectedUnder (wxTreeListItem *item);
687
688     void OnRenameTimer();
689     void OnRenameAccept();
690
691   void FillArray(wxTreeListItem*, wxArrayTreeItemIds&) const;
692     bool SelectAllChildrenUntilLast (wxTreeListItem *crt_item, wxTreeListItem *last_item);
693     bool SelectNextChildren (wxTreeListItem *crt_item, wxTreeListItem *last_item);
694   //    void UnselectAllChildren (wxTreeListItem *item );
695
696 private:
697     DECLARE_EVENT_TABLE()
698     DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow)
699 };
700
701
702 // timer used for enabling in-place edit
703 class  wxTreeListRenameTimer: public wxTimer
704 {
705 public:
706     wxTreeListRenameTimer( wxTreeListMainWindow *owner );
707
708     void Notify();
709
710 private:
711     wxTreeListMainWindow   *m_owner;
712 };
713
714 // control used for in-place edit
715 class  wxEditTextCtrl: public wxTextCtrl
716 {
717 public:
718     wxEditTextCtrl (wxWindow *parent,
719                     const wxWindowID id,
720                     bool *accept,
721                     wxString *res,
722                     wxTreeListMainWindow *owner,
723                     const wxString &value = wxEmptyString,
724                     const wxPoint &pos = wxDefaultPosition,
725                     const wxSize &size = wxDefaultSize,
726                     int style = 0,
727                     const wxValidator& validator = wxDefaultValidator,
728                     const wxString &name = wxTextCtrlNameStr );
729
730     void OnChar( wxKeyEvent &event );
731     void OnKeyUp( wxKeyEvent &event );
732     void OnKillFocus( wxFocusEvent &event );
733
734 private:
735     bool               *m_accept;
736     wxString           *m_res;
737     wxTreeListMainWindow  *m_owner;
738     wxString            m_startValue;
739     bool                m_finished;
740
741     DECLARE_EVENT_TABLE()
742 };
743
744 // a tree item
745 class  wxTreeListItem
746 {
747 public:
748     // ctors & dtor
749     wxTreeListItem() { m_data = NULL; }
750     wxTreeListItem( wxTreeListMainWindow *owner,
751                     wxTreeListItem *parent,
752                     const wxArrayString& text,
753                     int image,
754                     int selImage,
755                     wxTreeItemData *data );
756
757     ~wxTreeListItem();
758
759     // trivial accessors
760     wxArrayTreeListItems& GetChildren() { return m_children; }
761
762     const wxString GetText() const
763     {
764         return GetText(0);
765     }
766     const wxString GetText (int column) const
767     {
768         if(m_text.GetCount() > 0)
769         {
770             if( IsVirtual() )   return m_owner->GetItemText( m_data, column );
771             else                return m_text[column];
772         }
773         return wxEmptyString;
774     }
775
776     int GetImage (wxTreeItemIcon which = wxTreeItemIcon_Normal) const
777         { return m_images[which]; }
778     int GetImage (int column, wxTreeItemIcon which=wxTreeItemIcon_Normal) const
779     {
780         if(column == m_owner->GetMainColumn()) return m_images[which];
781         if(column < (int)m_col_images.GetCount()) return m_col_images[column];
782         return NO_IMAGE;
783     }
784
785     wxTreeItemData *GetData() const { return m_data; }
786
787     // returns the current image for the item (depending on its
788     // selected/expanded/whatever state)
789     int GetCurrentImage() const;
790
791     void SetText (const wxString &text );
792     void SetText (int column, const wxString& text)
793     {
794         if (column < (int)m_text.GetCount()) {
795             m_text[column] = text;
796         }else if (column < m_owner->GetColumnCount()) {
797             int howmany = m_owner->GetColumnCount();
798             for (int i = m_text.GetCount(); i < howmany; ++i) m_text.Add (wxEmptyString);
799             m_text[column] = text;
800         }
801     }
802     void SetImage (int image, wxTreeItemIcon which) { m_images[which] = image; }
803     void SetImage (int column, int image, wxTreeItemIcon which)
804     {
805         if (column == m_owner->GetMainColumn()) {
806             m_images[which] = image;
807         }else if (column < (int)m_col_images.GetCount()) {
808             m_col_images[column] = image;
809         }else if (column < m_owner->GetColumnCount()) {
810             int howmany = m_owner->GetColumnCount();
811             for (int i = m_col_images.GetCount(); i < howmany; ++i) m_col_images.Add (NO_IMAGE);
812             m_col_images[column] = image;
813         }
814     }
815
816     void SetData(wxTreeItemData *data) { m_data = data; }
817
818     void SetHasPlus(bool has = true) { m_hasPlus = has; }
819
820     void SetBold(bool bold) { m_isBold = bold; }
821
822     int GetX() const { return m_x; }
823     int GetY() const { return m_y; }
824
825     void SetX (int x) { m_x = x; }
826     void SetY (int y) { m_y = y; }
827
828     int  GetHeight() const { return m_height; }
829     int  GetWidth()  const { return m_width; }
830
831     void SetHeight (int height) { m_height = height; }
832     void SetWidth (int width) { m_width = width; }
833
834     int GetTextX() const { return m_text_x; }
835     void SetTextX (int text_x) { m_text_x = text_x; }
836
837     wxTreeListItem *GetItemParent() const { return m_parent; }
838
839     // operations
840     // deletes all children notifying the treectrl about it if !NULL
841     // pointer given
842     void DeleteChildren(wxTreeListMainWindow *tree = NULL);
843
844     // get count of all children (and grand children if 'recursively')
845     size_t GetChildrenCount(bool recursively = true) const;
846
847     void Insert(wxTreeListItem *child, size_t index)
848     { m_children.Insert(child, index); }
849
850     void GetSize( int &x, int &y, const wxTreeListMainWindow* );
851
852     // return the item at given position (or NULL if no item), onButton is
853     // true if the point belongs to the item's button, otherwise it lies
854     // on the button's label
855     wxTreeListItem *HitTest (const wxPoint& point,
856                              const wxTreeListMainWindow *,
857                              int &flags, int& column, int level);
858
859     void Expand() { m_isCollapsed = false; }
860     void Collapse() { m_isCollapsed = true; }
861
862     void SetSelected( bool set = true ) { m_hasHilight = set; }
863
864     // status inquiries
865     bool HasChildren() const { return !m_children.IsEmpty(); }
866     bool IsSelected()  const { return m_hasHilight != 0; }
867     bool IsExpanded()  const { return !m_isCollapsed; }
868     bool HasPlus()     const { return m_hasPlus || HasChildren(); }
869     bool IsBold()      const { return m_isBold != 0; }
870     bool IsVirtual()   const { return m_owner->IsVirtual(); }
871
872     // attributes
873     // get them - may be NULL
874     wxTreeItemAttr *GetAttributes() const { return m_attr; }
875     // get them ensuring that the pointer is not NULL
876     wxTreeItemAttr& Attr()
877     {
878         if ( !m_attr )
879         {
880             m_attr = new wxTreeItemAttr;
881             m_ownsAttr = true;
882         }
883         return *m_attr;
884     }
885     // set them
886     void SetAttributes(wxTreeItemAttr *attr)
887     {
888         if ( m_ownsAttr ) delete m_attr;
889         m_attr = attr;
890         m_ownsAttr = false;
891     }
892     // set them and delete when done
893     void AssignAttributes(wxTreeItemAttr *attr)
894     {
895         SetAttributes(attr);
896         m_ownsAttr = true;
897     }
898
899 private:
900     wxTreeListMainWindow  *m_owner;        // control the item belongs to
901
902     // since there can be very many of these, we save size by chosing
903     // the smallest representation for the elements and by ordering
904     // the members to avoid padding.
905     wxArrayString      m_text;    // labels to be rendered for item
906
907     wxTreeItemData     *m_data;         // user-provided data
908
909     wxArrayTreeListItems m_children; // list of children
910     wxTreeListItem  *m_parent;       // parent of this item
911
912     wxTreeItemAttr     *m_attr;         // attributes???
913
914     // tree ctrl images for the normal, selected, expanded and
915     // expanded+selected states
916     short               m_images[wxTreeItemIcon_Max];
917     wxArrayShort m_col_images; // images for the various columns (!= main)
918
919     // main column item positions
920     wxCoord             m_x;            // (virtual) offset from left (vertical line)
921     wxCoord             m_y;            // (virtual) offset from top
922     wxCoord             m_text_x;       // item offset from left
923     short               m_width;        // width of this item
924     unsigned char       m_height;       // height of this item
925
926     // use bitfields to save size
927     int                 m_isCollapsed :1;
928     int                 m_hasHilight  :1; // same as focused
929     int                 m_hasPlus     :1; // used for item which doesn't have
930                                           // children but has a [+] button
931     int                 m_isBold      :1; // render the label in bold font
932     int                 m_ownsAttr    :1; // delete attribute when done
933 };
934
935 // ===========================================================================
936 // implementation
937 // ===========================================================================
938
939 // ---------------------------------------------------------------------------
940 // wxTreeListRenameTimer (internal)
941 // ---------------------------------------------------------------------------
942
943 wxTreeListRenameTimer::wxTreeListRenameTimer( wxTreeListMainWindow *owner )
944 {
945     m_owner = owner;
946 }
947
948 void wxTreeListRenameTimer::Notify()
949 {
950     m_owner->OnRenameTimer();
951 }
952
953 //-----------------------------------------------------------------------------
954 // wxEditTextCtrl (internal)
955 //-----------------------------------------------------------------------------
956
957 BEGIN_EVENT_TABLE (wxEditTextCtrl,wxTextCtrl)
958     EVT_CHAR           (wxEditTextCtrl::OnChar)
959     EVT_KEY_UP         (wxEditTextCtrl::OnKeyUp)
960     EVT_KILL_FOCUS     (wxEditTextCtrl::OnKillFocus)
961 END_EVENT_TABLE()
962
963 wxEditTextCtrl::wxEditTextCtrl (wxWindow *parent,
964                                 const wxWindowID id,
965                                 bool *accept,
966                                 wxString *res,
967                                 wxTreeListMainWindow *owner,
968                                 const wxString &value,
969                                 const wxPoint &pos,
970                                 const wxSize &size,
971                                 int style,
972                                 const wxValidator& validator,
973                                 const wxString &name)
974     : wxTextCtrl (parent, id, value, pos, size, style|wxSIMPLE_BORDER, validator, name)
975 {
976     m_res = res;
977     m_accept = accept;
978     m_owner = owner;
979     (*m_accept) = false;
980     (*m_res) = wxEmptyString;
981     m_startValue = value;
982     m_finished = false;
983 }
984
985 void wxEditTextCtrl::OnChar( wxKeyEvent &event )
986 {
987     if (event.GetKeyCode() == WXK_RETURN)
988     {
989         (*m_accept) = true;
990         (*m_res) = GetValue();
991
992         if ((*m_res) != m_startValue)
993             m_owner->OnRenameAccept();
994
995         if (!wxPendingDelete.Member(this))
996             wxPendingDelete.Append(this);
997
998         m_finished = true;
999         m_owner->SetFocus(); // This doesn't work. TODO.
1000
1001         return;
1002     }
1003     if (event.GetKeyCode() == WXK_ESCAPE)
1004     {
1005         (*m_accept) = false;
1006         (*m_res) = wxEmptyString;
1007
1008         if (!wxPendingDelete.Member(this))
1009             wxPendingDelete.Append(this);
1010
1011         m_finished = true;
1012         m_owner->SetFocus(); // This doesn't work. TODO.
1013
1014         return;
1015     }
1016     event.Skip();
1017 }
1018
1019 void wxEditTextCtrl::OnKeyUp( wxKeyEvent &event )
1020 {
1021     if (m_finished)
1022     {
1023         event.Skip();
1024         return;
1025     }
1026
1027     // auto-grow the textctrl:
1028     wxSize parentSize = m_owner->GetSize();
1029     wxPoint myPos = GetPosition();
1030     wxSize mySize = GetSize();
1031     int sx, sy;
1032     GetTextExtent(GetValue() + _T("M"), &sx, &sy);
1033     if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x;
1034     if (mySize.x > sx) sx = mySize.x;
1035     SetSize(sx, -1);
1036
1037     event.Skip();
1038 }
1039
1040 void wxEditTextCtrl::OnKillFocus( wxFocusEvent &event )
1041 {
1042     if (m_finished)
1043     {
1044         event.Skip();
1045         return;
1046     }
1047
1048     if (!wxPendingDelete.Member(this))
1049         wxPendingDelete.Append(this);
1050
1051     (*m_accept) = true;
1052     (*m_res) = GetValue();
1053
1054     if ((*m_res) != m_startValue)
1055         m_owner->OnRenameAccept();
1056 }
1057
1058 //-----------------------------------------------------------------------------
1059 //  wxTreeListHeaderWindow
1060 //-----------------------------------------------------------------------------
1061
1062
1063
1064 //EED
1065 //IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow,wxNotifyEvent);
1066 IMPLEMENT_CLASS(wxTreeListHeaderWindow,wxNotifyEvent);
1067
1068 BEGIN_EVENT_TABLE(wxTreeListHeaderWindow,wxWindow)
1069     EVT_PAINT         (wxTreeListHeaderWindow::OnPaint)
1070     EVT_MOUSE_EVENTS  (wxTreeListHeaderWindow::OnMouse)
1071     EVT_SET_FOCUS     (wxTreeListHeaderWindow::OnSetFocus)
1072 END_EVENT_TABLE()
1073
1074
1075
1076
1077 void wxTreeListHeaderWindow::Init()
1078 {
1079     m_currentCursor = (wxCursor *) NULL;
1080     m_isDragging = false;
1081     m_dirty = false;
1082     m_total_col_width = 0;
1083 }
1084
1085 wxTreeListHeaderWindow::wxTreeListHeaderWindow()
1086 {
1087     Init();
1088
1089     m_owner = (wxTreeListMainWindow *) NULL;
1090     m_resizeCursor = (wxCursor *) NULL;
1091 }
1092
1093 wxTreeListHeaderWindow::wxTreeListHeaderWindow( wxWindow *win,
1094                                                 wxWindowID id,
1095                                                 wxTreeListMainWindow *owner,
1096                                                 const wxPoint& pos,
1097                                                 const wxSize& size,
1098                                                 long style,
1099                                                 const wxString &name )
1100     : wxWindow( win, id, pos, size, style, name )
1101 {
1102     Init();
1103
1104     m_owner = owner;
1105     m_resizeCursor = new wxCursor(wxCURSOR_SIZEWE);
1106
1107 #if !wxCHECK_VERSION(2, 5, 0)
1108     SetBackgroundColour (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNFACE));
1109 #else
1110     SetBackgroundColour (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNFACE));
1111 #endif
1112 }
1113
1114 wxTreeListHeaderWindow::~wxTreeListHeaderWindow()
1115 {
1116     delete m_resizeCursor;
1117 }
1118
1119 void wxTreeListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h )
1120 {
1121 #if !wxCHECK_VERSION(2, 5, 0)
1122     wxPen pen (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID);
1123 #else
1124     wxPen pen (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID);
1125 #endif
1126
1127     const int m_corner = 1;
1128
1129     dc->SetBrush( *wxTRANSPARENT_BRUSH );
1130 #if defined( __WXMAC__  )
1131     dc->SetPen (pen);
1132 #else // !GTK, !Mac
1133     dc->SetPen( *wxBLACK_PEN );
1134 #endif
1135     dc->DrawLine( x+w-m_corner+1, y, x+w, y+h );  // right (outer)
1136     dc->DrawRectangle( x, y+h, w+1, 1 );          // bottom (outer)
1137
1138 #if defined( __WXMAC__  )
1139     wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID );
1140 #endif
1141     dc->SetPen( pen );
1142     dc->DrawLine( x+w-m_corner, y, x+w-1, y+h );  // right (inner)
1143     dc->DrawRectangle( x+1, y+h-1, w-2, 1 );      // bottom (inner)
1144
1145     dc->SetPen( *wxWHITE_PEN );
1146     dc->DrawRectangle( x, y, w-m_corner+1, 1 );   // top (outer)
1147     dc->DrawRectangle( x, y, 1, h );              // left (outer)
1148     dc->DrawLine( x, y+h-1, x+1, y+h-1 );
1149     dc->DrawLine( x+w-1, y, x+w-1, y+1 );
1150 }
1151
1152 // shift the DC origin to match the position of the main window horz
1153 // scrollbar: this allows us to always use logical coords
1154 void wxTreeListHeaderWindow::AdjustDC(wxDC& dc)
1155 {
1156     int xpix;
1157     m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
1158     int x;
1159     m_owner->GetViewStart( &x, NULL );
1160
1161     // account for the horz scrollbar offset
1162     dc.SetDeviceOrigin( -x * xpix, 0 );
1163 }
1164
1165 void wxTreeListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1166 {
1167 #ifdef __WXGTK__
1168     wxClientDC dc( this );
1169 #else
1170     wxPaintDC dc( this );
1171 #endif
1172
1173     PrepareDC( dc );
1174     AdjustDC( dc );
1175     dc.SetFont( GetFont() );
1176
1177     // width and height of the entire header window
1178     int w, h;
1179     GetClientSize( &w, &h );
1180     m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1181     dc.SetBackgroundMode(wxTRANSPARENT);
1182
1183     // do *not* use the listctrl colour for headers - one day we will have a
1184     // function to set it separately
1185     //dc.SetTextForeground( *wxBLACK );
1186 #if !wxCHECK_VERSION(2, 5, 0)
1187     dc.SetTextForeground (wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
1188 #else
1189     dc.SetTextForeground (wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ));
1190 #endif
1191
1192     int x = HEADER_OFFSET_X;
1193
1194     int numColumns = GetColumnCount();
1195     for ( int i = 0; i < numColumns && x < w; i++ )
1196     {
1197         if (!IsColumnShown (i)) continue; // do next colume if not shown
1198
1199         wxTreeListColumnInfo& column = GetColumn(i);
1200         int wCol = column.GetWidth();
1201
1202         // the width of the rect to draw: make it smaller to fit entirely
1203         // inside the column rect
1204         int cw = wCol - 2;
1205
1206         dc.SetPen( *wxWHITE_PEN );
1207         DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 );
1208
1209         // if we have an image, draw it on the right of the label
1210         int image = column.GetImage(); //item.m_image;
1211         int ix = -2, iy = 0;
1212         wxImageList* imageList = m_owner->GetImageList();
1213         if ((image != -1) && imageList) {
1214             imageList->GetSize (image, ix, iy);
1215         }
1216
1217         // extra margins around the text label
1218         int text_width = 0;
1219         int text_x = x;
1220         int image_offset = cw - ix - 1;
1221
1222         switch(column.GetAlignment()) {
1223         case wxALIGN_LEFT:
1224             text_x += EXTRA_WIDTH;
1225             cw -= ix + 2;
1226             break;
1227         case wxALIGN_RIGHT:
1228             dc.GetTextExtent (column.GetText(), &text_width, NULL);
1229             text_x += cw - text_width - EXTRA_WIDTH - MARGIN;
1230             image_offset = 0;
1231             break;
1232         case wxALIGN_CENTER:
1233             dc.GetTextExtent(column.GetText(), &text_width, NULL);
1234             text_x += (cw - text_width)/2 + ix + 2;
1235             image_offset = (cw - text_width - ix - 2)/2 - MARGIN;
1236             break;
1237         }
1238
1239         // draw the image
1240         if ((image != -1) && imageList) {
1241             imageList->Draw (image, dc, x + image_offset/*cw - ix - 1*/,
1242                              HEADER_OFFSET_Y + (h - 4 - iy)/2,
1243                              wxIMAGELIST_DRAW_TRANSPARENT);
1244         }
1245
1246         // draw the text clipping it so that it doesn't overwrite the column boundary
1247         wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 );
1248         dc.DrawText (column.GetText(), text_x, HEADER_OFFSET_Y + EXTRA_HEIGHT );
1249
1250         // next column
1251         x += wCol;
1252     }
1253
1254     int more_w = m_owner->GetSize().x - x - HEADER_OFFSET_X;
1255     if (more_w > 0) {
1256         DoDrawRect (&dc, x, HEADER_OFFSET_Y, more_w, h-2 );
1257     }
1258
1259 }
1260
1261 void wxTreeListHeaderWindow::DrawCurrent()
1262 {
1263     int x1 = m_currentX;
1264     int y1 = 0;
1265     ClientToScreen (&x1, &y1);
1266
1267     int x2 = m_currentX-1;
1268 #ifdef __WXMSW__
1269     ++x2; // but why ????
1270 #endif
1271     int y2 = 0;
1272     m_owner->GetClientSize( NULL, &y2 );
1273     m_owner->ClientToScreen( &x2, &y2 );
1274
1275     wxScreenDC dc;
1276     dc.SetLogicalFunction (wxINVERT);
1277     dc.SetPen (wxPen (*wxBLACK, 2, wxSOLID));
1278     dc.SetBrush (*wxTRANSPARENT_BRUSH);
1279
1280     AdjustDC(dc);
1281     dc.DrawLine (x1, y1, x2, y2);
1282     dc.SetLogicalFunction (wxCOPY);
1283     dc.SetPen (wxNullPen);
1284     dc.SetBrush (wxNullBrush);
1285 }
1286
1287 void wxTreeListHeaderWindow::OnMouse (wxMouseEvent &event) {
1288
1289     // we want to work with logical coords
1290     int x;
1291     m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
1292     int y = event.GetY();
1293
1294     if (m_isDragging) {
1295
1296         SendListEvent (wxEVT_COMMAND_LIST_COL_DRAGGING, event.GetPosition());
1297
1298         // we don't draw the line beyond our window, but we allow dragging it
1299         // there
1300         int w = 0;
1301         GetClientSize( &w, NULL );
1302         m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1303         w -= 6;
1304
1305         // erase the line if it was drawn
1306         if (m_currentX < w) DrawCurrent();
1307
1308         if (event.ButtonUp()) {
1309             m_isDragging = false;
1310             if (HasCapture()) ReleaseMouse();
1311             m_dirty = true;
1312             SetColumnWidth (m_column, m_currentX - m_minX);
1313             Refresh();
1314             SendListEvent (wxEVT_COMMAND_LIST_COL_END_DRAG, event.GetPosition());
1315         }else{
1316             m_currentX = wxMax (m_minX + 7, x);
1317
1318             // draw in the new location
1319             if (m_currentX < w) DrawCurrent();
1320         }
1321
1322     }else{ // not dragging
1323
1324         m_minX = 0;
1325         bool hit_border = false;
1326
1327         // end of the current column
1328         int xpos = 0;
1329
1330         // find the column where this event occured
1331         int countCol = GetColumnCount();
1332         for (int column = 0; column < countCol; column++) {
1333             if (!IsColumnShown (column)) continue; // do next if not shown
1334
1335             xpos += GetColumnWidth (column);
1336             m_column = column;
1337             if ((abs (x-xpos) < 3) && (y < 22)) {
1338                 // near the column border
1339                 hit_border = true;
1340                 break;
1341             }
1342
1343             if (x < xpos) {
1344                 // inside the column
1345                 break;
1346             }
1347
1348             m_minX = xpos;
1349         }
1350
1351         if (event.LeftDown() || event.RightUp()) {
1352             if (hit_border && event.LeftDown()) {
1353                 m_isDragging = true;
1354                 CaptureMouse();
1355                 m_currentX = x;
1356                 DrawCurrent();
1357                 SendListEvent (wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, event.GetPosition());
1358             }else{ // click on a column
1359                 wxEventType evt = event.LeftDown()? wxEVT_COMMAND_LIST_COL_CLICK:
1360                                                     wxEVT_COMMAND_LIST_COL_RIGHT_CLICK;
1361                 SendListEvent (evt, event.GetPosition());
1362             }
1363         }else if (event.LeftDClick() && hit_border) {
1364             SetColumnWidth (m_column, m_owner->GetBestColumnWidth (m_column));
1365             Refresh();
1366
1367         }else if (event.Moving()) {
1368             bool setCursor;
1369             if (hit_border) {
1370                 setCursor = m_currentCursor == wxSTANDARD_CURSOR;
1371                 m_currentCursor = m_resizeCursor;
1372             }else{
1373                 setCursor = m_currentCursor != wxSTANDARD_CURSOR;
1374                 m_currentCursor = wxSTANDARD_CURSOR;
1375             }
1376             if (setCursor) SetCursor (*m_currentCursor);
1377         }
1378
1379     }
1380 }
1381
1382 void wxTreeListHeaderWindow::OnSetFocus (wxFocusEvent &WXUNUSED(event)) {
1383     m_owner->SetFocus();
1384 }
1385
1386 void wxTreeListHeaderWindow::SendListEvent (wxEventType type, wxPoint pos) {
1387     wxWindow *parent = GetParent();
1388     wxListEvent le (type, parent->GetId());
1389     le.SetEventObject (parent);
1390     le.m_pointDrag = pos;
1391
1392     // the position should be relative to the parent window, not
1393     // this one for compatibility with MSW and common sense: the
1394     // user code doesn't know anything at all about this header
1395     // window, so why should it get positions relative to it?
1396     le.m_pointDrag.y -= GetSize().y;
1397     le.m_col = m_column;
1398     parent->GetEventHandler()->ProcessEvent (le);
1399 }
1400
1401 void wxTreeListHeaderWindow::AddColumn (const wxTreeListColumnInfo& colInfo) {
1402     m_columns.Add (colInfo);
1403     m_total_col_width += colInfo.GetWidth();
1404     m_owner->AdjustMyScrollbars();
1405     m_owner->m_dirty = true;
1406 }
1407
1408 void wxTreeListHeaderWindow::SetColumnWidth (int column, int width) {
1409     wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1410     m_total_col_width -= m_columns[column].GetWidth();
1411     m_columns[column].SetWidth(width);
1412     m_total_col_width += width;
1413     m_owner->AdjustMyScrollbars();
1414     m_owner->m_dirty = true;
1415 }
1416
1417 void wxTreeListHeaderWindow::InsertColumn (int before, const wxTreeListColumnInfo& colInfo) {
1418     wxCHECK_RET ((before >= 0) && (before < GetColumnCount()), _T("Invalid column"));
1419     m_columns.Insert (colInfo, before);
1420     m_total_col_width += colInfo.GetWidth();
1421     m_owner->AdjustMyScrollbars();
1422     m_owner->m_dirty = true;
1423 }
1424
1425 void wxTreeListHeaderWindow::RemoveColumn (int column) {
1426     wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1427     m_total_col_width -= m_columns[column].GetWidth();
1428     m_columns.RemoveAt (column);
1429     m_owner->AdjustMyScrollbars();
1430     m_owner->m_dirty = true;
1431 }
1432
1433 void wxTreeListHeaderWindow::SetColumn (int column, const wxTreeListColumnInfo& info) {
1434     wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1435     int w = m_columns[column].GetWidth();
1436     m_columns[column] = info;
1437     if (w != info.GetWidth()) {
1438         m_total_col_width += info.GetWidth() - w;
1439         m_owner->AdjustMyScrollbars();
1440     }
1441     m_owner->m_dirty = true;
1442 }
1443
1444 // ---------------------------------------------------------------------------
1445 // wxTreeListItem
1446 // ---------------------------------------------------------------------------
1447
1448 wxTreeListItem::wxTreeListItem (wxTreeListMainWindow *owner,
1449                                 wxTreeListItem *parent,
1450                                 const wxArrayString& text,
1451                                 int image, int selImage,
1452                                 wxTreeItemData *data)
1453               : m_text (text) {
1454
1455     m_images[wxTreeItemIcon_Normal] = image;
1456     m_images[wxTreeItemIcon_Selected] = selImage;
1457     m_images[wxTreeItemIcon_Expanded] = NO_IMAGE;
1458     m_images[wxTreeItemIcon_SelectedExpanded] = NO_IMAGE;
1459
1460     m_data = data;
1461     m_x = 0;
1462     m_y = 0;
1463     m_text_x = 0;
1464
1465     m_isCollapsed = true;
1466     m_hasHilight = false;
1467     m_hasPlus = false;
1468     m_isBold = false;
1469
1470     m_owner = owner;
1471     m_parent = parent;
1472
1473     m_attr = (wxTreeItemAttr *)NULL;
1474     m_ownsAttr = false;
1475
1476     // We don't know the height here yet.
1477     m_width = 0;
1478     m_height = 0;
1479 }
1480
1481 wxTreeListItem::~wxTreeListItem() {
1482     delete m_data;
1483     if (m_ownsAttr) delete m_attr;
1484
1485     wxASSERT_MSG( m_children.IsEmpty(), _T("please call DeleteChildren() before destructor"));
1486 }
1487
1488 void wxTreeListItem::DeleteChildren (wxTreeListMainWindow *tree) {
1489     size_t count = m_children.Count();
1490     for (size_t n = 0; n < count; n++) {
1491         wxTreeListItem *child = m_children[n];
1492         if (tree) {
1493             tree->SendDeleteEvent (child);
1494             // LG 
1495             tree->RemoveFromSelection(child);
1496             /*
1497             if (child->IsSelected())
1498               {
1499                 tree->Unselect(child);
1500               }
1501             */
1502             //            if (tree->m_selectItem == child) tree->m_selectItem = (wxTreeListItem*)NULL;
1503         }
1504         child->DeleteChildren (tree);
1505         delete child;
1506     }
1507     m_children.Empty();
1508 }
1509
1510 void wxTreeListItem::SetText (const wxString &text) {
1511     if (m_text.GetCount() > 0) {
1512         m_text[0] = text;
1513     }else{
1514         m_text.Add (text);
1515     }
1516 }
1517
1518 size_t wxTreeListItem::GetChildrenCount (bool recursively) const {
1519     size_t count = m_children.Count();
1520     if (!recursively) return count;
1521
1522     size_t total = count;
1523     for (size_t n = 0; n < count; ++n) {
1524         total += m_children[n]->GetChildrenCount();
1525     }
1526     return total;
1527 }
1528
1529 void wxTreeListItem::GetSize (int &x, int &y, const wxTreeListMainWindow *theButton) {
1530     int bottomY = m_y + theButton->GetLineHeight (this);
1531     if (y < bottomY) y = bottomY;
1532     int width = m_x +  m_width;
1533     if ( x < width ) x = width;
1534
1535     if (IsExpanded()) {
1536         size_t count = m_children.Count();
1537         for (size_t n = 0; n < count; ++n ) {
1538             m_children[n]->GetSize (x, y, theButton);
1539         }
1540     }
1541 }
1542
1543 wxTreeListItem *wxTreeListItem::HitTest (const wxPoint& point,
1544                                          const wxTreeListMainWindow *theCtrl,
1545                                          int &flags, int& column, int level) {
1546
1547     // for a hidden root node, don't evaluate it, but do evaluate children
1548     if (!theCtrl->HasFlag(wxTR_HIDE_ROOT) || (level > 0)) {
1549
1550         // reset any previous hit infos
1551         flags = 0;
1552         column = -1;
1553         wxTreeListHeaderWindow* header_win = theCtrl->m_owner->GetHeaderWindow();
1554
1555         // check for right of all columns (outside)
1556         if (point.x > header_win->GetWidth()) return (wxTreeListItem*) NULL;
1557
1558         // evaluate if y-pos is okay
1559         int h = theCtrl->GetLineHeight (this);
1560         if ((point.y >= m_y) && (point.y <= m_y + h)) {
1561
1562             int maincol = theCtrl->GetMainColumn();
1563
1564             // check for above/below middle
1565             int y_mid = m_y + h/2;
1566             if (point.y < y_mid) {
1567                 flags |= wxTREE_HITTEST_ONITEMUPPERPART;
1568             }else{
1569                 flags |= wxTREE_HITTEST_ONITEMLOWERPART;
1570             }
1571
1572             // check for button hit
1573             if (HasPlus() && theCtrl->HasButtons()) {
1574                 int bntX = m_x - theCtrl->m_btnWidth2;
1575                 int bntY = y_mid - theCtrl->m_btnHeight2;
1576                 if ((point.x >= bntX) && (point.x <= (bntX + theCtrl->m_btnWidth)) &&
1577                     (point.y >= bntY) && (point.y <= (bntY + theCtrl->m_btnHeight))) {
1578                     flags |= wxTREE_HITTEST_ONITEMBUTTON;
1579                     column = maincol;
1580                     return this;
1581                 }
1582             }
1583
1584             // check for image hit
1585             if (theCtrl->m_imgWidth > 0) {
1586                 int imgX = m_text_x - theCtrl->m_imgWidth - MARGIN;
1587                 int imgY = y_mid - theCtrl->m_imgHeight2;
1588                 if ((point.x >= imgX) && (point.x <= (imgX + theCtrl->m_imgWidth)) &&
1589                     (point.y >= imgY) && (point.y <= (imgY + theCtrl->m_imgHeight))) {
1590                     flags |= wxTREE_HITTEST_ONITEMICON;
1591                     column = maincol;
1592                     return this;
1593                 }
1594             }
1595
1596             // check for label hit
1597             if ((point.x >= m_text_x) && (point.x <= (m_text_x + m_width))) {
1598                 flags |= wxTREE_HITTEST_ONITEMLABEL;
1599                 column = maincol;
1600                 return this;
1601             }
1602
1603             // check for indent hit after button and image hit
1604             if (point.x < m_x) {
1605                 flags |= wxTREE_HITTEST_ONITEMINDENT;
1606                 column = -1; // considered not belonging to main column
1607                 return this;
1608             }
1609
1610             // check for right of label
1611             int end = 0;
1612             for (int i = 0; i <= maincol; ++i) end += header_win->GetColumnWidth (i);
1613             if ((point.x > (m_text_x + m_width)) && (point.x <= end)) {
1614                 flags |= wxTREE_HITTEST_ONITEMRIGHT;
1615                 column = -1; // considered not belonging to main column
1616                 return this;
1617             }
1618
1619             // else check for each column except main
1620             int x = 0;
1621             for (int j = 0; j < theCtrl->GetColumnCount(); ++j) {
1622                 if (!header_win->IsColumnShown(j)) continue;
1623                 int w = header_win->GetColumnWidth (j);
1624                 if ((j != maincol) && (point.x >= x && point.x < x+w)) {
1625                     flags |= wxTREE_HITTEST_ONITEMCOLUMN;
1626                     column = j;
1627                     return this;
1628                 }
1629                 x += w;
1630             }
1631
1632             // no special flag or column found
1633             return this;
1634
1635         }
1636
1637         // if children not expanded, return no item
1638         if (!IsExpanded()) return (wxTreeListItem*) NULL;
1639     }
1640
1641     // in any case evaluate children
1642     wxTreeListItem *child;
1643     size_t count = m_children.Count();
1644     for (size_t n = 0; n < count; n++) {
1645         child = m_children[n]->HitTest (point, theCtrl, flags, column, level+1);
1646         if (child) return child;
1647     }
1648
1649     // not found
1650     return (wxTreeListItem*) NULL;
1651 }
1652
1653 int wxTreeListItem::GetCurrentImage() const {
1654     int image = NO_IMAGE;
1655     if (IsExpanded()) {
1656         if (IsSelected()) {
1657             image = GetImage (wxTreeItemIcon_SelectedExpanded);
1658         }else{
1659             image = GetImage (wxTreeItemIcon_Expanded);
1660         }
1661     }else{ // not expanded
1662         if (IsSelected()) {
1663             image = GetImage (wxTreeItemIcon_Selected);
1664         }else{
1665             image = GetImage (wxTreeItemIcon_Normal);
1666         }
1667     }
1668
1669     // maybe it doesn't have the specific image, try the default one instead
1670     if (image == NO_IMAGE) image = GetImage();
1671
1672     return image;
1673 }
1674
1675 // ---------------------------------------------------------------------------
1676 // wxTreeListMainWindow implementation
1677 // ---------------------------------------------------------------------------
1678
1679 IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow, wxScrolledWindow)
1680
1681 BEGIN_EVENT_TABLE(wxTreeListMainWindow, wxScrolledWindow)
1682     EVT_PAINT          (wxTreeListMainWindow::OnPaint)
1683     EVT_MOUSE_EVENTS   (wxTreeListMainWindow::OnMouse)
1684     EVT_CHAR           (wxTreeListMainWindow::OnChar)
1685     EVT_SET_FOCUS      (wxTreeListMainWindow::OnSetFocus)
1686     EVT_KILL_FOCUS     (wxTreeListMainWindow::OnKillFocus)
1687     EVT_IDLE           (wxTreeListMainWindow::OnIdle)
1688     EVT_SCROLLWIN      (wxTreeListMainWindow::OnScroll)
1689 END_EVENT_TABLE()
1690
1691
1692 // ---------------------------------------------------------------------------
1693 // construction/destruction
1694 // ---------------------------------------------------------------------------
1695
1696 void wxTreeListMainWindow::Init() {
1697
1698     m_rootItem = (wxTreeListItem*)NULL;
1699     m_curItem = (wxTreeListItem*)NULL;
1700     m_shiftItem = (wxTreeListItem*)NULL;
1701     m_editItem = (wxTreeListItem*)NULL;
1702     // LG 
1703     //    m_selectItem = (wxTreeListItem*)NULL;
1704
1705     m_curColumn = -1; // no current column
1706
1707     m_hasFocus = false;
1708     m_dirty = false;
1709
1710     m_lineHeight = LINEHEIGHT;
1711     m_indent = MININDENT; // min. indent
1712     m_linespacing = 4;
1713
1714 #if !wxCHECK_VERSION(2, 5, 0)
1715     m_hilightBrush = new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHT), wxSOLID);
1716     m_hilightUnfocusedBrush = new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNSHADOW), wxSOLID);
1717 #else
1718     m_hilightBrush = new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHT), wxSOLID);
1719     m_hilightUnfocusedBrush = new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNSHADOW), wxSOLID);
1720 #endif
1721
1722     m_imageListNormal = (wxImageList *) NULL;
1723     m_imageListButtons = (wxImageList *) NULL;
1724     m_imageListState = (wxImageList *) NULL;
1725     m_ownsImageListNormal = m_ownsImageListButtons =
1726     m_ownsImageListState = false;
1727
1728     m_imgWidth = 0, m_imgWidth2 = 0;
1729     m_imgHeight = 0, m_imgHeight2 = 0;
1730     m_btnWidth = 0, m_btnWidth2 = 0;
1731     m_btnHeight = 0, m_btnHeight2 = 0;
1732
1733     m_dragCount = 0;
1734     m_isDragging = false;
1735     m_dragTimer = new wxTimer (this, -1);
1736     m_dragItem = (wxTreeListItem*)NULL;
1737
1738     m_renameTimer = new wxTreeListRenameTimer (this);
1739     m_lastOnSame = false;
1740     m_left_down_selection = false;
1741
1742     m_findTimer = new wxTimer (this, -1);
1743
1744 #if defined( __WXMAC__ ) && defined(__WXMAC_CARBON__)
1745     m_normalFont.MacCreateThemeFont (kThemeViewsFont);
1746 #else
1747     m_normalFont = wxSystemSettings::GetFont (wxSYS_DEFAULT_GUI_FONT);
1748 #endif
1749     m_boldFont = wxFont( m_normalFont.GetPointSize(),
1750                          m_normalFont.GetFamily(),
1751                          m_normalFont.GetStyle(),
1752                          wxBOLD,
1753                          m_normalFont.GetUnderlined(),
1754                          m_normalFont.GetFaceName(),
1755                          m_normalFont.GetEncoding());
1756 }
1757
1758 bool wxTreeListMainWindow::Create (wxTreeListCtrl *parent,
1759                                    wxWindowID id,
1760                                    const wxPoint& pos,
1761                                    const wxSize& size,
1762                                    long style,
1763                                    const wxValidator &validator,
1764                                    const wxString& name) {
1765
1766 #ifdef __WXMAC__
1767     if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS;
1768     if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS;
1769     style &= ~wxTR_LINES_AT_ROOT;
1770     style |= wxTR_NO_LINES;
1771
1772     int major,minor;
1773     wxGetOsVersion( &major, &minor );
1774     if (major < 10) style |= wxTR_ROW_LINES;
1775 #endif
1776
1777     wxScrolledWindow::Create (parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, name);
1778
1779 #if wxUSE_VALIDATORS
1780     SetValidator(validator);
1781 #endif
1782
1783 #if !wxCHECK_VERSION(2, 5, 0)
1784     SetBackgroundColour (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_LISTBOX));
1785 #else
1786     SetBackgroundColour (wxSystemSettings::GetColour (wxSYS_COLOUR_LISTBOX));
1787 #endif
1788
1789 #ifdef __WXMSW__
1790     {
1791         int i, j;
1792         wxBitmap bmp(8, 8);
1793         wxMemoryDC bdc;
1794         bdc.SelectObject(bmp);
1795         bdc.SetPen(*wxGREY_PEN);
1796         bdc.DrawRectangle(-1, -1, 10, 10);
1797         for (i = 0; i < 8; i++) {
1798             for (j = 0; j < 8; j++) {
1799                 if (!((i + j) & 1)) {
1800                     bdc.DrawPoint(i, j);
1801                 }
1802             }
1803         }
1804
1805         m_dottedPen = wxPen(bmp, 1);
1806     }
1807 #else
1808 //?    m_dottedPen = wxPen( *wxGREY_PEN, 1, wxDOT );  // too slow under XFree86
1809     m_dottedPen = wxPen( _T("grey"), 0, 0 ); // Bitmap based pen is not supported by GTK!
1810 #endif
1811
1812     m_owner = parent;
1813     m_main_column = 0;
1814
1815     return true;
1816 }
1817
1818 wxTreeListMainWindow::~wxTreeListMainWindow() {
1819     delete m_hilightBrush;
1820     delete m_hilightUnfocusedBrush;
1821
1822     delete m_dragTimer;
1823     delete m_renameTimer;
1824     delete m_findTimer;
1825     if (m_ownsImageListNormal) delete m_imageListNormal;
1826     if (m_ownsImageListState) delete m_imageListState;
1827     if (m_ownsImageListButtons) delete m_imageListButtons;
1828
1829     DeleteRoot();
1830 }
1831
1832
1833 //-----------------------------------------------------------------------------
1834 // accessors
1835 //-----------------------------------------------------------------------------
1836
1837 size_t wxTreeListMainWindow::GetCount() const {
1838     return m_rootItem == NULL? 0: m_rootItem->GetChildrenCount();
1839 }
1840
1841 void wxTreeListMainWindow::SetIndent (unsigned int indent) {
1842     m_indent = wxMax (MININDENT, indent);
1843     m_dirty = true;
1844 }
1845
1846 void wxTreeListMainWindow::SetLineSpacing (unsigned int spacing) {
1847     m_linespacing = spacing;
1848     m_dirty = true;
1849     CalculateLineHeight();
1850 }
1851
1852 size_t wxTreeListMainWindow::GetChildrenCount (const wxTreeItemId& item,
1853                                                bool recursively) {
1854     wxCHECK_MSG (item.IsOk(), 0u, _T("invalid tree item"));
1855     return ((wxTreeListItem*)item.m_pItem)->GetChildrenCount (recursively);
1856 }
1857
1858 void wxTreeListMainWindow::SetWindowStyle (const long styles) {
1859     // right now, just sets the styles.  Eventually, we may
1860     // want to update the inherited styles, but right now
1861     // none of the parents has updatable styles
1862     m_windowStyle = styles;
1863     m_dirty = true;
1864 }
1865
1866 //-----------------------------------------------------------------------------
1867 // functions to work with tree items
1868 //-----------------------------------------------------------------------------
1869
1870 int wxTreeListMainWindow::GetItemImage (const wxTreeItemId& item, int column,
1871                                         wxTreeItemIcon which) const {
1872     wxCHECK_MSG (item.IsOk(), -1, _T("invalid tree item"));
1873     return ((wxTreeListItem*) item.m_pItem)->GetImage (column, which);
1874 }
1875
1876 wxTreeItemData *wxTreeListMainWindow::GetItemData (const wxTreeItemId& item) const {
1877     wxCHECK_MSG (item.IsOk(), NULL, _T("invalid tree item"));
1878     return ((wxTreeListItem*) item.m_pItem)->GetData();
1879 }
1880
1881 bool wxTreeListMainWindow::GetItemBold (const wxTreeItemId& item) const {
1882     wxCHECK_MSG(item.IsOk(), false, _T("invalid tree item"));
1883     return ((wxTreeListItem *)item.m_pItem)->IsBold();
1884 }
1885
1886 wxColour wxTreeListMainWindow::GetItemTextColour (const wxTreeItemId& item) const {
1887     wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
1888     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1889     return pItem->Attr().GetTextColour();
1890 }
1891
1892 wxColour wxTreeListMainWindow::GetItemBackgroundColour (const wxTreeItemId& item) const {
1893     wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
1894     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1895     return pItem->Attr().GetBackgroundColour();
1896 }
1897
1898 wxFont wxTreeListMainWindow::GetItemFont (const wxTreeItemId& item) const {
1899     wxCHECK_MSG (item.IsOk(), wxNullFont, _T("invalid tree item"));
1900     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1901     return pItem->Attr().GetFont();
1902 }
1903
1904 void wxTreeListMainWindow::SetItemImage (const wxTreeItemId& item, int column,
1905                                          int image, wxTreeItemIcon which) {
1906     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1907     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1908     pItem->SetImage (column, image, which);
1909     wxClientDC dc (this);
1910     CalculateSize (pItem, dc);
1911     RefreshLine (pItem);
1912 }
1913
1914 void wxTreeListMainWindow::SetItemData (const wxTreeItemId& item,
1915                                         wxTreeItemData *data) {
1916     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1917     ((wxTreeListItem*) item.m_pItem)->SetData(data);
1918 }
1919
1920 void wxTreeListMainWindow::SetItemHasChildren (const wxTreeItemId& item,
1921                                                bool has) {
1922     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1923     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1924     pItem->SetHasPlus (has);
1925     RefreshLine (pItem);
1926 }
1927
1928 void wxTreeListMainWindow::SetItemBold (const wxTreeItemId& item, bool bold) {
1929     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1930     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1931     if (pItem->IsBold() != bold) { // avoid redrawing if no real change
1932         pItem->SetBold (bold);
1933         RefreshLine (pItem);
1934     }
1935 }
1936
1937 void wxTreeListMainWindow::SetItemTextColour (const wxTreeItemId& item,
1938                                               const wxColour& colour) {
1939     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1940     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1941     pItem->Attr().SetTextColour (colour);
1942     RefreshLine (pItem);
1943 }
1944
1945 void wxTreeListMainWindow::SetItemBackgroundColour (const wxTreeItemId& item,
1946                                                     const wxColour& colour) {
1947     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1948     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1949     pItem->Attr().SetBackgroundColour (colour);
1950     RefreshLine (pItem);
1951 }
1952
1953 void wxTreeListMainWindow::SetItemFont (const wxTreeItemId& item,
1954                                         const wxFont& font) {
1955     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1956     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1957     pItem->Attr().SetFont (font);
1958     RefreshLine (pItem);
1959 }
1960
1961 bool wxTreeListMainWindow::SetFont (const wxFont &font) {
1962     wxScrolledWindow::SetFont (font);
1963     m_normalFont = font;
1964     m_boldFont = wxFont (m_normalFont.GetPointSize(),
1965                          m_normalFont.GetFamily(),
1966                          m_normalFont.GetStyle(),
1967                          wxBOLD,
1968                          m_normalFont.GetUnderlined(),
1969                          m_normalFont.GetFaceName());
1970     CalculateLineHeight();
1971     return true;
1972 }
1973
1974
1975 // ----------------------------------------------------------------------------
1976 // item status inquiries
1977 // ----------------------------------------------------------------------------
1978
1979 bool wxTreeListMainWindow::IsVisible (const wxTreeItemId& item, bool fullRow) const {
1980     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
1981
1982     // An item is only visible if it's not a descendant of a collapsed item
1983     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1984     wxTreeListItem* parent = pItem->GetItemParent();
1985     while (parent) {
1986         if (parent == m_rootItem && HasFlag(wxTR_HIDE_ROOT)) break;
1987         if (!parent->IsExpanded()) return false;
1988         parent = parent->GetItemParent();
1989     }
1990
1991     wxSize clientSize = GetClientSize();
1992     wxRect rect;
1993     if ((!GetBoundingRect (item, rect)) ||
1994         ((!fullRow && rect.GetWidth() == 0) || rect.GetHeight() == 0) ||
1995         (rect.GetBottom() < 0 || rect.GetTop() > clientSize.y) ||
1996         (!fullRow && (rect.GetRight() < 0 || rect.GetLeft() > clientSize.x))) return false;
1997
1998     return true;
1999 }
2000
2001 bool wxTreeListMainWindow::HasChildren (const wxTreeItemId& item) const {
2002     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2003
2004     // consider that the item does have children if it has the "+" button: it
2005     // might not have them (if it had never been expanded yet) but then it
2006     // could have them as well and it's better to err on this side rather than
2007     // disabling some operations which are restricted to the items with
2008     // children for an item which does have them
2009     return ((wxTreeListItem*) item.m_pItem)->HasPlus();
2010 }
2011
2012 bool wxTreeListMainWindow::IsExpanded (const wxTreeItemId& item) const {
2013     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2014     return ((wxTreeListItem*) item.m_pItem)->IsExpanded();
2015 }
2016
2017 bool wxTreeListMainWindow::IsSelected (const wxTreeItemId& item) const {
2018     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2019     return ((wxTreeListItem*) item.m_pItem)->IsSelected();
2020 }
2021
2022 bool wxTreeListMainWindow::IsBold (const wxTreeItemId& item) const {
2023     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2024     return ((wxTreeListItem*) item.m_pItem)->IsBold();
2025 }
2026
2027 // ----------------------------------------------------------------------------
2028 // navigation
2029 // ----------------------------------------------------------------------------
2030
2031 wxTreeItemId wxTreeListMainWindow::GetItemParent (const wxTreeItemId& item) const {
2032     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2033     return ((wxTreeListItem*) item.m_pItem)->GetItemParent();
2034 }
2035
2036 #if !wxCHECK_VERSION(2, 5, 0)
2037 wxTreeItemId wxTreeListMainWindow::GetFirstChild (const wxTreeItemId& item,
2038                                                   long& cookie) const {
2039 #else
2040 wxTreeItemId wxTreeListMainWindow::GetFirstChild (const wxTreeItemId& item,
2041                                                   wxTreeItemIdValue& cookie) const {
2042 #endif
2043     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2044     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2045     cookie = 0;
2046     return (!children.IsEmpty())? wxTreeItemId(children.Item(0)): wxTreeItemId();
2047 }
2048
2049 #if !wxCHECK_VERSION(2, 5, 0)
2050 wxTreeItemId wxTreeListMainWindow::GetNextChild (const wxTreeItemId& item,
2051                                                  long& cookie) const {
2052 #else
2053 wxTreeItemId wxTreeListMainWindow::GetNextChild (const wxTreeItemId& item,
2054                                                  wxTreeItemIdValue& cookie) const {
2055 #endif
2056     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2057     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2058     // it's ok to cast cookie to long, we never have indices which overflow "void*"
2059     long *pIndex = ((long*)&cookie);
2060     return ((*pIndex)+1 < (long)children.Count())? wxTreeItemId(children.Item(++(*pIndex))): wxTreeItemId();
2061 }
2062
2063 #if !wxCHECK_VERSION(2, 5, 0)
2064 wxTreeItemId wxTreeListMainWindow::GetPrevChild (const wxTreeItemId& item,
2065                                                  long& cookie) const {
2066 #else
2067 wxTreeItemId wxTreeListMainWindow::GetPrevChild (const wxTreeItemId& item,
2068                                                  wxTreeItemIdValue& cookie) const {
2069 #endif
2070     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2071     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2072     // it's ok to cast cookie to long, we never have indices which overflow "void*"
2073     long *pIndex = (long*)&cookie;
2074     return ((*pIndex)-1 >= 0)? wxTreeItemId(children.Item(--(*pIndex))): wxTreeItemId();
2075 }
2076
2077 #if !wxCHECK_VERSION(2, 5, 0)
2078 wxTreeItemId wxTreeListMainWindow::GetLastChild (const wxTreeItemId& item,
2079                                                  long& cookie) const {
2080 #else
2081 wxTreeItemId wxTreeListMainWindow::GetLastChild (const wxTreeItemId& item,
2082                                                  wxTreeItemIdValue& cookie) const {
2083 #endif
2084     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2085     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2086     // it's ok to cast cookie to long, we never have indices which overflow "void*"
2087     long *pIndex = ((long*)&cookie);
2088     (*pIndex) = children.Count();
2089     return (!children.IsEmpty())? wxTreeItemId(children.Last()): wxTreeItemId();
2090 }
2091
2092 wxTreeItemId wxTreeListMainWindow::GetNextSibling (const wxTreeItemId& item) const {
2093     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2094
2095     // get parent
2096     wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
2097     wxTreeListItem *parent = i->GetItemParent();
2098     if (!parent) return wxTreeItemId(); // root item doesn't have any siblings
2099
2100     // get index
2101     wxArrayTreeListItems& siblings = parent->GetChildren();
2102     size_t index = siblings.Index (i);
2103     wxASSERT (index != wxNOT_FOUND); // I'm not a child of my parent?
2104     return (index < siblings.Count()-1)? wxTreeItemId(siblings[index+1]): wxTreeItemId();
2105 }
2106
2107 wxTreeItemId wxTreeListMainWindow::GetPrevSibling (const wxTreeItemId& item) const {
2108     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2109
2110     // get parent
2111     wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
2112     wxTreeListItem *parent = i->GetItemParent();
2113     if (!parent) return wxTreeItemId(); // root item doesn't have any siblings
2114
2115     // get index
2116     wxArrayTreeListItems& siblings = parent->GetChildren();
2117     size_t index = siblings.Index(i);
2118     wxASSERT (index != wxNOT_FOUND); // I'm not a child of my parent?
2119     return (index >= 1)? wxTreeItemId(siblings[index-1]): wxTreeItemId();
2120 }
2121
2122 // Only for internal use right now, but should probably be public
2123 wxTreeItemId wxTreeListMainWindow::GetNext (const wxTreeItemId& item, bool fulltree) const {
2124     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2125
2126     // if there are any children, return first child
2127     if (fulltree || ((wxTreeListItem*)item.m_pItem)->IsExpanded()) {
2128         wxArrayTreeListItems& children = ((wxTreeListItem*)item.m_pItem)->GetChildren();
2129         if (children.GetCount() > 0) return children.Item (0);
2130     }
2131
2132     // get sibling of this item or of the ancestors instead
2133     wxTreeItemId next;
2134     wxTreeItemId parent = item;
2135     do {
2136         next = GetNextSibling (parent);
2137         parent = GetItemParent (parent);
2138     } while (!next.IsOk() && parent.IsOk());
2139     return next;
2140 }
2141
2142 // Only for internal use right now, but should probably be public
2143 wxTreeItemId wxTreeListMainWindow::GetPrev (const wxTreeItemId& item, bool fulltree) const {
2144     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2145
2146     // if there are any children, return last child
2147     if (fulltree || ((wxTreeListItem*)item.m_pItem)->IsExpanded()) {
2148         wxArrayTreeListItems& children = ((wxTreeListItem*)item.m_pItem)->GetChildren();
2149         if (children.GetCount() > 0) return children.Item (children.GetCount()-1);
2150     }
2151
2152     // get sibling of this item or of the ancestors instead
2153     wxTreeItemId next;
2154     wxTreeItemId parent = item;
2155     do {
2156         next = GetPrevSibling (parent);
2157         parent = GetItemParent (parent);
2158     } while (!next.IsOk() && parent.IsOk());
2159     return next;
2160 }
2161
2162 wxTreeItemId wxTreeListMainWindow::GetFirstExpandedItem() const {
2163     return GetNextExpanded (GetRootItem());
2164 }
2165
2166 wxTreeItemId wxTreeListMainWindow::GetNextExpanded (const wxTreeItemId& item) const {
2167     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2168     return GetNext (item, false);
2169 }
2170
2171 wxTreeItemId wxTreeListMainWindow::GetPrevExpanded (const wxTreeItemId& item) const {
2172     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2173     return GetPrev (item, false);
2174 }
2175
2176 wxTreeItemId wxTreeListMainWindow::GetFirstVisibleItem (bool fullRow) const {
2177     return GetNextVisible (GetRootItem(), fullRow);
2178 }
2179
2180 wxTreeItemId wxTreeListMainWindow::GetNextVisible (const wxTreeItemId& item, bool fullRow) const {
2181     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2182     wxTreeItemId id = GetNext (item, false);
2183     while (id.IsOk()) {
2184         if (IsVisible (id, fullRow)) return id;
2185         id = GetNext (id, false);
2186     }
2187     return wxTreeItemId();
2188 }
2189
2190 wxTreeItemId wxTreeListMainWindow::GetPrevVisible (const wxTreeItemId& item, bool fullRow) const {
2191     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2192     wxTreeItemId id = GetPrev (item, true);
2193     while (id.IsOk()) {
2194         if (IsVisible (id, fullRow)) return id;
2195         id = GetPrev(id, true);
2196     }
2197     return wxTreeItemId();
2198 }
2199
2200 // ----------------------------------------------------------------------------
2201 // operations
2202 // ----------------------------------------------------------------------------
2203
2204 wxTreeItemId wxTreeListMainWindow::DoInsertItem (const wxTreeItemId& parentId,
2205                                                  size_t previous,
2206                                                  const wxString& text,
2207                                                  int image, int selImage,
2208                                                  wxTreeItemData *data) {
2209     wxTreeListItem *parent = (wxTreeListItem*)parentId.m_pItem;
2210     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2211     m_dirty = true; // do this first so stuff below doesn't cause flicker
2212
2213     wxArrayString arr;
2214     arr.Alloc (GetColumnCount());
2215     for (int i = 0; i < (int)GetColumnCount(); ++i) arr.Add (wxEmptyString);
2216     arr[m_main_column] = text;
2217     wxTreeListItem *item = new wxTreeListItem (this, parent, arr, image, selImage, data);
2218     if (data != NULL) {
2219 #if !wxCHECK_VERSION(2, 5, 0)
2220         data->SetId ((long)item);
2221 #else
2222         data->SetId (item);
2223 #endif
2224     }
2225     parent->Insert (item, previous);
2226
2227     return item;
2228 }
2229
2230 wxTreeItemId wxTreeListMainWindow::AddRoot (const wxString& text,
2231                                             int image, int selImage,
2232                                             wxTreeItemData *data) {
2233     wxCHECK_MSG(!m_rootItem, wxTreeItemId(), _T("tree can have only one root"));
2234     wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), _T("Add column(s) before adding the root item"));
2235     m_dirty = true; // do this first so stuff below doesn't cause flicker
2236
2237     wxArrayString arr;
2238     arr.Alloc (GetColumnCount());
2239     for (int i = 0; i < (int)GetColumnCount(); ++i) arr.Add (wxEmptyString);
2240     arr[m_main_column] = text;
2241     m_rootItem = new wxTreeListItem (this, (wxTreeListItem *)NULL, arr, image, selImage, data);
2242     if (data != NULL) {
2243 #if !wxCHECK_VERSION(2, 5, 0)
2244         data->SetId((long)m_rootItem);
2245 #else
2246         data->SetId(m_rootItem);
2247 #endif
2248     }
2249     if (HasFlag(wxTR_HIDE_ROOT)) {
2250         // if we will hide the root, make sure children are visible
2251         m_rootItem->SetHasPlus();
2252         m_rootItem->Expand();
2253 #if !wxCHECK_VERSION(2, 5, 0)
2254         long cookie = 0;
2255 #else
2256         wxTreeItemIdValue cookie = 0;
2257 #endif
2258         m_curItem = (wxTreeListItem*)GetFirstChild (m_rootItem, cookie).m_pItem;
2259     }
2260     return m_rootItem;
2261 }
2262
2263 wxTreeItemId wxTreeListMainWindow::PrependItem (const wxTreeItemId& parent,
2264                                                 const wxString& text,
2265                                                 int image, int selImage,
2266                                                 wxTreeItemData *data) {
2267     return DoInsertItem (parent, 0u, text, image, selImage, data);
2268 }
2269
2270 wxTreeItemId wxTreeListMainWindow::InsertItem (const wxTreeItemId& parentId,
2271                                                const wxTreeItemId& idPrevious,
2272                                                const wxString& text,
2273                                                int image, int selImage,
2274                                                wxTreeItemData *data) {
2275     wxTreeListItem *parent = (wxTreeListItem*)parentId.m_pItem;
2276     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2277
2278     int index = parent->GetChildren().Index((wxTreeListItem*) idPrevious.m_pItem);
2279     wxASSERT_MSG( index != wxNOT_FOUND,
2280                   _T("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") );
2281
2282     return DoInsertItem (parentId, ++index, text, image, selImage, data);
2283 }
2284
2285 wxTreeItemId wxTreeListMainWindow::InsertItem (const wxTreeItemId& parentId,
2286                                                size_t before,
2287                                                const wxString& text,
2288                                                int image, int selImage,
2289                                                wxTreeItemData *data) {
2290     wxTreeListItem *parent = (wxTreeListItem*)parentId.m_pItem;
2291     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2292
2293     return DoInsertItem (parentId, before, text, image, selImage, data);
2294 }
2295
2296 wxTreeItemId wxTreeListMainWindow::AppendItem (const wxTreeItemId& parentId,
2297                                                const wxString& text,
2298                                                int image, int selImage,
2299                                                wxTreeItemData *data) {
2300     wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem;
2301     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2302
2303     return DoInsertItem (parent, parent->GetChildren().Count(), text, image, selImage, data);
2304 }
2305
2306 void wxTreeListMainWindow::SendDeleteEvent (wxTreeListItem *item) {
2307     // send event to user code
2308     wxTreeEvent event (wxEVT_COMMAND_TREE_DELETE_ITEM, m_owner->GetId());
2309 #if !wxCHECK_VERSION(2, 5, 0)
2310     event.SetItem ((long)item);
2311 #else
2312     event.SetItem (item);
2313 #endif
2314     event.SetEventObject (m_owner);
2315     m_owner->ProcessEvent (event);
2316 }
2317
2318 void wxTreeListMainWindow::Delete (const wxTreeItemId& itemId) {
2319     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2320     wxCHECK_RET (item != m_rootItem, _T("invalid item, root may not be deleted this way!"));
2321     m_dirty = true; // do this first so stuff below doesn't cause flicker
2322
2323     // don't stay with invalid m_shiftItem or we will crash in the next call to OnChar()
2324     bool changeKeyCurrent = false;
2325     wxTreeListItem *itemKey = m_shiftItem;
2326     while (itemKey) {
2327         if (itemKey == item) { // m_shiftItem is a descendant of the item being deleted
2328             changeKeyCurrent = true;
2329             break;
2330         }
2331         itemKey = itemKey->GetItemParent();
2332     }
2333
2334     wxTreeListItem *parent = item->GetItemParent();
2335     if (parent) {
2336         parent->GetChildren().Remove (item);  // remove by value
2337     }
2338     if (changeKeyCurrent)  m_shiftItem = parent;
2339
2340     SendDeleteEvent (item);
2341     // LG
2342     RemoveFromSelection(item);
2343     //    if (item->IsSelected()) Unselect(item);
2344     //if (m_selectItem == item) m_selectItem = (wxTreeListItem*)NULL;
2345     item->DeleteChildren (this);
2346     delete item;
2347 }
2348
2349 void wxTreeListMainWindow::DeleteChildren (const wxTreeItemId& itemId) {
2350     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2351     m_dirty = true; // do this first so stuff below doesn't cause flicker
2352
2353     item->DeleteChildren (this);
2354 }
2355
2356 void wxTreeListMainWindow::DeleteRoot() {
2357     if (m_rootItem) {
2358         m_dirty = true;
2359         SendDeleteEvent (m_rootItem);
2360         m_curItem = (wxTreeListItem*)NULL;
2361         // LG
2362         // m_selectItem= (wxTreeListItem*)NULL;
2363         UnselectAll();
2364         m_rootItem->DeleteChildren (this);
2365         delete m_rootItem;
2366         m_rootItem = NULL;
2367     }
2368 }
2369
2370 void wxTreeListMainWindow::Expand (const wxTreeItemId& itemId) {
2371     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2372     wxCHECK_RET (item, _T("invalid item in wxTreeListMainWindow::Expand") );
2373
2374     if (!item->HasPlus() || item->IsExpanded()) return;
2375
2376     // send event to user code
2377     wxTreeEvent event (wxEVT_COMMAND_TREE_ITEM_EXPANDING, m_owner->GetId());
2378 #if !wxCHECK_VERSION(2, 5, 0)
2379     event.SetItem ((long)item);
2380 #else
2381     event.SetItem (item);
2382 #endif
2383     event.SetEventObject (m_owner);
2384     if (m_owner->ProcessEvent (event) && !event.IsAllowed()) return; // expand canceled
2385
2386     item->Expand();
2387     m_dirty = true;
2388
2389     // send event to user code
2390     event.SetEventType (wxEVT_COMMAND_TREE_ITEM_EXPANDED);
2391     m_owner->ProcessEvent (event);
2392 }
2393
2394 void wxTreeListMainWindow::ExpandAll (const wxTreeItemId& itemId) {
2395     Expand (itemId);
2396     if (!IsExpanded (itemId)) return;
2397 #if !wxCHECK_VERSION(2, 5, 0)
2398     long cookie;
2399 #else
2400     wxTreeItemIdValue cookie;
2401 #endif
2402     wxTreeItemId child = GetFirstChild (itemId, cookie);
2403     while (child.IsOk()) {
2404         ExpandAll (child);
2405         child = GetNextChild (itemId, cookie);
2406     }
2407 }
2408
2409 void wxTreeListMainWindow::Collapse (const wxTreeItemId& itemId) {
2410     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2411     wxCHECK_RET (item, _T("invalid item in wxTreeListMainWindow::Collapse") );
2412
2413     if (!item->HasPlus() || !item->IsExpanded()) return;
2414
2415     // send event to user code
2416     wxTreeEvent event (wxEVT_COMMAND_TREE_ITEM_COLLAPSING, m_owner->GetId() );
2417 #if !wxCHECK_VERSION(2, 5, 0)
2418     event.SetItem ((long)item);
2419 #else
2420     event.SetItem (item);
2421 #endif
2422     event.SetEventObject (m_owner);
2423     if (m_owner->ProcessEvent (event) && !event.IsAllowed()) return; // collapse canceled
2424
2425     item->Collapse();
2426     m_dirty = true;
2427
2428     // send event to user code
2429     event.SetEventType (wxEVT_COMMAND_TREE_ITEM_COLLAPSED);
2430     ProcessEvent (event);
2431 }
2432
2433 void wxTreeListMainWindow::CollapseAndReset (const wxTreeItemId& item) {
2434     Collapse (item);
2435     DeleteChildren (item);
2436 }
2437
2438 void wxTreeListMainWindow::Toggle (const wxTreeItemId& itemId) {
2439     if (IsExpanded (itemId)) {
2440         Collapse (itemId);
2441     }else{
2442         Expand (itemId);
2443     }
2444 }
2445 /*
2446 void wxTreeListMainWindow::Unselect() {
2447     if (m_selectItem) {
2448         m_selectItem->SetHilight (false);
2449         RefreshLine (m_selectItem);
2450         m_selectItem = (wxTreeListItem*)NULL;
2451     }
2452 }
2453 */
2454 // LG 19/09/08 : Added 
2455 /*
2456 void wxTreeListMainWindow::Unselect(wxTreeListItem* item) 
2457 {
2458     if (item->IsSelected()) {
2459         item->SetSelected (false);
2460         RefreshLine (item);
2461         m_selected.Remove(item);
2462         // LG : TODO  : Remove from array
2463         //        if (item == m_selectItem) m_selectItem = (wxTreeListItem*)NULL;
2464     }
2465 }
2466 */
2467 /*
2468 void wxTreeListMainWindow::UnselectAllChildren (wxTreeListItem *item) {
2469     if (item->IsSelected()) {
2470         item->SetHilight (false);
2471         RefreshLine (item);
2472         if (item == m_selectItem) m_selectItem = (wxTreeListItem*)NULL;
2473     }
2474     if (item->HasChildren()) {
2475         wxArrayTreeListItems& children = item->GetChildren();
2476         size_t count = children.Count();
2477         for (size_t n = 0; n < count; ++n) {
2478             UnselectAllChildren (children[n]);
2479         }
2480     }
2481 }
2482 */
2483 void wxTreeListMainWindow::UnselectAll() {
2484   
2485   size_t count = m_selected.Count();
2486   for (size_t n = 0; n < count; ++n) 
2487     {
2488       m_selected[n]->SetSelected (false);
2489       RefreshLine (m_selected[n]);
2490     }
2491   m_selected.Empty();
2492   
2493   //UnselectAllChildren ((wxTreeListItem*)GetRootItem().m_pItem);
2494 }
2495
2496 // Recursive function !
2497 // To stop we must have crt_item<last_item
2498 // Algorithm :
2499 // Tag all next children, when no more children,
2500 // Move to parent (not to tag)
2501 // Keep going... if we found last_item, we stop.
2502 bool wxTreeListMainWindow::SelectNextChildren (wxTreeListItem *crt_item,
2503                                                wxTreeListItem *last_item) {
2504     wxTreeListItem *parent = crt_item->GetItemParent();
2505
2506     if (!parent) {// This is root item
2507         return SelectAllChildrenUntilLast (crt_item, last_item);
2508     }
2509
2510     wxArrayTreeListItems& children = parent->GetChildren();
2511     int index = children.Index(crt_item);
2512     wxASSERT (index != wxNOT_FOUND); // I'm not a child of my parent?
2513
2514     if ((parent->HasChildren() && parent->IsExpanded()) ||
2515         ((parent == (wxTreeListItem*)GetRootItem().m_pItem) && HasFlag(wxTR_HIDE_ROOT))) {
2516         size_t count = children.Count();
2517         for (size_t n = (index+1); n < count; ++n) {
2518             if (SelectAllChildrenUntilLast (children[n], last_item)) return true;
2519         }
2520     }
2521
2522     return SelectNextChildren (parent, last_item);
2523 }
2524
2525  bool wxTreeListMainWindow::SelectAllChildrenUntilLast (wxTreeListItem *crt_item,
2526                                                         wxTreeListItem *last_item) {
2527    if (!crt_item->IsSelected())
2528      {
2529        // LG : Send event to user to know is selection is accepted 
2530        // send event to the user code
2531        wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() );
2532 #if !wxCHECK_VERSION(2, 5, 0)
2533        event.SetItem ((long)crt_item);
2534 #else
2535        event.SetItem (crt_item);
2536 #endif
2537        event.SetEventObject (m_owner);
2538        if (m_owner->GetEventHandler()->ProcessEvent (event) && event.IsAllowed())
2539          {    
2540            AddToSelection(crt_item);
2541          }
2542      }
2543
2544     if (crt_item==last_item) return true;
2545
2546     if (crt_item->HasChildren() && crt_item->IsExpanded()) {
2547         wxArrayTreeListItems& children = crt_item->GetChildren();
2548         size_t count = children.Count();
2549         for (size_t n = 0; n < count; ++n) {
2550           if (SelectAllChildrenUntilLast (children[n], last_item)) return true;
2551         }
2552     }
2553
2554     return false;
2555 }
2556
2557  void wxTreeListMainWindow::RemoveFromSelection( wxTreeListItem *item )
2558  {
2559    if (!item->IsSelected()) return;
2560    item->SetSelected(false);
2561    m_selected.Remove(item);
2562    RefreshLine(item);
2563    
2564  }
2565  void wxTreeListMainWindow::AddToSelection( wxTreeListItem *item )
2566  {
2567    if (item->IsSelected()) return;
2568    item->SetSelected(true);
2569    m_selected.Add(item);
2570    RefreshLine(item);
2571  }
2572
2573 void wxTreeListMainWindow::SelectItem (const wxTreeItemId& itemId,
2574                                        const wxTreeItemId& lastId,
2575                                        bool unselect_others) {
2576     wxCHECK_RET (itemId.IsOk(), _T("invalid tree item") );
2577
2578     bool is_single = !HasFlag(wxTR_MULTIPLE);
2579     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2580
2581         
2582     // single selection requires unselect others
2583     if (is_single) unselect_others = true;
2584
2585     // unselect all if unselect other items
2586     bool unselected = false; // see that UnselectAll is done only once
2587     if (unselect_others) {
2588       /*
2589         if (is_single) {
2590             Unselect(); // to speed up thing
2591         }else{
2592       */
2593             UnselectAll();
2594             unselected = true;
2595             //        }
2596     }
2597
2598     // LG : Update current item
2599     wxTreeListItem *old_curItem = m_curItem;
2600     m_curItem = item;
2601     if (old_curItem) RefreshLine (old_curItem);
2602     
2603     // select item or item range
2604     if (lastId.IsOk() && (itemId != lastId)) 
2605       {
2606
2607
2608         if (!unselected) UnselectAll();
2609         wxTreeListItem *last = (wxTreeListItem*) lastId.m_pItem;
2610
2611         // LG : Update current item
2612         //      wxTreeListItem *old_curItem = m_curItem;
2613         //      m_curItem = last;
2614         //      if (old_curItem) RefreshLine (old_curItem);
2615
2616         // ensure that the position of the item it calculated in any case
2617         if (m_dirty) CalculatePositions();
2618
2619         // select item range according Y-position
2620         if (last->GetY() < item->GetY()) {
2621             if (!SelectAllChildrenUntilLast (last, item)) {
2622                 SelectNextChildren (last, item);
2623             }
2624         }else{
2625             if (!SelectAllChildrenUntilLast (item, last)) {
2626                 SelectNextChildren (item, last);
2627             }
2628         }
2629
2630     }
2631     else
2632       {
2633
2634         // send event to the user code
2635         wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() );
2636 #if !wxCHECK_VERSION(2, 5, 0)
2637         event.SetItem ((long)item);
2638         event.SetOldItem ((long)m_curItem);
2639 #else
2640         event.SetItem (item);
2641         event.SetOldItem (m_curItem);
2642 #endif
2643         event.SetEventObject (m_owner);
2644         
2645
2646
2647         if (m_owner->GetEventHandler()->ProcessEvent (event) && 
2648             event.IsAllowed())
2649           {
2650             // select item according its old selection
2651             if (item->IsSelected())
2652               RemoveFromSelection(item);
2653             else 
2654               AddToSelection(item);
2655           }
2656     }
2657
2658     // send event to user code
2659     wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGED, m_owner->GetId() );
2660     m_owner->GetEventHandler()->ProcessEvent (event);
2661 }
2662
2663 void wxTreeListMainWindow::SelectAll() {
2664     wxCHECK_RET (HasFlag(wxTR_MULTIPLE), _T("invalid tree style"));
2665
2666 #if !wxCHECK_VERSION(2, 5, 0)
2667     long cookie = 0;
2668 #else
2669     wxTreeItemIdValue cookie = 0;
2670 #endif
2671     wxTreeItemId root = GetRootItem();
2672     wxTreeListItem *first = (wxTreeListItem *)GetFirstChild (root, cookie).m_pItem;
2673     wxTreeListItem *last = (wxTreeListItem *)GetLastChild (root, cookie).m_pItem;
2674     if (!SelectAllChildrenUntilLast (first, last)) {
2675         SelectNextChildren (first, last);
2676     }
2677
2678     // send event to user code
2679     wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGED, m_owner->GetId() );
2680     m_owner->GetEventHandler()->ProcessEvent (event);
2681 }
2682
2683 void wxTreeListMainWindow::FillArray (wxTreeListItem *item,
2684                                       wxArrayTreeItemIds &array) const {
2685     if (item->IsSelected()) array.Add (wxTreeItemId(item));
2686
2687     if (item->HasChildren()) {
2688         wxArrayTreeListItems& children = item->GetChildren();
2689         size_t count = children.GetCount();
2690         for (size_t n = 0; n < count; ++n) FillArray (children[n], array);
2691     }
2692 }
2693
2694 size_t wxTreeListMainWindow::GetSelections (wxArrayTreeItemIds &array) const {
2695   /* 
2696      LG : NOT OK AS IS NOT IN TREE ORDER
2697     array.Empty();
2698     size_t count = m_selected.GetCount();
2699     for (size_t n = 0; n < count; ++n) array.Add(m_selected[n]);
2700   */
2701     wxTreeItemId idRoot = GetRootItem();
2702     if (idRoot.IsOk()) FillArray ((wxTreeListItem*) idRoot.m_pItem, array);
2703     return array.Count();
2704 }
2705
2706 void wxTreeListMainWindow::EnsureVisible (const wxTreeItemId& item) {
2707     if (!item.IsOk()) return; // do nothing if no item
2708
2709     // first expand all parent branches
2710     wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem;
2711     wxTreeListItem *parent = gitem->GetItemParent();
2712     while (parent) {
2713         Expand (parent);
2714         parent = parent->GetItemParent();
2715     }
2716
2717     ScrollTo (item);
2718     RefreshLine (gitem);
2719 }
2720
2721 void wxTreeListMainWindow::ScrollTo (const wxTreeItemId &item) {
2722     if (!item.IsOk()) return; // do nothing if no item
2723
2724     // ensure that the position of the item it calculated in any case
2725     if (m_dirty) CalculatePositions();
2726
2727     wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem;
2728
2729     // now scroll to the item
2730     int item_y = gitem->GetY();
2731
2732     int xUnit, yUnit;
2733     GetScrollPixelsPerUnit (&xUnit, &yUnit);
2734     int start_x = 0;
2735     int start_y = 0;
2736     GetViewStart (&start_x, &start_y);
2737     start_y *= yUnit;
2738
2739     int client_h = 0;
2740     int client_w = 0;
2741     GetClientSize (&client_w, &client_h);
2742
2743     int x = 0;
2744     int y = 0;
2745     m_rootItem->GetSize (x, y, this);
2746     x = m_owner->GetHeaderWindow()->GetWidth();
2747     y += yUnit + 2; // one more scrollbar unit + 2 pixels
2748     int x_pos = GetScrollPos( wxHORIZONTAL );
2749
2750     if (item_y < start_y+3) {
2751         // going down, item should appear at top
2752         SetScrollbars (xUnit, yUnit, xUnit ? x/xUnit : 0, yUnit ? y/yUnit : 0, x_pos, yUnit ? item_y/yUnit : 0);
2753     }else if (item_y+GetLineHeight(gitem) > start_y+client_h) {
2754         // going up, item should appear at bottom
2755         item_y += yUnit + 2;
2756         SetScrollbars (xUnit, yUnit, xUnit ? x/xUnit : 0, yUnit ? y/yUnit : 0, x_pos, yUnit ? (item_y+GetLineHeight(gitem)-client_h)/yUnit : 0 );
2757     }
2758 }
2759
2760 // FIXME: tree sorting functions are not reentrant and not MT-safe!
2761 static wxTreeListMainWindow *s_treeBeingSorted = NULL;
2762
2763 static int LINKAGEMODE tree_ctrl_compare_func(wxTreeListItem **item1,
2764                                   wxTreeListItem **item2)
2765 {
2766     wxCHECK_MSG (s_treeBeingSorted, 0, _T("bug in wxTreeListMainWindow::SortChildren()") );
2767
2768     return s_treeBeingSorted->OnCompareItems(*item1, *item2);
2769 }
2770
2771 int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId& item1,
2772                                const wxTreeItemId& item2)
2773 {
2774     return m_owner->OnCompareItems (item1, item2);
2775 }
2776
2777 void wxTreeListMainWindow::SortChildren (const wxTreeItemId& itemId) {
2778     wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
2779
2780     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2781
2782     wxCHECK_RET (!s_treeBeingSorted,
2783                  _T("wxTreeListMainWindow::SortChildren is not reentrant") );
2784
2785     wxArrayTreeListItems& children = item->GetChildren();
2786     if ( children.Count() > 1 ) {
2787         m_dirty = true;
2788         s_treeBeingSorted = this;
2789         children.Sort(tree_ctrl_compare_func);
2790         s_treeBeingSorted = NULL;
2791     }
2792 }
2793
2794 wxTreeItemId wxTreeListMainWindow::FindItem (const wxTreeItemId& item, const wxString& str, int mode) {
2795     wxString itemText;
2796     // determine start item
2797     wxTreeItemId next = item;
2798     if (next.IsOk()) {
2799         if (mode & wxTL_MODE_NAV_LEVEL) {
2800             next = GetNextSibling (next);
2801         }else if (mode & wxTL_MODE_NAV_VISIBLE) { //
2802             next = GetNextVisible (next, false);
2803         }else if (mode & wxTL_MODE_NAV_EXPANDED) {
2804             next = GetNextExpanded (next);
2805         }else{ // (mode & wxTL_MODE_NAV_FULLTREE) default
2806             next = GetNext (next, true);
2807         }
2808     }
2809
2810 #if !wxCHECK_VERSION(2, 5, 0)
2811     long cookie = 0;
2812 #else
2813     wxTreeItemIdValue cookie = 0;
2814 #endif
2815     if (!next.IsOk()) {
2816         next = (wxTreeListItem*)GetRootItem().m_pItem;
2817         if (HasFlag(wxTR_HIDE_ROOT)) {
2818             next = (wxTreeListItem*)GetFirstChild (GetRootItem().m_pItem, cookie).m_pItem;
2819         }
2820     }
2821     if (!next.IsOk()) return (wxTreeItemId*)NULL;
2822
2823     // start checking the next items
2824     while (next.IsOk() && (next != item)) {
2825         if (mode & wxTL_MODE_FIND_PARTIAL) {
2826             itemText = GetItemText (next).Mid (0, str.Length());
2827         }else{
2828             itemText = GetItemText (next);
2829         }
2830         if (mode & wxTL_MODE_FIND_NOCASE) {
2831             if (itemText.CmpNoCase (str) == 0) return next;
2832         }else{
2833             if (itemText.Cmp (str) == 0) return next;
2834         }
2835         if (mode & wxTL_MODE_NAV_LEVEL) {
2836             next = GetNextSibling (next);
2837         }else if (mode & wxTL_MODE_NAV_VISIBLE) { //
2838             next = GetNextVisible (next, false);
2839         }else if (mode & wxTL_MODE_NAV_EXPANDED) {
2840             next = GetNextExpanded (next);
2841         }else{ // (mode & wxTL_MODE_NAV_FULLTREE) default
2842             next = GetNext (next, true);
2843         }
2844         if (!next.IsOk() && item.IsOk()) {
2845             next = (wxTreeListItem*)GetRootItem().m_pItem;
2846             if (HasFlag(wxTR_HIDE_ROOT)) {
2847                 next = (wxTreeListItem*)GetNextChild (GetRootItem().m_pItem, cookie).m_pItem;
2848             }
2849         }
2850     }
2851     return (wxTreeItemId*)NULL;
2852 }
2853
2854 void wxTreeListMainWindow::SetDragItem (const wxTreeItemId& item) {
2855     wxTreeListItem *prevItem = m_dragItem;
2856     m_dragItem = (wxTreeListItem*) item.m_pItem;
2857     if (prevItem) RefreshLine (prevItem);
2858     if (m_dragItem) RefreshLine (m_dragItem);
2859 }
2860
2861 void wxTreeListMainWindow::CalculateLineHeight() {
2862     wxClientDC dc (this);
2863     dc.SetFont (m_normalFont);
2864     m_lineHeight = (int)(dc.GetCharHeight() + m_linespacing);
2865
2866     if (m_imageListNormal) {
2867         // Calculate a m_lineHeight value from the normal Image sizes.
2868         // May be toggle off. Then wxTreeListMainWindow will spread when
2869         // necessary (which might look ugly).
2870         int n = m_imageListNormal->GetImageCount();
2871         for (int i = 0; i < n ; i++) {
2872             int width = 0, height = 0;
2873             m_imageListNormal->GetSize(i, width, height);
2874             if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
2875         }
2876     }
2877
2878     if (m_imageListButtons) {
2879         // Calculate a m_lineHeight value from the Button image sizes.
2880         // May be toggle off. Then wxTreeListMainWindow will spread when
2881         // necessary (which might look ugly).
2882         int n = m_imageListButtons->GetImageCount();
2883         for (int i = 0; i < n ; i++) {
2884             int width = 0, height = 0;
2885             m_imageListButtons->GetSize(i, width, height);
2886             if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
2887         }
2888     }
2889
2890     if (m_lineHeight < 30) { // add 10% space if greater than 30 pixels
2891         m_lineHeight += 2; // minimal 2 pixel space
2892     }else{
2893         m_lineHeight += m_lineHeight / 10; // otherwise 10% space
2894     }
2895 }
2896
2897 void wxTreeListMainWindow::SetImageList (wxImageList *imageList) {
2898     if (m_ownsImageListNormal) delete m_imageListNormal;
2899     m_imageListNormal = imageList;
2900     m_ownsImageListNormal = false;
2901     m_dirty = true;
2902     CalculateLineHeight();
2903 }
2904
2905 void wxTreeListMainWindow::SetStateImageList (wxImageList *imageList) {
2906     if (m_ownsImageListState) delete m_imageListState;
2907     m_imageListState = imageList;
2908     m_ownsImageListState = false;
2909 }
2910
2911 void wxTreeListMainWindow::SetButtonsImageList (wxImageList *imageList) {
2912     if (m_ownsImageListButtons) delete m_imageListButtons;
2913     m_imageListButtons = imageList;
2914     m_ownsImageListButtons = false;
2915     m_dirty = true;
2916     CalculateLineHeight();
2917 }
2918
2919 void wxTreeListMainWindow::AssignImageList (wxImageList *imageList) {
2920     SetImageList(imageList);
2921     m_ownsImageListNormal = true;
2922 }
2923
2924 void wxTreeListMainWindow::AssignStateImageList (wxImageList *imageList) {
2925     SetStateImageList(imageList);
2926     m_ownsImageListState = true;
2927 }
2928
2929 void wxTreeListMainWindow::AssignButtonsImageList (wxImageList *imageList) {
2930     SetButtonsImageList(imageList);
2931     m_ownsImageListButtons = true;
2932 }
2933
2934 // ----------------------------------------------------------------------------
2935 // helpers
2936 // ----------------------------------------------------------------------------
2937
2938 void wxTreeListMainWindow::AdjustMyScrollbars() {
2939     if (m_rootItem) {
2940         int xUnit, yUnit;
2941         GetScrollPixelsPerUnit (&xUnit, &yUnit);
2942         if (xUnit == 0) xUnit = GetCharWidth();
2943         if (yUnit == 0) yUnit = m_lineHeight;
2944         int x = 0, y = 0;
2945         m_rootItem->GetSize (x, y, this);
2946         y += yUnit + 2; // one more scrollbar unit + 2 pixels
2947         int x_pos = GetScrollPos (wxHORIZONTAL);
2948         int y_pos = GetScrollPos (wxVERTICAL);
2949         x = m_owner->GetHeaderWindow()->GetWidth() + 2;
2950         if (x < GetClientSize().GetWidth()) x_pos = 0;
2951         SetScrollbars (xUnit, yUnit, x/xUnit, y/yUnit, x_pos, y_pos);
2952     }else{
2953         SetScrollbars (0, 0, 0, 0);
2954     }
2955 }
2956
2957 int wxTreeListMainWindow::GetLineHeight (wxTreeListItem *item) const {
2958     if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT) {
2959         return item->GetHeight();
2960     }else{
2961         return m_lineHeight;
2962     }
2963 }
2964
2965 void wxTreeListMainWindow::PaintItem (wxTreeListItem *item, wxDC& dc) {
2966
2967     wxTreeItemAttr *attr = item->GetAttributes();
2968
2969     dc.SetFont (GetItemFont (item));
2970
2971     wxColour colText;
2972     if (attr && attr->HasTextColour()) {
2973         colText = attr->GetTextColour();
2974     }else{
2975         colText = GetForegroundColour();
2976     }
2977 #if !wxCHECK_VERSION(2, 5, 0)
2978     wxColour colTextHilight = wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHTTEXT);
2979 #else
2980     wxColour colTextHilight = wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHTTEXT);
2981 #endif
2982
2983     int total_w = m_owner->GetHeaderWindow()->GetWidth();
2984     int total_h = GetLineHeight(item);
2985     int off_h = HasFlag(wxTR_ROW_LINES) ? 1 : 0;
2986     //    std::cout << "off_h="<<off_h<<std::endl;
2987
2988     wxDCClipper clipper (dc, 0, item->GetY(), total_w, total_h); // only within line
2989
2990     int text_w = 0, text_h = 0;
2991     dc.GetTextExtent( item->GetText(GetMainColumn()), &text_w, &text_h );
2992
2993     // determine background and show it
2994     wxColour colBg;
2995     if (attr && attr->HasBackgroundColour()) {
2996         colBg = attr->GetBackgroundColour();
2997     }else{
2998         colBg = m_backgroundColour;
2999     }
3000     dc.SetBrush (wxBrush (colBg, wxSOLID));
3001     dc.SetPen (*wxTRANSPARENT_PEN);
3002     if (HasFlag (wxTR_FULL_ROW_HIGHLIGHT)) {
3003         if (item == m_dragItem) {
3004             dc.SetBrush (*m_hilightBrush);
3005 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3006             dc.SetPen ((item == m_dragItem)? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3007 #endif // !__WXMAC__
3008             dc.SetTextForeground (colTextHilight);
3009         }else if (item->IsSelected()) {
3010             if (!m_isDragging && m_hasFocus) {
3011                 dc.SetBrush (*m_hilightBrush);
3012 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3013                 // LG : dc.SetPen (*wxBLACK_PEN);
3014                 dc.SetPen (*wxTRANSPARENT_PEN);
3015 #endif // !__WXMAC__
3016             }else{
3017                 dc.SetBrush (*m_hilightUnfocusedBrush);
3018 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3019                 dc.SetPen (*wxTRANSPARENT_PEN);
3020 #endif // !__WXMAC__
3021             }
3022             dc.SetTextForeground (colTextHilight);
3023         }
3024         // LG
3025         else if (item == m_curItem) {
3026           dc.SetPen (m_hasFocus? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3027         }
3028         else{
3029             dc.SetTextForeground (colText);
3030         }
3031         // LG 
3032         dc.DrawRectangle (0, item->GetY() + off_h, total_w, total_h - off_h);
3033     }else{
3034         dc.SetTextForeground (colText);
3035     }
3036
3037     int text_extraH = (total_h > text_h) ? (total_h - text_h)/2 : 0;
3038     int img_extraH = (total_h > m_imgHeight)? (total_h-m_imgHeight)/2: 0;
3039     int x_colstart = 0;
3040     for (int i = 0; i < GetColumnCount(); ++i ) {
3041         if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
3042
3043         int col_w = m_owner->GetHeaderWindow()->GetColumnWidth(i);
3044         wxDCClipper clipper (dc, x_colstart, item->GetY(), col_w, total_h); // only within column
3045
3046         int x = 0;
3047         int image = NO_IMAGE;
3048         int image_w = 0;
3049         if(i == GetMainColumn()) {
3050             x = item->GetX() + MARGIN;
3051             if (HasButtons()) {
3052                 x += (m_btnWidth-m_btnWidth2) + LINEATROOT;
3053             }else{
3054                 x -= m_indent/2;
3055             }
3056             if (m_imageListNormal) image = item->GetCurrentImage();
3057         }else{
3058             x = x_colstart + MARGIN;
3059             image = item->GetImage(i);
3060         }
3061         if (image != NO_IMAGE) image_w = m_imgWidth + MARGIN;
3062
3063         // honor text alignment
3064         wxString text = item->GetText(i);
3065         int w = 0;
3066         switch ( m_owner->GetHeaderWindow()->GetColumn(i).GetAlignment() ) {
3067         case wxALIGN_LEFT:
3068             // nothing to do, already left aligned
3069             break;
3070         case wxALIGN_RIGHT:
3071             dc.GetTextExtent (text, &text_w, NULL);
3072             w = col_w - (image_w + text_w + MARGIN);
3073             x += (w > 0)? w: 0;
3074             break;
3075         case wxALIGN_CENTER:
3076             dc.GetTextExtent(text, &text_w, NULL);
3077             w = (col_w - (image_w + text_w + MARGIN))/2;
3078             x += (w > 0)? w: 0;
3079             break;
3080         }
3081         int text_x = x + image_w;
3082         if (i == GetMainColumn()) item->SetTextX (text_x);
3083
3084         if (!HasFlag (wxTR_FULL_ROW_HIGHLIGHT)) {
3085             if (i == GetMainColumn()) {
3086                 if (item == m_dragItem) {
3087                     dc.SetBrush (*m_hilightBrush);
3088 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3089                     dc.SetPen ((item == m_dragItem)? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3090 #endif // !__WXMAC__
3091                     dc.SetTextForeground (colTextHilight);
3092                 }else if (item->IsSelected()) {
3093                     if (!m_isDragging && m_hasFocus) {
3094                         dc.SetBrush (*m_hilightBrush);
3095 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3096                         dc.SetPen (*wxBLACK_PEN);
3097 #endif // !__WXMAC__
3098                     }else{
3099                         dc.SetBrush (*m_hilightUnfocusedBrush);
3100 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3101                       dc.SetPen (*wxTRANSPARENT_PEN);
3102 #endif // !__WXMAC__
3103                     }
3104                     dc.SetTextForeground (colTextHilight);
3105                 }
3106                 // LG 
3107                 else if (item == m_curItem) {
3108                   dc.SetPen (m_hasFocus? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3109                 }
3110                 else{
3111                   dc.SetTextForeground (colText);
3112                 }
3113                 dc.DrawRectangle (text_x, item->GetY() + off_h, text_w, total_h - off_h);
3114             }else{
3115                 dc.SetTextForeground (colText);
3116             }
3117         }
3118
3119         dc.SetBackgroundMode (wxTRANSPARENT);
3120
3121         if (image != NO_IMAGE) {
3122             int y = item->GetY() + img_extraH;
3123             m_imageListNormal->Draw (image, dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
3124         }
3125         int text_y = item->GetY() + text_extraH;
3126         dc.DrawText (text, (wxCoord)text_x, (wxCoord)text_y);
3127
3128         x_colstart += col_w;
3129     }
3130
3131     // restore normal font
3132     dc.SetFont( m_normalFont );
3133 }
3134
3135 // Now y stands for the top of the item, whereas it used to stand for middle !
3136 void wxTreeListMainWindow::PaintLevel (wxTreeListItem *item, wxDC &dc,
3137                                        int level, int &y, int x_maincol) {
3138
3139     // Handle hide root (only level 0)
3140   // LG : test
3141   //  int nth = 2;
3142   //if (HasFlag(wxTR_HIDE_ROOT) && (level < nth)) {  
3143   if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) {
3144   
3145         wxArrayTreeListItems& children = item->GetChildren();
3146         for (size_t n = 0; n < children.Count(); n++) {
3147             PaintLevel (children[n], dc, 1, y, x_maincol);
3148         }
3149         // end after expanding root
3150         return;
3151     }
3152
3153     // calculate position of vertical lines
3154     int x = x_maincol + MARGIN; // start of column
3155     if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
3156     if (HasButtons()) {
3157         x += (m_btnWidth-m_btnWidth2); // half button space
3158     }else{
3159         x += (m_indent-m_indent/2);
3160     }
3161     if (HasFlag(wxTR_HIDE_ROOT)) {
3162       // LG 
3163       //        x += m_indent * (level-nth); // indent but not level 1
3164       x += m_indent * (level-1); // indent but not level 1
3165
3166     }else{
3167         x += m_indent * level; // indent according to level
3168     }
3169
3170     // set position of vertical line
3171     item->SetX (x);
3172     item->SetY (y);
3173
3174     int h = GetLineHeight (item);
3175     int y_top = y;
3176     int y_mid = y_top + (h/2);
3177     y += h;
3178
3179     int exposed_x = dc.LogicalToDeviceX(0);
3180     int exposed_y = dc.LogicalToDeviceY(y_top);
3181
3182     if (IsExposed(exposed_x, exposed_y, 10000, h)) { // 10000 = very much
3183
3184         if (HasFlag(wxTR_ROW_LINES)) { // horizontal lines between rows
3185             //dc.DestroyClippingRegion();
3186             int total_width = m_owner->GetHeaderWindow()->GetWidth();
3187             // if the background colour is white, choose a
3188             // contrasting color for the lines
3189             dc.SetPen (*((GetBackgroundColour() == *wxWHITE)?
3190                         wxMEDIUM_GREY_PEN : wxWHITE_PEN));
3191             dc.DrawLine(0, y_top, total_width, y_top);
3192             dc.DrawLine(0, y_top+h, total_width, y_top+h);
3193         }
3194
3195         // draw item
3196         PaintItem (item, dc);
3197
3198         // restore DC objects
3199         dc.SetBrush(*wxWHITE_BRUSH);
3200         dc.SetPen(m_dottedPen);
3201
3202         // clip to the column width
3203         int clip_width = m_owner->GetHeaderWindow()->
3204                             GetColumn(m_main_column).GetWidth();
3205         wxDCClipper clipper(dc, x_maincol, y_top, clip_width, 10000);
3206
3207         if (!HasFlag(wxTR_NO_LINES)) { // connection lines
3208
3209             // draw the horizontal line here
3210             dc.SetPen(m_dottedPen);
3211             int x2 = x - m_indent;
3212             if (x2 < (x_maincol + MARGIN)) x2 = x_maincol + MARGIN;
3213             int x3 = x + (m_btnWidth-m_btnWidth2);
3214             if (HasButtons()) {
3215                 if (item->HasPlus()) {
3216                     dc.DrawLine (x2, y_mid, x - m_btnWidth2, y_mid);
3217                     dc.DrawLine (x3, y_mid, x3 + LINEATROOT, y_mid);
3218                 }else{
3219                     dc.DrawLine (x2, y_mid, x3 + LINEATROOT, y_mid);
3220                 }
3221             }else{
3222                 dc.DrawLine (x2, y_mid, x - m_indent/2, y_mid);
3223             }
3224         }
3225
3226         if (item->HasPlus() && HasButtons()) { // should the item show a button?
3227
3228             if (m_imageListButtons) {
3229
3230                 // draw the image button here
3231                 int image = wxTreeItemIcon_Normal;
3232                 if (item->IsExpanded()) image = wxTreeItemIcon_Expanded;
3233                 if (item->IsSelected()) image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal;
3234                 int xx = x - m_btnWidth2 + MARGIN;
3235                 int yy = y_mid - m_btnHeight2;
3236                 dc.SetClippingRegion(xx, yy, m_btnWidth, m_btnHeight);
3237                 m_imageListButtons->Draw (image, dc, xx, yy, wxIMAGELIST_DRAW_TRANSPARENT);
3238                 dc.DestroyClippingRegion();
3239
3240             }else if (HasFlag (wxTR_TWIST_BUTTONS)) {
3241
3242                 // draw the twisty button here
3243                 dc.SetPen(*wxBLACK_PEN);
3244                 dc.SetBrush(*m_hilightBrush);
3245                 wxPoint button[3];
3246                 if (item->IsExpanded()) {
3247                     button[0].x = x - (m_btnWidth2+1);
3248                     button[0].y = y_mid - (m_btnHeight/3);
3249                     button[1].x = x + (m_btnWidth2+1);
3250                     button[1].y = button[0].y;
3251                     button[2].x = x;
3252                     button[2].y = button[0].y + (m_btnHeight2+1);
3253                 }else{
3254                     button[0].x = x - (m_btnWidth/3);
3255                     button[0].y = y_mid - (m_btnHeight2+1);
3256                     button[1].x = button[0].x;
3257                     button[1].y = y_mid + (m_btnHeight2+1);
3258                     button[2].x = button[0].x + (m_btnWidth2+1);
3259                     button[2].y = y_mid;
3260                 }
3261                 dc.DrawPolygon(3, button);
3262
3263             }else{ // if (HasFlag(wxTR_HAS_BUTTONS))
3264
3265                 // draw the plus sign here
3266                 dc.SetPen(*wxGREY_PEN);
3267                 dc.SetBrush(*wxWHITE_BRUSH);
3268                 dc.DrawRectangle (x-m_btnWidth2, y_mid-m_btnHeight2, m_btnWidth, m_btnHeight);
3269                 dc.SetPen(*wxBLACK_PEN);
3270                 dc.DrawLine (x-(m_btnWidth2-2), y_mid, x+(m_btnWidth2-1), y_mid);
3271                 if (!item->IsExpanded()) { // change "-" to "+"
3272                     dc.DrawLine (x, y_mid-(m_btnHeight2-2), x, y_mid+(m_btnHeight2-1));
3273                 }
3274
3275             }
3276
3277         }
3278
3279     }
3280
3281     // restore DC objects
3282     dc.SetBrush(*wxWHITE_BRUSH);
3283     dc.SetPen(m_dottedPen);
3284     dc.SetTextForeground(*wxBLACK);
3285
3286     if (item->IsExpanded())
3287     {
3288         wxArrayTreeListItems& children = item->GetChildren();
3289
3290         // clip to the column width
3291         int clip_width = m_owner->GetHeaderWindow()->
3292                             GetColumn(m_main_column).GetWidth();
3293
3294         // process lower levels
3295         int oldY;
3296         if (m_imgWidth > 0) {
3297             oldY = y_mid + m_imgHeight2;
3298         }else{
3299             oldY = y_mid + h/2;
3300         }
3301         int y2;
3302         for (size_t n = 0; n < children.Count(); ++n) {
3303
3304             y2 = y + h/2;
3305             PaintLevel (children[n], dc, level+1, y, x_maincol);
3306
3307             // draw vertical line
3308             wxDCClipper clipper(dc, x_maincol, y_top, clip_width, 10000);
3309             if (!HasFlag (wxTR_NO_LINES)) {
3310                 x = item->GetX();
3311                 dc.DrawLine (x, oldY, x, y2);
3312                 oldY = y2;
3313             }
3314         }
3315     }
3316 }
3317
3318
3319 // ----------------------------------------------------------------------------
3320 // wxWindows callbacks
3321 // ----------------------------------------------------------------------------
3322
3323 void wxTreeListMainWindow::OnPaint (wxPaintEvent &WXUNUSED(event)) {
3324
3325     wxPaintDC dc (this);
3326     PrepareDC (dc);
3327
3328     if (!m_rootItem || (GetColumnCount() <= 0)) return;
3329
3330     // calculate button size
3331     if (m_imageListButtons) {
3332         m_imageListButtons->GetSize (0, m_btnWidth, m_btnHeight);
3333     }else if (HasButtons()) {
3334         m_btnWidth = BTNWIDTH;
3335         m_btnHeight = BTNHEIGHT;
3336     }
3337     m_btnWidth2 = m_btnWidth/2;
3338     m_btnHeight2 = m_btnHeight/2;
3339
3340     // calculate image size
3341     if (m_imageListNormal) {
3342         m_imageListNormal->GetSize (0, m_imgWidth, m_imgHeight);
3343     }
3344     m_imgWidth2 = m_imgWidth/2;
3345     m_imgHeight2 = m_imgHeight/2;
3346
3347     // calculate indent size
3348     if (m_imageListButtons) {
3349         m_indent = wxMax (MININDENT, m_btnWidth + MARGIN);
3350     }else if (HasButtons()) {
3351         m_indent = wxMax (MININDENT, m_btnWidth + LINEATROOT);
3352     }
3353
3354     // set default values
3355     dc.SetFont( m_normalFont );
3356     dc.SetPen( m_dottedPen );
3357
3358     // calculate column start and paint
3359     int x_maincol = 0;
3360     int i = 0;
3361     for (i = 0; i < (int)GetMainColumn(); ++i) {
3362         if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
3363         x_maincol += m_owner->GetHeaderWindow()->GetColumnWidth (i);
3364     }
3365     int y = 0;
3366     PaintLevel (m_rootItem, dc, 0, y, x_maincol);
3367 }
3368
3369 void wxTreeListMainWindow::OnSetFocus (wxFocusEvent &event) {
3370
3371     m_hasFocus = true;
3372     RefreshSelected();
3373     if (m_curItem) RefreshLine (m_curItem);
3374     event.Skip();
3375 }
3376
3377 void wxTreeListMainWindow::OnKillFocus( wxFocusEvent &event )
3378 {
3379     m_hasFocus = false;
3380     RefreshSelected();
3381     if (m_curItem) RefreshLine (m_curItem);
3382     event.Skip();
3383 }
3384
3385 void wxTreeListMainWindow::OnChar (wxKeyEvent &event) {
3386     // send event to user code
3387     wxTreeEvent nevent (wxEVT_COMMAND_TREE_KEY_DOWN, m_owner->GetId());
3388     nevent.SetKeyEvent (event);
3389     nevent.SetEventObject (m_owner);
3390     if (m_owner->GetEventHandler()->ProcessEvent (nevent)) return; // handled in user code
3391
3392     // determine first current if none
3393     bool curItemSet = false;
3394     if (!m_curItem) {
3395         m_curItem = (wxTreeListItem*)GetRootItem().m_pItem;
3396         if (HasFlag(wxTR_HIDE_ROOT)) {
3397 #if !wxCHECK_VERSION(2, 5, 0)
3398             long cookie = 0;
3399 #else
3400             wxTreeItemIdValue cookie = 0;
3401 #endif
3402             m_curItem = (wxTreeListItem*)GetFirstChild (m_curItem, cookie).m_pItem;
3403         }
3404         curItemSet = true;
3405     }
3406     if (!m_curItem) return; // do nothing if empty tree
3407
3408     // remember item at shift down
3409     if (HasFlag(wxTR_MULTIPLE) && event.ShiftDown()) {
3410         if (!m_shiftItem) m_shiftItem = m_curItem;
3411     }else{
3412         m_shiftItem = (wxTreeListItem*)NULL;
3413     }
3414
3415     // process all cases
3416     wxTreeItemId newItem = (wxTreeItemId*)NULL;
3417     switch (event.GetKeyCode()) {
3418
3419         // '+': Expand subtree
3420         case '+':
3421         case WXK_ADD: {
3422             if (m_curItem->HasPlus() && !IsExpanded (m_curItem)) Expand (m_curItem);
3423         }break;
3424
3425         // '-': collapse subtree
3426         case '-':
3427         case WXK_SUBTRACT: {
3428             if (m_curItem->HasPlus() && IsExpanded (m_curItem)) Collapse (m_curItem);
3429         }break;
3430
3431         // '*': expand/collapse all subtrees // TODO: Mak it more useful
3432         case '*':
3433         case WXK_MULTIPLY: {
3434             if (m_curItem->HasPlus() && !IsExpanded (m_curItem)) {
3435                 ExpandAll (m_curItem);
3436             }else if (m_curItem->HasPlus()) {
3437                 Collapse (m_curItem); // TODO: CollapseAll
3438             }
3439         }break;
3440
3441         // ' ': toggle current item
3442         case ' ': {
3443             SelectItem (m_curItem, (wxTreeListItem*)NULL, false);
3444         }break;
3445
3446         // <RETURN>: activate current item
3447         case WXK_RETURN: {
3448             wxTreeEvent aevent (wxEVT_COMMAND_TREE_ITEM_ACTIVATED, m_owner->GetId());
3449 #if !wxCHECK_VERSION(2, 5, 0)
3450             aevent.SetItem ((long)m_curItem);
3451 #else
3452             aevent.SetItem (m_curItem);
3453 #endif
3454             aevent.SetEventObject (m_owner);
3455             m_owner->GetEventHandler()->ProcessEvent (aevent);
3456         }break;
3457
3458         // <BKSP>: go to the parent without collapsing
3459         case WXK_BACK: {
3460             newItem = GetItemParent (m_curItem);
3461             if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) {
3462                 newItem = GetPrevSibling (m_curItem); // get sibling instead of root
3463             }
3464         }break;
3465
3466         // <UP>: go to the previous sibling or to the last of its children, to the parent
3467         case WXK_UP: {
3468             newItem = GetPrevSibling (m_curItem);
3469             if (newItem) {
3470 #if !wxCHECK_VERSION(2, 5, 0)
3471                 long cookie = 0;
3472 #else
3473                 wxTreeItemIdValue cookie = 0;
3474 #endif
3475                 while (IsExpanded (newItem) && HasChildren (newItem)) {
3476                     newItem = GetLastChild (newItem, cookie);
3477                 }
3478             }else {
3479                 newItem = GetItemParent (m_curItem);
3480                 if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) {
3481                     newItem = (wxTreeItemId*)NULL; // don't go to root if it is hidden
3482                 }
3483             }
3484         }break;
3485
3486         // <LEFT>: if expanded collapse subtree, else go to the parent
3487         case WXK_LEFT: {
3488             if (IsExpanded (m_curItem)) {
3489                 Collapse (m_curItem);
3490             }else{
3491                 newItem = GetItemParent (m_curItem);
3492                 if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) {
3493                     newItem = GetPrevSibling (m_curItem); // go to sibling if it is hidden
3494                 }
3495             }
3496         }break;
3497
3498         // <RIGHT>: if possible expand subtree, else go go to the first child
3499         case WXK_RIGHT: {
3500             if (m_curItem->HasPlus() && !IsExpanded (m_curItem)) {
3501                 Expand (m_curItem);
3502             }else{
3503                 if (IsExpanded (m_curItem) && HasChildren (m_curItem)) {
3504 #if !wxCHECK_VERSION(2, 5, 0)
3505                     long cookie = 0;
3506 #else
3507                     wxTreeItemIdValue cookie = 0;
3508 #endif
3509                     newItem = GetFirstChild (m_curItem, cookie);
3510                 }
3511             }
3512         }break;
3513
3514         // <DOWN>: if expanded go to the first child, else to the next sibling, ect
3515         case WXK_DOWN: {
3516             if (curItemSet) {
3517                 newItem = m_curItem;
3518             }else{
3519                 if (IsExpanded (m_curItem) && HasChildren (m_curItem)) {
3520 #if !wxCHECK_VERSION(2, 5, 0)
3521                     long cookie = 0;
3522 #else
3523                     wxTreeItemIdValue cookie = 0;
3524 #endif
3525                     newItem = GetFirstChild( m_curItem, cookie );
3526                 }
3527                 if (!newItem) {
3528                     wxTreeItemId parent = m_curItem;
3529                     do {
3530                         newItem = GetNextSibling (parent);
3531                         parent = GetItemParent (parent);
3532                     } while (!newItem && parent);
3533                 }
3534             }
3535         }break;
3536
3537         // <END>: go to last item of the root
3538         case WXK_END: {
3539 #if !wxCHECK_VERSION(2, 5, 0)
3540             long cookie = 0;
3541 #else
3542             wxTreeItemIdValue cookie = 0;
3543 #endif
3544             newItem = GetLastChild (GetRootItem(), cookie);
3545         }break;
3546
3547         // <HOME>: go to root
3548         case WXK_HOME: {
3549             newItem = GetRootItem();
3550             if (HasFlag(wxTR_HIDE_ROOT)) {
3551 #if !wxCHECK_VERSION(2, 5, 0)
3552                 long cookie = 0;
3553 #else
3554                 wxTreeItemIdValue cookie = 0;
3555 #endif
3556                 newItem = GetFirstChild (newItem, cookie);
3557             }
3558         }break;
3559
3560         // any char: go to the next matching string
3561         default:
3562             if (event.GetKeyCode() >= (int)' ') {
3563                 if (!m_findTimer->IsRunning()) m_findStr.Clear();
3564                 m_findStr.Append (event.GetKeyCode());
3565                 m_findTimer->Start (FIND_TIMER_TICKS, wxTIMER_ONE_SHOT);
3566                 wxTreeItemId prev = m_curItem? (wxTreeItemId*)m_curItem: (wxTreeItemId*)NULL;
3567                 while (true) {
3568                     newItem = FindItem (prev, m_findStr, wxTL_MODE_NAV_EXPANDED |
3569                                                          wxTL_MODE_FIND_PARTIAL |
3570                                                          wxTL_MODE_FIND_NOCASE);
3571                     if (newItem || (m_findStr.Length() <= 1)) break;
3572                     m_findStr.RemoveLast();
3573                 };
3574             }
3575             event.Skip();
3576
3577     }
3578
3579     // select and show the new item
3580     if (newItem) {
3581         if (!event.ControlDown()) {
3582             bool unselect_others = !((event.ShiftDown() || event.ControlDown()) &&
3583                                       HasFlag(wxTR_MULTIPLE));
3584             SelectItem (newItem, m_shiftItem, unselect_others);
3585         }
3586         EnsureVisible (newItem);
3587         wxTreeListItem *oldItem = m_curItem;
3588         m_curItem = (wxTreeListItem*)newItem.m_pItem; // make the new item the current item
3589         RefreshLine (oldItem);
3590     }
3591
3592 }
3593
3594 wxTreeItemId wxTreeListMainWindow::HitTest (const wxPoint& point, int& flags, int& column) {
3595
3596     int w, h;
3597     GetSize(&w, &h);
3598     flags=0;
3599     column = -1;
3600     if (point.x<0) flags |= wxTREE_HITTEST_TOLEFT;
3601     if (point.x>w) flags |= wxTREE_HITTEST_TORIGHT;
3602     if (point.y<0) flags |= wxTREE_HITTEST_ABOVE;
3603     if (point.y>h) flags |= wxTREE_HITTEST_BELOW;
3604     if (flags) return wxTreeItemId();
3605
3606     if (!m_rootItem) {
3607         flags = wxTREE_HITTEST_NOWHERE;
3608         column = -1;
3609         return wxTreeItemId();
3610     }
3611
3612     wxTreeListItem *hit = m_rootItem->HitTest (CalcUnscrolledPosition(point),
3613                                                this, flags, column, 0);
3614     if (!hit) {
3615         flags = wxTREE_HITTEST_NOWHERE;
3616         column = -1;
3617         return wxTreeItemId();
3618     }
3619     return hit;
3620 }
3621
3622 // get the bounding rectangle of the item (or of its label only)
3623 bool wxTreeListMainWindow::GetBoundingRect (const wxTreeItemId& itemId, wxRect& rect,
3624                                             bool WXUNUSED(textOnly)) const {
3625     wxCHECK_MSG (itemId.IsOk(), false, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") );
3626
3627     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
3628
3629     int xUnit, yUnit;
3630     GetScrollPixelsPerUnit (&xUnit, &yUnit);
3631     int startX, startY;
3632     GetViewStart(& startX, & startY);
3633
3634     rect.x = item->GetX() - startX * xUnit;
3635     rect.y = item->GetY() - startY * yUnit;
3636     rect.width = item->GetWidth();
3637     rect.height = GetLineHeight (item);
3638
3639     return true;
3640 }
3641
3642 /* **** */
3643
3644 void wxTreeListMainWindow::EditLabel (const wxTreeItemId& item, int column) {
3645     if (!item.IsOk()) return;
3646     if (!((column >= 0) && (column < GetColumnCount()))) return;
3647
3648     m_editItem = (wxTreeListItem*) item.m_pItem;
3649
3650     wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, m_owner->GetId() );
3651 #if !wxCHECK_VERSION(2, 5, 0)
3652     te.SetItem ((long)m_editItem);
3653 #else
3654     te.SetItem (m_editItem);
3655 #endif
3656     te.SetInt (column);
3657     te.SetEventObject (m_owner );
3658     m_owner->GetEventHandler()->ProcessEvent (te);
3659
3660     if (!te.IsAllowed()) return;
3661
3662     // ensure that the position of the item it calculated in any case
3663     if (m_dirty) CalculatePositions();
3664
3665     wxTreeListHeaderWindow* header_win = m_owner->GetHeaderWindow();
3666     int x = 0;
3667     int y = m_editItem->GetY() + 1; // wxTextCtrl needs 1 pixels above the text
3668     int w = 0;
3669     int h = m_editItem->GetHeight();
3670     long style = 0;
3671     if (column == GetMainColumn()) {
3672         x += m_editItem->GetTextX() - 2; // wxTextCtrl needs 2 pixels before the text
3673         w = wxMin (m_editItem->GetWidth(), m_owner->GetHeaderWindow()->GetWidth() - x);
3674     }else{
3675         for (int i = 0; i < column; ++i) x += header_win->GetColumnWidth (i); // start of column
3676         switch (header_win->GetColumnAlignment (column)) {
3677             case wxALIGN_LEFT: {style = wxTE_LEFT; break;}
3678             case wxALIGN_RIGHT: {style = wxTE_RIGHT; break;}
3679             case wxALIGN_CENTER: {style = wxTE_CENTER; break;}
3680         }
3681         w = header_win->GetColumnWidth (column); // width of column
3682     }
3683
3684     wxClientDC dc (this);
3685     PrepareDC (dc);
3686     x = dc.LogicalToDeviceX (x);
3687     y = dc.LogicalToDeviceY (y);
3688
3689     wxEditTextCtrl *text = new wxEditTextCtrl (this, -1, &m_renameAccept, &m_renameRes,
3690                                                this, m_editItem->GetText (column),
3691                                                wxPoint (x, y), wxSize (w, h), style);
3692     text->SetFocus();
3693 }
3694
3695 void wxTreeListMainWindow::OnRenameTimer() {
3696     EditLabel (m_curItem, m_curColumn);
3697 }
3698
3699 void wxTreeListMainWindow::OnRenameAccept() {
3700
3701     // TODO if the validator fails this causes a crash
3702     wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, m_owner->GetId() );
3703 #if !wxCHECK_VERSION(2, 5, 0)
3704     le.SetItem((long)m_editItem);
3705 #else
3706     le.SetItem(m_editItem);
3707 #endif
3708     le.SetEventObject( /*this*/m_owner );
3709     le.SetLabel( m_renameRes );
3710     m_owner->GetEventHandler()->ProcessEvent( le );
3711
3712     if (!le.IsAllowed()) return;
3713
3714     SetItemText (m_editItem, m_curColumn, m_renameRes);
3715 }
3716
3717 void wxTreeListMainWindow::OnMouse (wxMouseEvent &event) {
3718     if (!m_rootItem) return;
3719
3720     // we process left mouse up event (enables in-place edit), right down
3721     // (pass to the user code), left dbl click (activate item) and
3722     // dragging/moving events for items drag-and-drop
3723     if (!(event.LeftDown() ||
3724           event.LeftUp() ||
3725           event.RightDown() ||
3726           event.RightUp() ||
3727           event.LeftDClick() ||
3728           event.Dragging() ||
3729           (event.GetWheelRotation() != 0 )/*? TODO ||
3730           event.Moving()?*/)) {
3731         m_owner->GetEventHandler()->ProcessEvent (event);
3732         return;
3733     }
3734
3735     // set focus if window clicked
3736     if (event.LeftDown() || event.RightDown()) SetFocus();
3737
3738     // determine event
3739     wxPoint p = wxPoint (event.GetX(), event.GetY());
3740     int flags = 0;
3741     wxTreeListItem *item = m_rootItem->HitTest (CalcUnscrolledPosition (p),
3742                                                 this, flags, m_curColumn, 0);
3743
3744     // we only process dragging here
3745     if (event.Dragging()){
3746         if (m_isDragging) return; // nothing to do, already done
3747         if (item == NULL) return; // we need an item to dragging
3748
3749         // determine drag start
3750         if (m_dragCount == 0) {
3751             m_dragTimer->Start (DRAG_TIMER_TICKS, wxTIMER_ONE_SHOT);
3752         }
3753         m_dragCount++;
3754         if (m_dragCount < 3) return; // minimum drag 3 pixel
3755         if (m_dragTimer->IsRunning()) return;
3756
3757         // we're going to drag
3758         m_dragCount = 0;
3759         m_isDragging = true;
3760         CaptureMouse();
3761         RefreshSelected();
3762
3763         // send drag start event
3764         wxEventType command = event.LeftIsDown()
3765                               ? wxEVT_COMMAND_TREE_BEGIN_DRAG
3766                               : wxEVT_COMMAND_TREE_BEGIN_RDRAG;
3767         wxTreeEvent nevent (command, m_owner->GetId());
3768         nevent.SetEventObject (m_owner);
3769 #if !wxCHECK_VERSION(2, 5, 0)
3770         nevent.SetItem ((long)item); // the item the drag is ended
3771 #else
3772         nevent.SetItem (item); // the item the drag is ended
3773 #endif
3774         nevent.Veto(); // dragging must be explicit allowed!
3775         m_owner->GetEventHandler()->ProcessEvent (nevent);
3776
3777     }else if (m_isDragging) { // any other event but not event.Dragging()
3778
3779         // end dragging
3780         m_dragCount = 0;
3781         m_isDragging = false;
3782         if (HasCapture()) ReleaseMouse();
3783         RefreshSelected();
3784
3785         // send drag end event event
3786         wxTreeEvent nevent (wxEVT_COMMAND_TREE_END_DRAG, m_owner->GetId());
3787         nevent.SetEventObject (m_owner);
3788 #if !wxCHECK_VERSION(2, 5, 0)
3789         nevent.SetItem ((long)item); // the item the drag is started
3790 #else
3791         nevent.SetItem (item); // the item the drag is started
3792 #endif
3793         nevent.SetPoint (p);
3794         m_owner->GetEventHandler()->ProcessEvent (nevent);
3795
3796     }else if (m_dragCount > 0) { // just in case dragging is initiated
3797
3798         // end dragging
3799         m_dragCount = 0;
3800
3801     }
3802
3803     // we process only the messages which happen on tree items
3804     if (item == NULL) {
3805         m_owner->GetEventHandler()->ProcessEvent (event);
3806         return;
3807     }
3808
3809     // remember item at shift down
3810     if (event.ShiftDown())  {
3811         if (!m_shiftItem) m_shiftItem = m_curItem;
3812     }else{
3813         m_shiftItem = (wxTreeListItem*)NULL;
3814     }
3815
3816     if (event.RightUp()) {
3817
3818         SetFocus();
3819         wxTreeEvent nevent (wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, m_owner->GetId());
3820         nevent.SetEventObject (m_owner);
3821 #if !wxCHECK_VERSION(2, 5, 0)
3822         nevent.SetItem ((long)item); // the item clicked
3823 #else
3824         nevent.SetItem (item); // the item clicked
3825 #endif
3826         nevent.SetInt (m_curColumn); // the colum clicked
3827         nevent.SetPoint (p);
3828         m_owner->GetEventHandler()->ProcessEvent (nevent);
3829
3830     }else if (event.LeftUp()) {
3831
3832         if (m_lastOnSame) {
3833             if ((item == m_curItem) && (m_curColumn != -1) &&
3834                 (m_owner->GetHeaderWindow()->IsColumnEditable (m_curColumn)) &&
3835                 (flags & (wxTREE_HITTEST_ONITEMLABEL | wxTREE_HITTEST_ONITEMCOLUMN))){
3836                 m_renameTimer->Start (RENAME_TIMER_TICKS, wxTIMER_ONE_SHOT);
3837             }
3838             m_lastOnSame = false;
3839         }
3840
3841         if (((flags & wxTREE_HITTEST_ONITEMBUTTON) ||
3842              (flags & wxTREE_HITTEST_ONITEMICON)) &&
3843             HasButtons() && item->HasPlus()) {
3844
3845
3846             // only toggle the item for a single click, double click on
3847             // the button doesn't do anything (it toggles the item twice)
3848             if (event.LeftDown()) Toggle (item);
3849
3850             // don't select the item if the button was clicked
3851             return;
3852         }
3853
3854         // determine the selection if not done by left down
3855         if (!m_left_down_selection) {
3856             bool unselect_others = !((event.ShiftDown() || event.ControlDown()) &&
3857                                      HasFlag(wxTR_MULTIPLE));
3858
3859             SelectItem (item, m_shiftItem, unselect_others);
3860             EnsureVisible (item);
3861             //  LG  m_curItem = item; // make the new item the current item
3862         }else{
3863             m_left_down_selection = false;
3864         }
3865
3866     }else if (event.LeftDown() || event.RightDown() || event.LeftDClick()) {
3867
3868         if (event.LeftDown() || event.RightDown()) {
3869             SetFocus();
3870             m_lastOnSame = item == m_curItem;
3871         }
3872
3873         if (((flags & wxTREE_HITTEST_ONITEMBUTTON) ||
3874              (flags & wxTREE_HITTEST_ONITEMICON)) &&
3875             item->HasPlus()) {
3876
3877             // only toggle the item for a single click, double click on
3878             // the button doesn't do anything (it toggles the item twice)
3879
3880             if (event.LeftDown()) Toggle (item);
3881
3882             // don't select the item if the button was clicked
3883             return;
3884         }
3885
3886         // determine the selection if the current item is not selected
3887         if (!item->IsSelected()) {
3888             bool unselect_others = !((event.ShiftDown() || event.ControlDown()) &&
3889                                      HasFlag(wxTR_MULTIPLE));
3890             SelectItem (item, m_shiftItem, unselect_others);
3891             EnsureVisible (item);
3892             // LG m_curItem = item; // make the new item the current item
3893             m_left_down_selection = true;
3894         }
3895
3896         // For some reason, Windows isn't recognizing a left double-click,
3897         // so we need to simulate it here.  Allow 200 milliseconds for now.
3898         if (event.LeftDClick()) {
3899
3900             // double clicking should not start editing the item label
3901             m_renameTimer->Stop();
3902             m_lastOnSame = false;
3903
3904             // send activate event first
3905             wxTreeEvent nevent (wxEVT_COMMAND_TREE_ITEM_ACTIVATED, m_owner->GetId());
3906             nevent.SetEventObject (m_owner);
3907 #if !wxCHECK_VERSION(2, 5, 0)
3908             nevent.SetItem ((long)item); // the item clicked
3909 #else
3910             nevent.SetItem (item); // the item clicked
3911 #endif
3912             nevent.SetInt (m_curColumn); // the colum clicked
3913             nevent.SetPoint (p);
3914             if (!m_owner->GetEventHandler()->ProcessEvent (nevent)) {
3915
3916                 // if the user code didn't process the activate event,
3917                 // handle it ourselves by toggling the item when it is
3918                 // double clicked
3919
3920                 if (item->HasPlus()) Toggle(item);
3921             }
3922         }
3923
3924     }else{ // any other event skip just in case
3925
3926         event.Skip();
3927
3928     }
3929 }
3930
3931 void wxTreeListMainWindow::OnIdle (wxIdleEvent &WXUNUSED(event)) {
3932     /* after all changes have been done to the tree control,
3933      * we actually redraw the tree when everything is over */
3934
3935     if (!m_dirty) return;
3936
3937     m_dirty = false;
3938
3939     CalculatePositions();
3940     Refresh();
3941     AdjustMyScrollbars();
3942 }
3943
3944 void wxTreeListMainWindow::OnScroll (wxScrollWinEvent& event) {
3945     // FIXME
3946 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
3947     wxScrolledWindow::OnScroll(event);
3948 #else
3949     HandleOnScroll( event );
3950 #endif
3951
3952     if(event.GetOrientation() == wxHORIZONTAL) {
3953         m_owner->GetHeaderWindow()->Refresh();
3954         m_owner->GetHeaderWindow()->Update();
3955     }
3956 }
3957
3958 void wxTreeListMainWindow::CalculateSize (wxTreeListItem *item, wxDC &dc) {
3959     wxCoord text_w = 0;
3960     wxCoord text_h = 0;
3961
3962     dc.SetFont (GetItemFont (item));
3963
3964     dc.GetTextExtent (item->GetText (m_main_column), &text_w, &text_h);
3965
3966     // restore normal font
3967     dc.SetFont (m_normalFont);
3968
3969     int total_h = (m_imgHeight > text_h) ? m_imgHeight : text_h;
3970     if (total_h < 30) { // add 10% space if greater than 30 pixels
3971       total_h += 2; // minimal 2 pixel space
3972     }else{
3973       total_h += total_h / 10; // otherwise 10% space
3974     }
3975
3976     item->SetHeight (total_h);
3977     if (total_h > m_lineHeight) m_lineHeight = total_h;
3978     item->SetWidth(m_imgWidth + text_w +2);
3979 }
3980
3981 // -----------------------------------------------------------------------------
3982 void wxTreeListMainWindow::CalculateLevel (wxTreeListItem *item, wxDC &dc,
3983                                            int level, int &y, int x_colstart) {
3984
3985     // calculate position of vertical lines
3986     int x = x_colstart + MARGIN; // start of column
3987     if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
3988     if (HasButtons()) {
3989         x += (m_btnWidth-m_btnWidth2); // half button space
3990     }else{
3991         x += (m_indent-m_indent/2);
3992     }
3993     if (HasFlag(wxTR_HIDE_ROOT)) {
3994       // LG
3995       //        x += m_indent * (level-2); // indent but not level 1
3996       x += m_indent * (level-1); // indent but not level 1
3997
3998     }else{
3999         x += m_indent * level; // indent according to level
4000     }
4001
4002     // a hidden root is not evaluated, but its children are always
4003     if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) goto Recurse;
4004
4005     CalculateSize( item, dc );
4006
4007     // set its position
4008     item->SetX (x);
4009     item->SetY (y);
4010     y += GetLineHeight(item);
4011
4012     // we don't need to calculate collapsed branches
4013     if ( !item->IsExpanded() ) return;
4014
4015 Recurse:
4016     wxArrayTreeListItems& children = item->GetChildren();
4017     long n, count = (long)children.Count();
4018     ++level;
4019     for (n = 0; n < count; ++n) {
4020         CalculateLevel( children[n], dc, level, y, x_colstart );  // recurse
4021     }
4022 }
4023
4024 void wxTreeListMainWindow::CalculatePositions() {
4025     if ( !m_rootItem ) return;
4026
4027     wxClientDC dc(this);
4028     PrepareDC( dc );
4029
4030     dc.SetFont( m_normalFont );
4031
4032     dc.SetPen( m_dottedPen );
4033     //if(GetImageList() == NULL)
4034     // m_lineHeight = (int)(dc.GetCharHeight() + 4);
4035
4036     int y = 2;
4037     int x_colstart = 0;
4038     for (int i = 0; i < (int)GetMainColumn(); ++i) {
4039         if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
4040         x_colstart += m_owner->GetHeaderWindow()->GetColumnWidth(i);
4041     }
4042     CalculateLevel( m_rootItem, dc, 0, y, x_colstart ); // start recursion
4043 }
4044
4045 void wxTreeListMainWindow::RefreshSubtree (wxTreeListItem *item) {
4046     if (m_dirty) return;
4047
4048     wxClientDC dc(this);
4049     PrepareDC(dc);
4050
4051     int cw = 0;
4052     int ch = 0;
4053     GetVirtualSize( &cw, &ch );
4054
4055     wxRect rect;
4056     rect.x = dc.LogicalToDeviceX( 0 );
4057     rect.width = cw;
4058     rect.y = dc.LogicalToDeviceY( item->GetY() - 2 );
4059     rect.height = ch;
4060
4061     Refresh (true, &rect );
4062     AdjustMyScrollbars();
4063 }
4064
4065 void wxTreeListMainWindow::RefreshLine (wxTreeListItem *item) {
4066
4067   //  return;
4068   //  std::cout << "RefreshLine = "<<item<<std::endl;
4069   //return;
4070
4071   if (m_dirty) return;
4072
4073     wxClientDC dc(this);
4074     PrepareDC( dc );
4075
4076     int cw = 0;
4077     int ch = 0;
4078     GetVirtualSize( &cw, &ch );
4079
4080     wxRect rect;
4081     rect.x = dc.LogicalToDeviceX( 0 );
4082     rect.y = dc.LogicalToDeviceY( item->GetY() );
4083     rect.width = cw;
4084     rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6;
4085
4086     Refresh (true, &rect);
4087 }
4088
4089 void wxTreeListMainWindow::RefreshSelected() 
4090 {
4091
4092   long count = m_selected.GetCount();
4093   for (long n = 0; n < count; n++ ) 
4094     {
4095       RefreshLine (m_selected[n]);
4096     }
4097 }
4098
4099 /*
4100 void wxTreeListMainWindow::RefreshSelectedUnder (wxTreeListItem *item) {
4101     if (item->IsSelected()) {
4102         RefreshLine (item);
4103     }
4104
4105     const wxArrayTreeListItems& children = item->GetChildren();
4106     long count = children.GetCount();
4107     for (long n = 0; n < count; n++ ) {
4108         RefreshSelectedUnder (children[n]);
4109     }
4110 }
4111 */
4112
4113 // ----------------------------------------------------------------------------
4114 // changing colours: we need to refresh the tree control
4115 // ----------------------------------------------------------------------------
4116
4117 bool wxTreeListMainWindow::SetBackgroundColour (const wxColour& colour) {
4118     if (!wxWindow::SetBackgroundColour(colour)) return false;
4119
4120     Refresh();
4121     return true;
4122 }
4123
4124 bool wxTreeListMainWindow::SetForegroundColour (const wxColour& colour) {
4125     if (!wxWindow::SetForegroundColour(colour)) return false;
4126
4127     Refresh();
4128     return true;
4129 }
4130
4131 void wxTreeListMainWindow::SetItemText (const wxTreeItemId& itemId, int column,
4132                                         const wxString& text) {
4133     wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
4134
4135     wxClientDC dc (this);
4136     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
4137     item->SetText (column, text);
4138     CalculateSize (item, dc);
4139     RefreshLine (item);
4140 }
4141
4142 wxString wxTreeListMainWindow::GetItemText (const wxTreeItemId& itemId,
4143                                             int column) const {
4144     wxCHECK_MSG (itemId.IsOk(), _T(""), _T("invalid tree item") );
4145
4146     if( IsVirtual() )   return m_owner->OnGetItemText(((wxTreeListItem*) itemId.m_pItem)->GetData(),column);
4147     else                return ((wxTreeListItem*) itemId.m_pItem)->GetText (column);
4148 }
4149
4150 wxString wxTreeListMainWindow::GetItemText (wxTreeItemData* item,
4151 int column) const {
4152    wxASSERT_MSG( IsVirtual(), _T("can be used only with virtual control") );
4153    return m_owner->OnGetItemText(item,column);
4154 }
4155
4156 void wxTreeListMainWindow::SetFocus() {
4157     wxWindow::SetFocus();
4158 }
4159
4160 wxFont wxTreeListMainWindow::GetItemFont (wxTreeListItem *item) {
4161     wxTreeItemAttr *attr = item->GetAttributes();
4162
4163     if (attr && attr->HasFont()) {
4164         return attr->GetFont();
4165     }else if (item->IsBold()) {
4166         return m_boldFont;
4167     }else{
4168         return m_normalFont;
4169    }
4170 }
4171
4172 int wxTreeListMainWindow::GetItemWidth (int column, wxTreeListItem *item) {
4173     if (!item) return 0;
4174
4175     // determine item width
4176     int w = 0, h = 0;
4177     wxFont font = GetItemFont (item);
4178     GetTextExtent (item->GetText (column), &w, &h, NULL, NULL, font.Ok()? &font: NULL);
4179     w += 2*MARGIN;
4180
4181     // calculate width
4182     int width = w + 2*MARGIN;
4183     if (column == GetMainColumn()) {
4184         width += MARGIN;
4185         if (HasFlag(wxTR_LINES_AT_ROOT)) width += LINEATROOT;
4186         if (HasButtons()) width += m_btnWidth + LINEATROOT;
4187         if (item->GetCurrentImage() != NO_IMAGE) width += m_imgWidth;
4188
4189         // count indent level
4190         int level = 0;
4191         wxTreeListItem *parent = item->GetItemParent();
4192         wxTreeListItem *root = (wxTreeListItem*)GetRootItem().m_pItem;
4193         while (parent && (!HasFlag(wxTR_HIDE_ROOT) || (parent != root))) {
4194             level++;
4195             parent = parent->GetItemParent();
4196         }
4197         if (level) width += level * GetIndent();
4198     }
4199
4200     return width;
4201 }
4202
4203 int wxTreeListMainWindow::GetBestColumnWidth (int column, wxTreeItemId parent) {
4204     int maxWidth, h;
4205     GetClientSize (&maxWidth, &h);
4206     int width = 0;
4207
4208     // get root if on item
4209     if (!parent.IsOk()) parent = GetRootItem();
4210
4211     // add root width
4212     if (!HasFlag(wxTR_HIDE_ROOT)) {
4213         int w = GetItemWidth (column, (wxTreeListItem*)parent.m_pItem);
4214         if (width < w) width = w;
4215         if (width > maxWidth) return maxWidth;
4216     }
4217
4218     wxTreeItemIdValue cookie = 0;
4219     wxTreeItemId item = GetFirstChild (parent, cookie);
4220     while (item.IsOk()) {
4221         int w = GetItemWidth (column, (wxTreeListItem*)item.m_pItem);
4222         if (width < w) width = w;
4223         if (width > maxWidth) return maxWidth;
4224
4225         // check the children of this item
4226         if (((wxTreeListItem*)item.m_pItem)->IsExpanded()) {
4227             int w = GetBestColumnWidth (column, item);
4228             if (width < w) width = w;
4229             if (width > maxWidth) return maxWidth;
4230         }
4231
4232         // next sibling
4233         item = GetNextChild (parent, cookie);
4234     }
4235
4236     return width;
4237 }
4238
4239
4240 //-----------------------------------------------------------------------------
4241 //  wxTreeListCtrl
4242 //-----------------------------------------------------------------------------
4243
4244 //IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl, wxControl);
4245 //IMPLEMENT_CLASS(wxTreeListCtrl, wxControl);
4246
4247 BEGIN_EVENT_TABLE(wxTreeListCtrl, wxControl)
4248     EVT_SIZE(wxTreeListCtrl::OnSize)
4249 END_EVENT_TABLE();
4250
4251 bool wxTreeListCtrl::Create(wxWindow *parent, wxWindowID id,
4252                             const wxPoint& pos,
4253                             const wxSize& size,
4254                             long style, const wxValidator &validator,
4255                             const wxString& name)
4256 {
4257     long main_style = style & ~(wxSIMPLE_BORDER|wxSUNKEN_BORDER|wxDOUBLE_BORDER|
4258                                 wxRAISED_BORDER|wxSTATIC_BORDER);
4259     long ctrl_style = style & ~(wxVSCROLL|wxHSCROLL);
4260
4261     if (!wxControl::Create(parent, id, pos, size, ctrl_style, validator, name)) {
4262        return false;
4263     }
4264     m_main_win = new wxTreeListMainWindow (this, -1, wxPoint(0, 0), size,
4265                                            main_style, validator);
4266     m_header_win = new wxTreeListHeaderWindow (this, -1, m_main_win,
4267                                                wxPoint(0, 0), wxDefaultSize,
4268                                                wxTAB_TRAVERSAL);
4269     CalculateAndSetHeaderHeight();
4270     return true;
4271 }
4272
4273 void wxTreeListCtrl::CalculateAndSetHeaderHeight()
4274 {
4275     if (m_header_win) {
4276
4277         // we use 'g' to get the descent, too
4278         int w, h, d;
4279         m_header_win->GetTextExtent(_T("Hg"), &w, &h, &d);
4280         h += d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
4281         h = 0 ;
4282         // only update if changed
4283         if (h != m_headerHeight) {
4284             m_headerHeight = h;
4285             DoHeaderLayout();
4286         }
4287     }
4288 }
4289
4290 void wxTreeListCtrl::DoHeaderLayout()
4291 {
4292     int w, h;
4293     GetClientSize(&w, &h);
4294     if (m_header_win) {
4295         m_header_win->SetSize (0, 0, w, m_headerHeight);
4296         m_header_win->Refresh();
4297     }
4298     if (m_main_win) {
4299         m_main_win->SetSize (0, m_headerHeight + 1, w, h - m_headerHeight - 1);
4300     }
4301 }
4302
4303 void wxTreeListCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
4304 {
4305     DoHeaderLayout();
4306 }
4307
4308 size_t wxTreeListCtrl::GetCount() const { return m_main_win->GetCount(); }
4309
4310 unsigned int wxTreeListCtrl::GetIndent() const
4311 { return m_main_win->GetIndent(); }
4312
4313 void wxTreeListCtrl::SetIndent(unsigned int indent)
4314 { m_main_win->SetIndent(indent); }
4315
4316 unsigned int wxTreeListCtrl::GetLineSpacing() const
4317 { return m_main_win->GetLineSpacing(); }
4318
4319 void wxTreeListCtrl::SetLineSpacing(unsigned int spacing)
4320 { m_main_win->SetLineSpacing(spacing); }
4321
4322 wxImageList* wxTreeListCtrl::GetImageList() const
4323 { return m_main_win->GetImageList(); }
4324
4325 wxImageList* wxTreeListCtrl::GetStateImageList() const
4326 { return m_main_win->GetStateImageList(); }
4327
4328 wxImageList* wxTreeListCtrl::GetButtonsImageList() const
4329 { return m_main_win->GetButtonsImageList(); }
4330
4331 void wxTreeListCtrl::SetImageList(wxImageList* imageList)
4332 { m_main_win->SetImageList(imageList); }
4333
4334 void wxTreeListCtrl::SetStateImageList(wxImageList* imageList)
4335 { m_main_win->SetStateImageList(imageList); }
4336
4337 void wxTreeListCtrl::SetButtonsImageList(wxImageList* imageList)
4338 { m_main_win->SetButtonsImageList(imageList); }
4339
4340 void wxTreeListCtrl::AssignImageList(wxImageList* imageList)
4341 { m_main_win->AssignImageList(imageList); }
4342
4343 void wxTreeListCtrl::AssignStateImageList(wxImageList* imageList)
4344 { m_main_win->AssignStateImageList(imageList); }
4345
4346 void wxTreeListCtrl::AssignButtonsImageList(wxImageList* imageList)
4347 { m_main_win->AssignButtonsImageList(imageList); }
4348
4349 wxString wxTreeListCtrl::GetItemText(const wxTreeItemId& item, int column) const
4350 { return m_main_win->GetItemText (item, column); }
4351
4352 int wxTreeListCtrl::GetItemImage(const wxTreeItemId& item, int column,
4353                                  wxTreeItemIcon which) const
4354 { return m_main_win->GetItemImage(item, column, which); }
4355
4356 wxTreeItemData* wxTreeListCtrl::GetItemData(const wxTreeItemId& item) const
4357 { return m_main_win->GetItemData(item); }
4358
4359 bool wxTreeListCtrl::GetItemBold(const wxTreeItemId& item) const
4360 { return m_main_win->GetItemBold(item); }
4361
4362 wxColour wxTreeListCtrl::GetItemTextColour(const wxTreeItemId& item) const
4363 { return m_main_win->GetItemTextColour(item); }
4364
4365 wxColour wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId& item)
4366     const
4367 { return m_main_win->GetItemBackgroundColour(item); }
4368
4369 wxFont wxTreeListCtrl::GetItemFont(const wxTreeItemId& item) const
4370 { return m_main_win->GetItemFont(item); }
4371
4372
4373 void wxTreeListCtrl::SetItemText(const wxTreeItemId& item, int column,
4374                                  const wxString& text)
4375 { m_main_win->SetItemText (item, column, text); }
4376
4377 void wxTreeListCtrl::SetItemImage(const wxTreeItemId& item,
4378                                   int column,
4379                                   int image,
4380                                   wxTreeItemIcon which)
4381 { m_main_win->SetItemImage(item, column, image, which); }
4382
4383 void wxTreeListCtrl::SetItemData(const wxTreeItemId& item,
4384                                  wxTreeItemData* data)
4385 { m_main_win->SetItemData(item, data); }
4386
4387 void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
4388 { m_main_win->SetItemHasChildren(item, has); }
4389
4390 void wxTreeListCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
4391 { m_main_win->SetItemBold(item, bold); }
4392
4393 void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId& item,
4394                                        const wxColour& colour)
4395 { m_main_win->SetItemTextColour(item, colour); }
4396
4397 void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId& item,
4398                                              const wxColour& colour)
4399 { m_main_win->SetItemBackgroundColour(item, colour); }
4400
4401 void wxTreeListCtrl::SetItemFont(const wxTreeItemId& item,
4402                                  const wxFont& font)
4403 { m_main_win->SetItemFont(item, font); }
4404
4405 bool wxTreeListCtrl::SetFont(const wxFont& font)
4406 {
4407     if (m_header_win) {
4408         m_header_win->SetFont(font);
4409         CalculateAndSetHeaderHeight();
4410         m_header_win->Refresh();
4411     }
4412     if (m_main_win) {
4413         return m_main_win->SetFont(font);
4414     }else{
4415         return false;
4416     }
4417 }
4418
4419 void wxTreeListCtrl::SetWindowStyle(const long style)
4420 {
4421     if(m_main_win)
4422         m_main_win->SetWindowStyle(style);
4423     m_windowStyle = style;
4424     // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win
4425 }
4426
4427 long wxTreeListCtrl::GetWindowStyle() const
4428 {
4429     long style = m_windowStyle;
4430     if(m_main_win)
4431         style |= m_main_win->GetWindowStyle();
4432     return style;
4433 }
4434
4435 bool wxTreeListCtrl::IsVisible(const wxTreeItemId& item, bool fullRow) const
4436 { return m_main_win->IsVisible(item, fullRow); }
4437
4438 bool wxTreeListCtrl::HasChildren(const wxTreeItemId& item) const
4439 { return m_main_win->HasChildren(item); }
4440
4441 bool wxTreeListCtrl::IsExpanded(const wxTreeItemId& item) const
4442 { return m_main_win->IsExpanded(item); }
4443
4444 bool wxTreeListCtrl::IsSelected(const wxTreeItemId& item) const
4445 { return m_main_win->IsSelected(item); }
4446
4447 bool wxTreeListCtrl::IsBold(const wxTreeItemId& item) const
4448 { return m_main_win->IsBold(item); }
4449
4450 size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId& item, bool rec)
4451 { return m_main_win->GetChildrenCount(item, rec); }
4452
4453 wxTreeItemId wxTreeListCtrl::GetRootItem() const
4454 { return m_main_win->GetRootItem(); }
4455
4456 //wxTreeItemId wxTreeListCtrl::GetSelection() const
4457 //{ return m_main_win->GetSelection(); }
4458  wxTreeItemId wxTreeListCtrl::GetCurrent() const
4459  { return m_main_win->GetCurrent(); }
4460
4461 size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds& arr) const
4462 { return m_main_win->GetSelections(arr); }
4463
4464 wxTreeItemId wxTreeListCtrl::GetItemParent(const wxTreeItemId& item) const
4465 { return m_main_win->GetItemParent(item); }
4466
4467 #if !wxCHECK_VERSION(2, 5, 0)
4468 wxTreeItemId wxTreeListCtrl::GetFirstChild (const wxTreeItemId& item,
4469                                             long& cookie) const
4470 #else
4471 wxTreeItemId wxTreeListCtrl::GetFirstChild (const wxTreeItemId& item,
4472                                             wxTreeItemIdValue& cookie) const
4473 #endif
4474 { return m_main_win->GetFirstChild(item, cookie); }
4475
4476 #if !wxCHECK_VERSION(2, 5, 0)
4477 wxTreeItemId wxTreeListCtrl::GetNextChild (const wxTreeItemId& item,
4478                                            long& cookie) const
4479 #else
4480 wxTreeItemId wxTreeListCtrl::GetNextChild (const wxTreeItemId& item,
4481                                            wxTreeItemIdValue& cookie) const
4482 #endif
4483 { return m_main_win->GetNextChild(item, cookie); }
4484
4485 #if !wxCHECK_VERSION(2, 5, 0)
4486 wxTreeItemId wxTreeListCtrl::GetPrevChild (const wxTreeItemId& item,
4487                                            long& cookie) const
4488 #else
4489 wxTreeItemId wxTreeListCtrl::GetPrevChild (const wxTreeItemId& item,
4490                                            wxTreeItemIdValue& cookie) const
4491 #endif
4492 { return m_main_win->GetPrevChild(item, cookie); }
4493
4494 #if !wxCHECK_VERSION(2, 5, 0)
4495 wxTreeItemId wxTreeListCtrl::GetLastChild (const wxTreeItemId& item,
4496                                            long& cookie) const
4497 #else
4498 wxTreeItemId wxTreeListCtrl::GetLastChild (const wxTreeItemId& item,
4499                                            wxTreeItemIdValue& cookie) const
4500 #endif
4501 { return m_main_win->GetLastChild(item, cookie); }
4502
4503
4504 wxTreeItemId wxTreeListCtrl::GetNextSibling(const wxTreeItemId& item) const
4505 { return m_main_win->GetNextSibling(item); }
4506
4507 wxTreeItemId wxTreeListCtrl::GetPrevSibling(const wxTreeItemId& item) const
4508 { return m_main_win->GetPrevSibling(item); }
4509
4510 wxTreeItemId wxTreeListCtrl::GetNext(const wxTreeItemId& item) const
4511 { return m_main_win->GetNext(item, true); }
4512
4513 wxTreeItemId wxTreeListCtrl::GetPrev(const wxTreeItemId& item) const
4514 { return m_main_win->GetPrev(item, true); }
4515
4516 wxTreeItemId wxTreeListCtrl::GetFirstExpandedItem() const
4517 { return m_main_win->GetFirstExpandedItem(); }
4518
4519 wxTreeItemId wxTreeListCtrl::GetNextExpanded(const wxTreeItemId& item) const
4520 { return m_main_win->GetNextExpanded(item); }
4521
4522 wxTreeItemId wxTreeListCtrl::GetPrevExpanded(const wxTreeItemId& item) const
4523 { return m_main_win->GetPrevExpanded(item); }
4524
4525 wxTreeItemId wxTreeListCtrl::GetFirstVisibleItem(bool fullRow) const
4526 { return m_main_win->GetFirstVisibleItem(fullRow); }
4527
4528 wxTreeItemId wxTreeListCtrl::GetNextVisible(const wxTreeItemId& item, bool fullRow) const
4529 { return m_main_win->GetNextVisible(item, fullRow); }
4530
4531 wxTreeItemId wxTreeListCtrl::GetPrevVisible(const wxTreeItemId& item, bool fullRow) const
4532 { return m_main_win->GetPrevVisible(item, fullRow); }
4533
4534 wxTreeItemId wxTreeListCtrl::AddRoot (const wxString& text, int image,
4535                                       int selectedImage, wxTreeItemData* data)
4536 { return m_main_win->AddRoot (text, image, selectedImage, data); }
4537
4538 wxTreeItemId wxTreeListCtrl::PrependItem(const wxTreeItemId& parent,
4539                                          const wxString& text, int image,
4540                                          int selectedImage,
4541                                          wxTreeItemData* data)
4542 { return m_main_win->PrependItem(parent, text, image, selectedImage, data); }
4543
4544 wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
4545                                         const wxTreeItemId& previous,
4546                                         const wxString& text, int image,
4547                                         int selectedImage,
4548                                         wxTreeItemData* data)
4549 {
4550     return m_main_win->InsertItem(parent, previous, text, image,
4551                                   selectedImage, data);
4552 }
4553
4554 wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
4555                                         size_t index,
4556                                         const wxString& text, int image,
4557                                         int selectedImage,
4558                                         wxTreeItemData* data)
4559 {
4560     return m_main_win->InsertItem(parent, index, text, image,
4561                                   selectedImage, data);
4562 }
4563
4564 wxTreeItemId wxTreeListCtrl::AppendItem(const wxTreeItemId& parent,
4565                                         const wxString& text, int image,
4566                                         int selectedImage,
4567                                         wxTreeItemData* data)
4568 { return m_main_win->AppendItem(parent, text, image, selectedImage, data); }
4569
4570 void wxTreeListCtrl::Delete(const wxTreeItemId& item)
4571 { m_main_win->Delete(item); }
4572
4573 void wxTreeListCtrl::DeleteChildren(const wxTreeItemId& item)
4574 { m_main_win->DeleteChildren(item); }
4575
4576 void wxTreeListCtrl::DeleteRoot()
4577 { m_main_win->DeleteRoot(); }
4578
4579 void wxTreeListCtrl::Expand(const wxTreeItemId& item)
4580 { m_main_win->Expand(item); }
4581
4582 void wxTreeListCtrl::ExpandAll(const wxTreeItemId& item)
4583 { m_main_win->ExpandAll(item); }
4584
4585 void wxTreeListCtrl::Collapse(const wxTreeItemId& item)
4586 { m_main_win->Collapse(item); }
4587
4588 void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId& item)
4589 { m_main_win->CollapseAndReset(item); }
4590
4591 void wxTreeListCtrl::Toggle(const wxTreeItemId& item)
4592 { m_main_win->Toggle(item); }
4593
4594 //void wxTreeListCtrl::Unselect()
4595 //{ m_main_win->Unselect(); }
4596
4597 // LG 19/09/08 : Added 
4598 //void wxTreeListCtrl::Unselect(wxTreeItemId& item)
4599 //{ m_main_win->Unselect((wxTreeListItem*)item.m_pItem); }
4600
4601 void wxTreeListCtrl::UnselectAll()
4602 { m_main_win->UnselectAll(); }
4603
4604 void wxTreeListCtrl::SelectItem(const wxTreeItemId& item, const wxTreeItemId& last,
4605                                 bool unselect_others)
4606 { m_main_win->SelectItem (item, last, unselect_others); }
4607
4608 void wxTreeListCtrl::SelectAll()
4609 { m_main_win->SelectAll(); }
4610
4611 void wxTreeListCtrl::EnsureVisible(const wxTreeItemId& item)
4612 { m_main_win->EnsureVisible(item); }
4613
4614 void wxTreeListCtrl::ScrollTo(const wxTreeItemId& item)
4615 { m_main_win->ScrollTo(item); }
4616
4617 wxTreeItemId wxTreeListCtrl::HitTest(const wxPoint& pos, int& flags, int& column)
4618 {
4619     wxPoint p = m_main_win->ScreenToClient (ClientToScreen (pos));
4620     return m_main_win->HitTest (p, flags, column);
4621 }
4622
4623 bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId& item, wxRect& rect,
4624                                      bool textOnly) const
4625 { return m_main_win->GetBoundingRect(item, rect, textOnly); }
4626
4627 void wxTreeListCtrl::EditLabel (const wxTreeItemId& item, int column)
4628 { m_main_win->EditLabel (item, column); }
4629
4630 int wxTreeListCtrl::OnCompareItems(const wxTreeItemId& item1,
4631                                    const wxTreeItemId& item2)
4632 {
4633     // do the comparison here, and not delegate to m_main_win, in order
4634     // to let the user override it
4635     //return m_main_win->OnCompareItems(item1, item2);
4636     return wxStrcmp(GetItemText(item1), GetItemText(item2));
4637 }
4638
4639 void wxTreeListCtrl::SortChildren(const wxTreeItemId& item)
4640 { m_main_win->SortChildren(item); }
4641
4642 wxTreeItemId wxTreeListCtrl::FindItem (const wxTreeItemId& item, const wxString& str, int mode)
4643 { return m_main_win->FindItem (item, str, mode); }
4644
4645 void wxTreeListCtrl::SetDragItem (const wxTreeItemId& item)
4646 { m_main_win->SetDragItem (item); }
4647
4648 bool wxTreeListCtrl::SetBackgroundColour(const wxColour& colour)
4649 {
4650     if (!m_main_win) return false;
4651     return m_main_win->SetBackgroundColour(colour);
4652 }
4653
4654 bool wxTreeListCtrl::SetForegroundColour(const wxColour& colour)
4655 {
4656     if (!m_main_win) return false;
4657     return m_main_win->SetForegroundColour(colour);
4658 }
4659
4660 int wxTreeListCtrl::GetColumnCount() const
4661 { return m_main_win->GetColumnCount(); }
4662
4663 void wxTreeListCtrl::SetColumnWidth(int column, int width)
4664 {
4665     m_header_win->SetColumnWidth (column, width);
4666     m_header_win->Refresh();
4667 }
4668
4669 int wxTreeListCtrl::GetColumnWidth(int column) const
4670 { return m_header_win->GetColumnWidth(column); }
4671
4672 void wxTreeListCtrl::SetMainColumn(int column)
4673 { m_main_win->SetMainColumn(column); }
4674
4675 int wxTreeListCtrl::GetMainColumn() const
4676 { return m_main_win->GetMainColumn(); }
4677
4678 void wxTreeListCtrl::SetColumnText(int column, const wxString& text)
4679 {
4680     m_header_win->SetColumnText (column, text);
4681     m_header_win->Refresh();
4682 }
4683
4684 wxString wxTreeListCtrl::GetColumnText(int column) const
4685 { return m_header_win->GetColumnText(column); }
4686
4687 void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo& colInfo)
4688 {
4689     m_header_win->AddColumn (colInfo);
4690     DoHeaderLayout();
4691 }
4692
4693 void wxTreeListCtrl::InsertColumn(int before, const wxTreeListColumnInfo& colInfo)
4694 {
4695     m_header_win->InsertColumn (before, colInfo);
4696     m_header_win->Refresh();
4697 }
4698
4699 void wxTreeListCtrl::RemoveColumn(int column)
4700 {
4701     m_header_win->RemoveColumn (column);
4702     m_header_win->Refresh();
4703 }
4704
4705 void wxTreeListCtrl::SetColumn(int column, const wxTreeListColumnInfo& colInfo)
4706 {
4707     m_header_win->SetColumn (column, colInfo);
4708     m_header_win->Refresh();
4709 }
4710
4711 const wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(int column) const
4712 { return m_header_win->GetColumn(column); }
4713
4714 wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(int column)
4715 { return m_header_win->GetColumn(column); }
4716
4717 void wxTreeListCtrl::SetColumnImage(int column, int image)
4718 {
4719     m_header_win->SetColumn (column, GetColumn(column).SetImage(image));
4720     m_header_win->Refresh();
4721 }
4722
4723 int wxTreeListCtrl::GetColumnImage(int column) const
4724 {
4725     return m_header_win->GetColumn(column).GetImage();
4726 }
4727
4728 void wxTreeListCtrl::SetColumnEditable(int column, bool shown)
4729 {
4730     m_header_win->SetColumn (column, GetColumn(column).SetEditable(shown));
4731 }
4732
4733 void wxTreeListCtrl::SetColumnShown(int column, bool shown)
4734 {
4735     wxASSERT_MSG (column != GetMainColumn(), _T("The main column may not be hidden") );
4736     m_header_win->SetColumn (column, GetColumn(column).SetShown(GetMainColumn()==column? true: shown));
4737     m_header_win->Refresh();
4738 }
4739
4740 bool wxTreeListCtrl::IsColumnEditable(int column) const
4741 {
4742     return m_header_win->GetColumn(column).IsEditable();
4743 }
4744
4745 bool wxTreeListCtrl::IsColumnShown(int column) const
4746 {
4747     return m_header_win->GetColumn(column).IsShown();
4748 }
4749
4750 void wxTreeListCtrl::SetColumnAlignment (int column, int flag)
4751 {
4752     m_header_win->SetColumn(column, GetColumn(column).SetAlignment(flag));
4753     m_header_win->Refresh();
4754 }
4755
4756 int wxTreeListCtrl::GetColumnAlignment(int column) const
4757 {
4758     return m_header_win->GetColumn(column).GetAlignment();
4759 }
4760
4761 void wxTreeListCtrl::Refresh(bool erase, const wxRect* rect)
4762 {
4763     m_main_win->Refresh (erase, rect);
4764     m_header_win->Refresh (erase, rect);
4765 }
4766
4767 void wxTreeListCtrl::SetFocus()
4768 { m_main_win->SetFocus(); }
4769
4770 wxSize wxTreeListCtrl::DoGetBestSize() const
4771 {
4772     // something is better than nothing...
4773     return wxSize (200,200); // but it should be specified values! FIXME
4774 }
4775
4776 wxString wxTreeListCtrl::OnGetItemText( wxTreeItemData* WXUNUSED(item), long WXUNUSED(column)) const
4777 {
4778     return wxEmptyString;
4779 }