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