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.cpp,v $
30 // $Source: /cvs/creatis/bbtk/kernel/src/ThirdParty/wx/treemultictrl/wxTreeMultiCtrl.cpp,v $
32 // $Date: 2012/11/16 08:49:16 $
33 //---------------------------------------------------------------------------
34 // Author: Jorgen Bodde
35 // Copyright: (c) Jorgen Bodde
36 // License: wxWidgets License
37 //---------------------------------------------------------------------------
40 #pragma implementation "wxTreeMultiCtrl.h"
43 // For compilers that support precompilation, includes "wx/wx.h".
44 #include "wx/wxprec.h"
45 #include "wx/treebase.h"
51 #include "wx/arrimpl.cpp"
53 #include "wx/treemultictrl/wxTreeMultiCtrl.h"
54 #include "wx/treemultictrl/wxTreeMultiEvent.h"
55 #include "tmcimages.h"
59 //----------------------------------------------------------------------------
61 //----------------------------------------------------------------------------
63 WX_DEFINE_OBJARRAY(wxArrayTreeMultiItem);
65 //----------------------------------------------------------------------------
67 //----------------------------------------------------------------------------
69 IMPLEMENT_DYNAMIC_CLASS(wxTreeMultiCtrl, wxScrolledWindow)
71 // WDR: event table for wxTreeMultiCtrl
72 BEGIN_EVENT_TABLE(wxTreeMultiCtrl, wxScrolledWindow)
73 EVT_LEFT_DOWN (wxTreeMultiCtrl::OnMouseClick)
74 EVT_LEFT_DCLICK(wxTreeMultiCtrl::OnMouseClick)
75 EVT_RIGHT_DOWN (wxTreeMultiCtrl::OnRightMouseClick)
76 EVT_PAINT(wxTreeMultiCtrl::OnPaint)
77 EVT_SIZE(wxTreeMultiCtrl::OnSize)
78 // EVT_KEY_UP(wxTreeMultiCtrl::OnKey)
81 bool wxTreeMultiCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos,
82 const wxSize& size, long style, const wxValidator & WXUNUSED(validator),
83 const wxString& name )
85 wxScrolledWindow::Create( parent, id, pos, size, style | wxTAB_TRAVERSAL, name);
87 _create_called = true;
95 void wxTreeMultiCtrl::Init()
110 _checkboxView = false;
113 _gutterWidth = WXTMC_GUTTER_DEFAULT;
118 _spacingY = WXTMC_YSPACING_DEFAULT;
121 // create two bitmap nodes for drawing
123 _expandBmp = new wxBitmap(expand_xpm);
124 _collBmp = new wxBitmap(collapse_xpm);
126 // calculate average font height for bitmap centering
128 _iconWidth = _expandBmp->GetWidth();
129 _iconHeight = _expandBmp->GetHeight();
132 // create bitmaps for checkboxes
133 _checkBmp = new wxBitmap(checked_icon);
134 _uncheckBmp = new wxBitmap(unchecked_icon);
135 _tristateBmp = new wxBitmap(tristate_icon);
137 // adjust the height if the checkboxes are higher
138 // so that everything is alligned properly
139 _checkHeight = _checkBmp->GetHeight();
140 _checkWidth = _checkBmp->GetWidth();
143 // remember the highest of the two bitmaps so there is
144 // always enough room
145 _maxHeight = _iconHeight;
148 if(_maxHeight < _checkHeight)
149 _maxHeight = _checkHeight;
152 // set standard highlighting brush
153 this->m_HilightBrush = new wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT),wxSOLID);
155 // set standard DC font
156 _captionFont = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
158 // adjust bitmap icon y position so they are centered
161 // set virtual size to this window size
162 if (_create_called) {
163 wxSize wndsize = GetSize();
164 SetVirtualSize(wndsize.GetWidth(), wndsize.GetWidth());
168 void wxTreeMultiCtrl::SetCaptionFont(const wxFont &font)
172 // adjust the icons so that they are in the middle
178 void wxTreeMultiCtrl::AdjustIconsDeltaY()
182 if(_captionFont.Ok())
183 GetTextExtent(wxT("jG"), &x, &y, 0, 0, &_captionFont);
186 if(_maxHeight < _captionHeight)
187 _maxHeight = _captionHeight;
189 // determine the center pos for the [+]
190 _iconDeltaY = abs(_maxHeight - _iconHeight) / 2 + 1;
195 // determine the center pos for the checkbox
196 _checkDeltaY = abs(_maxHeight - _checkHeight) / 2 + 1;
202 wxTreeMultiCtrl::~wxTreeMultiCtrl()
204 // delete the bitmap resources
215 wxTreeMultiItem wxTreeMultiCtrl::AddRoot(const wxString &caption, const wxString &name)
217 wxTreeMultiItem result((TreeMultiItemBase *)&_root);
218 result = AppendNode(result, caption, name);
223 wxTreeMultiItem wxTreeMultiCtrl::AppendWindow(const wxTreeMultiItem &ParentItem, wxWindow *window, const wxString &name, const wxTreeMultiWindowInfo &info, int flags)
225 // add window only if the parent item is valid and...
226 wxCHECK(ParentItem.IsOk(), wxTreeMultiItem(0));
228 TreeMultiItemNode* parent = ParentItem.GetItem()->IsTreeMultiItemNode(); // also roots are nodes
231 wxCHECK(parent != NULL, wxTreeMultiItem(0));
233 // now, append node to the tree control:
234 wxTreeMultiItem NewWindowItem(this->InsertWindow(parent,wx_static_cast(size_t,parent->GetNodeCount()),window,name,info,flags));
235 // redraw the stucture:
236 this->RedrawFromNode(parent);
237 // return the new window
238 return NewWindowItem;
241 wxTreeMultiItem wxTreeMultiCtrl::InsertWindow(wxTreeMultiItem const& ParentItem, size_t Position, wxWindow *window, wxString const& name, wxTreeMultiWindowInfo const& info, int flags)
243 // add window only if the parent item is valid and...
244 wxCHECK(ParentItem.IsOk(), wxTreeMultiItem(0));
246 TreeMultiItemNode* parent = ParentItem.GetItem()->IsTreeMultiItemNode(); // also roots are nodes
249 wxCHECK(parent != NULL, wxTreeMultiItem(0));
251 // now, append node to the tree control:
252 wxTreeMultiItem NewWindowItem(this->InsertWindow(parent,Position,window,name,info,flags));
253 // redraw the stucture:
254 this->RedrawFromNode(parent);
255 // return the new window
256 return NewWindowItem;
257 } /* wxTreeMultiCtrl::InsertWindow(wxTreeMultiItem const&, size_t, wxWindow*, wxString const&, wxTreeMultiWindowInfo const&, int) */
259 wxTreeMultiItem wxTreeMultiCtrl::PrependWindow(wxTreeMultiItem const& ParentItem, wxWindow *window, const wxString &name, wxTreeMultiWindowInfo const& info, int flags)
261 // add window only if the parent item is valid and...
262 wxCHECK(ParentItem.IsOk(), wxTreeMultiItem(0));
264 TreeMultiItemNode* parent = ParentItem.GetItem()->IsTreeMultiItemNode(); // also roots are nodes
267 wxCHECK(parent != NULL, wxTreeMultiItem(0));
269 // now, append node to the tree control:
270 wxTreeMultiItem NewWindowItem(this->InsertWindow(parent,0,window,name,info,flags));
271 // redraw the stucture:
272 this->RedrawFromNode(parent);
273 // return the new window
274 return NewWindowItem;
275 } /* wxTreeMultiCtrl::PrependWindow(wxTreeMultiItem const&, wxWindow*, const wxString &, wxTreeMultiWindowInfo const&, int) */
277 wxTreeMultiItem wxTreeMultiCtrl::AppendNode(wxTreeMultiItem const& ParentItem, const wxString &caption, const wxString &name)
279 // add window only if the parent item is valid and...
280 wxCHECK(ParentItem.IsOk(), wxTreeMultiItem(0));
282 TreeMultiItemNode* parent = ParentItem.GetItem()->IsTreeMultiItemNode(); // also roots are nodes
285 wxCHECK(parent != NULL, wxTreeMultiItem(0));
287 // now, append node to the tree control:
288 wxTreeMultiItem NewNodeItem(this->InsertNode(parent,wx_static_cast(size_t,parent->GetNodeCount()),caption,name));
289 // redraw the structure:
290 this->RedrawFromNode(parent);
291 // return the new node:
293 } /* wxTreeMultiCtrl::AppendNode(wxTreeMultiItem const&, const wxString &, const wxString&) */
295 wxTreeMultiItem wxTreeMultiCtrl::InsertNode(wxTreeMultiItem const& ParentItem, size_t Position, wxString const& caption, wxString const& name)
297 // add window only if the parent item is valid and...
298 wxCHECK(ParentItem.IsOk(), wxTreeMultiItem(0));
300 TreeMultiItemNode* parent = ParentItem.GetItem()->IsTreeMultiItemNode(); // also roots are nodes
303 wxCHECK(parent != NULL, wxTreeMultiItem(0));
305 // now, append node to the tree control:
306 wxTreeMultiItem NewNodeItem(this->InsertNode(parent,Position,caption,name));
307 // redraw the structure:
308 this->RedrawFromNode(parent);
309 // return the new node:
311 } /* wxTreeMultiCtrl::InsertNode(wxTreeMultiItem const&, size_t, wxString const&, wxString const&) */
313 wxTreeMultiItem wxTreeMultiCtrl::PrependNode(wxTreeMultiItem const& ParentItem, wxString const& caption, wxString const& name)
315 // add window only if the parent item is valid and...
316 wxCHECK(ParentItem.IsOk(), wxTreeMultiItem(0));
318 TreeMultiItemNode* parent = ParentItem.GetItem()->IsTreeMultiItemNode(); // also roots are nodes
321 wxCHECK(parent != NULL, wxTreeMultiItem(0));
323 // now, append node to the tree control:
324 wxTreeMultiItem NewNodeItem(this->InsertNode(parent,0,caption,name));
325 // redraw the structure:
326 this->RedrawFromNode(parent);
327 // return the new node:
329 } /* wxTreeMultiCtrl::PrependNode(wxTreeMultiItem const&, wxString const&, wxString const&) */
331 bool wxTreeMultiCtrl::Delete(wxTreeMultiItem &item)
334 wxCHECK(item.IsOk(), false);
336 wxTreeMultiItem nullItem(0);
339 // if item has been selected, remove it from the selected list:
340 size_t ItemIndex(this->GetSelectedItemIndex(item));
342 if (ItemIndex != this->GetSelectedItemCount())
343 this->m_SelectedItems.RemoveAt(ItemIndex);
345 // get parent, to delete item from
346 TreeMultiItemNode *p = item.GetItem()->GetParent();
348 // first check if it was visible, if so from the parent off
349 // it needs redrawing
350 redraw = item.GetItem()->IsVisible();
352 p->DeleteNode(item.GetItem());
354 _root.DeleteNode(item.GetItem());
358 // do redraw when node was visible
365 void wxTreeMultiCtrl::DeleteChildren(const wxTreeMultiItem &item)
367 if(item.IsNodeItem())
369 TreeMultiItemNode *n = (TreeMultiItemNode *)item.GetItem();
371 // remove all children from the selected item list:
372 if (n->GetNodeCount() > 0)
374 // variable definitions and initializations:
376 wxTreeMultiItem FirstItemIterator(this->GetFirstChild(item,Cookie)), LastItemIterator(this->GetLastChild(item));
380 size_t ItemIndex(this->GetSelectedItemIndex(item)); // variable definition and initialization
382 if (ItemIndex != this->GetSelectedItemCount())
383 this->m_SelectedItems.RemoveAt(ItemIndex);
384 if (FirstItemIterator == LastItemIterator)
385 break; // all children checked
387 FirstItemIterator = this->GetNext(FirstItemIterator);
397 void wxTreeMultiCtrl::Expand(const wxTreeMultiItem &item, bool recursive)
401 TreeMultiItemNode *n = item.GetItem()->IsTreeMultiItemNode();
403 n = item.GetItem()->GetParent();
404 DoFold(n, true, recursive);
405 RedrawFromNode(item.GetItem()->IsTreeMultiItemNode());
409 void wxTreeMultiCtrl::Collapse(const wxTreeMultiItem &item, bool recursive)
413 TreeMultiItemNode *n = item.GetItem()->IsTreeMultiItemNode();
415 n = item.GetItem()->GetParent();
416 DoFold(n, false, recursive);
417 RedrawFromNode(item.GetItem()->IsTreeMultiItemNode());
422 void wxTreeMultiCtrl::ExpandNodes(bool recursive)
424 // go through all children and call DoFold recursively
425 for(int i = 0; i < _root.GetNodeCount(); i++)
426 DoFold(_root.GetNode(i), true, recursive);
430 void wxTreeMultiCtrl::CollapseNodes(bool recursive)
432 // go through all children and call DoFold recursively
433 for(int i = 0; i < _root.GetNodeCount(); i++)
434 DoFold(_root.GetNode(i), false, recursive);
438 void wxTreeMultiCtrl::CollapseAndReset(const wxTreeMultiItem &item)
440 if(item.IsNodeItem())
442 TreeMultiItemNode *n = (TreeMultiItemNode *)item.GetItem();
446 Collapse(item, false);
450 // Selection manipulation
451 wxTreeMultiItem wxTreeMultiCtrl::GetFirstSelectedItem(void) const
453 if (this->GetSelectedItemCount() > 0)
454 return this->m_SelectedItems[0];
456 return wxTreeMultiItem();
457 } /* wxTreeMultiCtrl::GetFirstSelectedItem(void) const */
459 wxTreeMultiItem wxTreeMultiCtrl::GetLastSelectedItem(void) const
461 if (this->GetSelectedItemCount() > 0)
462 return this->m_SelectedItems[this->GetSelectedItemCount()-1];
464 return wxTreeMultiItem();
465 } /* wxTreeMultiCtrl::GetLastSelectedItem(void) const */
467 wxTreeMultiItem wxTreeMultiCtrl::GetSelectedItem(size_t Index) const
469 if (Index < this->GetSelectedItemCount())
470 return this->m_SelectedItems[Index];
472 return wxTreeMultiItem();
473 } /* wxTreeMultiCtrl::GetSelectedItem(size_t Index) const */
475 size_t wxTreeMultiCtrl::GetSelectedItemIndex(wxTreeMultiItem const& Item) const
477 // attention: the function wxArray::Index() can NOT be used in a save manner as it only checks the address of an item
478 // element but it is not guaranteed that Item may not be a copy of the originally inserted item
479 const size_t NoOfSelectedItems = this->GetSelectedItemCount();
484 while ((Index < NoOfSelectedItems) && (this->m_SelectedItems[Index] != Item))
487 } /* wxTreeMultiCtrl::GetSelectedItemIndex(wxTreeMultiItem const&) const */
489 void wxTreeMultiCtrl::SelectItem(wxTreeMultiItem const& Item, bool UnselectOthers, bool ExpandSelection)
491 TreeMultiItemNode* NodePtr(Item.GetItem()->IsTreeMultiItemNode());
494 // only nodes can be selected and they can only be selected if they are not already selected:
495 if ((NodePtr == NULL) || NodePtr->IsSelected())
498 // inform that we are about to change:
499 wxTreeMultiEvent Event(wxEVT_COMMAND_TREE_MULTI_SEL_CHANGING,Item); // variable definition and initialization
501 if (this->m_SelectedItems.GetCount() > 0) // the last item in the array is always the latest inserted item
502 Event.SetOldItem(this->m_SelectedItems.Last());
503 Event.SetEventObject(this);
504 if (this->GetEventHandler()->ProcessEvent(Event) && !(Event.IsAllowed()))
507 // make sure that the to be selected item can be seen:
510 // variable definition and initialization:
511 wxTreeMultiItem ExcludedParent(this->GetExcludedParent(Item));
513 while (ExcludedParent.IsOk())
515 this->Include(ExcludedParent);
516 ExcludedParent = this->GetExcludedParent(Item);
519 // unselect items if necessary:
522 // expand selection if necessary:
525 // variable definition:
526 wxTreeMultiItem FirstItemIterator, LastItemIterator;
527 wxTreeMultiItem LastSelectedItem;
529 // determine the last selected item or the first item in case nothing has been selected before:
530 if (this->m_SelectedItems.GetCount() > 0)
531 LastSelectedItem = this->m_SelectedItems.Last();
533 LastSelectedItem = this->GetFirstRoot();
534 // determine the item from which to start and the one with which to end the selection:
535 if (Item.GetItem()->GetY() > LastSelectedItem.GetItem()->GetY())
537 FirstItemIterator = LastSelectedItem;
538 LastItemIterator = Item;
542 FirstItemIterator = Item;
543 LastItemIterator = LastSelectedItem;
545 // select all items that are a node and are placed between the two limiting iterators (included the limits):
548 if (!(FirstItemIterator.IsSelected()) && FirstItemIterator.IsNodeItem())
550 FirstItemIterator.GetItem()->Select();
551 this->m_SelectedItems.Add(FirstItemIterator);
552 this->RefreshRect(wxRect(FirstItemIterator.GetItem()->GetX(), FirstItemIterator.GetItem()->GetY(),
553 FirstItemIterator.GetItem()->GetWidth(),FirstItemIterator.GetItem()->GetHeight()));
555 if (FirstItemIterator == LastItemIterator)
557 // continue iterating:
558 FirstItemIterator = this->GetNext(FirstItemIterator);
561 else // select passed item only
564 this->m_SelectedItems.Add(NodePtr);
565 this->RefreshRect(wxRect(NodePtr->GetX(),NodePtr->GetY(),NodePtr->GetWidth(),NodePtr->GetHeight()));
568 // inform that we have selected the item:
569 Event.SetEventType(wxEVT_COMMAND_TREE_MULTI_SEL_CHANGED);
570 this->GetEventHandler()->ProcessEvent(Event);
571 } /* wxTreeMultiCtrl::SelectItem(wxTreeMultiItem const&, bool, bool) */
573 void wxTreeMultiCtrl::UnselectAll(void)
575 const size_t NoOfSelectedItems = this->m_SelectedItems.GetCount();
578 for (size_t i=0; i<NoOfSelectedItems; ++i)
580 this->RefreshRect(wxRect(this->m_SelectedItems[i].GetItem()->GetX(), this->m_SelectedItems[i].GetItem()->GetY(),
581 this->m_SelectedItems[i].GetItem()->GetWidth(),this->m_SelectedItems[i].GetItem()->GetHeight()));
582 this->m_SelectedItems[i].GetItem()->Unselect();
584 this->m_SelectedItems.Clear();
585 } /* wxTreeMultiCtrl::UnselectAll(void) */
587 void wxTreeMultiCtrl::Unselect(wxTreeMultiItem const& Item)
589 size_t ItemIndex(this->GetSelectedItemIndex(Item));
592 if (ItemIndex != this->GetSelectedItemCount())
594 Item.GetItem()->Unselect();
595 this->m_SelectedItems.RemoveAt(ItemIndex);
596 this->RefreshRect(wxRect(Item.GetItem()->GetX(),Item.GetItem()->GetY(),Item.GetItem()->GetWidth(),Item.GetItem()->GetHeight()));
598 } /* wxTreeMultiCtrl::Unselect(wxTreeMultiItem const&) */
600 void wxTreeMultiCtrl::DoFold(TreeMultiItemBase *item, bool expand, bool recursive)
603 // go through all node objects on this level, and expand or
609 // if this is a node, use it to go through all the subnodes (if needed)
610 // if not, then just exit.
612 TreeMultiItemNode *node = item->IsTreeMultiItemNode();
620 TreeMultiItemNode *p;
621 for(int i = 0; i < node->GetNodeCount(); i++)
623 // get node, and if a real node, then call fold
624 p = node->GetNode(i)->IsTreeMultiItemNode();
628 // go recursive for every node
629 DoFold(p, expand, recursive);
635 void wxTreeMultiCtrl::Exclude(const wxTreeMultiItem &item)
637 wxCHECK2(item.IsOk(), return);
639 // exclude the item, and refresh
640 // if already excluded, skip
642 if(!item.GetItem()->IsExcluded())
644 item.GetItem()->SetExcluded(true);
645 RedrawFromParentNode(item.GetItem());
649 void wxTreeMultiCtrl::Include(const wxTreeMultiItem &item)
651 wxCHECK2(item.IsOk(), return);
653 // include the item, and refresh. If not
654 // excluded, do nothing
656 if(item.GetItem()->IsExcluded())
658 item.GetItem()->SetExcluded(false);
659 RedrawFromParentNode(item.GetItem());
663 wxTreeMultiItem wxTreeMultiCtrl::GetExcludedParent(const wxTreeMultiItem &item)
665 wxCHECK(item.IsOk(), wxTreeMultiItem(0));
667 // go find the parent (including this one) that
668 // can be the excluded one
670 TreeMultiItemNode *n = item.GetItem()->IsTreeMultiItemNode();
671 if(n && n->IsExcluded())
672 return wxTreeMultiItem(n);
674 n = item.GetItem()->GetParent();
678 return wxTreeMultiItem(n);
683 return wxTreeMultiItem(0);
686 void wxTreeMultiCtrl::OnSize(wxSizeEvent &WXUNUSED(event))
688 RecalculateSpanSizes();
691 void wxTreeMultiCtrl::OnPaint(wxPaintEvent& WXUNUSED(event) )
697 // go recursive and draw the whole visible tree.
698 dc.SetFont(_captionFont);
699 for(int i = 0; i < _root.GetNodeCount(); i++)
700 DrawNode(_root.GetNode(i), dc);
703 void wxTreeMultiCtrl::DrawNode(TreeMultiItemBase *b, wxDC &dc)
705 // go through this item .. if it is a node, draw
706 // the caption, else reposition the window.
711 // forget it if this node is not visible
714 int bmpOffsetX = b->GetX() - (_gutterWidth + _iconWidth);
717 // now draw the checkbox if there is any, in the proper state
722 // adjust the bmpOffset because we also have a checkbox
723 bmpOffsetX -= _checkWidth;
727 if(b->IsTreeMultiItemNode())
729 // draw the node icon and the caption
730 TreeMultiItemNode *n = (TreeMultiItemNode *)b;
732 // set background of caption item
735 dc.SetBrush(*(this->m_HilightBrush));
736 dc.SetPen(wxPen(this->m_HilightBrush->GetColour(),1,wxSOLID));
740 dc.SetBrush(wxBrush(*wxWHITE,wxSOLID));
741 dc.SetPen(wxPen(*wxWHITE,1,wxSOLID));
743 dc.DrawRectangle(n->GetX(),n->GetY(),n->GetWidth(),n->GetHeight());
745 dc.DrawText(n->GetCaption(), n->GetX(), n->GetY());
747 // draw the bitmap for the state
749 dc.DrawBitmap(*_expandBmp, bmpOffsetX, n->GetY() + _iconDeltaY, true);
751 dc.DrawBitmap(*_collBmp, bmpOffsetX, n->GetY() + _iconDeltaY, true);
753 // now go through all the subnodes
754 for(int i = 0; i < n->GetNodeCount(); i++)
755 DrawNode(n->GetNode(i), dc);
763 void wxTreeMultiCtrl::DrawCheckbox(TreeMultiItemBase *b, wxDC &dc, bool convertScrolled)
768 int bmpOffsetX = b->GetX() - (_gutterWidth + _iconWidth);
770 switch(b->GetCheckboxState())
785 if(b->IsTreeMultiItemWindow())
787 xx = x = bmpOffsetX - ((TreeMultiItemWindow *)b)->GetFrontSpacing() + _checkWidth;
788 yy = y = b->GetY() + _checkDeltaY;
793 yy = y = b->GetY() + _checkDeltaY;
797 CalcScrolledPosition(x, y, &xx, &yy);
799 dc.DrawBitmap(*bmp, xx, yy, true);
802 #endif // #if(CHECKBOXVIEW)
804 void wxTreeMultiCtrl::OnKey(wxKeyEvent &event)
806 // check if we need to traverse to upper or lower
807 // control in the list
808 if(event.GetKeyCode() == WXK_TAB)
810 wxTreeMultiItem item = GetFocus();
813 // traverse down direction
814 if(!event.ShiftDown())
815 item = FindNextVisibleWindowItem(item.GetItem());
816 //else // traverse in up direction
817 // item = FindPreviousVisibleWindowItem(item);
821 TreeMultiItemWindow *w = item.GetItem()->IsTreeMultiItemWindow();
824 wxWindow *wnd = w->GetWindow();
834 void wxTreeMultiCtrl::OnMouseClick( wxMouseEvent &event )
836 // react on double click and left mouse down
837 if(event.LeftDown() || event.LeftDClick())
839 // get translation point
840 wxPoint pt( event.GetPosition() );
843 CalcUnscrolledPosition( pt.x, pt.y, &x, &y );
845 // go check if we clicked a treenode
848 wxTreeMultiItem id = HitTest(p, flags);
851 if(flags == wxTMC_HITTEST_CHECKBOX)
853 // toggle the checkbox, and redraw
856 TreeMultiItemBase *b = id.GetItem();
857 b->SetCheckboxState((b->GetCheckboxState()+1) & 0x1);
859 TreeMultiItemWindow *w = b->IsTreeMultiItemWindow();
862 // try to force a focus on the window. This could
863 // be extended by searching for the first edit control
864 // class but for now, just a focus is tried.
865 w->GetWindow()->Enable(b->GetCheckboxState() == 1);
866 w->GetWindow()->SetFocus();
868 // draw the checkbox in the state needed
870 DrawCheckbox(b, dc, true);
872 // TODO: determine if the upper parents should be
875 ScanTristateCheckstates(b);
878 else if(b->IsTreeMultiItemNode())
880 // descend to all the children and set the state of the parent
881 SetRecursiveCheckState((TreeMultiItemNode *)b, b->GetCheckboxState() == 1);
882 RedrawFromNode((TreeMultiItemNode *)b);
887 #endif // #if(CHECKBOXVIEW)
889 // react on left mouse button, to fold and on
890 // right for caption doubleclick
893 // adjust behaviour for Linux (single click = always fold)
895 if(event.LeftDClick())
896 area = wxTMC_HITTEST_CAPTION;
898 area = wxTMC_HITTEST_GUTTER;
903 // Linux (single or double click -> always fold
907 // we have a valid item, if it is a node, then fold
908 TreeMultiItemNode *n = id.GetItem()->IsTreeMultiItemNode();
911 this->SelectItem(id);
912 Fold(n, !n->IsExpanded());
915 if (event.LeftDown())
916 if (flags == wxTMC_HITTEST_GUTTER)
918 TreeMultiItemNode *n = id.GetItem()->IsTreeMultiItemNode(); // for some reasons also windows may have set the flag
921 Fold(n, !n->IsExpanded());
923 else if (flags == wxTMC_HITTEST_CAPTION)
925 TreeMultiItemNode *n = id.GetItem()->IsTreeMultiItemNode(); // for some reasons also windows may have set the flag
929 this->SelectItem(id);
930 this->RedrawFromNode(n);
941 void wxTreeMultiCtrl::OnRightMouseClick(wxMouseEvent& Event)
943 if (Event.RightDown())
944 if (Event.Dragging())
948 // variable definitions:
952 // translate mouse coordinates:
953 CalcUnscrolledPosition(Event.GetPosition().x,Event.GetPosition().y,&(Point.x),&(Point.y));
954 // check if the mouse is above the caption of an item:
955 wxTreeMultiItem Item(this->HitTest(Point,Flags)); // variable definition and initialization
957 if (Item.IsOk() && (Flags == wxTMC_HITTEST_CAPTION))
959 this->SelectItem(Item);
960 this->RedrawFromNode(Item.GetItem()->IsTreeMultiItemNode());
961 Event.Skip(); // window will convert right mouse click to a context menu event or proceed with
962 // a right mouse click event if the context menu event cannot be processed
969 } /* wxTreeMultiCtrl::OnRightMouseClick(wxMouseEvent&) */
971 wxTreeMultiItem wxTreeMultiCtrl::HitTest(wxPoint const& pt, int &flags)
973 // scan all nodes to see which one matches
974 TreeMultiItemBase *b = 0;
975 for(int i = 0; i < _root.GetNodeCount() && !b; i++)
976 b = FindNodeByPoint(_root.GetNode(i), pt, flags);
982 return wxTreeMultiItem(0);
986 return wxTreeMultiItem(b);
989 TreeMultiItemBase *wxTreeMultiCtrl::FindNodeByPoint(TreeMultiItemBase *b, wxPoint const& pt, int &area)
993 // if this layer is not visible, return with nothing.
999 // now see if our y is matching the mouse
1000 if(pt.y >= b->GetY() && pt.y < (b->GetY() + b->GetHeight()))
1003 // if we are checkboxed, calculate the checkbox position
1004 if(b->GetCheckbox())
1006 int extraSpacing = 0, extraWidth = 0;
1008 // now for a windows item, this is minus the gutter. For a normal node it is X minus checkbox
1009 if(b->IsTreeMultiItemWindow())
1011 extraWidth = _checkWidth;
1012 extraSpacing = ((TreeMultiItemWindow *)b)->GetFrontSpacing();
1017 if(pt.x > (b->GetX() - extraSpacing - _checkWidth) && pt.x < (b->GetX() - extraSpacing + extraWidth))
1019 area = wxTMC_HITTEST_CHECKBOX;
1025 // allrighty we have something, now where and what is it (look with x)
1026 if(pt.x < b->GetX())
1027 area = wxTMC_HITTEST_GUTTER;
1029 /** \todo Match only the real part of the caption, window (we assume x > GetX() which is the rest)
1030 HOWEVER the window probably doesn't propagate the click event back to the parent, so we might
1031 leave it like this so the use can click behind a window so it will be selected.
1035 // inside area, return proper flag
1036 if(b->IsTreeMultiItemNode())
1037 area = wxTMC_HITTEST_CAPTION;
1039 area = wxTMC_HITTEST_WINDOW;
1046 // not found, let's try our children if we have some
1047 TreeMultiItemNode *n = b->IsTreeMultiItemNode();
1050 TreeMultiItemBase *bb = 0;
1051 for(int i = 0; i < n->GetNodeCount() && !bb; i++)
1052 bb = FindNodeByPoint(n->GetNode(i), pt, area);
1054 // keep returning result to caller
1062 wxTreeMultiItem wxTreeMultiCtrl::GetFocus()
1064 wxWindow *wnd = wxWindow::FindFocus();
1066 // now find window that holds this item. if not
1067 // visible it cannot have focus (should not have)
1069 wxTreeMultiItem item = FindWindowNode(wnd);
1070 if(item.IsOk() && item.GetItem()->IsVisible())
1073 return wxTreeMultiItem(0);
1078 void wxTreeMultiCtrl::SetRecursiveCheckState(TreeMultiItemNode *n, bool check)
1084 // go check all kids on this level
1085 for(int i = 0; i < n->GetNodeCount(); i++)
1087 // check all the nodes, and go deeper
1088 n->GetNode(i)->SetCheckboxState(state);
1089 if(n->GetNode(i)->IsTreeMultiItemNode())
1090 SetRecursiveCheckState((TreeMultiItemNode *)n->GetNode(i), check);
1094 void wxTreeMultiCtrl::ScanTristateCheckstates(TreeMultiItemBase *b)
1096 // check from the parent on, all node entries and see if they are
1097 // checked or cleared or scattered
1098 TreeMultiItemNode *p = b->GetParent();
1100 if(p && p->GetCheckbox())
1102 bool foundcheck = false, foundclear = false;
1103 for(size_t i = 0; i < (size_t)p->GetNodeCount(); ++i)
1105 // only evaluate when checkboxed
1106 if(p->GetNode(i)->IsTreeMultiItemWindow() && p->GetNode(i)->GetCheckbox())
1108 // record instance of a cleared checkbox
1109 if(!p->GetNode(i)->GetCheckboxState())
1111 // record instance of checked checkbox
1112 if(p->GetNode(i)->GetCheckboxState() == 1)
1117 // if we have both check and clear, go tristate
1118 // if all clear, clear parent and if all set, then set parent
1119 if(foundclear && !foundcheck)
1120 p->SetCheckboxState(0);
1121 else if(!foundclear && foundcheck)
1122 p->SetCheckboxState(1);
1123 else if(foundclear && foundcheck)
1124 p->SetCheckboxState(2);
1127 //DrawCheckbox(p, dc, false);
1132 #endif // #if(CHECKBOXVIEW)
1134 wxTreeMultiItem wxTreeMultiCtrl::InsertNode(TreeMultiItemNode* ParentPtr, size_t Position, wxString const& Caption, wxString const& Name)
1138 TreeMultiItemNode* NodePtr(new TreeMultiItemNode(ParentPtr,Caption,Name)); // generate new node pointer
1141 // continue with initializing the new node:
1143 // if checkbox view is desired, tag this item as a checkbox
1144 // and set the state as 'false'
1145 NodePtr->SetCheckbox(_checkboxView);
1146 NodePtr->SetCheckboxState(0);
1148 // calculate the height and width
1149 this->GetTextExtent(Caption,&extX,&extY,0,0,&(this->_captionFont));
1150 NodePtr->SetHeight(extY);
1151 NodePtr->SetWidth(extX);
1152 // finally, insert node:
1153 if (Position < (size_t)ParentPtr->GetNodeCount())
1154 ParentPtr->InsertNode(NodePtr,Position);
1156 ParentPtr->AddNode(NodePtr);
1157 // return the newly created node:
1158 return wxTreeMultiItem(NodePtr);
1159 } /* wxTreeMultiCtrl::InsertNode(TreeMultiItemNode*, size_t, wxString const&, wxString const&) */
1161 wxTreeMultiItem wxTreeMultiCtrl::InsertWindow(TreeMultiItemNode* ParentPtr, size_t Position, wxWindow* WindowPtr, wxString const& Name, wxTreeMultiWindowInfo const& Info, int Flags)
1165 TreeMultiItemWindow* NewWindowPtr = new TreeMultiItemWindow(ParentPtr,Name); // generate new window pointer
1168 // get flags from passed variable "Flags"; in case this variable does not contain any flags use the window's information flags:
1170 WindowFlags = Flags;
1172 WindowFlags = Info.GetFlags();
1174 // continue with initializing the new window:
1176 // if checkbox view is desired, tag this item as a checkbox
1177 // and set the state as 'false'
1178 NewWindowPtr->SetCheckbox(_checkboxView);
1180 // if style wants us to change background, set it to our background
1181 if (WindowFlags & wxTMC_BG_ADJUST_ALL)
1183 // go through all children of this window, and set the
1184 // background of it (recursively)
1185 this->SetWindowBackgroundColour(WindowPtr,this->GetBackgroundColour(),WindowFlags);
1189 NewWindowPtr->SetTopSpacing(Info.GetTopSpacing());
1191 // make sure that the checkboxes are at least indented enough
1192 if (this->_checkboxView)
1193 NewWindowPtr->SetFrontSpacing(Info.GetFrontSpacing() + this->_checkWidth);
1196 NewWindowPtr->SetFrontSpacing(Info.GetFrontSpacing());
1197 // assign finally the window:
1198 NewWindowPtr->AssignWindow(WindowPtr);
1201 // set the checkbox state after the window is assigned
1202 NewWindowPtr->SetCheckboxState(Info.GetDefaultCheckState());
1205 // if the window is not visible, set hide flag
1206 this->ShowTreeMultiWindow(NewWindowPtr,NewWindowPtr->IsVisible());
1208 // finally, insert the newly constructed window:
1209 if (Position < (size_t)ParentPtr->GetNodeCount())
1210 ParentPtr->InsertNode(NewWindowPtr,Position);
1212 ParentPtr->AddNode(NewWindowPtr);
1213 // return the newly created window:
1214 return wxTreeMultiItem(NewWindowPtr);
1215 } /* wxTreeMultiCtrl::InsertWindow(TreeMultiItemNode*, size_t, wxWindow*, wxString const&, wxTreeMultiWindowInfo const&, int) */
1217 void wxTreeMultiCtrl::RedrawFromParentNode(TreeMultiItemBase *n)
1219 TreeMultiItemNode *p = 0;
1226 void wxTreeMultiCtrl::RedrawFromNode(TreeMultiItemNode *n)
1228 static int recalcMutex = 0;
1229 bool visible = true;
1236 // when node is not visible or excluded
1237 // then don't redraw.
1240 visible = n->IsVisible();
1245 GetVirtualSize(&w, &h);
1247 UpdateAllWindowVisibility();
1248 RecalculateNodePositions();
1249 RecalculateVirtualSize();
1251 // why is this needed? Because folding or collapsing can change
1252 // the state. When the virtual area gets smaller, we need to keep
1253 // the largest one and the other way atound. And since we do not
1254 // know here we are folding or collapsing, we remember the biggest
1255 GetVirtualSize(&w1, &h1);
1260 // only refresh the part from x,y down
1264 CalcScrolledPosition(n->GetX(), n->GetY(), &x, &y);
1267 wxRect rect(0, y, w, h - y);
1274 Refresh(); // do a full refresh
1280 void wxTreeMultiCtrl::RecalculateNodePositions()
1282 int currentY = _spacingY;
1283 // go recursive on every node, and store the information in the node
1285 for(int i = 0; i < _root.GetNodeCount(); i++)
1286 currentY += CalculateNodeDimensions(_root.GetNode(i), currentY, 0);
1289 int wxTreeMultiCtrl::CalculateNodeDimensions(TreeMultiItemBase *b, int currentY, int level)
1291 int gutter = (_gutterWidth * 2) + _iconWidth;
1292 int y = 0, topSpacing = 0;
1294 // return same if no proper object
1298 if(b->GetCheckbox())
1299 gutter += _checkWidth;
1302 // if we are not visible, skip recalculation and descending
1307 // if level is 0, calculate with front gutter, else without
1308 y = currentY + b->GetHeight();
1309 if(b->IsTreeMultiItemNode())
1311 TreeMultiItemNode *n = (TreeMultiItemNode *)b;
1316 b->SetX(gutter + (level * (_gutterWidth + _iconWidth)));
1318 // now do children of this node
1320 for(int i = 0; i < n->GetNodeCount(); i++)
1321 y += CalculateNodeDimensions(n->GetNode(i), y + _spacingY, level+1);
1323 else if(b->IsTreeMultiItemWindow())
1325 TreeMultiItemWindow *w = (TreeMultiItemWindow *)b;
1328 b->SetX(gutter + w->GetFrontSpacing());
1330 b->SetX(_gutterWidth + (level * (_gutterWidth + _iconWidth)) + w->GetFrontSpacing());
1332 topSpacing = w->GetTopSpacing();
1334 // reposition the window
1336 wxWindow *wnd = w->GetWindow();
1340 CalcScrolledPosition(w->GetX(), w->GetY(), &x, &y);
1341 wnd->SetSize(x, y, w->GetWidth(), w->GetHeight());
1346 return (y - currentY) + _spacingY + topSpacing; // return delta
1351 return 0; // not visible, thus we skip calculations
1354 void wxTreeMultiCtrl::RecalculateSpanSizes()
1356 for(int i = 0; i < _root.GetNodeCount(); i++)
1357 CalculateNodeSpanning(_root.GetNode(i));
1360 void wxTreeMultiCtrl::CalculateNodeSpanning(TreeMultiItemBase *b)
1362 // return same if no proper object
1363 wxCHECK2(b, return);
1365 if(b->IsTreeMultiItemNode())
1367 TreeMultiItemNode *n = (TreeMultiItemNode *)b;
1369 // now do children of this node
1371 for(int i = 0; i < n->GetNodeCount(); i++)
1372 CalculateNodeSpanning(n->GetNode(i));
1374 else if(b->IsTreeMultiItemWindow())
1376 TreeMultiItemWindow *w = (TreeMultiItemWindow *)b;
1377 wxWindow *wnd = w->GetWindow();
1380 // if the window is spanning, we adjust the width to the max width of the control
1381 if(w->GetHorizontalSpan())
1383 wxSize tmcsize = GetClientSize();
1384 int maxwidth = tmcsize.GetWidth() - w->GetX() - 8; // extract 3 for border
1386 wxSizer *sz = wnd->GetSizer();
1389 if(maxwidth < sz->GetMinSize().GetWidth())
1390 maxwidth = sz->GetMinSize().GetWidth();
1393 // prevent a size of 0
1398 w->SetWidth(maxwidth);
1399 wnd->SetSize(w->GetWidth(), w->GetHeight());
1401 // layout by sizer (not sure if this is needed)
1403 wnd->GetSizer()->Layout();
1409 void wxTreeMultiCtrl::RecalculateVirtualSize()
1411 // go through all the nodes, and store the largest x and largest y
1414 RecalculateVirtualSizeFromNode(&_root, x, y);
1416 // now adjust virtual size
1417 SetVirtualSize(x, y);
1418 AdjustScrollbars(x, y);
1421 void wxTreeMultiCtrl::AdjustScrollbars(int x, int y)
1423 // adjust scrollbars
1424 // courtesy of treectrlg.cpp
1426 y += WXTMC_PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
1427 x += WXTMC_PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels
1428 int x_pos = GetScrollPos( wxHORIZONTAL );
1429 int y_pos = GetScrollPos( wxVERTICAL );
1430 SetScrollbars( WXTMC_PIXELS_PER_UNIT, WXTMC_PIXELS_PER_UNIT, x/WXTMC_PIXELS_PER_UNIT,
1431 y/WXTMC_PIXELS_PER_UNIT, x_pos, y_pos, true );
1434 void wxTreeMultiCtrl::RecalculateVirtualSizeFromNode(const TreeMultiItemNode *node, int &x, int &y)
1436 if(node->IsExcluded())
1439 // if calulate this node's dimensions
1440 if(x < (node->GetWidth() + node->GetX()))
1441 x = node->GetWidth() + node->GetX();
1443 y = node->GetY() + node->GetHeight();
1445 // if this node is collapsed, no subnodes are visible, else
1446 // go through all subnodes as well, node needs to be included as well
1447 if(node->IsExpanded())
1449 TreeMultiItemBase *b;
1450 for(int i = 0; i < node->GetNodeCount(); i++)
1452 b = node->GetNode(i);
1454 // calculate x and y
1455 if(x < (b->GetWidth() + b->GetX()))
1456 x = b->GetWidth() + b->GetX();
1458 y = b->GetY() + b->GetHeight();
1460 if(b->IsTreeMultiItemNode())
1461 RecalculateVirtualSizeFromNode((TreeMultiItemNode *)b, x, y);
1466 void wxTreeMultiCtrl::SetWindowBackgroundColour(wxWindow *wnd, const wxColour &col, int flags)
1470 // if we cannot change a button, make sure all button
1471 // classes are not changed
1473 wxButton *btn = wxDynamicCast(wnd, wxButton);
1474 if(!btn || ((flags & wxTMC_BG_ADJUST_BTN) != 0))
1475 wnd->SetBackgroundColour(col);
1477 // get every window, and make the background equal to the given one
1478 wxWindowListNode *node = wnd->GetChildren().GetFirst();
1481 SetWindowBackgroundColour(node->GetData(), col, flags);
1482 node = node->GetNext();
1487 void wxTreeMultiCtrl::ShowTreeMultiWindow(TreeMultiItemWindow *window, bool show)
1489 // show or hide window
1490 if(window && window->GetWindow())
1491 window->GetWindow()->Show(show);
1494 void wxTreeMultiCtrl::UpdateAllWindowVisibility()
1496 // all roots are visible, but what lies beneath ... who knows
1497 for(int i = 0; i < _root.GetNodeCount(); i++)
1498 UpdateTreeMultiWindowVisibility(_root.GetNode(i), true);
1501 void wxTreeMultiCtrl::UpdateTreeMultiWindowVisibility(TreeMultiItemBase *b, bool show)
1505 // this is done for performance issues. IsVisible can go all
1506 // the way up the tree to check. However if show is already
1507 // false, there is no need to check (some higher one is collapsed)
1511 showMe = b->IsVisible();
1513 if(b->IsTreeMultiItemWindow())
1515 // if this level must be hidden, hide
1516 ShowTreeMultiWindow((TreeMultiItemWindow*)b, showMe);
1518 else if(b->IsTreeMultiItemNode())
1520 TreeMultiItemNode *node = (TreeMultiItemNode *)b;
1522 // if hidden, descend and hide all windows
1523 for(int i = 0; i < node->GetNodeCount(); i++)
1524 UpdateTreeMultiWindowVisibility(node->GetNode(i), showMe);
1529 wxTreeMultiItem wxTreeMultiCtrl::FindItem(const wxTreeMultiItem &item, const wxString &name, bool ignoreCase, bool skipFirst)
1533 TreeMultiItemBase *b = item.GetItem();
1535 // check this item first (or not)
1539 if(b->GetName().IsSameAs(name, !ignoreCase))
1540 return wxTreeMultiItem(b);
1543 if(b->IsTreeMultiItemNode())
1545 // now check whether we are a node, then go check children
1547 TreeMultiItemNode *n = (TreeMultiItemNode *)b;
1548 wxTreeMultiItem result(0);
1549 for(int i = 0; i < n->GetNodeCount() && !result.IsOk(); i++)
1550 result = FindItem(wxTreeMultiItem(n->GetNode(i)), name, ignoreCase, false);
1556 return wxTreeMultiItem(0);
1559 wxTreeMultiItem wxTreeMultiCtrl::FindWindowNode(wxWindow *wnd, TreeMultiItemNode *n)
1561 wxCHECK(wnd, wxTreeMultiItem(0));
1563 // take root node if not assigned one
1566 n = (TreeMultiItemNode *)&_root;
1568 // check on this level for the wxWindow pointer
1570 TreeMultiItemWindow *w;
1571 wxTreeMultiItem result(0);
1572 for(int i = 0; i < n->GetNodeCount() && !result.IsOk(); i++)
1575 w = n->GetNode(i)->IsTreeMultiItemWindow();
1576 if(w && w->GetWindow() == wnd)
1577 return wxTreeMultiItem(n);
1579 // if node, go deeper
1580 if(n->GetNode(i)->IsTreeMultiItemNode())
1581 result = FindWindowNode(wnd, (TreeMultiItemNode*)n->GetNode(i));
1587 TreeMultiItemWindow *wxTreeMultiCtrl::FindNextVisibleWindowItem(TreeMultiItemBase *b, int index)
1591 // check on this level, go deeper with every node we got. When a node is not
1592 // visible anymore, skip the node.
1594 TreeMultiItemWindow *value = 0;
1597 // if we are already searching on a node with an index
1599 TreeMultiItemBase *bn = 0;
1600 TreeMultiItemNode *n = b->IsTreeMultiItemNode();
1603 for(int i = index + 1; i < n->GetNodeCount() && !value; i++)
1606 value = bn->IsTreeMultiItemWindow();
1608 // assume a node, root when not a a window
1610 value = FindNextVisibleWindowItem(bn, -1);
1616 if(b->IsTreeMultiItemWindow())
1618 // get parent first, and locate child as ptr
1619 TreeMultiItemNode *p = b->GetParent();
1622 // go scan the parent from the given index, if
1623 // the index is valid else there is no child with that index
1625 int idx = p->Index(b);
1626 wxCHECK(idx >= 0, 0);
1628 value = FindNextVisibleWindowItem(p, idx);
1637 bool wxTreeMultiCtrl::GetBooleanValue(int wndId)
1639 wxWindow *wnd = wxWindow::FindWindow(wndId);
1640 wxCHECK(wnd, false);
1642 // try a radio button
1643 wxRadioButton *b = wxDynamicCast(wnd, wxRadioButton);
1645 return b->GetValue();
1648 wxCheckBox *c = wxDynamicCast(wnd, wxCheckBox);
1650 return c->GetValue();
1652 /** \todo For custom controls we should put something in wxMultiTreeItemData class
1653 which can be overridden to retrieve the boolean value. It will also be passed
1654 the pointer to the window, so the derived class can figure out how to get a boolean
1658 // generate assert or just return with false
1662 void wxTreeMultiCtrl::SetBooleanValue(int wndId, bool value)
1664 wxWindow *wnd = wxWindow::FindWindow(wndId);
1665 wxCHECK2(wnd, return);
1667 // try a radio button
1668 wxRadioButton *b = wxDynamicCast(wnd, wxRadioButton);
1676 wxCheckBox *c = wxDynamicCast(wnd, wxCheckBox);
1683 /** \todo For custom controls we should put something in wxMultiTreeItemData class
1684 which can be overridden to retrieve the boolean value. It will also be passed
1685 the pointer to the window, so the derived class can figure out how to get a boolean
1690 wxCHECK2(0, return);
1693 void wxTreeMultiCtrl::SetTextValue(int wndId, const wxString &value)
1695 wxWindow *wnd = wxWindow::FindWindow(wndId);
1696 wxCHECK2(wnd, return);
1698 // try a radio button
1699 wxTextCtrl *t = wxDynamicCast(wnd, wxTextCtrl);
1706 /** \todo For custom controls we should put something in wxMultiTreeItemData class
1707 which can be overridden to retrieve the boolean value. It will also be passed
1708 the pointer to the window, so the derived class can figure out how to get a boolean
1713 wxCHECK2(0, return);
1716 wxString wxTreeMultiCtrl::GetTextValue(int wndId)
1718 wxWindow *wnd = wxWindow::FindWindow(wndId);
1719 wxCHECK(wnd, wxEmptyString);
1721 // try a radio button
1722 wxTextCtrl *t = wxDynamicCast(wnd, wxTextCtrl);
1724 return t->GetValue();
1727 wxChoice *c1 = wxDynamicCast(wnd, wxChoice);
1729 return c1->GetStringSelection();
1732 wxComboBox *c2 = wxDynamicCast(wnd, wxComboBox);
1734 return c2->GetStringSelection();
1737 wxListBox *l = wxDynamicCast(wnd, wxListBox);
1739 return l->GetStringSelection();
1741 /** \todo For custom controls we should put something in wxMultiTreeItemData class
1742 which can be overridden to retrieve the boolean value. It will also be passed
1743 the pointer to the window, so the derived class can figure out how to get a boolean
1747 // generate assert or just return with string
1748 wxCHECK(0, wxEmptyString);
1751 int wxTreeMultiCtrl::GetSelectionValue(int wndId)
1753 wxWindow *wnd = wxWindow::FindWindow(wndId);
1757 wxChoice *c1 = wxDynamicCast(wnd, wxChoice);
1759 return c1->GetSelection();
1762 wxComboBox *c2 = wxDynamicCast(wnd, wxComboBox);
1764 return c2->GetSelection();
1767 wxListBox *l = wxDynamicCast(wnd, wxListBox);
1769 return l->GetSelection();
1771 /** \todo For custom controls we should put something in wxMultiTreeItemData class
1772 which can be overridden to retrieve the boolean value. It will also be passed
1773 the pointer to the window, so the derived class can figure out how to get a boolean
1777 // generate assert or just return with string
1781 void wxTreeMultiCtrl::GetSelectionValues(int wndId, wxArrayInt &sels)
1785 wxWindow *wnd = wxWindow::FindWindow(wndId);
1786 wxCHECK2(wnd, return);
1789 wxListBox *l = wxDynamicCast(wnd, wxListBox);
1792 l->GetSelections(sels);
1796 /** \todo For custom controls we should put something in wxMultiTreeItemData class
1797 which can be overridden to retrieve the boolean value. It will also be passed
1798 the pointer to the window, so the derived class can figure out how to get a boolean
1802 // generate assert or just return with string
1803 wxCHECK2(0, return);
1806 void wxTreeMultiCtrl::SetSelectionValue(int wndId, int sel)
1808 wxWindow *wnd = wxWindow::FindWindow(wndId);
1809 wxCHECK2(wnd, return);
1812 wxChoice *c1 = wxDynamicCast(wnd, wxChoice);
1815 c1->SetSelection(sel);
1820 wxComboBox *c2 = wxDynamicCast(wnd, wxComboBox);
1823 c2->SetSelection(sel);
1828 wxListBox *l = wxDynamicCast(wnd, wxListBox);
1831 l->SetSelection(sel);
1835 /** \todo For custom controls we should put something in wxMultiTreeItemData class
1836 which can be overridden to retrieve the boolean value. It will also be passed
1837 the pointer to the window, so the derived class can figure out how to get a boolean
1841 // generate assert or just return with string
1842 wxCHECK2(0, return);
1846 wxTreeMultiItem wxTreeMultiCtrl::GetParent(wxTreeMultiItem const& item) const
1848 // check if valid or root item has been passed, both do not have parents:
1849 if (!(item.IsOk()) || item.GetItem()->IsTreeMultiItemRoot())
1850 return wxTreeMultiItem();
1852 return wxTreeMultiItem(item.GetItem()->GetParent()); // GetParent() returns a valid pointer in case of a root item!!
1853 // therefore, the check if the passed item is a root item is necessary
1854 } /* wxTreeMultiCtrl::GetParent(wxTreeMultiItem const& item) const */
1856 wxTreeMultiItem wxTreeMultiCtrl::GetFirstChild(const wxTreeMultiItem &item, int &cookie) const
1858 if(item.IsNodeItem())
1860 TreeMultiItemNode *n = (TreeMultiItemNode *)item.GetItem();
1862 if(n->GetNodeCount() > 0)
1865 return wxTreeMultiItem(n->GetNode(0));
1869 // no children or no valid node
1871 return wxTreeMultiItem(0);
1874 wxTreeMultiItem wxTreeMultiCtrl::GetNextChild(const wxTreeMultiItem &item, int &cookie) const
1876 if(item.IsNodeItem())
1878 TreeMultiItemNode *n = (TreeMultiItemNode *)item.GetItem();
1880 if(cookie >= 0 && cookie < (n->GetNodeCount()-1))
1882 // increment cookie, return node
1884 return wxTreeMultiItem(n->GetNode(cookie));
1888 // end of query, or no valid node
1890 return wxTreeMultiItem(0);
1893 wxTreeMultiItem wxTreeMultiCtrl::GetLastChild(const wxTreeMultiItem &item) const
1895 if(item.IsNodeItem())
1897 TreeMultiItemNode *n = (TreeMultiItemNode *)item.GetItem();
1899 if(n->GetNodeCount() > 0)
1900 return wxTreeMultiItem(n->GetNode(n->GetNodeCount()-1));
1903 return wxTreeMultiItem(0);
1906 wxTreeMultiItem wxTreeMultiCtrl::GetNextSibling(wxTreeMultiItem const& item) const
1908 // check if a valid item has been passed:
1910 return wxTreeMultiItem();
1912 TreeMultiItemNode* ParentPtr(item.GetItem()->GetParent());
1915 if (ParentPtr != NULL) // the parent pointer is only null if the passed item is the root
1917 // find the current item in the parent's list; the next sibling has an index that is one higher than the one of the current item:
1918 int NextItemIndex(ParentPtr->Index(item.GetItem())+1); // variable definition and initialization
1920 if (NextItemIndex < ParentPtr->GetNodeCount())
1921 return ParentPtr->GetNode(NextItemIndex);
1923 return wxTreeMultiItem();
1926 return wxTreeMultiItem();
1927 } /* wxTreeMultiCtrl::GetNextSibling(wxTreeMultiItem const&) const */
1929 wxTreeMultiItem wxTreeMultiCtrl::GetPrevSibling(wxTreeMultiItem const& item) const
1931 // check if a valid item has been passed:
1933 return wxTreeMultiItem();
1935 TreeMultiItemNode* ParentPtr(item.GetItem()->GetParent());
1938 if (ParentPtr != NULL)
1940 // find the current item in the parent's list; the next sibling has an index that is one higher than the one of the current item:
1941 int PrevItemIndex(ParentPtr->Index(item.GetItem())-1); // variable definition and initialization
1943 if (PrevItemIndex >= 0)
1944 return ParentPtr->GetNode(PrevItemIndex);
1946 return wxTreeMultiItem();
1949 return wxTreeMultiItem();
1950 } /* wxTreeMultiCtrl::GetPrevSibling(wxTreeMultiItem const&) const */
1952 wxTreeMultiItem wxTreeMultiCtrl::GetNext(wxTreeMultiItem const& item) const
1954 // check if a valid item has been passed:
1956 return wxTreeMultiItem();
1958 TreeMultiItemNode* NodePtr(item.GetItem()->IsTreeMultiItemNode()); // variable definition and initialization
1960 if ((NodePtr != NULL) && (NodePtr->GetNodeCount() > 0))
1961 return wxTreeMultiItem(NodePtr->First());
1964 // variable definitions and initializations:
1965 wxTreeMultiItem Parent(item);
1966 wxTreeMultiItem Sibling;
1970 Sibling = this->GetNextSibling(Parent); // try to find next sibling
1971 Parent = this->GetParent(Parent); // get next ancestor
1972 } while (!(Sibling.IsOk()) && Parent.IsOk());
1973 // in case the loop ended with Sibling.IsOk() "Sibling" contains a valid sibling otherwise an invalid
1976 } /* wxTreeMultiCtrl::GetNextSibling(wxTreeMultiItem const&) const */
1978 wxTreeMultiItem wxTreeMultiCtrl::GetPrevious(wxTreeMultiItem const& item) const
1980 // check if a valid item has been passed:
1982 return wxTreeMultiItem();
1984 TreeMultiItemNode* NodePtr(item.GetItem()->IsTreeMultiItemNode()); // variable definition and initialization
1986 if ((NodePtr != NULL) && (NodePtr->GetNodeCount() > 0))
1987 return wxTreeMultiItem(NodePtr->Last());
1990 // variable definitions and initializations:
1991 wxTreeMultiItem Parent(item);
1992 wxTreeMultiItem Sibling;
1996 Sibling = this->GetPrevSibling(Parent); // try to find next sibling
1997 Parent = this->GetParent(Parent); // get next ancestor
1998 } while (!(Sibling.IsOk()) && Parent.IsOk());
1999 // in case the loop ended with Sibling.IsOk() "Sibling" contains a valid sibling otherwise an invalid
2002 } /* wxTreeMultiCtrl::GetPrevious(wxTreeMultiItem const&) const */
2004 // WDR: handler implementations for wxTreeMultiCtrl
2006 void wxTreeMultiCtrl::OnDraw(wxDC& dc)
2008 // go recursive and draw the whole visible tree.
2009 dc.SetFont(_captionFont);
2010 for(int i = 0; i < _root.GetNodeCount(); i++)
2011 DrawNode(_root.GetNode(i), dc);