]> Creatis software - creaImageIO.git/blob - src/treelistctrl.cpp
c3762047718ad030993979e6419c6741c305a9e5
[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.4 2009/03/20 14:43:12 davila 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
1137  // EED
1138  //   wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID );
1139    pen.SetColour( wxColour( 0x88 , 0x88 , 0x88 )  );
1140  
1141 #endif
1142     dc->SetPen( pen );
1143     dc->DrawLine( x+w-m_corner, y, x+w-1, y+h );  // right (inner)
1144     dc->DrawRectangle( x+1, y+h-1, w-2, 1 );      // bottom (inner)
1145
1146     dc->SetPen( *wxWHITE_PEN );
1147     dc->DrawRectangle( x, y, w-m_corner+1, 1 );   // top (outer)
1148     dc->DrawRectangle( x, y, 1, h );              // left (outer)
1149     dc->DrawLine( x, y+h-1, x+1, y+h-1 );
1150     dc->DrawLine( x+w-1, y, x+w-1, y+1 );
1151 }
1152
1153 // shift the DC origin to match the position of the main window horz
1154 // scrollbar: this allows us to always use logical coords
1155 void wxTreeListHeaderWindow::AdjustDC(wxDC& dc)
1156 {
1157     int xpix;
1158     m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
1159     int x;
1160     m_owner->GetViewStart( &x, NULL );
1161
1162     // account for the horz scrollbar offset
1163     dc.SetDeviceOrigin( -x * xpix, 0 );
1164 }
1165
1166 void wxTreeListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
1167 {
1168 #ifdef __WXGTK__
1169     wxClientDC dc( this );
1170 #else
1171     wxPaintDC dc( this );
1172 #endif
1173
1174     PrepareDC( dc );
1175     AdjustDC( dc );
1176     dc.SetFont( GetFont() );
1177
1178     // width and height of the entire header window
1179     int w, h;
1180     GetClientSize( &w, &h );
1181     m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1182     dc.SetBackgroundMode(wxTRANSPARENT);
1183
1184     // do *not* use the listctrl colour for headers - one day we will have a
1185     // function to set it separately
1186     //dc.SetTextForeground( *wxBLACK );
1187 #if !wxCHECK_VERSION(2, 5, 0)
1188     dc.SetTextForeground (wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
1189 #else
1190     dc.SetTextForeground (wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ));
1191 #endif
1192
1193     int x = HEADER_OFFSET_X;
1194
1195     int numColumns = GetColumnCount();
1196     for ( int i = 0; i < numColumns && x < w; i++ )
1197     {
1198         if (!IsColumnShown (i)) continue; // do next colume if not shown
1199
1200         wxTreeListColumnInfo& column = GetColumn(i);
1201         int wCol = column.GetWidth();
1202
1203         // the width of the rect to draw: make it smaller to fit entirely
1204         // inside the column rect
1205         int cw = wCol - 2;
1206
1207         dc.SetPen( *wxWHITE_PEN );
1208         DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 );
1209
1210         // if we have an image, draw it on the right of the label
1211         int image = column.GetImage(); //item.m_image;
1212         int ix = -2, iy = 0;
1213         wxImageList* imageList = m_owner->GetImageList();
1214         if ((image != -1) && imageList) {
1215             imageList->GetSize (image, ix, iy);
1216         }
1217
1218         // extra margins around the text label
1219         int text_width = 0;
1220         int text_x = x;
1221         int image_offset = cw - ix - 1;
1222
1223         switch(column.GetAlignment()) {
1224         case wxALIGN_LEFT:
1225             text_x += EXTRA_WIDTH;
1226             cw -= ix + 2;
1227             break;
1228         case wxALIGN_RIGHT:
1229             dc.GetTextExtent (column.GetText(), &text_width, NULL);
1230             text_x += cw - text_width - EXTRA_WIDTH - MARGIN;
1231             image_offset = 0;
1232             break;
1233         case wxALIGN_CENTER:
1234             dc.GetTextExtent(column.GetText(), &text_width, NULL);
1235             text_x += (cw - text_width)/2 + ix + 2;
1236             image_offset = (cw - text_width - ix - 2)/2 - MARGIN;
1237             break;
1238         }
1239
1240         // draw the image
1241         if ((image != -1) && imageList) {
1242             imageList->Draw (image, dc, x + image_offset/*cw - ix - 1*/,
1243                              HEADER_OFFSET_Y + (h - 4 - iy)/2,
1244                              wxIMAGELIST_DRAW_TRANSPARENT);
1245         }
1246
1247         // draw the text clipping it so that it doesn't overwrite the column boundary
1248         wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 );
1249         dc.DrawText (column.GetText(), text_x, HEADER_OFFSET_Y + EXTRA_HEIGHT );
1250
1251         // next column
1252         x += wCol;
1253     }
1254
1255     int more_w = m_owner->GetSize().x - x - HEADER_OFFSET_X;
1256     if (more_w > 0) {
1257         DoDrawRect (&dc, x, HEADER_OFFSET_Y, more_w, h-2 );
1258     }
1259
1260 }
1261
1262 void wxTreeListHeaderWindow::DrawCurrent()
1263 {
1264     int x1 = m_currentX;
1265     int y1 = 0;
1266     ClientToScreen (&x1, &y1);
1267
1268     int x2 = m_currentX-1;
1269 #ifdef __WXMSW__
1270     ++x2; // but why ????
1271 #endif
1272     int y2 = 0;
1273     m_owner->GetClientSize( NULL, &y2 );
1274     m_owner->ClientToScreen( &x2, &y2 );
1275
1276     wxScreenDC dc;
1277     dc.SetLogicalFunction (wxINVERT);
1278     dc.SetPen (wxPen (*wxBLACK, 2, wxSOLID));
1279     dc.SetBrush (*wxTRANSPARENT_BRUSH);
1280
1281     AdjustDC(dc);
1282     dc.DrawLine (x1, y1, x2, y2);
1283     dc.SetLogicalFunction (wxCOPY);
1284     dc.SetPen (wxNullPen);
1285     dc.SetBrush (wxNullBrush);
1286 }
1287
1288 void wxTreeListHeaderWindow::OnMouse (wxMouseEvent &event) {
1289
1290     // we want to work with logical coords
1291     int x;
1292     m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
1293     int y = event.GetY();
1294
1295     if (m_isDragging) {
1296
1297         SendListEvent (wxEVT_COMMAND_LIST_COL_DRAGGING, event.GetPosition());
1298
1299         // we don't draw the line beyond our window, but we allow dragging it
1300         // there
1301         int w = 0;
1302         GetClientSize( &w, NULL );
1303         m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1304         w -= 6;
1305
1306         // erase the line if it was drawn
1307         if (m_currentX < w) DrawCurrent();
1308
1309         if (event.ButtonUp()) {
1310             m_isDragging = false;
1311             if (HasCapture()) ReleaseMouse();
1312             m_dirty = true;
1313             SetColumnWidth (m_column, m_currentX - m_minX);
1314             Refresh();
1315             SendListEvent (wxEVT_COMMAND_LIST_COL_END_DRAG, event.GetPosition());
1316         }else{
1317             m_currentX = wxMax (m_minX + 7, x);
1318
1319             // draw in the new location
1320             if (m_currentX < w) DrawCurrent();
1321         }
1322
1323     }else{ // not dragging
1324
1325         m_minX = 0;
1326         bool hit_border = false;
1327
1328         // end of the current column
1329         int xpos = 0;
1330
1331         // find the column where this event occured
1332         int countCol = GetColumnCount();
1333         for (int column = 0; column < countCol; column++) {
1334             if (!IsColumnShown (column)) continue; // do next if not shown
1335
1336             xpos += GetColumnWidth (column);
1337             m_column = column;
1338             if ((abs (x-xpos) < 3) && (y < 22)) {
1339                 // near the column border
1340                 hit_border = true;
1341                 break;
1342             }
1343
1344             if (x < xpos) {
1345                 // inside the column
1346                 break;
1347             }
1348
1349             m_minX = xpos;
1350         }
1351
1352         if (event.LeftDown() || event.RightUp()) {
1353             if (hit_border && event.LeftDown()) {
1354                 m_isDragging = true;
1355                 CaptureMouse();
1356                 m_currentX = x;
1357                 DrawCurrent();
1358                 SendListEvent (wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, event.GetPosition());
1359             }else{ // click on a column
1360                 wxEventType evt = event.LeftDown()? wxEVT_COMMAND_LIST_COL_CLICK:
1361                                                     wxEVT_COMMAND_LIST_COL_RIGHT_CLICK;
1362                 SendListEvent (evt, event.GetPosition());
1363             }
1364         }else if (event.LeftDClick() && hit_border) {
1365             SetColumnWidth (m_column, m_owner->GetBestColumnWidth (m_column));
1366             Refresh();
1367
1368         }else if (event.Moving()) {
1369             bool setCursor;
1370             if (hit_border) {
1371                 setCursor = m_currentCursor == wxSTANDARD_CURSOR;
1372                 m_currentCursor = m_resizeCursor;
1373             }else{
1374                 setCursor = m_currentCursor != wxSTANDARD_CURSOR;
1375                 m_currentCursor = wxSTANDARD_CURSOR;
1376             }
1377             if (setCursor) SetCursor (*m_currentCursor);
1378         }
1379
1380     }
1381 }
1382
1383 void wxTreeListHeaderWindow::OnSetFocus (wxFocusEvent &WXUNUSED(event)) {
1384     m_owner->SetFocus();
1385 }
1386
1387 void wxTreeListHeaderWindow::SendListEvent (wxEventType type, wxPoint pos) {
1388     wxWindow *parent = GetParent();
1389     wxListEvent le (type, parent->GetId());
1390     le.SetEventObject (parent);
1391     le.m_pointDrag = pos;
1392
1393     // the position should be relative to the parent window, not
1394     // this one for compatibility with MSW and common sense: the
1395     // user code doesn't know anything at all about this header
1396     // window, so why should it get positions relative to it?
1397     le.m_pointDrag.y -= GetSize().y;
1398     le.m_col = m_column;
1399     parent->GetEventHandler()->ProcessEvent (le);
1400 }
1401
1402 void wxTreeListHeaderWindow::AddColumn (const wxTreeListColumnInfo& colInfo) {
1403     m_columns.Add (colInfo);
1404     m_total_col_width += colInfo.GetWidth();
1405     m_owner->AdjustMyScrollbars();
1406     m_owner->m_dirty = true;
1407 }
1408
1409 void wxTreeListHeaderWindow::SetColumnWidth (int column, int width) {
1410     wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1411     m_total_col_width -= m_columns[column].GetWidth();
1412     m_columns[column].SetWidth(width);
1413     m_total_col_width += width;
1414     m_owner->AdjustMyScrollbars();
1415     m_owner->m_dirty = true;
1416 }
1417
1418 void wxTreeListHeaderWindow::InsertColumn (int before, const wxTreeListColumnInfo& colInfo) {
1419     wxCHECK_RET ((before >= 0) && (before < GetColumnCount()), _T("Invalid column"));
1420     m_columns.Insert (colInfo, before);
1421     m_total_col_width += colInfo.GetWidth();
1422     m_owner->AdjustMyScrollbars();
1423     m_owner->m_dirty = true;
1424 }
1425
1426 void wxTreeListHeaderWindow::RemoveColumn (int column) {
1427     wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1428     m_total_col_width -= m_columns[column].GetWidth();
1429     m_columns.RemoveAt (column);
1430     m_owner->AdjustMyScrollbars();
1431     m_owner->m_dirty = true;
1432 }
1433
1434 void wxTreeListHeaderWindow::SetColumn (int column, const wxTreeListColumnInfo& info) {
1435     wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1436     int w = m_columns[column].GetWidth();
1437     m_columns[column] = info;
1438     if (w != info.GetWidth()) {
1439         m_total_col_width += info.GetWidth() - w;
1440         m_owner->AdjustMyScrollbars();
1441     }
1442     m_owner->m_dirty = true;
1443 }
1444
1445 // ---------------------------------------------------------------------------
1446 // wxTreeListItem
1447 // ---------------------------------------------------------------------------
1448
1449 wxTreeListItem::wxTreeListItem (wxTreeListMainWindow *owner,
1450                                 wxTreeListItem *parent,
1451                                 const wxArrayString& text,
1452                                 int image, int selImage,
1453                                 wxTreeItemData *data)
1454               : m_text (text) {
1455
1456     m_images[wxTreeItemIcon_Normal] = image;
1457     m_images[wxTreeItemIcon_Selected] = selImage;
1458     m_images[wxTreeItemIcon_Expanded] = NO_IMAGE;
1459     m_images[wxTreeItemIcon_SelectedExpanded] = NO_IMAGE;
1460
1461     m_data = data;
1462     m_x = 0;
1463     m_y = 0;
1464     m_text_x = 0;
1465
1466     m_isCollapsed = true;
1467     m_hasHilight = false;
1468     m_hasPlus = false;
1469     m_isBold = false;
1470
1471     m_owner = owner;
1472     m_parent = parent;
1473
1474     m_attr = (wxTreeItemAttr *)NULL;
1475     m_ownsAttr = false;
1476
1477     // We don't know the height here yet.
1478     m_width = 0;
1479     m_height = 0;
1480 }
1481
1482 wxTreeListItem::~wxTreeListItem() {
1483     delete m_data;
1484     if (m_ownsAttr) delete m_attr;
1485
1486     wxASSERT_MSG( m_children.IsEmpty(), _T("please call DeleteChildren() before destructor"));
1487 }
1488
1489 void wxTreeListItem::DeleteChildren (wxTreeListMainWindow *tree) {
1490     size_t count = m_children.Count();
1491     for (size_t n = 0; n < count; n++) {
1492         wxTreeListItem *child = m_children[n];
1493         if (tree) {
1494             tree->SendDeleteEvent (child);
1495             // LG 
1496             tree->RemoveFromSelection(child);
1497             /*
1498             if (child->IsSelected())
1499               {
1500                 tree->Unselect(child);
1501               }
1502             */
1503             //            if (tree->m_selectItem == child) tree->m_selectItem = (wxTreeListItem*)NULL;
1504         }
1505         child->DeleteChildren (tree);
1506         delete child;
1507     }
1508     m_children.Empty();
1509 }
1510
1511 void wxTreeListItem::SetText (const wxString &text) {
1512     if (m_text.GetCount() > 0) {
1513         m_text[0] = text;
1514     }else{
1515         m_text.Add (text);
1516     }
1517 }
1518
1519 size_t wxTreeListItem::GetChildrenCount (bool recursively) const {
1520     size_t count = m_children.Count();
1521     if (!recursively) return count;
1522
1523     size_t total = count;
1524     for (size_t n = 0; n < count; ++n) {
1525         total += m_children[n]->GetChildrenCount();
1526     }
1527     return total;
1528 }
1529
1530 void wxTreeListItem::GetSize (int &x, int &y, const wxTreeListMainWindow *theButton) {
1531     int bottomY = m_y + theButton->GetLineHeight (this);
1532     if (y < bottomY) y = bottomY;
1533     int width = m_x +  m_width;
1534     if ( x < width ) x = width;
1535
1536     if (IsExpanded()) {
1537         size_t count = m_children.Count();
1538         for (size_t n = 0; n < count; ++n ) {
1539             m_children[n]->GetSize (x, y, theButton);
1540         }
1541     }
1542 }
1543
1544 wxTreeListItem *wxTreeListItem::HitTest (const wxPoint& point,
1545                                          const wxTreeListMainWindow *theCtrl,
1546                                          int &flags, int& column, int level) {
1547
1548     // for a hidden root node, don't evaluate it, but do evaluate children
1549     if (!theCtrl->HasFlag(wxTR_HIDE_ROOT) || (level > 0)) {
1550
1551         // reset any previous hit infos
1552         flags = 0;
1553         column = -1;
1554         wxTreeListHeaderWindow* header_win = theCtrl->m_owner->GetHeaderWindow();
1555
1556         // check for right of all columns (outside)
1557         if (point.x > header_win->GetWidth()) return (wxTreeListItem*) NULL;
1558
1559         // evaluate if y-pos is okay
1560         int h = theCtrl->GetLineHeight (this);
1561         if ((point.y >= m_y) && (point.y <= m_y + h)) {
1562
1563             int maincol = theCtrl->GetMainColumn();
1564
1565             // check for above/below middle
1566             int y_mid = m_y + h/2;
1567             if (point.y < y_mid) {
1568                 flags |= wxTREE_HITTEST_ONITEMUPPERPART;
1569             }else{
1570                 flags |= wxTREE_HITTEST_ONITEMLOWERPART;
1571             }
1572
1573             // check for button hit
1574             if (HasPlus() && theCtrl->HasButtons()) {
1575                 int bntX = m_x - theCtrl->m_btnWidth2;
1576                 int bntY = y_mid - theCtrl->m_btnHeight2;
1577                 if ((point.x >= bntX) && (point.x <= (bntX + theCtrl->m_btnWidth)) &&
1578                     (point.y >= bntY) && (point.y <= (bntY + theCtrl->m_btnHeight))) {
1579                     flags |= wxTREE_HITTEST_ONITEMBUTTON;
1580                     column = maincol;
1581                     return this;
1582                 }
1583             }
1584
1585             // check for image hit
1586             if (theCtrl->m_imgWidth > 0) {
1587                 int imgX = m_text_x - theCtrl->m_imgWidth - MARGIN;
1588                 int imgY = y_mid - theCtrl->m_imgHeight2;
1589                 if ((point.x >= imgX) && (point.x <= (imgX + theCtrl->m_imgWidth)) &&
1590                     (point.y >= imgY) && (point.y <= (imgY + theCtrl->m_imgHeight))) {
1591                     flags |= wxTREE_HITTEST_ONITEMICON;
1592                     column = maincol;
1593                     return this;
1594                 }
1595             }
1596
1597             // check for label hit
1598             if ((point.x >= m_text_x) && (point.x <= (m_text_x + m_width))) {
1599                 flags |= wxTREE_HITTEST_ONITEMLABEL;
1600                 column = maincol;
1601                 return this;
1602             }
1603
1604             // check for indent hit after button and image hit
1605             if (point.x < m_x) {
1606                 flags |= wxTREE_HITTEST_ONITEMINDENT;
1607                 column = -1; // considered not belonging to main column
1608                 return this;
1609             }
1610
1611             // check for right of label
1612             int end = 0;
1613             for (int i = 0; i <= maincol; ++i) end += header_win->GetColumnWidth (i);
1614             if ((point.x > (m_text_x + m_width)) && (point.x <= end)) {
1615                 flags |= wxTREE_HITTEST_ONITEMRIGHT;
1616                 column = -1; // considered not belonging to main column
1617                 return this;
1618             }
1619
1620             // else check for each column except main
1621             int x = 0;
1622             for (int j = 0; j < theCtrl->GetColumnCount(); ++j) {
1623                 if (!header_win->IsColumnShown(j)) continue;
1624                 int w = header_win->GetColumnWidth (j);
1625                 if ((j != maincol) && (point.x >= x && point.x < x+w)) {
1626                     flags |= wxTREE_HITTEST_ONITEMCOLUMN;
1627                     column = j;
1628                     return this;
1629                 }
1630                 x += w;
1631             }
1632
1633             // no special flag or column found
1634             return this;
1635
1636         }
1637
1638         // if children not expanded, return no item
1639         if (!IsExpanded()) return (wxTreeListItem*) NULL;
1640     }
1641
1642     // in any case evaluate children
1643     wxTreeListItem *child;
1644     size_t count = m_children.Count();
1645     for (size_t n = 0; n < count; n++) {
1646         child = m_children[n]->HitTest (point, theCtrl, flags, column, level+1);
1647         if (child) return child;
1648     }
1649
1650     // not found
1651     return (wxTreeListItem*) NULL;
1652 }
1653
1654 int wxTreeListItem::GetCurrentImage() const {
1655     int image = NO_IMAGE;
1656     if (IsExpanded()) {
1657         if (IsSelected()) {
1658             image = GetImage (wxTreeItemIcon_SelectedExpanded);
1659         }else{
1660             image = GetImage (wxTreeItemIcon_Expanded);
1661         }
1662     }else{ // not expanded
1663         if (IsSelected()) {
1664             image = GetImage (wxTreeItemIcon_Selected);
1665         }else{
1666             image = GetImage (wxTreeItemIcon_Normal);
1667         }
1668     }
1669
1670     // maybe it doesn't have the specific image, try the default one instead
1671     if (image == NO_IMAGE) image = GetImage();
1672
1673     return image;
1674 }
1675
1676 // ---------------------------------------------------------------------------
1677 // wxTreeListMainWindow implementation
1678 // ---------------------------------------------------------------------------
1679
1680 IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow, wxScrolledWindow)
1681
1682 BEGIN_EVENT_TABLE(wxTreeListMainWindow, wxScrolledWindow)
1683     EVT_PAINT          (wxTreeListMainWindow::OnPaint)
1684     EVT_MOUSE_EVENTS   (wxTreeListMainWindow::OnMouse)
1685     EVT_CHAR           (wxTreeListMainWindow::OnChar)
1686     EVT_SET_FOCUS      (wxTreeListMainWindow::OnSetFocus)
1687     EVT_KILL_FOCUS     (wxTreeListMainWindow::OnKillFocus)
1688     EVT_IDLE           (wxTreeListMainWindow::OnIdle)
1689     EVT_SCROLLWIN      (wxTreeListMainWindow::OnScroll)
1690 END_EVENT_TABLE()
1691
1692
1693 // ---------------------------------------------------------------------------
1694 // construction/destruction
1695 // ---------------------------------------------------------------------------
1696
1697 void wxTreeListMainWindow::Init() {
1698
1699     m_rootItem = (wxTreeListItem*)NULL;
1700     m_curItem = (wxTreeListItem*)NULL;
1701     m_shiftItem = (wxTreeListItem*)NULL;
1702     m_editItem = (wxTreeListItem*)NULL;
1703     // LG 
1704     //    m_selectItem = (wxTreeListItem*)NULL;
1705
1706     m_curColumn = -1; // no current column
1707
1708     m_hasFocus = false;
1709     m_dirty = false;
1710
1711     m_lineHeight = LINEHEIGHT;
1712     m_indent = MININDENT; // min. indent
1713     m_linespacing = 4;
1714
1715 #if !wxCHECK_VERSION(2, 5, 0)
1716     m_hilightBrush = new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHT), wxSOLID);
1717     m_hilightUnfocusedBrush = new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNSHADOW), wxSOLID);
1718 #else
1719     m_hilightBrush = new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHT), wxSOLID);
1720     m_hilightUnfocusedBrush = new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNSHADOW), wxSOLID);
1721 #endif
1722
1723     m_imageListNormal = (wxImageList *) NULL;
1724     m_imageListButtons = (wxImageList *) NULL;
1725     m_imageListState = (wxImageList *) NULL;
1726     m_ownsImageListNormal = m_ownsImageListButtons =
1727     m_ownsImageListState = false;
1728
1729     m_imgWidth = 0, m_imgWidth2 = 0;
1730     m_imgHeight = 0, m_imgHeight2 = 0;
1731     m_btnWidth = 0, m_btnWidth2 = 0;
1732     m_btnHeight = 0, m_btnHeight2 = 0;
1733
1734     m_dragCount = 0;
1735     m_isDragging = false;
1736     m_dragTimer = new wxTimer (this, -1);
1737     m_dragItem = (wxTreeListItem*)NULL;
1738
1739     m_renameTimer = new wxTreeListRenameTimer (this);
1740     m_lastOnSame = false;
1741     m_left_down_selection = false;
1742
1743     m_findTimer = new wxTimer (this, -1);
1744
1745 #if defined( __WXMAC__ ) && defined(__WXMAC_CARBON__)
1746     m_normalFont.MacCreateThemeFont (kThemeViewsFont);
1747 #else
1748     m_normalFont = wxSystemSettings::GetFont (wxSYS_DEFAULT_GUI_FONT);
1749 #endif
1750     m_boldFont = wxFont( m_normalFont.GetPointSize(),
1751                          m_normalFont.GetFamily(),
1752                          m_normalFont.GetStyle(),
1753                          wxBOLD,
1754                          m_normalFont.GetUnderlined(),
1755                          m_normalFont.GetFaceName(),
1756                          m_normalFont.GetEncoding());
1757 }
1758
1759 bool wxTreeListMainWindow::Create (wxTreeListCtrl *parent,
1760                                    wxWindowID id,
1761                                    const wxPoint& pos,
1762                                    const wxSize& size,
1763                                    long style,
1764                                    const wxValidator &validator,
1765                                    const wxString& name) {
1766
1767 #ifdef __WXMAC__
1768     if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS;
1769     if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS;
1770     style &= ~wxTR_LINES_AT_ROOT;
1771     style |= wxTR_NO_LINES;
1772
1773     int major,minor;
1774     wxGetOsVersion( &major, &minor );
1775     if (major < 10) style |= wxTR_ROW_LINES;
1776 #endif
1777
1778     wxScrolledWindow::Create (parent, id, pos, size, style|wxHSCROLL|wxVSCROLL, name);
1779
1780 #if wxUSE_VALIDATORS
1781     SetValidator(validator);
1782 #endif
1783
1784 #if !wxCHECK_VERSION(2, 5, 0)
1785     SetBackgroundColour (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_LISTBOX));
1786 #else
1787     SetBackgroundColour (wxSystemSettings::GetColour (wxSYS_COLOUR_LISTBOX));
1788 #endif
1789
1790 #ifdef __WXMSW__
1791     {
1792         int i, j;
1793         wxBitmap bmp(8, 8);
1794         wxMemoryDC bdc;
1795         bdc.SelectObject(bmp);
1796         bdc.SetPen(*wxGREY_PEN);
1797         bdc.DrawRectangle(-1, -1, 10, 10);
1798         for (i = 0; i < 8; i++) {
1799             for (j = 0; j < 8; j++) {
1800                 if (!((i + j) & 1)) {
1801                     bdc.DrawPoint(i, j);
1802                 }
1803             }
1804         }
1805
1806         m_dottedPen = wxPen(bmp, 1);
1807     }
1808 #else
1809 //?    m_dottedPen = wxPen( *wxGREY_PEN, 1, wxDOT );  // too slow under XFree86
1810     m_dottedPen = wxPen( _T("grey"), 0, 0 ); // Bitmap based pen is not supported by GTK!
1811 #endif
1812
1813     m_owner = parent;
1814     m_main_column = 0;
1815
1816     return true;
1817 }
1818
1819 wxTreeListMainWindow::~wxTreeListMainWindow() {
1820     delete m_hilightBrush;
1821     delete m_hilightUnfocusedBrush;
1822
1823     delete m_dragTimer;
1824     delete m_renameTimer;
1825     delete m_findTimer;
1826     if (m_ownsImageListNormal) delete m_imageListNormal;
1827     if (m_ownsImageListState) delete m_imageListState;
1828     if (m_ownsImageListButtons) delete m_imageListButtons;
1829
1830     DeleteRoot();
1831 }
1832
1833
1834 //-----------------------------------------------------------------------------
1835 // accessors
1836 //-----------------------------------------------------------------------------
1837
1838 size_t wxTreeListMainWindow::GetCount() const {
1839     return m_rootItem == NULL? 0: m_rootItem->GetChildrenCount();
1840 }
1841
1842 void wxTreeListMainWindow::SetIndent (unsigned int indent) {
1843     m_indent = wxMax (MININDENT, indent);
1844     m_dirty = true;
1845 }
1846
1847 void wxTreeListMainWindow::SetLineSpacing (unsigned int spacing) {
1848     m_linespacing = spacing;
1849     m_dirty = true;
1850     CalculateLineHeight();
1851 }
1852
1853 size_t wxTreeListMainWindow::GetChildrenCount (const wxTreeItemId& item,
1854                                                bool recursively) {
1855     wxCHECK_MSG (item.IsOk(), 0u, _T("invalid tree item"));
1856     return ((wxTreeListItem*)item.m_pItem)->GetChildrenCount (recursively);
1857 }
1858
1859 void wxTreeListMainWindow::SetWindowStyle (const long styles) {
1860     // right now, just sets the styles.  Eventually, we may
1861     // want to update the inherited styles, but right now
1862     // none of the parents has updatable styles
1863     m_windowStyle = styles;
1864     m_dirty = true;
1865 }
1866
1867 //-----------------------------------------------------------------------------
1868 // functions to work with tree items
1869 //-----------------------------------------------------------------------------
1870
1871 int wxTreeListMainWindow::GetItemImage (const wxTreeItemId& item, int column,
1872                                         wxTreeItemIcon which) const {
1873     wxCHECK_MSG (item.IsOk(), -1, _T("invalid tree item"));
1874     return ((wxTreeListItem*) item.m_pItem)->GetImage (column, which);
1875 }
1876
1877 wxTreeItemData *wxTreeListMainWindow::GetItemData (const wxTreeItemId& item) const {
1878     wxCHECK_MSG (item.IsOk(), NULL, _T("invalid tree item"));
1879     return ((wxTreeListItem*) item.m_pItem)->GetData();
1880 }
1881
1882 bool wxTreeListMainWindow::GetItemBold (const wxTreeItemId& item) const {
1883     wxCHECK_MSG(item.IsOk(), false, _T("invalid tree item"));
1884     return ((wxTreeListItem *)item.m_pItem)->IsBold();
1885 }
1886
1887 wxColour wxTreeListMainWindow::GetItemTextColour (const wxTreeItemId& item) const {
1888     wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
1889     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1890     return pItem->Attr().GetTextColour();
1891 }
1892
1893 wxColour wxTreeListMainWindow::GetItemBackgroundColour (const wxTreeItemId& item) const {
1894     wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
1895     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1896     return pItem->Attr().GetBackgroundColour();
1897 }
1898
1899 wxFont wxTreeListMainWindow::GetItemFont (const wxTreeItemId& item) const {
1900     wxCHECK_MSG (item.IsOk(), wxNullFont, _T("invalid tree item"));
1901     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1902     return pItem->Attr().GetFont();
1903 }
1904
1905 void wxTreeListMainWindow::SetItemImage (const wxTreeItemId& item, int column,
1906                                          int image, wxTreeItemIcon which) {
1907     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1908     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1909     pItem->SetImage (column, image, which);
1910     wxClientDC dc (this);
1911     CalculateSize (pItem, dc);
1912     RefreshLine (pItem);
1913 }
1914
1915 void wxTreeListMainWindow::SetItemData (const wxTreeItemId& item,
1916                                         wxTreeItemData *data) {
1917     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1918     ((wxTreeListItem*) item.m_pItem)->SetData(data);
1919 }
1920
1921 void wxTreeListMainWindow::SetItemHasChildren (const wxTreeItemId& item,
1922                                                bool has) {
1923     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1924     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1925     pItem->SetHasPlus (has);
1926     RefreshLine (pItem);
1927 }
1928
1929 void wxTreeListMainWindow::SetItemBold (const wxTreeItemId& item, bool bold) {
1930     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1931     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1932     if (pItem->IsBold() != bold) { // avoid redrawing if no real change
1933         pItem->SetBold (bold);
1934         RefreshLine (pItem);
1935     }
1936 }
1937
1938 void wxTreeListMainWindow::SetItemTextColour (const wxTreeItemId& item,
1939                                               const wxColour& colour) {
1940     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1941     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1942     pItem->Attr().SetTextColour (colour);
1943     RefreshLine (pItem);
1944 }
1945
1946 void wxTreeListMainWindow::SetItemBackgroundColour (const wxTreeItemId& item,
1947                                                     const wxColour& colour) {
1948     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1949     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1950     pItem->Attr().SetBackgroundColour (colour);
1951     RefreshLine (pItem);
1952 }
1953
1954 void wxTreeListMainWindow::SetItemFont (const wxTreeItemId& item,
1955                                         const wxFont& font) {
1956     wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
1957     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1958     pItem->Attr().SetFont (font);
1959     RefreshLine (pItem);
1960 }
1961
1962 bool wxTreeListMainWindow::SetFont (const wxFont &font) {
1963     wxScrolledWindow::SetFont (font);
1964     m_normalFont = font;
1965     m_boldFont = wxFont (m_normalFont.GetPointSize(),
1966                          m_normalFont.GetFamily(),
1967                          m_normalFont.GetStyle(),
1968                          wxBOLD,
1969                          m_normalFont.GetUnderlined(),
1970                          m_normalFont.GetFaceName());
1971     CalculateLineHeight();
1972     return true;
1973 }
1974
1975
1976 // ----------------------------------------------------------------------------
1977 // item status inquiries
1978 // ----------------------------------------------------------------------------
1979
1980 bool wxTreeListMainWindow::IsVisible (const wxTreeItemId& item, bool fullRow) const {
1981     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
1982
1983     // An item is only visible if it's not a descendant of a collapsed item
1984     wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem;
1985     wxTreeListItem* parent = pItem->GetItemParent();
1986     while (parent) {
1987         if (parent == m_rootItem && HasFlag(wxTR_HIDE_ROOT)) break;
1988         if (!parent->IsExpanded()) return false;
1989         parent = parent->GetItemParent();
1990     }
1991
1992     wxSize clientSize = GetClientSize();
1993     wxRect rect;
1994     if ((!GetBoundingRect (item, rect)) ||
1995         ((!fullRow && rect.GetWidth() == 0) || rect.GetHeight() == 0) ||
1996         (rect.GetBottom() < 0 || rect.GetTop() > clientSize.y) ||
1997         (!fullRow && (rect.GetRight() < 0 || rect.GetLeft() > clientSize.x))) return false;
1998
1999     return true;
2000 }
2001
2002 bool wxTreeListMainWindow::HasChildren (const wxTreeItemId& item) const {
2003     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2004
2005     // consider that the item does have children if it has the "+" button: it
2006     // might not have them (if it had never been expanded yet) but then it
2007     // could have them as well and it's better to err on this side rather than
2008     // disabling some operations which are restricted to the items with
2009     // children for an item which does have them
2010     return ((wxTreeListItem*) item.m_pItem)->HasPlus();
2011 }
2012
2013 bool wxTreeListMainWindow::IsExpanded (const wxTreeItemId& item) const {
2014     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2015     return ((wxTreeListItem*) item.m_pItem)->IsExpanded();
2016 }
2017
2018 bool wxTreeListMainWindow::IsSelected (const wxTreeItemId& item) const {
2019     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2020     return ((wxTreeListItem*) item.m_pItem)->IsSelected();
2021 }
2022
2023 bool wxTreeListMainWindow::IsBold (const wxTreeItemId& item) const {
2024     wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2025     return ((wxTreeListItem*) item.m_pItem)->IsBold();
2026 }
2027
2028 // ----------------------------------------------------------------------------
2029 // navigation
2030 // ----------------------------------------------------------------------------
2031
2032 wxTreeItemId wxTreeListMainWindow::GetItemParent (const wxTreeItemId& item) const {
2033     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2034     return ((wxTreeListItem*) item.m_pItem)->GetItemParent();
2035 }
2036
2037 #if !wxCHECK_VERSION(2, 5, 0)
2038 wxTreeItemId wxTreeListMainWindow::GetFirstChild (const wxTreeItemId& item,
2039                                                   long& cookie) const {
2040 #else
2041 wxTreeItemId wxTreeListMainWindow::GetFirstChild (const wxTreeItemId& item,
2042                                                   wxTreeItemIdValue& cookie) const {
2043 #endif
2044     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2045     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2046     cookie = 0;
2047     return (!children.IsEmpty())? wxTreeItemId(children.Item(0)): wxTreeItemId();
2048 }
2049
2050 #if !wxCHECK_VERSION(2, 5, 0)
2051 wxTreeItemId wxTreeListMainWindow::GetNextChild (const wxTreeItemId& item,
2052                                                  long& cookie) const {
2053 #else
2054 wxTreeItemId wxTreeListMainWindow::GetNextChild (const wxTreeItemId& item,
2055                                                  wxTreeItemIdValue& cookie) const {
2056 #endif
2057     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2058     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2059     // it's ok to cast cookie to long, we never have indices which overflow "void*"
2060     long *pIndex = ((long*)&cookie);
2061     return ((*pIndex)+1 < (long)children.Count())? wxTreeItemId(children.Item(++(*pIndex))): wxTreeItemId();
2062 }
2063
2064 #if !wxCHECK_VERSION(2, 5, 0)
2065 wxTreeItemId wxTreeListMainWindow::GetPrevChild (const wxTreeItemId& item,
2066                                                  long& cookie) const {
2067 #else
2068 wxTreeItemId wxTreeListMainWindow::GetPrevChild (const wxTreeItemId& item,
2069                                                  wxTreeItemIdValue& cookie) const {
2070 #endif
2071     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2072     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2073     // it's ok to cast cookie to long, we never have indices which overflow "void*"
2074     long *pIndex = (long*)&cookie;
2075     return ((*pIndex)-1 >= 0)? wxTreeItemId(children.Item(--(*pIndex))): wxTreeItemId();
2076 }
2077
2078 #if !wxCHECK_VERSION(2, 5, 0)
2079 wxTreeItemId wxTreeListMainWindow::GetLastChild (const wxTreeItemId& item,
2080                                                  long& cookie) const {
2081 #else
2082 wxTreeItemId wxTreeListMainWindow::GetLastChild (const wxTreeItemId& item,
2083                                                  wxTreeItemIdValue& cookie) const {
2084 #endif
2085     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2086     wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2087     // it's ok to cast cookie to long, we never have indices which overflow "void*"
2088     long *pIndex = ((long*)&cookie);
2089     (*pIndex) = children.Count();
2090     return (!children.IsEmpty())? wxTreeItemId(children.Last()): wxTreeItemId();
2091 }
2092
2093 wxTreeItemId wxTreeListMainWindow::GetNextSibling (const wxTreeItemId& item) const {
2094     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2095
2096     // get parent
2097     wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
2098     wxTreeListItem *parent = i->GetItemParent();
2099     if (!parent) return wxTreeItemId(); // root item doesn't have any siblings
2100
2101     // get index
2102     wxArrayTreeListItems& siblings = parent->GetChildren();
2103     size_t index = siblings.Index (i);
2104     wxASSERT (index != wxNOT_FOUND); // I'm not a child of my parent?
2105     return (index < siblings.Count()-1)? wxTreeItemId(siblings[index+1]): wxTreeItemId();
2106 }
2107
2108 wxTreeItemId wxTreeListMainWindow::GetPrevSibling (const wxTreeItemId& item) const {
2109     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2110
2111     // get parent
2112     wxTreeListItem *i = (wxTreeListItem*) item.m_pItem;
2113     wxTreeListItem *parent = i->GetItemParent();
2114     if (!parent) return wxTreeItemId(); // root item doesn't have any siblings
2115
2116     // get index
2117     wxArrayTreeListItems& siblings = parent->GetChildren();
2118     size_t index = siblings.Index(i);
2119     wxASSERT (index != wxNOT_FOUND); // I'm not a child of my parent?
2120     return (index >= 1)? wxTreeItemId(siblings[index-1]): wxTreeItemId();
2121 }
2122
2123 // Only for internal use right now, but should probably be public
2124 wxTreeItemId wxTreeListMainWindow::GetNext (const wxTreeItemId& item, bool fulltree) const {
2125     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2126
2127     // if there are any children, return first child
2128     if (fulltree || ((wxTreeListItem*)item.m_pItem)->IsExpanded()) {
2129         wxArrayTreeListItems& children = ((wxTreeListItem*)item.m_pItem)->GetChildren();
2130         if (children.GetCount() > 0) return children.Item (0);
2131     }
2132
2133     // get sibling of this item or of the ancestors instead
2134     wxTreeItemId next;
2135     wxTreeItemId parent = item;
2136     do {
2137         next = GetNextSibling (parent);
2138         parent = GetItemParent (parent);
2139     } while (!next.IsOk() && parent.IsOk());
2140     return next;
2141 }
2142
2143 // Only for internal use right now, but should probably be public
2144 wxTreeItemId wxTreeListMainWindow::GetPrev (const wxTreeItemId& item, bool fulltree) const {
2145     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2146
2147     // if there are any children, return last child
2148     if (fulltree || ((wxTreeListItem*)item.m_pItem)->IsExpanded()) {
2149         wxArrayTreeListItems& children = ((wxTreeListItem*)item.m_pItem)->GetChildren();
2150         if (children.GetCount() > 0) return children.Item (children.GetCount()-1);
2151     }
2152
2153     // get sibling of this item or of the ancestors instead
2154     wxTreeItemId next;
2155     wxTreeItemId parent = item;
2156     do {
2157         next = GetPrevSibling (parent);
2158         parent = GetItemParent (parent);
2159     } while (!next.IsOk() && parent.IsOk());
2160     return next;
2161 }
2162
2163 wxTreeItemId wxTreeListMainWindow::GetFirstExpandedItem() const {
2164     return GetNextExpanded (GetRootItem());
2165 }
2166
2167 wxTreeItemId wxTreeListMainWindow::GetNextExpanded (const wxTreeItemId& item) const {
2168     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2169     return GetNext (item, false);
2170 }
2171
2172 wxTreeItemId wxTreeListMainWindow::GetPrevExpanded (const wxTreeItemId& item) const {
2173     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2174     return GetPrev (item, false);
2175 }
2176
2177 wxTreeItemId wxTreeListMainWindow::GetFirstVisibleItem (bool fullRow) const {
2178     return GetNextVisible (GetRootItem(), fullRow);
2179 }
2180
2181 wxTreeItemId wxTreeListMainWindow::GetNextVisible (const wxTreeItemId& item, bool fullRow) const {
2182     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2183     wxTreeItemId id = GetNext (item, false);
2184     while (id.IsOk()) {
2185         if (IsVisible (id, fullRow)) return id;
2186         id = GetNext (id, false);
2187     }
2188     return wxTreeItemId();
2189 }
2190
2191 wxTreeItemId wxTreeListMainWindow::GetPrevVisible (const wxTreeItemId& item, bool fullRow) const {
2192     wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2193     wxTreeItemId id = GetPrev (item, true);
2194     while (id.IsOk()) {
2195         if (IsVisible (id, fullRow)) return id;
2196         id = GetPrev(id, true);
2197     }
2198     return wxTreeItemId();
2199 }
2200
2201 // ----------------------------------------------------------------------------
2202 // operations
2203 // ----------------------------------------------------------------------------
2204
2205 wxTreeItemId wxTreeListMainWindow::DoInsertItem (const wxTreeItemId& parentId,
2206                                                  size_t previous,
2207                                                  const wxString& text,
2208                                                  int image, int selImage,
2209                                                  wxTreeItemData *data) {
2210     wxTreeListItem *parent = (wxTreeListItem*)parentId.m_pItem;
2211     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2212     m_dirty = true; // do this first so stuff below doesn't cause flicker
2213
2214     wxArrayString arr;
2215     arr.Alloc (GetColumnCount());
2216     for (int i = 0; i < (int)GetColumnCount(); ++i) arr.Add (wxEmptyString);
2217     arr[m_main_column] = text;
2218     wxTreeListItem *item = new wxTreeListItem (this, parent, arr, image, selImage, data);
2219     if (data != NULL) {
2220 #if !wxCHECK_VERSION(2, 5, 0)
2221         data->SetId ((long)item);
2222 #else
2223         data->SetId (item);
2224 #endif
2225     }
2226     parent->Insert (item, previous);
2227
2228     return item;
2229 }
2230
2231 wxTreeItemId wxTreeListMainWindow::AddRoot (const wxString& text,
2232                                             int image, int selImage,
2233                                             wxTreeItemData *data) {
2234     wxCHECK_MSG(!m_rootItem, wxTreeItemId(), _T("tree can have only one root"));
2235     wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), _T("Add column(s) before adding the root item"));
2236     m_dirty = true; // do this first so stuff below doesn't cause flicker
2237
2238     wxArrayString arr;
2239     arr.Alloc (GetColumnCount());
2240     for (int i = 0; i < (int)GetColumnCount(); ++i) arr.Add (wxEmptyString);
2241     arr[m_main_column] = text;
2242     m_rootItem = new wxTreeListItem (this, (wxTreeListItem *)NULL, arr, image, selImage, data);
2243     if (data != NULL) {
2244 #if !wxCHECK_VERSION(2, 5, 0)
2245         data->SetId((long)m_rootItem);
2246 #else
2247         data->SetId(m_rootItem);
2248 #endif
2249     }
2250     if (HasFlag(wxTR_HIDE_ROOT)) {
2251         // if we will hide the root, make sure children are visible
2252         m_rootItem->SetHasPlus();
2253         m_rootItem->Expand();
2254 #if !wxCHECK_VERSION(2, 5, 0)
2255         long cookie = 0;
2256 #else
2257         wxTreeItemIdValue cookie = 0;
2258 #endif
2259         m_curItem = (wxTreeListItem*)GetFirstChild (m_rootItem, cookie).m_pItem;
2260     }
2261     return m_rootItem;
2262 }
2263
2264 wxTreeItemId wxTreeListMainWindow::PrependItem (const wxTreeItemId& parent,
2265                                                 const wxString& text,
2266                                                 int image, int selImage,
2267                                                 wxTreeItemData *data) {
2268     return DoInsertItem (parent, 0u, text, image, selImage, data);
2269 }
2270
2271 wxTreeItemId wxTreeListMainWindow::InsertItem (const wxTreeItemId& parentId,
2272                                                const wxTreeItemId& idPrevious,
2273                                                const wxString& text,
2274                                                int image, int selImage,
2275                                                wxTreeItemData *data) {
2276     wxTreeListItem *parent = (wxTreeListItem*)parentId.m_pItem;
2277     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2278
2279     int index = parent->GetChildren().Index((wxTreeListItem*) idPrevious.m_pItem);
2280     wxASSERT_MSG( index != wxNOT_FOUND,
2281                   _T("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") );
2282
2283     return DoInsertItem (parentId, ++index, text, image, selImage, data);
2284 }
2285
2286 wxTreeItemId wxTreeListMainWindow::InsertItem (const wxTreeItemId& parentId,
2287                                                size_t before,
2288                                                const wxString& text,
2289                                                int image, int selImage,
2290                                                wxTreeItemData *data) {
2291     wxTreeListItem *parent = (wxTreeListItem*)parentId.m_pItem;
2292     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2293
2294     return DoInsertItem (parentId, before, text, image, selImage, data);
2295 }
2296
2297 wxTreeItemId wxTreeListMainWindow::AppendItem (const wxTreeItemId& parentId,
2298                                                const wxString& text,
2299                                                int image, int selImage,
2300                                                wxTreeItemData *data) {
2301     wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem;
2302     wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2303
2304     return DoInsertItem (parent, parent->GetChildren().Count(), text, image, selImage, data);
2305 }
2306
2307 void wxTreeListMainWindow::SendDeleteEvent (wxTreeListItem *item) {
2308     // send event to user code
2309     wxTreeEvent event (wxEVT_COMMAND_TREE_DELETE_ITEM, m_owner->GetId());
2310 #if !wxCHECK_VERSION(2, 5, 0)
2311     event.SetItem ((long)item);
2312 #else
2313     event.SetItem (item);
2314 #endif
2315     event.SetEventObject (m_owner);
2316     m_owner->ProcessEvent (event);
2317 }
2318
2319 void wxTreeListMainWindow::Delete (const wxTreeItemId& itemId) {
2320     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2321     wxCHECK_RET (item != m_rootItem, _T("invalid item, root may not be deleted this way!"));
2322     m_dirty = true; // do this first so stuff below doesn't cause flicker
2323
2324     // don't stay with invalid m_shiftItem or we will crash in the next call to OnChar()
2325     bool changeKeyCurrent = false;
2326     wxTreeListItem *itemKey = m_shiftItem;
2327     while (itemKey) {
2328         if (itemKey == item) { // m_shiftItem is a descendant of the item being deleted
2329             changeKeyCurrent = true;
2330             break;
2331         }
2332         itemKey = itemKey->GetItemParent();
2333     }
2334
2335     wxTreeListItem *parent = item->GetItemParent();
2336     if (parent) {
2337         parent->GetChildren().Remove (item);  // remove by value
2338     }
2339     if (changeKeyCurrent)  m_shiftItem = parent;
2340
2341     SendDeleteEvent (item);
2342     // LG
2343     RemoveFromSelection(item);
2344     //    if (item->IsSelected()) Unselect(item);
2345     //if (m_selectItem == item) m_selectItem = (wxTreeListItem*)NULL;
2346     item->DeleteChildren (this);
2347     delete item;
2348 }
2349
2350 void wxTreeListMainWindow::DeleteChildren (const wxTreeItemId& itemId) {
2351     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2352     m_dirty = true; // do this first so stuff below doesn't cause flicker
2353
2354     item->DeleteChildren (this);
2355 }
2356
2357 void wxTreeListMainWindow::DeleteRoot() {
2358     if (m_rootItem) {
2359         m_dirty = true;
2360         SendDeleteEvent (m_rootItem);
2361         m_curItem = (wxTreeListItem*)NULL;
2362         // LG
2363         // m_selectItem= (wxTreeListItem*)NULL;
2364         UnselectAll();
2365         m_rootItem->DeleteChildren (this);
2366         delete m_rootItem;
2367         m_rootItem = NULL;
2368     }
2369 }
2370
2371 void wxTreeListMainWindow::Expand (const wxTreeItemId& itemId) {
2372     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2373     wxCHECK_RET (item, _T("invalid item in wxTreeListMainWindow::Expand") );
2374
2375     if (!item->HasPlus() || item->IsExpanded()) return;
2376
2377     // send event to user code
2378     wxTreeEvent event (wxEVT_COMMAND_TREE_ITEM_EXPANDING, m_owner->GetId());
2379 #if !wxCHECK_VERSION(2, 5, 0)
2380     event.SetItem ((long)item);
2381 #else
2382     event.SetItem (item);
2383 #endif
2384     event.SetEventObject (m_owner);
2385     if (m_owner->ProcessEvent (event) && !event.IsAllowed()) return; // expand canceled
2386
2387     item->Expand();
2388     m_dirty = true;
2389
2390     // send event to user code
2391     event.SetEventType (wxEVT_COMMAND_TREE_ITEM_EXPANDED);
2392     m_owner->ProcessEvent (event);
2393 }
2394
2395 void wxTreeListMainWindow::ExpandAll (const wxTreeItemId& itemId) {
2396     Expand (itemId);
2397     if (!IsExpanded (itemId)) return;
2398 #if !wxCHECK_VERSION(2, 5, 0)
2399     long cookie;
2400 #else
2401     wxTreeItemIdValue cookie;
2402 #endif
2403     wxTreeItemId child = GetFirstChild (itemId, cookie);
2404     while (child.IsOk()) {
2405         ExpandAll (child);
2406         child = GetNextChild (itemId, cookie);
2407     }
2408 }
2409
2410 void wxTreeListMainWindow::Collapse (const wxTreeItemId& itemId) {
2411     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2412     wxCHECK_RET (item, _T("invalid item in wxTreeListMainWindow::Collapse") );
2413
2414     if (!item->HasPlus() || !item->IsExpanded()) return;
2415
2416     // send event to user code
2417     wxTreeEvent event (wxEVT_COMMAND_TREE_ITEM_COLLAPSING, m_owner->GetId() );
2418 #if !wxCHECK_VERSION(2, 5, 0)
2419     event.SetItem ((long)item);
2420 #else
2421     event.SetItem (item);
2422 #endif
2423     event.SetEventObject (m_owner);
2424     if (m_owner->ProcessEvent (event) && !event.IsAllowed()) return; // collapse canceled
2425
2426     item->Collapse();
2427     m_dirty = true;
2428
2429     // send event to user code
2430     event.SetEventType (wxEVT_COMMAND_TREE_ITEM_COLLAPSED);
2431     ProcessEvent (event);
2432 }
2433
2434 void wxTreeListMainWindow::CollapseAndReset (const wxTreeItemId& item) {
2435     Collapse (item);
2436     DeleteChildren (item);
2437 }
2438
2439 void wxTreeListMainWindow::Toggle (const wxTreeItemId& itemId) {
2440     if (IsExpanded (itemId)) {
2441         Collapse (itemId);
2442     }else{
2443         Expand (itemId);
2444     }
2445 }
2446 /*
2447 void wxTreeListMainWindow::Unselect() {
2448     if (m_selectItem) {
2449         m_selectItem->SetHilight (false);
2450         RefreshLine (m_selectItem);
2451         m_selectItem = (wxTreeListItem*)NULL;
2452     }
2453 }
2454 */
2455 // LG 19/09/08 : Added 
2456 /*
2457 void wxTreeListMainWindow::Unselect(wxTreeListItem* item) 
2458 {
2459     if (item->IsSelected()) {
2460         item->SetSelected (false);
2461         RefreshLine (item);
2462         m_selected.Remove(item);
2463         // LG : TODO  : Remove from array
2464         //        if (item == m_selectItem) m_selectItem = (wxTreeListItem*)NULL;
2465     }
2466 }
2467 */
2468 /*
2469 void wxTreeListMainWindow::UnselectAllChildren (wxTreeListItem *item) {
2470     if (item->IsSelected()) {
2471         item->SetHilight (false);
2472         RefreshLine (item);
2473         if (item == m_selectItem) m_selectItem = (wxTreeListItem*)NULL;
2474     }
2475     if (item->HasChildren()) {
2476         wxArrayTreeListItems& children = item->GetChildren();
2477         size_t count = children.Count();
2478         for (size_t n = 0; n < count; ++n) {
2479             UnselectAllChildren (children[n]);
2480         }
2481     }
2482 }
2483 */
2484 void wxTreeListMainWindow::UnselectAll() {
2485   
2486   size_t count = m_selected.Count();
2487   for (size_t n = 0; n < count; ++n) 
2488     {
2489       m_selected[n]->SetSelected (false);
2490       RefreshLine (m_selected[n]);
2491     }
2492   m_selected.Empty();
2493   
2494   //UnselectAllChildren ((wxTreeListItem*)GetRootItem().m_pItem);
2495 }
2496
2497 // Recursive function !
2498 // To stop we must have crt_item<last_item
2499 // Algorithm :
2500 // Tag all next children, when no more children,
2501 // Move to parent (not to tag)
2502 // Keep going... if we found last_item, we stop.
2503 bool wxTreeListMainWindow::SelectNextChildren (wxTreeListItem *crt_item,
2504                                                wxTreeListItem *last_item) {
2505     wxTreeListItem *parent = crt_item->GetItemParent();
2506
2507     if (!parent) {// This is root item
2508         return SelectAllChildrenUntilLast (crt_item, last_item);
2509     }
2510
2511     wxArrayTreeListItems& children = parent->GetChildren();
2512     int index = children.Index(crt_item);
2513     wxASSERT (index != wxNOT_FOUND); // I'm not a child of my parent?
2514
2515     if ((parent->HasChildren() && parent->IsExpanded()) ||
2516         ((parent == (wxTreeListItem*)GetRootItem().m_pItem) && HasFlag(wxTR_HIDE_ROOT))) {
2517         size_t count = children.Count();
2518         for (size_t n = (index+1); n < count; ++n) {
2519             if (SelectAllChildrenUntilLast (children[n], last_item)) return true;
2520         }
2521     }
2522
2523     return SelectNextChildren (parent, last_item);
2524 }
2525
2526  bool wxTreeListMainWindow::SelectAllChildrenUntilLast (wxTreeListItem *crt_item,
2527                                                         wxTreeListItem *last_item) {
2528    if (!crt_item->IsSelected())
2529      {
2530        // LG : Send event to user to know is selection is accepted 
2531        // send event to the user code
2532        wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() );
2533 #if !wxCHECK_VERSION(2, 5, 0)
2534        event.SetItem ((long)crt_item);
2535 #else
2536        event.SetItem (crt_item);
2537 #endif
2538        event.SetEventObject (m_owner);
2539        if (m_owner->GetEventHandler()->ProcessEvent (event) && event.IsAllowed())
2540          {    
2541            AddToSelection(crt_item);
2542          }
2543      }
2544
2545     if (crt_item==last_item) return true;
2546
2547     if (crt_item->HasChildren() && crt_item->IsExpanded()) {
2548         wxArrayTreeListItems& children = crt_item->GetChildren();
2549         size_t count = children.Count();
2550         for (size_t n = 0; n < count; ++n) {
2551           if (SelectAllChildrenUntilLast (children[n], last_item)) return true;
2552         }
2553     }
2554
2555     return false;
2556 }
2557
2558  void wxTreeListMainWindow::RemoveFromSelection( wxTreeListItem *item )
2559  {
2560    if (!item->IsSelected()) return;
2561    item->SetSelected(false);
2562    m_selected.Remove(item);
2563    RefreshLine(item);
2564    
2565  }
2566  void wxTreeListMainWindow::AddToSelection( wxTreeListItem *item )
2567  {
2568    if (item->IsSelected()) return;
2569    item->SetSelected(true);
2570    m_selected.Add(item);
2571    RefreshLine(item);
2572  }
2573
2574 void wxTreeListMainWindow::SelectItem (const wxTreeItemId& itemId,
2575                                        const wxTreeItemId& lastId,
2576                                        bool unselect_others) {
2577     wxCHECK_RET (itemId.IsOk(), _T("invalid tree item") );
2578
2579     bool is_single = !HasFlag(wxTR_MULTIPLE);
2580     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2581
2582         
2583     // single selection requires unselect others
2584     if (is_single) unselect_others = true;
2585
2586     // unselect all if unselect other items
2587     bool unselected = false; // see that UnselectAll is done only once
2588     if (unselect_others) {
2589       /*
2590         if (is_single) {
2591             Unselect(); // to speed up thing
2592         }else{
2593       */
2594             UnselectAll();
2595             unselected = true;
2596             //        }
2597     }
2598
2599     // LG : Update current item
2600     wxTreeListItem *old_curItem = m_curItem;
2601     m_curItem = item;
2602     if (old_curItem) RefreshLine (old_curItem);
2603     
2604     // select item or item range
2605     if (lastId.IsOk() && (itemId != lastId)) 
2606       {
2607
2608
2609         if (!unselected) UnselectAll();
2610         wxTreeListItem *last = (wxTreeListItem*) lastId.m_pItem;
2611
2612         // LG : Update current item
2613         //      wxTreeListItem *old_curItem = m_curItem;
2614         //      m_curItem = last;
2615         //      if (old_curItem) RefreshLine (old_curItem);
2616
2617         // ensure that the position of the item it calculated in any case
2618         if (m_dirty) CalculatePositions();
2619
2620         // select item range according Y-position
2621         if (last->GetY() < item->GetY()) {
2622             if (!SelectAllChildrenUntilLast (last, item)) {
2623                 SelectNextChildren (last, item);
2624             }
2625         }else{
2626             if (!SelectAllChildrenUntilLast (item, last)) {
2627                 SelectNextChildren (item, last);
2628             }
2629         }
2630
2631     }
2632     else
2633       {
2634
2635         // send event to the user code
2636         wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() );
2637 #if !wxCHECK_VERSION(2, 5, 0)
2638         event.SetItem ((long)item);
2639         event.SetOldItem ((long)m_curItem);
2640 #else
2641         event.SetItem (item);
2642         event.SetOldItem (m_curItem);
2643 #endif
2644         event.SetEventObject (m_owner);
2645         
2646
2647
2648         if (m_owner->GetEventHandler()->ProcessEvent (event) && 
2649             event.IsAllowed())
2650           {
2651             // select item according its old selection
2652             if (item->IsSelected())
2653               RemoveFromSelection(item);
2654             else 
2655               AddToSelection(item);
2656           }
2657     }
2658
2659     // send event to user code
2660     wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGED, m_owner->GetId() );
2661     m_owner->GetEventHandler()->ProcessEvent (event);
2662 }
2663
2664 void wxTreeListMainWindow::SelectAll() {
2665     wxCHECK_RET (HasFlag(wxTR_MULTIPLE), _T("invalid tree style"));
2666
2667 #if !wxCHECK_VERSION(2, 5, 0)
2668     long cookie = 0;
2669 #else
2670     wxTreeItemIdValue cookie = 0;
2671 #endif
2672     wxTreeItemId root = GetRootItem();
2673     wxTreeListItem *first = (wxTreeListItem *)GetFirstChild (root, cookie).m_pItem;
2674     wxTreeListItem *last = (wxTreeListItem *)GetLastChild (root, cookie).m_pItem;
2675     if (!SelectAllChildrenUntilLast (first, last)) {
2676         SelectNextChildren (first, last);
2677     }
2678
2679     // send event to user code
2680     wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGED, m_owner->GetId() );
2681     m_owner->GetEventHandler()->ProcessEvent (event);
2682 }
2683
2684 void wxTreeListMainWindow::FillArray (wxTreeListItem *item,
2685                                       wxArrayTreeItemIds &array) const {
2686     if (item->IsSelected()) array.Add (wxTreeItemId(item));
2687
2688     if (item->HasChildren()) {
2689         wxArrayTreeListItems& children = item->GetChildren();
2690         size_t count = children.GetCount();
2691         for (size_t n = 0; n < count; ++n) FillArray (children[n], array);
2692     }
2693 }
2694
2695
2696 // returns the number of currently selected items
2697  size_t wxTreeListMainWindow::GetSelectionSize() const
2698  {
2699    return m_selected.GetCount();
2700  }
2701
2702 size_t wxTreeListMainWindow::GetSelections (wxArrayTreeItemIds &array) const {
2703   /* 
2704      LG : NOT OK AS IS NOT IN TREE ORDER
2705     array.Empty();
2706     size_t count = m_selected.GetCount();
2707     for (size_t n = 0; n < count; ++n) array.Add(m_selected[n]);
2708   */
2709     wxTreeItemId idRoot = GetRootItem();
2710     if (idRoot.IsOk()) FillArray ((wxTreeListItem*) idRoot.m_pItem, array);
2711     return array.Count();
2712 }
2713
2714 void wxTreeListMainWindow::EnsureVisible (const wxTreeItemId& item) {
2715     if (!item.IsOk()) return; // do nothing if no item
2716
2717     // first expand all parent branches
2718     wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem;
2719     wxTreeListItem *parent = gitem->GetItemParent();
2720     while (parent) {
2721         Expand (parent);
2722         parent = parent->GetItemParent();
2723     }
2724
2725     ScrollTo (item);
2726     RefreshLine (gitem);
2727 }
2728
2729 void wxTreeListMainWindow::ScrollTo (const wxTreeItemId &item) {
2730     if (!item.IsOk()) return; // do nothing if no item
2731
2732     // ensure that the position of the item it calculated in any case
2733     if (m_dirty) CalculatePositions();
2734
2735     wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem;
2736
2737     // now scroll to the item
2738     int item_y = gitem->GetY();
2739
2740     int xUnit, yUnit;
2741     GetScrollPixelsPerUnit (&xUnit, &yUnit);
2742     int start_x = 0;
2743     int start_y = 0;
2744     GetViewStart (&start_x, &start_y);
2745     start_y *= yUnit;
2746
2747     int client_h = 0;
2748     int client_w = 0;
2749     GetClientSize (&client_w, &client_h);
2750
2751     int x = 0;
2752     int y = 0;
2753     m_rootItem->GetSize (x, y, this);
2754     x = m_owner->GetHeaderWindow()->GetWidth();
2755     y += yUnit + 2; // one more scrollbar unit + 2 pixels
2756     int x_pos = GetScrollPos( wxHORIZONTAL );
2757
2758     if (item_y < start_y+3) {
2759         // going down, item should appear at top
2760         SetScrollbars (xUnit, yUnit, xUnit ? x/xUnit : 0, yUnit ? y/yUnit : 0, x_pos, yUnit ? item_y/yUnit : 0);
2761     }else if (item_y+GetLineHeight(gitem) > start_y+client_h) {
2762         // going up, item should appear at bottom
2763         item_y += yUnit + 2;
2764         SetScrollbars (xUnit, yUnit, xUnit ? x/xUnit : 0, yUnit ? y/yUnit : 0, x_pos, yUnit ? (item_y+GetLineHeight(gitem)-client_h)/yUnit : 0 );
2765     }
2766 }
2767
2768 // FIXME: tree sorting functions are not reentrant and not MT-safe!
2769 static wxTreeListMainWindow *s_treeBeingSorted = NULL;
2770
2771 static int LINKAGEMODE tree_ctrl_compare_func(wxTreeListItem **item1,
2772                                   wxTreeListItem **item2)
2773 {
2774     wxCHECK_MSG (s_treeBeingSorted, 0, _T("bug in wxTreeListMainWindow::SortChildren()") );
2775
2776     return s_treeBeingSorted->OnCompareItems(*item1, *item2);
2777 }
2778
2779 int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId& item1,
2780                                const wxTreeItemId& item2)
2781 {
2782     return m_owner->OnCompareItems (item1, item2);
2783 }
2784
2785 void wxTreeListMainWindow::SortChildren (const wxTreeItemId& itemId) {
2786     wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
2787
2788     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
2789
2790     wxCHECK_RET (!s_treeBeingSorted,
2791                  _T("wxTreeListMainWindow::SortChildren is not reentrant") );
2792
2793     wxArrayTreeListItems& children = item->GetChildren();
2794     if ( children.Count() > 1 ) {
2795         m_dirty = true;
2796         s_treeBeingSorted = this;
2797         children.Sort(tree_ctrl_compare_func);
2798         s_treeBeingSorted = NULL;
2799     }
2800 }
2801
2802 wxTreeItemId wxTreeListMainWindow::FindItem (const wxTreeItemId& item, const wxString& str, int mode) {
2803     wxString itemText;
2804     // determine start item
2805     wxTreeItemId next = item;
2806     if (next.IsOk()) {
2807         if (mode & wxTL_MODE_NAV_LEVEL) {
2808             next = GetNextSibling (next);
2809         }else if (mode & wxTL_MODE_NAV_VISIBLE) { //
2810             next = GetNextVisible (next, false);
2811         }else if (mode & wxTL_MODE_NAV_EXPANDED) {
2812             next = GetNextExpanded (next);
2813         }else{ // (mode & wxTL_MODE_NAV_FULLTREE) default
2814             next = GetNext (next, true);
2815         }
2816     }
2817
2818 #if !wxCHECK_VERSION(2, 5, 0)
2819     long cookie = 0;
2820 #else
2821     wxTreeItemIdValue cookie = 0;
2822 #endif
2823     if (!next.IsOk()) {
2824         next = (wxTreeListItem*)GetRootItem().m_pItem;
2825         if (HasFlag(wxTR_HIDE_ROOT)) {
2826             next = (wxTreeListItem*)GetFirstChild (GetRootItem().m_pItem, cookie).m_pItem;
2827         }
2828     }
2829     if (!next.IsOk()) return (wxTreeItemId*)NULL;
2830
2831     // start checking the next items
2832     while (next.IsOk() && (next != item)) {
2833         if (mode & wxTL_MODE_FIND_PARTIAL) {
2834             itemText = GetItemText (next).Mid (0, str.Length());
2835         }else{
2836             itemText = GetItemText (next);
2837         }
2838         if (mode & wxTL_MODE_FIND_NOCASE) {
2839             if (itemText.CmpNoCase (str) == 0) return next;
2840         }else{
2841             if (itemText.Cmp (str) == 0) return next;
2842         }
2843         if (mode & wxTL_MODE_NAV_LEVEL) {
2844             next = GetNextSibling (next);
2845         }else if (mode & wxTL_MODE_NAV_VISIBLE) { //
2846             next = GetNextVisible (next, false);
2847         }else if (mode & wxTL_MODE_NAV_EXPANDED) {
2848             next = GetNextExpanded (next);
2849         }else{ // (mode & wxTL_MODE_NAV_FULLTREE) default
2850             next = GetNext (next, true);
2851         }
2852         if (!next.IsOk() && item.IsOk()) {
2853             next = (wxTreeListItem*)GetRootItem().m_pItem;
2854             if (HasFlag(wxTR_HIDE_ROOT)) {
2855                 next = (wxTreeListItem*)GetNextChild (GetRootItem().m_pItem, cookie).m_pItem;
2856             }
2857         }
2858     }
2859     return (wxTreeItemId*)NULL;
2860 }
2861
2862 void wxTreeListMainWindow::SetDragItem (const wxTreeItemId& item) {
2863     wxTreeListItem *prevItem = m_dragItem;
2864     m_dragItem = (wxTreeListItem*) item.m_pItem;
2865     if (prevItem) RefreshLine (prevItem);
2866     if (m_dragItem) RefreshLine (m_dragItem);
2867 }
2868
2869 void wxTreeListMainWindow::CalculateLineHeight() {
2870     wxClientDC dc (this);
2871     dc.SetFont (m_normalFont);
2872     m_lineHeight = (int)(dc.GetCharHeight() + m_linespacing);
2873
2874     if (m_imageListNormal) {
2875         // Calculate a m_lineHeight value from the normal Image sizes.
2876         // May be toggle off. Then wxTreeListMainWindow will spread when
2877         // necessary (which might look ugly).
2878         int n = m_imageListNormal->GetImageCount();
2879         for (int i = 0; i < n ; i++) {
2880             int width = 0, height = 0;
2881             m_imageListNormal->GetSize(i, width, height);
2882             if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
2883         }
2884     }
2885
2886     if (m_imageListButtons) {
2887         // Calculate a m_lineHeight value from the Button image sizes.
2888         // May be toggle off. Then wxTreeListMainWindow will spread when
2889         // necessary (which might look ugly).
2890         int n = m_imageListButtons->GetImageCount();
2891         for (int i = 0; i < n ; i++) {
2892             int width = 0, height = 0;
2893             m_imageListButtons->GetSize(i, width, height);
2894             if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
2895         }
2896     }
2897
2898     if (m_lineHeight < 30) { // add 10% space if greater than 30 pixels
2899         m_lineHeight += 2; // minimal 2 pixel space
2900     }else{
2901         m_lineHeight += m_lineHeight / 10; // otherwise 10% space
2902     }
2903 }
2904
2905 void wxTreeListMainWindow::SetImageList (wxImageList *imageList) {
2906     if (m_ownsImageListNormal) delete m_imageListNormal;
2907     m_imageListNormal = imageList;
2908     m_ownsImageListNormal = false;
2909     m_dirty = true;
2910     CalculateLineHeight();
2911 }
2912
2913 void wxTreeListMainWindow::SetStateImageList (wxImageList *imageList) {
2914     if (m_ownsImageListState) delete m_imageListState;
2915     m_imageListState = imageList;
2916     m_ownsImageListState = false;
2917 }
2918
2919 void wxTreeListMainWindow::SetButtonsImageList (wxImageList *imageList) {
2920     if (m_ownsImageListButtons) delete m_imageListButtons;
2921     m_imageListButtons = imageList;
2922     m_ownsImageListButtons = false;
2923     m_dirty = true;
2924     CalculateLineHeight();
2925 }
2926
2927 void wxTreeListMainWindow::AssignImageList (wxImageList *imageList) {
2928     SetImageList(imageList);
2929     m_ownsImageListNormal = true;
2930 }
2931
2932 void wxTreeListMainWindow::AssignStateImageList (wxImageList *imageList) {
2933     SetStateImageList(imageList);
2934     m_ownsImageListState = true;
2935 }
2936
2937 void wxTreeListMainWindow::AssignButtonsImageList (wxImageList *imageList) {
2938     SetButtonsImageList(imageList);
2939     m_ownsImageListButtons = true;
2940 }
2941
2942 // ----------------------------------------------------------------------------
2943 // helpers
2944 // ----------------------------------------------------------------------------
2945
2946 void wxTreeListMainWindow::AdjustMyScrollbars() {
2947     if (m_rootItem) {
2948         int xUnit, yUnit;
2949         GetScrollPixelsPerUnit (&xUnit, &yUnit);
2950         if (xUnit == 0) xUnit = GetCharWidth();
2951         if (yUnit == 0) yUnit = m_lineHeight;
2952         int x = 0, y = 0;
2953         m_rootItem->GetSize (x, y, this);
2954         y += yUnit + 2; // one more scrollbar unit + 2 pixels
2955         int x_pos = GetScrollPos (wxHORIZONTAL);
2956         int y_pos = GetScrollPos (wxVERTICAL);
2957         x = m_owner->GetHeaderWindow()->GetWidth() + 2;
2958         if (x < GetClientSize().GetWidth()) x_pos = 0;
2959         SetScrollbars (xUnit, yUnit, x/xUnit, y/yUnit, x_pos, y_pos);
2960     }else{
2961         SetScrollbars (0, 0, 0, 0);
2962     }
2963 }
2964
2965 int wxTreeListMainWindow::GetLineHeight (wxTreeListItem *item) const {
2966     if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT) {
2967         return item->GetHeight();
2968     }else{
2969         return m_lineHeight;
2970     }
2971 }
2972
2973 void wxTreeListMainWindow::PaintItem (wxTreeListItem *item, wxDC& dc) {
2974
2975     wxTreeItemAttr *attr = item->GetAttributes();
2976
2977     dc.SetFont (GetItemFont (item));
2978
2979     wxColour colText;
2980     if (attr && attr->HasTextColour()) {
2981         colText = attr->GetTextColour();
2982     }else{
2983         colText = GetForegroundColour();
2984     }
2985 #if !wxCHECK_VERSION(2, 5, 0)
2986     wxColour colTextHilight = wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHTTEXT);
2987 #else
2988     wxColour colTextHilight = wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHTTEXT);
2989 #endif
2990
2991     int total_w = m_owner->GetHeaderWindow()->GetWidth();
2992     int total_h = GetLineHeight(item);
2993     int off_h = HasFlag(wxTR_ROW_LINES) ? 1 : 0;
2994     //    std::cout << "off_h="<<off_h<<std::endl;
2995
2996     wxDCClipper clipper (dc, 0, item->GetY(), total_w, total_h); // only within line
2997
2998     int text_w = 0, text_h = 0;
2999     dc.GetTextExtent( item->GetText(GetMainColumn()), &text_w, &text_h );
3000
3001     // determine background and show it
3002     wxColour colBg;
3003     if (attr && attr->HasBackgroundColour()) {
3004         colBg = attr->GetBackgroundColour();
3005     }else{
3006         colBg = m_backgroundColour;
3007     }
3008     dc.SetBrush (wxBrush (colBg, wxSOLID));
3009     dc.SetPen (*wxTRANSPARENT_PEN);
3010     if (HasFlag (wxTR_FULL_ROW_HIGHLIGHT)) {
3011         if (item == m_dragItem) {
3012             dc.SetBrush (*m_hilightBrush);
3013 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3014             dc.SetPen ((item == m_dragItem)? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3015 #endif // !__WXMAC__
3016             dc.SetTextForeground (colTextHilight);
3017         }else if (item->IsSelected()) {
3018             if (!m_isDragging && m_hasFocus) {
3019                 dc.SetBrush (*m_hilightBrush);
3020 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3021                 // LG : dc.SetPen (*wxBLACK_PEN);
3022                 dc.SetPen (*wxTRANSPARENT_PEN);
3023 #endif // !__WXMAC__
3024             }else{
3025                 dc.SetBrush (*m_hilightUnfocusedBrush);
3026 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3027                 dc.SetPen (*wxTRANSPARENT_PEN);
3028 #endif // !__WXMAC__
3029             }
3030             dc.SetTextForeground (colTextHilight);
3031         }
3032         // LG
3033         else if (item == m_curItem) {
3034           dc.SetPen (m_hasFocus? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3035         }
3036         else{
3037             dc.SetTextForeground (colText);
3038         }
3039         // LG 
3040         dc.DrawRectangle (0, item->GetY() + off_h, total_w, total_h - off_h);
3041     }else{
3042         dc.SetTextForeground (colText);
3043     }
3044
3045     int text_extraH = (total_h > text_h) ? (total_h - text_h)/2 : 0;
3046     int img_extraH = (total_h > m_imgHeight)? (total_h-m_imgHeight)/2: 0;
3047     int x_colstart = 0;
3048     for (int i = 0; i < GetColumnCount(); ++i ) {
3049         if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
3050
3051         int col_w = m_owner->GetHeaderWindow()->GetColumnWidth(i);
3052         wxDCClipper clipper (dc, x_colstart, item->GetY(), col_w, total_h); // only within column
3053
3054         int x = 0;
3055         int image = NO_IMAGE;
3056         int image_w = 0;
3057         if(i == GetMainColumn()) {
3058             x = item->GetX() + MARGIN;
3059             if (HasButtons()) {
3060                 x += (m_btnWidth-m_btnWidth2) + LINEATROOT;
3061             }else{
3062                 x -= m_indent/2;
3063             }
3064             if (m_imageListNormal) image = item->GetCurrentImage();
3065         }else{
3066             x = x_colstart + MARGIN;
3067             image = item->GetImage(i);
3068         }
3069         if (image != NO_IMAGE) image_w = m_imgWidth + MARGIN;
3070
3071         // honor text alignment
3072         wxString text = item->GetText(i);
3073         int w = 0;
3074         switch ( m_owner->GetHeaderWindow()->GetColumn(i).GetAlignment() ) {
3075         case wxALIGN_LEFT:
3076             // nothing to do, already left aligned
3077             break;
3078         case wxALIGN_RIGHT:
3079             dc.GetTextExtent (text, &text_w, NULL);
3080             w = col_w - (image_w + text_w + MARGIN);
3081             x += (w > 0)? w: 0;
3082             break;
3083         case wxALIGN_CENTER:
3084             dc.GetTextExtent(text, &text_w, NULL);
3085             w = (col_w - (image_w + text_w + MARGIN))/2;
3086             x += (w > 0)? w: 0;
3087             break;
3088         }
3089         int text_x = x + image_w;
3090         if (i == GetMainColumn()) item->SetTextX (text_x);
3091
3092         if (!HasFlag (wxTR_FULL_ROW_HIGHLIGHT)) {
3093             if (i == GetMainColumn()) {
3094                 if (item == m_dragItem) {
3095                     dc.SetBrush (*m_hilightBrush);
3096 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3097                     dc.SetPen ((item == m_dragItem)? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3098 #endif // !__WXMAC__
3099                     dc.SetTextForeground (colTextHilight);
3100                 }else if (item->IsSelected()) {
3101                     if (!m_isDragging && m_hasFocus) {
3102                         dc.SetBrush (*m_hilightBrush);
3103 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3104                         dc.SetPen (*wxBLACK_PEN);
3105 #endif // !__WXMAC__
3106                     }else{
3107                         dc.SetBrush (*m_hilightUnfocusedBrush);
3108 #ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3109                       dc.SetPen (*wxTRANSPARENT_PEN);
3110 #endif // !__WXMAC__
3111                     }
3112                     dc.SetTextForeground (colTextHilight);
3113                 }
3114                 // LG 
3115                 else if (item == m_curItem) {
3116                   dc.SetPen (m_hasFocus? *wxBLACK_PEN: *wxTRANSPARENT_PEN);
3117                 }
3118                 else{
3119                   dc.SetTextForeground (colText);
3120                 }
3121                 dc.DrawRectangle (text_x, item->GetY() + off_h, text_w, total_h - off_h);
3122             }else{
3123                 dc.SetTextForeground (colText);
3124             }
3125         }
3126
3127         dc.SetBackgroundMode (wxTRANSPARENT);
3128
3129         if (image != NO_IMAGE) {
3130             int y = item->GetY() + img_extraH;
3131             m_imageListNormal->Draw (image, dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
3132         }
3133         int text_y = item->GetY() + text_extraH;
3134         dc.DrawText (text, (wxCoord)text_x, (wxCoord)text_y);
3135
3136         x_colstart += col_w;
3137     }
3138
3139     // restore normal font
3140     dc.SetFont( m_normalFont );
3141 }
3142
3143 // Now y stands for the top of the item, whereas it used to stand for middle !
3144 void wxTreeListMainWindow::PaintLevel (wxTreeListItem *item, wxDC &dc,
3145                                        int level, int &y, int x_maincol) {
3146
3147     // Handle hide root (only level 0)
3148   // LG : test
3149   //  int nth = 2;
3150   //if (HasFlag(wxTR_HIDE_ROOT) && (level < nth)) {  
3151   if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) {
3152   
3153         wxArrayTreeListItems& children = item->GetChildren();
3154         for (size_t n = 0; n < children.Count(); n++) {
3155             PaintLevel (children[n], dc, 1, y, x_maincol);
3156         }
3157         // end after expanding root
3158         return;
3159     }
3160
3161     // calculate position of vertical lines
3162     int x = x_maincol + MARGIN; // start of column
3163     if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
3164     if (HasButtons()) {
3165         x += (m_btnWidth-m_btnWidth2); // half button space
3166     }else{
3167         x += (m_indent-m_indent/2);
3168     }
3169     if (HasFlag(wxTR_HIDE_ROOT)) {
3170       // LG 
3171       //        x += m_indent * (level-nth); // indent but not level 1
3172       x += m_indent * (level-1); // indent but not level 1
3173
3174     }else{
3175         x += m_indent * level; // indent according to level
3176     }
3177
3178     // set position of vertical line
3179     item->SetX (x);
3180     item->SetY (y);
3181
3182     int h = GetLineHeight (item);
3183     int y_top = y;
3184     int y_mid = y_top + (h/2);
3185     y += h;
3186
3187     int exposed_x = dc.LogicalToDeviceX(0);
3188     int exposed_y = dc.LogicalToDeviceY(y_top);
3189
3190     if (IsExposed(exposed_x, exposed_y, 10000, h)) { // 10000 = very much
3191
3192         if (HasFlag(wxTR_ROW_LINES)) { // horizontal lines between rows
3193             //dc.DestroyClippingRegion();
3194             int total_width = m_owner->GetHeaderWindow()->GetWidth();
3195             // if the background colour is white, choose a
3196             // contrasting color for the lines
3197             dc.SetPen (*((GetBackgroundColour() == *wxWHITE)?
3198                         wxMEDIUM_GREY_PEN : wxWHITE_PEN));
3199             dc.DrawLine(0, y_top, total_width, y_top);
3200             dc.DrawLine(0, y_top+h, total_width, y_top+h);
3201         }
3202
3203         // draw item
3204         PaintItem (item, dc);
3205
3206         // restore DC objects
3207         dc.SetBrush(*wxWHITE_BRUSH);
3208         dc.SetPen(m_dottedPen);
3209
3210         // clip to the column width
3211         int clip_width = m_owner->GetHeaderWindow()->
3212                             GetColumn(m_main_column).GetWidth();
3213         wxDCClipper clipper(dc, x_maincol, y_top, clip_width, 10000);
3214
3215         if (!HasFlag(wxTR_NO_LINES)) { // connection lines
3216
3217             // draw the horizontal line here
3218             dc.SetPen(m_dottedPen);
3219             int x2 = x - m_indent;
3220             if (x2 < (x_maincol + MARGIN)) x2 = x_maincol + MARGIN;
3221             int x3 = x + (m_btnWidth-m_btnWidth2);
3222             if (HasButtons()) {
3223                 if (item->HasPlus()) {
3224                     dc.DrawLine (x2, y_mid, x - m_btnWidth2, y_mid);
3225                     dc.DrawLine (x3, y_mid, x3 + LINEATROOT, y_mid);
3226                 }else{
3227                     dc.DrawLine (x2, y_mid, x3 + LINEATROOT, y_mid);
3228                 }
3229             }else{
3230                 dc.DrawLine (x2, y_mid, x - m_indent/2, y_mid);
3231             }
3232         }
3233
3234         if (item->HasPlus() && HasButtons()) { // should the item show a button?
3235
3236             if (m_imageListButtons) {
3237
3238                 // draw the image button here
3239                 int image = wxTreeItemIcon_Normal;
3240                 if (item->IsExpanded()) image = wxTreeItemIcon_Expanded;
3241                 if (item->IsSelected()) image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal;
3242                 int xx = x - m_btnWidth2 + MARGIN;
3243                 int yy = y_mid - m_btnHeight2;
3244                 dc.SetClippingRegion(xx, yy, m_btnWidth, m_btnHeight);
3245                 m_imageListButtons->Draw (image, dc, xx, yy, wxIMAGELIST_DRAW_TRANSPARENT);
3246                 dc.DestroyClippingRegion();
3247
3248             }else if (HasFlag (wxTR_TWIST_BUTTONS)) {
3249
3250                 // draw the twisty button here
3251                 dc.SetPen(*wxBLACK_PEN);
3252                 dc.SetBrush(*m_hilightBrush);
3253                 wxPoint button[3];
3254                 if (item->IsExpanded()) {
3255                     button[0].x = x - (m_btnWidth2+1);
3256                     button[0].y = y_mid - (m_btnHeight/3);
3257                     button[1].x = x + (m_btnWidth2+1);
3258                     button[1].y = button[0].y;
3259                     button[2].x = x;
3260                     button[2].y = button[0].y + (m_btnHeight2+1);
3261                 }else{
3262                     button[0].x = x - (m_btnWidth/3);
3263                     button[0].y = y_mid - (m_btnHeight2+1);
3264                     button[1].x = button[0].x;
3265                     button[1].y = y_mid + (m_btnHeight2+1);
3266                     button[2].x = button[0].x + (m_btnWidth2+1);
3267                     button[2].y = y_mid;
3268                 }
3269                 dc.DrawPolygon(3, button);
3270
3271             }else{ // if (HasFlag(wxTR_HAS_BUTTONS))
3272
3273                 // draw the plus sign here
3274                 dc.SetPen(*wxGREY_PEN);
3275                 dc.SetBrush(*wxWHITE_BRUSH);
3276                 dc.DrawRectangle (x-m_btnWidth2, y_mid-m_btnHeight2, m_btnWidth, m_btnHeight);
3277                 dc.SetPen(*wxBLACK_PEN);
3278                 dc.DrawLine (x-(m_btnWidth2-2), y_mid, x+(m_btnWidth2-1), y_mid);
3279                 if (!item->IsExpanded()) { // change "-" to "+"
3280                     dc.DrawLine (x, y_mid-(m_btnHeight2-2), x, y_mid+(m_btnHeight2-1));
3281                 }
3282
3283             }
3284
3285         }
3286
3287     }
3288
3289     // restore DC objects
3290     dc.SetBrush(*wxWHITE_BRUSH);
3291     dc.SetPen(m_dottedPen);
3292     dc.SetTextForeground(*wxBLACK);
3293
3294     if (item->IsExpanded())
3295     {
3296         wxArrayTreeListItems& children = item->GetChildren();
3297
3298         // clip to the column width
3299         int clip_width = m_owner->GetHeaderWindow()->
3300                             GetColumn(m_main_column).GetWidth();
3301
3302         // process lower levels
3303         int oldY;
3304         if (m_imgWidth > 0) {
3305             oldY = y_mid + m_imgHeight2;
3306         }else{
3307             oldY = y_mid + h/2;
3308         }
3309         int y2;
3310         for (size_t n = 0; n < children.Count(); ++n) {
3311
3312             y2 = y + h/2;
3313             PaintLevel (children[n], dc, level+1, y, x_maincol);
3314
3315             // draw vertical line
3316             wxDCClipper clipper(dc, x_maincol, y_top, clip_width, 10000);
3317             if (!HasFlag (wxTR_NO_LINES)) {
3318                 x = item->GetX();
3319                 dc.DrawLine (x, oldY, x, y2);
3320                 oldY = y2;
3321             }
3322         }
3323     }
3324 }
3325
3326
3327 // ----------------------------------------------------------------------------
3328 // wxWindows callbacks
3329 // ----------------------------------------------------------------------------
3330
3331 void wxTreeListMainWindow::OnPaint (wxPaintEvent &WXUNUSED(event)) {
3332
3333     wxPaintDC dc (this);
3334     PrepareDC (dc);
3335
3336     if (!m_rootItem || (GetColumnCount() <= 0)) return;
3337
3338     // calculate button size
3339     if (m_imageListButtons) {
3340         m_imageListButtons->GetSize (0, m_btnWidth, m_btnHeight);
3341     }else if (HasButtons()) {
3342         m_btnWidth = BTNWIDTH;
3343         m_btnHeight = BTNHEIGHT;
3344     }
3345     m_btnWidth2 = m_btnWidth/2;
3346     m_btnHeight2 = m_btnHeight/2;
3347
3348     // calculate image size
3349     if (m_imageListNormal) {
3350         m_imageListNormal->GetSize (0, m_imgWidth, m_imgHeight);
3351     }
3352     m_imgWidth2 = m_imgWidth/2;
3353     m_imgHeight2 = m_imgHeight/2;
3354
3355     // calculate indent size
3356     if (m_imageListButtons) {
3357         m_indent = wxMax (MININDENT, m_btnWidth + MARGIN);
3358     }else if (HasButtons()) {
3359         m_indent = wxMax (MININDENT, m_btnWidth + LINEATROOT);
3360     }
3361
3362     // set default values
3363     dc.SetFont( m_normalFont );
3364     dc.SetPen( m_dottedPen );
3365
3366     // calculate column start and paint
3367     int x_maincol = 0;
3368     int i = 0;
3369     for (i = 0; i < (int)GetMainColumn(); ++i) {
3370         if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
3371         x_maincol += m_owner->GetHeaderWindow()->GetColumnWidth (i);
3372     }
3373     int y = 0;
3374     PaintLevel (m_rootItem, dc, 0, y, x_maincol);
3375 }
3376
3377 void wxTreeListMainWindow::OnSetFocus (wxFocusEvent &event) {
3378
3379     m_hasFocus = true;
3380     RefreshSelected();
3381     if (m_curItem) RefreshLine (m_curItem);
3382     event.Skip();
3383 }
3384
3385 void wxTreeListMainWindow::OnKillFocus( wxFocusEvent &event )
3386 {
3387     m_hasFocus = false;
3388     RefreshSelected();
3389     if (m_curItem) RefreshLine (m_curItem);
3390     event.Skip();
3391 }
3392
3393 void wxTreeListMainWindow::OnChar (wxKeyEvent &event) {
3394     // send event to user code
3395     wxTreeEvent nevent (wxEVT_COMMAND_TREE_KEY_DOWN, m_owner->GetId());
3396     nevent.SetKeyEvent (event);
3397     nevent.SetEventObject (m_owner);
3398     if (m_owner->GetEventHandler()->ProcessEvent (nevent)) return; // handled in user code
3399
3400     // determine first current if none
3401     bool curItemSet = false;
3402     if (!m_curItem) {
3403         m_curItem = (wxTreeListItem*)GetRootItem().m_pItem;
3404         if (HasFlag(wxTR_HIDE_ROOT)) {
3405 #if !wxCHECK_VERSION(2, 5, 0)
3406             long cookie = 0;
3407 #else
3408             wxTreeItemIdValue cookie = 0;
3409 #endif
3410             m_curItem = (wxTreeListItem*)GetFirstChild (m_curItem, cookie).m_pItem;
3411         }
3412         curItemSet = true;
3413     }
3414     if (!m_curItem) return; // do nothing if empty tree
3415
3416     // remember item at shift down
3417     if (HasFlag(wxTR_MULTIPLE) && event.ShiftDown()) {
3418         if (!m_shiftItem) m_shiftItem = m_curItem;
3419     }else{
3420         m_shiftItem = (wxTreeListItem*)NULL;
3421     }
3422
3423     // process all cases
3424     wxTreeItemId newItem = (wxTreeItemId*)NULL;
3425     switch (event.GetKeyCode()) {
3426
3427         // '+': Expand subtree
3428         case '+':
3429         case WXK_ADD: {
3430             if (m_curItem->HasPlus() && !IsExpanded (m_curItem)) Expand (m_curItem);
3431         }break;
3432
3433         // '-': collapse subtree
3434         case '-':
3435         case WXK_SUBTRACT: {
3436             if (m_curItem->HasPlus() && IsExpanded (m_curItem)) Collapse (m_curItem);
3437         }break;
3438
3439         // '*': expand/collapse all subtrees // TODO: Mak it more useful
3440         case '*':
3441         case WXK_MULTIPLY: {
3442             if (m_curItem->HasPlus() && !IsExpanded (m_curItem)) {
3443                 ExpandAll (m_curItem);
3444             }else if (m_curItem->HasPlus()) {
3445                 Collapse (m_curItem); // TODO: CollapseAll
3446             }
3447         }break;
3448
3449         // ' ': toggle current item
3450         case ' ': {
3451             SelectItem (m_curItem, (wxTreeListItem*)NULL, false);
3452         }break;
3453
3454         // <RETURN>: activate current item
3455         case WXK_RETURN: {
3456             wxTreeEvent aevent (wxEVT_COMMAND_TREE_ITEM_ACTIVATED, m_owner->GetId());
3457 #if !wxCHECK_VERSION(2, 5, 0)
3458             aevent.SetItem ((long)m_curItem);
3459 #else
3460             aevent.SetItem (m_curItem);
3461 #endif
3462             aevent.SetEventObject (m_owner);
3463             m_owner->GetEventHandler()->ProcessEvent (aevent);
3464         }break;
3465
3466         // <BKSP>: go to the parent without collapsing
3467         case WXK_BACK: {
3468             newItem = GetItemParent (m_curItem);
3469             if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) {
3470                 newItem = GetPrevSibling (m_curItem); // get sibling instead of root
3471             }
3472         }break;
3473
3474         // <UP>: go to the previous sibling or to the last of its children, to the parent
3475         case WXK_UP: {
3476             newItem = GetPrevSibling (m_curItem);
3477             if (newItem) {
3478 #if !wxCHECK_VERSION(2, 5, 0)
3479                 long cookie = 0;
3480 #else
3481                 wxTreeItemIdValue cookie = 0;
3482 #endif
3483                 while (IsExpanded (newItem) && HasChildren (newItem)) {
3484                     newItem = GetLastChild (newItem, cookie);
3485                 }
3486             }else {
3487                 newItem = GetItemParent (m_curItem);
3488                 if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) {
3489                     newItem = (wxTreeItemId*)NULL; // don't go to root if it is hidden
3490                 }
3491             }
3492         }break;
3493
3494         // <LEFT>: if expanded collapse subtree, else go to the parent
3495         case WXK_LEFT: {
3496             if (IsExpanded (m_curItem)) {
3497                 Collapse (m_curItem);
3498             }else{
3499                 newItem = GetItemParent (m_curItem);
3500                 if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) {
3501                     newItem = GetPrevSibling (m_curItem); // go to sibling if it is hidden
3502                 }
3503             }
3504         }break;
3505
3506         // <RIGHT>: if possible expand subtree, else go go to the first child
3507         case WXK_RIGHT: {
3508             if (m_curItem->HasPlus() && !IsExpanded (m_curItem)) {
3509                 Expand (m_curItem);
3510             }else{
3511                 if (IsExpanded (m_curItem) && HasChildren (m_curItem)) {
3512 #if !wxCHECK_VERSION(2, 5, 0)
3513                     long cookie = 0;
3514 #else
3515                     wxTreeItemIdValue cookie = 0;
3516 #endif
3517                     newItem = GetFirstChild (m_curItem, cookie);
3518                 }
3519             }
3520         }break;
3521
3522         // <DOWN>: if expanded go to the first child, else to the next sibling, ect
3523         case WXK_DOWN: {
3524             if (curItemSet) {
3525                 newItem = m_curItem;
3526             }else{
3527                 if (IsExpanded (m_curItem) && HasChildren (m_curItem)) {
3528 #if !wxCHECK_VERSION(2, 5, 0)
3529                     long cookie = 0;
3530 #else
3531                     wxTreeItemIdValue cookie = 0;
3532 #endif
3533                     newItem = GetFirstChild( m_curItem, cookie );
3534                 }
3535                 if (!newItem) {
3536                     wxTreeItemId parent = m_curItem;
3537                     do {
3538                         newItem = GetNextSibling (parent);
3539                         parent = GetItemParent (parent);
3540                     } while (!newItem && parent);
3541                 }
3542             }
3543         }break;
3544
3545         // <END>: go to last item of the root
3546         case WXK_END: {
3547 #if !wxCHECK_VERSION(2, 5, 0)
3548             long cookie = 0;
3549 #else
3550             wxTreeItemIdValue cookie = 0;
3551 #endif
3552             newItem = GetLastChild (GetRootItem(), cookie);
3553         }break;
3554
3555         // <HOME>: go to root
3556         case WXK_HOME: {
3557             newItem = GetRootItem();
3558             if (HasFlag(wxTR_HIDE_ROOT)) {
3559 #if !wxCHECK_VERSION(2, 5, 0)
3560                 long cookie = 0;
3561 #else
3562                 wxTreeItemIdValue cookie = 0;
3563 #endif
3564                 newItem = GetFirstChild (newItem, cookie);
3565             }
3566         }break;
3567
3568         // any char: go to the next matching string
3569         default:
3570             if (event.GetKeyCode() >= (int)' ') {
3571                 if (!m_findTimer->IsRunning()) m_findStr.Clear();
3572                 m_findStr.Append (event.GetKeyCode());
3573                 m_findTimer->Start (FIND_TIMER_TICKS, wxTIMER_ONE_SHOT);
3574                 wxTreeItemId prev = m_curItem? (wxTreeItemId*)m_curItem: (wxTreeItemId*)NULL;
3575                 while (true) {
3576                     newItem = FindItem (prev, m_findStr, wxTL_MODE_NAV_EXPANDED |
3577                                                          wxTL_MODE_FIND_PARTIAL |
3578                                                          wxTL_MODE_FIND_NOCASE);
3579                     if (newItem || (m_findStr.Length() <= 1)) break;
3580                     m_findStr.RemoveLast();
3581                 };
3582             }
3583             event.Skip();
3584
3585     }
3586
3587     // select and show the new item
3588     if (newItem) {
3589         if (!event.ControlDown()) {
3590             bool unselect_others = !((event.ShiftDown() || event.ControlDown()) &&
3591                                       HasFlag(wxTR_MULTIPLE));
3592             SelectItem (newItem, m_shiftItem, unselect_others);
3593         }
3594         EnsureVisible (newItem);
3595         wxTreeListItem *oldItem = m_curItem;
3596         m_curItem = (wxTreeListItem*)newItem.m_pItem; // make the new item the current item
3597         RefreshLine (oldItem);
3598     }
3599
3600 }
3601
3602 wxTreeItemId wxTreeListMainWindow::HitTest (const wxPoint& point, int& flags, int& column) {
3603
3604     int w, h;
3605     GetSize(&w, &h);
3606     flags=0;
3607     column = -1;
3608     if (point.x<0) flags |= wxTREE_HITTEST_TOLEFT;
3609     if (point.x>w) flags |= wxTREE_HITTEST_TORIGHT;
3610     if (point.y<0) flags |= wxTREE_HITTEST_ABOVE;
3611     if (point.y>h) flags |= wxTREE_HITTEST_BELOW;
3612     if (flags) return wxTreeItemId();
3613
3614     if (!m_rootItem) {
3615         flags = wxTREE_HITTEST_NOWHERE;
3616         column = -1;
3617         return wxTreeItemId();
3618     }
3619
3620     wxTreeListItem *hit = m_rootItem->HitTest (CalcUnscrolledPosition(point),
3621                                                this, flags, column, 0);
3622     if (!hit) {
3623         flags = wxTREE_HITTEST_NOWHERE;
3624         column = -1;
3625         return wxTreeItemId();
3626     }
3627     return hit;
3628 }
3629
3630 // get the bounding rectangle of the item (or of its label only)
3631 bool wxTreeListMainWindow::GetBoundingRect (const wxTreeItemId& itemId, wxRect& rect,
3632                                             bool WXUNUSED(textOnly)) const {
3633     wxCHECK_MSG (itemId.IsOk(), false, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") );
3634
3635     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
3636
3637     int xUnit, yUnit;
3638     GetScrollPixelsPerUnit (&xUnit, &yUnit);
3639     int startX, startY;
3640     GetViewStart(& startX, & startY);
3641
3642     rect.x = item->GetX() - startX * xUnit;
3643     rect.y = item->GetY() - startY * yUnit;
3644     rect.width = item->GetWidth();
3645     rect.height = GetLineHeight (item);
3646
3647     return true;
3648 }
3649
3650 /* **** */
3651
3652 void wxTreeListMainWindow::EditLabel (const wxTreeItemId& item, int column) {
3653     if (!item.IsOk()) return;
3654     if (!((column >= 0) && (column < GetColumnCount()))) return;
3655
3656     m_editItem = (wxTreeListItem*) item.m_pItem;
3657
3658     wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, m_owner->GetId() );
3659 #if !wxCHECK_VERSION(2, 5, 0)
3660     te.SetItem ((long)m_editItem);
3661 #else
3662     te.SetItem (m_editItem);
3663 #endif
3664     te.SetInt (column);
3665     te.SetEventObject (m_owner );
3666     m_owner->GetEventHandler()->ProcessEvent (te);
3667
3668     if (!te.IsAllowed()) return;
3669
3670     // ensure that the position of the item it calculated in any case
3671     if (m_dirty) CalculatePositions();
3672
3673     wxTreeListHeaderWindow* header_win = m_owner->GetHeaderWindow();
3674     int x = 0;
3675     int y = m_editItem->GetY() + 1; // wxTextCtrl needs 1 pixels above the text
3676     int w = 0;
3677     int h = m_editItem->GetHeight();
3678     long style = 0;
3679     if (column == GetMainColumn()) {
3680         x += m_editItem->GetTextX() - 2; // wxTextCtrl needs 2 pixels before the text
3681         w = wxMin (m_editItem->GetWidth(), m_owner->GetHeaderWindow()->GetWidth() - x);
3682     }else{
3683         for (int i = 0; i < column; ++i) x += header_win->GetColumnWidth (i); // start of column
3684         switch (header_win->GetColumnAlignment (column)) {
3685             case wxALIGN_LEFT: {style = wxTE_LEFT; break;}
3686             case wxALIGN_RIGHT: {style = wxTE_RIGHT; break;}
3687             case wxALIGN_CENTER: {style = wxTE_CENTER; break;}
3688         }
3689         w = header_win->GetColumnWidth (column); // width of column
3690     }
3691
3692     wxClientDC dc (this);
3693     PrepareDC (dc);
3694     x = dc.LogicalToDeviceX (x);
3695     y = dc.LogicalToDeviceY (y);
3696
3697     wxEditTextCtrl *text = new wxEditTextCtrl (this, -1, &m_renameAccept, &m_renameRes,
3698                                                this, m_editItem->GetText (column),
3699                                                wxPoint (x, y), wxSize (w, h), style);
3700     text->SetFocus();
3701 }
3702
3703 void wxTreeListMainWindow::OnRenameTimer() {
3704     EditLabel (m_curItem, m_curColumn);
3705 }
3706
3707 void wxTreeListMainWindow::OnRenameAccept() {
3708
3709     // TODO if the validator fails this causes a crash
3710     wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, m_owner->GetId() );
3711 #if !wxCHECK_VERSION(2, 5, 0)
3712     le.SetItem((long)m_editItem);
3713 #else
3714     le.SetItem(m_editItem);
3715 #endif
3716     le.SetEventObject( /*this*/m_owner );
3717     le.SetLabel( m_renameRes );
3718     m_owner->GetEventHandler()->ProcessEvent( le );
3719
3720     if (!le.IsAllowed()) return;
3721
3722     SetItemText (m_editItem, m_curColumn, m_renameRes);
3723 }
3724
3725 void wxTreeListMainWindow::OnMouse (wxMouseEvent &event) {
3726     if (!m_rootItem) return;
3727
3728     // we process left mouse up event (enables in-place edit), right down
3729     // (pass to the user code), left dbl click (activate item) and
3730     // dragging/moving events for items drag-and-drop
3731     if (!(event.LeftDown() ||
3732           event.LeftUp() ||
3733           event.RightDown() ||
3734           event.RightUp() ||
3735           event.LeftDClick() ||
3736           event.Dragging() ||
3737           (event.GetWheelRotation() != 0 )/*? TODO ||
3738           event.Moving()?*/)) {
3739         m_owner->GetEventHandler()->ProcessEvent (event);
3740         return;
3741     }
3742
3743     // set focus if window clicked
3744     if (event.LeftDown() || event.RightDown()) SetFocus();
3745
3746     // determine event
3747     wxPoint p = wxPoint (event.GetX(), event.GetY());
3748     int flags = 0;
3749     wxTreeListItem *item = m_rootItem->HitTest (CalcUnscrolledPosition (p),
3750                                                 this, flags, m_curColumn, 0);
3751
3752     // we only process dragging here
3753     if (event.Dragging()){
3754         if (m_isDragging) return; // nothing to do, already done
3755         if (item == NULL) return; // we need an item to dragging
3756
3757         // determine drag start
3758         if (m_dragCount == 0) {
3759             m_dragTimer->Start (DRAG_TIMER_TICKS, wxTIMER_ONE_SHOT);
3760         }
3761         m_dragCount++;
3762         if (m_dragCount < 3) return; // minimum drag 3 pixel
3763         if (m_dragTimer->IsRunning()) return;
3764
3765         // we're going to drag
3766         m_dragCount = 0;
3767         m_isDragging = true;
3768         CaptureMouse();
3769         RefreshSelected();
3770
3771         // send drag start event
3772         wxEventType command = event.LeftIsDown()
3773                               ? wxEVT_COMMAND_TREE_BEGIN_DRAG
3774                               : wxEVT_COMMAND_TREE_BEGIN_RDRAG;
3775         wxTreeEvent nevent (command, m_owner->GetId());
3776         nevent.SetEventObject (m_owner);
3777 #if !wxCHECK_VERSION(2, 5, 0)
3778         nevent.SetItem ((long)item); // the item the drag is ended
3779 #else
3780         nevent.SetItem (item); // the item the drag is ended
3781 #endif
3782         nevent.Veto(); // dragging must be explicit allowed!
3783         m_owner->GetEventHandler()->ProcessEvent (nevent);
3784
3785     }else if (m_isDragging) { // any other event but not event.Dragging()
3786
3787         // end dragging
3788         m_dragCount = 0;
3789         m_isDragging = false;
3790         if (HasCapture()) ReleaseMouse();
3791         RefreshSelected();
3792
3793         // send drag end event event
3794         wxTreeEvent nevent (wxEVT_COMMAND_TREE_END_DRAG, m_owner->GetId());
3795         nevent.SetEventObject (m_owner);
3796 #if !wxCHECK_VERSION(2, 5, 0)
3797         nevent.SetItem ((long)item); // the item the drag is started
3798 #else
3799         nevent.SetItem (item); // the item the drag is started
3800 #endif
3801         nevent.SetPoint (p);
3802         m_owner->GetEventHandler()->ProcessEvent (nevent);
3803
3804     }else if (m_dragCount > 0) { // just in case dragging is initiated
3805
3806         // end dragging
3807         m_dragCount = 0;
3808
3809     }
3810
3811     // we process only the messages which happen on tree items
3812     if (item == NULL) {
3813         m_owner->GetEventHandler()->ProcessEvent (event);
3814         return;
3815     }
3816
3817     // remember item at shift down
3818     if (event.ShiftDown())  {
3819         if (!m_shiftItem) m_shiftItem = m_curItem;
3820     }else{
3821         m_shiftItem = (wxTreeListItem*)NULL;
3822     }
3823
3824     if (event.RightUp()) {
3825
3826         SetFocus();
3827         wxTreeEvent nevent (wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, m_owner->GetId());
3828         nevent.SetEventObject (m_owner);
3829 #if !wxCHECK_VERSION(2, 5, 0)
3830         nevent.SetItem ((long)item); // the item clicked
3831 #else
3832         nevent.SetItem (item); // the item clicked
3833 #endif
3834         nevent.SetInt (m_curColumn); // the colum clicked
3835         nevent.SetPoint (p);
3836         m_owner->GetEventHandler()->ProcessEvent (nevent);
3837
3838     }else if (event.LeftUp()) {
3839
3840         if (m_lastOnSame) {
3841             if ((item == m_curItem) && (m_curColumn != -1) &&
3842                 (m_owner->GetHeaderWindow()->IsColumnEditable (m_curColumn)) &&
3843                 (flags & (wxTREE_HITTEST_ONITEMLABEL | wxTREE_HITTEST_ONITEMCOLUMN))){
3844                 m_renameTimer->Start (RENAME_TIMER_TICKS, wxTIMER_ONE_SHOT);
3845             }
3846             m_lastOnSame = false;
3847         }
3848
3849         if (((flags & wxTREE_HITTEST_ONITEMBUTTON) ||
3850              (flags & wxTREE_HITTEST_ONITEMICON)) &&
3851             HasButtons() && item->HasPlus()) {
3852
3853
3854             // only toggle the item for a single click, double click on
3855             // the button doesn't do anything (it toggles the item twice)
3856             if (event.LeftDown()) Toggle (item);
3857
3858             // don't select the item if the button was clicked
3859             return;
3860         }
3861
3862         // determine the selection if not done by left down
3863         if (!m_left_down_selection) {
3864             bool unselect_others = !((event.ShiftDown() || event.ControlDown()) &&
3865                                      HasFlag(wxTR_MULTIPLE));
3866
3867             SelectItem (item, m_shiftItem, unselect_others);
3868             EnsureVisible (item);
3869             //  LG  m_curItem = item; // make the new item the current item
3870         }else{
3871             m_left_down_selection = false;
3872         }
3873
3874     }else if (event.LeftDown() || event.RightDown() || event.LeftDClick()) {
3875
3876         if (event.LeftDown() || event.RightDown()) {
3877             SetFocus();
3878             m_lastOnSame = item == m_curItem;
3879         }
3880
3881         if (((flags & wxTREE_HITTEST_ONITEMBUTTON) ||
3882              (flags & wxTREE_HITTEST_ONITEMICON)) &&
3883             item->HasPlus()) {
3884
3885             // only toggle the item for a single click, double click on
3886             // the button doesn't do anything (it toggles the item twice)
3887
3888             if (event.LeftDown()) Toggle (item);
3889
3890             // don't select the item if the button was clicked
3891             return;
3892         }
3893
3894         // determine the selection if the current item is not selected
3895         if (!item->IsSelected()) {
3896             bool unselect_others = !((event.ShiftDown() || event.ControlDown()) &&
3897                                      HasFlag(wxTR_MULTIPLE));
3898             SelectItem (item, m_shiftItem, unselect_others);
3899             EnsureVisible (item);
3900             // LG m_curItem = item; // make the new item the current item
3901             m_left_down_selection = true;
3902         }
3903
3904         // For some reason, Windows isn't recognizing a left double-click,
3905         // so we need to simulate it here.  Allow 200 milliseconds for now.
3906         if (event.LeftDClick()) {
3907
3908             // double clicking should not start editing the item label
3909             m_renameTimer->Stop();
3910             m_lastOnSame = false;
3911
3912             // send activate event first
3913             wxTreeEvent nevent (wxEVT_COMMAND_TREE_ITEM_ACTIVATED, m_owner->GetId());
3914             nevent.SetEventObject (m_owner);
3915 #if !wxCHECK_VERSION(2, 5, 0)
3916             nevent.SetItem ((long)item); // the item clicked
3917 #else
3918             nevent.SetItem (item); // the item clicked
3919 #endif
3920             nevent.SetInt (m_curColumn); // the colum clicked
3921             nevent.SetPoint (p);
3922             if (!m_owner->GetEventHandler()->ProcessEvent (nevent)) {
3923
3924                 // if the user code didn't process the activate event,
3925                 // handle it ourselves by toggling the item when it is
3926                 // double clicked
3927
3928                 if (item->HasPlus()) Toggle(item);
3929             }
3930         }
3931
3932     }else{ // any other event skip just in case
3933
3934         event.Skip();
3935
3936     }
3937 }
3938
3939 void wxTreeListMainWindow::OnIdle (wxIdleEvent &WXUNUSED(event)) {
3940     /* after all changes have been done to the tree control,
3941      * we actually redraw the tree when everything is over */
3942
3943     if (!m_dirty) return;
3944
3945     m_dirty = false;
3946
3947     CalculatePositions();
3948     Refresh();
3949     AdjustMyScrollbars();
3950 }
3951
3952 void wxTreeListMainWindow::OnScroll (wxScrollWinEvent& event) {
3953     // FIXME
3954 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
3955     wxScrolledWindow::OnScroll(event);
3956 #else
3957     HandleOnScroll( event );
3958 #endif
3959
3960     if(event.GetOrientation() == wxHORIZONTAL) {
3961         m_owner->GetHeaderWindow()->Refresh();
3962         m_owner->GetHeaderWindow()->Update();
3963     }
3964 }
3965
3966 void wxTreeListMainWindow::CalculateSize (wxTreeListItem *item, wxDC &dc) {
3967     wxCoord text_w = 0;
3968     wxCoord text_h = 0;
3969
3970     dc.SetFont (GetItemFont (item));
3971
3972     dc.GetTextExtent (item->GetText (m_main_column), &text_w, &text_h);
3973
3974     // restore normal font
3975     dc.SetFont (m_normalFont);
3976
3977     int total_h = (m_imgHeight > text_h) ? m_imgHeight : text_h;
3978     if (total_h < 30) { // add 10% space if greater than 30 pixels
3979       total_h += 2; // minimal 2 pixel space
3980     }else{
3981       total_h += total_h / 10; // otherwise 10% space
3982     }
3983
3984     item->SetHeight (total_h);
3985     if (total_h > m_lineHeight) m_lineHeight = total_h;
3986     item->SetWidth(m_imgWidth + text_w +2);
3987 }
3988
3989 // -----------------------------------------------------------------------------
3990 void wxTreeListMainWindow::CalculateLevel (wxTreeListItem *item, wxDC &dc,
3991                                            int level, int &y, int x_colstart) {
3992
3993     // calculate position of vertical lines
3994     int x = x_colstart + MARGIN; // start of column
3995     if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
3996     if (HasButtons()) {
3997         x += (m_btnWidth-m_btnWidth2); // half button space
3998     }else{
3999         x += (m_indent-m_indent/2);
4000     }
4001     if (HasFlag(wxTR_HIDE_ROOT)) {
4002       // LG
4003       //        x += m_indent * (level-2); // indent but not level 1
4004       x += m_indent * (level-1); // indent but not level 1
4005
4006     }else{
4007         x += m_indent * level; // indent according to level
4008     }
4009
4010     // a hidden root is not evaluated, but its children are always
4011     if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) goto Recurse;
4012
4013     CalculateSize( item, dc );
4014
4015     // set its position
4016     item->SetX (x);
4017     item->SetY (y);
4018     y += GetLineHeight(item);
4019
4020     // we don't need to calculate collapsed branches
4021     if ( !item->IsExpanded() ) return;
4022
4023 Recurse:
4024     wxArrayTreeListItems& children = item->GetChildren();
4025     long n, count = (long)children.Count();
4026     ++level;
4027     for (n = 0; n < count; ++n) {
4028         CalculateLevel( children[n], dc, level, y, x_colstart );  // recurse
4029     }
4030 }
4031
4032 void wxTreeListMainWindow::CalculatePositions() {
4033     if ( !m_rootItem ) return;
4034
4035     wxClientDC dc(this);
4036     PrepareDC( dc );
4037
4038     dc.SetFont( m_normalFont );
4039
4040     dc.SetPen( m_dottedPen );
4041     //if(GetImageList() == NULL)
4042     // m_lineHeight = (int)(dc.GetCharHeight() + 4);
4043
4044     int y = 2;
4045     int x_colstart = 0;
4046     for (int i = 0; i < (int)GetMainColumn(); ++i) {
4047         if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
4048         x_colstart += m_owner->GetHeaderWindow()->GetColumnWidth(i);
4049     }
4050     CalculateLevel( m_rootItem, dc, 0, y, x_colstart ); // start recursion
4051 }
4052
4053 void wxTreeListMainWindow::RefreshSubtree (wxTreeListItem *item) {
4054     if (m_dirty) return;
4055
4056     wxClientDC dc(this);
4057     PrepareDC(dc);
4058
4059     int cw = 0;
4060     int ch = 0;
4061     GetVirtualSize( &cw, &ch );
4062
4063     wxRect rect;
4064     rect.x = dc.LogicalToDeviceX( 0 );
4065     rect.width = cw;
4066     rect.y = dc.LogicalToDeviceY( item->GetY() - 2 );
4067     rect.height = ch;
4068
4069     Refresh (true, &rect );
4070     AdjustMyScrollbars();
4071 }
4072
4073 void wxTreeListMainWindow::RefreshLine (wxTreeListItem *item) {
4074
4075   //  return;
4076   //  std::cout << "RefreshLine = "<<item<<std::endl;
4077   //return;
4078
4079   if (m_dirty) return;
4080
4081     wxClientDC dc(this);
4082     PrepareDC( dc );
4083
4084     int cw = 0;
4085     int ch = 0;
4086     GetVirtualSize( &cw, &ch );
4087
4088     wxRect rect;
4089     rect.x = dc.LogicalToDeviceX( 0 );
4090     rect.y = dc.LogicalToDeviceY( item->GetY() );
4091     rect.width = cw;
4092     rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6;
4093
4094     Refresh (true, &rect);
4095 }
4096
4097 void wxTreeListMainWindow::RefreshSelected() 
4098 {
4099
4100   long count = m_selected.GetCount();
4101   for (long n = 0; n < count; n++ ) 
4102     {
4103       RefreshLine (m_selected[n]);
4104     }
4105 }
4106
4107 /*
4108 void wxTreeListMainWindow::RefreshSelectedUnder (wxTreeListItem *item) {
4109     if (item->IsSelected()) {
4110         RefreshLine (item);
4111     }
4112
4113     const wxArrayTreeListItems& children = item->GetChildren();
4114     long count = children.GetCount();
4115     for (long n = 0; n < count; n++ ) {
4116         RefreshSelectedUnder (children[n]);
4117     }
4118 }
4119 */
4120
4121 // ----------------------------------------------------------------------------
4122 // changing colours: we need to refresh the tree control
4123 // ----------------------------------------------------------------------------
4124
4125 bool wxTreeListMainWindow::SetBackgroundColour (const wxColour& colour) {
4126     if (!wxWindow::SetBackgroundColour(colour)) return false;
4127
4128     Refresh();
4129     return true;
4130 }
4131
4132 bool wxTreeListMainWindow::SetForegroundColour (const wxColour& colour) {
4133     if (!wxWindow::SetForegroundColour(colour)) return false;
4134
4135     Refresh();
4136     return true;
4137 }
4138
4139 void wxTreeListMainWindow::SetItemText (const wxTreeItemId& itemId, int column,
4140                                         const wxString& text) {
4141     wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
4142
4143     wxClientDC dc (this);
4144     wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem;
4145     item->SetText (column, text);
4146     CalculateSize (item, dc);
4147     RefreshLine (item);
4148 }
4149
4150 wxString wxTreeListMainWindow::GetItemText (const wxTreeItemId& itemId,
4151                                             int column) const {
4152     wxCHECK_MSG (itemId.IsOk(), _T(""), _T("invalid tree item") );
4153
4154     if( IsVirtual() )   return m_owner->OnGetItemText(((wxTreeListItem*) itemId.m_pItem)->GetData(),column);
4155     else                return ((wxTreeListItem*) itemId.m_pItem)->GetText (column);
4156 }
4157
4158 wxString wxTreeListMainWindow::GetItemText (wxTreeItemData* item,
4159 int column) const {
4160    wxASSERT_MSG( IsVirtual(), _T("can be used only with virtual control") );
4161    return m_owner->OnGetItemText(item,column);
4162 }
4163
4164 void wxTreeListMainWindow::SetFocus() {
4165     wxWindow::SetFocus();
4166 }
4167
4168 wxFont wxTreeListMainWindow::GetItemFont (wxTreeListItem *item) {
4169     wxTreeItemAttr *attr = item->GetAttributes();
4170
4171     if (attr && attr->HasFont()) {
4172         return attr->GetFont();
4173     }else if (item->IsBold()) {
4174         return m_boldFont;
4175     }else{
4176         return m_normalFont;
4177    }
4178 }
4179
4180 int wxTreeListMainWindow::GetItemWidth (int column, wxTreeListItem *item) {
4181     if (!item) return 0;
4182
4183     // determine item width
4184     int w = 0, h = 0;
4185     wxFont font = GetItemFont (item);
4186     GetTextExtent (item->GetText (column), &w, &h, NULL, NULL, font.Ok()? &font: NULL);
4187     w += 2*MARGIN;
4188
4189     // calculate width
4190     int width = w + 2*MARGIN;
4191     if (column == GetMainColumn()) {
4192         width += MARGIN;
4193         if (HasFlag(wxTR_LINES_AT_ROOT)) width += LINEATROOT;
4194         if (HasButtons()) width += m_btnWidth + LINEATROOT;
4195         if (item->GetCurrentImage() != NO_IMAGE) width += m_imgWidth;
4196
4197         // count indent level
4198         int level = 0;
4199         wxTreeListItem *parent = item->GetItemParent();
4200         wxTreeListItem *root = (wxTreeListItem*)GetRootItem().m_pItem;
4201         while (parent && (!HasFlag(wxTR_HIDE_ROOT) || (parent != root))) {
4202             level++;
4203             parent = parent->GetItemParent();
4204         }
4205         if (level) width += level * GetIndent();
4206     }
4207
4208     return width;
4209 }
4210
4211 int wxTreeListMainWindow::GetBestColumnWidth (int column, wxTreeItemId parent) {
4212     int maxWidth, h;
4213     GetClientSize (&maxWidth, &h);
4214     int width = 0;
4215
4216     // get root if on item
4217     if (!parent.IsOk()) parent = GetRootItem();
4218
4219     // add root width
4220     if (!HasFlag(wxTR_HIDE_ROOT)) {
4221         int w = GetItemWidth (column, (wxTreeListItem*)parent.m_pItem);
4222         if (width < w) width = w;
4223         if (width > maxWidth) return maxWidth;
4224     }
4225
4226     wxTreeItemIdValue cookie = 0;
4227     wxTreeItemId item = GetFirstChild (parent, cookie);
4228     while (item.IsOk()) {
4229         int w = GetItemWidth (column, (wxTreeListItem*)item.m_pItem);
4230         if (width < w) width = w;
4231         if (width > maxWidth) return maxWidth;
4232
4233         // check the children of this item
4234         if (((wxTreeListItem*)item.m_pItem)->IsExpanded()) {
4235             int w = GetBestColumnWidth (column, item);
4236             if (width < w) width = w;
4237             if (width > maxWidth) return maxWidth;
4238         }
4239
4240         // next sibling
4241         item = GetNextChild (parent, cookie);
4242     }
4243
4244     return width;
4245 }
4246
4247
4248 //-----------------------------------------------------------------------------
4249 //  wxTreeListCtrl
4250 //-----------------------------------------------------------------------------
4251
4252 //IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl, wxControl);
4253 //IMPLEMENT_CLASS(wxTreeListCtrl, wxControl);
4254
4255 BEGIN_EVENT_TABLE(wxTreeListCtrl, wxControl)
4256     EVT_SIZE(wxTreeListCtrl::OnSize)
4257 END_EVENT_TABLE();
4258
4259 bool wxTreeListCtrl::Create(wxWindow *parent, wxWindowID id,
4260                             const wxPoint& pos,
4261                             const wxSize& size,
4262                             long style, const wxValidator &validator,
4263                             const wxString& name)
4264 {
4265     long main_style = style & ~(wxSIMPLE_BORDER|wxSUNKEN_BORDER|wxDOUBLE_BORDER|
4266                                 wxRAISED_BORDER|wxSTATIC_BORDER);
4267     long ctrl_style = style & ~(wxVSCROLL|wxHSCROLL);
4268
4269     if (!wxControl::Create(parent, id, pos, size, ctrl_style, validator, name)) {
4270        return false;
4271     }
4272     m_main_win = new wxTreeListMainWindow (this, -1, wxPoint(0, 0), size,
4273                                            main_style, validator);
4274     m_header_win = new wxTreeListHeaderWindow (this, -1, m_main_win,
4275                                                wxPoint(0, 0), wxDefaultSize,
4276                                                wxTAB_TRAVERSAL);
4277     CalculateAndSetHeaderHeight();
4278     return true;
4279 }
4280
4281 void wxTreeListCtrl::CalculateAndSetHeaderHeight()
4282 {
4283     if (m_header_win) {
4284
4285         // we use 'g' to get the descent, too
4286         int w, h, d;
4287         m_header_win->GetTextExtent(_T("Hg"), &w, &h, &d);
4288         h += d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
4289         h = 0 ;
4290         // only update if changed
4291         if (h != m_headerHeight) {
4292             m_headerHeight = h;
4293             DoHeaderLayout();
4294         }
4295     }
4296 }
4297
4298 void wxTreeListCtrl::DoHeaderLayout()
4299 {
4300     int w, h;
4301     GetClientSize(&w, &h);
4302     if (m_header_win) {
4303         m_header_win->SetSize (0, 0, w, m_headerHeight);
4304         m_header_win->Refresh();
4305     }
4306     if (m_main_win) {
4307         m_main_win->SetSize (0, m_headerHeight + 1, w, h - m_headerHeight - 1);
4308     }
4309 }
4310
4311 void wxTreeListCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
4312 {
4313     DoHeaderLayout();
4314 }
4315
4316 size_t wxTreeListCtrl::GetCount() const { return m_main_win->GetCount(); }
4317
4318 unsigned int wxTreeListCtrl::GetIndent() const
4319 { return m_main_win->GetIndent(); }
4320
4321 void wxTreeListCtrl::SetIndent(unsigned int indent)
4322 { m_main_win->SetIndent(indent); }
4323
4324 unsigned int wxTreeListCtrl::GetLineSpacing() const
4325 { return m_main_win->GetLineSpacing(); }
4326
4327 void wxTreeListCtrl::SetLineSpacing(unsigned int spacing)
4328 { m_main_win->SetLineSpacing(spacing); }
4329
4330 wxImageList* wxTreeListCtrl::GetImageList() const
4331 { return m_main_win->GetImageList(); }
4332
4333 wxImageList* wxTreeListCtrl::GetStateImageList() const
4334 { return m_main_win->GetStateImageList(); }
4335
4336 wxImageList* wxTreeListCtrl::GetButtonsImageList() const
4337 { return m_main_win->GetButtonsImageList(); }
4338
4339 void wxTreeListCtrl::SetImageList(wxImageList* imageList)
4340 { m_main_win->SetImageList(imageList); }
4341
4342 void wxTreeListCtrl::SetStateImageList(wxImageList* imageList)
4343 { m_main_win->SetStateImageList(imageList); }
4344
4345 void wxTreeListCtrl::SetButtonsImageList(wxImageList* imageList)
4346 { m_main_win->SetButtonsImageList(imageList); }
4347
4348 void wxTreeListCtrl::AssignImageList(wxImageList* imageList)
4349 { m_main_win->AssignImageList(imageList); }
4350
4351 void wxTreeListCtrl::AssignStateImageList(wxImageList* imageList)
4352 { m_main_win->AssignStateImageList(imageList); }
4353
4354 void wxTreeListCtrl::AssignButtonsImageList(wxImageList* imageList)
4355 { m_main_win->AssignButtonsImageList(imageList); }
4356
4357 wxString wxTreeListCtrl::GetItemText(const wxTreeItemId& item, int column) const
4358 { return m_main_win->GetItemText (item, column); }
4359
4360 int wxTreeListCtrl::GetItemImage(const wxTreeItemId& item, int column,
4361                                  wxTreeItemIcon which) const
4362 { return m_main_win->GetItemImage(item, column, which); }
4363
4364 wxTreeItemData* wxTreeListCtrl::GetItemData(const wxTreeItemId& item) const
4365 { return m_main_win->GetItemData(item); }
4366
4367 bool wxTreeListCtrl::GetItemBold(const wxTreeItemId& item) const
4368 { return m_main_win->GetItemBold(item); }
4369
4370 wxColour wxTreeListCtrl::GetItemTextColour(const wxTreeItemId& item) const
4371 { return m_main_win->GetItemTextColour(item); }
4372
4373 wxColour wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId& item)
4374     const
4375 { return m_main_win->GetItemBackgroundColour(item); }
4376
4377 wxFont wxTreeListCtrl::GetItemFont(const wxTreeItemId& item) const
4378 { return m_main_win->GetItemFont(item); }
4379
4380
4381 void wxTreeListCtrl::SetItemText(const wxTreeItemId& item, int column,
4382                                  const wxString& text)
4383 { m_main_win->SetItemText (item, column, text); }
4384
4385 void wxTreeListCtrl::SetItemImage(const wxTreeItemId& item,
4386                                   int column,
4387                                   int image,
4388                                   wxTreeItemIcon which)
4389 { m_main_win->SetItemImage(item, column, image, which); }
4390
4391 void wxTreeListCtrl::SetItemData(const wxTreeItemId& item,
4392                                  wxTreeItemData* data)
4393 { m_main_win->SetItemData(item, data); }
4394
4395 void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
4396 { m_main_win->SetItemHasChildren(item, has); }
4397
4398 void wxTreeListCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
4399 { m_main_win->SetItemBold(item, bold); }
4400
4401 void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId& item,
4402                                        const wxColour& colour)
4403 { m_main_win->SetItemTextColour(item, colour); }
4404
4405 void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId& item,
4406                                              const wxColour& colour)
4407 { m_main_win->SetItemBackgroundColour(item, colour); }
4408
4409 void wxTreeListCtrl::SetItemFont(const wxTreeItemId& item,
4410                                  const wxFont& font)
4411 { m_main_win->SetItemFont(item, font); }
4412
4413 bool wxTreeListCtrl::SetFont(const wxFont& font)
4414 {
4415     if (m_header_win) {
4416         m_header_win->SetFont(font);
4417         CalculateAndSetHeaderHeight();
4418         m_header_win->Refresh();
4419     }
4420     if (m_main_win) {
4421         return m_main_win->SetFont(font);
4422     }else{
4423         return false;
4424     }
4425 }
4426
4427 void wxTreeListCtrl::SetWindowStyle(const long style)
4428 {
4429     if(m_main_win)
4430         m_main_win->SetWindowStyle(style);
4431     m_windowStyle = style;
4432     // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win
4433 }
4434
4435 long wxTreeListCtrl::GetWindowStyle() const
4436 {
4437     long style = m_windowStyle;
4438     if(m_main_win)
4439         style |= m_main_win->GetWindowStyle();
4440     return style;
4441 }
4442
4443 bool wxTreeListCtrl::IsVisible(const wxTreeItemId& item, bool fullRow) const
4444 { return m_main_win->IsVisible(item, fullRow); }
4445
4446 bool wxTreeListCtrl::HasChildren(const wxTreeItemId& item) const
4447 { return m_main_win->HasChildren(item); }
4448
4449 bool wxTreeListCtrl::IsExpanded(const wxTreeItemId& item) const
4450 { return m_main_win->IsExpanded(item); }
4451
4452 bool wxTreeListCtrl::IsSelected(const wxTreeItemId& item) const
4453 { return m_main_win->IsSelected(item); }
4454
4455 bool wxTreeListCtrl::IsBold(const wxTreeItemId& item) const
4456 { return m_main_win->IsBold(item); }
4457
4458 size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId& item, bool rec)
4459 { return m_main_win->GetChildrenCount(item, rec); }
4460
4461 wxTreeItemId wxTreeListCtrl::GetRootItem() const
4462 { return m_main_win->GetRootItem(); }
4463
4464 //wxTreeItemId wxTreeListCtrl::GetSelection() const
4465 //{ return m_main_win->GetSelection(); }
4466  wxTreeItemId wxTreeListCtrl::GetCurrent() const
4467  { return m_main_win->GetCurrent(); }
4468  
4469  // returns the number of currently selected items
4470  size_t wxTreeListCtrl::GetSelectionSize() const
4471  { return m_main_win->GetSelectionSize(); }
4472
4473 size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds& arr) const
4474 { return m_main_win->GetSelections(arr); }
4475
4476 wxTreeItemId wxTreeListCtrl::GetItemParent(const wxTreeItemId& item) const
4477 { return m_main_win->GetItemParent(item); }
4478
4479 #if !wxCHECK_VERSION(2, 5, 0)
4480 wxTreeItemId wxTreeListCtrl::GetFirstChild (const wxTreeItemId& item,
4481                                             long& cookie) const
4482 #else
4483 wxTreeItemId wxTreeListCtrl::GetFirstChild (const wxTreeItemId& item,
4484                                             wxTreeItemIdValue& cookie) const
4485 #endif
4486 { return m_main_win->GetFirstChild(item, cookie); }
4487
4488 #if !wxCHECK_VERSION(2, 5, 0)
4489 wxTreeItemId wxTreeListCtrl::GetNextChild (const wxTreeItemId& item,
4490                                            long& cookie) const
4491 #else
4492 wxTreeItemId wxTreeListCtrl::GetNextChild (const wxTreeItemId& item,
4493                                            wxTreeItemIdValue& cookie) const
4494 #endif
4495 { return m_main_win->GetNextChild(item, cookie); }
4496
4497 #if !wxCHECK_VERSION(2, 5, 0)
4498 wxTreeItemId wxTreeListCtrl::GetPrevChild (const wxTreeItemId& item,
4499                                            long& cookie) const
4500 #else
4501 wxTreeItemId wxTreeListCtrl::GetPrevChild (const wxTreeItemId& item,
4502                                            wxTreeItemIdValue& cookie) const
4503 #endif
4504 { return m_main_win->GetPrevChild(item, cookie); }
4505
4506 #if !wxCHECK_VERSION(2, 5, 0)
4507 wxTreeItemId wxTreeListCtrl::GetLastChild (const wxTreeItemId& item,
4508                                            long& cookie) const
4509 #else
4510 wxTreeItemId wxTreeListCtrl::GetLastChild (const wxTreeItemId& item,
4511                                            wxTreeItemIdValue& cookie) const
4512 #endif
4513 { return m_main_win->GetLastChild(item, cookie); }
4514
4515
4516 wxTreeItemId wxTreeListCtrl::GetNextSibling(const wxTreeItemId& item) const
4517 { return m_main_win->GetNextSibling(item); }
4518
4519 wxTreeItemId wxTreeListCtrl::GetPrevSibling(const wxTreeItemId& item) const
4520 { return m_main_win->GetPrevSibling(item); }
4521
4522 wxTreeItemId wxTreeListCtrl::GetNext(const wxTreeItemId& item) const
4523 { return m_main_win->GetNext(item, true); }
4524
4525 wxTreeItemId wxTreeListCtrl::GetPrev(const wxTreeItemId& item) const
4526 { return m_main_win->GetPrev(item, true); }
4527
4528 wxTreeItemId wxTreeListCtrl::GetFirstExpandedItem() const
4529 { return m_main_win->GetFirstExpandedItem(); }
4530
4531 wxTreeItemId wxTreeListCtrl::GetNextExpanded(const wxTreeItemId& item) const
4532 { return m_main_win->GetNextExpanded(item); }
4533
4534 wxTreeItemId wxTreeListCtrl::GetPrevExpanded(const wxTreeItemId& item) const
4535 { return m_main_win->GetPrevExpanded(item); }
4536
4537 wxTreeItemId wxTreeListCtrl::GetFirstVisibleItem(bool fullRow) const
4538 { return m_main_win->GetFirstVisibleItem(fullRow); }
4539
4540 wxTreeItemId wxTreeListCtrl::GetNextVisible(const wxTreeItemId& item, bool fullRow) const
4541 { return m_main_win->GetNextVisible(item, fullRow); }
4542
4543 wxTreeItemId wxTreeListCtrl::GetPrevVisible(const wxTreeItemId& item, bool fullRow) const
4544 { return m_main_win->GetPrevVisible(item, fullRow); }
4545
4546 wxTreeItemId wxTreeListCtrl::AddRoot (const wxString& text, int image,
4547                                       int selectedImage, wxTreeItemData* data)
4548 { return m_main_win->AddRoot (text, image, selectedImage, data); }
4549
4550 wxTreeItemId wxTreeListCtrl::PrependItem(const wxTreeItemId& parent,
4551                                          const wxString& text, int image,
4552                                          int selectedImage,
4553                                          wxTreeItemData* data)
4554 { return m_main_win->PrependItem(parent, text, image, selectedImage, data); }
4555
4556 wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
4557                                         const wxTreeItemId& previous,
4558                                         const wxString& text, int image,
4559                                         int selectedImage,
4560                                         wxTreeItemData* data)
4561 {
4562     return m_main_win->InsertItem(parent, previous, text, image,
4563                                   selectedImage, data);
4564 }
4565
4566 wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
4567                                         size_t index,
4568                                         const wxString& text, int image,
4569                                         int selectedImage,
4570                                         wxTreeItemData* data)
4571 {
4572     return m_main_win->InsertItem(parent, index, text, image,
4573                                   selectedImage, data);
4574 }
4575
4576 wxTreeItemId wxTreeListCtrl::AppendItem(const wxTreeItemId& parent,
4577                                         const wxString& text, int image,
4578                                         int selectedImage,
4579                                         wxTreeItemData* data)
4580 { return m_main_win->AppendItem(parent, text, image, selectedImage, data); }
4581
4582 void wxTreeListCtrl::Delete(const wxTreeItemId& item)
4583 { m_main_win->Delete(item); }
4584
4585 void wxTreeListCtrl::DeleteChildren(const wxTreeItemId& item)
4586 { m_main_win->DeleteChildren(item); }
4587
4588 void wxTreeListCtrl::DeleteRoot()
4589 { m_main_win->DeleteRoot(); }
4590
4591 void wxTreeListCtrl::Expand(const wxTreeItemId& item)
4592 { m_main_win->Expand(item); }
4593
4594 void wxTreeListCtrl::ExpandAll(const wxTreeItemId& item)
4595 { m_main_win->ExpandAll(item); }
4596
4597 void wxTreeListCtrl::Collapse(const wxTreeItemId& item)
4598 { m_main_win->Collapse(item); }
4599
4600 void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId& item)
4601 { m_main_win->CollapseAndReset(item); }
4602
4603 void wxTreeListCtrl::Toggle(const wxTreeItemId& item)
4604 { m_main_win->Toggle(item); }
4605
4606 //void wxTreeListCtrl::Unselect()
4607 //{ m_main_win->Unselect(); }
4608
4609 // LG 19/09/08 : Added 
4610 //void wxTreeListCtrl::Unselect(wxTreeItemId& item)
4611 //{ m_main_win->Unselect((wxTreeListItem*)item.m_pItem); }
4612
4613 void wxTreeListCtrl::UnselectAll()
4614 { m_main_win->UnselectAll(); }
4615
4616 void wxTreeListCtrl::SelectItem(const wxTreeItemId& item, const wxTreeItemId& last,
4617                                 bool unselect_others)
4618 { m_main_win->SelectItem (item, last, unselect_others); }
4619
4620 void wxTreeListCtrl::SelectAll()
4621 { m_main_win->SelectAll(); }
4622
4623 void wxTreeListCtrl::EnsureVisible(const wxTreeItemId& item)
4624 { m_main_win->EnsureVisible(item); }
4625
4626 void wxTreeListCtrl::ScrollTo(const wxTreeItemId& item)
4627 { m_main_win->ScrollTo(item); }
4628
4629 wxTreeItemId wxTreeListCtrl::HitTest(const wxPoint& pos, int& flags, int& column)
4630 {
4631     wxPoint p = m_main_win->ScreenToClient (ClientToScreen (pos));
4632     return m_main_win->HitTest (p, flags, column);
4633 }
4634
4635 bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId& item, wxRect& rect,
4636                                      bool textOnly) const
4637 { return m_main_win->GetBoundingRect(item, rect, textOnly); }
4638
4639 void wxTreeListCtrl::EditLabel (const wxTreeItemId& item, int column)
4640 { m_main_win->EditLabel (item, column); }
4641
4642 int wxTreeListCtrl::OnCompareItems(const wxTreeItemId& item1,
4643                                    const wxTreeItemId& item2)
4644 {
4645     // do the comparison here, and not delegate to m_main_win, in order
4646     // to let the user override it
4647     //return m_main_win->OnCompareItems(item1, item2);
4648     return wxStrcmp(GetItemText(item1), GetItemText(item2));
4649 }
4650
4651 void wxTreeListCtrl::SortChildren(const wxTreeItemId& item)
4652 { m_main_win->SortChildren(item); }
4653
4654 wxTreeItemId wxTreeListCtrl::FindItem (const wxTreeItemId& item, const wxString& str, int mode)
4655 { return m_main_win->FindItem (item, str, mode); }
4656
4657 void wxTreeListCtrl::SetDragItem (const wxTreeItemId& item)
4658 { m_main_win->SetDragItem (item); }
4659
4660 bool wxTreeListCtrl::SetBackgroundColour(const wxColour& colour)
4661 {
4662     if (!m_main_win) return false;
4663     return m_main_win->SetBackgroundColour(colour);
4664 }
4665
4666 bool wxTreeListCtrl::SetForegroundColour(const wxColour& colour)
4667 {
4668     if (!m_main_win) return false;
4669     return m_main_win->SetForegroundColour(colour);
4670 }
4671
4672 int wxTreeListCtrl::GetColumnCount() const
4673 { return m_main_win->GetColumnCount(); }
4674
4675 void wxTreeListCtrl::SetColumnWidth(int column, int width)
4676 {
4677     m_header_win->SetColumnWidth (column, width);
4678     m_header_win->Refresh();
4679 }
4680
4681 int wxTreeListCtrl::GetColumnWidth(int column) const
4682 { return m_header_win->GetColumnWidth(column); }
4683
4684 void wxTreeListCtrl::SetMainColumn(int column)
4685 { m_main_win->SetMainColumn(column); }
4686
4687 int wxTreeListCtrl::GetMainColumn() const
4688 { return m_main_win->GetMainColumn(); }
4689
4690 void wxTreeListCtrl::SetColumnText(int column, const wxString& text)
4691 {
4692     m_header_win->SetColumnText (column, text);
4693     m_header_win->Refresh();
4694 }
4695
4696 wxString wxTreeListCtrl::GetColumnText(int column) const
4697 { return m_header_win->GetColumnText(column); }
4698
4699 void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo& colInfo)
4700 {
4701     m_header_win->AddColumn (colInfo);
4702     DoHeaderLayout();
4703 }
4704
4705 void wxTreeListCtrl::InsertColumn(int before, const wxTreeListColumnInfo& colInfo)
4706 {
4707     m_header_win->InsertColumn (before, colInfo);
4708     m_header_win->Refresh();
4709 }
4710
4711 void wxTreeListCtrl::RemoveColumn(int column)
4712 {
4713     m_header_win->RemoveColumn (column);
4714     m_header_win->Refresh();
4715 }
4716
4717 void wxTreeListCtrl::SetColumn(int column, const wxTreeListColumnInfo& colInfo)
4718 {
4719     m_header_win->SetColumn (column, colInfo);
4720     m_header_win->Refresh();
4721 }
4722
4723 const wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(int column) const
4724 { return m_header_win->GetColumn(column); }
4725
4726 wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(int column)
4727 { return m_header_win->GetColumn(column); }
4728
4729 void wxTreeListCtrl::SetColumnImage(int column, int image)
4730 {
4731     m_header_win->SetColumn (column, GetColumn(column).SetImage(image));
4732     m_header_win->Refresh();
4733 }
4734
4735 int wxTreeListCtrl::GetColumnImage(int column) const
4736 {
4737     return m_header_win->GetColumn(column).GetImage();
4738 }
4739
4740 void wxTreeListCtrl::SetColumnEditable(int column, bool shown)
4741 {
4742     m_header_win->SetColumn (column, GetColumn(column).SetEditable(shown));
4743 }
4744
4745 void wxTreeListCtrl::SetColumnShown(int column, bool shown)
4746 {
4747     wxASSERT_MSG (column != GetMainColumn(), _T("The main column may not be hidden") );
4748     m_header_win->SetColumn (column, GetColumn(column).SetShown(GetMainColumn()==column? true: shown));
4749     m_header_win->Refresh();
4750 }
4751
4752 bool wxTreeListCtrl::IsColumnEditable(int column) const
4753 {
4754     return m_header_win->GetColumn(column).IsEditable();
4755 }
4756
4757 bool wxTreeListCtrl::IsColumnShown(int column) const
4758 {
4759     return m_header_win->GetColumn(column).IsShown();
4760 }
4761
4762 void wxTreeListCtrl::SetColumnAlignment (int column, int flag)
4763 {
4764     m_header_win->SetColumn(column, GetColumn(column).SetAlignment(flag));
4765     m_header_win->Refresh();
4766 }
4767
4768 int wxTreeListCtrl::GetColumnAlignment(int column) const
4769 {
4770     return m_header_win->GetColumn(column).GetAlignment();
4771 }
4772
4773 void wxTreeListCtrl::Refresh(bool erase, const wxRect* rect)
4774 {
4775     m_main_win->Refresh (erase, rect);
4776     m_header_win->Refresh (erase, rect);
4777 }
4778
4779 void wxTreeListCtrl::SetFocus()
4780 { m_main_win->SetFocus(); }
4781
4782 wxSize wxTreeListCtrl::DoGetBestSize() const
4783 {
4784     // something is better than nothing...
4785     return wxSize (200,200); // but it should be specified values! FIXME
4786 }
4787
4788 wxString wxTreeListCtrl::OnGetItemText( wxTreeItemData* WXUNUSED(item), long WXUNUSED(column)) const
4789 {
4790     return wxEmptyString;
4791 }