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