home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / samples / treectrl / treetest.cpp < prev    next >
C/C++ Source or Header  |  2002-07-22  |  37KB  |  1,160 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        treetest.cpp
  3. // Purpose:     wxTreeCtrl sample
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: treetest.cpp,v 1.70 2002/07/21 14:29:11 VZ Exp $
  8. // Copyright:   (c) Julian Smart and Markus Holzem
  9. // Licence:     wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13.   #pragma implementation
  14.   #pragma interface
  15. #endif
  16.  
  17. // For compilers that support precompilation, includes "wx/wx.h".
  18. #include "wx/wxprec.h"
  19.  
  20. #ifdef __BORLANDC__
  21.   #pragma hdrstop
  22. #endif
  23.  
  24. #ifndef WX_PRECOMP
  25.   #include "wx/wx.h"
  26.   #include "wx/log.h"
  27. #endif
  28.  
  29. #include "wx/colordlg.h"
  30.  
  31. #include "wx/image.h"
  32. #include "wx/imaglist.h"
  33. #include "wx/treectrl.h"
  34.  
  35. #include "math.h"
  36.  
  37. #ifdef __WIN32__
  38.     // this is not supported by native control
  39.     #define NO_VARIABLE_HEIGHT
  40. #endif
  41.  
  42. #include "treetest.h"
  43.  
  44. #include "icon1.xpm"
  45. #include "icon2.xpm"
  46. #include "icon3.xpm"
  47. #include "icon4.xpm"
  48. #include "icon5.xpm"
  49. #include "mondrian.xpm"
  50.  
  51.  
  52. // verify that the item is ok and insult the user if it is not
  53. #define CHECK_ITEM( item ) if ( !item.IsOk() ) {                                 \
  54.                              wxMessageBox(wxT("Please select some item first!"), \
  55.                                           wxT("Tree sample error"),              \
  56.                                           wxOK | wxICON_EXCLAMATION,             \
  57.                                           this);                                 \
  58.                              return;                                             \
  59.                            }
  60.  
  61. #define MENU_LINK(name) EVT_MENU(TreeTest_##name, MyFrame::On##name)
  62.  
  63. BEGIN_EVENT_TABLE(MyFrame, wxFrame)
  64.     EVT_SIZE(MyFrame::OnSize)
  65.  
  66.     MENU_LINK(Quit)
  67.     MENU_LINK(About)
  68.  
  69.     MENU_LINK(TogButtons)
  70.     MENU_LINK(TogTwist)
  71.     MENU_LINK(TogLines)
  72.     MENU_LINK(TogEdit)
  73.     MENU_LINK(TogHideRoot)
  74.     MENU_LINK(TogRootLines)
  75.     MENU_LINK(TogBorder)
  76.     MENU_LINK(TogFullHighlight)
  77.     MENU_LINK(SetFgColour)
  78.     MENU_LINK(SetBgColour)
  79.     MENU_LINK(ResetStyle)
  80.  
  81.     MENU_LINK(Dump)
  82. #ifndef NO_MULTIPLE_SELECTION
  83.     MENU_LINK(DumpSelected)
  84.     MENU_LINK(Select)
  85.     MENU_LINK(Unselect)
  86.     MENU_LINK(ToggleSel)
  87. #endif // NO_MULTIPLE_SELECTION
  88.     MENU_LINK(Rename)
  89.     MENU_LINK(Count)
  90.     MENU_LINK(CountRec)
  91.     MENU_LINK(Sort)
  92.     MENU_LINK(SortRev)
  93.     MENU_LINK(SetBold)
  94.     MENU_LINK(ClearBold)
  95.     MENU_LINK(Delete)
  96.     MENU_LINK(DeleteChildren)
  97.     MENU_LINK(DeleteAll)
  98.     MENU_LINK(Recreate)
  99.     MENU_LINK(ToggleImages)
  100.     MENU_LINK(ToggleButtons)
  101.     MENU_LINK(SetImageSize)
  102.     MENU_LINK(CollapseAndReset)
  103.     MENU_LINK(EnsureVisible)
  104.     MENU_LINK(AddItem)
  105.     MENU_LINK(InsertItem)
  106.     MENU_LINK(IncIndent)
  107.     MENU_LINK(DecIndent)
  108.     MENU_LINK(IncSpacing)
  109.     MENU_LINK(DecSpacing)
  110.     MENU_LINK(ToggleIcon)
  111. #undef MENU_LINK
  112.  
  113. END_EVENT_TABLE()
  114.  
  115. #if USE_GENERIC_TREECTRL
  116. BEGIN_EVENT_TABLE(MyTreeCtrl, wxGenericTreeCtrl)
  117. #else
  118. BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl)
  119. #endif
  120.     EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginDrag)
  121.     EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginRDrag)
  122.     EVT_TREE_END_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnEndDrag)
  123.     EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnBeginLabelEdit)
  124.     EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnEndLabelEdit)
  125.     EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, MyTreeCtrl::OnDeleteItem)
  126. #if 0       // there are so many of those that logging them causes flicker
  127.     EVT_TREE_GET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnGetInfo)
  128. #endif
  129.     EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo)
  130.     EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded)
  131.     EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding)
  132.     EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsed)
  133.     EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing)
  134.     EVT_TREE_ITEM_RIGHT_CLICK(TreeTest_Ctrl, MyTreeCtrl::OnItemRightClick)
  135.  
  136.     EVT_RIGHT_UP(MyTreeCtrl::OnRMouseUp)
  137.     EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged)
  138.     EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging)
  139.     EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnTreeKeyDown)
  140.     EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, MyTreeCtrl::OnItemActivated)
  141.     EVT_RIGHT_DCLICK(MyTreeCtrl::OnRMouseDClick)
  142. END_EVENT_TABLE()
  143.  
  144. IMPLEMENT_APP(MyApp)
  145.  
  146. bool MyApp::OnInit()
  147. {
  148.     // Create the main frame window
  149.     MyFrame *frame = new MyFrame(wxT("wxTreeCtrl Test"), 50, 50, 450, 600);
  150.  
  151.     // Show the frame
  152.     frame->Show(TRUE);
  153.     SetTopWindow(frame);
  154.  
  155.     return TRUE;
  156. }
  157.  
  158.  
  159. // My frame constructor
  160. MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h)
  161.        : wxFrame((wxFrame *)NULL, -1, title, wxPoint(x, y), wxSize(w, h)),
  162.          m_treeCtrl(NULL), m_textCtrl(NULL)
  163. {
  164.     // This reduces flicker effects - even better would be to define
  165.     // OnEraseBackground to do nothing. When the tree control's scrollbars are
  166.     // show or hidden, the frame is sent a background erase event.
  167.     SetBackgroundColour(wxColour(255, 255, 255));
  168.  
  169.     // Give it an icon
  170.     SetIcon(wxICON(mondrian));
  171.  
  172. #if wxUSE_MENUS
  173.     // Make a menubar
  174.     wxMenu *file_menu = new wxMenu,
  175.            *style_menu = new wxMenu,
  176.            *tree_menu = new wxMenu,
  177.            *item_menu = new wxMenu;
  178.  
  179.     file_menu->Append(TreeTest_About, wxT("&About..."));
  180.     file_menu->AppendSeparator();
  181.     file_menu->Append(TreeTest_Quit, wxT("E&xit\tAlt-X"));
  182.  
  183.     style_menu->Append(TreeTest_TogButtons, "Toggle &normal buttons", _T(""), TRUE);
  184.     style_menu->Append(TreeTest_TogTwist, "Toggle &twister buttons", _T(""), TRUE);
  185.     style_menu->Append(TreeTest_ToggleButtons, "Toggle image &buttons", _T(""), TRUE);
  186.     style_menu->AppendSeparator();
  187.     style_menu->Append(TreeTest_TogLines, "Toggle &connecting lines", _T(""), TRUE);
  188.     style_menu->Append(TreeTest_TogRootLines, "Toggle &lines at root", _T(""), TRUE);
  189.     style_menu->Append(TreeTest_TogHideRoot, "Toggle &hidden root", _T(""), TRUE);
  190.     style_menu->Append(TreeTest_TogBorder, "Toggle &item border", _T(""), TRUE);
  191.     style_menu->Append(TreeTest_TogFullHighlight, "Toggle &full row highlight", _T(""), TRUE);
  192.     style_menu->Append(TreeTest_TogEdit, "Toggle &edit mode", _T(""), TRUE);
  193. #ifndef NO_MULTIPLE_SELECTION
  194.     style_menu->Append(TreeTest_ToggleSel, wxT("Toggle &selection mode"), _T(""), TRUE);
  195. #endif // NO_MULTIPLE_SELECTION
  196.     style_menu->Append(TreeTest_ToggleImages, wxT("Toggle show ima&ges"), _T(""), TRUE);
  197.     style_menu->Append(TreeTest_SetImageSize, wxT("Set image si&ze..."));
  198.     style_menu->AppendSeparator();
  199.     style_menu->Append(TreeTest_SetFgColour, wxT("Set &foreground colour..."));
  200.     style_menu->Append(TreeTest_SetBgColour, wxT("Set &background colour..."));
  201.     style_menu->AppendSeparator();
  202.     style_menu->Append(TreeTest_ResetStyle, wxT("&Reset to default\tF10"));
  203.  
  204.     tree_menu->Append(TreeTest_Recreate, "&Recreate the tree");
  205.     tree_menu->Append(TreeTest_CollapseAndReset, "C&ollapse and reset");
  206.     tree_menu->AppendSeparator();
  207.     tree_menu->Append(TreeTest_AddItem, "Append a &new item");
  208.     tree_menu->Append(TreeTest_InsertItem, "&Insert a new item");
  209.     tree_menu->Append(TreeTest_Delete, "&Delete this item");
  210.     tree_menu->Append(TreeTest_DeleteChildren, "Delete &children");
  211.     tree_menu->Append(TreeTest_DeleteAll, "Delete &all items");
  212.     tree_menu->AppendSeparator();
  213.     tree_menu->Append(TreeTest_Count, "Count children of current item");
  214.     tree_menu->Append(TreeTest_CountRec, "Recursively count children of current item");
  215.     tree_menu->AppendSeparator();
  216.     tree_menu->Append(TreeTest_Sort, "Sort children of current item");
  217.     tree_menu->Append(TreeTest_SortRev, "Sort in reversed order");
  218.     tree_menu->AppendSeparator();
  219.     tree_menu->Append(TreeTest_EnsureVisible, "Make the last item &visible");
  220.     tree_menu->AppendSeparator();
  221.     tree_menu->Append(TreeTest_IncIndent, "Add 5 points to indentation\tAlt-I");
  222.     tree_menu->Append(TreeTest_DecIndent, "Reduce indentation by 5 points\tAlt-R");
  223.     tree_menu->AppendSeparator();
  224.     tree_menu->Append(TreeTest_IncSpacing, "Add 5 points to spacing\tCtrl-I");
  225.     tree_menu->Append(TreeTest_DecSpacing, "Reduce spacing by 5 points\tCtrl-R");
  226.  
  227.     item_menu->Append(TreeTest_Dump, "&Dump item children");
  228.     item_menu->Append(TreeTest_Rename, "&Rename item...");
  229.  
  230.     item_menu->AppendSeparator();
  231.     item_menu->Append(TreeTest_SetBold, "Make item &bold");
  232.     item_menu->Append(TreeTest_ClearBold, "Make item ¬ bold");
  233.     item_menu->AppendSeparator();
  234.     item_menu->Append(TreeTest_ToggleIcon, "Toggle the item's &icon");
  235.  
  236. #ifndef NO_MULTIPLE_SELECTION
  237.     item_menu->AppendSeparator();
  238.     item_menu->Append(TreeTest_DumpSelected, "Dump selected items\tAlt-D");
  239.     item_menu->Append(TreeTest_Select, "Select current item\tAlt-S");
  240.     item_menu->Append(TreeTest_Unselect, "Unselect everything\tAlt-U");
  241. #endif // NO_MULTIPLE_SELECTION
  242.  
  243.     wxMenuBar *menu_bar = new wxMenuBar;
  244.     menu_bar->Append(file_menu, "&File");
  245.     menu_bar->Append(style_menu, "&Style");
  246.     menu_bar->Append(tree_menu, "&Tree");
  247.     menu_bar->Append(item_menu, "&Item");
  248.     SetMenuBar(menu_bar);
  249. #endif // wxUSE_MENUS
  250.  
  251.     // create the controls
  252.     m_textCtrl = new wxTextCtrl(this, -1, "",
  253.                                 wxDefaultPosition, wxDefaultSize,
  254.                                 wxTE_MULTILINE | wxSUNKEN_BORDER);
  255.  
  256.     CreateTreeWithDefStyle();
  257.  
  258.     menu_bar->Check(TreeTest_ToggleImages, TRUE);
  259.  
  260.     // create a status bar with 3 panes
  261.     CreateStatusBar(3);
  262.     SetStatusText("", 0);
  263.  
  264. #ifdef __WXMOTIF__
  265.     // For some reason, we get a memcpy crash in wxLogStream::DoLogStream
  266.     // on gcc/wxMotif, if we use wxLogTextCtl. Maybe it's just gcc?
  267.     delete wxLog::SetActiveTarget(new wxLogStderr);
  268. #else
  269.     // set our text control as the log target
  270.     wxLogTextCtrl *logWindow = new wxLogTextCtrl(m_textCtrl);
  271.     delete wxLog::SetActiveTarget(logWindow);
  272. #endif
  273. }
  274.  
  275. MyFrame::~MyFrame()
  276. {
  277.     delete wxLog::SetActiveTarget(NULL);
  278. }
  279.  
  280. void MyFrame::CreateTreeWithDefStyle()
  281. {
  282.     long style = wxTR_DEFAULT_STYLE |
  283. #ifndef NO_VARIABLE_HEIGHT
  284.                  wxTR_HAS_VARIABLE_ROW_HEIGHT |
  285. #endif
  286.                  wxTR_EDIT_LABELS;
  287.  
  288.     CreateTree(style | wxSUNKEN_BORDER);
  289.  
  290.     // as we don't know what wxTR_DEFAULT_STYLE could contain, test for
  291.     // everything
  292.     wxMenuBar *mbar = GetMenuBar();
  293.     mbar->Check(TreeTest_TogButtons, (style & wxTR_HAS_BUTTONS) != 0);
  294.     mbar->Check(TreeTest_TogButtons, (style & wxTR_TWIST_BUTTONS) != 0);
  295.     mbar->Check(TreeTest_TogLines, (style & wxTR_NO_LINES) == 0);
  296.     mbar->Check(TreeTest_TogRootLines, (style & wxTR_LINES_AT_ROOT) != 0);
  297.     mbar->Check(TreeTest_TogHideRoot, (style & wxTR_HIDE_ROOT) != 0);
  298.     mbar->Check(TreeTest_TogEdit, (style & wxTR_EDIT_LABELS) != 0);
  299.     mbar->Check(TreeTest_TogBorder, (style & wxTR_ROW_LINES) != 0);
  300.     mbar->Check(TreeTest_TogFullHighlight, (style & wxTR_FULL_ROW_HIGHLIGHT) != 0);
  301. }
  302.  
  303. void MyFrame::CreateTree(long style)
  304. {
  305.     m_treeCtrl = new MyTreeCtrl(this, TreeTest_Ctrl,
  306.                                 wxDefaultPosition, wxDefaultSize,
  307.                                 style);
  308.     Resize();
  309. }
  310.  
  311. void MyFrame::TogStyle(int id, long flag)
  312. {
  313.     long style = m_treeCtrl->GetWindowStyle() ^ flag;
  314.  
  315.     // most treectrl styles can't be changed on the fly using the native
  316.     // control and the tree must be recreated
  317. #ifndef __WXMSW__
  318.     m_treeCtrl->SetWindowStyle(style);
  319. #else // MSW
  320.     delete m_treeCtrl;
  321.     CreateTree(style);
  322. #endif // !MSW/MSW
  323.  
  324.     GetMenuBar()->Check(id, (style & flag) != 0);
  325. }
  326.  
  327. void MyFrame::OnSize(wxSizeEvent& event)
  328. {
  329.     if ( m_treeCtrl && m_textCtrl )
  330.     {
  331.         Resize();
  332.     }
  333.  
  334.     event.Skip();
  335. }
  336.  
  337. void MyFrame::Resize()
  338. {
  339.     wxSize size = GetClientSize();
  340.     m_treeCtrl->SetSize(0, 0, size.x, 2*size.y/3);
  341.     m_textCtrl->SetSize(0, 2*size.y/3, size.x, size.y/3);
  342. }
  343.  
  344. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  345. {
  346.     Close(TRUE);
  347. }
  348.  
  349. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  350. {
  351.     wxMessageBox("Tree test sample\n"
  352.                  "(c) Julian Smart 1997, Vadim Zeitlin 1998",
  353.                  "About tree test",
  354.                  wxOK | wxICON_INFORMATION, this);
  355. }
  356.  
  357. void MyFrame::OnRename(wxCommandEvent& WXUNUSED(event))
  358. {
  359.     wxTreeItemId item = m_treeCtrl->GetSelection();
  360.  
  361.     CHECK_ITEM( item );
  362.  
  363.     // old code - now we edit in place
  364. #if 0
  365.     static wxString s_text;
  366.     s_text = wxGetTextFromUser("New name: ", "Tree sample question",
  367.             s_text, this);
  368.     if ( !s_text.IsEmpty() )
  369.     {
  370.         m_treeCtrl->SetItemText(item, s_text);
  371.     }
  372. #endif // 0
  373.  
  374.     // TODO demonstrate creating a custom edit control...
  375.     (void)m_treeCtrl->EditLabel(item);
  376. }
  377.  
  378. void MyFrame::OnCount(wxCommandEvent& WXUNUSED(event))
  379. {
  380.     wxTreeItemId item = m_treeCtrl->GetSelection();
  381.  
  382.     CHECK_ITEM( item );
  383.  
  384.     int i = m_treeCtrl->GetChildrenCount( item, FALSE );
  385.  
  386.     wxLogMessage(wxT("%d children"), i);
  387. }
  388.  
  389. void MyFrame::OnCountRec(wxCommandEvent& WXUNUSED(event))
  390. {
  391.     wxTreeItemId item = m_treeCtrl->GetSelection();
  392.  
  393.     CHECK_ITEM( item );
  394.  
  395.     int i = m_treeCtrl->GetChildrenCount( item );
  396.  
  397.     wxLogMessage(wxT("%d children"), i);
  398. }
  399.  
  400. void MyFrame::DoSort(bool reverse)
  401. {
  402.     wxTreeItemId item = m_treeCtrl->GetSelection();
  403.  
  404.     CHECK_ITEM( item );
  405.  
  406.     m_treeCtrl->DoSortChildren(item, reverse);
  407. }
  408.  
  409. void MyFrame::OnDump(wxCommandEvent& WXUNUSED(event))
  410. {
  411.     wxTreeItemId root = m_treeCtrl->GetSelection();
  412.  
  413.     CHECK_ITEM( root );
  414.  
  415.     m_treeCtrl->GetItemsRecursively(root, -1);
  416. }
  417.  
  418. #ifndef NO_MULTIPLE_SELECTION
  419.  
  420. void MyFrame::OnToggleSel(wxCommandEvent& event)
  421. {
  422.     TogStyle(event.GetId(), wxTR_MULTIPLE);
  423. }
  424.  
  425. void MyFrame::OnDumpSelected(wxCommandEvent& WXUNUSED(event))
  426. {
  427.     wxArrayTreeItemIds array;
  428.  
  429.     size_t count = m_treeCtrl->GetSelections(array);
  430.     wxLogMessage(wxT("%u items selected"), count);
  431.  
  432.     for ( size_t n = 0; n < count; n++ )
  433.     {
  434.         wxLogMessage(wxT("\t%s"), m_treeCtrl->GetItemText(array.Item(n)).c_str());
  435.     }
  436. }
  437.  
  438. void MyFrame::OnSelect(wxCommandEvent& event)
  439. {
  440.     m_treeCtrl->SelectItem(m_treeCtrl->GetSelection());
  441. }
  442.  
  443. void MyFrame::OnUnselect(wxCommandEvent& event)
  444. {
  445.     m_treeCtrl->UnselectAll();
  446. }
  447.  
  448. #endif // NO_MULTIPLE_SELECTION
  449.  
  450. void MyFrame::DoSetBold(bool bold)
  451. {
  452.     wxTreeItemId item = m_treeCtrl->GetSelection();
  453.  
  454.     CHECK_ITEM( item );
  455.  
  456.     m_treeCtrl->SetItemBold(item, bold);
  457. }
  458.  
  459. void MyFrame::OnDelete(wxCommandEvent& WXUNUSED(event))
  460. {
  461.     wxTreeItemId item = m_treeCtrl->GetSelection();
  462.  
  463.     CHECK_ITEM( item );
  464.  
  465.     m_treeCtrl->Delete(item);
  466. }
  467.  
  468. void MyFrame::OnDeleteChildren(wxCommandEvent& WXUNUSED(event))
  469. {
  470.     wxTreeItemId item = m_treeCtrl->GetSelection();
  471.  
  472.     CHECK_ITEM( item );
  473.  
  474.     m_treeCtrl->DeleteChildren(item);
  475. }
  476.  
  477. void MyFrame::OnDeleteAll(wxCommandEvent& WXUNUSED(event))
  478. {
  479.     m_treeCtrl->DeleteAllItems();
  480. }
  481.  
  482. void MyFrame::OnRecreate(wxCommandEvent& event)
  483. {
  484.     OnDeleteAll(event);
  485.     m_treeCtrl->AddTestItemsToTree(5, 2);
  486. }
  487.  
  488. void MyFrame::OnSetImageSize(wxCommandEvent& event)
  489. {
  490.     int size = wxGetNumberFromUser("Enter the size for the images to use",
  491.                                     "Size: ",
  492.                                     "TreeCtrl sample",
  493.                                     m_treeCtrl->ImageSize());
  494.     if ( size == -1 )
  495.         return;
  496.  
  497.     m_treeCtrl->CreateImageList(size);
  498.     wxGetApp().SetShowImages(TRUE);
  499. }
  500.  
  501. void MyFrame::OnToggleImages(wxCommandEvent& event)
  502. {
  503.     if ( wxGetApp().ShowImages() )
  504.     {
  505.         m_treeCtrl->CreateImageList(-1);
  506.         wxGetApp().SetShowImages(FALSE);
  507.     }
  508.     else
  509.     {
  510.         m_treeCtrl->CreateImageList(0);
  511.         wxGetApp().SetShowImages(TRUE);
  512.     }
  513. }
  514.  
  515. void MyFrame::OnToggleButtons(wxCommandEvent& event)
  516. {
  517. #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
  518.     if ( wxGetApp().ShowButtons() )
  519.     {
  520.         m_treeCtrl->CreateButtonsImageList(-1);
  521.         wxGetApp().SetShowButtons(FALSE);
  522.     }
  523.     else
  524.     {
  525.         m_treeCtrl->CreateButtonsImageList(15);
  526.         wxGetApp().SetShowButtons(TRUE);
  527.     }
  528. #endif
  529. }
  530.  
  531. void MyFrame::OnCollapseAndReset(wxCommandEvent& event)
  532. {
  533.     m_treeCtrl->CollapseAndReset(m_treeCtrl->GetRootItem());
  534. }
  535.  
  536. void MyFrame::OnEnsureVisible(wxCommandEvent& event)
  537. {
  538.     m_treeCtrl->DoEnsureVisible();
  539. }
  540.  
  541. void MyFrame::OnInsertItem(wxCommandEvent& WXUNUSED(event))
  542. {
  543.     int image = wxGetApp().ShowImages() ? MyTreeCtrl::TreeCtrlIcon_File : -1;
  544.     m_treeCtrl->InsertItem(m_treeCtrl->GetRootItem(), image, "2nd item");
  545. }
  546.  
  547. void MyFrame::OnAddItem(wxCommandEvent& WXUNUSED(event))
  548. {
  549.     static int s_num = 0;
  550.  
  551.     wxString text;
  552.     text.Printf(wxT("Item #%d"), ++s_num);
  553.  
  554.     m_treeCtrl->AppendItem(m_treeCtrl->GetRootItem(),
  555.                            text /*,
  556.                            MyTreeCtrl::TreeCtrlIcon_File */ );
  557. }
  558.  
  559. void MyFrame::OnIncIndent(wxCommandEvent& WXUNUSED(event))
  560. {
  561.     unsigned int indent = m_treeCtrl->GetIndent();
  562.     if (indent < 100)
  563.         m_treeCtrl->SetIndent( indent+5 );
  564. }
  565.  
  566. void MyFrame::OnDecIndent(wxCommandEvent& WXUNUSED(event))
  567. {
  568.     unsigned int indent = m_treeCtrl->GetIndent();
  569.     if (indent > 10)
  570.         m_treeCtrl->SetIndent( indent-5 );
  571. }
  572.  
  573. void MyFrame::OnIncSpacing(wxCommandEvent& WXUNUSED(event))
  574. {
  575.     unsigned int indent = m_treeCtrl->GetSpacing();
  576.     if (indent < 100)
  577.         m_treeCtrl->SetSpacing( indent+5 );
  578. }
  579.  
  580. void MyFrame::OnDecSpacing(wxCommandEvent& WXUNUSED(event))
  581. {
  582.     unsigned int indent = m_treeCtrl->GetSpacing();
  583.     if (indent > 10)
  584.         m_treeCtrl->SetSpacing( indent-5 );
  585. }
  586.  
  587. void MyFrame::OnToggleIcon(wxCommandEvent& WXUNUSED(event))
  588. {
  589.     wxTreeItemId item = m_treeCtrl->GetSelection();
  590.  
  591.     CHECK_ITEM( item );
  592.  
  593.     m_treeCtrl->DoToggleIcon(item);
  594. }
  595.  
  596. void MyFrame::OnSetFgColour(wxCommandEvent& WXUNUSED(event))
  597. {
  598.     wxColour col = wxGetColourFromUser(this, m_treeCtrl->GetForegroundColour());
  599.     if ( col.Ok() )
  600.         m_treeCtrl->SetForegroundColour(col);
  601. }
  602.  
  603. void MyFrame::OnSetBgColour(wxCommandEvent& WXUNUSED(event))
  604. {
  605.     wxColour col = wxGetColourFromUser(this, m_treeCtrl->GetBackgroundColour());
  606.     if ( col.Ok() )
  607.         m_treeCtrl->SetBackgroundColour(col);
  608. }
  609.  
  610. // MyTreeCtrl implementation
  611. #if USE_GENERIC_TREECTRL
  612. IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxGenericTreeCtrl)
  613. #else
  614. IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)
  615. #endif
  616.  
  617. MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
  618.                        const wxPoint& pos, const wxSize& size,
  619.                        long style)
  620.           : wxTreeCtrl(parent, id, pos, size, style)
  621. {
  622.     m_reverseSort = FALSE;
  623.  
  624.     CreateImageList();
  625.  
  626.     // Add some items to the tree
  627.     AddTestItemsToTree(5, 2);
  628. }
  629.  
  630. void MyTreeCtrl::CreateImageList(int size)
  631. {
  632.     if ( size == -1 )
  633.     {
  634.         SetImageList(NULL);
  635.         return;
  636.     }
  637.     if ( size == 0 )
  638.         size = m_imageSize;
  639.     else
  640.         m_imageSize = size;
  641.  
  642.     // Make an image list containing small icons
  643.     wxImageList *images = new wxImageList(size, size, TRUE);
  644.  
  645.     // should correspond to TreeCtrlIcon_xxx enum
  646.     wxBusyCursor wait;
  647.     wxIcon icons[5];
  648.     icons[0] = wxIcon(icon1_xpm);
  649.     icons[1] = wxIcon(icon2_xpm);
  650.     icons[2] = wxIcon(icon3_xpm);
  651.     icons[3] = wxIcon(icon4_xpm);
  652.     icons[4] = wxIcon(icon5_xpm);
  653.  
  654.     int sizeOrig = icons[0].GetWidth();
  655.     for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
  656.     {
  657.         if ( size == sizeOrig )
  658.         {
  659.             images->Add(icons[i]);
  660.         }
  661.         else
  662.         {
  663.             images->Add(wxBitmap(wxBitmap(icons[i]).ConvertToImage().Rescale(size, size)));
  664.         }
  665.     }
  666.  
  667.     AssignImageList(images);
  668. }
  669.  
  670. void MyTreeCtrl::CreateButtonsImageList(int size)
  671. {
  672. #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
  673.     if ( size == -1 )
  674.     {
  675.         SetButtonsImageList(NULL);
  676.         return;
  677.     }
  678.  
  679.     // Make an image list containing small icons
  680.     wxImageList *images = new wxImageList(size, size, TRUE);
  681.  
  682.     // should correspond to TreeCtrlIcon_xxx enum
  683.     wxBusyCursor wait;
  684.     wxIcon icons[4];
  685.     icons[0] = wxIcon(icon3_xpm);   // closed
  686.     icons[1] = wxIcon(icon3_xpm);   // closed, selected
  687.     icons[2] = wxIcon(icon5_xpm);   // open
  688.     icons[3] = wxIcon(icon5_xpm);   // open, selected
  689.  
  690.     for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
  691.     {
  692.         int sizeOrig = icons[i].GetWidth();
  693.         if ( size == sizeOrig )
  694.         {
  695.             images->Add(icons[i]);
  696.         }
  697.         else
  698.         {
  699.             images->Add(wxBitmap(icons[i].ConvertToImage().Rescale(size, size)));
  700.         }
  701.     }
  702.  
  703.     AssignButtonsImageList(images);
  704. #endif
  705. }
  706.  
  707. MyTreeCtrl::~MyTreeCtrl()
  708. {
  709. }
  710.  
  711. int MyTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
  712.                                const wxTreeItemId& item2)
  713. {
  714.     if ( m_reverseSort )
  715.     {
  716.         // just exchange 1st and 2nd items
  717.         return wxTreeCtrl::OnCompareItems(item2, item1);
  718.     }
  719.     else
  720.     {
  721.         return wxTreeCtrl::OnCompareItems(item1, item2);
  722.     }
  723. }
  724.  
  725. void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent,
  726.                                      size_t numChildren,
  727.                                      size_t depth,
  728.                                      size_t folder)
  729. {
  730.     if ( depth > 0 )
  731.     {
  732.         bool hasChildren = depth > 1;
  733.  
  734.         wxString str;
  735.         for ( size_t n = 0; n < numChildren; n++ )
  736.         {
  737.             // at depth 1 elements won't have any more children
  738.             if ( hasChildren )
  739.                 str.Printf(wxT("%s child %d"), wxT("Folder"), n + 1);
  740.             else
  741.                 str.Printf(wxT("%s child %d.%d"), wxT("File"), folder, n + 1);
  742.  
  743.             // here we pass to AppendItem() normal and selected item images (we
  744.             // suppose that selected image follows the normal one in the enum)
  745.             int image, imageSel;
  746.             if ( wxGetApp().ShowImages() )
  747.             {
  748.                 image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
  749.                 imageSel = image + 1;
  750.             }
  751.             else
  752.             {
  753.                 image = imageSel = -1;
  754.             }
  755.             wxTreeItemId id = AppendItem(idParent, str, image, imageSel,
  756.                                          new MyTreeItemData(str));
  757.  
  758.             // and now we also set the expanded one (only for the folders)
  759.             if ( hasChildren && wxGetApp().ShowImages() )
  760.             {
  761.                 SetItemImage(id, TreeCtrlIcon_FolderOpened,
  762.                              wxTreeItemIcon_Expanded);
  763.             }
  764.  
  765.             // remember the last child for OnEnsureVisible()
  766.             if ( !hasChildren && n == numChildren - 1 )
  767.             {
  768.                 m_lastItem = id;
  769.             }
  770.  
  771.             AddItemsRecursively(id, numChildren, depth - 1, n + 1);
  772.         }
  773.     }
  774.     //else: done!
  775. }
  776.  
  777. void MyTreeCtrl::AddTestItemsToTree(size_t numChildren,
  778.                                     size_t depth)
  779. {
  780.     int image = wxGetApp().ShowImages() ? MyTreeCtrl::TreeCtrlIcon_Folder : -1;
  781.     wxTreeItemId rootId = AddRoot("Root",
  782.                                   image, image,
  783.                                   new MyTreeItemData("Root item"));
  784.     if ( image != -1 )
  785.     {
  786.         SetItemImage(rootId, TreeCtrlIcon_FolderOpened, wxTreeItemIcon_Expanded);
  787.     }
  788.  
  789.     AddItemsRecursively(rootId, numChildren, depth, 0);
  790.  
  791.     // set some colours/fonts for testing
  792.     SetItemFont(rootId, *wxITALIC_FONT);
  793.  
  794.     long cookie;
  795.     wxTreeItemId id = GetFirstChild(rootId, cookie);
  796.     SetItemTextColour(id, *wxBLUE);
  797.  
  798.     id = GetNextChild(rootId, cookie);
  799.     id = GetNextChild(rootId, cookie);
  800.     SetItemTextColour(id, *wxRED);
  801.     SetItemBackgroundColour(id, *wxLIGHT_GREY);
  802. }
  803.  
  804. void MyTreeCtrl::GetItemsRecursively(const wxTreeItemId& idParent, long cookie)
  805. {
  806.     wxTreeItemId id;
  807.  
  808.     if( cookie == -1 )
  809.         id = GetFirstChild(idParent, cookie);
  810.     else
  811.         id = GetNextChild(idParent, cookie);
  812.  
  813.     if(id <= 0)
  814.         return;
  815.  
  816.     wxString text = GetItemText(id);
  817.     wxLogMessage(text);
  818.  
  819.     if (ItemHasChildren(id))
  820.         GetItemsRecursively(id,-1);
  821.  
  822.     GetItemsRecursively(idParent, cookie);
  823. }
  824.  
  825. void MyTreeCtrl::DoToggleIcon(const wxTreeItemId& item)
  826. {
  827.     int image = GetItemImage(item) == TreeCtrlIcon_Folder ? TreeCtrlIcon_File
  828.                                                           : TreeCtrlIcon_Folder;
  829.  
  830.     SetItemImage(item, image);
  831. }
  832.  
  833.  
  834. // avoid repetition
  835. #define TREE_EVENT_HANDLER(name)                                 \
  836. void MyTreeCtrl::name(wxTreeEvent& event)                        \
  837. {                                                                \
  838.     wxLogMessage(wxT(#name));                                    \
  839.     event.Skip();                                                \
  840. }
  841.  
  842. TREE_EVENT_HANDLER(OnBeginRDrag)
  843. TREE_EVENT_HANDLER(OnDeleteItem)
  844. TREE_EVENT_HANDLER(OnGetInfo)
  845. TREE_EVENT_HANDLER(OnSetInfo)
  846. TREE_EVENT_HANDLER(OnItemExpanded)
  847. TREE_EVENT_HANDLER(OnItemExpanding)
  848. TREE_EVENT_HANDLER(OnItemCollapsed)
  849. TREE_EVENT_HANDLER(OnSelChanged)
  850. TREE_EVENT_HANDLER(OnSelChanging)
  851.  
  852. #undef TREE_EVENT_HANDLER
  853.  
  854. void LogKeyEvent(const wxChar *name, const wxKeyEvent& event)
  855. {
  856.     wxString key;
  857.     long keycode = event.KeyCode();
  858.     {
  859.         switch ( keycode )
  860.         {
  861.             case WXK_BACK: key = "BACK"; break;
  862.             case WXK_TAB: key = "TAB"; break;
  863.             case WXK_RETURN: key = "RETURN"; break;
  864.             case WXK_ESCAPE: key = "ESCAPE"; break;
  865.             case WXK_SPACE: key = "SPACE"; break;
  866.             case WXK_DELETE: key = "DELETE"; break;
  867.             case WXK_START: key = "START"; break;
  868.             case WXK_LBUTTON: key = "LBUTTON"; break;
  869.             case WXK_RBUTTON: key = "RBUTTON"; break;
  870.             case WXK_CANCEL: key = "CANCEL"; break;
  871.             case WXK_MBUTTON: key = "MBUTTON"; break;
  872.             case WXK_CLEAR: key = "CLEAR"; break;
  873.             case WXK_SHIFT: key = "SHIFT"; break;
  874.             case WXK_ALT: key = "ALT"; break;
  875.             case WXK_CONTROL: key = "CONTROL"; break;
  876.             case WXK_MENU: key = "MENU"; break;
  877.             case WXK_PAUSE: key = "PAUSE"; break;
  878.             case WXK_CAPITAL: key = "CAPITAL"; break;
  879.             case WXK_PRIOR: key = "PRIOR"; break;
  880.             case WXK_NEXT: key = "NEXT"; break;
  881.             case WXK_END: key = "END"; break;
  882.             case WXK_HOME: key = "HOME"; break;
  883.             case WXK_LEFT: key = "LEFT"; break;
  884.             case WXK_UP: key = "UP"; break;
  885.             case WXK_RIGHT: key = "RIGHT"; break;
  886.             case WXK_DOWN: key = "DOWN"; break;
  887.             case WXK_SELECT: key = "SELECT"; break;
  888.             case WXK_PRINT: key = "PRINT"; break;
  889.             case WXK_EXECUTE: key = "EXECUTE"; break;
  890.             case WXK_SNAPSHOT: key = "SNAPSHOT"; break;
  891.             case WXK_INSERT: key = "INSERT"; break;
  892.             case WXK_HELP: key = "HELP"; break;
  893.             case WXK_NUMPAD0: key = "NUMPAD0"; break;
  894.             case WXK_NUMPAD1: key = "NUMPAD1"; break;
  895.             case WXK_NUMPAD2: key = "NUMPAD2"; break;
  896.             case WXK_NUMPAD3: key = "NUMPAD3"; break;
  897.             case WXK_NUMPAD4: key = "NUMPAD4"; break;
  898.             case WXK_NUMPAD5: key = "NUMPAD5"; break;
  899.             case WXK_NUMPAD6: key = "NUMPAD6"; break;
  900.             case WXK_NUMPAD7: key = "NUMPAD7"; break;
  901.             case WXK_NUMPAD8: key = "NUMPAD8"; break;
  902.             case WXK_NUMPAD9: key = "NUMPAD9"; break;
  903.             case WXK_MULTIPLY: key = "MULTIPLY"; break;
  904.             case WXK_ADD: key = "ADD"; break;
  905.             case WXK_SEPARATOR: key = "SEPARATOR"; break;
  906.             case WXK_SUBTRACT: key = "SUBTRACT"; break;
  907.             case WXK_DECIMAL: key = "DECIMAL"; break;
  908.             case WXK_DIVIDE: key = "DIVIDE"; break;
  909.             case WXK_F1: key = "F1"; break;
  910.             case WXK_F2: key = "F2"; break;
  911.             case WXK_F3: key = "F3"; break;
  912.             case WXK_F4: key = "F4"; break;
  913.             case WXK_F5: key = "F5"; break;
  914.             case WXK_F6: key = "F6"; break;
  915.             case WXK_F7: key = "F7"; break;
  916.             case WXK_F8: key = "F8"; break;
  917.             case WXK_F9: key = "F9"; break;
  918.             case WXK_F10: key = "F10"; break;
  919.             case WXK_F11: key = "F11"; break;
  920.             case WXK_F12: key = "F12"; break;
  921.             case WXK_F13: key = "F13"; break;
  922.             case WXK_F14: key = "F14"; break;
  923.             case WXK_F15: key = "F15"; break;
  924.             case WXK_F16: key = "F16"; break;
  925.             case WXK_F17: key = "F17"; break;
  926.             case WXK_F18: key = "F18"; break;
  927.             case WXK_F19: key = "F19"; break;
  928.             case WXK_F20: key = "F20"; break;
  929.             case WXK_F21: key = "F21"; break;
  930.             case WXK_F22: key = "F22"; break;
  931.             case WXK_F23: key = "F23"; break;
  932.             case WXK_F24: key = "F24"; break;
  933.             case WXK_NUMLOCK: key = "NUMLOCK"; break;
  934.             case WXK_SCROLL: key = "SCROLL"; break;
  935.             case WXK_PAGEUP: key = "PAGEUP"; break;
  936.             case WXK_PAGEDOWN: key = "PAGEDOWN"; break;
  937.             case WXK_NUMPAD_SPACE: key = "NUMPAD_SPACE"; break;
  938.             case WXK_NUMPAD_TAB: key = "NUMPAD_TAB"; break;
  939.             case WXK_NUMPAD_ENTER: key = "NUMPAD_ENTER"; break;
  940.             case WXK_NUMPAD_F1: key = "NUMPAD_F1"; break;
  941.             case WXK_NUMPAD_F2: key = "NUMPAD_F2"; break;
  942.             case WXK_NUMPAD_F3: key = "NUMPAD_F3"; break;
  943.             case WXK_NUMPAD_F4: key = "NUMPAD_F4"; break;
  944.             case WXK_NUMPAD_HOME: key = "NUMPAD_HOME"; break;
  945.             case WXK_NUMPAD_LEFT: key = "NUMPAD_LEFT"; break;
  946.             case WXK_NUMPAD_UP: key = "NUMPAD_UP"; break;
  947.             case WXK_NUMPAD_RIGHT: key = "NUMPAD_RIGHT"; break;
  948.             case WXK_NUMPAD_DOWN: key = "NUMPAD_DOWN"; break;
  949.             case WXK_NUMPAD_PRIOR: key = "NUMPAD_PRIOR"; break;
  950.             case WXK_NUMPAD_PAGEUP: key = "NUMPAD_PAGEUP"; break;
  951.             case WXK_NUMPAD_PAGEDOWN: key = "NUMPAD_PAGEDOWN"; break;
  952.             case WXK_NUMPAD_END: key = "NUMPAD_END"; break;
  953.             case WXK_NUMPAD_BEGIN: key = "NUMPAD_BEGIN"; break;
  954.             case WXK_NUMPAD_INSERT: key = "NUMPAD_INSERT"; break;
  955.             case WXK_NUMPAD_DELETE: key = "NUMPAD_DELETE"; break;
  956.             case WXK_NUMPAD_EQUAL: key = "NUMPAD_EQUAL"; break;
  957.             case WXK_NUMPAD_MULTIPLY: key = "NUMPAD_MULTIPLY"; break;
  958.             case WXK_NUMPAD_ADD: key = "NUMPAD_ADD"; break;
  959.             case WXK_NUMPAD_SEPARATOR: key = "NUMPAD_SEPARATOR"; break;
  960.             case WXK_NUMPAD_SUBTRACT: key = "NUMPAD_SUBTRACT"; break;
  961.             case WXK_NUMPAD_DECIMAL: key = "NUMPAD_DECIMAL"; break;
  962.  
  963.             default:
  964.             {
  965.                if ( wxIsprint((int)keycode) )
  966.                    key.Printf(_T("'%c'"), (char)keycode);
  967.                else if ( keycode > 0 && keycode < 27 )
  968.                    key.Printf(_("Ctrl-%c"), _T('A') + keycode - 1);
  969.                else
  970.                    key.Printf(_T("unknown (%ld)"), keycode);
  971.             }
  972.         }
  973.     }
  974.  
  975.     wxLogMessage( _T("%s event: %s (flags = %c%c%c%c)"),
  976.                   name,
  977.                   key.c_str(),
  978.                   event.ControlDown() ? _T('C') : _T('-'),
  979.                   event.AltDown() ? _T('A') : _T('-'),
  980.                   event.ShiftDown() ? _T('S') : _T('-'),
  981.                   event.MetaDown() ? _T('M') : _T('-'));
  982. }
  983.  
  984. void MyTreeCtrl::OnTreeKeyDown(wxTreeEvent& event)
  985. {
  986.     LogKeyEvent(_T("Tree key down "), event.GetKeyEvent());
  987.  
  988.     event.Skip();
  989. }
  990.  
  991. void MyTreeCtrl::OnBeginDrag(wxTreeEvent& event)
  992. {
  993.     // need to explicitly allow drag
  994.     if ( event.GetItem() != GetRootItem() )
  995.     {
  996.         m_draggedItem = event.GetItem();
  997.  
  998.         wxLogMessage(wxT("OnBeginDrag: started dragging %s"),
  999.                      GetItemText(m_draggedItem).c_str());
  1000.  
  1001.         event.Allow();
  1002.     }
  1003.     else
  1004.     {
  1005.         wxLogMessage(wxT("OnBeginDrag: this item can't be dragged."));
  1006.     }
  1007. }
  1008.  
  1009. void MyTreeCtrl::OnEndDrag(wxTreeEvent& event)
  1010. {
  1011.     wxTreeItemId itemSrc = m_draggedItem,
  1012.                  itemDst = event.GetItem();
  1013.     m_draggedItem = (wxTreeItemId)0l;
  1014.  
  1015.     // where to copy the item?
  1016.     if ( itemDst.IsOk() && !ItemHasChildren(itemDst) )
  1017.     {
  1018.         // copy to the parent then
  1019.         itemDst = GetParent(itemDst);
  1020.     }
  1021.  
  1022.     if ( !itemDst.IsOk() )
  1023.     {
  1024.         wxLogMessage(wxT("OnEndDrag: can't drop here."));
  1025.  
  1026.         return;
  1027.     }
  1028.  
  1029.     wxString text = GetItemText(itemSrc);
  1030.     wxLogMessage(wxT("OnEndDrag: '%s' copied to '%s'."),
  1031.                  text.c_str(), GetItemText(itemDst).c_str());
  1032.  
  1033.     // just do append here - we could also insert it just before/after the item
  1034.     // on which it was dropped, but this requires slightly more work... we also
  1035.     // completely ignore the client data and icon of the old item but could
  1036.     // copy them as well.
  1037.     //
  1038.     // Finally, we only copy one item here but we might copy the entire tree if
  1039.     // we were dragging a folder.
  1040.     int image = wxGetApp().ShowImages() ? TreeCtrlIcon_File : -1;
  1041.     AppendItem(itemDst, text, image);
  1042. }
  1043.  
  1044. void MyTreeCtrl::OnBeginLabelEdit(wxTreeEvent& event)
  1045. {
  1046.     wxLogMessage(wxT("OnBeginLabelEdit"));
  1047.  
  1048.     // for testing, prevent this item's label editing
  1049.     wxTreeItemId itemId = event.GetItem();
  1050.     if ( IsTestItem(itemId) )
  1051.     {
  1052.         wxMessageBox(wxT("You can't edit this item."));
  1053.  
  1054.         event.Veto();
  1055.     }
  1056. }
  1057.  
  1058. void MyTreeCtrl::OnEndLabelEdit(wxTreeEvent& event)
  1059. {
  1060.     wxLogMessage(wxT("OnEndLabelEdit"));
  1061.  
  1062.     // don't allow anything except letters in the labels
  1063.     if ( !event.GetLabel().IsWord() )
  1064.     {
  1065.         wxMessageBox(wxT("The new label should be a single word."));
  1066.  
  1067.         event.Veto();
  1068.     }
  1069. }
  1070.  
  1071. void MyTreeCtrl::OnItemCollapsing(wxTreeEvent& event)
  1072. {
  1073.     wxLogMessage(wxT("OnItemCollapsing"));
  1074.  
  1075.     // for testing, prevent the user from collapsing the first child folder
  1076.     wxTreeItemId itemId = event.GetItem();
  1077.     if ( IsTestItem(itemId) )
  1078.     {
  1079.         wxMessageBox(wxT("You can't collapse this item."));
  1080.  
  1081.         event.Veto();
  1082.     }
  1083. }
  1084.  
  1085. void MyTreeCtrl::OnItemActivated(wxTreeEvent& event)
  1086. {
  1087.     // show some info about this item
  1088.     wxTreeItemId itemId = event.GetItem();
  1089.     MyTreeItemData *item = (MyTreeItemData *)GetItemData(itemId);
  1090.  
  1091.     if ( item != NULL )
  1092.     {
  1093.         item->ShowInfo(this);
  1094.     }
  1095.  
  1096.     wxLogMessage(wxT("OnItemActivated"));
  1097. }
  1098.  
  1099. void MyTreeCtrl::OnItemRightClick(wxTreeEvent& event)
  1100. {
  1101.     ShowMenu(event.GetItem(), event.GetPoint());
  1102. }
  1103.  
  1104. void MyTreeCtrl::OnRMouseUp(wxMouseEvent& event)
  1105. {
  1106.     wxPoint pt = event.GetPosition();
  1107.     ShowMenu(HitTest(pt), pt);
  1108. }
  1109.  
  1110. void MyTreeCtrl::ShowMenu(wxTreeItemId id, const wxPoint& pt)
  1111. {
  1112.     wxString title;
  1113.     if ( id.IsOk() )
  1114.     {
  1115.         title << _T("Menu for ") << GetItemText(id);
  1116.     }
  1117.     else
  1118.     {
  1119.         title = _T("Menu for no particular item");
  1120.     }
  1121.  
  1122. #if wxUSE_MENUS
  1123.     wxMenu menu(title);
  1124.     menu.Append(TreeTest_About, _T("&About..."));
  1125.     menu.Append(TreeTest_Dump, _T("&Dump"));
  1126.  
  1127.     PopupMenu(&menu, pt);
  1128. #endif // wxUSE_MENUS
  1129. }
  1130.  
  1131. void MyTreeCtrl::OnRMouseDClick(wxMouseEvent& event)
  1132. {
  1133.     wxTreeItemId id = HitTest(event.GetPosition());
  1134.     if ( !id )
  1135.         wxLogMessage(wxT("No item under mouse"));
  1136.     else
  1137.     {
  1138.         MyTreeItemData *item = (MyTreeItemData *)GetItemData(id);
  1139.         if ( item )
  1140.             wxLogMessage(wxT("Item '%s' under mouse"), item->GetDesc());
  1141.     }
  1142. }
  1143.  
  1144. static inline const wxChar *Bool2String(bool b)
  1145. {
  1146.     return b ? wxT("") : wxT("not ");
  1147. }
  1148.  
  1149. void MyTreeItemData::ShowInfo(wxTreeCtrl *tree)
  1150. {
  1151.     wxLogMessage(wxT("Item '%s': %sselected, %sexpanded, %sbold,\n")
  1152.                  wxT("%u children (%u immediately under this item)."),
  1153.                  m_desc.c_str(),
  1154.                  Bool2String(tree->IsSelected(GetId())),
  1155.                  Bool2String(tree->IsExpanded(GetId())),
  1156.                  Bool2String(tree->IsBold(GetId())),
  1157.                  tree->GetChildrenCount(GetId()),
  1158.                  tree->GetChildrenCount(GetId(), FALSE));
  1159. }
  1160.