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