]> git.saurik.com Git - wxWidgets.git/blob - src/msw/treectrl.cpp
aa41b2d72223e0964014d450472eee8eebc87eef
[wxWidgets.git] / src / msw / treectrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: treectrl.cpp
3 // Purpose: wxTreeCtrl
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin to be less MSW-specific on 10.10.98
6 // Created: 1997
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19 #ifdef __GNUG__
20 #pragma implementation "treectrl.h"
21 #endif
22
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 #ifndef WX_PRECOMP
31 #include "wx.h"
32 #endif
33
34 #if defined(__WIN95__)
35
36 #include "wx/log.h"
37 #include "wx/imaglist.h"
38
39 #include "wx/msw/private.h"
40
41 #ifndef __GNUWIN32__
42 #include <commctrl.h>
43 #endif
44
45 #ifdef GetFirstChild
46 #undef GetFirstChild
47 #endif
48
49 #ifdef GetNextChild
50 #undef GetNextChild
51 #endif
52
53 #ifdef GetNextSibling
54 #undef GetNextSibling
55 #endif
56
57 #include "wx/treectrl.h"
58
59 // Bug in headers, sometimes
60 #ifndef TVIS_FOCUSED
61 #define TVIS_FOCUSED 0x0001
62 #endif
63
64 // ----------------------------------------------------------------------------
65 // private classes
66 // ----------------------------------------------------------------------------
67
68 // a convenient wrapper around TV_ITEM struct which adds a ctor
69 struct wxTreeViewItem : public TV_ITEM
70 {
71 wxTreeViewItem(const wxTreeItemId& item,
72 UINT mask_, UINT stateMask_ = 0)
73 {
74 mask = mask_;
75 stateMask = stateMask_;
76 hItem = (HTREEITEM) (WXHTREEITEM) item;
77 }
78 };
79
80 // ----------------------------------------------------------------------------
81 // macros
82 // ----------------------------------------------------------------------------
83
84 #if !USE_SHARED_LIBRARY
85 IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl)
86 #endif
87
88 // hide the ugly cast (of course, the macro is _quite_ ugly too...)
89 #define wxhWnd ((HWND)m_hWnd)
90
91 // ----------------------------------------------------------------------------
92 // variables
93 // ----------------------------------------------------------------------------
94
95 // handy table for sending events
96 static const wxEventType g_events[2][2] =
97 {
98 { wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxEVT_COMMAND_TREE_ITEM_COLLAPSING },
99 { wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxEVT_COMMAND_TREE_ITEM_EXPANDING }
100 };
101
102 // ============================================================================
103 // implementation
104 // ============================================================================
105
106 // ----------------------------------------------------------------------------
107 // construction and destruction
108 // ----------------------------------------------------------------------------
109
110 void wxTreeCtrl::Init()
111 {
112 m_imageListNormal = NULL;
113 m_imageListState = NULL;
114 m_textCtrl = NULL;
115 }
116
117 bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id,
118 const wxPoint& pos, const wxSize& size,
119 long style, const wxValidator& validator,
120 const wxString& name)
121 {
122 Init();
123
124 wxSystemSettings settings;
125
126 SetName(name);
127 SetValidator(validator);
128
129 m_windowStyle = style;
130
131 SetParent(parent);
132
133 m_windowId = (id == -1) ? NewControlId() : id;
134
135 DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | TVS_HASLINES;
136
137 bool want3D;
138 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
139
140 // Even with extended styles, need to combine with WS_BORDER
141 // for them to look right.
142 if ( want3D || wxStyleHasBorder(m_windowStyle) )
143 {
144 wstyle |= WS_BORDER;
145 }
146
147 if ( m_windowStyle & wxTR_HAS_BUTTONS )
148 wstyle |= TVS_HASBUTTONS;
149
150 if ( m_windowStyle & wxTR_EDIT_LABELS )
151 wstyle |= TVS_EDITLABELS;
152
153 if ( m_windowStyle & wxTR_LINES_AT_ROOT )
154 wstyle |= TVS_LINESATROOT;
155
156 // Create the tree control.
157 m_hWnd = (WXHWND)::CreateWindowEx
158 (
159 exStyle,
160 WC_TREEVIEW,
161 "",
162 wstyle,
163 pos.x, pos.y, size.x, size.y,
164 (HWND)parent->GetHWND(),
165 (HMENU)m_windowId,
166 wxGetInstance(),
167 NULL
168 );
169
170 wxCHECK_MSG( m_hWnd, FALSE, "Failed to create tree ctrl" );
171
172 if ( parent )
173 parent->AddChild(this);
174
175 SubclassWin(m_hWnd);
176
177 return TRUE;
178 }
179
180 wxTreeCtrl::~wxTreeCtrl()
181 {
182 DeleteTextCtrl();
183
184 // delete user data to prevent memory leaks
185 DeleteAllItems();
186 }
187
188 // ----------------------------------------------------------------------------
189 // accessors
190 // ----------------------------------------------------------------------------
191
192 // simple wrappers which add error checking in debug mode
193
194 bool wxTreeCtrl::DoGetItem(wxTreeViewItem* tvItem) const
195 {
196 if ( !TreeView_GetItem(wxhWnd, tvItem) )
197 {
198 wxLogLastError("TreeView_GetItem");
199
200 return FALSE;
201 }
202
203 return TRUE;
204 }
205
206 void wxTreeCtrl::DoSetItem(wxTreeViewItem* tvItem)
207 {
208 if ( TreeView_SetItem(wxhWnd, tvItem) == -1 )
209 {
210 wxLogLastError("TreeView_SetItem");
211 }
212 }
213
214 size_t wxTreeCtrl::GetCount() const
215 {
216 return (size_t)TreeView_GetCount(wxhWnd);
217 }
218
219 unsigned int wxTreeCtrl::GetIndent() const
220 {
221 return TreeView_GetIndent(wxhWnd);
222 }
223
224 void wxTreeCtrl::SetIndent(unsigned int indent)
225 {
226 TreeView_SetIndent(wxhWnd, indent);
227 }
228
229 wxImageList *wxTreeCtrl::GetImageList() const
230 {
231 return m_imageListNormal;
232 }
233
234 wxImageList *wxTreeCtrl::GetStateImageList() const
235 {
236 return m_imageListNormal;
237 }
238
239 void wxTreeCtrl::SetAnyImageList(wxImageList *imageList, int which)
240 {
241 // no error return
242 TreeView_SetImageList(wxhWnd,
243 imageList ? imageList->GetHIMAGELIST() : 0,
244 which);
245 }
246
247 void wxTreeCtrl::SetImageList(wxImageList *imageList)
248 {
249 SetAnyImageList(m_imageListNormal = imageList, TVSIL_NORMAL);
250 }
251
252 void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
253 {
254 SetAnyImageList(m_imageListState = imageList, TVSIL_STATE);
255 }
256
257 // ----------------------------------------------------------------------------
258 // Item access
259 // ----------------------------------------------------------------------------
260
261 wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const
262 {
263 char buf[512]; // the size is arbitrary...
264
265 wxTreeViewItem tvItem(item, TVIF_TEXT);
266 tvItem.pszText = buf;
267 tvItem.cchTextMax = WXSIZEOF(buf);
268 if ( !DoGetItem(&tvItem) )
269 {
270 // don't return some garbage which was on stack, but an empty string
271 buf[0] = '\0';
272 }
273
274 return wxString(buf);
275 }
276
277 void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text)
278 {
279 wxTreeViewItem tvItem(item, TVIF_TEXT);
280 tvItem.pszText = (char *)text.c_str(); // conversion is ok
281 DoSetItem(&tvItem);
282 }
283
284 int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const
285 {
286 wxTreeViewItem tvItem(item, TVIF_IMAGE);
287 DoGetItem(&tvItem);
288
289 return tvItem.iImage;
290 }
291
292 void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image)
293 {
294 wxTreeViewItem tvItem(item, TVIF_IMAGE);
295 tvItem.iImage = image;
296 DoSetItem(&tvItem);
297 }
298
299 int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const
300 {
301 wxTreeViewItem tvItem(item, TVIF_SELECTEDIMAGE);
302 DoGetItem(&tvItem);
303
304 return tvItem.iSelectedImage;
305 }
306
307 void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image)
308 {
309 wxTreeViewItem tvItem(item, TVIF_SELECTEDIMAGE);
310 tvItem.iSelectedImage = image;
311 DoSetItem(&tvItem);
312 }
313
314 wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const
315 {
316 wxTreeViewItem tvItem(item, TVIF_PARAM);
317 if ( !DoGetItem(&tvItem) )
318 {
319 return NULL;
320 }
321
322 return (wxTreeItemData *)tvItem.lParam;
323 }
324
325 void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data)
326 {
327 wxTreeViewItem tvItem(item, TVIF_PARAM);
328 tvItem.lParam = (LPARAM)data;
329 DoSetItem(&tvItem);
330 }
331
332 void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
333 {
334 wxTreeViewItem tvItem(item, TVIF_CHILDREN);
335 tvItem.cChildren = (int)has;
336 DoSetItem(&tvItem);
337 }
338
339 // ----------------------------------------------------------------------------
340 // Item status
341 // ----------------------------------------------------------------------------
342
343 bool wxTreeCtrl::IsVisible(const wxTreeItemId& item) const
344 {
345 RECT rect;
346 // return (TreeView_GetItemRect(wxhWnd, (HTREEITEM) (WXHTREEITEM)item, &rect, FALSE) != 0);
347 // Bug in Gnu-Win32 headers, so don't use the macro.
348 return (SendMessage((wxhWnd), TVM_GETITEMRECT, (WPARAM) FALSE, (LPARAM) & rect) != 0);
349
350 }
351
352 bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const
353 {
354 wxTreeViewItem tvItem(item, TVIF_CHILDREN);
355 DoGetItem(&tvItem);
356
357 return tvItem.cChildren != 0;
358 }
359
360 bool wxTreeCtrl::IsExpanded(const wxTreeItemId& item) const
361 {
362 // probably not a good idea to put it here
363 //wxASSERT( ItemHasChildren(item) );
364
365 wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_EXPANDED);
366 DoGetItem(&tvItem);
367
368 return (tvItem.state & TVIS_EXPANDED) != 0;
369 }
370
371 bool wxTreeCtrl::IsSelected(const wxTreeItemId& item) const
372 {
373 wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_SELECTED);
374 DoGetItem(&tvItem);
375
376 return (tvItem.state & TVIS_SELECTED) != 0;
377 }
378
379 // ----------------------------------------------------------------------------
380 // navigation
381 // ----------------------------------------------------------------------------
382
383 wxTreeItemId wxTreeCtrl::GetRootItem() const
384 {
385 return wxTreeItemId((WXHTREEITEM) TreeView_GetRoot(wxhWnd));
386 }
387
388 wxTreeItemId wxTreeCtrl::GetSelection() const
389 {
390 return wxTreeItemId((WXHTREEITEM) TreeView_GetSelection(wxhWnd));
391 }
392
393 wxTreeItemId wxTreeCtrl::GetParent(const wxTreeItemId& item) const
394 {
395 return wxTreeItemId((WXHTREEITEM) TreeView_GetParent(wxhWnd, (HTREEITEM) (WXHTREEITEM) item));
396 }
397
398 wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item,
399 long& _cookie) const
400 {
401 // remember the last child returned in 'cookie'
402 _cookie = (long)TreeView_GetChild(wxhWnd, (HTREEITEM) (WXHTREEITEM)item);
403
404 return wxTreeItemId((WXHTREEITEM)_cookie);
405 }
406
407 wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& WXUNUSED(item),
408 long& _cookie) const
409 {
410 wxTreeItemId l=wxTreeItemId((WXHTREEITEM) TreeView_GetNextSibling(wxhWnd,
411 (HTREEITEM) (WXHTREEITEM)_cookie));
412 _cookie=(long)l;
413 return l;
414 }
415
416 wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const
417 {
418 return wxTreeItemId((WXHTREEITEM) TreeView_GetNextSibling(wxhWnd, (HTREEITEM) (WXHTREEITEM) item));
419 }
420
421 wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const
422 {
423 return wxTreeItemId((WXHTREEITEM) TreeView_GetPrevSibling(wxhWnd, (HTREEITEM) (WXHTREEITEM) item));
424 }
425
426 wxTreeItemId wxTreeCtrl::GetFirstVisibleItem() const
427 {
428 return wxTreeItemId((WXHTREEITEM) TreeView_GetFirstVisible(wxhWnd));
429 }
430
431 wxTreeItemId wxTreeCtrl::GetNextVisible(const wxTreeItemId& item) const
432 {
433 wxASSERT_MSG( IsVisible(item), "The item you call GetNextVisible() "
434 "for must be visible itself!");
435
436 return wxTreeItemId((WXHTREEITEM) TreeView_GetNextVisible(wxhWnd, (HTREEITEM) (WXHTREEITEM) item));
437 }
438
439 wxTreeItemId wxTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const
440 {
441 wxASSERT_MSG( IsVisible(item), "The item you call GetPrevVisible() "
442 "for must be visible itself!");
443
444 return wxTreeItemId((WXHTREEITEM) TreeView_GetPrevVisible(wxhWnd, (HTREEITEM) (WXHTREEITEM) item));
445 }
446
447 // ----------------------------------------------------------------------------
448 // Usual operations
449 // ----------------------------------------------------------------------------
450
451 wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parent,
452 wxTreeItemId hInsertAfter,
453 const wxString& text,
454 int image, int selectedImage,
455 wxTreeItemData *data)
456 {
457 TV_INSERTSTRUCT tvIns;
458 tvIns.hParent = (HTREEITEM) (WXHTREEITEM)parent;
459 tvIns.hInsertAfter = (HTREEITEM) (WXHTREEITEM) hInsertAfter;
460 UINT mask = 0;
461 if ( !text.IsEmpty() )
462 {
463 mask |= TVIF_TEXT;
464 tvIns.item.pszText = (char *)text.c_str(); // cast is ok
465 }
466
467 if ( image != -1 )
468 {
469 mask |= TVIF_IMAGE;
470 tvIns.item.iImage = image;
471
472 if ( selectedImage == -1 )
473 {
474 // take the same image for selected icon if not specified
475 selectedImage = image;
476 }
477 }
478
479 if ( selectedImage != -1 )
480 {
481 mask |= TVIF_SELECTEDIMAGE;
482 tvIns.item.iSelectedImage = selectedImage;
483 }
484
485 if ( data != NULL )
486 {
487 mask |= TVIF_PARAM;
488 tvIns.item.lParam = (LPARAM)data;
489 }
490
491 tvIns.item.mask = mask;
492
493 HTREEITEM id = (HTREEITEM) TreeView_InsertItem(wxhWnd, &tvIns);
494 if ( id == 0 )
495 {
496 wxLogLastError("TreeView_InsertItem");
497 }
498
499 return wxTreeItemId((WXHTREEITEM)id);
500 }
501
502 // for compatibility only
503 wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent,
504 const wxString& text,
505 int image, int selImage,
506 long insertAfter)
507 {
508 return DoInsertItem(parent, (WXHTREEITEM)insertAfter, text,
509 image, selImage, NULL);
510 }
511
512 wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text,
513 int image, int selectedImage,
514 wxTreeItemData *data)
515 {
516 return DoInsertItem(wxTreeItemId((WXHTREEITEM) 0), (WXHTREEITEM) 0,
517 text, image, selectedImage, data);
518 }
519
520 wxTreeItemId wxTreeCtrl::PrependItem(const wxTreeItemId& parent,
521 const wxString& text,
522 int image, int selectedImage,
523 wxTreeItemData *data)
524 {
525 return DoInsertItem(parent, (WXHTREEITEM) TVI_FIRST,
526 text, image, selectedImage, data);
527 }
528
529 wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent,
530 const wxTreeItemId& idPrevious,
531 const wxString& text,
532 int image, int selectedImage,
533 wxTreeItemData *data)
534 {
535 return DoInsertItem(parent, idPrevious, text, image, selectedImage, data);
536 }
537
538 wxTreeItemId wxTreeCtrl::AppendItem(const wxTreeItemId& parent,
539 const wxString& text,
540 int image, int selectedImage,
541 wxTreeItemData *data)
542 {
543 return DoInsertItem(parent, (WXHTREEITEM) TVI_LAST,
544 text, image, selectedImage, data);
545 }
546
547 void wxTreeCtrl::Delete(const wxTreeItemId& item)
548 {
549 wxTreeItemData *data = GetItemData(item);
550 if(data!=NULL)
551 delete data; // may be NULL, ok
552
553 if ( !TreeView_DeleteItem(wxhWnd, (HTREEITEM)(WXHTREEITEM)item) )
554 {
555 wxLogLastError("TreeView_DeleteItem");
556 }
557 }
558
559 void wxTreeCtrl::DeleteAllItems()
560 {
561 if ( !TreeView_DeleteAllItems(wxhWnd) )
562 {
563 wxLogLastError("TreeView_DeleteAllItems");
564 }
565 }
566
567 void wxTreeCtrl::DoExpand(const wxTreeItemId& item, int flag)
568 {
569 wxASSERT_MSG( flag == TVE_COLLAPSE || flag == TVE_COLLAPSERESET ||
570 flag == TVE_EXPAND || flag == TVE_TOGGLE,
571 "Unknown flag in wxTreeCtrl::DoExpand" );
572
573 // TreeView_Expand doesn't send TVN_ITEMEXPAND(ING) messages, so we must
574 // emulate them
575 if ( TreeView_Expand(wxhWnd, (HTREEITEM) (WXHTREEITEM) item, flag) != 0 )
576 {
577 wxTreeEvent event(wxEVT_NULL, m_windowId);
578 event.m_item = item;
579
580 bool isExpanded = IsExpanded(item);
581
582 event.SetEventObject(this);
583
584 // @@@ return values of {EXPAND|COLLAPS}ING event handler is discarded
585 event.SetEventType(g_events[isExpanded][TRUE]);
586 GetEventHandler()->ProcessEvent(event);
587
588 event.SetEventType(g_events[isExpanded][FALSE]);
589 GetEventHandler()->ProcessEvent(event);
590 }
591 else
592 {
593 // I wonder if it really ever happens...
594 wxLogDebug("TreeView_Expand: change didn't took place.");
595 }
596 }
597
598 void wxTreeCtrl::Expand(const wxTreeItemId& item)
599 {
600 DoExpand(item, TVE_EXPAND);
601 }
602
603 void wxTreeCtrl::Collapse(const wxTreeItemId& item)
604 {
605 DoExpand(item, TVE_COLLAPSE);
606 }
607
608 void wxTreeCtrl::CollapseAndReset(const wxTreeItemId& item)
609 {
610 DoExpand(item, TVE_COLLAPSERESET);
611 }
612
613 void wxTreeCtrl::Toggle(const wxTreeItemId& item)
614 {
615 DoExpand(item, TVE_TOGGLE);
616 }
617
618 void wxTreeCtrl::ExpandItem(const wxTreeItemId& item, int action)
619 {
620 DoExpand(item, action);
621 }
622
623 void wxTreeCtrl::Unselect()
624 {
625 SelectItem(wxTreeItemId((WXHTREEITEM) 0));
626 }
627
628 void wxTreeCtrl::SelectItem(const wxTreeItemId& item)
629 {
630 if ( !TreeView_SelectItem(wxhWnd, (HTREEITEM) (WXHTREEITEM) item) )
631 {
632 wxLogLastError("TreeView_SelectItem");
633 }
634 }
635
636 void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)
637 {
638 // no error return
639 TreeView_EnsureVisible(wxhWnd, (HTREEITEM) (WXHTREEITEM) item);
640 }
641
642 void wxTreeCtrl::ScrollTo(const wxTreeItemId& item)
643 {
644 if ( !TreeView_SelectSetFirstVisible(wxhWnd, (HTREEITEM) (WXHTREEITEM) item) )
645 {
646 wxLogLastError("TreeView_SelectSetFirstVisible");
647 }
648 }
649
650 wxTextCtrl* wxTreeCtrl::GetEditControl() const
651 {
652 return m_textCtrl;
653 }
654
655 void wxTreeCtrl::DeleteTextCtrl()
656 {
657 if ( m_textCtrl )
658 {
659 m_textCtrl->UnsubclassWin();
660 m_textCtrl->SetHWND(0);
661 delete m_textCtrl;
662 m_textCtrl = NULL;
663 }
664 }
665
666 wxTextCtrl* wxTreeCtrl::EditLabel(const wxTreeItemId& item,
667 wxClassInfo* textControlClass)
668 {
669 wxASSERT( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)) );
670
671 HWND hWnd = (HWND) TreeView_EditLabel(wxhWnd, (HTREEITEM) (WXHTREEITEM) item);
672
673 wxCHECK_MSG( hWnd, NULL, "Can't edit tree ctrl label" );
674
675 DeleteTextCtrl();
676
677 m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject();
678 m_textCtrl->SetHWND((WXHWND)hWnd);
679 m_textCtrl->SubclassWin((WXHWND)hWnd);
680
681 return m_textCtrl;
682 }
683
684 // End label editing, optionally cancelling the edit
685 void wxTreeCtrl::EndEditLabel(const wxTreeItemId& item, bool discardChanges)
686 {
687 TreeView_EndEditLabelNow(wxhWnd, discardChanges);
688
689 DeleteTextCtrl();
690 }
691
692 wxTreeItemId wxTreeCtrl::HitTest(const wxPoint& point, int& flags)
693 {
694 TV_HITTESTINFO hitTestInfo;
695 hitTestInfo.pt.x = (int)point.x;
696 hitTestInfo.pt.y = (int)point.y;
697
698 TreeView_HitTest(wxhWnd, &hitTestInfo);
699
700 flags = 0;
701
702 // avoid repetition
703 #define TRANSLATE_FLAG(flag) if ( hitTestInfo.flags & TVHT_##flag ) \
704 flags |= wxTREE_HITTEST_##flag
705
706 TRANSLATE_FLAG(ABOVE);
707 TRANSLATE_FLAG(BELOW);
708 TRANSLATE_FLAG(NOWHERE);
709 TRANSLATE_FLAG(ONITEMBUTTON);
710 TRANSLATE_FLAG(ONITEMICON);
711 TRANSLATE_FLAG(ONITEMINDENT);
712 TRANSLATE_FLAG(ONITEMLABEL);
713 TRANSLATE_FLAG(ONITEMRIGHT);
714 TRANSLATE_FLAG(ONITEMSTATEICON);
715 TRANSLATE_FLAG(TOLEFT);
716 TRANSLATE_FLAG(TORIGHT);
717
718 #undef TRANSLATE_FLAG
719
720 return wxTreeItemId((WXHTREEITEM) hitTestInfo.hItem);
721 }
722
723 void wxTreeCtrl::SortChildren(const wxTreeItemId& item,
724 wxTreeItemCmpFunc *cmpFunction)
725 {
726 if ( cmpFunction == NULL )
727 {
728 TreeView_SortChildren(wxhWnd, (HTREEITEM) (WXHTREEITEM) item, 0);
729 }
730 else
731 {
732 // TODO: use TreeView_SortChildrenCB
733 wxFAIL_MSG("wxTreeCtrl::SortChildren not implemented");
734 }
735 }
736
737 // ----------------------------------------------------------------------------
738 // implementation
739 // ----------------------------------------------------------------------------
740
741 bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id)
742 {
743 if ( cmd == EN_UPDATE )
744 {
745 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id);
746 event.SetEventObject( this );
747 ProcessCommand(event);
748 }
749 else if ( cmd == EN_KILLFOCUS )
750 {
751 wxCommandEvent event(wxEVT_KILL_FOCUS, id);
752 event.SetEventObject( this );
753 ProcessCommand(event);
754 }
755 else
756 {
757 // nothing done
758 return FALSE;
759 }
760
761 // command processed
762 return TRUE;
763 }
764
765 // process WM_NOTIFY Windows message
766 bool wxTreeCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam)
767 {
768 wxTreeEvent event(wxEVT_NULL, m_windowId);
769 wxEventType eventType = wxEVT_NULL;
770 NMHDR *hdr = (NMHDR *)lParam;
771
772 switch ( hdr->code )
773 {
774 case TVN_BEGINDRAG:
775 eventType = wxEVT_COMMAND_TREE_BEGIN_DRAG;
776 // fall through
777
778 case TVN_BEGINRDRAG:
779 {
780 if ( eventType == wxEVT_NULL )
781 eventType = wxEVT_COMMAND_TREE_BEGIN_RDRAG;
782 //else: left drag, already set above
783
784 NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam;
785
786 event.m_item = (WXHTREEITEM) tv->itemNew.hItem;
787 event.m_pointDrag = wxPoint(tv->ptDrag.x, tv->ptDrag.y);
788 break;
789 }
790
791 case TVN_BEGINLABELEDIT:
792 {
793 eventType = wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT;
794 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
795
796 event.m_item = (WXHTREEITEM) info->item.hItem;
797 break;
798 }
799
800 case TVN_DELETEITEM:
801 {
802 eventType = wxEVT_COMMAND_TREE_DELETE_ITEM;
803 NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam;
804
805 event.m_item = (WXHTREEITEM) tv->itemOld.hItem;
806 break;
807 }
808
809 case TVN_ENDLABELEDIT:
810 {
811 eventType = wxEVT_COMMAND_TREE_END_LABEL_EDIT;
812 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
813
814 event.m_item = (WXHTREEITEM) info->item.hItem;
815 break;
816 }
817
818 case TVN_GETDISPINFO:
819 eventType = wxEVT_COMMAND_TREE_GET_INFO;
820 // fall through
821
822 case TVN_SETDISPINFO:
823 {
824 if ( eventType == wxEVT_NULL )
825 eventType = wxEVT_COMMAND_TREE_SET_INFO;
826 //else: get, already set above
827
828 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
829
830 event.m_item = (WXHTREEITEM) info->item.hItem;
831 break;
832 }
833
834 case TVN_ITEMEXPANDING:
835 event.m_code = FALSE;
836 // fall through
837
838 case TVN_ITEMEXPANDED:
839 {
840 NM_TREEVIEW* tv = (NM_TREEVIEW*)lParam;
841
842 bool expand = FALSE;
843 switch ( tv->action )
844 {
845 case TVE_EXPAND:
846 expand = TRUE;
847 break;
848
849 case TVE_COLLAPSE:
850 expand = FALSE;
851 break;
852
853 default:
854 wxLogDebug("unexpected code %d in TVN_ITEMEXPAND "
855 "message", tv->action);
856 }
857
858 bool ing = (hdr->code == TVN_ITEMEXPANDING);
859 eventType = g_events[expand][ing];
860
861 event.m_item = (WXHTREEITEM) tv->itemNew.hItem;
862 break;
863 }
864
865 case TVN_KEYDOWN:
866 {
867 eventType = wxEVT_COMMAND_TREE_KEY_DOWN;
868 TV_KEYDOWN *info = (TV_KEYDOWN *)lParam;
869
870 event.m_code = wxCharCodeMSWToWX(info->wVKey);
871 break;
872 }
873
874 case TVN_SELCHANGED:
875 eventType = wxEVT_COMMAND_TREE_SEL_CHANGED;
876 // fall through
877
878 case TVN_SELCHANGING:
879 {
880 if ( eventType == wxEVT_NULL )
881 eventType = wxEVT_COMMAND_TREE_SEL_CHANGING;
882 //else: already set above
883
884 NM_TREEVIEW* tv = (NM_TREEVIEW *)lParam;
885
886 event.m_item = (WXHTREEITEM) tv->itemNew.hItem;
887 event.m_itemOld = (WXHTREEITEM) tv->itemOld.hItem;
888 break;
889 }
890
891 default:
892 return wxControl::MSWNotify(wParam, lParam);
893 }
894
895 event.SetEventObject(this);
896 event.SetEventType(eventType);
897
898 bool rc = GetEventHandler()->ProcessEvent(event);
899
900 // post processing
901 switch ( hdr->code )
902 {
903 // NB: we might process this message using wxWindows event tables, but
904 // due to overhead of wxWin event system we prefer to do it here
905 // (otherwise deleting a tree with many items is just too slow)
906 case TVN_DELETEITEM:
907 {
908 NM_TREEVIEW* tv = (NM_TREEVIEW *)lParam;
909 wxTreeItemData *data = (wxTreeItemData *)tv->itemOld.lParam;
910 delete data; // may be NULL, ok
911 }
912 break;
913
914 case TVN_ITEMEXPANDING:
915 // if user called Veto(), don't allow expansion/collapse by
916 // returning TRUE from here
917 rc = event.m_code != 0;
918 break;
919 }
920
921 return rc;
922 }
923
924 // ----------------------------------------------------------------------------
925 // Tree event
926 // ----------------------------------------------------------------------------
927
928 IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxCommandEvent)
929
930 wxTreeEvent::wxTreeEvent(wxEventType commandType, int id)
931 : wxCommandEvent(commandType, id)
932 {
933 m_code = 0;
934 m_itemOld = 0;
935 }
936
937 #endif // __WIN95__
938