1 //---------------------------------------------------------------------------
2 // $RCSfile: wxTreeMultiCtrl.h,v $
3 // $Source: /cvs/creatis/bbtk/kernel/src/ThirdParty/wx/treemultictrl/wxTreeMultiCtrl.h,v $
5 // $Date: 2009/10/05 22:44:50 $
6 //---------------------------------------------------------------------------
7 // Author: Jorgen Bodde
8 // Copyright: (c) Jorgen Bodde
9 // License: wxWidgets License
10 //---------------------------------------------------------------------------
12 #ifndef __WXTREEMULTICTRL_H__
13 #define __WXTREEMULTICTRL_H__
15 /** \author Jorgen Bodde
18 This is the wxTreeMultiCtrl documentation guide. For the upcoming CodeShop project I am working on, I've
19 created a new control for wxWidgets (http://www.wxwidgets.com), with similar functionality as
20 the wxTreeCtrl. This control allows you to add multiple wxWindow based components in a tree shaped form,
21 with multiple root entries, which can contain multiple sub nodes, which can contain the visual controls
22 in the tree. The tree behaves very much like a wxTreeCtrl, showing all controls in a more structured way.
24 wxTreeMultiCtrl is freeware and distributed under the wxWidgets license. wxWidgets is THE toolkit for
25 (cross platform) C++ / Python programming!
27 \section how_work How does it work?
29 The internals of the wxTreeMultiCtrl are built up from a composite pattern. This pattern forms a recursive
30 tree where each end node can consist of a Window or a Node type. The Node type can consist out of multiple
31 Window or Node types, and the Window type is an end node which contains an assigned wxWindow to be displayed
34 The wxTreeMultiCtrl communicates to the developer by using the wxTreeMultiItem class, which is about the same
35 as a wxTreeItemId. The wxTreeMultiItem class can be used in add or delete operations, fold operations, find
36 operations, data get and set methods, and more. It helps the developer build up the tree, and later on,
37 get and set data from it.
39 \section what_dp What can it do and what not?
43 - Run-time addition / deletion of nodes, with an unlimited level depth
44 - Inheriting the control makes it possible to respond to the events of the added wxWindow based components
45 - Since all structured controls are owned by the wxTreeMultiCtrl, FindWindow will work, and all events can be captured
46 - Collapsing and expanding of a (or all) sub nodes from a specific location by method or by mouse click
47 - Typesafe getting or setting boolean, text or selection values by simply passing the window ID
48 - Run-time adjustment of spacing between controls
49 - Easy indenting of Window nodes
50 - Contain complex controls per Window node by putting them on a wxPanel, allowing custom behavior of those controls on the wxPanel
51 - Automatic deep background color adjustment of every window added, which means that every control on a wxPanel will be
52 automatically set to the proper background. There is also an exception flag for wxButton controls, so that they remain
53 their original color (if desired).
57 - Drag and drop support of individual nodes. Since the purpose was creating a tree shaped / property sheet kind of window,
58 dragging and dropping is not really desired behavior.
59 - No selection possible. Click on the controls to edit, double click on a container node to collapse and expand.
60 - Draw a selection border. Since there is no selection possible, no selection will be drawn
61 - Editing of captions like point and click in wxTreeCtrl. Again this is not desired behavior, because the (sub)
62 items are not really the same as wxTreeCtrl items.
64 Special thanks to Phil for testing, Julian Smart et al. for making this great toolkit!
68 #pragma interface "wxTreeMultiCtrl.cpp"
75 #include <wx/dynarray.h>
78 // classes for internal tree structure
79 #include "TreeMultiItemRoot.h"
81 // Flags for wxTreeMultCtrl use
82 #define wxTMC_DEFAULT_STYLE wxSIMPLE_BORDER
84 /** @defgroup wndflags wxTreeMultiWindowItem flags
85 These flags can be used in wxTreeMultiCtrl::AppendWindow as enforced flags, or in wxTreeMultiWindowInfo to set the flags
86 for repetetive adding of Window nodes with the same (or near same) properties.
89 /** When set, this flag will change the background of all the panels
90 and subwindows added to the wxTreeMultiCtrl. */
91 #define wxTMC_BG_ADJUST_CNT 0x000000001
92 /** When set, the background of the wxButton windows will also be changed.
93 This needs wxTMC_ADJUST_BACKGROUND to be set as well. */
94 #define wxTMC_BG_ADJUST_BTN 0x000000002
95 /** When set, all backgrounds from windows and buttons will be adjusted
96 to match the control background */
97 #define wxTMC_BG_ADJUST_ALL (wxTMC_BG_ADJUST_CNT | wxTMC_BG_ADJUST_BTN)
98 /** When set, the control added is resized horizontally over the complete
99 length. When the user resizes the window, the control is resized as well */
100 #define wxTMC_SPAN_WIDTH 0x000000004
105 #define wxTreeMultiCtrlNameStr wxT("wxTreeMultiCtrl")
107 #define WXTMC_GUTTER_DEFAULT 6 // gutter before and after image of [+] or [-]
108 #define WXTMC_YSPACING_DEFAULT 10 // per item 10 pixels spacing extra for every item
109 #define WXTMC_PIXELS_PER_UNIT 10
111 /** \defgroup hitflags wxTreeMultiCtrl HitTest flags
117 /// wxCoord was found in the gutter of the node (in front of the [+])
118 wxTMC_HITTEST_GUTTER = 1,
119 /// wxCoord was found inside a window, or behind it, on a Window node
120 wxTMC_HITTEST_WINDOW,
121 /// wxCoord was found on a caption of a Node or Root item
122 wxTMC_HITTEST_CAPTION,
123 /// wxCoord was found on a checkbox (only when item really has a checkbox)
124 wxTMC_HITTEST_CHECKBOX
130 /** @defgroup classes wxTreeMultiCtrl Classes
131 These classes are all the available classes in the wxTreeMultiCtrl you should know about.
137 /** \class wxTreeMultiItem
139 \brief An intermediate class which is used to return as 'item' value for the wxTreeMultiCtrl. This class
140 is comparable with wxTreeItemId.
142 The wxTreeMultiItem is used to pass information to the user about the tree node in question. It can also be used point out where the
143 subnodes should be added.
148 wxTreeMultiItem item = MyMultiTreeCtrl->AddRoot("This is the first root");
150 // now add a node to the root
152 MyMultiTreeCtrl->AppendWindow(item, new wxStaticText(MyMultiTreeCtrl, -1, "This is a static text");
157 The wxTreeMultiItem comes in three internal types which are used in the wxTreeMultiCtrl. For functions such as
158 wxTreeMultiCtrl::AddRoot, a Root item is returned. For functions such as wxTreeMultiCtrl::AppendWindow, a
159 Window node is returned. For functions such as wxTreeMultiCtrl::AppendNode, a Node item is returned.
161 \li A Root item represents a top level item. Special operations on this item is adding multiple nodes to it from a
164 \li A Node item represents a container item which has multiple sub items which can both be Window items, or Node items.
165 A root item is a special type of Node item, so all operations which are only for Node items, are also for Root items.
167 \li A Window node represents an end node, which points to a wxWindow which represents the visual contents of this node.
168 This type of node can hold any wxWindow derived class.
172 class wxTreeMultiItem
175 TreeMultiItemBase *_item;
177 /** Default declaration constructor, and should be used when declaring an item which gets assigned a new
178 value by e.g. wxTreeMultiCtrl::AppendNode. */
185 wxTreeMultiItem(TreeMultiItemBase *ptr) {
189 // Returns the TreeMultiItemBase class. This shoult *NOT* be
190 // used if you don't know what you are doing! This means never use it. */
191 TreeMultiItemBase *GetItem() const {
195 #endif // _NO_DOXYGEN_
197 /** The copy operator. Used in assigning one wxTreeMultiItem to another, usually in returning wxTreeMultiItem
198 classes from the wxTreeMultiCtrl.
200 void operator=(const wxTreeMultiItem &item) {
204 /** Equality operator. It returns true if the items are identical or if both items are invalid. */
205 bool operator==(wxTreeMultiItem const& item) const {return (this->GetItem() == item.GetItem());}
207 /** Inequality operator. It returns true if the items are different or one of them is invalid. */
208 bool operator!=(wxTreeMultiItem const& item) const {return (this->GetItem() != item.GetItem());}
210 /** Returns the parent of the current wxTreeMultiItem. This means the wxTreeMultiNode is returned. It can
211 be useful to check or clear the checkbox at this level. */
212 wxTreeMultiItem GetParent() const{
213 wxCHECK(IsOk(), wxTreeMultiItem(0));
214 return wxTreeMultiItem(_item->GetParent());
217 /** Validates if the wxTreeMultiItem is a valid instance to use in the wxTreeMultiCtrl. Returns TRUE when there
218 is a member value is associated with it, or FALSE when not. This value can also be checked when this class is returned from a wxTreeMultiCtrl operation. For example:
222 wxTreeMultiItem item = MyTreeMultiCtrl->FindNode("NAME");
225 // Found the node, now do something with it
239 /** Returns TRUE when the wxTreeMultiItem is a Window item. This means the item is both valid, and points to a
240 window node. This means it can be used in functions that expect a Window node. If the item is invalid or a Window
241 item, FALSE is returned
242 \sa wxTreeMultiCtrl::AppendWindow
244 bool IsWindowItem() const {
245 if(_item && _item->IsTreeMultiItemWindow())
250 /** Returns TRUE when the wxTreeMultiItem is a Node item. This means the item is both valid, and points to a
251 node element (i.e. setting the caption, counting node children, etc). If the item is invalid or not a Node
252 item, FALSE is returned.
253 When the item is actually a root item (specialised node type), this also returns TRUE.
254 \sa wxTreeMultiCtrl::AppendNode wxTreeMultiCtrl::AddRoot
256 bool IsNodeItem() const {
257 if(_item && (_item->IsTreeMultiItemNode() || _item->IsTreeMultiItemRoot()))
262 /** Returns True when the wxTreeMultiItem is a Root (top node) item. This means the item is both valid,
263 and points to a root element (this item is always shown as first node in the tree). A root node is
264 always visible, but can contain other collapsed children. If the item is invalid or not a Root node,
267 bool IsRootItem() const {
268 if(_item && _item->IsTreeMultiItemRoot())
273 /** Returns TRUE if the node is expanded, else FALSE if it is collapsed. If the item is not a Root or Node
274 item, an assertion failure is generated (in debug mode) or FALSE is returned (in release mode).
276 \sa wxTreeMultiCtrl::Expand, wxTreeMultiCtrl::Collapse, wxTreeMultiCtrl::CollapseAndReset
278 bool IsExpanded() const {
279 wxCHECK(_item, false);
280 TreeMultiItemNode *n = _item->IsTreeMultiItemNode();
283 return n->IsExpanded();
286 /** Returns true if this node is excluded from drawing. Please note that when this node is not visible
287 due to a higher excluded parent node but not literally excluded itself, it will return false (not excluded).
288 Use wxTreeMultiCtrl::GetExcludedParent() to get the node that hides this one. */
290 wxCHECK(_item, false);
291 return _item->IsExcluded();
294 /** Returns true if the item is selected.
295 Please note that currently only nodes can be selected.
297 bool IsSelected(void) const
299 wxCHECK(this->GetItem(),false);
300 return this->GetItem()->IsSelected();
302 /** Returns true if this node is visible. Please note that when this node is a child node of a collapsed
303 node, it is not visible. Also if this node is a child node of an excluded node, it is also not visible.
304 It does <b>NOT</b> return false when it's drawn somewhere outside of the visible area. */
306 wxCHECK(_item, false);
307 return _item->IsVisible();
312 WX_DECLARE_OBJARRAY(wxTreeMultiItem,wxArrayTreeMultiItem);
314 /** \class wxTreeMultiWindowInfo
316 \brief This class contains information for every Window node to be added.
318 This class can be used to modify the behaviour of the Window node to be added, and can be reused to pass along
319 upon every wxTreeMultiCtrl::AppendWindow call. For example:
323 wxTreeMultiWindowInfo wndinfo;
325 MyTreeMultiCtrl->AppendWindow(item, new wxStaticText(MyTreeMultiCtrl,
326 -1, "Press this button"), "", wndinfo));
328 // now adjust the spacing of our next window to add, by indenting
329 // 4 times the indent size
332 MyTreeMultiCtrl->AppendWindow(item, new wxButton(MyTreeMultiCtrl,
333 -1, "Apply"), "", wndinfo);
337 The class is created to prevent long parameter lists in the functions. Other ways to manipulate a newly added
340 \li Change top spacing of the Window node to be added
341 \li Change front spacing (indent) of the Window node
342 \li Set extra flags for this Window node
345 //-------------------------------------------------------------------------------------------------------------------
347 class wxTreeMultiWindowInfo
350 /** Flag that indicates that every window background in the assigned wxWindow needs te be overriden with the
351 current colour of the TreeMultiCtrl. This is a deep adjustment and will do every subwindow until none are
352 left. If 'false' no adjustment is done. For AppendWindow only */
354 /** Extra indent for every item that is added. This will add front spacing to the item's x calculation.
355 For AppendNode and AppendWindow. Spacing is added behind the collapse image not in front. */
359 /** Extra top spacing for every item that is added. This will add top spacing to the item's y calculation */
363 /** Checkstate for checkboxed property sheets */
369 wxTreeMultiWindowInfo(int flags, int frontSpacing, int topSpacing, bool checkState = false)
371 , _frontSpacing(frontSpacing)
372 , _frontSpacingOrg(frontSpacing)
373 , _topSpacing(topSpacing)
374 , _checkState(checkState)
376 wxTreeMultiWindowInfo(int flags, int frontSpacing, int topSpacing)
378 , _frontSpacing(frontSpacing)
379 , _frontSpacingOrg(frontSpacing)
380 , _topSpacing(topSpacing)
385 /** Adds indent to original front spacing and increments it with that value (quick extra indent).
386 The original value of FrontSpacing (see SetFrontSpacing() gets indented by multiplying
387 the 'num' factor (default = 1) times the indent value. So if the FrontSpacing was set to 10,
388 and Indent(2) is called, the new indent will be 30. (10 + 2 * 10). The original FrontSpacing
389 value is remembered, so calling Outdent(2) will bring it back to 10 (30 - (2*10). Calling
390 SetFrontSpacing with a new value, deletes the old indent.
392 \sa Outdent, SetFrontSpacing
394 int Indent(int num = 1) {
396 _frontSpacing += (_frontSpacingOrg * num);
397 return _frontSpacing;
399 /** Reduces indent a number of times, by subtracting 'num' times the original FrontSpacing value from
400 the current FrontSpacing value (quick extra indent). Thus if the original FrontSpacing was set to
401 10, and the current indent value is 40, Outdent(2) will do 40 - (2 * 10) = 20
403 \sa Indent, SetFrontSpacing
405 int Outdent(int num = 1) {
406 _frontSpacing -= (_frontSpacingOrg * num);
407 if(_frontSpacing < 0)
409 return _frontSpacing;
412 /** Sets FrontSpacing value. This also resets the current indent level. */
413 void SetFrontSpacing(int frontSpacing) {
414 _frontSpacing = frontSpacing;
415 _frontSpacingOrg = frontSpacing;
417 /** Gets front spacing. This will return the current indent level set. If Indent or Outdent is used,
418 this level represents the current Indent level.*/
419 int GetFrontSpacing() const {
420 return _frontSpacing;
423 /** Sets top spacing. This means the number of pixels spacing between the last node and the next one to
426 void SetTopSpacing(int topSpacing) {
427 _topSpacing = topSpacing;
432 /* Gets top spacing currently set. */
433 int GetTopSpacing() const {
437 /** Sets the current flags set, and returns previous flags state.
438 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
440 int SetFlags(int flags) {
446 /** Gets the current flags set.
447 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
449 int GetFlags() const {
453 /** Or's the given flag with the current flagset, and adds it. The
454 old flag set is returned before the OR is applied.
455 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
457 int AddFlag(int flag_mask) {
463 /** And's the given flag in a negated manner and removes this flag set from
464 the current flags. The old flag set is returned.
465 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
467 int RemoveFlag(int flag_mask) {
469 _flags &= ~(flag_mask);
474 /** Sets the default checkstate if checkboxes if SetCheckboxView is chosen. For all the
475 items to be added (even captions) this checkstate is chosen. The default checkstate
476 is false. <b>This needs USE_CHECKBOXVIEW set to YES, or CHECKBOXVIEW=1 during compile</b> */
477 void SetDefaultCheckState(bool checkState = true) {
478 _checkState = checkState;
481 /** Gets the default checkstate of the item. <b>This needs USE_CHECKBOXVIEW set to YES, or CHECKBOXVIEW=1 during compile</b>
482 \sa SetDefaultCheckState */
483 bool GetDefaultCheckState() const {
489 // Default info string
491 #define wxTreeMultiWindowInfoDefault wxTreeMultiWindowInfo(wxTMC_BG_ADJUST_CNT, 8, 0)
493 #define wxTreeMultiWindowInfoDefault wxTreeMultiWindowInfo(wxTMC_BG_ADJUST_ALL, 8, 0)
496 /** \class wxTreeMultiCtrl
498 \brief This is the visual control, which will contain all the logic for the tree mechanism.
500 The wxTreeMultiCtrl is the container class which can be filled in to get the tree shaped structure in
501 which the controls are displayed. The user can add / delete new nodes at runtime, expand or collapse
502 nodes, perform get or set actions on the controls inside, and iterate over the items.
504 A typical usage of the wxTreeCtrl is;
507 wxTreeMultiCtrl *tmc = new wxTreeMultiCtrl(this, -1);
510 wxTreeMultiItem item = tmc->AddRoot("This is the first root");
512 // create a wxTreeMultiWindowInfo object for indenting etc
513 wxTreeMultiWindowInfo wndinfo;
515 // add subitem to root
516 tmc->AppendWindow(item, new wxButton(tmc, -1, "Press this"), "", wndinfo);
522 tmc->AddWindow(item, new wxCheckBox(tmc, ID_MYCHECK, "Check this!"), "", wndinfo);
524 // now check the value of the checkbox
525 tmc->SetBooleanValue(ID_MYCHECK, true);
529 <b>IMPORTANT:</b> Every control added to the wxTreeMultiCtrl has to be child of the wxTreeMultiCtrl.
532 class wxTreeMultiCtrl: public wxScrolledWindow
534 DECLARE_DYNAMIC_CLASS(wxTreeMultiCtrl)
536 /** \todo When tab is pressed, the focus can get out of sight. This should be resolved by
537 catching the TAB, see what window is focussed, and scroll the window so it's visible */
539 TreeMultiItemRoot _root;
542 wxBitmap *_expandBmp, *_collBmp;
544 /** Delta Y for bitmap, to center it on the caption */
545 int _iconDeltaY, _checkDeltaY;
547 /* Caption height. This is the height of the font of this window */
550 /** The gutter spacing in front and back of the image. This determines the amount of spacing in front
554 /** The image width of the [+] / [-] icon. This is also calculated in the gutter */
557 /** The image height of the [+] / [-] icon. This is calculated as minimal size and to allign */
560 /** Max height. This is either the [+] bitmap or the checkbox */
564 /** Extra Y spacing between the items. */
567 /** Two step create prevention. Something with GetWindowSize freaks out when not actually created */
571 wxBitmap *_checkBmp, *_uncheckBmp, *_tristateBmp;
573 /** Toggles checkbox view. If true, every item created (caption or node) will be created with checkbox */
576 /** Height and weight for checkbox */
577 int _checkHeight, _checkWidth;
580 /** brush for highlighting nodes */
581 wxBrush* m_HilightBrush;
583 /** This captionFont is made equal to the font of the wxScrolledWindow. As extra the bold face
584 is set on it when this is wanted by the user (see flags) */
587 /** list of selected items */
588 wxArrayTreeMultiItem m_SelectedItems;
590 /** Does the actual collapsing / expanding. So that Expand and Collapse aren't using the same code twice */
591 void DoFold(TreeMultiItemBase *item, bool expand, bool recursive);
593 /** Redraws and recalculates the nodes from the current node. It will also clear all 'dirty' flags when
594 they are recalculated */
595 void RedrawFromNode(TreeMultiItemNode *n);
597 /** Redraws from parent node of this node */
598 void RedrawFromParentNode(TreeMultiItemBase *b);
600 /** Draws checkbox belonging to this node, in the given state */
601 void DrawCheckbox(TreeMultiItemBase *b, wxDC &dc, bool convertScrolled = false);
603 /** Recalculate the space needed based on every node. It goes as follows.
604 - A foldable node (TreeMultiItemNode) is as high as the 'Jg' y-size. This type only has a caption plus a
605 picture which explains the state ([+] or [-]), the width will be the caption length
606 - A window node will be as high as the y size of the window. The X size is the total length of the
608 - For every child node an indent will be added to the x size.
610 Only visible nodes will be recalculated. Non visible (collapsed) children will be skipped */
611 void RecalculateNodePositions();
613 /** Recurses into the whole tree and provides every node with the proper x and y values. All non visible items
614 are skipped (so when it encounters a collapsed node, it's children are not calculated). Returns the last Y */
615 int CalculateNodeDimensions(TreeMultiItemBase *b, int currentY, int level);
617 void DrawNode(TreeMultiItemBase *b, wxDC &dc);
619 /** Sets background colour of all the windows and subwindows in this wxWindow. This is very handy
620 for wxPanel derived classes which need to be made equal to the background colour of the wxTreeMultiCtrl */
621 void SetWindowBackgroundColour(wxWindow *wnd, const wxColour &col, int flags);
623 /** Shows or hides the assigned window (if there is any) */
624 void ShowTreeMultiWindow(TreeMultiItemWindow *window, bool show = true);
626 /** Goes down the tree, and if a window is not visible (thus all it's children aren't too) it will hide
627 the window so it is not shown on the control */
628 void UpdateAllWindowVisibility();
630 /** Hides tree multi window. It this is a TreeMultiItemNode, hide all subwindows as well. */
631 void UpdateTreeMultiWindowVisibility(TreeMultiItemBase *b, bool show);
633 /** Recalculates totally needed virtual size of the wxTreeMultiCtrl. It will scan for
634 the largest window, with the biggest size, and report that back */
635 void RecalculateVirtualSize();
637 /** Adjusts scrollbars in window, usually done after virtual size (x,y) is recalculated */
638 using wxScrolledWindow::AdjustScrollbars;
639 virtual void AdjustScrollbars(int x, int y);
641 /** Recalculates and accumulates largest x and y */
642 void RecalculateVirtualSizeFromNode(const TreeMultiItemNode *node, int &x, int &y);
644 /** Scans for TreeMultiItemBase node that contains x,y and in area returns a hittest constant to
645 indicate what matched */
646 TreeMultiItemBase *FindNodeByPoint(TreeMultiItemBase *b, wxPoint const& pt, int &area);
648 /** Scans for TreeMultiItemWindow that holds the wxWindow pointer. Does not scan in panels or does
649 a deep search. Reason, this function is used to advance to next TreeMultiItemWindow for focus
650 on this wxScrolledWindow. If a sub window is found, it will skip other windows on that same level */
651 wxTreeMultiItem FindWindowNode(wxWindow *wnd, TreeMultiItemNode *n = 0);
653 /** Finds next visible window item in chain. If not found use FindFirstVisibleItem to start from the
655 TreeMultiItemWindow *FindNextVisibleWindowItem(TreeMultiItemBase *b, int index = -1);
657 /** Adjust the centering of the bitmap icons (collapse / expand) when the caption font changes. They need to
658 be centered in the middle of the font, so a bit of deltaY adjustment is needed */
659 void AdjustIconsDeltaY();
661 /** Calculate the spanning of the individual nodes */
662 void CalculateNodeSpanning(TreeMultiItemBase *b);
665 /** Recurse to all the children and set the checkbox state (even when there is no checkbox) */
666 void SetRecursiveCheckState(TreeMultiItemNode *n, bool check);
668 /** From current checked node, all children will be scanned and the parent node of this node
669 will get tristate if the checked items are scattered (some are some aren't). If all nodes in this
670 node are checked, the parent node gets checked all the way up to the last one that matches
671 criteria. If all are cleared, parent node gets cleared */
672 void ScanTristateCheckstates(TreeMultiItemBase *b);
675 /** \name Private add and delete methods
679 /** Inserts a node into the parent's node at the specified position.
680 As this is a private method error checking is limited. Therefore, it has to be guaranteed that this method
681 is only called with a valid parent node pointer.
682 The position is zero based. In case the position is equal or larger than the current number of
683 parent's elements the new node is appended.
684 The newly inserted node is being returned.
686 wxTreeMultiItem InsertNode(TreeMultiItemNode* ParentPtr, size_t Position, wxString const& Caption, wxString const& Name);
688 /** Inserts a window into the parent's node at the specified position.
689 As this is a private method error checking is limited. Therefore, it has to be guaranteed that this method
690 is only called with a valid parent node and window pointer.
691 The position is zero based. In case the position is equal or larger than the current number of
692 parent's elements the new node is appended.
693 The newly inserted window is being returned.
695 wxTreeMultiItem InsertWindow(TreeMultiItemNode* ParentPtr, size_t Position, wxWindow* WindowPtr, wxString const& Name,
696 wxTreeMultiWindowInfo const& Info, int Flags);
706 //virtual void OnDraw(wxDC& dc);
707 void OnPaint(wxPaintEvent &event);
708 void OnMouseClick (wxMouseEvent& event);
709 void OnRightMouseClick(wxMouseEvent& Event);
710 void OnKey(wxKeyEvent &event);
711 void OnSize(wxSizeEvent &event);
713 /** Recalculates the spanning controls */
714 void RecalculateSpanSizes();
717 /** Two step constructor. Call Create when this constructor is called to build up the
721 : _create_called(false)
727 /** The default constructor. The style wxTAB_TRAVERSAL is enforced to make sure that the
728 focus handling is being done correctly. The styles to be used are styles valid for
729 the wxWindow and wxScrolledWindow
731 wxTreeMultiCtrl(wxWindow *parent, wxWindowID id = -1,
732 const wxPoint& pos = wxDefaultPosition,
733 const wxSize& size = wxDefaultSize,
734 long style = wxTMC_DEFAULT_STYLE,
735 const wxValidator &validator = wxDefaultValidator,
736 const wxString& name = wxTreeMultiCtrlNameStr)
737 : _style(style | wxTAB_TRAVERSAL)
738 , _create_called(false)
740 Create(parent, id, pos, size, style, validator, name);
744 virtual ~wxTreeMultiCtrl();
746 /** Two step creation. Whenever the control is created without any parameters, use Create to actually
747 create it. Don't access the control's public methods before this is called
749 \sa wxTreeMultiCtrl()
751 bool Create(wxWindow *parent, wxWindowID id = -1,
752 const wxPoint& pos = wxDefaultPosition,
753 const wxSize& size = wxDefaultSize,
754 long style = wxTMC_DEFAULT_STYLE,
755 const wxValidator &validator = wxDefaultValidator,
756 const wxString& name = wxTreeMultiCtrlNameStr);
761 /** @name Add and delete methods
762 To add and delete node items like a Root item, Window item or Node item. This allows the user to
763 manipulate the tree, and build it up.
767 /** Adds a root node to the wxTreeMultiItem. There can be many root nodes. Use this wxTreeMultiNode pointer to add
768 more subnodes to it. */
769 wxTreeMultiItem AddRoot(const wxString &caption, const wxString &name = wxEmptyString);
771 /** Adds a window to the tree control. Use this wxTreeMultiItem method to add a window class to the
772 current wxTreeMultiItem. The wxTreeMultiItem must point to a Node class. If this is not the case
773 an empty wxTreeMultiItem is returned. The mask is used to override the mask settings of the
774 wxTreeMultiWindowInfo class. This can be handy to set or clear extra flags only needed for certain
776 wxTreeMultiItem AppendWindow(const wxTreeMultiItem &ParentItem, wxWindow *window = NULL, const wxString &name = wxEmptyString,
777 wxTreeMultiWindowInfo const& info = wxTreeMultiWindowInfoDefault, int flags = 0);
779 /** Adds a window to the tree control. Use this method to add a window class at the specified position
780 of the parent's wxTreeMultiItem. In case the position is smaller than the current number of children all elements
781 are shifted upwards, otherwise the new window is appended to the parent's wxTreeMultiItem.
782 The parent wxTreeMultiItem must point to a Node class. If this is not the case an
783 empty wxTreeMultiItem is returned.
785 wxTreeMultiItem InsertWindow(wxTreeMultiItem const& ParentItem, size_t Position, wxWindow *window = NULL, wxString const& Name = wxEmptyString,
786 wxTreeMultiWindowInfo const& info = wxTreeMultiWindowInfoDefault, int flags = 0);
788 /** Adds a window to the tree control. Use this method to add a window class as the first element
789 of the parent's wxTreeMultiItem. The parent wxTreeMultiItem must point to a Node class. If this is not the case an
790 empty wxTreeMultiItem is returned.
792 wxTreeMultiItem PrependWindow(wxTreeMultiItem const& ParentItem, wxWindow *window = NULL, const wxString &name = wxEmptyString,
793 wxTreeMultiWindowInfo const& info = wxTreeMultiWindowInfoDefault, int flags = 0);
795 /** Adds a node to the tree control. Use this wxTreeMultiItem method to add a recursive subnode class as the last element
796 of the parent's wxTreeMultiItem. The parent wxTreeMultiItem must point to a Node class. If this is not the case
797 an empty wxTreeMultiItem is returned. A node can contain multiple nodes or window classes */
798 wxTreeMultiItem AppendNode(wxTreeMultiItem const& ParentItem, const wxString &caption = wxEmptyString,
799 const wxString &name = wxEmptyString);
801 /** Adds a node to the tree control. Use this method to add a recursive subnode class at the specified position
802 of the parent's wxTreeMultiItem. In case the position is smaller than the current number of nodes all elements
803 are shifted upwards, otherwise the new node is appended to the parent's wxTreeMultiItem.
804 The parent wxTreeMultiItem must point to a Node class. If this is not the case an
805 empty wxTreeMultiItem is returned. A node can contain multiple nodes or window classes.
807 wxTreeMultiItem InsertNode(wxTreeMultiItem const& ParentItem, size_t Position, wxString const& caption, wxString const& name);
809 /** Adds a node to the tree control. Use this method to add a recursive subnode class as the first element
810 of the parent's wxTreeMultiItem. The parent wxTreeMultiItem must point to a Node class. If this is not the case an
811 empty wxTreeMultiItem is returned. A node can contain multiple nodes or window classes.
813 wxTreeMultiItem PrependNode(wxTreeMultiItem const& ParentItem, wxString const& caption = wxEmptyString,
814 wxString const& name = wxEmptyString);
816 /** Delete item from the tree control. Whenever it is present, delete it. If not, return false. After
817 deletion the wxTreeMultiItem is 0, thus IsOk will return false */
818 bool Delete(wxTreeMultiItem &item);
820 /** Deletes all the items from the wxTreeMultiCtrl. */
821 void DeleteAllItems(void)
824 this->m_SelectedItems.Clear();
828 /** Deletes all children of the current node. The wxTreeMultiItem needs to be of type Node to
829 do this. Call GetParentNode to get the parent wxTreeMultiItem which is always a node. */
830 void DeleteChildren(const wxTreeMultiItem &item);
835 /** @name Expand and collapse methods
836 These methods are all for items of type Node.
840 /** Expand all nodes and subnodes. Recursive = true means all subnodes are also expanded. */
841 void ExpandNodes(bool recursive = false);
843 /** Collapses all nodes and subnodes. Recursive = true means all subnodes are also expanded. */
844 void CollapseNodes(bool recursive = false);
846 /** Expands given node, and with recursive, also the subnodes */
847 void Expand(const wxTreeMultiItem &item, bool recursive);
849 /** Collapses given node, and with recursive, also the subnodes. If this item is not a node, but a window.
850 the parent is resolved and that node is collapsed */
851 void Collapse(const wxTreeMultiItem &item, bool recursive);
853 /** Collapses this node and removes all children from it. This is only applicable on
854 wxTreeMultiItems which are of type Node / Root. */
855 void CollapseAndReset(const wxTreeMultiItem &item);
857 /** Folds the given node. The same as Expand and Collapse, but the state can be
858 given through a parameter */
859 void Fold(const wxTreeMultiItem &item, bool expand = true) {
863 Collapse(item, false);
869 /** @name Selection manipulation
870 These methods allow you to select, unselect or test wxTreeMultiItems on selection.
871 Currently only items of type Node can be manipulated.
875 /** Returns the number of selected items. */
876 size_t GetSelectedItemCount(void) const {return this->m_SelectedItems.GetCount();}
878 /** Returns the first selected item.
879 If there is no selected item an invalid tree multi item is returned.
881 wxTreeMultiItem GetFirstSelectedItem(void) const;
883 /** Returns the last selected item.
884 If there is no selected item an invalid tree multi item is returned.
886 wxTreeMultiItem GetLastSelectedItem(void) const;
888 /** Returns a selected item with the specified index.
889 If there is no selected item with the passed index an invalide tree multi item is returned.
891 wxTreeMultiItem GetSelectedItem(size_t Index) const;
893 /** Returns the index of the selected item.
894 In case the item is not selected "GetSelectedItemCount()" - which is an invalid index - is returned.
896 size_t GetSelectedItemIndex(wxTreeMultiItem const& Item) const;
898 /** Selects the specified item AND in case
899 - UnselectOthers is set all other selected items are going to be unselected;
900 - ExpandSelection is set all items between the last selected item and the passed item
901 are selected, too (in case there this is the first selection all items between the first root
902 and the passed item are selected).
903 If the passed item is already selected the other parameters are ignored.
904 Please not that currently only nodes can be selected, therefore, if any other item is passed nothing will happen.
906 void SelectItem(wxTreeMultiItem const& Item, bool UnselectOthers=true, bool ExpandSelection=false);
908 /** Unselect all selected items. */
909 void UnselectAll(void);
911 /** Unselect specified item */
912 void Unselect(wxTreeMultiItem const& Item);
918 /** \name Visibility manipulation
919 These methods allow you to manipulate a certain wxTreeMultiItem to temporarily exclude or to include
920 the node from drawing. Whenever it is excluded, all operations can still be performed, however
921 the node may not be visible.
925 /** Excludes this node from drawing. When excluded, the node will dissapear from the control but is still
926 physically present in the tree itself. If this node is a composite node with children, they will all be
927 hidden from the control. */
928 void Exclude(const wxTreeMultiItem &item);
930 /** Includes an excluded node. If the node was already present on the drawing, nothing happens. If the
931 node is included after exclusion it will become visible. If the parent node is still excluded or
932 collapsed (not visible) this will not show, until the parent node shows */
933 void Include(const wxTreeMultiItem &item);
935 /** Returns the parent that is responsible for excluding this node. If there is no excluded node as parent,
936 the wxTreeMultiItem is zero. */
937 wxTreeMultiItem GetExcludedParent(const wxTreeMultiItem &item);
942 /** Checks if the point is under one of the given areas. The returned areas can be
943 \li wxTMC_HITTEST_GUTTER If the front part of the item is clicked (where the node is)
944 \li wxTMC_HITTEST_WINDOW If located in the window area
945 \li wxTMC_HITTEST_CAPTION If located on the caption of the MultiTreeItemNode
947 Returned is the item which is located under the mouse, or none (IsOk = false) if
948 no item under the mouse */
949 wxTreeMultiItem HitTest(wxPoint const& pt, int &flags);
951 /** @name Find methods
952 These methods are used for finding a node in the wxTreeMultiCtrl.
956 /** Searches for the given name from the given level and lower. It will return a wxTreeMultiItem which needs
957 to be checked with IsOk() to see if it is a correct item. IsRootItem, IsNodeItem and IsWindowItem can be
958 used to determine the type of item. If the search returned an item which doesn't satisfy the query, you can
959 restart the search from here, with skip = true to skip the passed item. */
960 wxTreeMultiItem FindItem(const wxTreeMultiItem &item, const wxString &name, bool ignoreCase = false,
961 bool skipFirst = false);
963 /** Searches all nodes for the given name and returns the one found. This is a specialised method for FindItem */
964 wxTreeMultiItem FindItem(const wxString &name, bool ignoreCase = false) {
965 return FindItem(wxTreeMultiItem(&_root), name, ignoreCase, false);
971 /** Returns the number of children in this node. If this node is not of type Node, count returns -1. */
972 int GetChildrenCount(const wxTreeMultiItem &item) {
973 if(item.IsNodeItem())
975 TreeMultiItemNode *n = (TreeMultiItemNode *)item.GetItem();
976 return n->GetNodeCount();
982 /** This method finds the current focused window, and returns the wxTreeMultiItem that has this window as pointer.
983 If the wxTreeMultiItem is not ok, the focused window is on a sub-panel, or not on this control. If the focus is
984 on a sub-panel, this panel will handle the focusing. If you are still interested in this window, try
985 wxWindow::FindFocus which will always return with a pointer if a wxWindow has focus */
986 wxTreeMultiItem GetFocus();
988 /** @name Smart window Get/Set methods
989 These methods are used for quickly getting or setting primitive values, like boolean, string, or selections into
990 primitive wxWindow controls like a wxRadioButton, wxCheckBox, wxTextCtrl, etc.
991 The methods allow you to quickly set e.g. a boolean value by using the wxWindow ID of the control. A type
992 check is performed before the value is actually set with the appropiate method for it. If it fails, an assertion
993 will follow in debug mode. If you want to get values back similar get methods are present to return values.
994 This allows the user to quickly retrieve or set values by ID, without the fuss of remembering the pointer or
995 node ID of the wxTreeMultiCtrl.
999 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1000 AppendWindow). When it is found, it is type casted towards a <b>wxCheckBox</b> and <b>wxRadioButton</b>. Whenever
1001 it finds a proper type it will return true or false. Whenever no proper type is found, it will return with false.
1002 In debug mode it will cause an assertion failure as well, to notify the developer something is wrong.
1006 bool GetBooleanValue(int wndId);
1008 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1009 AppendWindow). When it is found, it is type casted towards a <b>wxTextCtrl</b>, <b>wxChoice</b> and <b>wxComboBox</b>.
1010 Whenever it finds a proper type it will return the (selected) text in the control. Whenever no proper type is found,
1011 it will return with an empty string. In debug mode it will cause an exception error as well if the cast fails, to notify
1012 the developer something is wrong.
1016 wxString GetTextValue(int wndId);
1018 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1019 AppendWindow). When it is found, it is type casted towards a <b>wxCheckBox</b> and <b>wxRadioButton</b>. Whenever
1020 it finds a proper type it set the control's value to the given boolean parameter. Nothing happens when no proper type
1021 is found, however debug mode it will cause an assertion failure.
1025 void SetBooleanValue(int wndId, bool value = true);
1027 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1028 AppendWindow). When it is found, it is type casted towards a <b>wxTextCtrl</b>. If the control is not found or
1029 of the wrong type, an asserion failure (in debug mode) follows. <br><i><b>NOTE: </b></i> this method
1030 does not typecast to wxChoice or wxComboBox and the likes. If a selection in one of those needs to be set, use the
1031 SetSelectionValue / GetSelectionValue combination.
1032 \sa GetTextValue, GetSelectionValue, SetSelectionValue
1034 void SetTextValue(int wndId, const wxString &value = wxEmptyString);
1036 /** Retrieves the wxWindow * associated with the wxTreeMultiItem. This only works for Window typed wxTreeMultiItem
1037 classes. If this type does not match or no window is associated, 0 is returned. */
1038 wxWindow *GetWindow(const wxTreeMultiItem &item) {
1039 if(item.IsWindowItem())
1040 return ((TreeMultiItemWindow *)item.GetItem())->GetWindow();
1044 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1045 AppendWindow). When it is found, it is type casted towards a <b>wxListBox, wxChoice, wxComboBox</b>.
1046 If the control is not found or of the wrong type, an asserion failure (in debug mode) follows. If it is found
1047 the selection is set in the control.
1049 void SetSelectionValue(int wndId, int sel);
1051 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1052 AppendWindow). When it is found, it is type casted towards a <b>wxListBox, wxChoice, wxComboBox</b>.
1053 If the control is not found or of the wrong type, an asserion failure (in debug mode) follows. In release mode -1 is
1054 returned. If it is found the selection index is returned.
1056 int GetSelectionValue(int wndId);
1058 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1059 AppendWindow). When it is found, it is type casted towards a <b>wxListBox</b>. If the control is not found or
1060 of the wrong type, an asserion failure (in debug mode) follows. In release mode an empty wxArrayInt is returned.
1061 If it is found the selections are stored in the wxArrayInt. This is only valid for wxListBox classes with multiple
1064 void GetSelectionValues(int wndId, wxArrayInt &sels);
1067 /** Gets the checkbox state of the wxTreeMultiItem pointed out by "item". If the item does not have a checkbox
1068 associated (or the item is not ok), it will return -1. If the checkbox is checked it will return 1,
1069 unchecked is 0, and tri-state (usually only for caption nodes) it will return 2. <b>This needs USE_CHECKBOXVIEW
1070 set to YES, or CHECKBOXVIEW=1 during compile</b>*/
1071 int GetCheckboxState(const wxTreeMultiItem &item, bool WXUNUSED(recursive)) {
1072 wxCHECK(item.IsOk(), -1);
1074 // return the checkbox state
1075 TreeMultiItemBase *b = item.GetItem();
1076 if(b->GetCheckbox())
1077 return b->GetCheckboxState();
1082 /** Sets the checkbox state of the wxTreeMultiItem pointed out by "item". If the item does not have a checkbox
1083 associated (or the item is not ok), it will simply ignore this. <b>This needs USE_CHECKBOXVIEW
1084 set to YES, or CHECKBOXVIEW=1 during compile</b>. Contributed by Thomas Enickl.*/
1085 void SetCheckboxState( const wxTreeMultiItem &item, int state ) {
1086 wxCHECK2( item.IsOk(), return );
1087 TreeMultiItemBase *b = item.GetItem();
1088 if( b->GetCheckbox() )
1089 b->SetCheckboxState( state );
1090 RedrawFromNode( item.GetItem()->GetParent() );
1097 /** @name Extended visibility and manipulation methods
1098 These methods alter the wxTreeMultiCtrl appearance, or add more functionality like checkboxes before each node.
1102 /** Sets the Y spacing of the wxTreeMultiCtrl to a new size. This can be used to give the controls some more
1103 spacing in between */
1105 void SetSpacingY(int spacingY) {
1108 _spacingY = spacingY;
1113 /** Gets the Y spacing of the wxTreeMultiCtrl. */
1115 int GetSpacingY() const {
1120 /** This method toggles the checkbox view mode. Whenever set to true, the next window item, or caption node item
1121 will get a checkbox. <b>This needs USE_CHECKBOXVIEW set to YES, or CHECKBOXVIEW=1 during compile</b>
1122 \sa GetCheckboxView, wxTreeMultiWindowInfo::SetDefaultCheckState
1124 void SetCheckboxView(bool value) {
1125 _checkboxView = value;
1128 /** This method returns the checkbox state currently used. <b>This needs USE_CHECKBOXVIEW set to YES, or
1129 CHECKBOXVIEW=1 during compile</b>
1130 \sa SetCheckboxView, wxTreeMultiWindowInfo::SetDefaultCheckState, wxTreeMultiWindowInfo::GetDefaultCheckState
1132 bool GetCheckboxView() const {
1133 return _checkboxView;
1140 /** @name Iteration methods
1141 Allows the user to iterate through a wxTreeMultiCtrl node, and get all the children or siblings.
1142 To start an iteration from the lowest level the functions GetFirstRoot and GetLastRoot are provided.
1146 /** Returns the first root. */
1147 wxTreeMultiItem GetFirstRoot(void) const {return wxTreeMultiItem(this->_root.First());}
1149 /** Returns the last root. */
1150 wxTreeMultiItem GetLastRoot(void) const {return wxTreeMultiItem(this->_root.Last());}
1152 /** Returns the items parent. */
1153 wxTreeMultiItem GetParent(wxTreeMultiItem const& item) const;
1155 /** Returns the first child of this node. The type of wxTreeMultiItem needs to be of Node. Whenever not succesful,
1156 the item returned is not ok (IsOk = false). Upon success, a valid child is returned. The cookie variable doesn't
1157 need to be initialized */
1158 wxTreeMultiItem GetFirstChild(const wxTreeMultiItem &item, int &cookie) const;
1160 /** Returns the next child in the iteration on the level of 'item'. Make sure you called GetFirstChild first
1161 before calling this one */
1162 wxTreeMultiItem GetNextChild(const wxTreeMultiItem &item, int &cookie) const;
1164 /** Returns the last child of this node. The type of 'item' needs to be of Node. Whenever not succesful,
1165 the item returned is not ok (IsOk = false). Upon success, a valid last child is returned. */
1166 wxTreeMultiItem GetLastChild(const wxTreeMultiItem &item) const;
1168 /** Returns the next sibling of the passed item. */
1169 wxTreeMultiItem GetNextSibling(wxTreeMultiItem const& item) const;
1171 /** Returns the previous sibling of the passed item. */
1172 wxTreeMultiItem GetPrevSibling(wxTreeMultiItem const& item) const;
1174 /** Returns the next item. "Next" is defined by the following order:
1175 - in case the current item has a child it is the first child of the current item;
1176 - in case the current item has a next sibling as the next sibling;
1177 - as the parent's (or one of its ancestor's) next sibling.
1179 wxTreeMultiItem GetNext(wxTreeMultiItem const& item) const;
1181 /** Returns the previous item. "Previous" is defined by the following order:
1182 - in case the current item has a child it is the last child of the current item;
1183 - in case the current item has a previous sibling it is the previous sibling;
1184 - as the parent's (or one of its ancestor's) previous sibling.
1186 wxTreeMultiItem GetPrevious(wxTreeMultiItem const& item) const;
1192 /** @name Get and set methods
1193 These methods allow you to set or get certain properties of the wxTreeMultiCtrl.
1197 /** Get the currently used font for the caption headers in the wxTreeMultiCtrl. If you want to alter this
1198 font, simply obtain it and copy it to a local font. After that, set this font back using SetCaptionFont()
1200 const wxFont &GetCaptionFont() const {
1201 return _captionFont;
1204 /** Sets the font to be used for the text caption headers. This triggers a complete redraw because x,y sizes can
1205 differ, and ofcourse all nodes need to be updated. You can call this method at any time not only at the
1207 void SetCaptionFont(const wxFont &font);
1212 void OnDraw(wxDC& dc);
1215 DECLARE_EVENT_TABLE()