]> git.saurik.com Git - wxWidgets.git/blob - samples/treectrl/treetest.cpp
628f84ce8e3d040a38dc37c6a4dd5a2f911382f7
[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 EVT_MENU(TreeTest_EnsureVisible, MyFrame::OnEnsureVisible)
65 END_EVENT_TABLE()
66
67 BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl)
68 EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginDrag)
69 EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginRDrag)
70 EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnBeginLabelEdit)
71 EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnEndLabelEdit)
72 EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, MyTreeCtrl::OnDeleteItem)
73 EVT_TREE_GET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnGetInfo)
74 EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo)
75 EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded)
76 EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding)
77 EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsed)
78 EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing)
79 EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged)
80 EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging)
81 EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnTreeKeyDown)
82 EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, MyTreeCtrl::OnItemActivated)
83 END_EVENT_TABLE()
84
85 IMPLEMENT_APP(MyApp)
86
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 tree_menu->AppendSeparator();
134 tree_menu->Append(TreeTest_EnsureVisible, "Make the last item &visible");
135
136 wxMenuBar *menu_bar = new wxMenuBar;
137 menu_bar->Append(file_menu, "&File");
138 menu_bar->Append(tree_menu, "&Tree");
139 SetMenuBar(menu_bar);
140
141 m_treeCtrl = new MyTreeCtrl(this, TreeTest_Ctrl,
142 wxDefaultPosition, wxDefaultSize,
143 wxTR_HAS_BUTTONS | wxSUNKEN_BORDER);
144 wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, "",
145 wxDefaultPosition, wxDefaultSize,
146 wxTE_MULTILINE | wxSUNKEN_BORDER);
147
148 wxLayoutConstraints *c = new wxLayoutConstraints;
149 c->top.SameAs(this, wxTop);
150 c->left.SameAs(this, wxLeft);
151 c->right.SameAs(this, wxRight);
152 c->height.PercentOf(this, wxHeight, 66);
153 m_treeCtrl->SetConstraints(c);
154
155 c = new wxLayoutConstraints;
156 c->top.Below(m_treeCtrl);
157 c->left.SameAs(this, wxLeft);
158 c->right.SameAs(this, wxRight);
159 c->bottom.SameAs(this, wxBottom);
160 textCtrl->SetConstraints(c);
161 SetAutoLayout(TRUE);
162
163 // create a status bar with 3 panes
164 CreateStatusBar(3);
165 SetStatusText("", 0);
166
167 #ifdef __WXMOTIF__
168 // For some reason, we get a memcpy crash in wxLogStream::DoLogStream
169 // on gcc/wxMotif, if we use wxLogTextCtl. Maybe it's just gcc?
170 delete wxLog::SetActiveTarget(new wxLogStderr);
171 #else
172 // set our text control as the log target
173 wxLogTextCtrl *logWindow = new wxLogTextCtrl(textCtrl);
174 delete wxLog::SetActiveTarget(logWindow);
175 #endif
176 }
177
178 MyFrame::~MyFrame()
179 {
180 delete wxLog::SetActiveTarget(NULL);
181 }
182
183 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
184 {
185 Close(TRUE);
186 }
187
188 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
189 {
190 wxMessageBox("Tree test sample\n"
191 "Julian Smart (c) 1997,\n"
192 "Vadim Zeitlin (c) 1998",
193 "About tree test",
194 wxOK | wxICON_INFORMATION, this);
195 }
196
197 void MyFrame::OnRename(wxCommandEvent& WXUNUSED(event))
198 {
199 wxTreeItemId item = m_treeCtrl->GetSelection();
200
201 CHECK_ITEM( item );
202
203 static wxString s_text;
204 s_text = wxGetTextFromUser("New name: ", "Tree sample question",
205 s_text, this);
206 if ( !s_text.IsEmpty() )
207 {
208 m_treeCtrl->SetItemText(item, s_text);
209 }
210 }
211
212 void MyFrame::DoSort(bool reverse)
213 {
214 wxTreeItemId item = m_treeCtrl->GetSelection();
215
216 CHECK_ITEM( item );
217
218 m_treeCtrl->DoSortChildren(item, reverse);
219 }
220
221 void MyFrame::OnDump(wxCommandEvent& WXUNUSED(event))
222 {
223 wxTreeItemId root = m_treeCtrl->GetSelection();
224
225 CHECK_ITEM( root );
226
227 m_treeCtrl->GetItemsRecursively(root, -1);
228 }
229
230 void MyFrame::DoSetBold(bool bold)
231 {
232 wxTreeItemId item = m_treeCtrl->GetSelection();
233
234 CHECK_ITEM( item );
235
236 m_treeCtrl->SetItemBold(item, bold);
237 }
238
239 void MyFrame::OnDelete(wxCommandEvent& WXUNUSED(event))
240 {
241 wxTreeItemId item = m_treeCtrl->GetSelection();
242
243 CHECK_ITEM( item );
244
245 m_treeCtrl->Delete(item);
246 }
247
248 void MyFrame::OnDeleteChildren(wxCommandEvent& WXUNUSED(event))
249 {
250 wxTreeItemId item = m_treeCtrl->GetSelection();
251
252 CHECK_ITEM( item );
253
254 m_treeCtrl->DeleteChildren(item);
255 }
256
257 void MyFrame::OnDeleteAll(wxCommandEvent& WXUNUSED(event))
258 {
259 m_treeCtrl->DeleteAllItems();
260 }
261
262 void MyFrame::OnRecreate(wxCommandEvent& event)
263 {
264 OnDeleteAll(event);
265 m_treeCtrl->AddTestItemsToTree(3, 2);
266 }
267
268 void MyFrame::OnEnsureVisible(wxCommandEvent& event)
269 {
270 m_treeCtrl->DoEnsureVisible();
271 }
272
273 // MyTreeCtrl implementation
274 IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)
275
276 MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
277 const wxPoint& pos, const wxSize& size,
278 long style)
279 : wxTreeCtrl(parent, id, pos, size, style)
280 {
281 m_reverseSort = FALSE;
282
283 // Make an image list containing small icons
284 m_imageListNormal = new wxImageList(16, 16, TRUE);
285
286 // should correspond to TreeCtrlIcon_xxx enum
287 #if defined(__WXMSW__) && defined(__WIN16__)
288 // This is required in 16-bit Windows mode only because we can't load a specific (16x16)
289 // icon image, so it comes out stretched
290 m_imageListNormal->Add(wxBitmap("bitmap1", wxBITMAP_TYPE_BMP_RESOURCE));
291 m_imageListNormal->Add(wxBitmap("bitmap2", wxBITMAP_TYPE_BMP_RESOURCE));
292 #else
293 m_imageListNormal->Add(wxICON(icon1));
294 m_imageListNormal->Add(wxICON(icon2));
295 #endif
296
297 SetImageList(m_imageListNormal);
298
299 // Add some items to the tree
300 AddTestItemsToTree(3, 2);
301 }
302
303 MyTreeCtrl::~MyTreeCtrl()
304 {
305 delete m_imageListNormal;
306 }
307
308 int MyTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
309 const wxTreeItemId& item2)
310 {
311 if ( m_reverseSort )
312 {
313 // just exchange 1st and 2nd items
314 return wxTreeCtrl::OnCompareItems(item2, item1);
315 }
316 else
317 {
318 return wxTreeCtrl::OnCompareItems(item1, item2);
319 }
320 }
321
322 void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent,
323 size_t numChildren,
324 size_t depth,
325 size_t folder)
326 {
327 if ( depth > 0 )
328 {
329 wxString str;
330 for ( size_t n = 0; n < numChildren; n++ )
331 {
332 // at depth 1 elements won't have any more children
333 if (depth == 1)
334 str.Printf("%s child %d.%d", "File", folder, n + 1);
335 else
336 str.Printf("%s child %d", "Folder", n + 1);
337
338 int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
339 wxTreeItemId id = AppendItem(idParent, str, image, image,
340 new MyTreeItemData(str));
341
342 // remember the last child for OnEnsureVisible()
343 if ( depth == 1 && n == numChildren - 1 )
344 {
345 m_lastItem = id;
346 }
347
348 AddItemsRecursively(id, numChildren, depth - 1, n + 1);
349 }
350 }
351 //else: done!
352 }
353
354 void MyTreeCtrl::AddTestItemsToTree(size_t numChildren,
355 size_t depth)
356 {
357 wxTreeItemId rootId = AddRoot("Root",
358 TreeCtrlIcon_Folder, TreeCtrlIcon_Folder,
359 new MyTreeItemData("Root item"));
360
361 AddItemsRecursively(rootId, numChildren, depth, 0);
362 }
363
364 void MyTreeCtrl::GetItemsRecursively(const wxTreeItemId& idParent, long cookie)
365 {
366 wxTreeItemId id;
367
368 if( cookie == -1 )
369 id = GetFirstChild(idParent, cookie);
370 else
371 id = GetNextChild(idParent, cookie);
372
373 if(id <= 0)
374 return;
375
376 wxString text=GetItemText(id);
377 wxLogMessage(text);
378
379 if (ItemHasChildren(id))
380 GetItemsRecursively(id,-1);
381
382 GetItemsRecursively(idParent, cookie);
383 }
384
385
386 // avoid repetition
387 #define TREE_EVENT_HANDLER(name) \
388 void MyTreeCtrl::name(wxTreeEvent& WXUNUSED(event)) \
389 { \
390 wxLogMessage(#name); \
391 }
392
393 TREE_EVENT_HANDLER(OnBeginDrag)
394 TREE_EVENT_HANDLER(OnBeginRDrag)
395 TREE_EVENT_HANDLER(OnBeginLabelEdit)
396 TREE_EVENT_HANDLER(OnEndLabelEdit)
397 TREE_EVENT_HANDLER(OnDeleteItem)
398 TREE_EVENT_HANDLER(OnGetInfo)
399 TREE_EVENT_HANDLER(OnSetInfo)
400 TREE_EVENT_HANDLER(OnItemExpanded)
401 TREE_EVENT_HANDLER(OnItemExpanding)
402 TREE_EVENT_HANDLER(OnItemCollapsed)
403 TREE_EVENT_HANDLER(OnSelChanged)
404 TREE_EVENT_HANDLER(OnSelChanging)
405
406 #undef TREE_EVENT_HANDLER
407
408 void MyTreeCtrl::OnItemCollapsing(wxTreeEvent& event)
409 {
410 wxLogMessage("OnItemCollapsing");
411
412 // for testing, prevent the user from collapsing the root item
413 wxTreeItemId itemId = event.GetItem();
414 if ( !GetParent(itemId).IsOk() )
415 {
416 wxMessageBox("You can't collapse the root item.");
417
418 event.Veto();
419 }
420 }
421
422 void MyTreeCtrl::OnTreeKeyDown(wxTreeEvent&WXUNUSED(event))
423 {
424 wxLogMessage("OnTreeKeyDown");
425 }
426
427 void MyTreeCtrl::OnItemActivated(wxTreeEvent&WXUNUSED(event))
428 {
429 // show some info about this item
430 wxTreeItemId itemId = GetSelection();
431 MyTreeItemData *item = (MyTreeItemData *)GetItemData(itemId);
432
433 if ( item != NULL )
434 {
435 item->ShowInfo(this);
436 }
437
438 wxLogMessage("OnItemActivated");
439 }
440
441 static inline const char *Bool2String(bool b)
442 {
443 return b ? "" : "not ";
444 }
445
446 void MyTreeItemData::ShowInfo(wxTreeCtrl *tree)
447 {
448 wxLogMessage("Item '%s': %sselected, %sexpanded, %sbold,\n"
449 "%u children (%u immediately under this item).",
450 m_desc.c_str(),
451 Bool2String(tree->IsSelected(GetId())),
452 Bool2String(tree->IsExpanded(GetId())),
453 Bool2String(tree->IsBold(GetId())),
454 tree->GetChildrenCount(GetId()),
455 tree->GetChildrenCount(GetId(), FALSE));
456 }