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