NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
treelistctrl.cpp
Go to the documentation of this file.
1
2// 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 3043 2012-07-31 19:28:14Z 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#if wxCHECK_VERSION(2, 7, 0)
44#include <wx/renderer.h>
45#endif
46#include <wx/apptrait.h>
47#include <wx/dcbuffer.h>
48#include <wx/tooltip.h>
49#include <wx/hashmap.h>
50#include <wx/dynarray.h>
51#include <wx/arrimpl.cpp>
52
53#ifdef __WXMAC__
54#include "wx/mac/private.h"
55#endif
56
57#include "treelistctrl.h"
58
59#include <wx/log.h> // only required for debugging purpose
60#include <wx/msgdlg.h> // only required for debugging purpose
61
62
63#if wxCHECK_VERSION(2,9,0)
64namespace wxcode
65{
66#endif
67
68// ---------------------------------------------------------------------------
69// array types
70// ---------------------------------------------------------------------------
71
72 class wxTreeListItem;
74
75#if !wxCHECK_VERSION(2, 5, 0)
76 WX_DEFINE_ARRAY(wxTreeListItem*, wxArrayTreeListItems);
77#else
78 WX_DEFINE_ARRAY_PTR(wxTreeListItem*, wxArrayTreeListItems);
79#endif
80
81 WX_DECLARE_OBJARRAY(wxTreeListColumnInfo, wxArrayTreeListColumnInfo);
82 WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo);
83
84
85 WX_DECLARE_HASH_MAP( int, wxTreeListItemCellAttr*, wxIntegerHash, wxIntegerEqual, wxTreeListItemCellAttrHash );
86
87// --------------------------------------------------------------------------
88// constants
89// --------------------------------------------------------------------------
90
91 static const int NO_IMAGE = -1;
92
93 static const int LINEHEIGHT = 10;
94 static const int LINEATROOT = 5;
95 static const int MARGIN = 2;
96 static const int MININDENT = 16;
97 static const int BTNWIDTH = 9;
98 static const int BTNHEIGHT = 9;
99 static const int EXTRA_WIDTH = 4;
100 static const int EXTRA_HEIGHT = 4;
101 static const int HEADER_OFFSET_X = 0; // changed from 1 to 0 on 2009.03.10 for Windows (other OS untested)
102 static const int HEADER_OFFSET_Y = 1;
103
104 static const int DRAG_TIMER_TICKS = 250; // minimum drag wait time in ms
105 static const int FIND_TIMER_TICKS = 500; // minimum find wait time in ms
106 static const int RENAME_TIMER_TICKS = 250; // minimum rename wait time in ms
107
108 const wxChar* wxTreeListCtrlNameStr = _T("treelistctrl");
109
111
112
113// ---------------------------------------------------------------------------
114// private classes
115// ---------------------------------------------------------------------------
116
117 class wxTreeListHeaderWindow : public wxWindow
118 {
119 protected:
121 const wxCursor* m_currentCursor;
122 const wxCursor* m_resizeCursor;
124
125 // column being resized
127
128 // divider line position in logical (unscrolled) coords
130
131 // minimal position beyond which the divider line can't be dragged in
132 // logical coords
134
135 wxArrayTreeListColumnInfo m_columns;
136
137 // total width of the columns
139
140#if wxCHECK_VERSION_FULL(2, 7, 0, 1)
141 // which col header is currently highlighted with mouse-over
142 int m_hotTrackCol;
143 int XToCol(int x);
144 void RefreshColLabel(int col);
145#endif
146
147 public:
149
150 wxTreeListHeaderWindow( wxWindow* win,
151 wxWindowID id,
153 const wxPoint& pos = wxDefaultPosition,
154 const wxSize& size = wxDefaultSize,
155 long style = 0,
156 const wxString& name = _T("wxtreelistctrlcolumntitles") );
157
158 virtual ~wxTreeListHeaderWindow();
159
160 void DoDrawRect( wxDC* dc, int x, int y, int w, int h );
161 void DrawCurrent();
162 void AdjustDC(wxDC& dc);
163
164 void OnPaint( wxPaintEvent& event );
165 void OnEraseBackground(wxEraseEvent& WXUNUSED(event)) { ;; } // reduce flicker
166 void OnMouse( wxMouseEvent& event );
167 void OnSetFocus( wxFocusEvent& event );
168
169 // total width of all columns
170 int GetWidth() const
171 {
172 return m_total_col_width;
173 }
174
175 // column manipulation
176 int GetColumnCount() const
177 {
178 return (int)m_columns.GetCount();
179 }
180
181 void AddColumn (const wxTreeListColumnInfo& colInfo);
182
183 void InsertColumn (int before, const wxTreeListColumnInfo& colInfo);
184
185 void RemoveColumn (int column);
186
187 // column information manipulation
188 const wxTreeListColumnInfo& GetColumn (int column) const
189 {
190 wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
191 wxInvalidTreeListColumnInfo, _T("Invalid column"));
192 return m_columns[column];
193 }
195 {
196 wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
197 wxInvalidTreeListColumnInfo, _T("Invalid column"));
198 return m_columns[column];
199 }
200 void SetColumn (int column, const wxTreeListColumnInfo& info);
201
202 wxString GetColumnText (int column) const
203 {
204 wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
205 wxEmptyString, _T("Invalid column"));
206 return m_columns[column].GetText();
207 }
208 void SetColumnText (int column, const wxString& text)
209 {
210 wxCHECK_RET ((column >= 0) && (column < GetColumnCount()),
211 _T("Invalid column"));
212 m_columns[column].SetText (text);
213 }
214
215 int GetColumnAlignment (int column) const
216 {
217 wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
218 wxALIGN_LEFT, _T("Invalid column"));
219 return m_columns[column].GetAlignment();
220 }
221 void SetColumnAlignment (int column, int flag)
222 {
223 wxCHECK_RET ((column >= 0) && (column < GetColumnCount()),
224 _T("Invalid column"));
225 m_columns[column].SetAlignment (flag);
226 }
227
228 int GetColumnWidth (int column) const
229 {
230 wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
231 -1, _T("Invalid column"));
232 return m_columns[column].GetWidth();
233 }
234 void SetColumnWidth (int column, int width);
235
236 bool IsColumnEditable (int column) const
237 {
238 wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
239 false, _T("Invalid column"));
240 return m_columns[column].IsEditable();
241 }
242
243 bool IsColumnShown (int column) const
244 {
245 wxCHECK_MSG ((column >= 0) && (column < GetColumnCount()),
246 true, _T("Invalid column"));
247 return m_columns[column].IsShown();
248 }
249
250 // needs refresh
252
253 private:
254 // common part of all ctors
255 void Init();
256
257 void SendListEvent(wxEventType type, wxPoint pos);
258
259 DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow)
260 DECLARE_EVENT_TABLE()
261 };
262
263
264//-----------------------------------------------------------------------------
265
266 class wxEditTextCtrl;
267
268
269// this is the "true" control
270 class wxTreeListMainWindow: public wxScrolledWindow
271 {
272 friend class wxTreeListItem;
274 friend class wxEditTextCtrl;
275
276 public:
277 // creation
278 // --------
280 {
281 Init();
282 }
283
284 wxTreeListMainWindow (wxTreeListCtrl* parent, wxWindowID id = -1,
285 const wxPoint& pos = wxDefaultPosition,
286 const wxSize& size = wxDefaultSize,
287 long style = wxTR_DEFAULT_STYLE,
288 const wxValidator& validator = wxDefaultValidator,
289 const wxString& name = _T("wxtreelistmainwindow"))
290 {
291 Init();
292 Create (parent, id, pos, size, style, validator, name);
293 }
294
295 virtual ~wxTreeListMainWindow();
296
297 bool Create(wxTreeListCtrl* parent, wxWindowID id = -1,
298 const wxPoint& pos = wxDefaultPosition,
299 const wxSize& size = wxDefaultSize,
300 long style = wxTR_DEFAULT_STYLE,
301 const wxValidator& validator = wxDefaultValidator,
302 const wxString& name = _T("wxtreelistctrl"));
303
304 // accessors
305 // ---------
306
307 // return true if this is a virtual list control
308 bool IsVirtual() const
309 {
310 return HasFlag(wxTR_VIRTUAL);
311 }
312
313 // get the total number of items in the control
314 size_t GetCount() const;
315
316 // indent is the number of pixels the children are indented relative to
317 // the parents position. SetIndent() also redraws the control
318 // immediately.
319 unsigned int GetIndent() const
320 {
321 return m_indent;
322 }
323 void SetIndent(unsigned int indent);
324
325 // see wxTreeListCtrl for the meaning
326 unsigned int GetLineSpacing() const
327 {
328 return m_linespacing;
329 }
330 void SetLineSpacing(unsigned int spacing);
331
332 // image list: these functions allow to associate an image list with
333 // the control and retrieve it. Note that when assigned with
334 // SetImageList, the control does _not_ delete
335 // the associated image list when it's deleted in order to allow image
336 // lists to be shared between different controls. If you use
337 // AssignImageList, the control _does_ delete the image list.
338
339 // The normal image list is for the icons which correspond to the
340 // normal tree item state (whether it is selected or not).
341 // Additionally, the application might choose to show a state icon
342 // which corresponds to an app-defined item state (for example,
343 // checked/unchecked) which are taken from the state image list.
344 wxImageList* GetImageList() const
345 {
346 return m_imageListNormal;
347 }
348 wxImageList* GetStateImageList() const
349 {
350 return m_imageListState;
351 }
352 wxImageList* GetButtonsImageList() const
353 {
354 return m_imageListButtons;
355 }
356
357 void SetImageList(wxImageList* imageList);
358 void SetStateImageList(wxImageList* imageList);
359 void SetButtonsImageList(wxImageList* imageList);
360 void AssignImageList(wxImageList* imageList);
361 void AssignStateImageList(wxImageList* imageList);
362 void AssignButtonsImageList(wxImageList* imageList);
363
364 void SetToolTip(const wxString& tip);
365 void SetToolTip(wxToolTip* tip);
366 void SetItemToolTip(const wxTreeItemId& item, const wxString& tip);
367
368 // Functions to work with tree ctrl items.
369
370
371
372 // accessors (most props have a default at row/item level *and* a default at cell level)
373 // ---------
374
375 wxString GetItemText (const wxTreeItemId& item, int column) const;
376 wxString GetItemText (wxTreeItemData* item, int column) const;
377
378 // ItemImage is special: main col has multiple images
379 int GetItemImage (const wxTreeItemId& item, wxTreeItemIcon which = wxTreeItemIcon_Normal) const
380 {
381 return GetItemImage (item, GetMainColumn(), which);
382 }
383 int GetItemImage (const wxTreeItemId& item, int column, wxTreeItemIcon which = wxTreeItemIcon_Normal) const;
384
385 // ItemData is special, there is a separate default at row/item level
386 wxTreeItemData* GetItemData(const wxTreeItemId& item) const;
387 wxTreeItemData* GetItemData(const wxTreeItemId& item, int column) const;
388
389 bool GetItemBold(const wxTreeItemId& item) const;
390 bool GetItemBold(const wxTreeItemId& item, int column) const;
391
392 wxColour GetItemTextColour(const wxTreeItemId& item) const;
393 wxColour GetItemTextColour(const wxTreeItemId& item, int column) const;
394
395 wxColour GetItemBackgroundColour(const wxTreeItemId& item) const;
396 wxColour GetItemBackgroundColour(const wxTreeItemId& item, int column) const;
397
398 wxFont GetItemFont(const wxTreeItemId& item) const;
399 wxFont GetItemFont(const wxTreeItemId& item, int column) const;
400
401
402
403 // modifiers (most properties have a default at row/item level *and* a default at cell level)
404 // ---------
405
406 // force appearance of [+] button near the item. This is useful to
407 // allow the user to expand the items which don't have any children now
408 // - but instead add them only when needed, thus minimizing memory
409 // usage and loading time.
410 void SetItemHasChildren(const wxTreeItemId& item, bool has = true);
411
412 // set item's label
413 void SetItemText (const wxTreeItemId& item, int column, const wxString& text);
414
415 // get one of the images associated with the item (normal by default)
416 void SetItemImage (const wxTreeItemId& item, int image, wxTreeItemIcon which = wxTreeItemIcon_Normal)
417 {
418 SetItemImage (item, GetMainColumn(), image, which);
419 }
420 void SetItemImage (const wxTreeItemId& item, int column, int image, wxTreeItemIcon which = wxTreeItemIcon_Normal);
421
422 // associate some data with the item
423 void SetItemData(const wxTreeItemId& item, wxTreeItemData* data);
424 void SetItemData(const wxTreeItemId& item, int column, wxTreeItemData* data);
425
426 // the item will be shown in bold
427 void SetItemBold(const wxTreeItemId& item, bool bold = true);
428 void SetItemBold(const wxTreeItemId& item, int column, bool bold = true);
429
430 // set the item's text colour
431 void SetItemTextColour(const wxTreeItemId& item, const wxColour& colour);
432 void SetItemTextColour(const wxTreeItemId& item, int column, const wxColour& colour);
433
434 // set the item's background colour
435 void SetItemBackgroundColour(const wxTreeItemId& item, const wxColour& colour);
436 void SetItemBackgroundColour(const wxTreeItemId& item, int column, const wxColour& colour);
437
438 // set the item's font (should be of the same height for all items)
439 void SetItemFont(const wxTreeItemId& item, const wxFont& font);
440 void SetItemFont(const wxTreeItemId& item, int column, const wxFont& font);
441
442
443
444 // item status inquiries
445 // ---------------------
446
447 // is the item visible (it might be outside the view or not expanded)?
448 bool IsVisible(const wxTreeItemId& item, bool fullRow, bool within = true) const;
449 // does the item has any children?
450 bool HasChildren(const wxTreeItemId& item) const;
451 // is the item expanded (only makes sense if HasChildren())?
452 bool IsExpanded(const wxTreeItemId& item) const;
453 // is this item currently selected (the same as has focus)?
454 bool IsSelected(const wxTreeItemId& item) const;
455 // is item text in bold font?
456 bool IsBold(const wxTreeItemId& item) const;
457 bool IsBold(const wxTreeItemId& item, int column) const;
458
459
460
461 // set the window font
462 virtual bool SetFont( const wxFont& font );
463
464 // set the styles. No need to specify a GetWindowStyle here since
465 // the base wxWindow member function will do it for us
466 void SetWindowStyle(const long styles);
467
468 // number of children
469 // ------------------
470
471 // if 'recursively' is false, only immediate children count, otherwise
472 // the returned number is the number of all items in this branch
473 size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = true);
474
475 // navigation
476 // ----------
477
478 // wxTreeItemId.IsOk() will return false if there is no such item
479
480 // get the root tree item
481 wxTreeItemId GetRootItem() const
482 {
483 return m_rootItem; // implict cast from wxTreeListItem *
484 }
485
486 // get the item currently selected, only if a single item is selected
487 wxTreeItemId GetSelection() const
488 {
489 return m_selectItem;
490 }
491
492 // get all the items currently selected, return count of items
493 size_t GetSelections(wxArrayTreeItemIds&) const;
494
495 // get the parent of this item (may return NULL if root)
496 wxTreeItemId GetItemParent(const wxTreeItemId& item) const;
497
498 // for this enumeration function you must pass in a "cookie" parameter
499 // which is opaque for the application but is necessary for the library
500 // to make these functions reentrant (i.e. allow more than one
501 // enumeration on one and the same object simultaneously). Of course,
502 // the "cookie" passed to GetFirstChild() and GetNextChild() should be
503 // the same!
504
505 // get child of this item
506#if !wxCHECK_VERSION(2, 5, 0)
507 wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const;
508 wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const;
509 wxTreeItemId GetPrevChild(const wxTreeItemId& item, long& cookie) const;
510 wxTreeItemId GetLastChild(const wxTreeItemId& item, long& cookie) const;
511#else
512 wxTreeItemId GetFirstChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
513 wxTreeItemId GetNextChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
514 wxTreeItemId GetPrevChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
515 wxTreeItemId GetLastChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const;
516#endif
517
518 // get sibling of this item
519 wxTreeItemId GetNextSibling(const wxTreeItemId& item) const;
520 wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const;
521
522 // get item in the full tree (currently only for internal use)
523 wxTreeItemId GetNext(const wxTreeItemId& item, bool fulltree = true) const;
524 wxTreeItemId GetPrev(const wxTreeItemId& item, bool fulltree = true) const;
525
526 // get expanded item, see IsExpanded()
527 wxTreeItemId GetFirstExpandedItem() const;
528 wxTreeItemId GetNextExpanded(const wxTreeItemId& item) const;
529 wxTreeItemId GetPrevExpanded(const wxTreeItemId& item) const;
530
531 // get visible item, see IsVisible()
532 wxTreeItemId GetFirstVisible( bool fullRow, bool within) const;
533 wxTreeItemId GetNextVisible (const wxTreeItemId& item, bool fullRow, bool within) const;
534 wxTreeItemId GetPrevVisible (const wxTreeItemId& item, bool fullRow, bool within) const;
535 wxTreeItemId GetLastVisible ( bool fullRow, bool within) const;
536
537 // operations
538 // ----------
539
540 // add the root node to the tree
541 wxTreeItemId AddRoot (const wxString& text,
542 int image = -1, int selectedImage = -1,
543 wxTreeItemData* data = NULL);
544
545 // insert a new item in as the first child of the parent
546 wxTreeItemId PrependItem(const wxTreeItemId& parent,
547 const wxString& text,
548 int image = -1, int selectedImage = -1,
549 wxTreeItemData* data = NULL);
550
551 // insert a new item after a given one
552 wxTreeItemId InsertItem(const wxTreeItemId& parent,
553 const wxTreeItemId& idPrevious,
554 const wxString& text,
555 int image = -1, int selectedImage = -1,
556 wxTreeItemData* data = NULL);
557
558 // insert a new item before the one with the given index
559 wxTreeItemId InsertItem(const wxTreeItemId& parent,
560 size_t index,
561 const wxString& text,
562 int image = -1, int selectedImage = -1,
563 wxTreeItemData* data = NULL);
564
565 // insert a new item in as the last child of the parent
566 wxTreeItemId AppendItem(const wxTreeItemId& parent,
567 const wxString& text,
568 int image = -1, int selectedImage = -1,
569 wxTreeItemData* data = NULL);
570
571 // delete this item and associated data if any
572 void Delete(const wxTreeItemId& item);
573 // delete all children (but don't delete the item itself)
574 // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
575 void DeleteChildren(const wxTreeItemId& item);
576 // delete the root and all its children from the tree
577 // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events
578 void DeleteRoot();
579
580 void SetItemParent(const wxTreeItemId& parent, const wxTreeItemId& item);
581
582 // expand this item
583 void Expand(const wxTreeItemId& item);
584 // expand this item and all subitems recursively
585 void ExpandAll(const wxTreeItemId& item);
586 // collapse the item without removing its children
587 void Collapse(const wxTreeItemId& item);
588 // collapse the item and remove all children
589 void CollapseAndReset(const wxTreeItemId& item);
590 // toggles the current state
591 void Toggle(const wxTreeItemId& item);
592
593 // set cursor item (indicated by black rectangle)
594 void SetCurrentItem(const wxTreeItemId& item);
595
596 // remove the selection from currently selected item (if any)
597 void Unselect();
598 void UnselectAll();
599 // select this item
600 bool SelectItem(const wxTreeItemId& item, const wxTreeItemId& prev = (wxTreeItemId*)NULL,
601 bool unselect_others = true);
602 void SelectAll();
603 // make sure this item is visible (expanding the parent item and/or
604 // scrolling to this item if necessary)
605 void EnsureVisible(const wxTreeItemId& item);
606 // scroll to this item (but don't expand its parent)
607 void ScrollTo(const wxTreeItemId& item);
608 void AdjustMyScrollbars();
609
610 // The first function is more portable (because easier to implement
611 // on other platforms), but the second one returns some extra info.
612 wxTreeItemId HitTest (const wxPoint& point)
613 {
614 int flags;
615 int column;
616 return HitTest (point, flags, column);
617 }
618 wxTreeItemId HitTest (const wxPoint& point, int& flags)
619 {
620 int column;
621 return HitTest (point, flags, column);
622 }
623 wxTreeItemId HitTest (const wxPoint& point, int& flags, int& column);
624
625
626 // get the bounding rectangle of the item (or of its label only)
627 bool GetBoundingRect(const wxTreeItemId& item,
628 wxRect& rect,
629 bool textOnly = false) const;
630
631 // Start editing the item label: this (temporarily) replaces the item
632 // with a one line edit control. The item will be selected if it hadn't
633 // been before.
634 void EditLabel (const wxTreeItemId& item, int column);
635 void EndEdit(bool isCancelled);
636
637 // sorting
638 // this function is called to compare 2 items and should return -1, 0
639 // or +1 if the first item is less than, equal to or greater than the
640 // second one. The base class version performs alphabetic comparaison
641 // of item labels (GetText)
642 virtual int OnCompareItems(const wxTreeItemId& item1,
643 const wxTreeItemId& item2);
644 // sort the children of this item using OnCompareItems
645 //
646 // NB: this function is not reentrant and not MT-safe (TODO)!
647 void SortChildren(const wxTreeItemId& item, int column, bool reverseOrder);
648
649 // searching
650 wxTreeItemId FindItem (const wxTreeItemId& item, int column, const wxString& str, int mode = 0);
651
652 // implementation only from now on
653
654 // overridden base class virtuals
655 virtual bool SetBackgroundColour(const wxColour& colour);
656 virtual bool SetForegroundColour(const wxColour& colour);
657
658 // drop over item
659 void SetDragItem (const wxTreeItemId& item = (wxTreeItemId*)NULL);
660
661 // callbacks
662 void OnPaint( wxPaintEvent& event );
663 void OnEraseBackground(wxEraseEvent& WXUNUSED(event)) { ;; } // to reduce flicker
664 void OnSetFocus( wxFocusEvent& event );
665 void OnKillFocus( wxFocusEvent& event );
666 void OnChar( wxKeyEvent& event );
667 void OnMouse( wxMouseEvent& event );
668 void OnIdle( wxIdleEvent& event );
669 void OnScroll(wxScrollWinEvent& event);
670 void OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) { ;; }
671
672 // implementation helpers
673 int GetColumnCount() const
674 {
675 return m_owner->GetHeaderWindow()->GetColumnCount();
676 }
677
678 void SetMainColumn (int column)
679 {
680 if ((column >= 0) && (column < GetColumnCount())) m_main_column = column;
681 }
682
683 int GetMainColumn() const
684 {
685 return m_main_column;
686 }
688 {
689 return m_curColumn >= 0 ? m_curColumn : m_main_column;
690 }
691
692 int GetBestColumnWidth (int column, wxTreeItemId parent = wxTreeItemId());
693 int GetItemWidth (int column, wxTreeListItem* item);
694
695 void SetFocus();
696
697 protected:
699
702
704 wxTreeListItem* m_curItem; // current item, either selected or marked
705 wxTreeListItem* m_shiftItem; // item, where the shift key was pressed
706 wxTreeListItem* m_selectItem; // current selected item, not with wxTR_MULTIPLE
707
712
713 int m_btnWidth, m_btnWidth2;
714 int m_btnHeight, m_btnHeight2;
715 int m_imgWidth, m_imgWidth2;
716 int m_imgHeight, m_imgHeight2;
717 unsigned short m_indent;
719 unsigned short m_linespacing;
724 public:
726 protected:
730 bool m_lastOnSame; // last click on the same item as prev
732
733 wxImageList* m_imageListNormal,
736
737 bool m_isDragStarted; // set at the very beginning of dragging
738 bool m_isDragging; // set once a drag begin event was fired
739 wxPoint m_dragStartPos; // set whenever m_isDragStarted is set to true
742
743 wxTreeListItem* m_editItem; // item, which is currently edited
744 wxTimer* m_editTimer;
745 bool m_editAccept; // currently unused, OnRenameAccept() argument makes it redundant
746 wxString m_editRes;
749
750 // char navigation
751 wxTimer* m_findTimer;
752 wxString m_findStr;
753
754 bool m_isItemToolTip; // true if individual item tooltips were set (disable global tooltip)
755 wxString m_toolTip; // global tooltip
756 wxTreeListItem* m_toolTipItem; // item whose tip is currently shown (NULL==global, -1==not displayed)
757
758 // the common part of all ctors
759 void Init();
760
761 // misc helpers
762 wxTreeItemId DoInsertItem(const wxTreeItemId& parent,
763 size_t previous,
764 const wxString& text,
765 int image, int selectedImage,
766 wxTreeItemData* data);
767 void DoDeleteItem (wxTreeListItem* item);
768 void SetCurrentItem(wxTreeListItem* item);
769 bool HasButtons(void) const
770 {
771 return (m_imageListButtons) || HasFlag (wxTR_TWIST_BUTTONS | wxTR_HAS_BUTTONS);
772 }
773
774 void CalculateLineHeight();
775 int GetLineHeight(wxTreeListItem* item) const;
776 void PaintLevel( wxTreeListItem* item, wxDC& dc, int level, int& y,
777 int x_maincol);
778 void PaintItem( wxTreeListItem* item, wxDC& dc);
779
780 void CalculateLevel( wxTreeListItem* item, wxDC& dc, int level, int& y,
781 int x_maincol);
782 void CalculatePositions();
783 void CalculateSize( wxTreeListItem* item, wxDC& dc );
784
785 void RefreshSubtree (wxTreeListItem* item);
786 void RefreshLine (wxTreeListItem* item);
787 // redraw all selected items
788 void RefreshSelected();
789 // RefreshSelected() recursive helper
790 void RefreshSelectedUnder (wxTreeListItem* item);
791
792 void OnRenameTimer();
793 void OnRenameAccept(bool isCancelled);
794
795 void FillArray(wxTreeListItem*, wxArrayTreeItemIds&) const;
796 bool TagAllChildrenUntilLast (wxTreeListItem* crt_item, wxTreeListItem* last_item);
797 bool TagNextChildren (wxTreeListItem* crt_item, wxTreeListItem* last_item);
798 void UnselectAllChildren (wxTreeListItem* item );
799 bool SendEvent(wxEventType event_type, wxTreeListItem* item = NULL, wxTreeEvent* event = NULL); // returns true if processed
800
801 private:
802 DECLARE_EVENT_TABLE()
803 DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow)
804 };
805
806
807//-----------------------------------------------------------------------------
808
809// timer used for enabling in-place edit
810 class wxTreeListRenameTimer: public wxTimer
811 {
812 public:
814
815 void Notify();
816
817 private:
819 };
820
821
822//-----------------------------------------------------------------------------
823
824// control used for in-place edit
825 class wxEditTextCtrl: public wxTextCtrl
826 {
827 public:
828 wxEditTextCtrl (wxWindow* parent,
829 const wxWindowID id,
830 bool* accept,
831 wxString* res,
833 const wxString& value = wxEmptyString,
834 const wxPoint& pos = wxDefaultPosition,
835 const wxSize& size = wxDefaultSize,
836 int style = 0,
837 const wxValidator& validator = wxDefaultValidator,
838 const wxString& name = wxTextCtrlNameStr );
840
841 virtual bool Destroy(); // wxWindow override
842 void EndEdit(bool isCancelled);
844 {
845 m_owner = owner;
846 }
847
848 void OnChar( wxKeyEvent& event );
849 void OnKeyUp( wxKeyEvent& event );
850 void OnKillFocus( wxFocusEvent& event );
851
852
853 private:
855 bool* m_accept;
856 wxString* m_res;
857 wxString m_startValue;
858 bool m_finished; // true==deleting, don't process events anymore
859
860 DECLARE_EVENT_TABLE()
861 };
862
863
864//-----------------------------------------------------------------------------
865
866// list of per-column attributes for an item (wxTreeListItem)
867// since there can be very many of these, we save size by chosing
868// the smallest representation for the elements and by ordering
869// the members to avoid padding.
871 {
872 public:
874 {
875 m_attr = NULL;
876 m_data = NULL;
877 m_isBold = 0;
878 m_isBoldSet = 0;
879 m_ownsAttr = 0;
880 m_image = NO_IMAGE;
881 };
883 {
884 if (m_ownsAttr) delete m_attr;
885 }
886
887 // generic attribute from wxWidgets lib
888 wxTreeItemAttr* m_attr;
889
890 // other attributes
891 wxTreeItemData* m_data; // user-provided data
892 short m_image; // images for the various columns (!= main)
893 int m_isBold : 1; // render the label in bold font
894 int m_isBoldSet : 1; // was 'm_isBold' set ?
895 int m_ownsAttr : 1; // delete attribute when done
896 };
897
898
899//-----------------------------------------------------------------------------
900
901// a tree item (NOTE: this class is storage only, does not generate events)
903 {
904 public:
905 // ctors & dtor
906 // ------------
908 {
909 m_toolTip = NULL;
910 }
912 wxTreeListItem* parent,
913 const wxArrayString& text,
914 int image,
915 int selImage,
916 wxTreeItemData* data );
917
919
920
921 // accessors (most properties have a default at row/item level)
922 // ---------
923 wxArrayTreeListItems& GetChildren()
924 {
925 return m_children;
926 }
927
928// const wxString GetText ( ) const { return GetText(m_owner->GetMainColumn()); }
929 const wxString GetText (int column) const
930 {
931 if ( IsVirtual() ) return m_owner->GetItemText( m_props_row.m_data, column );
932 if (column < (signed)m_text.GetCount()) return m_text[column];
933 return wxEmptyString;
934 };
935
936 int GetImage ( wxTreeItemIcon which = wxTreeItemIcon_Normal) const
937 {
938 return m_images[which];
939 };
940 int GetImage (int column, wxTreeItemIcon which = wxTreeItemIcon_Normal) const
941 {
942 // main column is special, more images available
943 if (column == m_owner->GetMainColumn()) return m_images[which];
944
945 // other columns ignore the 'which' parameter
946 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
947 if (entry == m_props_cell.end()) return NO_IMAGE;
948 return entry->second->m_image;
949 };
950
951 // data is special: it has a default value at row/item level
952 wxTreeItemData* GetData() const
953 {
954 return m_props_row.m_data;
955 };
956 wxTreeItemData* GetData(int column) const
957 {
958 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
959 if (entry == m_props_cell.end()) return NULL;
960 return entry->second->m_data;
961 };
962
963 const wxString* GetToolTip() const
964 {
965 return m_toolTip;
966 };
967
968 // returns the current image for the item (depending on its
969 // selected/expanded/whatever state)
970 int GetCurrentImage() const;
971
972
973 // modifiers (most properties have a default at row/item level)
974 // ---------
975 void SetHasPlus(bool has = true)
976 {
977 m_hasPlus = has;
978 };
979
980 void SetText (int column, const wxString& text)
981 {
982 if (column < (int)m_text.GetCount())
983 {
984 m_text[column] = text;
985 }
986 else if (column < m_owner->GetColumnCount())
987 {
988 int howmany = m_owner->GetColumnCount();
989 for (int i = (int)m_text.GetCount(); i < howmany; ++i) m_text.Add (wxEmptyString);
990 m_text[column] = text;
991 }
992 };
993 void SetImage ( int image, wxTreeItemIcon which)
994 {
995 m_images[which] = image;
996 };
997 void SetImage (int column, int image, wxTreeItemIcon which)
998 {
999 // main column is special, more images available
1000 if (column == m_owner->GetMainColumn()) m_images[which] = image;
1001 // other columns ignore the 'which' parameter
1002 else
1003 {
1004 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
1005 if (entry == m_props_cell.end())
1006 {
1007 m_props_cell[column] = new wxTreeListItemCellAttr();
1008 m_props_cell[column]->m_image = image;
1009 }
1010 else
1011 {
1012 entry->second->m_image = image;
1013 }
1014 }
1015 };
1016
1017 // data is special: it has a default value at row/item level
1018 void SetData( wxTreeItemData* data)
1019 {
1020 m_props_row.m_data = data;
1021 };
1022 void SetData(int column, wxTreeItemData* data)
1023 {
1024 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
1025 if (entry == m_props_cell.end())
1026 {
1027 m_props_cell[column] = new wxTreeListItemCellAttr();
1028 m_props_cell[column]->m_data = data;
1029 }
1030 else
1031 {
1032 entry->second->m_data = data;
1033 }
1034 }
1035
1036 void SetBold( bool bold)
1037 {
1038 m_props_row.m_isBold = bold;
1039 }
1040 void SetBold(int column, bool bold)
1041 {
1042 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
1043 if (entry == m_props_cell.end())
1044 {
1045 m_props_cell[column] = new wxTreeListItemCellAttr();
1046 m_props_cell[column]->m_isBold = bold;
1047 m_props_cell[column]->m_isBoldSet = 1;
1048 }
1049 else
1050 {
1051 entry->second->m_isBold = bold;
1052 entry->second->m_isBoldSet = 1;
1053 }
1054 }
1055
1056
1057 void SetToolTip(const wxString& tip)
1058 {
1059 if (m_toolTip)
1060 {
1061 delete m_toolTip;
1062 m_toolTip = NULL;
1063 }
1064 if (tip.length() > 0)
1065 {
1066 m_toolTip = new wxString(tip);
1067 }
1068 };
1069
1070
1071 // status inquiries
1072 // ----------------
1073 bool HasChildren() const
1074 {
1075 return !m_children.IsEmpty();
1076 }
1077 bool IsSelected() const
1078 {
1079 return m_hasHilight != 0;
1080 }
1081 bool IsExpanded() const
1082 {
1083 return !m_isCollapsed;
1084 }
1085 bool HasPlus() const
1086 {
1087 return m_hasPlus || HasChildren();
1088 }
1089 bool IsBold() const
1090 {
1091 return m_props_row.m_isBold;
1092 }
1093 bool IsBold(int column) const
1094 {
1095 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
1096 if (entry == m_props_cell.end() || ! entry->second->m_isBoldSet) return IsBold();
1097 return (entry->second->m_isBold != 0);
1098 }
1099 bool IsVirtual() const
1100 {
1101 return m_owner->IsVirtual();
1102 }
1103
1104
1105
1106 int GetX() const
1107 {
1108 return m_x;
1109 }
1110 int GetY() const
1111 {
1112 return m_y;
1113 }
1114
1115 void SetX (int x)
1116 {
1117 m_x = x;
1118 }
1119 void SetY (int y)
1120 {
1121 m_y = y;
1122 }
1123
1124 int GetHeight() const
1125 {
1126 return m_height;
1127 }
1128 int GetWidth() const
1129 {
1130 return m_width;
1131 }
1132
1133 void SetHeight (int height)
1134 {
1135 m_height = height;
1136 }
1137 void SetWidth (int width)
1138 {
1139 m_width = width;
1140 }
1141
1142 int GetTextX() const
1143 {
1144 return m_text_x;
1145 }
1146 void SetTextX (int text_x)
1147 {
1148 m_text_x = text_x;
1149 }
1150
1152 {
1153 return m_parent;
1154 }
1156 {
1157 m_parent = parent;
1158 }
1159
1160 // get count of all children (and grand children if 'recursively')
1161 size_t GetChildrenCount(bool recursively = true) const;
1162
1163 void GetSize( int& x, int& y, const wxTreeListMainWindow* );
1164
1165 // return the item at given position (or NULL if no item), onButton is
1166 // true if the point belongs to the item's button, otherwise it lies
1167 // on the button's label
1168 wxTreeListItem* HitTest (const wxPoint& point,
1169 const wxTreeListMainWindow*,
1170 int& flags, int& column, int level);
1171
1172
1173 // operations
1174 // ----------
1175 // deletes all children
1176 void DeleteChildren();
1177
1178 void Insert(wxTreeListItem* child, size_t index)
1179 {
1180 m_children.Insert(child, index);
1181 }
1182
1183 void Expand()
1184 {
1185 m_isCollapsed = false;
1186 }
1188 {
1189 m_isCollapsed = true;
1190 }
1191
1192 void SetHilight( bool set = true )
1193 {
1194 m_hasHilight = set;
1195 }
1196
1197
1198 // attributes
1199 // ----------
1200
1201 // get them - may be NULL (used to read attributes)
1202 // NOTE: fall back on default at row/item level is not defined for cell
1203 wxTreeItemAttr* GetAttributes(int column) const
1204 {
1205 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
1206 if (entry == m_props_cell.end()) return GetAttributes();
1207 return entry->second->m_attr;
1208 }
1209 wxTreeItemAttr* GetAttributes() const
1210 {
1211 return m_props_row.m_attr;
1212 }
1213
1214 // get them ensuring that the pointer is not NULL (used to write attributes)
1215 wxTreeItemAttr& Attr(int column)
1216 {
1217 wxTreeListItemCellAttrHash::const_iterator entry = m_props_cell.find( column );
1218 if (entry == m_props_cell.end())
1219 {
1220 m_props_cell[column] = new wxTreeListItemCellAttr();
1221 m_props_cell[column]->m_attr = new wxTreeItemAttr;
1222 m_props_cell[column]->m_ownsAttr = 1;
1223 return *(m_props_cell[column]->m_attr);
1224 }
1225 else
1226 {
1227 return *(entry->second->m_attr);
1228 }
1229 }
1230 wxTreeItemAttr& Attr()
1231 {
1232 if ( !m_props_row.m_attr )
1233 {
1234 m_props_row.m_attr = new wxTreeItemAttr;
1235 m_props_row.m_ownsAttr = 1;
1236 }
1237 return *m_props_row.m_attr;
1238 }
1239 /* ----- unused -----
1240 // set them
1241 void SetAttributes(wxTreeItemAttr *attr)
1242 {
1243 if ( m_props_row.m_ownsAttr ) delete m_props_row.m_attr;
1244 m_props_row.m_attr = attr;
1245 m_props_row.m_ownsAttr = 0;
1246 }
1247 // set them and delete when done
1248 void AssignAttributes(wxTreeItemAttr *attr)
1249 {
1250 SetAttributes(attr);
1251 m_props_row.m_ownsAttr = 1;
1252 }
1253 */
1254
1255 private:
1256 wxTreeListMainWindow* m_owner; // control the item belongs to
1257
1258 wxArrayTreeListItems m_children; // list of children
1259 wxTreeListItem* m_parent; // parent of this item
1260
1261 // main column item positions
1262 wxCoord m_x; // (virtual) offset from left (vertical line)
1263 wxCoord m_y; // (virtual) offset from top
1264 wxCoord m_text_x; // item offset from left
1265 short m_width; // width of this item
1266 unsigned char m_height; // height of this item
1267
1268 // for the normal, selected, expanded and expanded+selected states
1269 short m_images[wxTreeItemIcon_Max];
1270 // currently there is no tooltip at cell level
1271 wxString* m_toolTip;
1272
1273 // use bitfields to save size
1275 int m_hasHilight : 1; // same as focused
1276 int m_hasPlus : 1; // used for item which doesn't have
1277 // children but has a [+] button
1278
1279 // here are all the properties which can be set per column
1280 wxArrayString m_text; // labels to be rendered for item
1281 wxTreeListItemCellAttr m_props_row; // default at row/item level for: data, attr
1282 wxTreeListItemCellAttrHash m_props_cell;
1283 };
1284
1285
1286// ===========================================================================
1287// implementation
1288// ===========================================================================
1289
1290// ---------------------------------------------------------------------------
1291// wxTreeListRenameTimer (internal)
1292// ---------------------------------------------------------------------------
1293
1295 {
1296 m_owner = owner;
1297 }
1298
1300 {
1301 m_owner->OnRenameTimer();
1302 }
1303
1304//-----------------------------------------------------------------------------
1305// wxEditTextCtrl (internal)
1306//-----------------------------------------------------------------------------
1307
1308 BEGIN_EVENT_TABLE (wxEditTextCtrl, wxTextCtrl)
1309 EVT_CHAR (wxEditTextCtrl::OnChar)
1310 EVT_KEY_UP (wxEditTextCtrl::OnKeyUp)
1311 EVT_KILL_FOCUS (wxEditTextCtrl::OnKillFocus)
1313
1314 wxEditTextCtrl::wxEditTextCtrl (wxWindow* parent,
1315 const wxWindowID id,
1316 bool* accept,
1317 wxString* res,
1318 wxTreeListMainWindow* owner,
1319 const wxString& value,
1320 const wxPoint& pos,
1321 const wxSize& size,
1322 int style,
1323 const wxValidator& validator,
1324 const wxString& name)
1325 : wxTextCtrl (parent, id, value, pos, size, style | wxSIMPLE_BORDER, validator, name)
1326 {
1327 m_res = res;
1328 m_accept = accept;
1329 m_owner = owner;
1330 (*m_accept) = false;
1331 (*m_res) = wxEmptyString;
1332 m_startValue = value;
1333 m_finished = false;
1334 }
1335
1337 {
1338 EndEdit(true); // cancelled
1339 }
1340
1341 void wxEditTextCtrl::EndEdit(bool isCancelled)
1342 {
1343 if (m_finished) return;
1344 m_finished = true;
1345
1346 if (m_owner)
1347 {
1348 (*m_accept) = ! isCancelled;
1349 (*m_res) = isCancelled ? m_startValue : GetValue();
1350 m_owner->OnRenameAccept(*m_res == m_startValue);
1351 m_owner->m_editControl = NULL;
1352 m_owner->m_editItem = NULL;
1353 m_owner->SetFocus(); // This doesn't work. TODO.
1354 m_owner = NULL;
1355 }
1356
1357 Destroy();
1358 }
1359
1361 {
1362 Hide();
1363#if wxCHECK_VERSION(2,9,0)
1364 wxTheApp->ScheduleForDestruction(this);
1365#else
1366 wxTheApp->GetTraits()->ScheduleForDestroy(this);
1367#endif
1368 return true;
1369 }
1370
1371 void wxEditTextCtrl::OnChar( wxKeyEvent& event )
1372 {
1373 if (m_finished)
1374 {
1375 event.Skip();
1376 return;
1377 }
1378 if (event.GetKeyCode() == WXK_RETURN)
1379 {
1380 EndEdit(false); // not cancelled
1381 return;
1382 }
1383 if (event.GetKeyCode() == WXK_ESCAPE)
1384 {
1385 EndEdit(true); // cancelled
1386 return;
1387 }
1388 event.Skip();
1389 }
1390
1391 void wxEditTextCtrl::OnKeyUp( wxKeyEvent& event )
1392 {
1393 if (m_finished)
1394 {
1395 event.Skip();
1396 return;
1397 }
1398
1399 // auto-grow the textctrl:
1400 wxSize parentSize = m_owner->GetSize();
1401 wxPoint myPos = GetPosition();
1402 wxSize mySize = GetSize();
1403 int sx, sy;
1404 GetTextExtent(GetValue() + _T("M"), &sx, &sy);
1405 if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x;
1406 if (mySize.x > sx) sx = mySize.x;
1407 SetSize(sx, -1);
1408
1409 event.Skip();
1410 }
1411
1412 void wxEditTextCtrl::OnKillFocus( wxFocusEvent& event )
1413 {
1414 if (m_finished)
1415 {
1416 event.Skip();
1417 return;
1418 }
1419
1420 EndEdit(false); // not cancelled
1421 }
1422
1423//-----------------------------------------------------------------------------
1424// wxTreeListHeaderWindow
1425//-----------------------------------------------------------------------------
1426
1428
1429 BEGIN_EVENT_TABLE(wxTreeListHeaderWindow, wxWindow)
1431 EVT_ERASE_BACKGROUND(wxTreeListHeaderWindow::OnEraseBackground) // reduce flicker
1432 EVT_MOUSE_EVENTS (wxTreeListHeaderWindow::OnMouse)
1433 EVT_SET_FOCUS (wxTreeListHeaderWindow::OnSetFocus)
1435
1436
1437 void wxTreeListHeaderWindow::Init()
1438 {
1439 m_currentCursor = (wxCursor*) NULL;
1440 m_isDragging = false;
1441 m_dirty = false;
1442 m_total_col_width = 0;
1443#if wxCHECK_VERSION_FULL(2, 7, 0, 1)
1444 m_hotTrackCol = -1;
1445#endif
1446
1447 // prevent any background repaint in order to reducing flicker
1448 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
1449 }
1450
1452 {
1453 Init();
1454
1455 m_owner = (wxTreeListMainWindow*) NULL;
1456 m_resizeCursor = (wxCursor*) NULL;
1457 }
1458
1460 wxWindowID id,
1461 wxTreeListMainWindow* owner,
1462 const wxPoint& pos,
1463 const wxSize& size,
1464 long style,
1465 const wxString& name )
1466 : wxWindow( win, id, pos, size, style, name )
1467 {
1468 Init();
1469
1470 m_owner = owner;
1471 m_resizeCursor = new wxCursor(wxCURSOR_SIZEWE);
1472
1473#if !wxCHECK_VERSION(2, 5, 0)
1474 SetBackgroundColour (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNFACE));
1475#else
1476 SetBackgroundColour (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNFACE));
1477#endif
1478 }
1479
1481 {
1482 delete m_resizeCursor;
1483 }
1484
1485 void wxTreeListHeaderWindow::DoDrawRect( wxDC* dc, int x, int y, int w, int h )
1486 {
1487#if !wxCHECK_VERSION(2, 5, 0)
1488 wxPen pen (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID);
1489#else
1490 wxPen pen (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID);
1491#endif
1492
1493 const int m_corner = 1;
1494
1495 dc->SetBrush( *wxTRANSPARENT_BRUSH );
1496#if defined( __WXMAC__ )
1497 dc->SetPen (pen);
1498#else // !GTK, !Mac
1499 dc->SetPen( *wxBLACK_PEN );
1500#endif
1501 dc->DrawLine( x + w - m_corner + 1, y, x + w, y + h ); // right (outer)
1502 dc->DrawRectangle( x, y + h, w + 1, 1 ); // bottom (outer)
1503
1504#if defined( __WXMAC__ )
1505 pen = wxPen( wxColour( 0x88, 0x88, 0x88 ), 1, wxSOLID );
1506#endif
1507 dc->SetPen( pen );
1508 dc->DrawLine( x + w - m_corner, y, x + w - 1, y + h ); // right (inner)
1509 dc->DrawRectangle( x + 1, y + h - 1, w - 2, 1 ); // bottom (inner)
1510
1511 dc->SetPen( *wxWHITE_PEN );
1512 dc->DrawRectangle( x, y, w - m_corner + 1, 1 ); // top (outer)
1513 dc->DrawRectangle( x, y, 1, h ); // left (outer)
1514 dc->DrawLine( x, y + h - 1, x + 1, y + h - 1 );
1515 dc->DrawLine( x + w - 1, y, x + w - 1, y + 1 );
1516 }
1517
1518// shift the DC origin to match the position of the main window horz
1519// scrollbar: this allows us to always use logical coords
1521 {
1522 int xpix;
1523 m_owner->GetScrollPixelsPerUnit( &xpix, NULL );
1524 int x;
1525 m_owner->GetViewStart( &x, NULL );
1526
1527 // account for the horz scrollbar offset
1528 dc.SetDeviceOrigin( -x * xpix, 0 );
1529 }
1530
1531 void wxTreeListHeaderWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
1532 {
1533 wxAutoBufferedPaintDC dc( this );
1534 AdjustDC( dc );
1535
1536 int x = HEADER_OFFSET_X;
1537
1538 // width and height of the entire header window
1539 int w, h;
1540 GetClientSize( &w, &h );
1541 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1542 dc.SetBackgroundMode(wxTRANSPARENT);
1543
1544#if wxCHECK_VERSION_FULL(2, 7, 0, 1)
1545 int numColumns = GetColumnCount();
1546 for ( int i = 0; i < numColumns && x < w; i++ )
1547 {
1548 if (!IsColumnShown (i)) continue; // do next column if not shown
1549
1550 wxHeaderButtonParams params;
1551
1552 params.m_labelColour = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT );
1553 params.m_labelFont = GetFont();
1554
1555 wxTreeListColumnInfo& column = GetColumn(i);
1556 int wCol = column.GetWidth();
1557 int flags = 0;
1558 wxRect rect(x, 0, wCol, h);
1559 x += wCol;
1560
1561 if ( i == m_hotTrackCol)
1562 flags |= wxCONTROL_CURRENT;
1563
1564 params.m_labelText = column.GetText();
1565 params.m_labelAlignment = column.GetAlignment();
1566
1567 int image = column.GetImage();
1568 wxImageList* imageList = m_owner->GetImageList();
1569 if ((image != -1) && imageList)
1570 params.m_labelBitmap = imageList->GetBitmap(image);
1571
1572 wxRendererNative::Get().DrawHeaderButton(this, dc, rect, flags, wxHDR_SORT_ICON_NONE, &params);
1573 }
1574
1575 if (x < w)
1576 {
1577 wxRect rect(x, 0, w - x, h);
1578 wxRendererNative::Get().DrawHeaderButton(this, dc, rect);
1579 }
1580
1581#else // not 2.7.0.1+
1582
1583 dc.SetFont( GetFont() );
1584
1585 // do *not* use the listctrl colour for headers - one day we will have a
1586 // function to set it separately
1587 //dc.SetTextForeground( *wxBLACK );
1588#if !wxCHECK_VERSION(2, 5, 0)
1589 dc.SetTextForeground (wxSystemSettings::GetSystemColour( wxSYS_COLOUR_WINDOWTEXT ));
1590#else
1591 dc.SetTextForeground (wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOWTEXT ));
1592#endif
1593
1594 int numColumns = GetColumnCount();
1595 for ( int i = 0; i < numColumns && x < w; i++ )
1596 {
1597 if (!IsColumnShown (i)) continue; // do next column if not shown
1598
1599 wxTreeListColumnInfo& column = GetColumn(i);
1600 int wCol = column.GetWidth();
1601
1602 // the width of the rect to draw: make it smaller to fit entirely
1603 // inside the column rect
1604 int cw = wCol - 2;
1605
1606#if !wxCHECK_VERSION(2, 7, 0)
1607 dc.SetPen( *wxWHITE_PEN );
1608 DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h - 2 );
1609#else
1610 wxRect rect(x, HEADER_OFFSET_Y, cw, h - 2);
1611 wxRendererNative::GetDefault().DrawHeaderButton (this, dc, rect);
1612#endif
1613
1614 // if we have an image, draw it on the right of the label
1615 int image = column.GetImage(); //item.m_image;
1616 int ix = -2, iy = 0;
1617 wxImageList* imageList = m_owner->GetImageList();
1618 if ((image != -1) && imageList)
1619 {
1620 imageList->GetSize (image, ix, iy);
1621 }
1622
1623 // extra margins around the text label
1624 int text_width = 0;
1625 int text_x = x;
1626 int image_offset = cw - ix - 1;
1627
1628 switch (column.GetAlignment())
1629 {
1630 case wxALIGN_LEFT:
1631 text_x += EXTRA_WIDTH;
1632 cw -= ix + 2;
1633 break;
1634 case wxALIGN_RIGHT:
1635 dc.GetTextExtent (column.GetText(), &text_width, NULL);
1636 text_x += cw - text_width - EXTRA_WIDTH - MARGIN;
1637 image_offset = 0;
1638 break;
1639 case wxALIGN_CENTER:
1640 dc.GetTextExtent(column.GetText(), &text_width, NULL);
1641 text_x += (cw - text_width) / 2 + ix + 2;
1642 image_offset = (cw - text_width - ix - 2) / 2 - MARGIN;
1643 break;
1644 }
1645
1646 // draw the image
1647 if ((image != -1) && imageList)
1648 {
1649 imageList->Draw (image, dc, x + image_offset/*cw - ix - 1*/,
1650 HEADER_OFFSET_Y + (h - 4 - iy) / 2,
1651 wxIMAGELIST_DRAW_TRANSPARENT);
1652 }
1653
1654 // draw the text clipping it so that it doesn't overwrite the column boundary
1655 wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 );
1656 dc.DrawText (column.GetText(), text_x, HEADER_OFFSET_Y + EXTRA_HEIGHT );
1657
1658 // next column
1659 x += wCol;
1660 }
1661
1662 int more_w = m_owner->GetSize().x - x - HEADER_OFFSET_X;
1663 if (more_w > 0)
1664 {
1665#if !wxCHECK_VERSION(2, 7, 0)
1666 DoDrawRect (&dc, x, HEADER_OFFSET_Y, more_w, h - 2 );
1667#else
1668 wxRect rect (x, HEADER_OFFSET_Y, more_w, h - 2);
1669 wxRendererNative::GetDefault().DrawHeaderButton (this, dc, rect);
1670#endif
1671 }
1672
1673#endif // 2.7.0.1
1674 }
1675
1677 {
1678 int x1 = m_currentX;
1679 int y1 = 0;
1680 ClientToScreen (&x1, &y1);
1681
1682 int x2 = m_currentX - 1;
1683#ifdef __WXMSW__
1684 ++x2; // but why ????
1685#endif
1686 int y2 = 0;
1687 m_owner->GetClientSize( NULL, &y2 );
1688 m_owner->ClientToScreen( &x2, &y2 );
1689
1690 wxScreenDC dc;
1691 dc.SetLogicalFunction (wxINVERT);
1692 dc.SetPen (wxPen (*wxBLACK, 2, wxSOLID));
1693 dc.SetBrush (*wxTRANSPARENT_BRUSH);
1694
1695 AdjustDC(dc);
1696 dc.DrawLine (x1, y1, x2, y2);
1697 dc.SetLogicalFunction (wxCOPY);
1698 dc.SetPen (wxNullPen);
1699 dc.SetBrush (wxNullBrush);
1700 }
1701
1702#if wxCHECK_VERSION_FULL(2, 7, 0, 1)
1703 int wxTreeListHeaderWindow::XToCol(int x)
1704 {
1705 int colLeft = 0;
1706 int numColumns = GetColumnCount();
1707 for ( int col = 0; col < numColumns; col++ )
1708 {
1709 if (!IsColumnShown(col)) continue;
1710 wxTreeListColumnInfo& column = GetColumn(col);
1711
1712 if ( x < (colLeft + column.GetWidth()) )
1713 return col;
1714
1715 colLeft += column.GetWidth();
1716 }
1717 return -1;
1718 }
1719
1720 void wxTreeListHeaderWindow::RefreshColLabel(int col)
1721 {
1722 if ( col > GetColumnCount() )
1723 return;
1724
1725 int x = 0;
1726 int width = 0;
1727 int idx = 0;
1728 do
1729 {
1730 if (!IsColumnShown(idx)) continue;
1731 wxTreeListColumnInfo& column = GetColumn(idx);
1732 x += width;
1733 width = column.GetWidth();
1734 }
1735 while (++idx <= col);
1736
1737 m_owner->CalcScrolledPosition(x, 0, &x, NULL);
1738 RefreshRect(wxRect(x, 0, width, GetSize().GetHeight()));
1739 }
1740#endif
1741
1742 void wxTreeListHeaderWindow::OnMouse (wxMouseEvent& event)
1743 {
1744
1745 // we want to work with logical coords
1746 int x;
1747 m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL);
1748
1749#if wxCHECK_VERSION_FULL(2, 7, 0, 1)
1750 if ( event.Moving() )
1751 {
1752 int col = XToCol(x);
1753 if ( col != m_hotTrackCol )
1754 {
1755 // Refresh the col header so it will be painted with hot tracking
1756 // (if supported by the native renderer.)
1757 RefreshColLabel(col);
1758
1759 // Also refresh the old hot header
1760 if ( m_hotTrackCol >= 0 )
1761 RefreshColLabel(m_hotTrackCol);
1762
1763 m_hotTrackCol = col;
1764 }
1765 }
1766
1767 if ( event.Leaving() && m_hotTrackCol >= 0 )
1768 {
1769 // Leaving the window so clear any hot tracking indicator that may be present
1770 RefreshColLabel(m_hotTrackCol);
1771 m_hotTrackCol = -1;
1772 }
1773#endif
1774
1775 if (m_isDragging)
1776 {
1777
1778 SendListEvent (wxEVT_COMMAND_LIST_COL_DRAGGING, event.GetPosition());
1779
1780 // we don't draw the line beyond our window, but we allow dragging it
1781 // there
1782 int w = 0;
1783 GetClientSize( &w, NULL );
1784 m_owner->CalcUnscrolledPosition(w, 0, &w, NULL);
1785 w -= 6;
1786
1787 // erase the line if it was drawn
1788 if (m_currentX < w) DrawCurrent();
1789
1790 if (event.ButtonUp())
1791 {
1792 m_isDragging = false;
1793 if (HasCapture()) ReleaseMouse();
1794 m_dirty = true;
1796 Refresh();
1797 SendListEvent (wxEVT_COMMAND_LIST_COL_END_DRAG, event.GetPosition());
1798 }
1799 else
1800 {
1801 m_currentX = wxMax (m_minX + 7, x);
1802
1803 // draw in the new location
1804 if (m_currentX < w) DrawCurrent();
1805 }
1806
1807 }
1808 else // not dragging
1809 {
1810
1811 m_minX = 0;
1812 bool hit_border = false;
1813
1814 // end of the current column
1815 int xpos = 0;
1816
1817 // find the column where this event occured
1818 int countCol = GetColumnCount();
1819 for (int column = 0; column < countCol; column++)
1820 {
1821 if (!IsColumnShown (column)) continue; // do next if not shown
1822
1823 xpos += GetColumnWidth (column);
1824 m_column = column;
1825 if (abs (x - xpos) < 3)
1826 {
1827 // near the column border
1828 hit_border = true;
1829 break;
1830 }
1831
1832 if (x < xpos)
1833 {
1834 // inside the column
1835 break;
1836 }
1837
1838 m_minX = xpos;
1839 }
1840
1841 if (event.LeftDown() || event.RightUp())
1842 {
1843 m_owner->EndEdit(true); // cancelled
1844
1845 if (hit_border && event.LeftDown())
1846 {
1847 m_isDragging = true;
1848 CaptureMouse();
1849 m_currentX = x;
1850 DrawCurrent();
1851 SendListEvent (wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, event.GetPosition());
1852 }
1853 else // click on a column
1854 {
1855 wxEventType evt = event.LeftDown() ? wxEVT_COMMAND_LIST_COL_CLICK :
1856 wxEVT_COMMAND_LIST_COL_RIGHT_CLICK;
1857 SendListEvent (evt, event.GetPosition());
1858 }
1859 }
1860 else if (event.LeftDClick() && hit_border)
1861 {
1863 Refresh();
1864
1865 }
1866 else if (event.Moving())
1867 {
1868 bool setCursor;
1869 if (hit_border)
1870 {
1871 setCursor = m_currentCursor == wxSTANDARD_CURSOR;
1873 }
1874 else
1875 {
1876 setCursor = m_currentCursor != wxSTANDARD_CURSOR;
1877 m_currentCursor = wxSTANDARD_CURSOR;
1878 }
1879 if (setCursor) SetCursor (*m_currentCursor);
1880 }
1881
1882 }
1883 }
1884
1885 void wxTreeListHeaderWindow::OnSetFocus (wxFocusEvent& WXUNUSED(event))
1886 {
1887 m_owner->SetFocus();
1888 }
1889
1890 void wxTreeListHeaderWindow::SendListEvent (wxEventType type, wxPoint pos)
1891 {
1892 wxWindow* parent = GetParent();
1893 wxListEvent le (type, parent->GetId());
1894 le.SetEventObject (parent);
1895 le.m_pointDrag = pos;
1896
1897 // the position should be relative to the parent window, not
1898 // this one for compatibility with MSW and common sense: the
1899 // user code doesn't know anything at all about this header
1900 // window, so why should it get positions relative to it?
1901 le.m_pointDrag.y -= GetSize().y;
1902 le.m_col = m_column;
1903 parent->GetEventHandler()->ProcessEvent (le);
1904 }
1905
1907 {
1908 m_columns.Add (colInfo);
1909 m_total_col_width += colInfo.GetWidth();
1911 m_owner->m_dirty = true;
1912 }
1913
1914 void wxTreeListHeaderWindow::SetColumnWidth (int column, int width)
1915 {
1916 wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1917 m_total_col_width -= m_columns[column].GetWidth();
1918 m_columns[column].SetWidth(width);
1919 m_total_col_width += m_columns[column].GetWidth();
1921 m_owner->m_dirty = true;
1922 }
1923
1925 {
1926 wxCHECK_RET ((before >= 0) && (before < GetColumnCount()), _T("Invalid column"));
1927 m_columns.Insert (colInfo, before);
1928 m_total_col_width += colInfo.GetWidth();
1930 m_owner->m_dirty = true;
1931 }
1932
1934 {
1935 wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1936 m_total_col_width -= m_columns[column].GetWidth();
1937 m_columns.RemoveAt (column);
1939 m_owner->m_dirty = true;
1940 }
1941
1943 {
1944 wxCHECK_RET ((column >= 0) && (column < GetColumnCount()), _T("Invalid column"));
1945 int w = m_columns[column].GetWidth();
1946 m_columns[column] = info;
1947 if (w != info.GetWidth())
1948 {
1949 m_total_col_width -= w;
1950 m_total_col_width += info.GetWidth();
1952 }
1953 m_owner->m_dirty = true;
1954 }
1955
1956// ---------------------------------------------------------------------------
1957// wxTreeListItem
1958// ---------------------------------------------------------------------------
1959
1961 wxTreeListItem* parent,
1962 const wxArrayString& text,
1963 int image, int selImage,
1964 wxTreeItemData* data)
1965 : m_text (text)
1966 {
1967
1968 m_images[wxTreeItemIcon_Normal] = image;
1969 m_images[wxTreeItemIcon_Selected] = selImage;
1970 m_images[wxTreeItemIcon_Expanded] = NO_IMAGE;
1971 m_images[wxTreeItemIcon_SelectedExpanded] = NO_IMAGE;
1972
1973 m_props_row.m_data = data;
1974 m_toolTip = NULL;
1975 m_x = 0;
1976 m_y = 0;
1977 m_text_x = 0;
1978
1979 m_isCollapsed = true;
1980 m_hasHilight = false;
1981 m_hasPlus = false;
1982
1983 m_owner = owner;
1984 m_parent = parent;
1985
1986 // We don't know the height here yet.
1987 m_width = 0;
1988 m_height = 0;
1989 }
1990
1992 {
1993 if (m_toolTip) delete m_toolTip;
1994
1995 wxTreeListItemCellAttrHash::iterator entry = m_props_cell.begin();
1996 while (entry != m_props_cell.end())
1997 {
1998 if (entry->second) delete entry->second;
1999 entry++;
2000 }
2001
2002 wxASSERT_MSG( m_children.IsEmpty(), _T("please call DeleteChildren() before destructor"));
2003 }
2004
2006 {
2007 m_children.Empty();
2008 }
2009
2010 size_t wxTreeListItem::GetChildrenCount (bool recursively) const
2011 {
2012 size_t count = m_children.Count();
2013 if (!recursively) return count;
2014
2015 size_t total = count;
2016 for (size_t n = 0; n < count; ++n)
2017 {
2018 total += m_children[n]->GetChildrenCount();
2019 }
2020 return total;
2021 }
2022
2023 void wxTreeListItem::GetSize (int& x, int& y, const wxTreeListMainWindow* theButton)
2024 {
2025 int bottomY = m_y + theButton->GetLineHeight (this);
2026 if (y < bottomY) y = bottomY;
2027 int width = m_x + GetWidth();
2028 if ( x < width ) x = width;
2029
2030 if (IsExpanded())
2031 {
2032 size_t count = m_children.Count();
2033 for (size_t n = 0; n < count; ++n )
2034 {
2035 m_children[n]->GetSize (x, y, theButton);
2036 }
2037 }
2038 }
2039
2041 const wxTreeListMainWindow* theCtrl,
2042 int& flags, int& column, int level)
2043 {
2044
2045 // reset any previous hit infos
2046 flags = 0;
2047 column = -1;
2048
2049 // for a hidden root node, don't evaluate it, but do evaluate children
2050 if (!theCtrl->HasFlag(wxTR_HIDE_ROOT) || (level > 0))
2051 {
2052
2053 wxTreeListHeaderWindow* header_win = theCtrl->m_owner->GetHeaderWindow();
2054
2055 // check for right of all columns (outside)
2056 if (point.x > header_win->GetWidth()) return (wxTreeListItem*) NULL;
2057 // else find column
2058 for (int x = 0, j = 0; j < theCtrl->GetColumnCount(); ++j)
2059 {
2060 if (!header_win->IsColumnShown(j)) continue;
2061 int w = header_win->GetColumnWidth (j);
2062 if (point.x >= x && point.x < x + w)
2063 {
2064 column = j;
2065 break;
2066 }
2067 x += w;
2068 }
2069
2070 // evaluate if y-pos is okay
2071 int h = theCtrl->GetLineHeight (this);
2072 if ((point.y >= m_y) && (point.y <= m_y + h))
2073 {
2074
2075 // check for above/below middle
2076 int y_mid = m_y + h / 2;
2077 if (point.y < y_mid)
2078 {
2079 flags |= wxTREE_HITTEST_ONITEMUPPERPART;
2080 }
2081 else
2082 {
2083 flags |= wxTREE_HITTEST_ONITEMLOWERPART;
2084 }
2085
2086 // check for button hit
2087 if (HasPlus() && theCtrl->HasButtons())
2088 {
2089 int bntX = m_x - theCtrl->m_btnWidth2;
2090 int bntY = y_mid - theCtrl->m_btnHeight2;
2091 if ((point.x >= bntX) && (point.x <= (bntX + theCtrl->m_btnWidth)) &&
2092 (point.y >= bntY) && (point.y <= (bntY + theCtrl->m_btnHeight)))
2093 {
2094 flags |= wxTREE_HITTEST_ONITEMBUTTON;
2095 return this;
2096 }
2097 }
2098
2099 // check for image hit
2100 if (theCtrl->m_imgWidth > 0)
2101 {
2102 int imgX = m_text_x - theCtrl->m_imgWidth - MARGIN;
2103 int imgY = y_mid - theCtrl->m_imgHeight2;
2104 if ((point.x >= imgX) && (point.x <= (imgX + theCtrl->m_imgWidth)) &&
2105 (point.y >= imgY) && (point.y <= (imgY + theCtrl->m_imgHeight)))
2106 {
2107 flags |= wxTREE_HITTEST_ONITEMICON;
2108 return this;
2109 }
2110 }
2111
2112 // check for label hit
2113 if ((point.x >= m_text_x) && (point.x <= (m_text_x + GetWidth())))
2114 {
2115 flags |= wxTREE_HITTEST_ONITEMLABEL;
2116 return this;
2117 }
2118
2119 // check for indent hit after button and image hit
2120 if (point.x < m_x)
2121 {
2122 flags |= wxTREE_HITTEST_ONITEMINDENT;
2123 return this;
2124 }
2125
2126 // check for right of label
2127 int end = 0;
2128 for (int i = 0; i <= theCtrl->GetMainColumn(); ++i) end += header_win->GetColumnWidth (i);
2129 if ((point.x > (m_text_x + GetWidth())) && (point.x <= end))
2130 {
2131 flags |= wxTREE_HITTEST_ONITEMRIGHT;
2132 return this;
2133 }
2134
2135 // else check for each column except main
2136 if (column >= 0 && column != theCtrl->GetMainColumn())
2137 {
2139 return this;
2140 }
2141
2142 // no special flag or column found
2143 return this;
2144
2145 }
2146
2147 // if children not expanded, return no item
2148 if (!IsExpanded()) return (wxTreeListItem*) NULL;
2149 }
2150
2151 // in any case evaluate children
2152 wxTreeListItem* child;
2153 size_t count = m_children.Count();
2154 for (size_t n = 0; n < count; n++)
2155 {
2156 child = m_children[n]->HitTest (point, theCtrl, flags, column, level + 1);
2157 if (child) return child;
2158 }
2159
2160 // not found
2161 return (wxTreeListItem*) NULL;
2162 }
2163
2165 {
2166 int image = NO_IMAGE;
2167 if (IsExpanded())
2168 {
2169 if (IsSelected())
2170 {
2171 image = GetImage (wxTreeItemIcon_SelectedExpanded);
2172 }
2173 else
2174 {
2175 image = GetImage (wxTreeItemIcon_Expanded);
2176 }
2177 }
2178 else // not expanded
2179 {
2180 if (IsSelected())
2181 {
2182 image = GetImage (wxTreeItemIcon_Selected);
2183 }
2184 else
2185 {
2186 image = GetImage (wxTreeItemIcon_Normal);
2187 }
2188 }
2189
2190 // maybe it doesn't have the specific image, try the default one instead
2191 if (image == NO_IMAGE) image = GetImage();
2192
2193 return image;
2194 }
2195
2196// ---------------------------------------------------------------------------
2197// wxTreeListMainWindow implementation
2198// ---------------------------------------------------------------------------
2199
2201
2202 BEGIN_EVENT_TABLE(wxTreeListMainWindow, wxScrolledWindow)
2204 EVT_ERASE_BACKGROUND(wxTreeListMainWindow::OnEraseBackground) // to reduce flicker
2205 EVT_MOUSE_EVENTS (wxTreeListMainWindow::OnMouse)
2206 EVT_CHAR (wxTreeListMainWindow::OnChar)
2207 EVT_SET_FOCUS (wxTreeListMainWindow::OnSetFocus)
2208 EVT_KILL_FOCUS (wxTreeListMainWindow::OnKillFocus)
2209 EVT_IDLE (wxTreeListMainWindow::OnIdle)
2210 EVT_SCROLLWIN (wxTreeListMainWindow::OnScroll)
2211 EVT_MOUSE_CAPTURE_LOST(wxTreeListMainWindow::OnCaptureLost)
2213
2214
2215// ---------------------------------------------------------------------------
2216// construction/destruction
2217// ---------------------------------------------------------------------------
2218
2219
2220 void wxTreeListMainWindow::Init()
2221 {
2222
2223 m_rootItem = (wxTreeListItem*)NULL;
2224 m_curItem = (wxTreeListItem*)NULL;
2225 m_shiftItem = (wxTreeListItem*)NULL;
2226 m_editItem = (wxTreeListItem*)NULL;
2227 m_selectItem = (wxTreeListItem*)NULL;
2228
2229 m_curColumn = -1; // no current column
2230
2231 m_hasFocus = false;
2232 m_dirty = false;
2233
2234 m_lineHeight = LINEHEIGHT;
2235 m_indent = MININDENT; // min. indent
2236 m_linespacing = 4;
2237
2238#if !wxCHECK_VERSION(2, 5, 0)
2239 m_hilightBrush = new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHT), wxSOLID);
2240 m_hilightUnfocusedBrush = new wxBrush (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_BTNSHADOW), wxSOLID);
2241#else
2242 m_hilightBrush = new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHT), wxSOLID);
2243 m_hilightUnfocusedBrush = new wxBrush (wxSystemSettings::GetColour (wxSYS_COLOUR_BTNSHADOW), wxSOLID);
2244#endif
2245
2246 m_imageListNormal = (wxImageList*) NULL;
2247 m_imageListButtons = (wxImageList*) NULL;
2248 m_imageListState = (wxImageList*) NULL;
2249 m_ownsImageListNormal = m_ownsImageListButtons =
2250 m_ownsImageListState = false;
2251
2252 m_imgWidth = 0, m_imgWidth2 = 0;
2253 m_imgHeight = 0, m_imgHeight2 = 0;
2254 m_btnWidth = 0, m_btnWidth2 = 0;
2255 m_btnHeight = 0, m_btnHeight2 = 0;
2256
2257 m_isDragStarted = m_isDragging = false;
2258 m_dragItem = NULL;
2259 m_dragCol = -1;
2260
2261 m_editTimer = new wxTreeListRenameTimer (this);
2262 m_editControl = NULL;
2263
2264 m_lastOnSame = false;
2265 m_left_down_selection = false;
2266
2267 m_findTimer = new wxTimer (this, -1);
2268
2269#if defined( __WXMAC__ ) && defined(__WXMAC_CARBON__)
2270 m_normalFont.MacCreateThemeFont (kThemeViewsFont);
2271#else
2272 m_normalFont = wxSystemSettings::GetFont (wxSYS_DEFAULT_GUI_FONT);
2273#endif
2274 m_boldFont = wxFont( m_normalFont.GetPointSize(),
2275 m_normalFont.GetFamily(),
2276 m_normalFont.GetStyle(),
2277 wxBOLD,
2278 m_normalFont.GetUnderlined(),
2279 m_normalFont.GetFaceName(),
2280 m_normalFont.GetEncoding());
2281
2282 m_toolTip.clear();
2283 m_toolTipItem = (wxTreeListItem*) - 1; // no tooltip displayed
2284 m_isItemToolTip = false; // so far no item-specific tooltip
2285 }
2286
2288 wxWindowID id,
2289 const wxPoint& pos,
2290 const wxSize& size,
2291 long style,
2292 const wxValidator& validator,
2293 const wxString& name)
2294 {
2295
2296#ifdef __WXMAC__
2297 if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS;
2298 if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS;
2299 style &= ~wxTR_LINES_AT_ROOT;
2300 style |= wxTR_NO_LINES;
2301
2302 int major, minor;
2303 wxGetOsVersion( &major, &minor );
2304 if (major < 10) style |= wxTR_ROW_LINES;
2305#endif
2306
2307 wxScrolledWindow::Create (parent, id, pos, size, style | wxHSCROLL | wxVSCROLL, name);
2308
2309#if wxUSE_VALIDATORS
2310 SetValidator(validator);
2311#endif
2312
2313#if !wxCHECK_VERSION(2, 5, 0)
2314 SetBackgroundColour (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_LISTBOX));
2315#else
2316 SetBackgroundColour (wxSystemSettings::GetColour (wxSYS_COLOUR_LISTBOX));
2317#endif
2318 // prevent any background repaint in order to reducing flicker
2319 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
2320
2321#ifdef __WXMSW__
2322 {
2323 int i, j;
2324 wxBitmap bmp(8, 8);
2325 wxMemoryDC bdc;
2326 bdc.SelectObject(bmp);
2327 bdc.SetPen(*wxGREY_PEN);
2328 bdc.DrawRectangle(-1, -1, 10, 10);
2329 for (i = 0; i < 8; i++)
2330 {
2331 for (j = 0; j < 8; j++)
2332 {
2333 if (!((i + j) & 1))
2334 {
2335 bdc.DrawPoint(i, j);
2336 }
2337 }
2338 }
2339
2340 m_dottedPen = wxPen(bmp, 1);
2341 }
2342#else
2343//? m_dottedPen = wxPen( *wxGREY_PEN, 1, wxDOT ); // too slow under XFree86
2344 m_dottedPen = wxPen( _T("grey"), 0, 0 ); // Bitmap based pen is not supported by GTK!
2345#endif
2346
2347 m_owner = parent;
2348 m_main_column = 0;
2349
2350 return true;
2351 }
2352
2354 {
2355 delete m_hilightBrush;
2357
2358 delete m_editTimer;
2359 delete m_findTimer;
2363
2364 if (m_editControl)
2365 {
2366 m_editControl->SetOwner(NULL); // prevent control from calling us during delete
2367 delete m_editControl;
2368 }
2369
2370 DeleteRoot();
2371 }
2372
2373
2374//-----------------------------------------------------------------------------
2375// accessors
2376//-----------------------------------------------------------------------------
2377
2379 {
2380 return m_rootItem == NULL ? 0 : m_rootItem->GetChildrenCount();
2381 }
2382
2383 void wxTreeListMainWindow::SetIndent (unsigned int indent)
2384 {
2385 m_indent = wxMax ((unsigned)MININDENT, indent);
2386 m_dirty = true;
2387 }
2388
2389 void wxTreeListMainWindow::SetLineSpacing (unsigned int spacing)
2390 {
2391 m_linespacing = spacing;
2392 m_dirty = true;
2394 }
2395
2396 size_t wxTreeListMainWindow::GetChildrenCount (const wxTreeItemId& item,
2397 bool recursively)
2398 {
2399 wxCHECK_MSG (item.IsOk(), 0u, _T("invalid tree item"));
2400 return ((wxTreeListItem*)item.m_pItem)->GetChildrenCount (recursively);
2401 }
2402
2404 {
2405 // change to selection mode, reset selection
2406 if ((styles ^ m_windowStyle) & wxTR_MULTIPLE)
2407 {
2408 UnselectAll();
2409 }
2410 // right now, just sets the styles. Eventually, we may
2411 // want to update the inherited styles, but right now
2412 // none of the parents has updatable styles
2413 m_windowStyle = styles;
2414 m_dirty = true;
2415 }
2416
2417 void wxTreeListMainWindow::SetToolTip(const wxString& tip)
2418 {
2419 m_isItemToolTip = false;
2420 m_toolTip = tip;
2421 m_toolTipItem = (wxTreeListItem*) - 1; // no tooltip displayed (force refresh)
2422 }
2424 {
2425 m_isItemToolTip = false;
2426 m_toolTip = (tip == NULL) ? wxString() : tip->GetTip();
2427 m_toolTipItem = (wxTreeListItem*) - 1; // no tooltip displayed (force refresh)
2428 }
2429
2430 void wxTreeListMainWindow::SetItemToolTip(const wxTreeItemId& item, const wxString& tip)
2431 {
2432 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2433 m_isItemToolTip = true;
2434 ((wxTreeListItem*) item.m_pItem)->SetToolTip(tip);
2435 m_toolTipItem = (wxTreeListItem*) - 1; // no tooltip displayed (force refresh)
2436 }
2437
2438
2439//-----------------------------------------------------------------------------
2440// functions to work with tree items
2441//-----------------------------------------------------------------------------
2442
2443 int wxTreeListMainWindow::GetItemImage (const wxTreeItemId& item, int column, wxTreeItemIcon which) const
2444 {
2445 wxCHECK_MSG (item.IsOk(), -1, _T("invalid tree item"));
2446 return ((wxTreeListItem*) item.m_pItem)->GetImage (column, which);
2447 }
2448
2449 wxTreeItemData* wxTreeListMainWindow::GetItemData (const wxTreeItemId& item) const
2450 {
2451 wxCHECK_MSG (item.IsOk(), NULL, _T("invalid tree item"));
2452 return ((wxTreeListItem*) item.m_pItem)->GetData();
2453 }
2454 wxTreeItemData* wxTreeListMainWindow::GetItemData (const wxTreeItemId& item, int column) const
2455 {
2456 wxCHECK_MSG (item.IsOk(), NULL, _T("invalid tree item"));
2457 return ((wxTreeListItem*) item.m_pItem)->GetData(column);
2458 }
2459
2460 bool wxTreeListMainWindow::GetItemBold (const wxTreeItemId& item) const
2461 {
2462 wxCHECK_MSG(item.IsOk(), false, _T("invalid tree item"));
2463 return ((wxTreeListItem*)item.m_pItem)->IsBold();
2464 }
2465 bool wxTreeListMainWindow::GetItemBold (const wxTreeItemId& item, int column) const
2466 {
2467 wxCHECK_MSG(item.IsOk(), false, _T("invalid tree item"));
2468 return ((wxTreeListItem*)item.m_pItem)->IsBold(column);
2469 }
2470
2471 wxColour wxTreeListMainWindow::GetItemTextColour (const wxTreeItemId& item) const
2472 {
2473 wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
2474 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2475 wxTreeItemAttr* attr = pItem->GetAttributes();
2476 if (attr && attr->HasTextColour())
2477 {
2478 return attr->GetTextColour();
2479 }
2480 else
2481 {
2482 return GetForegroundColour();
2483 }
2484 }
2485 wxColour wxTreeListMainWindow::GetItemTextColour (const wxTreeItemId& item, int column) const
2486 {
2487 wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
2488 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2489 wxTreeItemAttr* attr = pItem->GetAttributes(column);
2490 if (attr && attr->HasTextColour())
2491 {
2492 return attr->GetTextColour();
2493 }
2494 else
2495 {
2496 return GetItemTextColour(item);
2497 }
2498 }
2499
2500 wxColour wxTreeListMainWindow::GetItemBackgroundColour (const wxTreeItemId& item) const
2501 {
2502 wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
2503 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2504 wxTreeItemAttr* attr = pItem->GetAttributes();
2505 if (attr && attr->HasBackgroundColour())
2506 {
2507 return attr->GetBackgroundColour();
2508 }
2509 else
2510 {
2511 return GetBackgroundColour();
2512 }
2513 }
2514 wxColour wxTreeListMainWindow::GetItemBackgroundColour (const wxTreeItemId& item, int column) const
2515 {
2516 wxCHECK_MSG (item.IsOk(), wxNullColour, _T("invalid tree item"));
2517 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2518 wxTreeItemAttr* attr = pItem->GetAttributes(column);
2519 if (attr && attr->HasBackgroundColour())
2520 {
2521 return attr->GetBackgroundColour();
2522 }
2523 else
2524 {
2525 return GetItemBackgroundColour(item);
2526 }
2527 }
2528
2529 wxFont wxTreeListMainWindow::GetItemFont (const wxTreeItemId& item) const
2530 {
2531 wxCHECK_MSG (item.IsOk(), wxNullFont, _T("invalid tree item"));
2532 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2533 wxTreeItemAttr* attr = pItem->GetAttributes();
2534 if (attr && attr->HasFont())
2535 {
2536 return attr->GetFont();
2537 }
2538 else if (pItem->IsBold())
2539 {
2540 return m_boldFont;
2541 }
2542 else
2543 {
2544 return m_normalFont;
2545 }
2546 }
2547 wxFont wxTreeListMainWindow::GetItemFont (const wxTreeItemId& item, int column) const
2548 {
2549 wxCHECK_MSG (item.IsOk(), wxNullFont, _T("invalid tree item"));
2550 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2551 wxTreeItemAttr* attr_cell = pItem->GetAttributes(column);
2552 wxTreeItemAttr* attr_row = pItem->GetAttributes();
2553 if (attr_cell && attr_cell->HasFont())
2554 {
2555 return attr_cell->GetFont();
2556 }
2557 else if (attr_row && attr_row->HasFont())
2558 {
2559 return attr_row->GetFont();
2560 }
2561 else if (pItem->IsBold(column))
2562 {
2563 return m_boldFont;
2564 }
2565 else
2566 {
2567 return m_normalFont;
2568 }
2569 }
2570
2571 void wxTreeListMainWindow::SetItemHasChildren (const wxTreeItemId& item, bool has)
2572 {
2573 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2574 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2575 pItem->SetHasPlus (has);
2576 RefreshLine (pItem);
2577 }
2578
2579 void wxTreeListMainWindow::SetItemImage (const wxTreeItemId& item, int column, int image, wxTreeItemIcon which)
2580 {
2581 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2582 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2583 pItem->SetImage (column, image, which);
2584 wxClientDC dc (this);
2585 CalculateSize (pItem, dc);
2586 RefreshLine (pItem);
2587 }
2588
2589 void wxTreeListMainWindow::SetItemData (const wxTreeItemId& item, wxTreeItemData* data)
2590 {
2591 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2592 ((wxTreeListItem*) item.m_pItem)->SetData(data);
2593 }
2594 void wxTreeListMainWindow::SetItemData (const wxTreeItemId& item, int column, wxTreeItemData* data)
2595 {
2596 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2597 ((wxTreeListItem*) item.m_pItem)->SetData(column, data);
2598 }
2599
2600 void wxTreeListMainWindow::SetItemBold (const wxTreeItemId& item, bool bold)
2601 {
2602 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2603 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2604 if (pItem->IsBold() != bold) // avoid redrawing if no real change
2605 {
2606 pItem->SetBold (bold);
2607 RefreshLine (pItem);
2608 }
2609 }
2610 void wxTreeListMainWindow::SetItemBold (const wxTreeItemId& item, int column, bool bold)
2611 {
2612 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2613 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2614// if (pItem->IsBold(column) != bold) { // avoid redrawing if no real change
2615 pItem->SetBold (column, bold);
2616 RefreshLine (pItem);
2617// }
2618 }
2619
2620 void wxTreeListMainWindow::SetItemTextColour (const wxTreeItemId& item, const wxColour& colour)
2621 {
2622 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2623 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2624 pItem->Attr().SetTextColour (colour);
2625 RefreshLine (pItem);
2626 }
2627 void wxTreeListMainWindow::SetItemTextColour (const wxTreeItemId& item, int column, const wxColour& colour)
2628 {
2629 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2630 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2631 pItem->Attr(column).SetTextColour (colour);
2632 RefreshLine (pItem);
2633 }
2634
2635 void wxTreeListMainWindow::SetItemBackgroundColour (const wxTreeItemId& item, const wxColour& colour)
2636 {
2637 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2638 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2639 pItem->Attr().SetBackgroundColour (colour);
2640 RefreshLine (pItem);
2641 }
2642 void wxTreeListMainWindow::SetItemBackgroundColour (const wxTreeItemId& item, int column, const wxColour& colour)
2643 {
2644 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2645 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2646 pItem->Attr(column).SetBackgroundColour (colour);
2647 RefreshLine (pItem);
2648 }
2649
2650 void wxTreeListMainWindow::SetItemFont (const wxTreeItemId& item, const wxFont& font)
2651 {
2652 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2653 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2654 pItem->Attr().SetFont (font);
2655 RefreshLine (pItem);
2656 }
2657 void wxTreeListMainWindow::SetItemFont (const wxTreeItemId& item, int column, const wxFont& font)
2658 {
2659 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
2660 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2661 pItem->Attr(column).SetFont (font);
2662 RefreshLine (pItem);
2663 }
2664
2665
2666 bool wxTreeListMainWindow::SetFont (const wxFont& font)
2667 {
2668 wxScrolledWindow::SetFont (font);
2669 m_normalFont = font;
2670 m_boldFont = wxFont (m_normalFont.GetPointSize(),
2671 m_normalFont.GetFamily(),
2672 m_normalFont.GetStyle(),
2673 wxBOLD,
2674 m_normalFont.GetUnderlined(),
2675 m_normalFont.GetFaceName());
2677 return true;
2678 }
2679
2680
2681// ----------------------------------------------------------------------------
2682// item status inquiries
2683// ----------------------------------------------------------------------------
2684
2685 bool wxTreeListMainWindow::IsVisible (const wxTreeItemId& item, bool fullRow, bool within) const
2686 {
2687 wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2688
2689 // An item is only visible if it's not a descendant of a collapsed item
2690 wxTreeListItem* pItem = (wxTreeListItem*) item.m_pItem;
2691 wxTreeListItem* parent = pItem->GetItemParent();
2692 while (parent)
2693 {
2694 if (parent == m_rootItem && HasFlag(wxTR_HIDE_ROOT)) break;
2695 if (!parent->IsExpanded()) return false;
2696 parent = parent->GetItemParent();
2697 }
2698
2699 // and the item is only visible if it is currently (fully) within the view
2700 if (within)
2701 {
2702 wxSize clientSize = GetClientSize();
2703 wxRect rect;
2704 if ((!GetBoundingRect (item, rect)) ||
2705 ((!fullRow && rect.GetWidth() == 0) || rect.GetHeight() == 0) ||
2706 (rect.GetTop() < 0 || rect.GetBottom() >= clientSize.y) ||
2707 (!fullRow && (rect.GetLeft() < 0 || rect.GetRight() >= clientSize.x))) return false;
2708 }
2709
2710 return true;
2711 }
2712
2713 bool wxTreeListMainWindow::HasChildren (const wxTreeItemId& item) const
2714 {
2715 wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2716
2717 // consider that the item does have children if it has the "+" button: it
2718 // might not have them (if it had never been expanded yet) but then it
2719 // could have them as well and it's better to err on this side rather than
2720 // disabling some operations which are restricted to the items with
2721 // children for an item which does have them
2722 return ((wxTreeListItem*) item.m_pItem)->HasPlus();
2723 }
2724
2725 bool wxTreeListMainWindow::IsExpanded (const wxTreeItemId& item) const
2726 {
2727 wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2728 return ((wxTreeListItem*) item.m_pItem)->IsExpanded();
2729 }
2730
2731 bool wxTreeListMainWindow::IsSelected (const wxTreeItemId& item) const
2732 {
2733 wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2734 return ((wxTreeListItem*) item.m_pItem)->IsSelected();
2735 }
2736
2737 bool wxTreeListMainWindow::IsBold (const wxTreeItemId& item, int column) const
2738 {
2739 wxCHECK_MSG (item.IsOk(), false, _T("invalid tree item"));
2740 return ((wxTreeListItem*) item.m_pItem)->IsBold(column);
2741 }
2742
2743// ----------------------------------------------------------------------------
2744// navigation
2745// ----------------------------------------------------------------------------
2746
2747 wxTreeItemId wxTreeListMainWindow::GetItemParent (const wxTreeItemId& item) const
2748 {
2749 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2750 return ((wxTreeListItem*) item.m_pItem)->GetItemParent();
2751 }
2752
2753#if !wxCHECK_VERSION(2, 5, 0)
2754 wxTreeItemId wxTreeListMainWindow::GetFirstChild (const wxTreeItemId& item,
2755 long& cookie) const
2756 {
2757#else
2758 wxTreeItemId wxTreeListMainWindow::GetFirstChild (const wxTreeItemId& item,
2759 wxTreeItemIdValue& cookie) const
2760 {
2761#endif
2762 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2763 wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2764 cookie = 0;
2765 return (!children.IsEmpty()) ? wxTreeItemId(children.Item(0)) : wxTreeItemId();
2766 }
2767
2768#if !wxCHECK_VERSION(2, 5, 0)
2769 wxTreeItemId wxTreeListMainWindow::GetNextChild (const wxTreeItemId& item,
2770 long& cookie) const
2771 {
2772#else
2773 wxTreeItemId wxTreeListMainWindow::GetNextChild (const wxTreeItemId& item,
2774 wxTreeItemIdValue& cookie) const
2775 {
2776#endif
2777 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2778 wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2779 // it's ok to cast cookie to long, we never have indices which overflow "void*"
2780 long* pIndex = ((long*)&cookie);
2781 return ((*pIndex) + 1 < (long)children.Count()) ? wxTreeItemId(children.Item(++(*pIndex))) : wxTreeItemId();
2782 }
2783
2784#if !wxCHECK_VERSION(2, 5, 0)
2785 wxTreeItemId wxTreeListMainWindow::GetPrevChild (const wxTreeItemId& item,
2786 long& cookie) const
2787 {
2788#else
2789 wxTreeItemId wxTreeListMainWindow::GetPrevChild (const wxTreeItemId& item,
2790 wxTreeItemIdValue& cookie) const
2791 {
2792#endif
2793 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2794 wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2795 // it's ok to cast cookie to long, we never have indices which overflow "void*"
2796 long* pIndex = (long*)&cookie;
2797 return ((*pIndex) - 1 >= 0) ? wxTreeItemId(children.Item(--(*pIndex))) : wxTreeItemId();
2798 }
2799
2800#if !wxCHECK_VERSION(2, 5, 0)
2801 wxTreeItemId wxTreeListMainWindow::GetLastChild (const wxTreeItemId& item,
2802 long& cookie) const
2803 {
2804#else
2805 wxTreeItemId wxTreeListMainWindow::GetLastChild (const wxTreeItemId& item,
2806 wxTreeItemIdValue& cookie) const
2807 {
2808#endif
2809 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2810 wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren();
2811 // it's ok to cast cookie to long, we never have indices which overflow "void*"
2812 long* pIndex = ((long*)&cookie);
2813 (*pIndex) = (long)children.Count();
2814 return (!children.IsEmpty()) ? wxTreeItemId(children.Last()) : wxTreeItemId();
2815 }
2816
2817 wxTreeItemId wxTreeListMainWindow::GetNextSibling (const wxTreeItemId& item) const
2818 {
2819 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2820
2821 // get parent
2822 wxTreeListItem* i = (wxTreeListItem*) item.m_pItem;
2823 wxTreeListItem* parent = i->GetItemParent();
2824 if (!parent) return wxTreeItemId(); // root item doesn't have any siblings
2825
2826 // get index
2827 wxArrayTreeListItems& siblings = parent->GetChildren();
2828 size_t index = siblings.Index (i);
2829 wxASSERT (index != (size_t)wxNOT_FOUND); // I'm not a child of my parent?
2830 return (index < siblings.Count() - 1) ? wxTreeItemId(siblings[index + 1]) : wxTreeItemId();
2831 }
2832
2833 wxTreeItemId wxTreeListMainWindow::GetPrevSibling (const wxTreeItemId& item) const
2834 {
2835 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2836
2837 // get parent
2838 wxTreeListItem* i = (wxTreeListItem*) item.m_pItem;
2839 wxTreeListItem* parent = i->GetItemParent();
2840 if (!parent) return wxTreeItemId(); // root item doesn't have any siblings
2841
2842 // get index
2843 wxArrayTreeListItems& siblings = parent->GetChildren();
2844 size_t index = siblings.Index(i);
2845 wxASSERT (index != (size_t)wxNOT_FOUND); // I'm not a child of my parent?
2846 return (index >= 1) ? wxTreeItemId(siblings[index - 1]) : wxTreeItemId();
2847 }
2848
2849// Only for internal use right now, but should probably be public
2850 wxTreeItemId wxTreeListMainWindow::GetNext (const wxTreeItemId& item, bool fulltree) const
2851 {
2852 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2853
2854 // if there are any children, return first child
2855 if (fulltree || ((wxTreeListItem*)item.m_pItem)->IsExpanded())
2856 {
2857 wxArrayTreeListItems& children = ((wxTreeListItem*)item.m_pItem)->GetChildren();
2858 if (children.GetCount() > 0) return children.Item (0);
2859 }
2860
2861 // get sibling of this item or of the ancestors instead
2862 wxTreeItemId next;
2863 wxTreeItemId parent = item;
2864 do
2865 {
2866 next = GetNextSibling (parent);
2867 parent = GetItemParent (parent);
2868 }
2869 while (!next.IsOk() && parent.IsOk());
2870 return next;
2871 }
2872
2873// Only for internal use right now, but should probably be public
2874 wxTreeItemId wxTreeListMainWindow::GetPrev (const wxTreeItemId& item, bool fulltree) const
2875 {
2876 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2877
2878 // if there are no previous sibling get parent
2879 wxTreeItemId prev = GetPrevSibling (item);
2880 if (! prev.IsOk()) return GetItemParent (item);
2881
2882 // while previous sibling has children, return last
2883 while (fulltree || ((wxTreeListItem*)prev.m_pItem)->IsExpanded())
2884 {
2885 wxArrayTreeListItems& children = ((wxTreeListItem*)prev.m_pItem)->GetChildren();
2886 if (children.GetCount() == 0) break;
2887 prev = children.Item (children.GetCount() - 1);
2888 }
2889
2890 return prev;
2891 }
2892
2894 {
2895 return GetNextExpanded (GetRootItem());
2896 }
2897
2898 wxTreeItemId wxTreeListMainWindow::GetNextExpanded (const wxTreeItemId& item) const
2899 {
2900 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2901 return GetNext (item, false);
2902 }
2903
2904 wxTreeItemId wxTreeListMainWindow::GetPrevExpanded (const wxTreeItemId& item) const
2905 {
2906 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2907 return GetPrev (item, false);
2908 }
2909
2910 wxTreeItemId wxTreeListMainWindow::GetFirstVisible(bool fullRow, bool within) const
2911 {
2912 if (HasFlag(wxTR_HIDE_ROOT) || ! IsVisible(GetRootItem(), fullRow, within))
2913 {
2914 return GetNextVisible (GetRootItem(), fullRow, within);
2915 }
2916 else
2917 {
2918 return GetRootItem();
2919 }
2920 }
2921
2922 wxTreeItemId wxTreeListMainWindow::GetNextVisible (const wxTreeItemId& item, bool fullRow, bool within) const
2923 {
2924 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2925 wxTreeItemId id = GetNext (item, false);
2926 while (id.IsOk())
2927 {
2928 if (IsVisible (id, fullRow, within)) return id;
2929 id = GetNext (id, false);
2930 }
2931 return wxTreeItemId();
2932 }
2933
2934 wxTreeItemId wxTreeListMainWindow::GetLastVisible ( bool fullRow, bool within) const
2935 {
2936 wxCHECK_MSG (GetRootItem().IsOk(), wxTreeItemId(), _T("invalid tree item"));
2937 wxTreeItemId id = GetRootItem();
2938 wxTreeItemId res = id;
2939 while ((id = GetNext (id, false)).IsOk())
2940 {
2941 if (IsVisible (id, fullRow, within)) res = id;
2942 }
2943 return res;
2944 }
2945
2946 wxTreeItemId wxTreeListMainWindow::GetPrevVisible (const wxTreeItemId& item, bool fullRow, bool within) const
2947 {
2948 wxCHECK_MSG (item.IsOk(), wxTreeItemId(), _T("invalid tree item"));
2949 wxTreeItemId id = GetPrev (item, true);
2950 while (id.IsOk())
2951 {
2952 if (IsVisible (id, fullRow, within)) return id;
2953 id = GetPrev(id, true);
2954 }
2955 return wxTreeItemId();
2956 }
2957
2958// ----------------------------------------------------------------------------
2959// operations
2960// ----------------------------------------------------------------------------
2961
2962// ---------------------------- ADD OPERATION -------------------------------
2963
2964 wxTreeItemId wxTreeListMainWindow::DoInsertItem (const wxTreeItemId& parentId,
2965 size_t previous,
2966 const wxString& text,
2967 int image, int selImage,
2968 wxTreeItemData* data)
2969 {
2970 wxTreeListItem* parent = (wxTreeListItem*)parentId.m_pItem;
2971 wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
2972 m_dirty = true; // do this first so stuff below doesn't cause flicker
2973
2974 wxArrayString arr;
2975 arr.Alloc (GetColumnCount());
2976 for (int i = 0; i < (int)GetColumnCount(); ++i) arr.Add (wxEmptyString);
2977 arr[m_main_column] = text;
2978 wxTreeListItem* item = new wxTreeListItem (this, parent, arr, image, selImage, data);
2979 if (data != NULL)
2980 {
2981#if !wxCHECK_VERSION(2, 5, 0)
2982 data->SetId ((long)item);
2983#else
2984 data->SetId (item);
2985#endif
2986 }
2987 parent->Insert (item, previous);
2988
2989 return item;
2990 }
2991
2992 wxTreeItemId wxTreeListMainWindow::AddRoot (const wxString& text,
2993 int image, int selImage,
2994 wxTreeItemData* data)
2995 {
2996 wxCHECK_MSG(!m_rootItem, wxTreeItemId(), _T("tree can have only one root"));
2997 wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), _T("Add column(s) before adding the root item"));
2998 m_dirty = true; // do this first so stuff below doesn't cause flicker
2999
3000 wxArrayString arr;
3001 arr.Alloc (GetColumnCount());
3002 for (int i = 0; i < (int)GetColumnCount(); ++i) arr.Add (wxEmptyString);
3003 arr[m_main_column] = text;
3004 m_rootItem = new wxTreeListItem (this, (wxTreeListItem*)NULL, arr, image, selImage, data);
3005 if (data != NULL)
3006 {
3007#if !wxCHECK_VERSION(2, 5, 0)
3008 data->SetId((long)m_rootItem);
3009#else
3010 data->SetId(m_rootItem);
3011#endif
3012 }
3013 if (HasFlag(wxTR_HIDE_ROOT))
3014 {
3015 // if we will hide the root, make sure children are visible
3017 m_rootItem->Expand();
3018#if !wxCHECK_VERSION(2, 5, 0)
3019 long cookie = 0;
3020#else
3021 wxTreeItemIdValue cookie = 0;
3022#endif
3024 }
3025 return m_rootItem;
3026 }
3027
3028 wxTreeItemId wxTreeListMainWindow::PrependItem (const wxTreeItemId& parent,
3029 const wxString& text,
3030 int image, int selImage,
3031 wxTreeItemData* data)
3032 {
3033 return DoInsertItem (parent, 0u, text, image, selImage, data);
3034 }
3035
3036 wxTreeItemId wxTreeListMainWindow::InsertItem (const wxTreeItemId& parentId,
3037 const wxTreeItemId& idPrevious,
3038 const wxString& text,
3039 int image, int selImage,
3040 wxTreeItemData* data)
3041 {
3042 wxTreeListItem* parent = (wxTreeListItem*)parentId.m_pItem;
3043 wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
3044
3045 int index = parent->GetChildren().Index((wxTreeListItem*) idPrevious.m_pItem);
3046 wxASSERT_MSG( index != wxNOT_FOUND,
3047 _T("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") );
3048
3049 return DoInsertItem (parentId, ++index, text, image, selImage, data);
3050 }
3051
3052 wxTreeItemId wxTreeListMainWindow::InsertItem (const wxTreeItemId& parentId,
3053 size_t before,
3054 const wxString& text,
3055 int image, int selImage,
3056 wxTreeItemData* data)
3057 {
3058 wxTreeListItem* parent = (wxTreeListItem*)parentId.m_pItem;
3059 wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
3060
3061 return DoInsertItem (parentId, before, text, image, selImage, data);
3062 }
3063
3064 wxTreeItemId wxTreeListMainWindow::AppendItem (const wxTreeItemId& parentId,
3065 const wxString& text,
3066 int image, int selImage,
3067 wxTreeItemData* data)
3068 {
3069 wxTreeListItem* parent = (wxTreeListItem*) parentId.m_pItem;
3070 wxCHECK_MSG (parent, wxTreeItemId(), _T("item must have a parent, at least root!") );
3071
3072 return DoInsertItem (parent, parent->GetChildren().Count(), text, image, selImage, data);
3073 }
3074
3075
3076// -------------------------- DELETE OPERATION ------------------------------
3077
3078 void wxTreeListMainWindow::Delete (const wxTreeItemId& itemId)
3079 {
3080 if (! itemId.IsOk()) return;
3081 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
3082 wxTreeListItem* parent = item->GetItemParent();
3083 wxCHECK_RET (item != m_rootItem, _T("invalid item, root may not be deleted this way!"));
3084
3085 // recursive delete
3086 DoDeleteItem(item);
3087
3088 // update parent --CAUTION: must come after delete itself, so that item's
3089 // siblings may be found
3090 if (parent)
3091 {
3092 parent->GetChildren().Remove (item); // remove by value
3093 }
3094 }
3095
3096
3098 {
3099 if (! m_rootItem) return;
3100
3103 m_shiftItem = (wxTreeListItem*)NULL;
3104
3106 SendEvent(wxEVT_COMMAND_TREE_DELETE_ITEM, m_rootItem);
3107 delete m_rootItem;
3108 m_rootItem = NULL;
3109 }
3110
3111
3112 void wxTreeListMainWindow::DeleteChildren (const wxTreeItemId& itemId)
3113 {
3114 if (! itemId.IsOk()) return;
3115 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
3116
3117 // recursive delete on all children, starting from the right to prevent
3118 // multiple selection changes (see m_curItem handling in DoDeleteItem() )
3119 wxArrayTreeListItems& children = item->GetChildren();
3120 for (size_t n = children.GetCount(); n > 0; n--)
3121 {
3122 DoDeleteItem(children[n - 1]);
3123 // immediately remove child from array, otherwise it might get selected
3124 // as current item (see m_curItem handling in DoDeleteItem() )
3125 children.RemoveAt(n - 1);
3126 }
3127 }
3128
3129
3131 {
3132 wxCHECK_RET (item, _T("invalid item for delete!"));
3133
3134 m_dirty = true; // do this first so stuff below doesn't cause flicker
3135
3136 // cancel any editing
3137
3138 if (m_editControl)
3139 {
3140 m_editControl->EndEdit(true); // cancelled
3141 }
3142
3143 // cancel any dragging
3144 if (item == m_dragItem)
3145 {
3146 // stop dragging
3147 m_isDragStarted = m_isDragging = false;
3148 if (HasCapture()) ReleaseMouse();
3149 }
3150
3151 // don't stay with invalid m_curItem: take next sibling or reset to NULL
3152 // NOTE: this might be slighty inefficient when deleting a whole tree
3153 // but has the advantage that all deletion side-effects are handled here
3154 if (item == m_curItem)
3155 {
3157 if (m_curItem)
3158 {
3159 wxArrayTreeListItems& siblings = m_curItem->GetChildren();
3160 size_t index = siblings.Index (item);
3161 wxASSERT (index != (size_t)wxNOT_FOUND); // I'm not a child of my parent?
3162 SetCurrentItem(index < siblings.Count() - 1 ? siblings[index + 1] : (wxTreeListItem*)NULL);
3163 }
3164 }
3165 // don't stay with invalid m_shiftItem: reset it to NULL
3166 if (item == m_shiftItem) m_shiftItem = (wxTreeListItem*)NULL;
3167 // don't stay with invalid m_selectItem: default to current item
3168 if (item == m_selectItem)
3169 {
3171 SelectItem(m_selectItem, (wxTreeItemId*)NULL, true); // unselect others
3172 }
3173
3174 // recurse children, starting from the right to prevent multiple selection
3175 // changes (see m_curItem handling above)
3176 wxArrayTreeListItems& children = item->GetChildren();
3177 for (size_t n = children.GetCount(); n > 0; n--)
3178 {
3179 DoDeleteItem(children[n - 1]);
3180 // immediately remove child from array, otherwise it might get selected
3181 // as current item (see m_curItem handling above)
3182 children.RemoveAt(n - 1);
3183 }
3184
3185 // delete item itself
3186 SendEvent(wxEVT_COMMAND_TREE_DELETE_ITEM, item);
3187 delete item;
3188 }
3189
3190
3191// ----------------------------------------------------------------------------
3192
3193 void wxTreeListMainWindow::SetItemParent(const wxTreeItemId& parentId, const wxTreeItemId& itemId)
3194 {
3195 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
3196 wxTreeListItem* parent_new = (wxTreeListItem*) parentId.m_pItem;
3197 wxCHECK_RET (item, _T("invalid item in wxTreeListMainWindow::SetItemParent") );
3198 wxCHECK_RET (parent_new, _T("invalid parent in wxTreeListMainWindow::SetItemParent") );
3199 wxCHECK_RET (item != m_rootItem, _T("invalid root as item in wxTreeListMainWindow::SetItemParent!") );
3200 wxTreeListItem* parent_old = item->GetItemParent();
3201
3202 m_dirty = true; // do this first so stuff below doesn't cause flicker
3203
3204 parent_old->GetChildren().Remove (item);
3205 parent_new->Insert(item, parent_new->GetChildren().Count());
3206 item->SetItemParent(parent_new);
3207 // new parent was a leaf, show its new child
3208 if (parent_new->GetChildren().Count() == 1) parent_new->Expand();
3209 }
3210
3211
3212// ----------------------------------------------------------------------------
3213
3214 void wxTreeListMainWindow::SetCurrentItem(const wxTreeItemId& itemId)
3215 {
3216 SetCurrentItem((wxTreeListItem*)(itemId ? itemId.m_pItem : NULL));
3217 }
3219 {
3220 wxTreeListItem* old_item;
3221
3222 old_item = m_curItem;
3223 m_curItem = item;
3224
3225 // change of item, redraw previous
3226 if (old_item != NULL && old_item != item)
3227 {
3228 RefreshLine(old_item);
3229 }
3230
3231 }
3232
3233// ----------------------------------------------------------------------------
3234
3235 void wxTreeListMainWindow::Expand (const wxTreeItemId& itemId)
3236 {
3237 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
3238 wxCHECK_RET (item, _T("invalid item in wxTreeListMainWindow::Expand") );
3239
3240 if (!item->HasPlus() || item->IsExpanded()) return;
3241
3242 // send event to user code
3243 wxTreeEvent event(wxEVT_COMMAND_TREE_ITEM_EXPANDING, 0);
3244 event.SetInt(m_curColumn);
3245 if (SendEvent(0, item, &event) && !event.IsAllowed()) return; // expand canceled
3246
3247 item->Expand();
3248 m_dirty = true;
3249
3250 // send event to user code
3251 event.SetEventType (wxEVT_COMMAND_TREE_ITEM_EXPANDED);
3252 SendEvent(0, NULL, &event);
3253 }
3254
3255 void wxTreeListMainWindow::ExpandAll (const wxTreeItemId& itemId)
3256 {
3257 wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
3258
3259 Expand (itemId);
3260 if (!IsExpanded (itemId)) return;
3261#if !wxCHECK_VERSION(2, 5, 0)
3262 long cookie;
3263#else
3264 wxTreeItemIdValue cookie;
3265#endif
3266 wxTreeItemId child = GetFirstChild (itemId, cookie);
3267 while (child.IsOk())
3268 {
3269 ExpandAll (child);
3270 child = GetNextChild (itemId, cookie);
3271 }
3272 }
3273
3274 void wxTreeListMainWindow::Collapse (const wxTreeItemId& itemId)
3275 {
3276 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
3277 wxCHECK_RET (item, _T("invalid item in wxTreeListMainWindow::Collapse") );
3278
3279 if (!item->HasPlus() || !item->IsExpanded()) return;
3280
3281 // send event to user code
3282 wxTreeEvent event (wxEVT_COMMAND_TREE_ITEM_COLLAPSING, 0 );
3283 event.SetInt(m_curColumn);
3284 if (SendEvent(0, item, &event) && !event.IsAllowed()) return; // collapse canceled
3285
3286 item->Collapse();
3287 m_dirty = true;
3288
3289 // send event to user code
3290 event.SetEventType (wxEVT_COMMAND_TREE_ITEM_COLLAPSED);
3291 SendEvent(0, NULL, &event);
3292 }
3293
3294 void wxTreeListMainWindow::CollapseAndReset (const wxTreeItemId& item)
3295 {
3296 wxCHECK_RET (item.IsOk(), _T("invalid tree item"));
3297
3298 Collapse (item);
3299 DeleteChildren (item);
3300 }
3301
3302 void wxTreeListMainWindow::Toggle (const wxTreeItemId& itemId)
3303 {
3304 wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
3305
3306 if (IsExpanded (itemId))
3307 {
3308 Collapse (itemId);
3309 }
3310 else
3311 {
3312 Expand (itemId);
3313 }
3314 }
3315
3317 {
3318 if (m_selectItem)
3319 {
3320 m_selectItem->SetHilight (false);
3323 }
3324 }
3325
3327 {
3328 wxCHECK_RET (item, _T("invalid tree item"));
3329
3330 if (item->IsSelected())
3331 {
3332 item->SetHilight (false);
3333 RefreshLine (item);
3334 if (item == m_selectItem) m_selectItem = (wxTreeListItem*)NULL;
3335 if (item != m_curItem) m_lastOnSame = false; // selection change, so reset edit marker
3336 }
3337 if (item->HasChildren())
3338 {
3339 wxArrayTreeListItems& children = item->GetChildren();
3340 size_t count = children.Count();
3341 for (size_t n = 0; n < count; ++n)
3342 {
3343 UnselectAllChildren (children[n]);
3344 }
3345 }
3346 }
3347
3349 {
3351 }
3352
3353// Recursive function !
3354// To stop we must have crt_item<last_item
3355// Algorithm :
3356// Tag all next children, when no more children,
3357// Move to parent (not to tag)
3358// Keep going... if we found last_item, we stop.
3360 wxTreeListItem* last_item)
3361 {
3362 wxTreeListItem* parent = crt_item->GetItemParent();
3363
3364 if (!parent) // This is root item
3365 {
3366 return TagAllChildrenUntilLast (crt_item, last_item);
3367 }
3368
3369 wxArrayTreeListItems& children = parent->GetChildren();
3370 int index = children.Index(crt_item);
3371 wxASSERT (index != wxNOT_FOUND); // I'm not a child of my parent?
3372
3373 if ((parent->HasChildren() && parent->IsExpanded()) ||
3374 ((parent == (wxTreeListItem*)GetRootItem().m_pItem) && HasFlag(wxTR_HIDE_ROOT)))
3375 {
3376 size_t count = children.Count();
3377 for (size_t n = (index + 1); n < count; ++n)
3378 {
3379 if (TagAllChildrenUntilLast (children[n], last_item)) return true;
3380 }
3381 }
3382
3383 return TagNextChildren (parent, last_item);
3384 }
3385
3387 wxTreeListItem* last_item)
3388 {
3389 crt_item->SetHilight (true);
3390 RefreshLine(crt_item);
3391
3392 if (crt_item == last_item) return true;
3393
3394 if (crt_item->HasChildren() && crt_item->IsExpanded())
3395 {
3396 wxArrayTreeListItems& children = crt_item->GetChildren();
3397 size_t count = children.Count();
3398 for (size_t n = 0; n < count; ++n)
3399 {
3400 if (TagAllChildrenUntilLast (children[n], last_item)) return true;
3401 }
3402 }
3403
3404 return false;
3405 }
3406
3407 bool wxTreeListMainWindow::SelectItem (const wxTreeItemId& itemId,
3408 const wxTreeItemId& lastId,
3409 bool unselect_others)
3410 {
3411
3412 wxTreeListItem* item = itemId.IsOk() ? (wxTreeListItem*) itemId.m_pItem : NULL;
3413
3414 // send selecting event to the user code
3415 wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, 0);
3416 event.SetInt(m_curColumn);
3417#if !wxCHECK_VERSION(2, 5, 0)
3418 event.SetOldItem ((long)m_curItem);
3419#else
3420 event.SetOldItem (m_curItem);
3421#endif
3422 if (SendEvent(0, item, &event) && !event.IsAllowed()) return false; // veto on selection change
3423
3424 // unselect all if unselect other items
3425 bool bUnselectedAll = false; // see that UnselectAll is done only once
3426 if (unselect_others)
3427 {
3428 if (HasFlag(wxTR_MULTIPLE))
3429 {
3430 UnselectAll();
3431 bUnselectedAll = true;
3432 }
3433 else
3434 {
3435 Unselect(); // to speed up thing
3436 }
3437 }
3438
3439 // select item range
3440 if (lastId.IsOk() && itemId.IsOk() && (itemId != lastId))
3441 {
3442
3443 if (! bUnselectedAll) UnselectAll();
3444 wxTreeListItem* last = (wxTreeListItem*) lastId.m_pItem;
3445
3446 // ensure that the position of the item it calculated in any case
3448
3449 // select item range according Y-position
3450 if (last->GetY() < item->GetY())
3451 {
3452 if (!TagAllChildrenUntilLast (last, item))
3453 {
3454 TagNextChildren (last, item);
3455 }
3456 }
3457 else
3458 {
3459 if (!TagAllChildrenUntilLast (item, last))
3460 {
3461 TagNextChildren (item, last);
3462 }
3463 }
3464
3465 // or select single item
3466 }
3467 else if (itemId.IsOk())
3468 {
3469
3470 // select item according its old selection
3471 item->SetHilight (!item->IsSelected());
3472 RefreshLine (item);
3473 if (unselect_others)
3474 {
3475 m_selectItem = (item->IsSelected()) ? item : (wxTreeListItem*)NULL;
3476 }
3477
3478 // or select nothing
3479 }
3480 else
3481 {
3482 if (! bUnselectedAll) UnselectAll();
3483 }
3484
3485 // send event to user code
3486 event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
3487 SendEvent(0, NULL, &event);
3488
3489 return true;
3490 }
3491
3493 {
3494 wxTreeItemId root = GetRootItem();
3495 wxCHECK_RET (HasFlag(wxTR_MULTIPLE), _T("invalid tree style"));
3496 wxCHECK_RET (root.IsOk(), _T("no tree"));
3497
3498 // send event to user code
3499 wxTreeEvent event (wxEVT_COMMAND_TREE_SEL_CHANGING, 0);
3500#if !wxCHECK_VERSION(2, 5, 0)
3501 event.SetOldItem ((long)m_curItem);
3502#else
3503 event.SetOldItem (m_curItem);
3504#endif
3505 event.SetInt (-1); // no colum clicked
3506 if (SendEvent(0, m_rootItem, &event) && !event.IsAllowed()) return; // selection change vetoed
3507
3508#if !wxCHECK_VERSION(2, 5, 0)
3509 long cookie = 0;
3510#else
3511 wxTreeItemIdValue cookie = 0;
3512#endif
3513 wxTreeListItem* first = (wxTreeListItem*)GetFirstChild (root, cookie).m_pItem;
3514 wxTreeListItem* last = (wxTreeListItem*)GetLastChild (root, cookie).m_pItem;
3515 if (!TagAllChildrenUntilLast (first, last))
3516 {
3517 TagNextChildren (first, last);
3518 }
3519
3520 // send event to user code
3521 event.SetEventType (wxEVT_COMMAND_TREE_SEL_CHANGED);
3522 SendEvent(0, NULL, &event);
3523 }
3524
3526 wxArrayTreeItemIds& array) const
3527 {
3528 if (item->IsSelected()) array.Add (wxTreeItemId(item));
3529
3530 if (item->HasChildren())
3531 {
3532 wxArrayTreeListItems& children = item->GetChildren();
3533 size_t count = children.GetCount();
3534 for (size_t n = 0; n < count; ++n) FillArray (children[n], array);
3535 }
3536 }
3537
3538 size_t wxTreeListMainWindow::GetSelections (wxArrayTreeItemIds& array) const
3539 {
3540 array.Empty();
3541 wxTreeItemId idRoot = GetRootItem();
3542 if (idRoot.IsOk()) FillArray ((wxTreeListItem*) idRoot.m_pItem, array);
3543 return array.Count();
3544 }
3545
3546 void wxTreeListMainWindow::EnsureVisible (const wxTreeItemId& item)
3547 {
3548 if (!item.IsOk()) return; // do nothing if no item
3549
3550 // first expand all parent branches
3551 wxTreeListItem* gitem = (wxTreeListItem*) item.m_pItem;
3552 wxTreeListItem* parent = gitem->GetItemParent();
3553 while (parent)
3554 {
3555 Expand (parent);
3556 parent = parent->GetItemParent();
3557 }
3558
3559 ScrollTo (item);
3560 RefreshLine (gitem);
3561 }
3562
3563 void wxTreeListMainWindow::ScrollTo (const wxTreeItemId& item)
3564 {
3565 if (!item.IsOk()) return; // do nothing if no item
3566
3567 // ensure that the position of the item it calculated in any case
3569
3570 wxTreeListItem* gitem = (wxTreeListItem*) item.m_pItem;
3571
3572 // now scroll to the item
3573 int item_y = gitem->GetY();
3574
3575 int xUnit, yUnit;
3576 GetScrollPixelsPerUnit (&xUnit, &yUnit);
3577 int start_x = 0;
3578 int start_y = 0;
3579 GetViewStart (&start_x, &start_y);
3580 start_y *= yUnit;
3581
3582 int client_h = 0;
3583 int client_w = 0;
3584 GetClientSize (&client_w, &client_h);
3585
3586 int x = 0;
3587 int y = 0;
3588 m_rootItem->GetSize (x, y, this);
3590 y += yUnit + 2; // one more scrollbar unit + 2 pixels
3591 int x_pos = GetScrollPos( wxHORIZONTAL );
3592
3593 if (item_y < start_y + 3)
3594 {
3595 // going down, item should appear at top
3596 SetScrollbars (xUnit, yUnit, xUnit ? x / xUnit : 0, yUnit ? y / yUnit : 0, x_pos, yUnit ? item_y / yUnit : 0);
3597 }
3598 else if (item_y + GetLineHeight(gitem) > start_y + client_h)
3599 {
3600 // going up, item should appear at bottom
3601 item_y += yUnit + 2;
3602 SetScrollbars (xUnit, yUnit, xUnit ? x / xUnit : 0, yUnit ? y / yUnit : 0, x_pos, yUnit ? (item_y + GetLineHeight(gitem) - client_h) / yUnit : 0 );
3603 }
3604 }
3605
3607
3608 static int LINKAGEMODE tree_ctrl_compare_func(wxTreeListItem** item1, wxTreeListItem** item2)
3609 {
3610 wxCHECK_MSG (s_treeBeingSorted, 0, _T("bug in wxTreeListMainWindow::SortChildren()") );
3611 return s_treeBeingSorted->OnCompareItems(*item1, *item2);
3612 }
3613
3614 int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2)
3615 {
3616 return (m_sortColumn == -1
3617 ? m_owner->OnCompareItems (item1, item2)
3619 ? m_owner->OnCompareItems (item2, item1, m_sortColumn)
3620 : m_owner->OnCompareItems (item1, item2, m_sortColumn)
3621 )
3622 );
3623 }
3624
3625 void wxTreeListMainWindow::SortChildren (const wxTreeItemId& itemId, int column, bool reverseOrder)
3626 {
3627 wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
3628
3629 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
3630
3631 wxCHECK_RET (!s_treeBeingSorted,
3632 _T("wxTreeListMainWindow::SortChildren is not reentrant") );
3633
3634 wxArrayTreeListItems& children = item->GetChildren();
3635 if ( children.Count() > 1 )
3636 {
3637 m_dirty = true;
3638 s_treeBeingSorted = this;
3639 m_sortColumn = column; // -1 indicates legacy mode
3640 m_ReverseSortOrder = reverseOrder;
3641 children.Sort(tree_ctrl_compare_func);
3642 s_treeBeingSorted = NULL;
3643 }
3644 }
3645
3646 wxTreeItemId wxTreeListMainWindow::FindItem (const wxTreeItemId& item, int column, const wxString& str, int mode)
3647 {
3648
3649 // determine start item
3650 wxTreeItemId next = item;
3651 if (next.IsOk())
3652 {
3653 if (mode & wxTL_MODE_NAV_LEVEL)
3654 {
3655 next = GetNextSibling (next);
3656 }
3657 else if (mode & wxTL_MODE_NAV_VISIBLE) //
3658 {
3659 next = GetNextVisible (next, false, true);
3660 }
3661 else if (mode & wxTL_MODE_NAV_EXPANDED)
3662 {
3663 next = GetNextExpanded (next);
3664 }
3665 else // (mode & wxTL_MODE_NAV_FULLTREE) default
3666 {
3667 next = GetNext (next, true);
3668 }
3669 }
3670
3671#if !wxCHECK_VERSION(2, 5, 0)
3672 long cookie = 0;
3673#else
3674 wxTreeItemIdValue cookie = 0;
3675#endif
3676 if (!next.IsOk())
3677 {
3678 next = GetRootItem();
3679 if (next.IsOk() && HasFlag(wxTR_HIDE_ROOT))
3680 {
3681 next = GetFirstChild (GetRootItem(), cookie);
3682 }
3683 }
3684 if (!next.IsOk()) return (wxTreeItemId*)NULL;
3685
3686 // start checking the next items
3687 wxString itemText;
3688 int col = 0, col_start, col_end;
3689 if (column >= 0)
3690 {
3691 col_start = col_end = col;
3692 }
3693 else
3694 {
3695 col_start = 0;
3696 col_end = GetColumnCount() - 1;
3697 }
3698 while (next.IsOk() && (next != item))
3699 {
3700 // check for a match
3701 for (col = col_start; col <= col_end; col++)
3702 {
3703 if (mode & wxTL_MODE_FIND_PARTIAL)
3704 {
3705 itemText = GetItemText (next, col).Mid (0, str.Length());
3706 }
3707 else
3708 {
3709 itemText = GetItemText (next, col);
3710 }
3711 if (mode & wxTL_MODE_FIND_NOCASE)
3712 {
3713 if (itemText.CmpNoCase (str) == 0) return next;
3714 }
3715 else
3716 {
3717 if (itemText.Cmp (str) == 0) return next;
3718 }
3719 }
3720 // no match, go to next item
3721 if (mode & wxTL_MODE_NAV_LEVEL)
3722 {
3723 next = GetNextSibling (next);
3724 }
3725 else if (mode & wxTL_MODE_NAV_VISIBLE) //
3726 {
3727 next = GetNextVisible (next, false, true);
3728 }
3729 else if (mode & wxTL_MODE_NAV_EXPANDED)
3730 {
3731 next = GetNextExpanded (next);
3732 }
3733 else // (mode & wxTL_MODE_NAV_FULLTREE) default
3734 {
3735 next = GetNext (next, true);
3736 }
3737 if (!next.IsOk() && item.IsOk())
3738 {
3739 next = (wxTreeListItem*)GetRootItem().m_pItem;
3740 if (HasFlag(wxTR_HIDE_ROOT))
3741 {
3742 next = (wxTreeListItem*)GetNextChild (GetRootItem().m_pItem, cookie).m_pItem;
3743 }
3744 }
3745 }
3746 return (wxTreeItemId*)NULL;
3747 }
3748
3749 void wxTreeListMainWindow::SetDragItem (const wxTreeItemId& item)
3750 {
3751 wxTreeListItem* prevItem = m_dragItem;
3752 m_dragItem = (wxTreeListItem*) item.m_pItem;
3753 if (prevItem) RefreshLine (prevItem);
3755 }
3756
3758 {
3759 wxClientDC dc (this);
3760 dc.SetFont (m_normalFont);
3761 m_lineHeight = (int)(dc.GetCharHeight() + m_linespacing);
3762
3764 {
3765 // Calculate a m_lineHeight value from the normal Image sizes.
3766 // May be toggle off. Then wxTreeListMainWindow will spread when
3767 // necessary (which might look ugly).
3768 int n = m_imageListNormal->GetImageCount();
3769 for (int i = 0; i < n ; i++)
3770 {
3771 int width = 0, height = 0;
3772 m_imageListNormal->GetSize(i, width, height);
3773 if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
3774 }
3775 }
3776
3778 {
3779 // Calculate a m_lineHeight value from the Button image sizes.
3780 // May be toggle off. Then wxTreeListMainWindow will spread when
3781 // necessary (which might look ugly).
3782 int n = m_imageListButtons->GetImageCount();
3783 for (int i = 0; i < n ; i++)
3784 {
3785 int width = 0, height = 0;
3786 m_imageListButtons->GetSize(i, width, height);
3787 if (height > m_lineHeight) m_lineHeight = height + m_linespacing;
3788 }
3789 }
3790
3791 if (m_lineHeight < 30) // add 10% space if greater than 30 pixels
3792 {
3793 m_lineHeight += 2; // minimal 2 pixel space
3794 }
3795 else
3796 {
3797 m_lineHeight += m_lineHeight / 10; // otherwise 10% space
3798 }
3799 }
3800
3801 void wxTreeListMainWindow::SetImageList (wxImageList* imageList)
3802 {
3804 m_imageListNormal = imageList;
3805 m_ownsImageListNormal = false;
3806 m_dirty = true;
3808 }
3809
3810 void wxTreeListMainWindow::SetStateImageList (wxImageList* imageList)
3811 {
3813 m_imageListState = imageList;
3814 m_ownsImageListState = false;
3815 }
3816
3817 void wxTreeListMainWindow::SetButtonsImageList (wxImageList* imageList)
3818 {
3820 m_imageListButtons = imageList;
3821 m_ownsImageListButtons = false;
3822 m_dirty = true;
3824 }
3825
3826 void wxTreeListMainWindow::AssignImageList (wxImageList* imageList)
3827 {
3828 SetImageList(imageList);
3829 m_ownsImageListNormal = true;
3830 }
3831
3833 {
3834 SetStateImageList(imageList);
3835 m_ownsImageListState = true;
3836 }
3837
3839 {
3840 SetButtonsImageList(imageList);
3842 }
3843
3844// ----------------------------------------------------------------------------
3845// helpers
3846// ----------------------------------------------------------------------------
3847
3849 {
3850 if (m_rootItem)
3851 {
3852 int xUnit, yUnit;
3853 GetScrollPixelsPerUnit (&xUnit, &yUnit);
3854 if (xUnit == 0) xUnit = GetCharWidth();
3855 if (yUnit == 0) yUnit = m_lineHeight;
3856 int x = 0, y = 0;
3857 m_rootItem->GetSize (x, y, this);
3858 y += yUnit + 2; // one more scrollbar unit + 2 pixels
3859 int x_pos = GetScrollPos (wxHORIZONTAL);
3860 int y_pos = GetScrollPos (wxVERTICAL);
3861 x = m_owner->GetHeaderWindow()->GetWidth() + 2;
3862 if (x < GetClientSize().GetWidth()) x_pos = 0;
3863 SetScrollbars (xUnit, yUnit, x / xUnit, y / yUnit, x_pos, y_pos);
3864 }
3865 else
3866 {
3867 SetScrollbars (0, 0, 0, 0);
3868 }
3869 }
3870
3872 {
3873 if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT)
3874 {
3875 return item->GetHeight();
3876 }
3877 else
3878 {
3879 return m_lineHeight;
3880 }
3881 }
3882
3884 {
3885
3886// read attributes constant for all item cells
3887 wxColour colText = GetItemTextColour(item);
3888 wxColour colBg = GetItemBackgroundColour(item);
3889#if !wxCHECK_VERSION(2, 5, 0)
3890 wxColour colTextHilight = wxSystemSettings::GetSystemColour (wxSYS_COLOUR_HIGHLIGHTTEXT);
3891#else
3892 wxColour colTextHilight = wxSystemSettings::GetColour (wxSYS_COLOUR_HIGHLIGHTTEXT);
3893#endif
3894 int total_w = m_owner->GetHeaderWindow()->GetWidth();
3895 int total_h = GetLineHeight(item);
3896 int off_h = HasFlag(wxTR_ROW_LINES) ? 1 : 0;
3897 int off_w = HasFlag(wxTR_COLUMN_LINES) ? 1 : 0;
3898 wxDCClipper clipper (dc, 0, item->GetY(), total_w, total_h); // only within line
3899 // compute text height based on main col
3900 int text_h = 0;
3901 dc.GetTextExtent( item->GetText(GetMainColumn()).size() > 0
3902 ? item->GetText(GetMainColumn())
3903 : _T("M"), // dummy text to avoid zero height and no highlight width
3904 NULL, &text_h );
3905
3906// determine background and show it
3907// in wxTR_FULL_ROW_HIGHLIGHT mode, some drawing can be done already now
3908 dc.SetBrush (wxBrush ( colBg, wxSOLID));
3909 dc.SetPen (*wxTRANSPARENT_PEN);
3910 if (HasFlag (wxTR_FULL_ROW_HIGHLIGHT))
3911 {
3912 if (item->IsSelected())
3913 {
3914 if (! m_isDragging && m_hasFocus)
3915 {
3916 dc.SetBrush (*m_hilightBrush);
3917#ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3918 dc.SetPen (*wxBLACK_PEN);
3919#endif // !__WXMAC__
3920 }
3921 else
3922 {
3923 dc.SetBrush (*m_hilightUnfocusedBrush);
3924#ifndef __WXMAC__ // don't draw rect outline if we already have the background color
3925 dc.SetPen (*wxTRANSPARENT_PEN);
3926#endif // !__WXMAC__
3927 }
3928 dc.SetTextForeground (colTextHilight);
3929 }
3930 else
3931 {
3932 dc.SetTextForeground (GetItemTextColour(item));
3933 if (item == m_curItem)
3934 {
3935 dc.SetPen (m_hasFocus ? *wxBLACK_PEN : *wxTRANSPARENT_PEN);
3936 }
3937 }
3938 dc.DrawRectangle (0, item->GetY() + off_h, total_w, total_h - off_h);
3939 }
3940
3941// iterate through all cells
3942 int text_extraH = (total_h > text_h) ? (total_h - text_h) / 2 : 0;
3943 int img_extraH = (total_h > m_imgHeight) ? (total_h - m_imgHeight) / 2 : 0;
3944 int x_colstart = 0;
3945 for (int i = 0; i < GetColumnCount(); ++i )
3946 {
3947 if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
3948 int col_w = m_owner->GetHeaderWindow()->GetColumnWidth(i);
3949 if (col_w <= 0) continue; // workaround for probable GTK2 bug [wxCode-Bugs-#3061215]
3950 wxDCClipper clipper (dc, x_colstart, item->GetY(), col_w, total_h); // only within column
3951
3952 // read variable attributes
3953 dc.SetFont (GetItemFont (item, i));
3954 colText = GetItemTextColour(item, i);
3955 colBg = GetItemBackgroundColour(item, i);
3956
3957 //
3958 int x = 0;
3959 int image = NO_IMAGE;
3960 int image_w = 0;
3961 if (i == GetMainColumn())
3962 {
3963 x = item->GetX() + MARGIN;
3964 if (HasButtons())
3965 {
3967 }
3968 else
3969 {
3970 x -= m_indent / 2;
3971 }
3972 if (m_imageListNormal) image = item->GetCurrentImage();
3973 }
3974 else
3975 {
3976 x = x_colstart + MARGIN;
3977 image = item->GetImage(i);
3978 }
3979 if (image != NO_IMAGE) image_w = m_imgWidth + MARGIN;
3980
3981 // honor text alignment
3982 int w = 0, text_w = 0;
3983 wxString text = item->GetText(i);
3984 dc.GetTextExtent (text, &text_w, NULL);
3985 switch ( m_owner->GetHeaderWindow()->GetColumn(i).GetAlignment() )
3986 {
3987 case wxALIGN_LEFT:
3988 // nothing to do, already left aligned
3989 break;
3990 case wxALIGN_RIGHT:
3991 w = col_w - (image_w + text_w + off_w + MARGIN);
3992 x += (w > 0) ? w : 0;
3993 break;
3994 case wxALIGN_CENTER:
3995 w = (col_w - (image_w + text_w + off_w + MARGIN)) / 2;
3996 x += (w > 0) ? w : 0;
3997 break;
3998 }
3999 int text_x = x + image_w;
4000 if (i == GetMainColumn()) item->SetTextX (text_x);
4001
4002 // draw background (in non wxTR_FULL_ROW_HIGHLIGHT mode)
4003 // cell-specific settings are used --excepted for selection:
4004 if ( ! HasFlag (wxTR_FULL_ROW_HIGHLIGHT))
4005 {
4006 // cursor: indicate current cell
4007 bool drawCursor = false;
4008#ifndef __WXMAC__ // don't draw rect outline if we already have the background color
4009 drawCursor = (item == m_curItem && i == m_curColumn && !m_isDragging && m_hasFocus);
4010#endif // !__WXMAC__
4011 // selection: main col only, overrides colors + separate draw
4012 if (item->IsSelected() && i == GetMainColumn())
4013 {
4014 // draw normal background
4015 dc.SetPen (*wxTRANSPARENT_PEN);
4016 dc.SetBrush (wxBrush ( colBg, wxSOLID));
4017 dc.DrawRectangle (x_colstart, item->GetY() + off_h, col_w, total_h - off_h);
4018 // draw selection & optionally cursor
4019 dc.SetPen (drawCursor ? *wxBLACK_PEN : *wxTRANSPARENT_PEN);
4021 dc.SetTextForeground (colTextHilight);
4022 dc.DrawRectangle (text_x, item->GetY() + off_h, text_w, total_h - off_h);
4023 // normal FG / BG from attributes
4024 }
4025 else
4026 {
4027 // draw normal background & optionally cursor
4028 dc.SetPen (drawCursor && i != GetMainColumn() ? *wxBLACK_PEN : *wxTRANSPARENT_PEN);
4029 dc.SetBrush (wxBrush ( colBg, wxSOLID));
4030 dc.SetTextForeground (colText);
4031 dc.DrawRectangle (x_colstart, item->GetY() + off_h, col_w, total_h - off_h);
4032 // on main col draw a separate cursor
4033 if (drawCursor && i == GetMainColumn())
4034 {
4035 dc.SetPen (*wxBLACK_PEN);
4036 dc.SetBackgroundMode (wxTRANSPARENT);
4037 dc.DrawRectangle (text_x, item->GetY() + off_h, text_w, total_h - off_h);
4038 }
4039 }
4040 }
4041
4042 // draw vertical column lines
4043 if (HasFlag(wxTR_COLUMN_LINES)) // vertical lines between columns
4044 {
4045#if !wxCHECK_VERSION(2, 5, 0)
4046 wxPen pen (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_3DLIGHT ), 1, wxSOLID);
4047#else
4048 wxPen pen (wxSystemSettings::GetColour (wxSYS_COLOUR_3DLIGHT ), 1, wxSOLID);
4049#endif
4050 dc.SetPen ((GetBackgroundColour() == *wxWHITE) ? pen : *wxWHITE_PEN);
4051 dc.DrawLine (x_colstart + col_w - 1, item->GetY(), x_colstart + col_w - 1, item->GetY() + total_h);
4052 }
4053
4054 dc.SetBackgroundMode (wxTRANSPARENT);
4055
4056 // draw image
4057 if (image != NO_IMAGE && m_imageListNormal && image < m_imageListNormal->GetImageCount())
4058 {
4059 int y = item->GetY() + img_extraH;
4060 m_imageListNormal->Draw (image, dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
4061 }
4062
4063 // draw text
4064 int text_y = item->GetY() + text_extraH;
4065 dc.DrawText (text, (wxCoord)text_x, (wxCoord)text_y);
4066
4067 x_colstart += col_w;
4068 }
4069
4070 // restore normal font
4071 dc.SetFont( m_normalFont );
4072 }
4073
4074// Now y stands for the top of the item, whereas it used to stand for middle !
4076 int level, int& y, int x_maincol)
4077 {
4078
4079 // Handle hide root (only level 0)
4080 if (HasFlag(wxTR_HIDE_ROOT) && (level == 0))
4081 {
4082 wxArrayTreeListItems& children = item->GetChildren();
4083 for (size_t n = 0; n < children.Count(); n++)
4084 {
4085 PaintLevel (children[n], dc, 1, y, x_maincol);
4086 }
4087 // end after expanding root
4088 return;
4089 }
4090
4091 // calculate position of vertical lines
4092 int x = x_maincol + MARGIN; // start of column
4093 if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
4094 if (HasButtons())
4095 {
4096 x += (m_btnWidth - m_btnWidth2); // half button space
4097 }
4098 else
4099 {
4100 x += (m_indent - m_indent / 2);
4101 }
4102 if (HasFlag(wxTR_HIDE_ROOT))
4103 {
4104 x += m_indent * (level - 1); // indent but not level 1
4105 }
4106 else
4107 {
4108 x += m_indent * level; // indent according to level
4109 }
4110
4111 // set position of vertical line
4112 item->SetX (x);
4113 item->SetY (y);
4114
4115 int h = GetLineHeight (item);
4116 int y_top = y;
4117 int y_mid = y_top + (h / 2);
4118 y += h;
4119
4120 int exposed_x = dc.LogicalToDeviceX(0);
4121 int exposed_y = dc.LogicalToDeviceY(y_top);
4122
4123 if (IsExposed(exposed_x, exposed_y, 10000, h)) // 10000 = very much
4124 {
4125
4126 if (HasFlag(wxTR_ROW_LINES)) // horizontal lines between rows
4127 {
4128 //dc.DestroyClippingRegion();
4129 int total_width = m_owner->GetHeaderWindow()->GetWidth();
4130 // if the background colour is white, choose a
4131 // contrasting color for the lines
4132#if !wxCHECK_VERSION(2, 5, 0)
4133 wxPen pen (wxSystemSettings::GetSystemColour (wxSYS_COLOUR_3DLIGHT ), 1, wxSOLID);
4134#else
4135 wxPen pen (wxSystemSettings::GetColour (wxSYS_COLOUR_3DLIGHT ), 1, wxSOLID);
4136#endif
4137 dc.SetPen ((GetBackgroundColour() == *wxWHITE) ? pen : *wxWHITE_PEN);
4138 dc.DrawLine (0, y_top, total_width, y_top);
4139 dc.DrawLine (0, y_top + h, total_width, y_top + h);
4140 }
4141
4142 // draw item
4143 PaintItem (item, dc);
4144
4145 // restore DC objects
4146 dc.SetBrush(*wxWHITE_BRUSH);
4147 dc.SetPen(m_dottedPen);
4148
4149 // clip to the column width
4150 int clip_width = m_owner->GetHeaderWindow()->
4151 GetColumn(m_main_column).GetWidth();
4152 wxDCClipper clipper(dc, x_maincol, y_top, clip_width, 10000);
4153
4154 if (!HasFlag(wxTR_NO_LINES)) // connection lines
4155 {
4156
4157 // draw the horizontal line here
4158 dc.SetPen(m_dottedPen);
4159 int x2 = x - m_indent;
4160 if (x2 < (x_maincol + MARGIN)) x2 = x_maincol + MARGIN;
4161 int x3 = x + (m_btnWidth - m_btnWidth2);
4162 if (HasButtons())
4163 {
4164 if (item->HasPlus())
4165 {
4166 dc.DrawLine (x2, y_mid, x - m_btnWidth2, y_mid);
4167 dc.DrawLine (x3, y_mid, x3 + LINEATROOT, y_mid);
4168 }
4169 else
4170 {
4171 dc.DrawLine (x2, y_mid, x3 + LINEATROOT, y_mid);
4172 }
4173 }
4174 else
4175 {
4176 dc.DrawLine (x2, y_mid, x - m_indent / 2, y_mid);
4177 }
4178 }
4179
4180 if (item->HasPlus() && HasButtons()) // should the item show a button?
4181 {
4182
4184 {
4185
4186 // draw the image button here
4187 int image = wxTreeItemIcon_Normal;
4188 if (item->IsExpanded()) image = wxTreeItemIcon_Expanded;
4189 if (item->IsSelected()) image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal;
4190 int xx = x - m_btnWidth2 + MARGIN;
4191 int yy = y_mid - m_btnHeight2;
4192 dc.SetClippingRegion(xx, yy, m_btnWidth, m_btnHeight);
4193 m_imageListButtons->Draw (image, dc, xx, yy, wxIMAGELIST_DRAW_TRANSPARENT);
4194 dc.DestroyClippingRegion();
4195
4196 }
4197 else if (HasFlag (wxTR_TWIST_BUTTONS))
4198 {
4199
4200 // draw the twisty button here
4201 dc.SetPen(*wxBLACK_PEN);
4202 dc.SetBrush(*m_hilightBrush);
4203 wxPoint button[3];
4204 if (item->IsExpanded())
4205 {
4206 button[0].x = x - (m_btnWidth2 + 1);
4207 button[0].y = y_mid - (m_btnHeight / 3);
4208 button[1].x = x + (m_btnWidth2 + 1);
4209 button[1].y = button[0].y;
4210 button[2].x = x;
4211 button[2].y = button[0].y + (m_btnHeight2 + 1);
4212 }
4213 else
4214 {
4215 button[0].x = x - (m_btnWidth / 3);
4216 button[0].y = y_mid - (m_btnHeight2 + 1);
4217 button[1].x = button[0].x;
4218 button[1].y = y_mid + (m_btnHeight2 + 1);
4219 button[2].x = button[0].x + (m_btnWidth2 + 1);
4220 button[2].y = y_mid;
4221 }
4222 dc.DrawPolygon(3, button);
4223
4224 }
4225 else // if (HasFlag(wxTR_HAS_BUTTONS))
4226 {
4227
4228 // draw the plus sign here
4229#if !wxCHECK_VERSION(2, 7, 0)
4230 dc.SetPen(*wxGREY_PEN);
4231 dc.SetBrush(*wxWHITE_BRUSH);
4232 dc.DrawRectangle (x - m_btnWidth2, y_mid - m_btnHeight2, m_btnWidth, m_btnHeight);
4233 dc.SetPen(*wxBLACK_PEN);
4234 dc.DrawLine (x - (m_btnWidth2 - 2), y_mid, x + (m_btnWidth2 - 1), y_mid);
4235 if (!item->IsExpanded()) // change "-" to "+"
4236 {
4237 dc.DrawLine (x, y_mid - (m_btnHeight2 - 2), x, y_mid + (m_btnHeight2 - 1));
4238 }
4239#else
4240 wxRect rect (x - m_btnWidth2, y_mid - m_btnHeight2, m_btnWidth, m_btnHeight);
4241 int flag = item->IsExpanded() ? wxCONTROL_EXPANDED : 0;
4242 wxRendererNative::GetDefault().DrawTreeItemButton (this, dc, rect, flag);
4243#endif
4244
4245 }
4246
4247 }
4248
4249 }
4250
4251 // restore DC objects
4252 dc.SetBrush(*wxWHITE_BRUSH);
4253 dc.SetPen(m_dottedPen);
4254 dc.SetTextForeground(*wxBLACK);
4255
4256 if (item->IsExpanded())
4257 {
4258 wxArrayTreeListItems& children = item->GetChildren();
4259
4260 // clip to the column width
4261 int clip_width = m_owner->GetHeaderWindow()->
4262 GetColumn(m_main_column).GetWidth();
4263
4264 // process lower levels
4265 int oldY;
4266 if (m_imgWidth > 0)
4267 {
4268 oldY = y_mid + m_imgHeight2;
4269 }
4270 else
4271 {
4272 oldY = y_mid + h / 2;
4273 }
4274 int y2;
4275 for (size_t n = 0; n < children.Count(); ++n)
4276 {
4277
4278 y2 = y + h / 2;
4279 PaintLevel (children[n], dc, level + 1, y, x_maincol);
4280
4281 // draw vertical line
4282 wxDCClipper clipper(dc, x_maincol, y_top, clip_width, 10000);
4283 if (!HasFlag (wxTR_NO_LINES))
4284 {
4285 x = item->GetX();
4286 dc.DrawLine (x, oldY, x, y2);
4287 oldY = y2;
4288 }
4289 }
4290 }
4291 }
4292
4293
4294// ----------------------------------------------------------------------------
4295// wxWindows callbacks
4296// ----------------------------------------------------------------------------
4297
4298 void wxTreeListMainWindow::OnPaint (wxPaintEvent& WXUNUSED(event))
4299 {
4300
4301 // init device context, clear background (BEFORE changing DC origin...)
4302 wxAutoBufferedPaintDC dc (this);
4303 wxBrush brush(GetBackgroundColour(), wxSOLID);
4304 dc.SetBackground(brush);
4305 dc.Clear();
4306 DoPrepareDC (dc);
4307
4308 if (!m_rootItem || (GetColumnCount() <= 0)) return;
4309
4310 // calculate button size
4312 {
4314 }
4315 else if (HasButtons())
4316 {
4319 }
4320 m_btnWidth2 = m_btnWidth / 2;
4322
4323 // calculate image size
4325 {
4327 }
4328 m_imgWidth2 = m_imgWidth / 2;
4330
4331 // calculate indent size
4333 {
4334 m_indent = wxMax (MININDENT, m_btnWidth + MARGIN);
4335 }
4336 else if (HasButtons())
4337 {
4339 }
4340
4341 // set default values
4342 dc.SetFont( m_normalFont );
4343 dc.SetPen( m_dottedPen );
4344
4345 // calculate column start and paint
4346 int x_maincol = 0;
4347 int i = 0;
4348 for (i = 0; i < (int)GetMainColumn(); ++i)
4349 {
4350 if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
4351 x_maincol += m_owner->GetHeaderWindow()->GetColumnWidth (i);
4352 }
4353 int y = 0;
4354 PaintLevel (m_rootItem, dc, 0, y, x_maincol);
4355 }
4356
4357 void wxTreeListMainWindow::OnSetFocus (wxFocusEvent& event)
4358 {
4359 m_hasFocus = true;
4362 event.Skip();
4363 }
4364
4365 void wxTreeListMainWindow::OnKillFocus( wxFocusEvent& event )
4366 {
4367 m_hasFocus = false;
4370 event.Skip();
4371 }
4372
4373 void wxTreeListMainWindow::OnChar (wxKeyEvent& event)
4374 {
4375 // send event to user code
4376 wxTreeEvent nevent (wxEVT_COMMAND_TREE_KEY_DOWN, 0 );
4377 nevent.SetInt(m_curColumn);
4378 nevent.SetKeyEvent (event);
4379 if (SendEvent(0, NULL, &nevent)) return; // char event handled in user code
4380
4381 // if no item current, select root
4382 bool curItemSet = false;
4383 if (!m_curItem)
4384 {
4385 if (! GetRootItem().IsOk()) return;
4387 if (HasFlag(wxTR_HIDE_ROOT))
4388 {
4389#if !wxCHECK_VERSION(2, 5, 0)
4390 long cookie = 0;
4391#else
4392 wxTreeItemIdValue cookie = 0;
4393#endif
4395 }
4396 SelectItem(m_curItem, (wxTreeItemId*)NULL, true); // unselect others
4397 curItemSet = true;
4398 }
4399
4400 // remember item at shift down
4401 if (HasFlag(wxTR_MULTIPLE) && event.ShiftDown())
4402 {
4404 }
4405 else
4406 {
4407 m_shiftItem = (wxTreeListItem*)NULL;
4408 }
4409
4410 if (curItemSet) return; // if no item was current until now, do nothing more
4411
4412 // process all cases
4413 wxTreeItemId newItem = (wxTreeItemId*)NULL;
4414 switch (event.GetKeyCode())
4415 {
4416
4417 // '+': Expand subtree
4418 case '+':
4419 case WXK_ADD:
4420 {
4422 }
4423 break;
4424
4425 // '-': collapse subtree
4426 case '-':
4427 case WXK_SUBTRACT:
4428 {
4430 }
4431 break;
4432
4433 // '*': expand/collapse all subtrees
4434 case '*':
4435 case WXK_MULTIPLY:
4436 {
4438 {
4440 }
4441 else if (m_curItem->HasPlus())
4442 {
4444 }
4445 }
4446 break;
4447
4448 // ' ': toggle current item
4449 case ' ':
4450 {
4451 SelectItem (m_curItem, (wxTreeListItem*)NULL, false);
4452 }
4453 break;
4454
4455 // <RETURN>: activate current item
4456 case WXK_RETURN:
4457 {
4458 if (! SendEvent(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, m_curItem))
4459 {
4460
4461 // if the user code didn't process the activate event,
4462 // handle it ourselves by toggling the item when it is
4463 // double clicked
4465 }
4466 }
4467 break;
4468
4469 // <BKSP>: go to the parent without collapsing
4470 case WXK_BACK:
4471 {
4472 newItem = GetItemParent (m_curItem);
4473 if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT))
4474 {
4475 newItem = GetPrevSibling (m_curItem); // get sibling instead of root
4476 }
4477 }
4478 break;
4479
4480 // <HOME>: go to first visible
4481 case WXK_HOME:
4482 {
4483 newItem = GetFirstVisible(false, false);
4484 }
4485 break;
4486
4487 // <PAGE-UP>: go to the top of the page, or if we already are then one page back
4488 case WXK_PAGEUP:
4489 {
4490 int flags = 0;
4491 int col = 0;
4492 wxPoint abs_p = CalcUnscrolledPosition (wxPoint(1, 1));
4493 // PAGE-UP: first go the the first visible row
4494 newItem = m_rootItem->HitTest(abs_p, this, flags, col, 0);
4495 newItem = GetFirstVisible(false, true);
4496 // if we are already there then scroll back one page
4497 if (newItem == m_curItem)
4498 {
4499 abs_p.y -= GetClientSize().GetHeight() - m_curItem->GetHeight();
4500 if (abs_p.y < 0) abs_p.y = 0;
4501 newItem = m_rootItem->HitTest(abs_p, this, flags, col, 0);
4502 }
4503 // newItem should never be NULL
4504 }
4505 break;
4506
4507 // <UP>: go to the previous sibling or for the last of its children, to the parent
4508 case WXK_UP:
4509 {
4510 newItem = GetPrevSibling (m_curItem);
4511 if (newItem)
4512 {
4513#if !wxCHECK_VERSION(2, 5, 0)
4514 long cookie = 0;
4515#else
4516 wxTreeItemIdValue cookie = 0;
4517#endif
4518 while (IsExpanded (newItem) && HasChildren (newItem))
4519 {
4520 newItem = GetLastChild (newItem, cookie);
4521 }
4522 }
4523 else
4524 {
4525 newItem = GetItemParent (m_curItem);
4526 if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT))
4527 {
4528 newItem = (wxTreeItemId*)NULL; // don't go to root if it is hidden
4529 }
4530 }
4531 }
4532 break;
4533
4534 // <LEFT>: if expanded collapse subtree, else go to the parent
4535 case WXK_LEFT:
4536 {
4537 if (IsExpanded (m_curItem))
4538 {
4540 }
4541 else
4542 {
4543 newItem = GetItemParent (m_curItem);
4544 if ((newItem == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT))
4545 {
4546 newItem = GetPrevSibling (m_curItem); // go to sibling if it is hidden
4547 }
4548 }
4549 }
4550 break;
4551
4552 // <RIGHT>: if possible expand subtree, else go go to the first child
4553 case WXK_RIGHT:
4554 {
4556 {
4557 Expand (m_curItem);
4558 }
4559 else
4560 {
4562 {
4563#if !wxCHECK_VERSION(2, 5, 0)
4564 long cookie = 0;
4565#else
4566 wxTreeItemIdValue cookie = 0;
4567#endif
4568 newItem = GetFirstChild (m_curItem, cookie);
4569 }
4570 }
4571 }
4572 break;
4573
4574 // <DOWN>: if expanded go to the first child, else to the next sibling, ect
4575 case WXK_DOWN:
4576 {
4578 {
4579#if !wxCHECK_VERSION(2, 5, 0)
4580 long cookie = 0;
4581#else
4582 wxTreeItemIdValue cookie = 0;
4583#endif
4584 newItem = GetFirstChild( m_curItem, cookie );
4585 }
4586 if (!newItem)
4587 {
4588 wxTreeItemId parent = m_curItem;
4589 do
4590 {
4591 newItem = GetNextSibling (parent);
4592 parent = GetItemParent (parent);
4593 }
4594 while (!newItem && parent);
4595 }
4596 }
4597 break;
4598
4599 // <PAGE-DOWN>: go to the bottom of the page, or if we already are then one page further
4600 case WXK_PAGEDOWN:
4601 {
4602 int flags = 0;
4603 int col = 0;
4604 wxPoint abs_p = CalcUnscrolledPosition (wxPoint(1, GetClientSize().GetHeight() - m_curItem->GetHeight()));
4605 // PAGE-UP: first go the the first visible row
4606 newItem = m_rootItem->HitTest(abs_p, this, flags, col, 0);
4607 newItem = GetLastVisible(false, true);
4608 // if we are already there then scroll down one page
4609 if (newItem == m_curItem)
4610 {
4611 abs_p.y += GetClientSize().GetHeight() - m_curItem->GetHeight();
4612// if (abs_p.y >= GetVirtualSize().GetHeight()) abs_p.y = GetVirtualSize().GetHeight() - 1;
4613 newItem = m_rootItem->HitTest(abs_p, this, flags, col, 0);
4614 }
4615 // if we reached the empty area below the rows, return last item instead
4616 if (! newItem) newItem = GetLastVisible(false, false);
4617 }
4618 break;
4619
4620 // <END>: go to last item of the root
4621 case WXK_END:
4622 {
4623 newItem = GetLastVisible (false, false);
4624 }
4625 break;
4626
4627 // any char: go to the next matching string
4628 default:
4629 if (event.GetKeyCode() >= (int)' ' && event.GetKeyCode() < WXK_START)
4630 {
4631 if (!m_findTimer->IsRunning()) m_findStr.Clear();
4632 m_findStr.Append ((char)event.GetKeyCode());
4633 m_findTimer->Start (FIND_TIMER_TICKS, wxTIMER_ONE_SHOT);
4634 wxTreeItemId prev = m_curItem ? (wxTreeItemId*)m_curItem : (wxTreeItemId*)NULL;
4635 while (true)
4636 {
4638 if (newItem || (m_findStr.Length() <= 1)) break;
4639 m_findStr.RemoveLast();
4640 };
4641 }
4642 event.Skip();
4643
4644 }
4645
4646 // select and show the new item
4647 if (newItem)
4648 {
4649 if (!event.ControlDown())
4650 {
4651 bool unselect_others = !((event.ShiftDown() || event.ControlDown()) &&
4652 HasFlag(wxTR_MULTIPLE));
4653 SelectItem (newItem, m_shiftItem, unselect_others);
4654 }
4655 EnsureVisible (newItem);
4656 wxTreeListItem* oldItem = m_curItem;
4657 SetCurrentItem((wxTreeListItem*)newItem.m_pItem); // make the new item the current item
4658 RefreshLine (oldItem);
4659 }
4660
4661 }
4662
4663 wxTreeItemId wxTreeListMainWindow::HitTest (const wxPoint& point, int& flags, int& column)
4664 {
4665
4666 int w, h;
4667 GetSize(&w, &h);
4668 flags = 0;
4669 column = -1;
4670 if (point.x < 0) flags |= wxTREE_HITTEST_TOLEFT;
4671 if (point.x > w) flags |= wxTREE_HITTEST_TORIGHT;
4672 if (point.y < 0) flags |= wxTREE_HITTEST_ABOVE;
4673 if (point.y > h) flags |= wxTREE_HITTEST_BELOW;
4674 if (flags) return wxTreeItemId();
4675
4676 if (!m_rootItem)
4677 {
4678 flags = wxTREE_HITTEST_NOWHERE;
4679 column = -1;
4680 return wxTreeItemId();
4681 }
4682
4683 wxTreeListItem* hit = m_rootItem->HitTest (CalcUnscrolledPosition(point),
4684 this, flags, column, 0);
4685 if (!hit)
4686 {
4687 flags = wxTREE_HITTEST_NOWHERE;
4688 column = -1;
4689 return wxTreeItemId();
4690 }
4691 return hit;
4692 }
4693
4694// get the bounding rectangle of the item (or of its label only)
4695 bool wxTreeListMainWindow::GetBoundingRect (const wxTreeItemId& itemId, wxRect& rect,
4696 bool WXUNUSED(textOnly)) const
4697 {
4698 wxCHECK_MSG (itemId.IsOk(), false, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") );
4699
4700 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
4701
4702 int xUnit, yUnit;
4703 GetScrollPixelsPerUnit (&xUnit, &yUnit);
4704 int startX, startY;
4705 GetViewStart(& startX, & startY);
4706
4707 rect.x = item->GetX() - startX * xUnit;
4708 rect.y = item->GetY() - startY * yUnit;
4709 rect.width = item->GetWidth();
4710 rect.height = GetLineHeight (item);
4711
4712 return true;
4713 }
4714
4715 /* **** */
4716
4717 void wxTreeListMainWindow::EditLabel (const wxTreeItemId& item, int column)
4718 {
4719
4720// validate
4721 if (!item.IsOk()) return;
4722 if (!((column >= 0) && (column < GetColumnCount()))) return;
4723
4724// cancel any editing
4725 if (m_editControl)
4726 {
4727 m_editControl->EndEdit(true); // cancelled
4728 }
4729
4730// prepare edit (position)
4731 m_editItem = (wxTreeListItem*) item.m_pItem;
4732
4733 wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, 0 );
4734 te.SetInt (column);
4735 SendEvent(0, m_editItem, &te);
4736 if (!te.IsAllowed()) return;
4737
4738 // ensure that the position of the item it calculated in any case
4740
4742
4743 // position & size are rather unpredictable (tsssk, tssssk) so were
4744 // set by trial & error (on Win 2003 pre-XP style)
4745 int x = 0;
4746 int w = +4; // +4 is necessary, don't know why (simple border erronously counted somewhere ?)
4747 int y = m_editItem->GetY() + 1; // this is cell, not text
4748 int h = m_editItem->GetHeight() - 1; // consequence from above
4749 long style = 0;
4750 if (column == GetMainColumn())
4751 {
4752 x += m_editItem->GetTextX() - 2; // wrong by 2, don't know why
4753 w += m_editItem->GetWidth();
4754 }
4755 else
4756 {
4757 for (int i = 0; i < column; ++i)
4758 {
4759 if ( header_win->IsColumnShown(i) )
4760 {
4761 x += header_win->GetColumnWidth (i); // start of column
4762 }
4763 }
4764 w += header_win->GetColumnWidth (column); // currently non-main column width not pre-computed
4765 }
4766 switch (header_win->GetColumnAlignment (column))
4767 {
4768 case wxALIGN_LEFT:
4769 {
4770 style = wxTE_LEFT;
4771 x -= 1;
4772 break;
4773 }
4774 case wxALIGN_CENTER:
4775 {
4776 style = wxTE_CENTER;
4777 x -= 1;
4778 break;
4779 }
4780 case wxALIGN_RIGHT:
4781 {
4782 style = wxTE_RIGHT; // yes, strange but that's the way it is
4783 x += 0;
4784 break;
4785 }
4786 }
4787 // wxTextCtrl simple border style requires 2 extra pixels before and after
4788 // (measured by changing to style wxNO_BORDER in wxEditTextCtrl::wxEditTextCtrl() )
4789 y -= 2;
4790 x -= 2;
4791 w += 4;
4792 h += 4;
4793
4794 wxClientDC dc (this);
4795 PrepareDC (dc);
4796 x = dc.LogicalToDeviceX (x);
4797 y = dc.LogicalToDeviceY (y);
4798
4799// now do edit (change state, show control)
4800 m_editCol = column; // only used in OnRenameAccept()
4802 this, m_editItem->GetText (column),
4803 wxPoint (x, y), wxSize (w, h), style);
4804 m_editControl->SetFocus();
4805 }
4806
4808 {
4810 }
4811
4813 {
4814 wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, 0 );
4815 le.SetLabel( m_editRes );
4816 le.SetEditCanceled(isCancelled);
4817 le.SetInt(m_editCol);
4818 SendEvent(0, m_editItem, &le);
4819 if (! isCancelled && le.IsAllowed())
4820 {
4821 SetItemText (m_editItem, le.GetInt(), le.GetLabel());
4822 }
4823 }
4824
4825 void wxTreeListMainWindow::EndEdit(bool isCancelled)
4826 {
4827 if (m_editControl)
4828 {
4829 m_editControl->EndEdit(true);
4830 }
4831 }
4832
4833 void wxTreeListMainWindow::OnMouse (wxMouseEvent& event)
4834 {
4835 bool mayDrag = true;
4836 bool maySelect = true; // may change selection
4837 bool mayClick = true; // may process DOWN clicks to expand, send click events
4838 bool mayDoubleClick = true; // implies mayClick
4839 bool bSkip = true;
4840
4841 // send event to user code
4842 if (m_owner->GetEventHandler()->ProcessEvent(event)) return; // handled (and not skipped) in user code
4843 if (!m_rootItem) return;
4844
4845
4846// ---------- DETERMINE EVENT ----------
4847 /*
4848 wxLogMessage("OnMouse: LMR down=<%d, %d, %d> up=<%d, %d, %d> LDblClick=<%d> dragging=<%d>",
4849 event.LeftDown(), event.MiddleDown(), event.RightDown(),
4850 event.LeftUp(), event.MiddleUp(), event.RightUp(),
4851 event.LeftDClick(), event.Dragging());
4852 */
4853 wxPoint p = wxPoint (event.GetX(), event.GetY());
4854 int flags = 0;
4855 wxTreeListItem* item = m_rootItem->HitTest (CalcUnscrolledPosition (p),
4856 this, flags, m_curColumn, 0);
4857 bool bCrosshair = (item && item->HasPlus() && (flags & wxTREE_HITTEST_ONITEMBUTTON));
4858 // we were dragging
4859 if (m_isDragging)
4860 {
4861 maySelect = mayDoubleClick = false;
4862 }
4863 // we are starting or continuing to drag
4864 if (event.Dragging())
4865 {
4866 maySelect = mayDoubleClick = mayClick = false;
4867 }
4868 // crosshair area is special
4869 if (bCrosshair)
4870 {
4871 // left click does not select
4872 if (event.LeftDown()) maySelect = false;
4873 // double click is ignored
4874 mayDoubleClick = false;
4875 }
4876 // double click only if simple click
4877 if (mayDoubleClick) mayDoubleClick = mayClick;
4878 // selection conditions --remember also that selection exludes editing
4879 if (maySelect) maySelect = mayClick; // yes, select/unselect requires a click
4880 if (maySelect)
4881 {
4882
4883 // multiple selection mode complicates things, sometimes we
4884 // select on button-up instead of down:
4885 if (HasFlag(wxTR_MULTIPLE))
4886 {
4887
4888 // CONTROL/SHIFT key used, don't care about anything else, will
4889 // toggle on key down
4890 if (event.ControlDown() || event.ShiftDown())
4891 {
4892 maySelect = maySelect && (event.LeftDown() || event.RightDown());
4893 m_lastOnSame = false; // prevent editing when keys are used
4894
4895 // already selected item: to allow drag or contextual menu for multiple
4896 // items, we only select/unselect on click-up --and only on LEFT
4897 // click, right is reserved for contextual menu
4898 }
4899 else if ((item != NULL && item->IsSelected()))
4900 {
4901 maySelect = maySelect && event.LeftUp();
4902
4903 // non-selected items: select on click-down like simple select (so
4904 // that a right-click contextual menu may be chained)
4905 }
4906 else
4907 {
4908 maySelect = maySelect && (event.LeftDown() || event.RightDown());
4909 }
4910
4911 // single-select is simply on left or right click-down
4912 }
4913 else
4914 {
4915 maySelect = maySelect && (event.LeftDown() || event.RightDown());
4916 }
4917 }
4918
4919
4920// ---------- GENERAL ACTIONS ----------
4921
4922 // set focus if window clicked
4923 if (event.LeftDown() || event.MiddleDown() || event.RightDown()) SetFocus();
4924
4925 // tooltip change ?
4926 if (item != m_toolTipItem)
4927 {
4928
4929 // not over an item, use global tip
4930 if (item == NULL)
4931 {
4932 m_toolTipItem = NULL;
4933 wxScrolledWindow::SetToolTip(m_toolTip);
4934
4935 // over an item
4936 }
4937 else
4938 {
4939 const wxString* tip = item->GetToolTip();
4940
4941 // is there an item-specific tip ?
4942 if (tip)
4943 {
4944 m_toolTipItem = item;
4945 wxScrolledWindow::SetToolTip(*tip);
4946
4947 // no item tip, but we are in item-specific mode (SetItemToolTip()
4948 // was called after SetToolTip() )
4949 }
4950 else if (m_isItemToolTip)
4951 {
4952 m_toolTipItem = item;
4953 wxScrolledWindow::SetToolTip(wxString());
4954
4955 // no item tip, display global tip instead; item change ignored
4956 }
4957 else if (m_toolTipItem != NULL)
4958 {
4959 m_toolTipItem = NULL;
4960 wxScrolledWindow::SetToolTip(m_toolTip);
4961 }
4962 }
4963 }
4964
4965
4966// ---------- HANDLE SIMPLE-CLICKS (selection change, contextual menu) ----------
4967 if (mayClick)
4968 {
4969
4970 // 2nd left-click on an item might trigger edit
4971 if (event.LeftDown()) m_lastOnSame = (item == m_curItem);
4972
4973 // left-click on haircross is expand (and no select)
4974 if (bCrosshair && event.LeftDown())
4975 {
4976
4977 bSkip = false;
4978
4979 // note that we only toggle the item for a single click, double
4980 // click on the button doesn't do anything
4981 Toggle (item);
4982 }
4983
4984 if (maySelect)
4985 {
4986 bSkip = false;
4987
4988 // set / remember item at shift down before current item gets changed
4989 if (event.LeftDown() && HasFlag(wxTR_MULTIPLE) && event.ShiftDown())
4990 {
4992 }
4993 else
4994 {
4995 m_shiftItem = (wxTreeListItem*)NULL;
4996 }
4997
4998 // how is selection altered
4999 // keep or discard already selected ?
5000 bool unselect_others = ! (HasFlag(wxTR_MULTIPLE) && (
5001 event.ShiftDown()
5002 || event.ControlDown()
5003 ));
5004
5005 // check is selection change is not vetoed
5006 if (SelectItem(item, m_shiftItem, unselect_others))
5007 {
5008 // make the new item the current item
5009 EnsureVisible (item);
5010 SetCurrentItem(item);
5011 }
5012 }
5013
5014 // generate click & menu events
5015 if (event.MiddleDown())
5016 {
5017 // our own event to set point
5018 wxTreeEvent nevent(0, 0);
5019 nevent.SetPoint(p);
5020 nevent.SetInt(m_curColumn);
5021 bSkip = false;
5022 SendEvent(wxEVT_COMMAND_TREE_ITEM_MIDDLE_CLICK, item, &nevent);
5023 }
5024 if (event.RightDown())
5025 {
5026 // our own event to set point
5027 wxTreeEvent nevent(0, 0);
5028 nevent.SetPoint(p);
5029 nevent.SetInt(m_curColumn);
5030 bSkip = false;
5031 SendEvent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, item, &nevent);
5032 }
5033 if (event.RightUp())
5034 {
5035 // our own event to set point
5036 wxTreeEvent nevent(0, 0);
5037 nevent.SetPoint(p);
5038 nevent.SetInt(m_curColumn);
5039 SendEvent(wxEVT_COMMAND_TREE_ITEM_MENU, item, &nevent);
5040 }
5041
5042 // if 2nd left click finishes on same item, will edit it
5043 if (m_lastOnSame && event.LeftUp())
5044 {
5045 if ((item == m_curItem) && (m_curColumn != -1) &&
5047 (flags & (wxTREE_HITTEST_ONITEMLABEL | wxTREE_HITTEST_ONITEMCOLUMN))
5048 )
5049 {
5050 m_editTimer->Start (RENAME_TIMER_TICKS, wxTIMER_ONE_SHOT);
5051 bSkip = false;
5052 }
5053 m_lastOnSame = false;
5054 }
5055 }
5056
5057
5058// ---------- HANDLE DOUBLE-CLICKS ----------
5059 if (mayDoubleClick && event.LeftDClick())
5060 {
5061
5062 bSkip = false;
5063
5064 // double clicking should not start editing the item label
5065 m_editTimer->Stop();
5066 m_lastOnSame = false;
5067
5068 // selection reset to that single item which was double-clicked
5069 if (SelectItem(item, (wxTreeItemId*)NULL, true)) // unselect others --return false if vetoed
5070 {
5071
5072 // selection change not vetoed, send activate event
5073 if (! SendEvent(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, item))
5074 {
5075
5076 // if the user code didn't process the activate event,
5077 // handle it ourselves by toggling the item when it is
5078 // double clicked
5079 if (item && item->HasPlus()) Toggle(item);
5080 }
5081 }
5082 }
5083
5084
5085// ---------- HANDLE DRAGGING ----------
5086// NOTE: drag itself makes no change to selection
5087 if (mayDrag) // actually this is always true
5088 {
5089
5090 // CASE 1: we were dragging => continue, end, abort
5091 if (m_isDragging)
5092 {
5093
5094 // CASE 1.1: click aborts drag:
5095 if (event.LeftDown() || event.MiddleDown() || event.RightDown())
5096 {
5097
5098 bSkip = false;
5099
5100 // stop dragging
5101 m_isDragStarted = m_isDragging = false;
5102 if (HasCapture()) ReleaseMouse();
5104
5105 // CASE 1.2: still dragging
5106 }
5107 else if (event.Dragging())
5108 {
5109
5110 ;; // nothing to do
5111
5112 // CASE 1.3: dragging now ends normally
5113 }
5114 else
5115 {
5116
5117 bSkip = false;
5118
5119 // stop dragging
5120 m_isDragStarted = m_isDragging = false;
5121 if (HasCapture()) ReleaseMouse();
5123
5124 // send drag end event
5125 // our own event to set point
5126 wxTreeEvent nevent(0, 0);
5127 nevent.SetPoint(p);
5128 nevent.SetInt(m_curColumn);
5129 SendEvent(wxEVT_COMMAND_TREE_END_DRAG, item, &nevent);
5130 }
5131
5132 // CASE 2: not were not dragging => continue, start
5133 }
5134 else if (event.Dragging())
5135 {
5136
5137 // We will really start dragging if we've moved beyond a few pixels
5138 if (m_isDragStarted)
5139 {
5140 const int tolerance = 3;
5141 int dx = abs(p.x - m_dragStartPos.x);
5142 int dy = abs(p.y - m_dragStartPos.y);
5143 if (dx <= tolerance && dy <= tolerance)
5144 return;
5145 // determine drag start
5146 }
5147 else
5148 {
5149 m_dragStartPos = p;
5151 m_dragItem = item;
5152 m_isDragStarted = true;
5153 return;
5154 }
5155
5156 bSkip = false;
5157
5158 // we are now dragging
5159 m_isDragging = true;
5161 CaptureMouse();
5162
5163 wxTreeEvent nevent(0, 0);
5164 nevent.SetPoint(p);
5165 nevent.SetInt(m_dragCol);
5166 nevent.Veto();
5167 SendEvent(event.LeftIsDown()
5168 ? wxEVT_COMMAND_TREE_BEGIN_DRAG
5169 : wxEVT_COMMAND_TREE_BEGIN_RDRAG,
5170 m_dragItem, &nevent);
5171 }
5172 }
5173
5174
5175 if (bSkip) event.Skip();
5176 }
5177
5178
5179 void wxTreeListMainWindow::OnIdle (wxIdleEvent& WXUNUSED(event))
5180 {
5181 /* after all changes have been done to the tree control,
5182 * we actually redraw the tree when everything is over */
5183
5184 if (!m_dirty) return;
5185
5186 m_dirty = false;
5187
5189 Refresh();
5191 }
5192
5193 void wxTreeListMainWindow::OnScroll (wxScrollWinEvent& event)
5194 {
5195
5196 // send event to wxTreeListCtrl (for user code)
5197 if (m_owner->GetEventHandler()->ProcessEvent(event)) return; // handled (and not skipped) in user code
5198
5199#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
5200 wxScrolledWindow::OnScroll(event);
5201#else
5202 HandleOnScroll( event );
5203#endif
5204
5205 if (event.GetOrientation() == wxHORIZONTAL)
5206 {
5207 m_owner->GetHeaderWindow()->Refresh();
5208 m_owner->GetHeaderWindow()->Update();
5209 }
5210 }
5211
5213 {
5214 wxCoord text_w = 0;
5215 wxCoord text_h = 0;
5216
5217 dc.SetFont (GetItemFont (item));
5218 dc.GetTextExtent (item->GetText(m_main_column).size() > 0
5219 ? item->GetText (m_main_column)
5220 : _T(" "), // blank to avoid zero height and no highlight width
5221 &text_w, &text_h);
5222 // restore normal font
5223 dc.SetFont (m_normalFont);
5224
5225 int max_h = (m_imgHeight > text_h) ? m_imgHeight : text_h;
5226 if (max_h < 30) // add 10% space if greater than 30 pixels
5227 {
5228 max_h += 2; // minimal 2 pixel space
5229 }
5230 else
5231 {
5232 max_h += max_h / 10; // otherwise 10% space
5233 }
5234
5235 item->SetHeight (max_h);
5236 if (max_h > m_lineHeight) m_lineHeight = max_h;
5237 item->SetWidth(m_imgWidth + text_w + 2);
5238 }
5239
5240// -----------------------------------------------------------------------------
5242 int level, int& y, int x_colstart)
5243 {
5244
5245 // calculate position of vertical lines
5246 int x = x_colstart + MARGIN; // start of column
5247 if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root
5248 if (HasButtons())
5249 {
5250 x += (m_btnWidth - m_btnWidth2); // half button space
5251 }
5252 else
5253 {
5254 x += (m_indent - m_indent / 2);
5255 }
5256 if (HasFlag(wxTR_HIDE_ROOT))
5257 {
5258 x += m_indent * (level - 1); // indent but not level 1
5259 }
5260 else
5261 {
5262 x += m_indent * level; // indent according to level
5263 }
5264
5265 // a hidden root is not evaluated, but its children are always
5266 if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) goto Recurse;
5267
5268 CalculateSize( item, dc );
5269
5270 // set its position
5271 item->SetX (x);
5272 item->SetY (y);
5273 y += GetLineHeight(item);
5274
5275 // we don't need to calculate collapsed branches
5276 if ( !item->IsExpanded() ) return;
5277
5278Recurse:
5279 wxArrayTreeListItems& children = item->GetChildren();
5280 long n, count = (long)children.Count();
5281 ++level;
5282 for (n = 0; n < count; ++n)
5283 {
5284 CalculateLevel( children[n], dc, level, y, x_colstart ); // recurse
5285 }
5286 }
5287
5289 {
5290 if ( !m_rootItem ) return;
5291
5292 wxClientDC dc(this);
5293 PrepareDC( dc );
5294
5295 dc.SetFont( m_normalFont );
5296
5297 dc.SetPen( m_dottedPen );
5298 //if(GetImageList() == NULL)
5299 // m_lineHeight = (int)(dc.GetCharHeight() + 4);
5300
5301 int y = 2;
5302 int x_colstart = 0;
5303 for (int i = 0; i < (int)GetMainColumn(); ++i)
5304 {
5305 if (!m_owner->GetHeaderWindow()->IsColumnShown(i)) continue;
5306 x_colstart += m_owner->GetHeaderWindow()->GetColumnWidth(i);
5307 }
5308 CalculateLevel( m_rootItem, dc, 0, y, x_colstart ); // start recursion
5309 }
5310
5312 {
5313 if (m_dirty) return;
5314
5315 wxClientDC dc(this);
5316 PrepareDC(dc);
5317
5318 int cw = 0;
5319 int ch = 0;
5320 GetVirtualSize( &cw, &ch );
5321
5322 wxRect rect;
5323 rect.x = dc.LogicalToDeviceX( 0 );
5324 rect.width = cw;
5325 rect.y = dc.LogicalToDeviceY( item->GetY() - 2 );
5326 rect.height = ch;
5327
5328 Refresh (true, &rect );
5330 }
5331
5333 {
5334 if (m_dirty) return;
5335
5336 wxClientDC dc(this);
5337 PrepareDC( dc );
5338
5339 int cw = 0;
5340 int ch = 0;
5341 GetVirtualSize( &cw, &ch );
5342
5343 wxRect rect;
5344 rect.x = dc.LogicalToDeviceX( 0 );
5345 rect.y = dc.LogicalToDeviceY( item->GetY() );
5346 rect.width = cw;
5347 rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6;
5348
5349 Refresh (true, &rect);
5350 }
5351
5353 {
5354 if (m_rootItem)
5355 {
5357 }
5358 }
5359
5361 {
5362 if (item->IsSelected())
5363 {
5364 RefreshLine (item);
5365 }
5366
5367 const wxArrayTreeListItems& children = item->GetChildren();
5368 long count = (long)children.GetCount();
5369 for (long n = 0; n < count; n++ )
5370 {
5371 RefreshSelectedUnder (children[n]);
5372 }
5373 }
5374
5375// ----------------------------------------------------------------------------
5376// changing colours: we need to refresh the tree control
5377// ----------------------------------------------------------------------------
5378
5379 bool wxTreeListMainWindow::SetBackgroundColour (const wxColour& colour)
5380 {
5381 if (!wxWindow::SetBackgroundColour(colour)) return false;
5382
5383 Refresh();
5384 return true;
5385 }
5386
5387 bool wxTreeListMainWindow::SetForegroundColour (const wxColour& colour)
5388 {
5389 if (!wxWindow::SetForegroundColour(colour)) return false;
5390
5391 Refresh();
5392 return true;
5393 }
5394
5395 void wxTreeListMainWindow::SetItemText (const wxTreeItemId& itemId, int column, const wxString& text)
5396 {
5397 wxCHECK_RET (itemId.IsOk(), _T("invalid tree item"));
5398
5399 wxClientDC dc (this);
5400 wxTreeListItem* item = (wxTreeListItem*) itemId.m_pItem;
5401 item->SetText (column, text);
5402 CalculateSize (item, dc);
5403 RefreshLine (item);
5404 }
5405
5406 wxString wxTreeListMainWindow::GetItemText (const wxTreeItemId& itemId, int column) const
5407 {
5408 wxCHECK_MSG (itemId.IsOk(), _T(""), _T("invalid tree item") );
5409
5410 if ( IsVirtual() ) return m_owner->OnGetItemText(((wxTreeListItem*) itemId.m_pItem)->GetData(), column);
5411 else return ((wxTreeListItem*) itemId.m_pItem)->GetText (column);
5412 }
5413
5414 wxString wxTreeListMainWindow::GetItemText (wxTreeItemData* item, int column) const
5415 {
5416 wxASSERT_MSG( IsVirtual(), _T("can be used only with virtual control") );
5417 return m_owner->OnGetItemText(item, column);
5418 }
5419
5421 {
5422 wxWindow::SetFocus();
5423 }
5424
5425
5427 {
5428 if (!item) return 0;
5429
5430 // determine item width
5431 int w = 0, h = 0;
5432 wxFont font = GetItemFont (item);
5433 GetTextExtent (item->GetText (column), &w, &h, NULL, NULL, font.Ok() ? &font : NULL);
5434 w += 2 * MARGIN;
5435
5436 // calculate width
5437 int width = w + 2 * MARGIN;
5438 if (column == GetMainColumn())
5439 {
5440 width += MARGIN;
5441 if (HasFlag(wxTR_LINES_AT_ROOT)) width += LINEATROOT;
5442 if (HasButtons()) width += m_btnWidth + LINEATROOT;
5443 if (item->GetCurrentImage() != NO_IMAGE) width += m_imgWidth;
5444
5445 // count indent level
5446 int level = 0;
5447 wxTreeListItem* parent = item->GetItemParent();
5448 wxTreeListItem* root = (wxTreeListItem*)GetRootItem().m_pItem;
5449 while (parent && (!HasFlag(wxTR_HIDE_ROOT) || (parent != root)))
5450 {
5451 level++;
5452 parent = parent->GetItemParent();
5453 }
5454 if (level) width += level * GetIndent();
5455 }
5456
5457 return width;
5458 }
5459
5460 int wxTreeListMainWindow::GetBestColumnWidth (int column, wxTreeItemId parent)
5461 {
5462 int maxWidth, h;
5463 GetClientSize (&maxWidth, &h);
5464 int width = 0;
5465
5466 // get root if on item
5467 if (!parent.IsOk()) parent = GetRootItem();
5468
5469 // add root width
5470 if (!HasFlag(wxTR_HIDE_ROOT))
5471 {
5472 int w = GetItemWidth (column, (wxTreeListItem*)parent.m_pItem);
5473 if (width < w) width = w;
5474 if (width > maxWidth) return maxWidth;
5475 }
5476
5477 wxTreeItemIdValue cookie = 0;
5478 wxTreeItemId item = GetFirstChild (parent, cookie);
5479 while (item.IsOk())
5480 {
5481 int w = GetItemWidth (column, (wxTreeListItem*)item.m_pItem);
5482 if (width < w) width = w;
5483 if (width > maxWidth) return maxWidth;
5484
5485 // check the children of this item
5486 if (((wxTreeListItem*)item.m_pItem)->IsExpanded())
5487 {
5488 int w = GetBestColumnWidth (column, item);
5489 if (width < w) width = w;
5490 if (width > maxWidth) return maxWidth;
5491 }
5492
5493 // next sibling
5494 item = GetNextChild (parent, cookie);
5495 }
5496
5497 return width;
5498 }
5499
5500
5501 bool wxTreeListMainWindow::SendEvent(wxEventType event_type, wxTreeListItem* item, wxTreeEvent* event)
5502 {
5503 wxTreeEvent nevent (event_type, 0);
5504
5505 if (event == NULL)
5506 {
5507 event = &nevent;
5508 event->SetInt (m_curColumn); // the mouse colum
5509 }
5510 else if (event_type)
5511 {
5512 event->SetEventType(event_type);
5513 }
5514
5515 event->SetEventObject (m_owner);
5516 event->SetId(m_owner->GetId());
5517 if (item)
5518 {
5519#if !wxCHECK_VERSION(2, 5, 0)
5520 event->SetItem ((long)item);
5521#else
5522 event->SetItem (item);
5523#endif
5524 }
5525
5526 return m_owner->GetEventHandler()->ProcessEvent (*event);
5527 }
5528
5529
5530//-----------------------------------------------------------------------------
5531// wxTreeListCtrl
5532//-----------------------------------------------------------------------------
5533
5535
5536 BEGIN_EVENT_TABLE(wxTreeListCtrl, wxControl)
5537 EVT_SIZE(wxTreeListCtrl::OnSize)
5539
5540 bool wxTreeListCtrl::Create(wxWindow* parent, wxWindowID id,
5541 const wxPoint& pos,
5542 const wxSize& size,
5543 long style, const wxValidator& validator,
5544 const wxString& name)
5545 {
5546 long main_style = style & ~(wxSIMPLE_BORDER | wxSUNKEN_BORDER | wxDOUBLE_BORDER |
5547 wxRAISED_BORDER | wxSTATIC_BORDER);
5548 main_style |= wxWANTS_CHARS ;
5549 long ctrl_style = style & ~(wxVSCROLL | wxHSCROLL);
5550
5551 if (!wxControl::Create(parent, id, pos, size, ctrl_style, validator, name))
5552 {
5553 return false;
5554 }
5555 m_main_win = new wxTreeListMainWindow (this, -1, wxPoint(0, 0), size,
5556 main_style, validator);
5557 m_header_win = new wxTreeListHeaderWindow (this, -1, m_main_win,
5558 wxPoint(0, 0), wxDefaultSize,
5559 wxTAB_TRAVERSAL);
5560 CalculateAndSetHeaderHeight();
5561 return true;
5562 }
5563
5565 {
5566 if (m_header_win)
5567 {
5568
5569 // we use 'g' to get the descent, too
5570 int h;
5571#if wxCHECK_VERSION_FULL(2, 7, 0, 1)
5572#ifdef __WXMSW__
5573 h = (int)(wxRendererNative::Get().GetHeaderButtonHeight(m_header_win) * 0.8) + 2;
5574#else
5575 h = wxRendererNative::Get().GetHeaderButtonHeight(m_header_win);
5576#endif
5577#else
5578 int w, d;
5579 m_header_win->GetTextExtent(_T("Hg"), &w, &h, &d);
5580 h += d + 2 * HEADER_OFFSET_Y + EXTRA_HEIGHT;
5581#endif
5582
5583 // only update if changed
5584 if (h != m_headerHeight)
5585 {
5586 m_headerHeight = h;
5587 DoHeaderLayout();
5588 }
5589 }
5590 }
5591
5593 {
5594 int w, h;
5595 GetClientSize(&w, &h);
5596 if (m_header_win)
5597 {
5598 m_header_win->SetSize (0, 0, w, m_headerHeight);
5599 m_header_win->Refresh();
5600 }
5601 if (m_main_win)
5602 {
5603 m_main_win->SetSize (0, m_headerHeight, w, h - m_headerHeight);
5604 }
5605 }
5606
5607 void wxTreeListCtrl::OnSize(wxSizeEvent& WXUNUSED(event))
5608 {
5609 DoHeaderLayout();
5610 }
5611
5613 {
5614 return m_main_win->GetCount();
5615 }
5616
5617 unsigned int wxTreeListCtrl::GetIndent() const
5618 {
5619 return m_main_win->GetIndent();
5620 }
5621
5622 void wxTreeListCtrl::SetIndent(unsigned int indent)
5623 {
5624 m_main_win->SetIndent(indent);
5625 }
5626
5628 {
5629 return m_main_win->GetLineSpacing();
5630 }
5631
5632 void wxTreeListCtrl::SetLineSpacing(unsigned int spacing)
5633 {
5634 m_main_win->SetLineSpacing(spacing);
5635 }
5636
5637 wxImageList* wxTreeListCtrl::GetImageList() const
5638 {
5639 return m_main_win->GetImageList();
5640 }
5641
5643 {
5644 return m_main_win->GetStateImageList();
5645 }
5646
5648 {
5649 return m_main_win->GetButtonsImageList();
5650 }
5651
5652 void wxTreeListCtrl::SetImageList(wxImageList* imageList)
5653 {
5654 m_main_win->SetImageList(imageList);
5655 }
5656
5657 void wxTreeListCtrl::SetStateImageList(wxImageList* imageList)
5658 {
5659 m_main_win->SetStateImageList(imageList);
5660 }
5661
5662 void wxTreeListCtrl::SetButtonsImageList(wxImageList* imageList)
5663 {
5664 m_main_win->SetButtonsImageList(imageList);
5665 }
5666
5667 void wxTreeListCtrl::AssignImageList(wxImageList* imageList)
5668 {
5669 m_main_win->AssignImageList(imageList);
5670 }
5671
5672 void wxTreeListCtrl::AssignStateImageList(wxImageList* imageList)
5673 {
5674 m_main_win->AssignStateImageList(imageList);
5675 }
5676
5677 void wxTreeListCtrl::AssignButtonsImageList(wxImageList* imageList)
5678 {
5679 m_main_win->AssignButtonsImageList(imageList);
5680 }
5681
5682
5683
5684 wxString wxTreeListCtrl::GetItemText(const wxTreeItemId& item, int column) const
5685 {
5686 return m_main_win->GetItemText (item, column);
5687 }
5688
5689 int wxTreeListCtrl::GetItemImage(const wxTreeItemId& item, wxTreeItemIcon which) const
5690 {
5691 return m_main_win->GetItemImage(item, which);
5692 }
5693 int wxTreeListCtrl::GetItemImage(const wxTreeItemId& item, int column) const
5694 {
5695 return m_main_win->GetItemImage(item, column);
5696 }
5697
5698 wxTreeItemData* wxTreeListCtrl::GetItemData(const wxTreeItemId& item) const
5699 {
5700 return m_main_win->GetItemData(item);
5701 }
5702 wxTreeItemData* wxTreeListCtrl::GetItemData(const wxTreeItemId& item, int column) const
5703 {
5704 return m_main_win->GetItemData(item, column);
5705 }
5706
5707 bool wxTreeListCtrl::GetItemBold(const wxTreeItemId& item) const
5708 {
5709 return m_main_win->GetItemBold(item);
5710 }
5711 bool wxTreeListCtrl::GetItemBold(const wxTreeItemId& item, int column) const
5712 {
5713 return m_main_win->GetItemBold(item, column);
5714 }
5715
5716 wxColour wxTreeListCtrl::GetItemTextColour(const wxTreeItemId& item) const
5717 {
5718 return m_main_win->GetItemTextColour(item);
5719 }
5720 wxColour wxTreeListCtrl::GetItemTextColour(const wxTreeItemId& item, int column) const
5721 {
5722 return m_main_win->GetItemTextColour(item, column);
5723 }
5724
5725 wxColour wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId& item) const
5726 {
5727 return m_main_win->GetItemBackgroundColour(item);
5728 }
5729 wxColour wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId& item, int column) const
5730 {
5731 return m_main_win->GetItemBackgroundColour(item, column);
5732 }
5733
5734 wxFont wxTreeListCtrl::GetItemFont(const wxTreeItemId& item) const
5735 {
5736 return m_main_win->GetItemFont(item);
5737 }
5738 wxFont wxTreeListCtrl::GetItemFont(const wxTreeItemId& item, int column) const
5739 {
5740 return m_main_win->GetItemFont(item, column);
5741 }
5742
5743
5744
5745 void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
5746 {
5747 m_main_win->SetItemHasChildren(item, has);
5748 }
5749
5750 void wxTreeListCtrl::SetItemText(const wxTreeItemId& item, int column, const wxString& text)
5751 {
5752 m_main_win->SetItemText (item, column, text);
5753 }
5754
5755 void wxTreeListCtrl::SetItemImage(const wxTreeItemId& item, int image, wxTreeItemIcon which)
5756 {
5757 m_main_win->SetItemImage(item, image, which);
5758 }
5759 void wxTreeListCtrl::SetItemImage(const wxTreeItemId& item, int column, int image)
5760 {
5761 m_main_win->SetItemImage(item, column, image);
5762 }
5763
5764 void wxTreeListCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData* data)
5765 {
5766 m_main_win->SetItemData(item, data);
5767 }
5768 void wxTreeListCtrl::SetItemData(const wxTreeItemId& item, int column, wxTreeItemData* data)
5769 {
5770 m_main_win->SetItemData(item, column, data);
5771 }
5772
5773 void wxTreeListCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
5774 {
5775 m_main_win->SetItemBold(item, bold);
5776 }
5777 void wxTreeListCtrl::SetItemBold(const wxTreeItemId& item, int column, bool bold)
5778 {
5779 m_main_win->SetItemBold(item, column, bold);
5780 }
5781
5782 void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId& item, const wxColour& colour)
5783 {
5784 m_main_win->SetItemTextColour(item, colour);
5785 }
5786 void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId& item, int column, const wxColour& colour)
5787 {
5788 m_main_win->SetItemTextColour(item, column, colour);
5789 }
5790
5791 void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId& item, const wxColour& colour)
5792 {
5793 m_main_win->SetItemBackgroundColour(item, colour);
5794 }
5795 void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId& item, int column, const wxColour& colour)
5796 {
5797 m_main_win->SetItemBackgroundColour(item, column, colour);
5798 }
5799
5800 void wxTreeListCtrl::SetItemFont(const wxTreeItemId& item, const wxFont& font)
5801 {
5802 m_main_win->SetItemFont(item, font);
5803 }
5804 void wxTreeListCtrl::SetItemFont(const wxTreeItemId& item, int column, const wxFont& font)
5805 {
5806 m_main_win->SetItemFont(item, column, font);
5807 }
5808
5809
5810
5811 bool wxTreeListCtrl::SetFont(const wxFont& font)
5812 {
5813 if (m_header_win)
5814 {
5815 m_header_win->SetFont(font);
5816 CalculateAndSetHeaderHeight();
5817 m_header_win->Refresh();
5818 }
5819 if (m_main_win)
5820 {
5821 return m_main_win->SetFont(font);
5822 }
5823 else
5824 {
5825 return false;
5826 }
5827 }
5828
5829 void wxTreeListCtrl::SetWindowStyle(const long style)
5830 {
5831 if (m_main_win)
5832 m_main_win->SetWindowStyle(style);
5833 m_windowStyle = style;
5834 }
5835
5837 {
5838 long style = m_windowStyle;
5839 if (m_main_win)
5840 style |= m_main_win->GetWindowStyle();
5841 return style;
5842 }
5843
5844 bool wxTreeListCtrl::IsVisible(const wxTreeItemId& item, bool fullRow, bool within) const
5845 {
5846 return m_main_win->IsVisible(item, fullRow, within);
5847 }
5848
5849 bool wxTreeListCtrl::HasChildren(const wxTreeItemId& item) const
5850 {
5851 return m_main_win->HasChildren(item);
5852 }
5853
5854 bool wxTreeListCtrl::IsExpanded(const wxTreeItemId& item) const
5855 {
5856 return m_main_win->IsExpanded(item);
5857 }
5858
5859 bool wxTreeListCtrl::IsSelected(const wxTreeItemId& item) const
5860 {
5861 return m_main_win->IsSelected(item);
5862 }
5863
5864 size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId& item, bool rec)
5865 {
5866 return m_main_win->GetChildrenCount(item, rec);
5867 }
5868
5869 wxTreeItemId wxTreeListCtrl::GetRootItem() const
5870 {
5871 return m_main_win->GetRootItem();
5872 }
5873
5874 wxTreeItemId wxTreeListCtrl::GetSelection() const
5875 {
5876 return m_main_win->GetSelection();
5877 }
5878
5879 size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds& arr) const
5880 {
5881 return m_main_win->GetSelections(arr);
5882 }
5883
5884 wxTreeItemId wxTreeListCtrl::GetItemParent(const wxTreeItemId& item) const
5885 {
5886 return m_main_win->GetItemParent(item);
5887 }
5888
5889#if !wxCHECK_VERSION(2, 5, 0)
5890 wxTreeItemId wxTreeListCtrl::GetFirstChild (const wxTreeItemId& item,
5891 long& cookie) const
5892#else
5893 wxTreeItemId wxTreeListCtrl::GetFirstChild (const wxTreeItemId& item,
5894 wxTreeItemIdValue& cookie) const
5895#endif
5896 {
5897 return m_main_win->GetFirstChild(item, cookie);
5898 }
5899
5900#if !wxCHECK_VERSION(2, 5, 0)
5901 wxTreeItemId wxTreeListCtrl::GetNextChild (const wxTreeItemId& item,
5902 long& cookie) const
5903#else
5904 wxTreeItemId wxTreeListCtrl::GetNextChild (const wxTreeItemId& item,
5905 wxTreeItemIdValue& cookie) const
5906#endif
5907 {
5908 return m_main_win->GetNextChild(item, cookie);
5909 }
5910
5911#if !wxCHECK_VERSION(2, 5, 0)
5912 wxTreeItemId wxTreeListCtrl::GetPrevChild (const wxTreeItemId& item,
5913 long& cookie) const
5914#else
5915 wxTreeItemId wxTreeListCtrl::GetPrevChild (const wxTreeItemId& item,
5916 wxTreeItemIdValue& cookie) const
5917#endif
5918 {
5919 return m_main_win->GetPrevChild(item, cookie);
5920 }
5921
5922#if !wxCHECK_VERSION(2, 5, 0)
5923 wxTreeItemId wxTreeListCtrl::GetLastChild (const wxTreeItemId& item,
5924 long& cookie) const
5925#else
5926 wxTreeItemId wxTreeListCtrl::GetLastChild (const wxTreeItemId& item,
5927 wxTreeItemIdValue& cookie) const
5928#endif
5929 {
5930 return m_main_win->GetLastChild(item, cookie);
5931 }
5932
5933
5934 wxTreeItemId wxTreeListCtrl::GetNextSibling(const wxTreeItemId& item) const
5935 {
5936 return m_main_win->GetNextSibling(item);
5937 }
5938
5939 wxTreeItemId wxTreeListCtrl::GetPrevSibling(const wxTreeItemId& item) const
5940 {
5941 return m_main_win->GetPrevSibling(item);
5942 }
5943
5944 wxTreeItemId wxTreeListCtrl::GetNext(const wxTreeItemId& item) const
5945 {
5946 return m_main_win->GetNext(item, true);
5947 }
5948
5949 wxTreeItemId wxTreeListCtrl::GetPrev(const wxTreeItemId& item) const
5950 {
5951 return m_main_win->GetPrev(item, true);
5952 }
5953
5955 {
5956 return m_main_win->GetFirstExpandedItem();
5957 }
5958
5959 wxTreeItemId wxTreeListCtrl::GetNextExpanded(const wxTreeItemId& item) const
5960 {
5961 return m_main_win->GetNextExpanded(item);
5962 }
5963
5964 wxTreeItemId wxTreeListCtrl::GetPrevExpanded(const wxTreeItemId& item) const
5965 {
5966 return m_main_win->GetPrevExpanded(item);
5967 }
5968
5969 wxTreeItemId wxTreeListCtrl::GetFirstVisibleItem(bool fullRow) const
5970 {
5971 return GetFirstVisible(fullRow);
5972 }
5973 wxTreeItemId wxTreeListCtrl::GetFirstVisible(bool fullRow, bool within) const
5974 {
5975 return m_main_win->GetFirstVisible(fullRow, within);
5976 }
5977
5978 wxTreeItemId wxTreeListCtrl::GetLastVisible(bool fullRow, bool within) const
5979 {
5980 return m_main_win->GetLastVisible(fullRow, within);
5981 }
5982
5983 wxTreeItemId wxTreeListCtrl::GetNextVisible(const wxTreeItemId& item, bool fullRow, bool within) const
5984 {
5985 return m_main_win->GetNextVisible(item, fullRow, within);
5986 }
5987
5988 wxTreeItemId wxTreeListCtrl::GetPrevVisible(const wxTreeItemId& item, bool fullRow, bool within) const
5989 {
5990 return m_main_win->GetPrevVisible(item, fullRow, within);
5991 }
5992
5993 wxTreeItemId wxTreeListCtrl::AddRoot (const wxString& text, int image,
5994 int selectedImage, wxTreeItemData* data)
5995 {
5996 return m_main_win->AddRoot (text, image, selectedImage, data);
5997 }
5998
5999 wxTreeItemId wxTreeListCtrl::PrependItem(const wxTreeItemId& parent,
6000 const wxString& text, int image,
6001 int selectedImage,
6002 wxTreeItemData* data)
6003 {
6004 return m_main_win->PrependItem(parent, text, image, selectedImage, data);
6005 }
6006
6007 wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
6008 const wxTreeItemId& previous,
6009 const wxString& text, int image,
6010 int selectedImage,
6011 wxTreeItemData* data)
6012 {
6013 return m_main_win->InsertItem(parent, previous, text, image,
6014 selectedImage, data);
6015 }
6016
6017 wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent,
6018 size_t index,
6019 const wxString& text, int image,
6020 int selectedImage,
6021 wxTreeItemData* data)
6022 {
6023 return m_main_win->InsertItem(parent, index, text, image,
6024 selectedImage, data);
6025 }
6026
6027 wxTreeItemId wxTreeListCtrl::AppendItem(const wxTreeItemId& parent,
6028 const wxString& text, int image,
6029 int selectedImage,
6030 wxTreeItemData* data)
6031 {
6032 return m_main_win->AppendItem(parent, text, image, selectedImage, data);
6033 }
6034
6035 void wxTreeListCtrl::Delete(const wxTreeItemId& item)
6036 {
6037 m_main_win->Delete(item);
6038 }
6039
6040 void wxTreeListCtrl::DeleteChildren(const wxTreeItemId& item)
6041 {
6042 m_main_win->DeleteChildren(item);
6043 }
6044
6046 {
6047 m_main_win->DeleteRoot();
6048 }
6049
6050 void wxTreeListCtrl::Expand(const wxTreeItemId& item)
6051 {
6052 m_main_win->Expand(item);
6053 }
6054
6055 void wxTreeListCtrl::ExpandAll(const wxTreeItemId& item)
6056 {
6057 m_main_win->ExpandAll(item);
6058 }
6059
6060 void wxTreeListCtrl::Collapse(const wxTreeItemId& item)
6061 {
6062 m_main_win->Collapse(item);
6063 }
6064
6065 void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId& item)
6066 {
6067 m_main_win->CollapseAndReset(item);
6068 }
6069
6070 void wxTreeListCtrl::Toggle(const wxTreeItemId& item)
6071 {
6072 m_main_win->Toggle(item);
6073 }
6074
6076 {
6077 m_main_win->Unselect();
6078 }
6079
6081 {
6082 m_main_win->UnselectAll();
6083 }
6084
6085 bool wxTreeListCtrl::SelectItem(const wxTreeItemId& item, const wxTreeItemId& last,
6086 bool unselect_others)
6087 {
6088 return m_main_win->SelectItem (item, last, unselect_others);
6089 }
6090
6092 {
6093 m_main_win->SelectAll();
6094 }
6095
6096 void wxTreeListCtrl::EnsureVisible(const wxTreeItemId& item)
6097 {
6098 m_main_win->EnsureVisible(item);
6099 }
6100
6101 void wxTreeListCtrl::ScrollTo(const wxTreeItemId& item)
6102 {
6103 m_main_win->ScrollTo(item);
6104 }
6105
6106 wxTreeItemId wxTreeListCtrl::HitTest(const wxPoint& pos, int& flags, int& column)
6107 {
6108 wxPoint p = pos;
6109 return m_main_win->HitTest (p, flags, column);
6110 }
6111
6112 bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId& item, wxRect& rect,
6113 bool textOnly) const
6114 {
6115 return m_main_win->GetBoundingRect(item, rect, textOnly);
6116 }
6117
6118 void wxTreeListCtrl::EditLabel (const wxTreeItemId& item, int column)
6119 {
6120 m_main_win->EditLabel (item, column);
6121 }
6122 void wxTreeListCtrl::EndEdit(bool isCancelled)
6123 {
6124 m_main_win->EndEdit(isCancelled);
6125 }
6126
6127 int wxTreeListCtrl::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2)
6128 {
6129 // do the comparison here and not in m_main_win in order to allow
6130 // override in child class
6131 return wxStricmp(GetItemText(item1), GetItemText(item2));
6132 }
6133 int wxTreeListCtrl::OnCompareItems(const wxTreeItemId& item1, const wxTreeItemId& item2, int column)
6134 {
6135 // do the comparison here and not in m_main_win in order to allow
6136 // override in child class
6137 return wxStricmp(GetItemText(item1, column), GetItemText(item2, column));
6138 }
6139
6140 void wxTreeListCtrl::SortChildren(const wxTreeItemId& item, int column, bool reverseOrder)
6141 {
6142 m_main_win->SortChildren(item, column, reverseOrder);
6143 }
6144
6145 wxTreeItemId wxTreeListCtrl::FindItem (const wxTreeItemId& item, int column, const wxString& str, int mode)
6146 {
6147 return m_main_win->FindItem (item, column, str, mode);
6148 }
6149
6150 void wxTreeListCtrl::SetDragItem (const wxTreeItemId& item)
6151 {
6152 m_main_win->SetDragItem (item);
6153 }
6154
6155 bool wxTreeListCtrl::SetBackgroundColour(const wxColour& colour)
6156 {
6157 if (!m_main_win) return false;
6158 return m_main_win->SetBackgroundColour(colour);
6159 }
6160
6161 bool wxTreeListCtrl::SetForegroundColour(const wxColour& colour)
6162 {
6163 if (!m_main_win) return false;
6164 return m_main_win->SetForegroundColour(colour);
6165 }
6166
6168 {
6169 return m_main_win->GetColumnCount();
6170 }
6171
6172 void wxTreeListCtrl::SetColumnWidth(int column, int width)
6173 {
6174 m_header_win->SetColumnWidth (column, width);
6175 m_header_win->Refresh();
6176 }
6177
6179 {
6180 return m_header_win->GetColumnWidth(column);
6181 }
6182
6184 {
6185 m_main_win->SetMainColumn(column);
6186 }
6187
6189 {
6190 return m_main_win->GetMainColumn();
6191 }
6192
6193 void wxTreeListCtrl::SetColumnText(int column, const wxString& text)
6194 {
6195 m_header_win->SetColumnText (column, text);
6196 m_header_win->Refresh();
6197 }
6198
6199 wxString wxTreeListCtrl::GetColumnText(int column) const
6200 {
6201 return m_header_win->GetColumnText(column);
6202 }
6203
6205 {
6206 m_header_win->AddColumn (colInfo);
6207 DoHeaderLayout();
6208 }
6209
6211 {
6212 m_header_win->InsertColumn (before, colInfo);
6213 m_header_win->Refresh();
6214 }
6215
6217 {
6218 m_header_win->RemoveColumn (column);
6219 m_header_win->Refresh();
6220 }
6221
6222 void wxTreeListCtrl::SetColumn(int column, const wxTreeListColumnInfo& colInfo)
6223 {
6224 m_header_win->SetColumn (column, colInfo);
6225 m_header_win->Refresh();
6226 }
6227
6229 {
6230 return m_header_win->GetColumn(column);
6231 }
6232
6234 {
6235 return m_header_win->GetColumn(column);
6236 }
6237
6238 void wxTreeListCtrl::SetColumnImage(int column, int image)
6239 {
6240 m_header_win->SetColumn (column, GetColumn(column).SetImage(image));
6241 m_header_win->Refresh();
6242 }
6243
6245 {
6246 return m_header_win->GetColumn(column).GetImage();
6247 }
6248
6249 void wxTreeListCtrl::SetColumnEditable(int column, bool shown)
6250 {
6251 m_header_win->SetColumn (column, GetColumn(column).SetEditable(shown));
6252 }
6253
6254 void wxTreeListCtrl::SetColumnShown(int column, bool shown)
6255 {
6256 wxASSERT_MSG (column != GetMainColumn(), _T("The main column may not be hidden") );
6257 m_header_win->SetColumn (column, GetColumn(column).SetShown(GetMainColumn() == column ? true : shown));
6258 m_header_win->Refresh();
6259 }
6260
6262 {
6263 return m_header_win->GetColumn(column).IsEditable();
6264 }
6265
6266 bool wxTreeListCtrl::IsColumnShown(int column) const
6267 {
6268 return m_header_win->GetColumn(column).IsShown();
6269 }
6270
6271 void wxTreeListCtrl::SetColumnAlignment (int column, int flag)
6272 {
6273 m_header_win->SetColumn(column, GetColumn(column).SetAlignment(flag));
6274 m_header_win->Refresh();
6275 }
6276
6278 {
6279 return m_header_win->GetColumn(column).GetAlignment();
6280 }
6281
6282 void wxTreeListCtrl::Refresh(bool erase, const wxRect* rect)
6283 {
6284 m_main_win->Refresh (erase, rect);
6285 m_header_win->Refresh (erase, rect);
6286 }
6287
6289 {
6290 m_main_win->SetFocus();
6291 }
6292
6294 {
6295 wxSize bestSizeHeader = m_header_win->GetBestSize();
6296 wxSize bestSizeMain = m_main_win->GetBestSize();
6297 return wxSize (bestSizeHeader.x > bestSizeMain.x ? bestSizeHeader.x : bestSizeMain.x, bestSizeHeader.y + bestSizeMain.y);
6298 }
6299
6300 wxString wxTreeListCtrl::OnGetItemText( wxTreeItemData* WXUNUSED(item), long WXUNUSED(column)) const
6301 {
6302 return wxEmptyString;
6303 }
6304
6305 void wxTreeListCtrl::SetToolTip(const wxString& tip)
6306 {
6307 m_header_win->SetToolTip(tip);
6308 m_main_win->SetToolTip(tip);
6309 }
6310 void wxTreeListCtrl::SetToolTip(wxToolTip* tip)
6311 {
6312 m_header_win->SetToolTip(tip);
6313 m_main_win->SetToolTip(tip);
6314 }
6315
6316 void wxTreeListCtrl::SetItemToolTip(const wxTreeItemId& item, const wxString& tip)
6317 {
6318 m_main_win->SetItemToolTip(item, tip);
6319 }
6320
6321 void wxTreeListCtrl::SetCurrentItem(const wxTreeItemId& itemId)
6322 {
6323 m_main_win->SetCurrentItem(itemId);
6324 }
6325
6326 void wxTreeListCtrl::SetItemParent(const wxTreeItemId& parent, const wxTreeItemId& item)
6327 {
6328 m_main_win->SetItemParent(parent, item);
6329 }
6330
6331//-----------------------------------------------------------------------------
6332// wxTreeListCtrlXmlHandler - XRC support for wxTreeListCtrl
6333//-----------------------------------------------------------------------------
6334
6335#if wxUSE_XRC
6336
6337 IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrlXmlHandler, wxXmlResourceHandler)
6338
6339 wxTreeListCtrlXmlHandler::wxTreeListCtrlXmlHandler() : wxXmlResourceHandler()
6340 {
6341
6342#define wxTR_NO_BUTTONS 0x0000 // for convenience
6343#define wxTR_HAS_BUTTONS 0x0001 // draw collapsed/expanded btns
6344#define wxTR_NO_LINES 0x0004 // don't draw lines at all
6345#define wxTR_LINES_AT_ROOT 0x0008 // connect top-level nodes
6346#define wxTR_TWIST_BUTTONS 0x0010 // still used by wxTreeListCtrl
6347
6348#define wxTR_SINGLE 0x0000 // for convenience
6349#define wxTR_MULTIPLE 0x0020 // can select multiple items
6350#define wxTR_EXTENDED 0x0040 // NOT IMPLEMENTED
6351#define wxTR_HAS_VARIABLE_ROW_HEIGHT 0x0080 // what it says
6352
6353#define wxTR_EDIT_LABELS 0x0200 // can edit item labels
6354#define wxTR_ROW_LINES 0x0400 // put border around items
6355#define wxTR_HIDE_ROOT 0x0800 // don't display root node
6356
6357#define wxTR_FULL_ROW_HIGHLIGHT 0x2000 // highlight full horz space
6358
6359#ifdef __WXGTK20__
6360#define wxTR_DEFAULT_STYLE (wxTR_HAS_BUTTONS | wxTR_NO_LINES)
6361#else
6362#define wxTR_DEFAULT_STYLE (wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT)
6363#endif
6364
6365// wxTreeCtrl styles, taken from treebase.h
6366 XRC_ADD_STYLE(wxTR_NO_BUTTONS);
6367 XRC_ADD_STYLE(wxTR_HAS_BUTTONS);
6368 XRC_ADD_STYLE(wxTR_NO_LINES);
6369 XRC_ADD_STYLE(wxTR_LINES_AT_ROOT);
6370 XRC_ADD_STYLE(wxTR_TWIST_BUTTONS);
6371
6372 XRC_ADD_STYLE(wxTR_SINGLE);
6373 XRC_ADD_STYLE(wxTR_MULTIPLE);
6374#if WXWIN_COMPATIBILITY_2_8
6375 // according to wxWidgets release notes, wxTR_EXTENDED is deprecated
6376 XRC_ADD_STYLE(wxTR_EXTENDED);
6377#endif // WXWIN_COMPATIBILITY_2_8
6378 XRC_ADD_STYLE(wxTR_HAS_VARIABLE_ROW_HEIGHT);
6379
6380 XRC_ADD_STYLE(wxTR_EDIT_LABELS);
6381 XRC_ADD_STYLE(wxTR_ROW_LINES);
6382 XRC_ADD_STYLE(wxTR_HIDE_ROOT);
6383
6384 XRC_ADD_STYLE(wxTR_FULL_ROW_HIGHLIGHT);
6385
6386 XRC_ADD_STYLE(wxTR_DEFAULT_STYLE);
6387
6388// wxTreeListCtrl-specific styles
6389 XRC_ADD_STYLE(wxTR_COLUMN_LINES);
6390 XRC_ADD_STYLE(wxTR_VIRTUAL);
6391
6392// standard wxWidgets styles
6393 AddWindowStyles();
6394 }
6395
6396 wxObject* wxTreeListCtrlXmlHandler::DoCreateResource()
6397 {
6398 XRC_MAKE_INSTANCE(tlc, wxTreeListCtrl);
6399 tlc->Create(m_parentAsWindow, GetID(), GetPosition(), GetSize(), GetStyle(), wxDefaultValidator, GetName());
6400 SetupWindow(tlc);
6401 return tlc;
6402 }
6403
6404 bool wxTreeListCtrlXmlHandler::CanHandle(wxXmlNode* node)
6405 {
6406 return IsOfClass(node, wxT("TreeListCtrl"));
6407 }
6408
6409#endif // wxUSE_XRC
6410
6411#if wxCHECK_VERSION(2,9,0)
6412} // namespace wxcode
6413#endif
void OnKeyUp(wxKeyEvent &event)
void OnKillFocus(wxFocusEvent &event)
wxTreeListMainWindow * m_owner
void EndEdit(bool isCancelled)
void SetOwner(wxTreeListMainWindow *owner)
virtual bool Destroy()
wxString m_startValue
wxString * m_res
void OnChar(wxKeyEvent &event)
int GetWidth() const
Definition: treelistctrl.h:92
wxString GetText() const
Definition: treelistctrl.h:89
int GetAlignment() const
Definition: treelistctrl.h:95
int GetImage() const
Definition: treelistctrl.h:98
wxImageList * GetButtonsImageList() const
wxTreeItemId GetFirstChild(const wxTreeItemId &item, long &cookie) const
void AssignButtonsImageList(wxImageList *imageList)
bool HasChildren(const wxTreeItemId &item) const
void EditLabel(const wxTreeItemId &item)
Definition: treelistctrl.h:513
void ExpandAll(const wxTreeItemId &item)
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)
Definition: treelistctrl.h:234
void Collapse(const wxTreeItemId &item)
virtual bool SetForegroundColour(const wxColour &colour)
unsigned int GetIndent() const
virtual int OnCompareItems(const wxTreeItemId &item1, const wxTreeItemId &item2)
int GetColumnCount() const
void SetItemTextColour(const wxTreeItemId &item, const wxColour &colour)
void SetColumnAlignment(int column, int flag)
void Refresh(bool erase=TRUE, const wxRect *rect=NULL)
wxTreeItemId GetFirstVisible(bool fullRow=false, bool within=true) const
virtual wxSize DoGetBestSize() const
void SetImageList(wxImageList *imageList)
bool IsSelected(const wxTreeItemId &item) const
void SetMainColumn(int column)
wxTreeItemId AddRoot(const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void Delete(const wxTreeItemId &item)
void SetColumnWidth(int column, int width)
void DeleteChildren(const wxTreeItemId &item)
wxTreeItemId GetNextExpanded(const wxTreeItemId &item) const
void ScrollTo(const wxTreeItemId &item)
void SetItemData(const wxTreeItemId &item, wxTreeItemData *data)
wxTreeItemId HitTest(const wxPoint &point)
Definition: treelistctrl.h:500
virtual bool SetBackgroundColour(const wxColour &colour)
wxTreeItemId GetNextSibling(const wxTreeItemId &item) const
void SetColumnEditable(int column, bool edit=true)
void SetItemImage(const wxTreeItemId &item, int image, wxTreeItemIcon which=wxTreeItemIcon_Normal)
void AssignStateImageList(wxImageList *imageList)
wxTreeItemId FindItem(const wxTreeItemId &item, const wxString &str, int mode=0)
Definition: treelistctrl.h:534
void SetItemFont(const wxTreeItemId &item, const wxFont &font)
void RemoveColumn(int column)
void SetColumn(int column, const wxTreeListColumnInfo &colInfo)
wxTreeItemId GetFirstExpandedItem() const
void EndEdit(bool isCancelled)
bool IsExpanded(const wxTreeItemId &item) const
wxString GetItemText(const wxTreeItemId &item) const
Definition: treelistctrl.h:283
void SetItemHasChildren(const wxTreeItemId &item, bool has=true)
wxTreeItemId GetNext(const wxTreeItemId &item) const
void SetColumnShown(int column, bool shown=true)
void SetButtonsImageList(wxImageList *imageList)
wxTreeItemId GetPrevChild(const wxTreeItemId &item, long &cookie) const
void SetColumnText(int column, const wxString &text)
wxTreeItemId GetNextChild(const wxTreeItemId &item, long &cookie) const
long GetWindowStyle() const
bool GetBoundingRect(const wxTreeItemId &item, wxRect &rect, bool textOnly=false) const
wxTreeItemId AppendItem(const wxTreeItemId &parent, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void OnSize(wxSizeEvent &event)
wxTreeListHeaderWindow * GetHeaderWindow() const
Definition: treelistctrl.h:549
bool SelectItem(const wxTreeItemId &item, const wxTreeItemId &last=(wxTreeItemId *) NULL, bool unselect_others=true)
wxColour GetItemTextColour(const wxTreeItemId &item) const
bool IsColumnShown(int column) const
wxTreeItemId GetPrevVisible(const wxTreeItemId &item, bool fullRow=false, bool within=true) const
wxTreeItemId GetPrevExpanded(const wxTreeItemId &item) const
wxTreeItemId GetLastVisible(bool fullRow=false, bool within=true) const
void AddColumn(const wxString &text, int width=DEFAULT_COL_WIDTH, int flag=wxALIGN_LEFT, int image=-1, bool shown=true, bool edit=false)
Definition: treelistctrl.h:223
bool GetItemBold(const wxTreeItemId &item) const
int GetColumnImage(int column) const
void SetItemToolTip(const wxTreeItemId &item, const wxString &tip)
wxTreeItemId PrependItem(const wxTreeItemId &parent, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
wxFont GetItemFont(const wxTreeItemId &item) const
wxTreeListColumnInfo GetColumn(int column)
size_t GetSelections(wxArrayTreeItemIds &) const
void SetColumnImage(int column, int image)
wxTreeItemId GetPrevSibling(const wxTreeItemId &item) const
wxString GetColumnText(int column) const
wxTreeItemId InsertItem(const wxTreeItemId &parent, const wxTreeItemId &idPrevious, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
wxTreeItemId GetSelection() const
wxTreeItemId GetFirstVisibleItem(bool fullRow=false) const
int GetColumnAlignment(int column) const
void CalculateAndSetHeaderHeight()
void SetItemBackgroundColour(const wxTreeItemId &item, const wxColour &colour)
wxColour GetItemBackgroundColour(const wxTreeItemId &item) const
void SetToolTip(const wxString &tip)
wxTreeItemData * GetItemData(const wxTreeItemId &item) const
size_t GetChildrenCount(const wxTreeItemId &item, bool recursively=true)
void SortChildren(const wxTreeItemId &item, int column=-1, bool reverseOrder=false)
wxImageList * GetImageList() const
wxTreeItemId GetRootItem() const
void SetStateImageList(wxImageList *imageList)
void Toggle(const wxTreeItemId &item)
size_t GetCount() const
bool IsVisible(const wxTreeItemId &item, bool fullRow=false, bool within=true) const
int GetColumnWidth(int column) const
void SetDragItem(const wxTreeItemId &item=(wxTreeItemId *) NULL)
wxTreeItemId GetLastChild(const wxTreeItemId &item, long &cookie) const
void EnsureVisible(const wxTreeItemId &item)
virtual bool SetFont(const wxFont &font)
int GetMainColumn() const
void SetWindowStyle(const long styles)
void CollapseAndReset(const wxTreeItemId &item)
void SetItemBold(const wxTreeItemId &item, bool bold=true)
bool IsColumnEditable(int column) const
void SetLineSpacing(unsigned int spacing)
unsigned int GetLineSpacing() const
virtual wxString OnGetItemText(wxTreeItemData *item, long column) const
wxTreeItemId GetNextVisible(const wxTreeItemId &item, bool fullRow=false, bool within=true) const
wxImageList * GetStateImageList() const
void AssignImageList(wxImageList *imageList)
wxTreeItemId GetItemParent(const wxTreeItemId &item) const
void SetCurrentItem(const wxTreeItemId &item=(wxTreeItemId *) NULL)
void SetItemText(const wxTreeItemId &item, const wxString &text)
void SetIndent(unsigned int indent)
void SetItemParent(const wxTreeItemId &parent, const wxTreeItemId &item)
void Expand(const wxTreeItemId &item)
int GetItemImage(const wxTreeItemId &item, wxTreeItemIcon which=wxTreeItemIcon_Normal) const
wxTreeItemId GetPrev(const wxTreeItemId &item) const
wxTreeListMainWindow * m_owner
int GetColumnWidth(int column) const
wxTreeListColumnInfo & GetColumn(int column)
void RemoveColumn(int column)
wxString GetColumnText(int column) const
void OnEraseBackground(wxEraseEvent &WXUNUSED(event))
const wxCursor * m_resizeCursor
void SetColumnText(int column, const wxString &text)
wxArrayTreeListColumnInfo m_columns
void OnSetFocus(wxFocusEvent &event)
void OnMouse(wxMouseEvent &event)
int GetColumnAlignment(int column) const
void InsertColumn(int before, const wxTreeListColumnInfo &colInfo)
void SendListEvent(wxEventType type, wxPoint pos)
bool IsColumnShown(int column) const
void AddColumn(const wxTreeListColumnInfo &colInfo)
void SetColumnAlignment(int column, int flag)
void DoDrawRect(wxDC *dc, int x, int y, int w, int h)
void SetColumnWidth(int column, int width)
const wxCursor * m_currentCursor
bool IsColumnEditable(int column) const
void OnPaint(wxPaintEvent &event)
const wxTreeListColumnInfo & GetColumn(int column) const
void SetColumn(int column, const wxTreeListColumnInfo &info)
wxTreeItemAttr * m_attr
wxTreeItemData * m_data
void SetData(int column, wxTreeItemData *data)
unsigned char m_height
bool IsVirtual() const
wxTreeListItem * m_parent
void SetTextX(int text_x)
wxTreeItemData * GetData(int column) const
wxArrayString m_text
short m_images[wxTreeItemIcon_Max]
int GetHeight() const
size_t GetChildrenCount(bool recursively=true) const
bool IsExpanded() const
void SetItemParent(wxTreeListItem *parent)
wxTreeItemData * GetData() const
wxTreeListMainWindow * m_owner
wxTreeItemAttr * GetAttributes() const
wxArrayTreeListItems & GetChildren()
void GetSize(int &x, int &y, const wxTreeListMainWindow *)
void SetY(int y)
wxString * m_toolTip
bool IsBold(int column) const
void SetBold(int column, bool bold)
wxTreeItemAttr & Attr(int column)
const wxString * GetToolTip() const
void SetBold(bool bold)
int GetY() const
const wxString GetText(int column) const
bool HasChildren() const
void SetHilight(bool set=true)
void SetWidth(int width)
void SetImage(int column, int image, wxTreeItemIcon which)
wxTreeListItemCellAttrHash m_props_cell
void SetText(int column, const wxString &text)
void SetImage(int image, wxTreeItemIcon which)
bool IsBold() const
int GetWidth() const
void SetData(wxTreeItemData *data)
wxTreeListItemCellAttr m_props_row
wxTreeListItem * GetItemParent() const
bool IsSelected() const
wxTreeItemAttr * GetAttributes(int column) const
wxTreeListItem * HitTest(const wxPoint &point, const wxTreeListMainWindow *, int &flags, int &column, int level)
wxArrayTreeListItems m_children
int GetX() const
void SetX(int x)
void SetToolTip(const wxString &tip)
void SetHeight(int height)
int GetCurrentImage() const
void SetHasPlus(bool has=true)
int GetImage(wxTreeItemIcon which=wxTreeItemIcon_Normal) const
wxTreeItemAttr & Attr()
bool HasPlus() const
int GetTextX() const
void Insert(wxTreeListItem *child, size_t index)
int GetImage(int column, wxTreeItemIcon which=wxTreeItemIcon_Normal) const
void SetItemBold(const wxTreeItemId &item, bool bold=true)
void AssignButtonsImageList(wxImageList *imageList)
wxFont GetItemFont(const wxTreeItemId &item) const
size_t GetChildrenCount(const wxTreeItemId &item, bool recursively=true)
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"))
wxTreeItemId InsertItem(const wxTreeItemId &parent, const wxTreeItemId &idPrevious, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
unsigned short m_indent
void SetCurrentItem(const wxTreeItemId &item)
wxTreeItemId GetLastChild(const wxTreeItemId &item, long &cookie) const
void SetWindowStyle(const long styles)
void SetItemImage(const wxTreeItemId &item, int image, wxTreeItemIcon which=wxTreeItemIcon_Normal)
wxImageList * m_imageListButtons
size_t GetSelections(wxArrayTreeItemIds &) const
wxTreeItemId GetPrevVisible(const wxTreeItemId &item, bool fullRow, bool within) const
void CalculateSize(wxTreeListItem *item, wxDC &dc)
wxTreeItemId DoInsertItem(const wxTreeItemId &parent, size_t previous, const wxString &text, int image, int selectedImage, wxTreeItemData *data)
int GetItemWidth(int column, wxTreeListItem *item)
wxTreeItemId GetNextVisible(const wxTreeItemId &item, bool fullRow, bool within) const
bool IsExpanded(const wxTreeItemId &item) const
wxTreeItemId GetNext(const wxTreeItemId &item, bool fulltree=true) const
wxImageList * m_imageListNormal
int GetColumnCount() const
friend class wxTreeListItem
void SetItemData(const wxTreeItemId &item, wxTreeItemData *data)
void Delete(const wxTreeItemId &item)
wxColour GetItemTextColour(const wxTreeItemId &item) const
wxTreeItemId GetPrevExpanded(const wxTreeItemId &item) const
void SetItemTextColour(const wxTreeItemId &item, const wxColour &colour)
bool IsVirtual() const
bool HasButtons(void) const
wxTreeItemId GetNextSibling(const wxTreeItemId &item) const
virtual bool SetForegroundColour(const wxColour &colour)
void RefreshSubtree(wxTreeListItem *item)
void EditLabel(const wxTreeItemId &item, int column)
unsigned int GetLineSpacing() const
void FillArray(wxTreeListItem *, wxArrayTreeItemIds &) const
wxTreeItemId GetNextExpanded(const wxTreeItemId &item) const
wxTreeListItem * m_editItem
void ExpandAll(const wxTreeItemId &item)
wxTreeItemId FindItem(const wxTreeItemId &item, int column, const wxString &str, int mode=0)
wxTreeItemId GetFirstChild(const wxTreeItemId &item, long &cookie) const
wxTreeListItem * m_toolTipItem
void RefreshLine(wxTreeListItem *item)
void SetItemHasChildren(const wxTreeItemId &item, bool has=true)
wxTreeItemId GetNextChild(const wxTreeItemId &item, long &cookie) const
int GetCurrentColumn() const
void AssignStateImageList(wxImageList *imageList)
wxColour GetItemBackgroundColour(const wxTreeItemId &item) const
void OnScroll(wxScrollWinEvent &event)
void CalculateLevel(wxTreeListItem *item, wxDC &dc, int level, int &y, int x_maincol)
void CollapseAndReset(const wxTreeItemId &item)
bool HasChildren(const wxTreeItemId &item) const
void Toggle(const wxTreeItemId &item)
wxImageList * GetImageList() const
int GetItemImage(const wxTreeItemId &item, wxTreeItemIcon which=wxTreeItemIcon_Normal) const
void Collapse(const wxTreeItemId &item)
wxTreeItemId GetFirstExpandedItem() const
void SetItemToolTip(const wxTreeItemId &item, const wxString &tip)
void SetMainColumn(int column)
void PaintItem(wxTreeListItem *item, wxDC &dc)
bool TagNextChildren(wxTreeListItem *crt_item, wxTreeListItem *last_item)
void EndEdit(bool isCancelled)
wxImageList * m_imageListState
void OnMouse(wxMouseEvent &event)
void OnKillFocus(wxFocusEvent &event)
bool IsSelected(const wxTreeItemId &item) const
wxImageList * GetStateImageList() const
void SetToolTip(const wxString &tip)
void OnRenameAccept(bool isCancelled)
virtual ~wxTreeListMainWindow()
bool IsBold(const wxTreeItemId &item) const
wxString GetItemText(const wxTreeItemId &item, int column) const
void SetItemBackgroundColour(const wxTreeItemId &item, const wxColour &colour)
void SetButtonsImageList(wxImageList *imageList)
bool GetBoundingRect(const wxTreeItemId &item, wxRect &rect, bool textOnly=false) const
wxImageList * GetButtonsImageList() const
wxTreeListItem * m_dragItem
unsigned short m_linespacing
void SetImageList(wxImageList *imageList)
void OnChar(wxKeyEvent &event)
void OnIdle(wxIdleEvent &event)
void EnsureVisible(const wxTreeItemId &item)
wxTreeListItem * m_selectItem
wxTreeItemId AddRoot(const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void SetItemParent(const wxTreeItemId &parent, const wxTreeItemId &item)
void DoDeleteItem(wxTreeListItem *item)
bool IsVisible(const wxTreeItemId &item, bool fullRow, bool within=true) const
void Expand(const wxTreeItemId &item)
void ScrollTo(const wxTreeItemId &item)
unsigned int GetIndent() const
void SetItemFont(const wxTreeItemId &item, const wxFont &font)
void SetIndent(unsigned int indent)
wxTreeItemId GetLastVisible(bool fullRow, bool within) const
wxTreeItemId GetPrev(const wxTreeItemId &item, bool fulltree=true) const
void SetStateImageList(wxImageList *imageList)
bool SendEvent(wxEventType event_type, wxTreeListItem *item=NULL, wxTreeEvent *event=NULL)
wxTreeItemId GetFirstVisible(bool fullRow, bool within) const
bool TagAllChildrenUntilLast(wxTreeListItem *crt_item, wxTreeListItem *last_item)
wxBrush * m_hilightUnfocusedBrush
wxTreeItemId GetPrevSibling(const wxTreeItemId &item) const
wxTreeItemId GetPrevChild(const wxTreeItemId &item, long &cookie) const
int GetLineHeight(wxTreeListItem *item) const
virtual bool SetBackgroundColour(const wxColour &colour)
virtual bool SetFont(const wxFont &font)
virtual int OnCompareItems(const wxTreeItemId &item1, const wxTreeItemId &item2)
bool SelectItem(const wxTreeItemId &item, const wxTreeItemId &prev=(wxTreeItemId *) NULL, bool unselect_others=true)
wxTreeItemId AppendItem(const wxTreeItemId &parent, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
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"))
wxTreeItemId HitTest(const wxPoint &point)
void PaintLevel(wxTreeListItem *item, wxDC &dc, int level, int &y, int x_maincol)
void UnselectAllChildren(wxTreeListItem *item)
void DeleteChildren(const wxTreeItemId &item)
void OnSetFocus(wxFocusEvent &event)
void OnEraseBackground(wxEraseEvent &WXUNUSED(event))
void SetDragItem(const wxTreeItemId &item=(wxTreeItemId *) NULL)
void SortChildren(const wxTreeItemId &item, int column, bool reverseOrder)
size_t GetCount() const
wxTreeListItem * m_curItem
void OnPaint(wxPaintEvent &event)
friend class wxEditTextCtrl
wxTreeItemId GetItemParent(const wxTreeItemId &item) const
void AssignImageList(wxImageList *imageList)
int GetMainColumn() const
wxTreeListItem * m_rootItem
void SetLineSpacing(unsigned int spacing)
bool GetItemBold(const wxTreeItemId &item) const
wxTreeListItem * m_shiftItem
wxTreeItemId GetSelection() const
wxTreeItemId PrependItem(const wxTreeItemId &parent, const wxString &text, int image=-1, int selectedImage=-1, wxTreeItemData *data=NULL)
void OnCaptureLost(wxMouseCaptureLostEvent &WXUNUSED(event))
int GetBestColumnWidth(int column, wxTreeItemId parent=wxTreeItemId())
wxTreeListCtrl * m_owner
wxTreeItemId HitTest(const wxPoint &point, int &flags)
void SetItemText(const wxTreeItemId &item, int column, const wxString &text)
wxTreeItemId GetRootItem() const
wxEditTextCtrl * m_editControl
void RefreshSelectedUnder(wxTreeListItem *item)
wxTreeItemData * GetItemData(const wxTreeItemId &item) const
wxTreeListRenameTimer(wxTreeListMainWindow *owner)
wxTreeListMainWindow * m_owner
if(nReturnType==EIGENVALUES)
Definition: matfuncs.hpp:390
#define _T(x)
Definition: muParserDef.h:72
CONSTDATA date::last_spec last
Definition: date.h:1989
CONSTCD11 std::chrono::duration< Rep, Period > abs(std::chrono::duration< Rep, Period > d)
Definition: date.h:1317
char name[32]
Definition: resampler.cpp:371
static int LINKAGEMODE tree_ctrl_compare_func(wxTreeListItem **item1, wxTreeListItem **item2)
static wxTreeListColumnInfo wxInvalidTreeListColumnInfo
static const int HEADER_OFFSET_Y
static const int MARGIN
static const int BTNHEIGHT
static const int NO_IMAGE
static const int HEADER_OFFSET_X
static const int LINEHEIGHT
EVT_ERASE_BACKGROUND(wxTreeListHeaderWindow::OnEraseBackground) void wxTreeListHeaderWindow
END_EVENT_TABLE()
static const int MININDENT
static const int EXTRA_WIDTH
static const int FIND_TIMER_TICKS
static const int LINEATROOT
static const int DRAG_TIMER_TICKS
static wxTreeListMainWindow * s_treeBeingSorted
static const int RENAME_TIMER_TICKS
WX_DECLARE_OBJARRAY(wxTreeListColumnInfo, wxArrayTreeListColumnInfo)
static const int BTNWIDTH
WX_DEFINE_ARRAY(wxTreeListItem *, wxArrayTreeListItems)
WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo)
WX_DECLARE_HASH_MAP(int, wxTreeListItemCellAttr *, wxIntegerHash, wxIntegerEqual, wxTreeListItemCellAttrHash)
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
const wxChar * wxTreeListCtrlNameStr
static const int EXTRA_HEIGHT
class WXDLLEXPORT wxTreeListItem
Definition: treelistctrl.h:34
const int wxTL_MODE_NAV_VISIBLE
Definition: treelistctrl.h:128
const int wxTL_MODE_NAV_LEVEL
Definition: treelistctrl.h:129
class WXDLLEXPORT wxTreeListHeaderWindow
Definition: treelistctrl.h:35
const int wxTL_MODE_FIND_NOCASE
Definition: treelistctrl.h:134
const int wxTREE_HITTEST_ONITEMCOLUMN
Definition: treelistctrl.h:137
#define wxTR_COLUMN_LINES
Definition: treelistctrl.h:38
#define wxTR_VIRTUAL
Definition: treelistctrl.h:39
const int wxTL_MODE_NAV_EXPANDED
Definition: treelistctrl.h:127
const int wxTL_MODE_FIND_PARTIAL
Definition: treelistctrl.h:133