2 # ---------------------------------------------------------------------
4 # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
6 # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7 # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8 # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
10 # This software is governed by the CeCILL-B license under French law and
11 # abiding by the rules of distribution of free software. You can use,
12 # modify and/ or redistribute the software under the terms of the CeCILL-B
13 # license as circulated by CEA, CNRS and INRIA at the following URL
14 # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15 # or in the file LICENSE.txt.
17 # As a counterpart to the access to the source code and rights to copy,
18 # modify and redistribute granted by the license, users are provided only
19 # with a limited warranty and the software's author, the holder of the
20 # economic rights, and the successive licensors have only limited
23 # The fact that you are presently reading this means that you have had
24 # knowledge of the CeCILL-B license and that you accept its terms.
25 # ------------------------------------------------------------------------ */
28 //---------------------------------------------------------------------------
29 // $RCSfile: wxTreeMultiCtrl.h,v $
30 // $Source: /cvs/creatis/bbtk/kernel/src/ThirdParty/wx/treemultictrl/wxTreeMultiCtrl.h,v $
32 // $Date: 2012/11/16 08:49:16 $
33 //---------------------------------------------------------------------------
34 // Author: Jorgen Bodde
35 // Copyright: (c) Jorgen Bodde
36 // License: wxWidgets License
37 //---------------------------------------------------------------------------
39 #ifndef __WXTREEMULTICTRL_H__
40 #define __WXTREEMULTICTRL_H__
42 /** \author Jorgen Bodde
45 This is the wxTreeMultiCtrl documentation guide. For the upcoming CodeShop project I am working on, I've
46 created a new control for wxWidgets (http://www.wxwidgets.com), with similar functionality as
47 the wxTreeCtrl. This control allows you to add multiple wxWindow based components in a tree shaped form,
48 with multiple root entries, which can contain multiple sub nodes, which can contain the visual controls
49 in the tree. The tree behaves very much like a wxTreeCtrl, showing all controls in a more structured way.
51 wxTreeMultiCtrl is freeware and distributed under the wxWidgets license. wxWidgets is THE toolkit for
52 (cross platform) C++ / Python programming!
54 \section how_work How does it work?
56 The internals of the wxTreeMultiCtrl are built up from a composite pattern. This pattern forms a recursive
57 tree where each end node can consist of a Window or a Node type. The Node type can consist out of multiple
58 Window or Node types, and the Window type is an end node which contains an assigned wxWindow to be displayed
61 The wxTreeMultiCtrl communicates to the developer by using the wxTreeMultiItem class, which is about the same
62 as a wxTreeItemId. The wxTreeMultiItem class can be used in add or delete operations, fold operations, find
63 operations, data get and set methods, and more. It helps the developer build up the tree, and later on,
64 get and set data from it.
66 \section what_dp What can it do and what not?
70 - Run-time addition / deletion of nodes, with an unlimited level depth
71 - Inheriting the control makes it possible to respond to the events of the added wxWindow based components
72 - Since all structured controls are owned by the wxTreeMultiCtrl, FindWindow will work, and all events can be captured
73 - Collapsing and expanding of a (or all) sub nodes from a specific location by method or by mouse click
74 - Typesafe getting or setting boolean, text or selection values by simply passing the window ID
75 - Run-time adjustment of spacing between controls
76 - Easy indenting of Window nodes
77 - Contain complex controls per Window node by putting them on a wxPanel, allowing custom behavior of those controls on the wxPanel
78 - Automatic deep background color adjustment of every window added, which means that every control on a wxPanel will be
79 automatically set to the proper background. There is also an exception flag for wxButton controls, so that they remain
80 their original color (if desired).
84 - Drag and drop support of individual nodes. Since the purpose was creating a tree shaped / property sheet kind of window,
85 dragging and dropping is not really desired behavior.
86 - No selection possible. Click on the controls to edit, double click on a container node to collapse and expand.
87 - Draw a selection border. Since there is no selection possible, no selection will be drawn
88 - Editing of captions like point and click in wxTreeCtrl. Again this is not desired behavior, because the (sub)
89 items are not really the same as wxTreeCtrl items.
91 Special thanks to Phil for testing, Julian Smart et al. for making this great toolkit!
95 #pragma interface "wxTreeMultiCtrl.cpp"
102 #include <wx/dynarray.h>
105 // classes for internal tree structure
106 #include "TreeMultiItemRoot.h"
108 // Flags for wxTreeMultCtrl use
109 #define wxTMC_DEFAULT_STYLE wxSIMPLE_BORDER
111 /** @defgroup wndflags wxTreeMultiWindowItem flags
112 These flags can be used in wxTreeMultiCtrl::AppendWindow as enforced flags, or in wxTreeMultiWindowInfo to set the flags
113 for repetetive adding of Window nodes with the same (or near same) properties.
116 /** When set, this flag will change the background of all the panels
117 and subwindows added to the wxTreeMultiCtrl. */
118 #define wxTMC_BG_ADJUST_CNT 0x000000001
119 /** When set, the background of the wxButton windows will also be changed.
120 This needs wxTMC_ADJUST_BACKGROUND to be set as well. */
121 #define wxTMC_BG_ADJUST_BTN 0x000000002
122 /** When set, all backgrounds from windows and buttons will be adjusted
123 to match the control background */
124 #define wxTMC_BG_ADJUST_ALL (wxTMC_BG_ADJUST_CNT | wxTMC_BG_ADJUST_BTN)
125 /** When set, the control added is resized horizontally over the complete
126 length. When the user resizes the window, the control is resized as well */
127 #define wxTMC_SPAN_WIDTH 0x000000004
132 #define wxTreeMultiCtrlNameStr wxT("wxTreeMultiCtrl")
134 #define WXTMC_GUTTER_DEFAULT 6 // gutter before and after image of [+] or [-]
135 #define WXTMC_YSPACING_DEFAULT 10 // per item 10 pixels spacing extra for every item
136 #define WXTMC_PIXELS_PER_UNIT 10
138 /** \defgroup hitflags wxTreeMultiCtrl HitTest flags
144 /// wxCoord was found in the gutter of the node (in front of the [+])
145 wxTMC_HITTEST_GUTTER = 1,
146 /// wxCoord was found inside a window, or behind it, on a Window node
147 wxTMC_HITTEST_WINDOW,
148 /// wxCoord was found on a caption of a Node or Root item
149 wxTMC_HITTEST_CAPTION,
150 /// wxCoord was found on a checkbox (only when item really has a checkbox)
151 wxTMC_HITTEST_CHECKBOX
157 /** @defgroup classes wxTreeMultiCtrl Classes
158 These classes are all the available classes in the wxTreeMultiCtrl you should know about.
164 /** \class wxTreeMultiItem
166 \brief An intermediate class which is used to return as 'item' value for the wxTreeMultiCtrl. This class
167 is comparable with wxTreeItemId.
169 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
170 subnodes should be added.
175 wxTreeMultiItem item = MyMultiTreeCtrl->AddRoot("This is the first root");
177 // now add a node to the root
179 MyMultiTreeCtrl->AppendWindow(item, new wxStaticText(MyMultiTreeCtrl, -1, "This is a static text");
184 The wxTreeMultiItem comes in three internal types which are used in the wxTreeMultiCtrl. For functions such as
185 wxTreeMultiCtrl::AddRoot, a Root item is returned. For functions such as wxTreeMultiCtrl::AppendWindow, a
186 Window node is returned. For functions such as wxTreeMultiCtrl::AppendNode, a Node item is returned.
188 \li A Root item represents a top level item. Special operations on this item is adding multiple nodes to it from a
191 \li A Node item represents a container item which has multiple sub items which can both be Window items, or Node items.
192 A root item is a special type of Node item, so all operations which are only for Node items, are also for Root items.
194 \li A Window node represents an end node, which points to a wxWindow which represents the visual contents of this node.
195 This type of node can hold any wxWindow derived class.
199 class wxTreeMultiItem
202 TreeMultiItemBase *_item;
204 /** Default declaration constructor, and should be used when declaring an item which gets assigned a new
205 value by e.g. wxTreeMultiCtrl::AppendNode. */
212 wxTreeMultiItem(TreeMultiItemBase *ptr) {
216 // Returns the TreeMultiItemBase class. This shoult *NOT* be
217 // used if you don't know what you are doing! This means never use it. */
218 TreeMultiItemBase *GetItem() const {
222 #endif // _NO_DOXYGEN_
224 /** The copy operator. Used in assigning one wxTreeMultiItem to another, usually in returning wxTreeMultiItem
225 classes from the wxTreeMultiCtrl.
227 void operator=(const wxTreeMultiItem &item) {
231 /** Equality operator. It returns true if the items are identical or if both items are invalid. */
232 bool operator==(wxTreeMultiItem const& item) const {return (this->GetItem() == item.GetItem());}
234 /** Inequality operator. It returns true if the items are different or one of them is invalid. */
235 bool operator!=(wxTreeMultiItem const& item) const {return (this->GetItem() != item.GetItem());}
237 /** Returns the parent of the current wxTreeMultiItem. This means the wxTreeMultiNode is returned. It can
238 be useful to check or clear the checkbox at this level. */
239 wxTreeMultiItem GetParent() const{
240 wxCHECK(IsOk(), wxTreeMultiItem(0));
241 return wxTreeMultiItem(_item->GetParent());
244 /** Validates if the wxTreeMultiItem is a valid instance to use in the wxTreeMultiCtrl. Returns TRUE when there
245 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:
249 wxTreeMultiItem item = MyTreeMultiCtrl->FindNode("NAME");
252 // Found the node, now do something with it
266 /** Returns TRUE when the wxTreeMultiItem is a Window item. This means the item is both valid, and points to a
267 window node. This means it can be used in functions that expect a Window node. If the item is invalid or a Window
268 item, FALSE is returned
269 \sa wxTreeMultiCtrl::AppendWindow
271 bool IsWindowItem() const {
272 if(_item && _item->IsTreeMultiItemWindow())
277 /** Returns TRUE when the wxTreeMultiItem is a Node item. This means the item is both valid, and points to a
278 node element (i.e. setting the caption, counting node children, etc). If the item is invalid or not a Node
279 item, FALSE is returned.
280 When the item is actually a root item (specialised node type), this also returns TRUE.
281 \sa wxTreeMultiCtrl::AppendNode wxTreeMultiCtrl::AddRoot
283 bool IsNodeItem() const {
284 if(_item && (_item->IsTreeMultiItemNode() || _item->IsTreeMultiItemRoot()))
289 /** Returns True when the wxTreeMultiItem is a Root (top node) item. This means the item is both valid,
290 and points to a root element (this item is always shown as first node in the tree). A root node is
291 always visible, but can contain other collapsed children. If the item is invalid or not a Root node,
294 bool IsRootItem() const {
295 if(_item && _item->IsTreeMultiItemRoot())
300 /** Returns TRUE if the node is expanded, else FALSE if it is collapsed. If the item is not a Root or Node
301 item, an assertion failure is generated (in debug mode) or FALSE is returned (in release mode).
303 \sa wxTreeMultiCtrl::Expand, wxTreeMultiCtrl::Collapse, wxTreeMultiCtrl::CollapseAndReset
305 bool IsExpanded() const {
306 wxCHECK(_item, false);
307 TreeMultiItemNode *n = _item->IsTreeMultiItemNode();
310 return n->IsExpanded();
313 /** Returns true if this node is excluded from drawing. Please note that when this node is not visible
314 due to a higher excluded parent node but not literally excluded itself, it will return false (not excluded).
315 Use wxTreeMultiCtrl::GetExcludedParent() to get the node that hides this one. */
317 wxCHECK(_item, false);
318 return _item->IsExcluded();
321 /** Returns true if the item is selected.
322 Please note that currently only nodes can be selected.
324 bool IsSelected(void) const
326 wxCHECK(this->GetItem(),false);
327 return this->GetItem()->IsSelected();
329 /** Returns true if this node is visible. Please note that when this node is a child node of a collapsed
330 node, it is not visible. Also if this node is a child node of an excluded node, it is also not visible.
331 It does <b>NOT</b> return false when it's drawn somewhere outside of the visible area. */
333 wxCHECK(_item, false);
334 return _item->IsVisible();
339 WX_DECLARE_OBJARRAY(wxTreeMultiItem,wxArrayTreeMultiItem);
341 /** \class wxTreeMultiWindowInfo
343 \brief This class contains information for every Window node to be added.
345 This class can be used to modify the behaviour of the Window node to be added, and can be reused to pass along
346 upon every wxTreeMultiCtrl::AppendWindow call. For example:
350 wxTreeMultiWindowInfo wndinfo;
352 MyTreeMultiCtrl->AppendWindow(item, new wxStaticText(MyTreeMultiCtrl,
353 -1, "Press this button"), "", wndinfo));
355 // now adjust the spacing of our next window to add, by indenting
356 // 4 times the indent size
359 MyTreeMultiCtrl->AppendWindow(item, new wxButton(MyTreeMultiCtrl,
360 -1, "Apply"), "", wndinfo);
364 The class is created to prevent long parameter lists in the functions. Other ways to manipulate a newly added
367 \li Change top spacing of the Window node to be added
368 \li Change front spacing (indent) of the Window node
369 \li Set extra flags for this Window node
372 //-------------------------------------------------------------------------------------------------------------------
374 class wxTreeMultiWindowInfo
377 /** Flag that indicates that every window background in the assigned wxWindow needs te be overriden with the
378 current colour of the TreeMultiCtrl. This is a deep adjustment and will do every subwindow until none are
379 left. If 'false' no adjustment is done. For AppendWindow only */
381 /** Extra indent for every item that is added. This will add front spacing to the item's x calculation.
382 For AppendNode and AppendWindow. Spacing is added behind the collapse image not in front. */
386 /** Extra top spacing for every item that is added. This will add top spacing to the item's y calculation */
390 /** Checkstate for checkboxed property sheets */
396 wxTreeMultiWindowInfo(int flags, int frontSpacing, int topSpacing, bool checkState = false)
398 , _frontSpacing(frontSpacing)
399 , _frontSpacingOrg(frontSpacing)
400 , _topSpacing(topSpacing)
401 , _checkState(checkState)
403 wxTreeMultiWindowInfo(int flags, int frontSpacing, int topSpacing)
405 , _frontSpacing(frontSpacing)
406 , _frontSpacingOrg(frontSpacing)
407 , _topSpacing(topSpacing)
412 /** Adds indent to original front spacing and increments it with that value (quick extra indent).
413 The original value of FrontSpacing (see SetFrontSpacing() gets indented by multiplying
414 the 'num' factor (default = 1) times the indent value. So if the FrontSpacing was set to 10,
415 and Indent(2) is called, the new indent will be 30. (10 + 2 * 10). The original FrontSpacing
416 value is remembered, so calling Outdent(2) will bring it back to 10 (30 - (2*10). Calling
417 SetFrontSpacing with a new value, deletes the old indent.
419 \sa Outdent, SetFrontSpacing
421 int Indent(int num = 1) {
423 _frontSpacing += (_frontSpacingOrg * num);
424 return _frontSpacing;
426 /** Reduces indent a number of times, by subtracting 'num' times the original FrontSpacing value from
427 the current FrontSpacing value (quick extra indent). Thus if the original FrontSpacing was set to
428 10, and the current indent value is 40, Outdent(2) will do 40 - (2 * 10) = 20
430 \sa Indent, SetFrontSpacing
432 int Outdent(int num = 1) {
433 _frontSpacing -= (_frontSpacingOrg * num);
434 if(_frontSpacing < 0)
436 return _frontSpacing;
439 /** Sets FrontSpacing value. This also resets the current indent level. */
440 void SetFrontSpacing(int frontSpacing) {
441 _frontSpacing = frontSpacing;
442 _frontSpacingOrg = frontSpacing;
444 /** Gets front spacing. This will return the current indent level set. If Indent or Outdent is used,
445 this level represents the current Indent level.*/
446 int GetFrontSpacing() const {
447 return _frontSpacing;
450 /** Sets top spacing. This means the number of pixels spacing between the last node and the next one to
453 void SetTopSpacing(int topSpacing) {
454 _topSpacing = topSpacing;
459 /* Gets top spacing currently set. */
460 int GetTopSpacing() const {
464 /** Sets the current flags set, and returns previous flags state.
465 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
467 int SetFlags(int flags) {
473 /** Gets the current flags set.
474 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
476 int GetFlags() const {
480 /** Or's the given flag with the current flagset, and adds it. The
481 old flag set is returned before the OR is applied.
482 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
484 int AddFlag(int flag_mask) {
490 /** And's the given flag in a negated manner and removes this flag set from
491 the current flags. The old flag set is returned.
492 \sa @link wndflags wxTreeMultiWindowInfo flags@endlink
494 int RemoveFlag(int flag_mask) {
496 _flags &= ~(flag_mask);
501 /** Sets the default checkstate if checkboxes if SetCheckboxView is chosen. For all the
502 items to be added (even captions) this checkstate is chosen. The default checkstate
503 is false. <b>This needs USE_CHECKBOXVIEW set to YES, or CHECKBOXVIEW=1 during compile</b> */
504 void SetDefaultCheckState(bool checkState = true) {
505 _checkState = checkState;
508 /** Gets the default checkstate of the item. <b>This needs USE_CHECKBOXVIEW set to YES, or CHECKBOXVIEW=1 during compile</b>
509 \sa SetDefaultCheckState */
510 bool GetDefaultCheckState() const {
516 // Default info string
518 #define wxTreeMultiWindowInfoDefault wxTreeMultiWindowInfo(wxTMC_BG_ADJUST_CNT, 8, 0)
520 #define wxTreeMultiWindowInfoDefault wxTreeMultiWindowInfo(wxTMC_BG_ADJUST_ALL, 8, 0)
523 /** \class wxTreeMultiCtrl
525 \brief This is the visual control, which will contain all the logic for the tree mechanism.
527 The wxTreeMultiCtrl is the container class which can be filled in to get the tree shaped structure in
528 which the controls are displayed. The user can add / delete new nodes at runtime, expand or collapse
529 nodes, perform get or set actions on the controls inside, and iterate over the items.
531 A typical usage of the wxTreeCtrl is;
534 wxTreeMultiCtrl *tmc = new wxTreeMultiCtrl(this, -1);
537 wxTreeMultiItem item = tmc->AddRoot("This is the first root");
539 // create a wxTreeMultiWindowInfo object for indenting etc
540 wxTreeMultiWindowInfo wndinfo;
542 // add subitem to root
543 tmc->AppendWindow(item, new wxButton(tmc, -1, "Press this"), "", wndinfo);
549 tmc->AddWindow(item, new wxCheckBox(tmc, ID_MYCHECK, "Check this!"), "", wndinfo);
551 // now check the value of the checkbox
552 tmc->SetBooleanValue(ID_MYCHECK, true);
556 <b>IMPORTANT:</b> Every control added to the wxTreeMultiCtrl has to be child of the wxTreeMultiCtrl.
559 class wxTreeMultiCtrl: public wxScrolledWindow
561 DECLARE_DYNAMIC_CLASS(wxTreeMultiCtrl)
563 /** \todo When tab is pressed, the focus can get out of sight. This should be resolved by
564 catching the TAB, see what window is focussed, and scroll the window so it's visible */
566 TreeMultiItemRoot _root;
569 wxBitmap *_expandBmp, *_collBmp;
571 /** Delta Y for bitmap, to center it on the caption */
572 int _iconDeltaY, _checkDeltaY;
574 /* Caption height. This is the height of the font of this window */
577 /** The gutter spacing in front and back of the image. This determines the amount of spacing in front
581 /** The image width of the [+] / [-] icon. This is also calculated in the gutter */
584 /** The image height of the [+] / [-] icon. This is calculated as minimal size and to allign */
587 /** Max height. This is either the [+] bitmap or the checkbox */
591 /** Extra Y spacing between the items. */
594 /** Two step create prevention. Something with GetWindowSize freaks out when not actually created */
598 wxBitmap *_checkBmp, *_uncheckBmp, *_tristateBmp;
600 /** Toggles checkbox view. If true, every item created (caption or node) will be created with checkbox */
603 /** Height and weight for checkbox */
604 int _checkHeight, _checkWidth;
607 /** brush for highlighting nodes */
608 wxBrush* m_HilightBrush;
610 /** This captionFont is made equal to the font of the wxScrolledWindow. As extra the bold face
611 is set on it when this is wanted by the user (see flags) */
614 /** list of selected items */
615 wxArrayTreeMultiItem m_SelectedItems;
617 /** Does the actual collapsing / expanding. So that Expand and Collapse aren't using the same code twice */
618 void DoFold(TreeMultiItemBase *item, bool expand, bool recursive);
620 /** Redraws and recalculates the nodes from the current node. It will also clear all 'dirty' flags when
621 they are recalculated */
622 void RedrawFromNode(TreeMultiItemNode *n);
624 /** Redraws from parent node of this node */
625 void RedrawFromParentNode(TreeMultiItemBase *b);
627 /** Draws checkbox belonging to this node, in the given state */
628 void DrawCheckbox(TreeMultiItemBase *b, wxDC &dc, bool convertScrolled = false);
630 /** Recalculate the space needed based on every node. It goes as follows.
631 - A foldable node (TreeMultiItemNode) is as high as the 'Jg' y-size. This type only has a caption plus a
632 picture which explains the state ([+] or [-]), the width will be the caption length
633 - A window node will be as high as the y size of the window. The X size is the total length of the
635 - For every child node an indent will be added to the x size.
637 Only visible nodes will be recalculated. Non visible (collapsed) children will be skipped */
638 void RecalculateNodePositions();
640 /** Recurses into the whole tree and provides every node with the proper x and y values. All non visible items
641 are skipped (so when it encounters a collapsed node, it's children are not calculated). Returns the last Y */
642 int CalculateNodeDimensions(TreeMultiItemBase *b, int currentY, int level);
644 void DrawNode(TreeMultiItemBase *b, wxDC &dc);
646 /** Sets background colour of all the windows and subwindows in this wxWindow. This is very handy
647 for wxPanel derived classes which need to be made equal to the background colour of the wxTreeMultiCtrl */
648 void SetWindowBackgroundColour(wxWindow *wnd, const wxColour &col, int flags);
650 /** Shows or hides the assigned window (if there is any) */
651 void ShowTreeMultiWindow(TreeMultiItemWindow *window, bool show = true);
653 /** Goes down the tree, and if a window is not visible (thus all it's children aren't too) it will hide
654 the window so it is not shown on the control */
655 void UpdateAllWindowVisibility();
657 /** Hides tree multi window. It this is a TreeMultiItemNode, hide all subwindows as well. */
658 void UpdateTreeMultiWindowVisibility(TreeMultiItemBase *b, bool show);
660 /** Recalculates totally needed virtual size of the wxTreeMultiCtrl. It will scan for
661 the largest window, with the biggest size, and report that back */
662 void RecalculateVirtualSize();
664 /** Adjusts scrollbars in window, usually done after virtual size (x,y) is recalculated */
665 using wxScrolledWindow::AdjustScrollbars;
666 virtual void AdjustScrollbars(int x, int y);
668 /** Recalculates and accumulates largest x and y */
669 void RecalculateVirtualSizeFromNode(const TreeMultiItemNode *node, int &x, int &y);
671 /** Scans for TreeMultiItemBase node that contains x,y and in area returns a hittest constant to
672 indicate what matched */
673 TreeMultiItemBase *FindNodeByPoint(TreeMultiItemBase *b, wxPoint const& pt, int &area);
675 /** Scans for TreeMultiItemWindow that holds the wxWindow pointer. Does not scan in panels or does
676 a deep search. Reason, this function is used to advance to next TreeMultiItemWindow for focus
677 on this wxScrolledWindow. If a sub window is found, it will skip other windows on that same level */
678 wxTreeMultiItem FindWindowNode(wxWindow *wnd, TreeMultiItemNode *n = 0);
680 /** Finds next visible window item in chain. If not found use FindFirstVisibleItem to start from the
682 TreeMultiItemWindow *FindNextVisibleWindowItem(TreeMultiItemBase *b, int index = -1);
684 /** Adjust the centering of the bitmap icons (collapse / expand) when the caption font changes. They need to
685 be centered in the middle of the font, so a bit of deltaY adjustment is needed */
686 void AdjustIconsDeltaY();
688 /** Calculate the spanning of the individual nodes */
689 void CalculateNodeSpanning(TreeMultiItemBase *b);
692 /** Recurse to all the children and set the checkbox state (even when there is no checkbox) */
693 void SetRecursiveCheckState(TreeMultiItemNode *n, bool check);
695 /** From current checked node, all children will be scanned and the parent node of this node
696 will get tristate if the checked items are scattered (some are some aren't). If all nodes in this
697 node are checked, the parent node gets checked all the way up to the last one that matches
698 criteria. If all are cleared, parent node gets cleared */
699 void ScanTristateCheckstates(TreeMultiItemBase *b);
702 /** \name Private add and delete methods
706 /** Inserts a node into the parent's node at the specified position.
707 As this is a private method error checking is limited. Therefore, it has to be guaranteed that this method
708 is only called with a valid parent node pointer.
709 The position is zero based. In case the position is equal or larger than the current number of
710 parent's elements the new node is appended.
711 The newly inserted node is being returned.
713 wxTreeMultiItem InsertNode(TreeMultiItemNode* ParentPtr, size_t Position, wxString const& Caption, wxString const& Name);
715 /** Inserts a window into the parent's node at the specified position.
716 As this is a private method error checking is limited. Therefore, it has to be guaranteed that this method
717 is only called with a valid parent node and window pointer.
718 The position is zero based. In case the position is equal or larger than the current number of
719 parent's elements the new node is appended.
720 The newly inserted window is being returned.
722 wxTreeMultiItem InsertWindow(TreeMultiItemNode* ParentPtr, size_t Position, wxWindow* WindowPtr, wxString const& Name,
723 wxTreeMultiWindowInfo const& Info, int Flags);
733 //virtual void OnDraw(wxDC& dc);
734 void OnPaint(wxPaintEvent &event);
735 void OnMouseClick (wxMouseEvent& event);
736 void OnRightMouseClick(wxMouseEvent& Event);
737 void OnKey(wxKeyEvent &event);
738 void OnSize(wxSizeEvent &event);
740 /** Recalculates the spanning controls */
741 void RecalculateSpanSizes();
744 /** Two step constructor. Call Create when this constructor is called to build up the
748 : _create_called(false)
754 /** The default constructor. The style wxTAB_TRAVERSAL is enforced to make sure that the
755 focus handling is being done correctly. The styles to be used are styles valid for
756 the wxWindow and wxScrolledWindow
758 wxTreeMultiCtrl(wxWindow *parent, wxWindowID id = -1,
759 const wxPoint& pos = wxDefaultPosition,
760 const wxSize& size = wxDefaultSize,
761 long style = wxTMC_DEFAULT_STYLE,
762 const wxValidator &validator = wxDefaultValidator,
763 const wxString& name = wxTreeMultiCtrlNameStr)
764 : _style(style | wxTAB_TRAVERSAL)
765 , _create_called(false)
767 Create(parent, id, pos, size, style, validator, name);
771 virtual ~wxTreeMultiCtrl();
773 /** Two step creation. Whenever the control is created without any parameters, use Create to actually
774 create it. Don't access the control's public methods before this is called
776 \sa wxTreeMultiCtrl()
778 bool Create(wxWindow *parent, wxWindowID id = -1,
779 const wxPoint& pos = wxDefaultPosition,
780 const wxSize& size = wxDefaultSize,
781 long style = wxTMC_DEFAULT_STYLE,
782 const wxValidator &validator = wxDefaultValidator,
783 const wxString& name = wxTreeMultiCtrlNameStr);
788 /** @name Add and delete methods
789 To add and delete node items like a Root item, Window item or Node item. This allows the user to
790 manipulate the tree, and build it up.
794 /** Adds a root node to the wxTreeMultiItem. There can be many root nodes. Use this wxTreeMultiNode pointer to add
795 more subnodes to it. */
796 wxTreeMultiItem AddRoot(const wxString &caption, const wxString &name = wxEmptyString);
798 /** Adds a window to the tree control. Use this wxTreeMultiItem method to add a window class to the
799 current wxTreeMultiItem. The wxTreeMultiItem must point to a Node class. If this is not the case
800 an empty wxTreeMultiItem is returned. The mask is used to override the mask settings of the
801 wxTreeMultiWindowInfo class. This can be handy to set or clear extra flags only needed for certain
803 wxTreeMultiItem AppendWindow(const wxTreeMultiItem &ParentItem, wxWindow *window = NULL, const wxString &name = wxEmptyString,
804 wxTreeMultiWindowInfo const& info = wxTreeMultiWindowInfoDefault, int flags = 0);
806 /** Adds a window to the tree control. Use this method to add a window class at the specified position
807 of the parent's wxTreeMultiItem. In case the position is smaller than the current number of children all elements
808 are shifted upwards, otherwise the new window is appended to the parent's wxTreeMultiItem.
809 The parent wxTreeMultiItem must point to a Node class. If this is not the case an
810 empty wxTreeMultiItem is returned.
812 wxTreeMultiItem InsertWindow(wxTreeMultiItem const& ParentItem, size_t Position, wxWindow *window = NULL, wxString const& Name = wxEmptyString,
813 wxTreeMultiWindowInfo const& info = wxTreeMultiWindowInfoDefault, int flags = 0);
815 /** Adds a window to the tree control. Use this method to add a window class as the first element
816 of the parent's wxTreeMultiItem. The parent wxTreeMultiItem must point to a Node class. If this is not the case an
817 empty wxTreeMultiItem is returned.
819 wxTreeMultiItem PrependWindow(wxTreeMultiItem const& ParentItem, wxWindow *window = NULL, const wxString &name = wxEmptyString,
820 wxTreeMultiWindowInfo const& info = wxTreeMultiWindowInfoDefault, int flags = 0);
822 /** Adds a node to the tree control. Use this wxTreeMultiItem method to add a recursive subnode class as the last element
823 of the parent's wxTreeMultiItem. The parent wxTreeMultiItem must point to a Node class. If this is not the case
824 an empty wxTreeMultiItem is returned. A node can contain multiple nodes or window classes */
825 wxTreeMultiItem AppendNode(wxTreeMultiItem const& ParentItem, const wxString &caption = wxEmptyString,
826 const wxString &name = wxEmptyString);
828 /** Adds a node to the tree control. Use this method to add a recursive subnode class at the specified position
829 of the parent's wxTreeMultiItem. In case the position is smaller than the current number of nodes all elements
830 are shifted upwards, otherwise the new node is appended to the parent's wxTreeMultiItem.
831 The parent wxTreeMultiItem must point to a Node class. If this is not the case an
832 empty wxTreeMultiItem is returned. A node can contain multiple nodes or window classes.
834 wxTreeMultiItem InsertNode(wxTreeMultiItem const& ParentItem, size_t Position, wxString const& caption, wxString const& name);
836 /** Adds a node to the tree control. Use this method to add a recursive subnode class as the first element
837 of the parent's wxTreeMultiItem. The parent wxTreeMultiItem must point to a Node class. If this is not the case an
838 empty wxTreeMultiItem is returned. A node can contain multiple nodes or window classes.
840 wxTreeMultiItem PrependNode(wxTreeMultiItem const& ParentItem, wxString const& caption = wxEmptyString,
841 wxString const& name = wxEmptyString);
843 /** Delete item from the tree control. Whenever it is present, delete it. If not, return false. After
844 deletion the wxTreeMultiItem is 0, thus IsOk will return false */
845 bool Delete(wxTreeMultiItem &item);
847 /** Deletes all the items from the wxTreeMultiCtrl. */
848 void DeleteAllItems(void)
851 this->m_SelectedItems.Clear();
855 /** Deletes all children of the current node. The wxTreeMultiItem needs to be of type Node to
856 do this. Call GetParentNode to get the parent wxTreeMultiItem which is always a node. */
857 void DeleteChildren(const wxTreeMultiItem &item);
862 /** @name Expand and collapse methods
863 These methods are all for items of type Node.
867 /** Expand all nodes and subnodes. Recursive = true means all subnodes are also expanded. */
868 void ExpandNodes(bool recursive = false);
870 /** Collapses all nodes and subnodes. Recursive = true means all subnodes are also expanded. */
871 void CollapseNodes(bool recursive = false);
873 /** Expands given node, and with recursive, also the subnodes */
874 void Expand(const wxTreeMultiItem &item, bool recursive);
876 /** Collapses given node, and with recursive, also the subnodes. If this item is not a node, but a window.
877 the parent is resolved and that node is collapsed */
878 void Collapse(const wxTreeMultiItem &item, bool recursive);
880 /** Collapses this node and removes all children from it. This is only applicable on
881 wxTreeMultiItems which are of type Node / Root. */
882 void CollapseAndReset(const wxTreeMultiItem &item);
884 /** Folds the given node. The same as Expand and Collapse, but the state can be
885 given through a parameter */
886 void Fold(const wxTreeMultiItem &item, bool expand = true) {
890 Collapse(item, false);
896 /** @name Selection manipulation
897 These methods allow you to select, unselect or test wxTreeMultiItems on selection.
898 Currently only items of type Node can be manipulated.
902 /** Returns the number of selected items. */
903 size_t GetSelectedItemCount(void) const {return this->m_SelectedItems.GetCount();}
905 /** Returns the first selected item.
906 If there is no selected item an invalid tree multi item is returned.
908 wxTreeMultiItem GetFirstSelectedItem(void) const;
910 /** Returns the last selected item.
911 If there is no selected item an invalid tree multi item is returned.
913 wxTreeMultiItem GetLastSelectedItem(void) const;
915 /** Returns a selected item with the specified index.
916 If there is no selected item with the passed index an invalide tree multi item is returned.
918 wxTreeMultiItem GetSelectedItem(size_t Index) const;
920 /** Returns the index of the selected item.
921 In case the item is not selected "GetSelectedItemCount()" - which is an invalid index - is returned.
923 size_t GetSelectedItemIndex(wxTreeMultiItem const& Item) const;
925 /** Selects the specified item AND in case
926 - UnselectOthers is set all other selected items are going to be unselected;
927 - ExpandSelection is set all items between the last selected item and the passed item
928 are selected, too (in case there this is the first selection all items between the first root
929 and the passed item are selected).
930 If the passed item is already selected the other parameters are ignored.
931 Please not that currently only nodes can be selected, therefore, if any other item is passed nothing will happen.
933 void SelectItem(wxTreeMultiItem const& Item, bool UnselectOthers=true, bool ExpandSelection=false);
935 /** Unselect all selected items. */
936 void UnselectAll(void);
938 /** Unselect specified item */
939 void Unselect(wxTreeMultiItem const& Item);
945 /** \name Visibility manipulation
946 These methods allow you to manipulate a certain wxTreeMultiItem to temporarily exclude or to include
947 the node from drawing. Whenever it is excluded, all operations can still be performed, however
948 the node may not be visible.
952 /** Excludes this node from drawing. When excluded, the node will dissapear from the control but is still
953 physically present in the tree itself. If this node is a composite node with children, they will all be
954 hidden from the control. */
955 void Exclude(const wxTreeMultiItem &item);
957 /** Includes an excluded node. If the node was already present on the drawing, nothing happens. If the
958 node is included after exclusion it will become visible. If the parent node is still excluded or
959 collapsed (not visible) this will not show, until the parent node shows */
960 void Include(const wxTreeMultiItem &item);
962 /** Returns the parent that is responsible for excluding this node. If there is no excluded node as parent,
963 the wxTreeMultiItem is zero. */
964 wxTreeMultiItem GetExcludedParent(const wxTreeMultiItem &item);
969 /** Checks if the point is under one of the given areas. The returned areas can be
970 \li wxTMC_HITTEST_GUTTER If the front part of the item is clicked (where the node is)
971 \li wxTMC_HITTEST_WINDOW If located in the window area
972 \li wxTMC_HITTEST_CAPTION If located on the caption of the MultiTreeItemNode
974 Returned is the item which is located under the mouse, or none (IsOk = false) if
975 no item under the mouse */
976 wxTreeMultiItem HitTest(wxPoint const& pt, int &flags);
978 /** @name Find methods
979 These methods are used for finding a node in the wxTreeMultiCtrl.
983 /** Searches for the given name from the given level and lower. It will return a wxTreeMultiItem which needs
984 to be checked with IsOk() to see if it is a correct item. IsRootItem, IsNodeItem and IsWindowItem can be
985 used to determine the type of item. If the search returned an item which doesn't satisfy the query, you can
986 restart the search from here, with skip = true to skip the passed item. */
987 wxTreeMultiItem FindItem(const wxTreeMultiItem &item, const wxString &name, bool ignoreCase = false,
988 bool skipFirst = false);
990 /** Searches all nodes for the given name and returns the one found. This is a specialised method for FindItem */
991 wxTreeMultiItem FindItem(const wxString &name, bool ignoreCase = false) {
992 return FindItem(wxTreeMultiItem(&_root), name, ignoreCase, false);
998 /** Returns the number of children in this node. If this node is not of type Node, count returns -1. */
999 int GetChildrenCount(const wxTreeMultiItem &item) {
1000 if(item.IsNodeItem())
1002 TreeMultiItemNode *n = (TreeMultiItemNode *)item.GetItem();
1003 return n->GetNodeCount();
1009 /** This method finds the current focused window, and returns the wxTreeMultiItem that has this window as pointer.
1010 If the wxTreeMultiItem is not ok, the focused window is on a sub-panel, or not on this control. If the focus is
1011 on a sub-panel, this panel will handle the focusing. If you are still interested in this window, try
1012 wxWindow::FindFocus which will always return with a pointer if a wxWindow has focus */
1013 wxTreeMultiItem GetFocus();
1015 /** @name Smart window Get/Set methods
1016 These methods are used for quickly getting or setting primitive values, like boolean, string, or selections into
1017 primitive wxWindow controls like a wxRadioButton, wxCheckBox, wxTextCtrl, etc.
1018 The methods allow you to quickly set e.g. a boolean value by using the wxWindow ID of the control. A type
1019 check is performed before the value is actually set with the appropiate method for it. If it fails, an assertion
1020 will follow in debug mode. If you want to get values back similar get methods are present to return values.
1021 This allows the user to quickly retrieve or set values by ID, without the fuss of remembering the pointer or
1022 node ID of the wxTreeMultiCtrl.
1026 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1027 AppendWindow). When it is found, it is type casted towards a <b>wxCheckBox</b> and <b>wxRadioButton</b>. Whenever
1028 it finds a proper type it will return true or false. Whenever no proper type is found, it will return with false.
1029 In debug mode it will cause an assertion failure as well, to notify the developer something is wrong.
1033 bool GetBooleanValue(int wndId);
1035 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1036 AppendWindow). When it is found, it is type casted towards a <b>wxTextCtrl</b>, <b>wxChoice</b> and <b>wxComboBox</b>.
1037 Whenever it finds a proper type it will return the (selected) text in the control. Whenever no proper type is found,
1038 it will return with an empty string. In debug mode it will cause an exception error as well if the cast fails, to notify
1039 the developer something is wrong.
1043 wxString GetTextValue(int wndId);
1045 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1046 AppendWindow). When it is found, it is type casted towards a <b>wxCheckBox</b> and <b>wxRadioButton</b>. Whenever
1047 it finds a proper type it set the control's value to the given boolean parameter. Nothing happens when no proper type
1048 is found, however debug mode it will cause an assertion failure.
1052 void SetBooleanValue(int wndId, bool value = true);
1054 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1055 AppendWindow). When it is found, it is type casted towards a <b>wxTextCtrl</b>. If the control is not found or
1056 of the wrong type, an asserion failure (in debug mode) follows. <br><i><b>NOTE: </b></i> this method
1057 does not typecast to wxChoice or wxComboBox and the likes. If a selection in one of those needs to be set, use the
1058 SetSelectionValue / GetSelectionValue combination.
1059 \sa GetTextValue, GetSelectionValue, SetSelectionValue
1061 void SetTextValue(int wndId, const wxString &value = wxEmptyString);
1063 /** Retrieves the wxWindow * associated with the wxTreeMultiItem. This only works for Window typed wxTreeMultiItem
1064 classes. If this type does not match or no window is associated, 0 is returned. */
1065 wxWindow *GetWindow(const wxTreeMultiItem &item) {
1066 if(item.IsWindowItem())
1067 return ((TreeMultiItemWindow *)item.GetItem())->GetWindow();
1071 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1072 AppendWindow). When it is found, it is type casted towards a <b>wxListBox, wxChoice, wxComboBox</b>.
1073 If the control is not found or of the wrong type, an asserion failure (in debug mode) follows. If it is found
1074 the selection is set in the control.
1076 void SetSelectionValue(int wndId, int sel);
1078 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1079 AppendWindow). When it is found, it is type casted towards a <b>wxListBox, wxChoice, wxComboBox</b>.
1080 If the control is not found or of the wrong type, an asserion failure (in debug mode) follows. In release mode -1 is
1081 returned. If it is found the selection index is returned.
1083 int GetSelectionValue(int wndId);
1085 /** This function calls FindWindow on the wxTreeMultiCtrl to find the window with the given ID (which is added with
1086 AppendWindow). When it is found, it is type casted towards a <b>wxListBox</b>. If the control is not found or
1087 of the wrong type, an asserion failure (in debug mode) follows. In release mode an empty wxArrayInt is returned.
1088 If it is found the selections are stored in the wxArrayInt. This is only valid for wxListBox classes with multiple
1091 void GetSelectionValues(int wndId, wxArrayInt &sels);
1094 /** Gets the checkbox state of the wxTreeMultiItem pointed out by "item". If the item does not have a checkbox
1095 associated (or the item is not ok), it will return -1. If the checkbox is checked it will return 1,
1096 unchecked is 0, and tri-state (usually only for caption nodes) it will return 2. <b>This needs USE_CHECKBOXVIEW
1097 set to YES, or CHECKBOXVIEW=1 during compile</b>*/
1098 int GetCheckboxState(const wxTreeMultiItem &item, bool WXUNUSED(recursive)) {
1099 wxCHECK(item.IsOk(), -1);
1101 // return the checkbox state
1102 TreeMultiItemBase *b = item.GetItem();
1103 if(b->GetCheckbox())
1104 return b->GetCheckboxState();
1109 /** Sets the checkbox state of the wxTreeMultiItem pointed out by "item". If the item does not have a checkbox
1110 associated (or the item is not ok), it will simply ignore this. <b>This needs USE_CHECKBOXVIEW
1111 set to YES, or CHECKBOXVIEW=1 during compile</b>. Contributed by Thomas Enickl.*/
1112 void SetCheckboxState( const wxTreeMultiItem &item, int state ) {
1113 wxCHECK2( item.IsOk(), return );
1114 TreeMultiItemBase *b = item.GetItem();
1115 if( b->GetCheckbox() )
1116 b->SetCheckboxState( state );
1117 RedrawFromNode( item.GetItem()->GetParent() );
1124 /** @name Extended visibility and manipulation methods
1125 These methods alter the wxTreeMultiCtrl appearance, or add more functionality like checkboxes before each node.
1129 /** Sets the Y spacing of the wxTreeMultiCtrl to a new size. This can be used to give the controls some more
1130 spacing in between */
1132 void SetSpacingY(int spacingY) {
1135 _spacingY = spacingY;
1140 /** Gets the Y spacing of the wxTreeMultiCtrl. */
1142 int GetSpacingY() const {
1147 /** This method toggles the checkbox view mode. Whenever set to true, the next window item, or caption node item
1148 will get a checkbox. <b>This needs USE_CHECKBOXVIEW set to YES, or CHECKBOXVIEW=1 during compile</b>
1149 \sa GetCheckboxView, wxTreeMultiWindowInfo::SetDefaultCheckState
1151 void SetCheckboxView(bool value) {
1152 _checkboxView = value;
1155 /** This method returns the checkbox state currently used. <b>This needs USE_CHECKBOXVIEW set to YES, or
1156 CHECKBOXVIEW=1 during compile</b>
1157 \sa SetCheckboxView, wxTreeMultiWindowInfo::SetDefaultCheckState, wxTreeMultiWindowInfo::GetDefaultCheckState
1159 bool GetCheckboxView() const {
1160 return _checkboxView;
1167 /** @name Iteration methods
1168 Allows the user to iterate through a wxTreeMultiCtrl node, and get all the children or siblings.
1169 To start an iteration from the lowest level the functions GetFirstRoot and GetLastRoot are provided.
1173 /** Returns the first root. */
1174 wxTreeMultiItem GetFirstRoot(void) const {return wxTreeMultiItem(this->_root.First());}
1176 /** Returns the last root. */
1177 wxTreeMultiItem GetLastRoot(void) const {return wxTreeMultiItem(this->_root.Last());}
1179 /** Returns the items parent. */
1180 wxTreeMultiItem GetParent(wxTreeMultiItem const& item) const;
1182 /** Returns the first child of this node. The type of wxTreeMultiItem needs to be of Node. Whenever not succesful,
1183 the item returned is not ok (IsOk = false). Upon success, a valid child is returned. The cookie variable doesn't
1184 need to be initialized */
1185 wxTreeMultiItem GetFirstChild(const wxTreeMultiItem &item, int &cookie) const;
1187 /** Returns the next child in the iteration on the level of 'item'. Make sure you called GetFirstChild first
1188 before calling this one */
1189 wxTreeMultiItem GetNextChild(const wxTreeMultiItem &item, int &cookie) const;
1191 /** Returns the last child of this node. The type of 'item' needs to be of Node. Whenever not succesful,
1192 the item returned is not ok (IsOk = false). Upon success, a valid last child is returned. */
1193 wxTreeMultiItem GetLastChild(const wxTreeMultiItem &item) const;
1195 /** Returns the next sibling of the passed item. */
1196 wxTreeMultiItem GetNextSibling(wxTreeMultiItem const& item) const;
1198 /** Returns the previous sibling of the passed item. */
1199 wxTreeMultiItem GetPrevSibling(wxTreeMultiItem const& item) const;
1201 /** Returns the next item. "Next" is defined by the following order:
1202 - in case the current item has a child it is the first child of the current item;
1203 - in case the current item has a next sibling as the next sibling;
1204 - as the parent's (or one of its ancestor's) next sibling.
1206 wxTreeMultiItem GetNext(wxTreeMultiItem const& item) const;
1208 /** Returns the previous item. "Previous" is defined by the following order:
1209 - in case the current item has a child it is the last child of the current item;
1210 - in case the current item has a previous sibling it is the previous sibling;
1211 - as the parent's (or one of its ancestor's) previous sibling.
1213 wxTreeMultiItem GetPrevious(wxTreeMultiItem const& item) const;
1219 /** @name Get and set methods
1220 These methods allow you to set or get certain properties of the wxTreeMultiCtrl.
1224 /** Get the currently used font for the caption headers in the wxTreeMultiCtrl. If you want to alter this
1225 font, simply obtain it and copy it to a local font. After that, set this font back using SetCaptionFont()
1227 const wxFont &GetCaptionFont() const {
1228 return _captionFont;
1231 /** Sets the font to be used for the text caption headers. This triggers a complete redraw because x,y sizes can
1232 differ, and ofcourse all nodes need to be updated. You can call this method at any time not only at the
1234 void SetCaptionFont(const wxFont &font);
1239 void OnDraw(wxDC& dc);
1242 DECLARE_EVENT_TABLE()