]> git.saurik.com Git - wxWidgets.git/blob - samples/treectrl/treetest.cpp
check wxUSE_LIBJPEG
[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 #include "wx/log.h"
29
30 #include "wx/image.h"
31 #include "wx/imaglist.h"
32 #include "wx/treectrl.h"
33
34 #include "math.h"
35
36 #include "treetest.h"
37
38 #ifdef wxTR_HAS_VARIABLE_ROW_HIGHT
39 #define USE_TR_HAS_VARIABLE_ROW_HIGHT 1
40 #else
41 #define USE_TR_HAS_VARIABLE_ROW_HIGHT 0
42 #endif
43
44 // under Windows the icons are in the .rc file
45 #ifndef __WXMSW__
46 #if !USE_TR_HAS_VARIABLE_ROW_HIGHT
47 #include "icon1.xpm"
48 #endif
49 #include "icon2.xpm"
50 #include "mondrian.xpm"
51 #endif
52
53
54 // verify that the item is ok and insult the user if it is not
55 #define CHECK_ITEM( item ) if ( !item.IsOk() ) { \
56 wxMessageBox("Please select some item first!", \
57 "Tree sample error", \
58 wxOK | wxICON_EXCLAMATION, \
59 this); \
60 return; \
61 }
62
63 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
64 EVT_MENU(TreeTest_Quit, MyFrame::OnQuit)
65 EVT_MENU(TreeTest_About, MyFrame::OnAbout)
66 EVT_MENU(TreeTest_Dump, MyFrame::OnDump)
67 EVT_MENU(TreeTest_Dump_Selected, MyFrame::OnDumpSelected)
68 EVT_MENU(TreeTest_Rename, MyFrame::OnRename)
69 EVT_MENU(TreeTest_Sort, MyFrame::OnSort)
70 EVT_MENU(TreeTest_SortRev, MyFrame::OnSortRev)
71 EVT_MENU(TreeTest_Bold, MyFrame::OnSetBold)
72 EVT_MENU(TreeTest_UnBold, MyFrame::OnClearBold)
73 EVT_MENU(TreeTest_Delete, MyFrame::OnDelete)
74 EVT_MENU(TreeTest_DeleteChildren, MyFrame::OnDeleteChildren)
75 EVT_MENU(TreeTest_DeleteAll, MyFrame::OnDeleteAll)
76 EVT_MENU(TreeTest_Recreate, MyFrame::OnRecreate)
77 EVT_MENU(TreeTest_CollapseAndReset, MyFrame::OnCollapseAndReset)
78 EVT_MENU(TreeTest_EnsureVisible, MyFrame::OnEnsureVisible)
79 EVT_MENU(TreeTest_AddItem, MyFrame::OnAddItem)
80 EVT_MENU(TreeTest_IncIndent, MyFrame::OnIncIndent)
81 EVT_MENU(TreeTest_DecIndent, MyFrame::OnDecIndent)
82 EVT_MENU(TreeTest_IncSpacing, MyFrame::OnIncSpacing)
83 EVT_MENU(TreeTest_DecSpacing, MyFrame::OnDecSpacing)
84 END_EVENT_TABLE()
85
86 BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl)
87 EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginDrag)
88 EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginRDrag)
89 EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnBeginLabelEdit)
90 EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnEndLabelEdit)
91 EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, MyTreeCtrl::OnDeleteItem)
92 EVT_TREE_GET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnGetInfo)
93 EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo)
94 EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded)
95 EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding)
96 EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsed)
97 EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing)
98 EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged)
99 EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging)
100 EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnTreeKeyDown)
101 EVT_TREE_ITEM_ACTIVATED(TreeTest_Ctrl, MyTreeCtrl::OnItemActivated)
102 EVT_RIGHT_DCLICK(MyTreeCtrl::OnRMouseDClick)
103 END_EVENT_TABLE()
104
105 IMPLEMENT_APP(MyApp)
106
107 bool MyApp::OnInit()
108 {
109 // Create the main frame window
110 MyFrame *frame = new MyFrame("wxTreeCtrl Test", 50, 50, 450, 340);
111
112 // Show the frame
113 frame->Show(TRUE);
114 SetTopWindow(frame);
115
116 return TRUE;
117 }
118
119
120 // My frame constructor
121 MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h)
122 : wxFrame((wxFrame *)NULL, -1, title, wxPoint(x, y), wxSize(w, h))
123 {
124 // This reduces flicker effects - even better would be to define
125 // OnEraseBackground to do nothing. When the tree control's scrollbars are
126 // show or hidden, the frame is sent a background erase event.
127 SetBackgroundColour(wxColour(255, 255, 255));
128
129 // Give it an icon
130 SetIcon(wxICON(mondrian));
131
132 // Make a menubar
133 wxMenu *file_menu = new wxMenu,
134 *tree_menu = new wxMenu,
135 *item_menu = new wxMenu;
136
137 file_menu->Append(TreeTest_About, "&About...");
138 file_menu->AppendSeparator();
139 file_menu->Append(TreeTest_Quit, "E&xit");
140
141 tree_menu->Append(TreeTest_Recreate, "&Recreate the tree");
142 tree_menu->Append(TreeTest_CollapseAndReset, "C&ollapse and reset");
143 tree_menu->AppendSeparator();
144 tree_menu->Append(TreeTest_AddItem, "Append a &new item");
145 tree_menu->Append(TreeTest_Delete, "&Delete this item");
146 tree_menu->Append(TreeTest_DeleteChildren, "Delete &children");
147 tree_menu->Append(TreeTest_DeleteAll, "Delete &all items");
148 tree_menu->AppendSeparator();
149 tree_menu->Append(TreeTest_Sort, "Sort children of current item");
150 tree_menu->Append(TreeTest_SortRev, "Sort in reversed order");
151 tree_menu->AppendSeparator();
152 tree_menu->Append(TreeTest_EnsureVisible, "Make the last item &visible");
153 tree_menu->AppendSeparator();
154 tree_menu->Append(TreeTest_IncIndent, "Add 5 points to indentation\tAlt-I");
155 tree_menu->Append(TreeTest_DecIndent, "Reduce indentation by 5 points\tAlt-R");
156 tree_menu->AppendSeparator();
157 tree_menu->Append(TreeTest_IncSpacing, "Add 5 points to spacing\tCtrl-I");
158 tree_menu->Append(TreeTest_DecSpacing, "Reduce spacing by 5 points\tCtrl-R");
159
160 item_menu->AppendSeparator();
161 item_menu->Append(TreeTest_Dump, "&Dump item children");
162 #ifdef wxTR_MULTIPLE
163 item_menu->Append(TreeTest_Dump_Selected, "Dump selected items\tAlt-S");
164 #endif
165 item_menu->Append(TreeTest_Rename, "&Rename item...");
166
167 item_menu->AppendSeparator();
168 item_menu->Append(TreeTest_Bold, "Make item &bold");
169 item_menu->Append(TreeTest_UnBold, "Make item &not bold");
170
171 wxMenuBar *menu_bar = new wxMenuBar;
172 menu_bar->Append(file_menu, "&File");
173 menu_bar->Append(tree_menu, "&Tree");
174 menu_bar->Append(item_menu, "&Item");
175 SetMenuBar(menu_bar);
176
177 m_treeCtrl = new MyTreeCtrl(this, TreeTest_Ctrl,
178 wxDefaultPosition, wxDefaultSize,
179 wxTR_HAS_BUTTONS |
180 #ifdef wxTR_MULTIPLE
181 wxTR_MULTIPLE |
182 #endif
183 #if USE_TR_HAS_VARIABLE_ROW_HIGHT
184 wxTR_HAS_VARIABLE_ROW_HIGHT |
185 #endif
186 wxSUNKEN_BORDER);
187 wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, "",
188 wxDefaultPosition, wxDefaultSize,
189 wxTE_MULTILINE | wxSUNKEN_BORDER);
190
191 wxLayoutConstraints *c = new wxLayoutConstraints;
192 c->top.SameAs(this, wxTop);
193 c->left.SameAs(this, wxLeft);
194 c->right.SameAs(this, wxRight);
195 c->height.PercentOf(this, wxHeight, 66);
196 m_treeCtrl->SetConstraints(c);
197
198 c = new wxLayoutConstraints;
199 c->top.Below(m_treeCtrl);
200 c->left.SameAs(this, wxLeft);
201 c->right.SameAs(this, wxRight);
202 c->bottom.SameAs(this, wxBottom);
203 textCtrl->SetConstraints(c);
204 SetAutoLayout(TRUE);
205
206 // create a status bar with 3 panes
207 CreateStatusBar(3);
208 SetStatusText("", 0);
209
210 #ifdef __WXMOTIF__
211 // For some reason, we get a memcpy crash in wxLogStream::DoLogStream
212 // on gcc/wxMotif, if we use wxLogTextCtl. Maybe it's just gcc?
213 delete wxLog::SetActiveTarget(new wxLogStderr);
214 #else
215 // set our text control as the log target
216 wxLogTextCtrl *logWindow = new wxLogTextCtrl(textCtrl);
217 delete wxLog::SetActiveTarget(logWindow);
218 #endif
219 }
220
221 MyFrame::~MyFrame()
222 {
223 delete wxLog::SetActiveTarget(NULL);
224 }
225
226 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
227 {
228 Close(TRUE);
229 }
230
231 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
232 {
233 wxMessageBox("Tree test sample\n"
234 "Julian Smart (c) 1997,\n"
235 "Vadim Zeitlin (c) 1998",
236 "About tree test",
237 wxOK | wxICON_INFORMATION, this);
238 }
239
240 void MyFrame::OnRename(wxCommandEvent& WXUNUSED(event))
241 {
242 wxTreeItemId item = m_treeCtrl->GetSelection();
243
244 CHECK_ITEM( item );
245
246 static wxString s_text;
247 s_text = wxGetTextFromUser("New name: ", "Tree sample question",
248 s_text, this);
249 if ( !s_text.IsEmpty() )
250 {
251 m_treeCtrl->SetItemText(item, s_text);
252 }
253 }
254
255 void MyFrame::DoSort(bool reverse)
256 {
257 wxTreeItemId item = m_treeCtrl->GetSelection();
258
259 CHECK_ITEM( item );
260
261 m_treeCtrl->DoSortChildren(item, reverse);
262 }
263
264 void MyFrame::OnDump(wxCommandEvent& WXUNUSED(event))
265 {
266 wxTreeItemId root = m_treeCtrl->GetSelection();
267
268 CHECK_ITEM( root );
269
270 m_treeCtrl->GetItemsRecursively(root, -1);
271 }
272
273 void MyFrame::OnDumpSelected(wxCommandEvent& WXUNUSED(event))
274 {
275 #ifdef wxTR_MULTIPLE
276 wxArrayTreeItemIds array;
277
278 m_treeCtrl->GetSelections(array);
279 size_t nos=array.Count();
280 wxLogMessage(wxString("items selected : ")<< (int)nos);
281
282 for (size_t n=0; n<nos; ++n)
283 wxLogMessage(m_treeCtrl->GetItemText(array.Item(n)));
284 #endif
285 }
286
287 void MyFrame::DoSetBold(bool bold)
288 {
289 wxTreeItemId item = m_treeCtrl->GetSelection();
290
291 CHECK_ITEM( item );
292
293 m_treeCtrl->SetItemBold(item, bold);
294 }
295
296 void MyFrame::OnDelete(wxCommandEvent& WXUNUSED(event))
297 {
298 wxTreeItemId item = m_treeCtrl->GetSelection();
299
300 CHECK_ITEM( item );
301
302 m_treeCtrl->Delete(item);
303 }
304
305 void MyFrame::OnDeleteChildren(wxCommandEvent& WXUNUSED(event))
306 {
307 wxTreeItemId item = m_treeCtrl->GetSelection();
308
309 CHECK_ITEM( item );
310
311 m_treeCtrl->DeleteChildren(item);
312 }
313
314 void MyFrame::OnDeleteAll(wxCommandEvent& WXUNUSED(event))
315 {
316 m_treeCtrl->DeleteAllItems();
317 }
318
319 void MyFrame::OnRecreate(wxCommandEvent& event)
320 {
321 OnDeleteAll(event);
322 m_treeCtrl->AddTestItemsToTree(3, 2);
323 }
324
325 void MyFrame::OnCollapseAndReset(wxCommandEvent& event)
326 {
327 m_treeCtrl->CollapseAndReset(m_treeCtrl->GetRootItem());
328 }
329
330 void MyFrame::OnEnsureVisible(wxCommandEvent& event)
331 {
332 m_treeCtrl->DoEnsureVisible();
333 }
334
335 void MyFrame::OnAddItem(wxCommandEvent& WXUNUSED(event))
336 {
337 static int s_num = 0;
338
339 wxString text;
340 text.Printf("Item #%d", ++s_num);
341
342 m_treeCtrl->AppendItem(m_treeCtrl->GetRootItem(),
343 text,
344 MyTreeCtrl::TreeCtrlIcon_File);
345 }
346
347 void MyFrame::OnIncIndent(wxCommandEvent& WXUNUSED(event))
348 {
349 unsigned int indent = m_treeCtrl->GetIndent();
350 if (indent < 100)
351 m_treeCtrl->SetIndent( indent+5 );
352 }
353
354 void MyFrame::OnDecIndent(wxCommandEvent& WXUNUSED(event))
355 {
356 unsigned int indent = m_treeCtrl->GetIndent();
357 if (indent > 10)
358 m_treeCtrl->SetIndent( indent-5 );
359 }
360
361 void MyFrame::OnIncSpacing(wxCommandEvent& WXUNUSED(event))
362 {
363 unsigned int indent = m_treeCtrl->GetSpacing();
364 if (indent < 100)
365 m_treeCtrl->SetSpacing( indent+5 );
366 }
367
368 void MyFrame::OnDecSpacing(wxCommandEvent& WXUNUSED(event))
369 {
370 unsigned int indent = m_treeCtrl->GetSpacing();
371 if (indent > 10)
372 m_treeCtrl->SetSpacing( indent-5 );
373 }
374
375 // MyTreeCtrl implementation
376 IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)
377
378 MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
379 const wxPoint& pos, const wxSize& size,
380 long style)
381 : wxTreeCtrl(parent, id, pos, size, style)
382 {
383 #if (USE_TR_HAS_VARIABLE_ROW_HIGHT && wxUSE_LIBJPEG)
384 wxImage::AddHandler(new wxJPEGHandler);
385 wxImage image;
386
387 image.LoadFile(wxString("horse.jpg"), wxBITMAP_TYPE_JPEG );
388 #endif
389
390 m_reverseSort = FALSE;
391
392 // Make an image list containing small icons
393 m_imageListNormal = new wxImageList(16, 16, TRUE);
394
395 // should correspond to TreeCtrlIcon_xxx enum
396 #if defined(__WXMSW__) && defined(__WIN16__)
397 // This is required in 16-bit Windows mode only because we can't load a specific (16x16)
398 // icon image, so it comes out stretched
399 # if USE_TR_HAS_VARIABLE_ROW_HIGHT
400 m_imageListNormal->Add(image.ConvertToBitmap());
401 # else
402 m_imageListNormal->Add(wxBitmap("bitmap1", wxBITMAP_TYPE_BMP_RESOURCE));
403 # endif
404 m_imageListNormal->Add(wxBitmap("bitmap2", wxBITMAP_TYPE_BMP_RESOURCE));
405 #else
406 # if USE_TR_HAS_VARIABLE_ROW_HIGHT
407 m_imageListNormal->Add(image.ConvertToBitmap());
408 # else
409 m_imageListNormal->Add(wxICON(icon1));
410 # endif
411 m_imageListNormal->Add(wxICON(icon2));
412 #endif
413
414 SetImageList(m_imageListNormal);
415
416 // Add some items to the tree
417 AddTestItemsToTree(3, 2);
418 }
419
420 MyTreeCtrl::~MyTreeCtrl()
421 {
422 delete m_imageListNormal;
423 }
424
425 int MyTreeCtrl::OnCompareItems(const wxTreeItemId& item1,
426 const wxTreeItemId& item2)
427 {
428 if ( m_reverseSort )
429 {
430 // just exchange 1st and 2nd items
431 return wxTreeCtrl::OnCompareItems(item2, item1);
432 }
433 else
434 {
435 return wxTreeCtrl::OnCompareItems(item1, item2);
436 }
437 }
438
439 void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent,
440 size_t numChildren,
441 size_t depth,
442 size_t folder)
443 {
444 if ( depth > 0 )
445 {
446 wxString str;
447 for ( size_t n = 0; n < numChildren; n++ )
448 {
449 // at depth 1 elements won't have any more children
450 if (depth == 1)
451 str.Printf("%s child %d.%d", "File", folder, n + 1);
452 else
453 str.Printf("%s child %d", "Folder", n + 1);
454
455 int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
456 wxTreeItemId id = AppendItem(idParent, str, image, image,
457 new MyTreeItemData(str));
458
459 // remember the last child for OnEnsureVisible()
460 if ( depth == 1 && n == numChildren - 1 )
461 {
462 m_lastItem = id;
463 }
464
465 AddItemsRecursively(id, numChildren, depth - 1, n + 1);
466 }
467 }
468 //else: done!
469 }
470
471 void MyTreeCtrl::AddTestItemsToTree(size_t numChildren,
472 size_t depth)
473 {
474 wxTreeItemId rootId = AddRoot("Root",
475 TreeCtrlIcon_Folder, TreeCtrlIcon_Folder,
476 new MyTreeItemData("Root item"));
477
478 AddItemsRecursively(rootId, numChildren, depth, 0);
479 }
480
481 void MyTreeCtrl::GetItemsRecursively(const wxTreeItemId& idParent, long cookie)
482 {
483 wxTreeItemId id;
484
485 if( cookie == -1 )
486 id = GetFirstChild(idParent, cookie);
487 else
488 id = GetNextChild(idParent, cookie);
489
490 if(id <= 0)
491 return;
492
493 wxString text=GetItemText(id);
494 wxLogMessage(text);
495
496 if (ItemHasChildren(id))
497 GetItemsRecursively(id,-1);
498
499 GetItemsRecursively(idParent, cookie);
500 }
501
502
503 // avoid repetition
504 #define TREE_EVENT_HANDLER(name) \
505 void MyTreeCtrl::name(wxTreeEvent& WXUNUSED(event)) \
506 { \
507 wxLogMessage(#name); \
508 }
509
510 TREE_EVENT_HANDLER(OnBeginDrag)
511 TREE_EVENT_HANDLER(OnBeginRDrag)
512 TREE_EVENT_HANDLER(OnBeginLabelEdit)
513 TREE_EVENT_HANDLER(OnEndLabelEdit)
514 TREE_EVENT_HANDLER(OnDeleteItem)
515 TREE_EVENT_HANDLER(OnGetInfo)
516 TREE_EVENT_HANDLER(OnSetInfo)
517 TREE_EVENT_HANDLER(OnItemExpanded)
518 TREE_EVENT_HANDLER(OnItemExpanding)
519 TREE_EVENT_HANDLER(OnItemCollapsed)
520 TREE_EVENT_HANDLER(OnSelChanged)
521 TREE_EVENT_HANDLER(OnSelChanging)
522
523 #undef TREE_EVENT_HANDLER
524
525 void MyTreeCtrl::OnItemCollapsing(wxTreeEvent& event)
526 {
527 wxLogMessage("OnItemCollapsing");
528
529 // for testing, prevent the user from collapsing the first child folder
530 wxTreeItemId itemId = event.GetItem();
531 if ( GetParent(itemId) == GetRootItem() && !GetPrevSibling(itemId) )
532 {
533 wxMessageBox("You can't collapse this item.");
534
535 event.Veto();
536 }
537 }
538
539 void MyTreeCtrl::OnTreeKeyDown(wxTreeEvent&WXUNUSED(event))
540 {
541 wxLogMessage("OnTreeKeyDown");
542 }
543
544 void MyTreeCtrl::OnItemActivated(wxTreeEvent&WXUNUSED(event))
545 {
546 // show some info about this item
547 wxTreeItemId itemId = GetSelection();
548 MyTreeItemData *item = (MyTreeItemData *)GetItemData(itemId);
549
550 if ( item != NULL )
551 {
552 item->ShowInfo(this);
553 }
554
555 wxLogMessage("OnItemActivated");
556 }
557
558 void MyTreeCtrl::OnRMouseDClick(wxMouseEvent& event)
559 {
560 wxTreeItemId id = HitTest(event.GetPosition());
561 if ( !id )
562 wxLogMessage("No item under mouse");
563 else
564 {
565 MyTreeItemData *item = (MyTreeItemData *)GetItemData(id);
566 if ( item )
567 wxLogMessage("Item '%s' under mouse", item->GetDesc());
568 }
569 }
570
571 static inline const char *Bool2String(bool b)
572 {
573 return b ? "" : "not ";
574 }
575
576 void MyTreeItemData::ShowInfo(wxTreeCtrl *tree)
577 {
578 wxLogMessage("Item '%s': %sselected, %sexpanded, %sbold,\n"
579 "%u children (%u immediately under this item).",
580 m_desc.c_str(),
581 Bool2String(tree->IsSelected(GetId())),
582 Bool2String(tree->IsExpanded(GetId())),
583 Bool2String(tree->IsBold(GetId())),
584 tree->GetChildrenCount(GetId()),
585 tree->GetChildrenCount(GetId(), FALSE));
586 }