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