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