]> git.saurik.com Git - wxWidgets.git/blob - samples/treectrl/treetest.cpp
missing functions implemented in wxMSW tree ctrl (custom sorting,
[wxWidgets.git] / samples / treectrl / treetest.cpp
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$
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 #endif
27
28 // under Windows the icons are in the .rc file
29 #ifndef __WXMSW__
30 #include "icon1.xpm"
31 #include "icon2.xpm"
32 #include "mondrian.xpm"
33 #endif
34
35 #include "wx/log.h"
36
37 #include "wx/imaglist.h"
38 #include "wx/treectrl.h"
39
40 #include "treetest.h"
41
42 // verify that the item is ok and insult the user if it is not
43 #define CHECK_ITEM( item ) if ( !item.IsOk() ) { \
44 wxMessageBox("Please select some item first!", \
45 "Tree sample error", \
46 wxOK | wxICON_EXCLAMATION, \
47 this); \
48 return; \
49 }
50
51 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
52 EVT_MENU(TreeTest_Quit, MyFrame::OnQuit)
53 EVT_MENU(TreeTest_About, MyFrame::OnAbout)
54 EVT_MENU(TreeTest_Dump, MyFrame::OnDump)
55 EVT_MENU(TreeTest_Rename, MyFrame::OnRename)
56 EVT_MENU(TreeTest_Sort, MyFrame::OnSort)
57 EVT_MENU(TreeTest_SortRev, MyFrame::OnSortRev)
58 EVT_MENU(TreeTest_Bold, MyFrame::OnSetBold)
59 EVT_MENU(TreeTest_UnBold, MyFrame::OnClearBold)
60 EVT_MENU(TreeTest_Delete, MyFrame::OnDelete)
61 EVT_MENU(TreeTest_DeleteChildren, MyFrame::OnDeleteChildren)
62 EVT_MENU(TreeTest_DeleteAll, MyFrame::OnDeleteAll)
63 EVT_MENU(TreeTest_Recreate, MyFrame::OnRecreate)
64 END_EVENT_TABLE()
65
66 BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl)
67 EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginDrag)
68 EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginRDrag)
69 EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnBeginLabelEdit)
70 EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnEndLabelEdit)
71 EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, MyTreeCtrl::OnDeleteItem)
72 EVT_TREE_GET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnGetInfo)
73 EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo)
74 EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded)
75 EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding)
76 EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsed)
77 EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing)
78 EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged)
79 EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging)
80 EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnTreeKeyDown)
81 EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, MyTreeCtrl::OnItemActivated)
82 END_EVENT_TABLE()
83
84 IMPLEMENT_APP(MyApp)
85
86 // `Main program' equivalent, creating windows and returning main app frame
87 bool MyApp::OnInit()
88 {
89 // Create the main frame window
90 MyFrame *frame = new MyFrame("wxTreeCtrl Test", 50, 50, 450, 340);
91
92 // Show the frame
93 frame->Show(TRUE);
94 SetTopWindow(frame);
95
96 return TRUE;
97 }
98
99
100 // My frame constructor
101 MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h)
102 : wxFrame((wxFrame *)NULL, -1, title, wxPoint(x, y), wxSize(w, h))
103 {
104 // This reduces flicker effects - even better would be to define
105 // OnEraseBackground to do nothing. When the tree control's scrollbars are
106 // show or hidden, the frame is sent a background erase event.
107 SetBackgroundColour(wxColour(255, 255, 255));
108
109 // Give it an icon
110 SetIcon(wxICON(mondrian));
111
112 // Make a menubar
113 wxMenu *file_menu = new wxMenu,
114 *tree_menu = new wxMenu;
115
116 file_menu->Append(TreeTest_About, "&About...");
117 file_menu->AppendSeparator();
118 file_menu->Append(TreeTest_Quit, "E&xit");
119
120 tree_menu->Append(TreeTest_Dump, "D&ump tree items");
121 tree_menu->Append(TreeTest_Recreate, "&Recreate the tree");
122 tree_menu->AppendSeparator();
123 tree_menu->Append(TreeTest_Delete, "&Delete this item");
124 tree_menu->Append(TreeTest_DeleteChildren, "Delete &children");
125 tree_menu->Append(TreeTest_DeleteAll, "Delete &all items");
126 tree_menu->AppendSeparator();
127 tree_menu->Append(TreeTest_Sort, "Sort children of current item");
128 tree_menu->Append(TreeTest_SortRev, "Sort in reversed order");
129 tree_menu->Append(TreeTest_Rename, "Rename item...");
130 tree_menu->AppendSeparator();
131 tree_menu->Append(TreeTest_Bold, "Make item &bold");
132 tree_menu->Append(TreeTest_UnBold, "Make item &not bold");
133
134 wxMenuBar *menu_bar = new wxMenuBar;
135 menu_bar->Append(file_menu, "&File");
136 menu_bar->Append(tree_menu, "&Tree");
137 SetMenuBar(menu_bar);
138
139 // Make a panel with a message
140 m_treeCtrl = new MyTreeCtrl(this, TreeTest_Ctrl,
141 wxDefaultPosition, wxDefaultSize,
142 wxTR_HAS_BUTTONS | wxSUNKEN_BORDER);
143 wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, "",
144 wxDefaultPosition, wxDefaultSize,
145 wxTE_MULTILINE | wxSUNKEN_BORDER);
146
147 wxLayoutConstraints *c = new wxLayoutConstraints;
148 c->top.SameAs(this, wxTop);
149 c->left.SameAs(this, wxLeft);
150 c->right.SameAs(this, wxRight);
151 c->height.PercentOf(this, wxHeight, 66);
152 m_treeCtrl->SetConstraints(c);
153
154 c = new wxLayoutConstraints;
155 c->top.Below(m_treeCtrl);
156 c->left.SameAs(this, wxLeft);
157 c->right.SameAs(this, wxRight);
158 c->bottom.SameAs(this, wxBottom);
159 textCtrl->SetConstraints(c);
160 SetAutoLayout(TRUE);
161
162 // create a status bar with 3 panes
163 CreateStatusBar(3);
164 SetStatusText("", 0);
165
166 #ifdef __WXMOTIF__
167 // For some reason, we get a memcpy crash in wxLogStream::DoLogStream
168 // on gcc/wxMotif, if we use wxLogTextCtl. Maybe it's just gcc?
169 delete wxLog::SetActiveTarget(new wxLogStderr);
170 #else
171 // set our text control as the log target
172 wxLogTextCtrl *logWindow = new wxLogTextCtrl(textCtrl);
173 delete wxLog::SetActiveTarget(logWindow);
174 #endif
175 }
176
177 MyFrame::~MyFrame()
178 {
179 delete wxLog::SetActiveTarget(NULL);
180 }
181
182 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
183 {
184 Close(TRUE);
185 }
186
187 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
188 {
189 wxMessageBox("Tree test sample\n"
190 "Julian Smart (c) 1997,\n"
191 "Vadim Zeitlin (c) 1998",
192 "About tree test",
193 wxOK | wxICON_INFORMATION, this);
194 }
195
196 void MyFrame::OnRename(wxCommandEvent& WXUNUSED(event))
197 {
198 wxTreeItemId item = m_treeCtrl->GetSelection();
199
200 CHECK_ITEM( item );
201
202 static wxString s_text;
203 s_text = wxGetTextFromUser("New name: ", "Tree sample question",
204 s_text, this);
205 if ( !s_text.IsEmpty() )
206 {
207 m_treeCtrl->SetItemText(item, s_text);
208 }
209 }
210
211 void MyFrame::DoSort(bool reverse)
212 {
213 wxTreeItemId item = m_treeCtrl->GetSelection();
214
215 CHECK_ITEM( item );
216
217 m_treeCtrl->DoSortChildren(item, reverse);
218 }
219
220 void MyFrame::OnDump(wxCommandEvent& WXUNUSED(event))
221 {
222 wxTreeItemId root = m_treeCtrl->GetSelection();
223
224 CHECK_ITEM( root );
225
226 m_treeCtrl->GetItemsRecursively(root, -1);
227 }
228
229 void MyFrame::DoSetBold(bool bold)
230 {
231 wxTreeItemId item = m_treeCtrl->GetSelection();
232
233 CHECK_ITEM( item );
234
235 m_treeCtrl->SetItemBold(item, bold);
236 }
237
238 void MyFrame::OnDelete(wxCommandEvent& WXUNUSED(event))
239 {
240 wxTreeItemId item = m_treeCtrl->GetSelection();
241
242 CHECK_ITEM( item );
243
244 m_treeCtrl->Delete(item);
245 }
246
247 void MyFrame::OnDeleteChildren(wxCommandEvent& WXUNUSED(event))
248 {
249 wxTreeItemId item = m_treeCtrl->GetSelection();
250
251 CHECK_ITEM( item );
252
253 m_treeCtrl->DeleteChildren(item);
254 }
255
256 void MyFrame::OnDeleteAll(wxCommandEvent& WXUNUSED(event))
257 {
258 m_treeCtrl->DeleteAllItems();
259 }
260
261 void MyFrame::OnRecreate(wxCommandEvent& event)
262 {
263 OnDeleteAll(event);
264 m_treeCtrl->AddTestItemsToTree(3, 2);
265 }
266
267 // MyTreeCtrl implementation
268 IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)
269
270 MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
271 const wxPoint& pos, const wxSize& size,
272 long style)
273 : wxTreeCtrl(parent, id, pos, size, style)
274 {
275 m_reverseSort = FALSE;
276
277 // Make an image list containing small icons
278 m_imageListNormal = new wxImageList(16, 16, TRUE);
279
280 // should correspond to TreeCtrlIcon_xxx enum
281 m_imageListNormal->Add(wxICON(icon1));
282 m_imageListNormal->Add(wxICON(icon2));
283
284 SetImageList(m_imageListNormal);
285
286 // Add some items to the tree
287 AddTestItemsToTree(3, 2);
288 }
289
290 MyTreeCtrl::~MyTreeCtrl()
291 {
292 delete m_imageListNormal;
293 }
294
295 int MyTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
296 const wxTreeItemId& item2)
297 {
298 if ( m_reverseSort )
299 {
300 // just exchange 1st and 2nd items
301 return wxTreeCtrl::OnCompareItems(item2, item1);
302 }
303 else
304 {
305 return wxTreeCtrl::OnCompareItems(item1, item2);
306 }
307 }
308
309 void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent,
310 size_t numChildren,
311 size_t depth,
312 size_t folder)
313 {
314 if ( depth > 0 )
315 {
316 wxString str;
317 for ( size_t n = 0; n < numChildren; n++ )
318 {
319 // at depth 1 elements won't have any more children
320 if (depth == 1)
321 str.Printf("%s child %d.%d", "File", folder, n + 1);
322 else
323 str.Printf("%s child %d","Folder", n + 1);
324
325 int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
326 wxTreeItemId id = AppendItem(idParent, str, image, image,
327 new MyTreeItemData(str));
328 AddItemsRecursively(id, numChildren, depth - 1, n + 1);
329 }
330 }
331 //else: done!
332 }
333
334 void MyTreeCtrl::AddTestItemsToTree(size_t numChildren,
335 size_t depth)
336 {
337 wxTreeItemId rootId = AddRoot("Root",
338 TreeCtrlIcon_Folder, TreeCtrlIcon_Folder,
339 new MyTreeItemData("Root item"));
340
341 AddItemsRecursively(rootId, numChildren, depth, 0);
342 }
343
344 void MyTreeCtrl::GetItemsRecursively(const wxTreeItemId& idParent, long cookie)
345 {
346 wxTreeItemId id;
347
348 if( cookie == -1 )
349 id = GetFirstChild(idParent, cookie);
350 else
351 id = GetNextChild(idParent, cookie);
352
353 if(id <= 0)
354 return;
355
356 wxString text=GetItemText(id);
357 wxLogMessage(text);
358
359 if (ItemHasChildren(id))
360 GetItemsRecursively(id,-1);
361
362 GetItemsRecursively(idParent, cookie);
363 }
364
365
366 // avoid repetition
367 #define TREE_EVENT_HANDLER(name) \
368 void MyTreeCtrl::name(wxTreeEvent& WXUNUSED(event)) \
369 { \
370 wxLogMessage(#name); \
371 }
372
373 TREE_EVENT_HANDLER(OnBeginDrag)
374 TREE_EVENT_HANDLER(OnBeginRDrag)
375 TREE_EVENT_HANDLER(OnBeginLabelEdit)
376 TREE_EVENT_HANDLER(OnEndLabelEdit)
377 TREE_EVENT_HANDLER(OnDeleteItem)
378 TREE_EVENT_HANDLER(OnGetInfo)
379 TREE_EVENT_HANDLER(OnSetInfo)
380 TREE_EVENT_HANDLER(OnItemExpanded)
381 TREE_EVENT_HANDLER(OnItemExpanding)
382 TREE_EVENT_HANDLER(OnItemCollapsed)
383 TREE_EVENT_HANDLER(OnSelChanged)
384 TREE_EVENT_HANDLER(OnSelChanging)
385
386 #undef TREE_EVENT_HANDLER
387
388 void MyTreeCtrl::OnItemCollapsing(wxTreeEvent& event)
389 {
390 wxLogMessage("OnItemCollapsing");
391
392 // for testing, prevent the user from collapsing the root item
393 wxTreeItemId itemId = event.GetItem();
394 if ( !GetParent(itemId).IsOk() )
395 {
396 wxMessageBox("You can't collapse the root item.");
397
398 event.Veto();
399 }
400 }
401
402 void MyTreeCtrl::OnTreeKeyDown(wxTreeEvent&WXUNUSED(event))
403 {
404 wxLogMessage("OnTreeKeyDown");
405 }
406
407 void MyTreeCtrl::OnItemActivated(wxTreeEvent&WXUNUSED(event))
408 {
409 // show some info about this item
410 wxTreeItemId itemId = GetSelection();
411 MyTreeItemData *item = (MyTreeItemData *)GetItemData(itemId);
412
413 if ( item != NULL )
414 {
415 item->ShowInfo(this);
416 }
417
418 wxLogMessage("OnItemActivated");
419 }
420
421 static inline const char *Bool2String(bool b)
422 {
423 return b ? "" : "not ";
424 }
425
426 void MyTreeItemData::ShowInfo(wxTreeCtrl *tree)
427 {
428 wxLogMessage("Item '%s': %sselected, %sexpanded, %sbold,\n"
429 "%u children (%u immediately under this item).",
430 m_desc.c_str(),
431 Bool2String(tree->IsSelected(GetId())),
432 Bool2String(tree->IsExpanded(GetId())),
433 Bool2String(tree->IsBold(GetId())),
434 tree->GetChildrenCount(GetId()),
435 tree->GetChildrenCount(GetId(), FALSE));
436 }