]> git.saurik.com Git - wxWidgets.git/blob - src/msw/treectrl.cpp
code using ms_PaintDC changed a little (a couple of asserts added, the behaviour
[wxWidgets.git] / src / msw / treectrl.cpp
1 /*
2 * File: TreeCtrl.cpp
3 * Purpose: Tree control
4 * Author: Julian Smart
5 * Created: 1997
6 * Updated:
7 * Copyright:
8 */
9
10 /* static const char sccsid[] = "%W% %G%"; */
11
12 #ifdef __GNUG__
13 #pragma implementation "treectrl.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx.h"
25 #endif
26
27 #include "wx/log.h"
28
29 #if defined(__WIN95__)
30
31 #include "wx/treectrl.h"
32 #include "wx/msw/private.h"
33
34 #ifndef __GNUWIN32__
35 #include <commctrl.h>
36 #endif
37
38 // Bug in headers, sometimes
39 #ifndef TVIS_FOCUSED
40 #define TVIS_FOCUSED 0x0001
41 #endif
42
43 static void wxConvertToMSWTreeItem(wxTreeItem& info, TV_ITEM& tvItem);
44 static void wxConvertFromMSWTreeItem(wxTreeItem& info, TV_ITEM& tvItem, HWND getFullInfo = 0);
45
46 #if !USE_SHARED_LIBRARY
47 IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl)
48 IMPLEMENT_DYNAMIC_CLASS(wxTreeItem, wxObject)
49
50 #endif
51
52 wxTreeCtrl::wxTreeCtrl(void)
53 {
54 m_imageListNormal = NULL;
55 m_imageListState = NULL;
56 }
57
58 bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
59 long style, const wxValidator& validator, const wxString& name)
60 {
61 wxSystemSettings settings;
62 SetBackgroundColour(settings.GetSystemColour(wxSYS_COLOUR_WINDOW));
63 SetForegroundColour(parent->GetDefaultForegroundColour());
64
65 SetName(name);
66 SetValidator(validator);
67
68 m_imageListNormal = NULL;
69 m_imageListState = NULL;
70
71 int x = pos.x;
72 int y = pos.y;
73 int width = size.x;
74 int height = size.y;
75
76 m_windowStyle = style;
77
78 // SetFont(wxTheFontList->FindOrCreateFont(11, wxSWISS, wxNORMAL, wxNORMAL));
79
80 SetParent(parent);
81
82 if (width <= 0)
83 width = 100;
84 if (height <= 0)
85 height = 30;
86 if (x < 0)
87 x = 0;
88 if (y < 0)
89 y = 0;
90
91 m_windowId = (id == -1) ? NewControlId() : id;
92
93 DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | TVS_HASLINES;
94
95 bool want3D;
96 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
97
98 // Even with extended styles, need to combine with WS_BORDER
99 // for them to look right.
100 if (want3D || (m_windowStyle & wxSIMPLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) ||
101 (m_windowStyle & wxSUNKEN_BORDER) || (m_windowStyle & wxDOUBLE_BORDER))
102 wstyle |= WS_BORDER;
103
104 if ( m_windowStyle & wxTR_HAS_BUTTONS )
105 wstyle |= TVS_HASBUTTONS;
106
107 if ( m_windowStyle & wxTR_EDIT_LABELS )
108 wstyle |= TVS_EDITLABELS;
109
110 if ( m_windowStyle & wxTR_LINES_AT_ROOT )
111 wstyle |= TVS_LINESATROOT;
112
113 // Create the toolbar control.
114 HWND hWndTreeControl = CreateWindowEx(exStyle,
115 WC_TREEVIEW,
116 "",
117 wstyle,
118 x, y, width, height,
119 (HWND) parent->GetHWND(),
120 (HMENU)m_windowId,
121 wxGetInstance(),
122 NULL );
123
124 m_hWnd = (WXHWND) hWndTreeControl;
125 if (parent) parent->AddChild(this);
126
127 SubclassWin((WXHWND) m_hWnd);
128
129 return TRUE;
130 }
131
132 wxTreeCtrl::~wxTreeCtrl(void)
133 {
134 m_textCtrl.SetHWND((WXHWND) NULL);
135 }
136
137 // Attributes
138 int wxTreeCtrl::GetCount(void) const
139 {
140 return (int) TreeView_GetCount((HWND) GetHWND());
141 }
142
143 int wxTreeCtrl::GetIndent(void) const
144 {
145 return (int) TreeView_GetIndent((HWND) GetHWND());
146 }
147
148 void wxTreeCtrl::SetIndent(int indent)
149 {
150 TreeView_SetIndent((HWND) GetHWND(), indent);
151 }
152
153 wxImageList *wxTreeCtrl::GetImageList(int which) const
154 {
155 if ( which == wxIMAGE_LIST_NORMAL )
156 {
157 return m_imageListNormal;
158 }
159 else if ( which == wxIMAGE_LIST_STATE )
160 {
161 return m_imageListState;
162 }
163 return NULL;
164 }
165
166 void wxTreeCtrl::SetImageList(wxImageList *imageList, int which)
167 {
168 int flags = 0;
169 if ( which == wxIMAGE_LIST_NORMAL )
170 {
171 flags = TVSIL_NORMAL;
172 m_imageListNormal = imageList;
173 }
174 else if ( which == wxIMAGE_LIST_STATE )
175 {
176 flags = TVSIL_STATE;
177 m_imageListState = imageList;
178 }
179 TreeView_SetImageList((HWND) GetHWND(), (HIMAGELIST) imageList ? imageList->GetHIMAGELIST() : 0, flags);
180 }
181
182 long wxTreeCtrl::GetNextItem(long item, int code) const
183 {
184 UINT flag = 0;
185 switch ( code )
186 {
187 case wxTREE_NEXT_CARET:
188 flag = TVGN_CARET;
189 break;
190 case wxTREE_NEXT_CHILD:
191 flag = TVGN_CHILD;
192 break;
193 case wxTREE_NEXT_DROPHILITE:
194 flag = TVGN_DROPHILITE;
195 break;
196 case wxTREE_NEXT_FIRSTVISIBLE:
197 flag = TVGN_FIRSTVISIBLE;
198 break;
199 case wxTREE_NEXT_NEXT:
200 flag = TVGN_NEXT;
201 break;
202 case wxTREE_NEXT_NEXTVISIBLE:
203 flag = TVGN_NEXTVISIBLE;
204 break;
205 case wxTREE_NEXT_PARENT:
206 flag = TVGN_PARENT;
207 break;
208 case wxTREE_NEXT_PREVIOUS:
209 flag = TVGN_PREVIOUS;
210 break;
211 case wxTREE_NEXT_PREVIOUSVISIBLE:
212 flag = TVGN_PREVIOUSVISIBLE;
213 break;
214 case wxTREE_NEXT_ROOT:
215 flag = TVGN_ROOT;
216 break;
217
218 default :
219 break;
220 }
221 return (long) TreeView_GetNextItem( (HWND) GetHWND(), (HTREEITEM) item, flag);
222 }
223
224 bool wxTreeCtrl::ItemHasChildren(long item) const
225 {
226 TV_ITEM item2;
227 item2.hItem = (HTREEITEM) item;
228 item2.mask = TVIF_CHILDREN;
229 TreeView_GetItem((HWND) GetHWND(), &item2);
230 return (item2.cChildren != 0);
231 }
232
233 long wxTreeCtrl::GetChild(long item) const
234 {
235 return (long) ::SendMessage((HWND) GetHWND(), TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)item);
236 }
237
238 long wxTreeCtrl::GetParent(long item) const
239 {
240 return (long) ::SendMessage((HWND) GetHWND(), TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)item);
241 }
242
243 long wxTreeCtrl::GetFirstVisibleItem(void) const
244 {
245 return (long) ::SendMessage((HWND) GetHWND(), TVM_GETNEXTITEM, TVGN_FIRSTVISIBLE, 0);
246 }
247
248 long wxTreeCtrl::GetNextVisibleItem(long item) const
249 {
250 return (long) ::SendMessage((HWND) GetHWND(), TVM_GETNEXTITEM, TVGN_NEXTVISIBLE, (LPARAM)item);
251 }
252
253 long wxTreeCtrl::GetSelection(void) const
254 {
255 return (long) ::SendMessage((HWND) GetHWND(), TVM_GETNEXTITEM, TVGN_CARET, 0);
256 }
257
258 long wxTreeCtrl::GetRootItem(void) const
259 {
260 return (long) ::SendMessage((HWND) GetHWND(), TVM_GETNEXTITEM, TVGN_ROOT, 0);
261 }
262
263 bool wxTreeCtrl::GetItem(wxTreeItem& info) const
264 {
265 TV_ITEM tvItem;
266 tvItem.hItem = (HTREEITEM)info.m_itemId;
267 tvItem.pszText = NULL;
268 tvItem.mask =
269 tvItem.stateMask = 0;
270
271 // TODO: convert other bits in the mask
272 if ( info.m_mask & wxTREE_MASK_TEXT )
273 {
274 tvItem.mask |= TVIF_TEXT;
275 tvItem.pszText = new char[513];
276 tvItem.cchTextMax = 512;
277 }
278 if ( info.m_mask & wxTREE_MASK_DATA )
279 tvItem.mask |= TVIF_PARAM;
280 if ( info.m_stateMask & wxTREE_STATE_EXPANDED ) {
281 tvItem.mask |= TVIF_STATE;
282 tvItem.stateMask |= TVIS_EXPANDED;
283 }
284
285 bool success = TreeView_GetItem((HWND)GetHWND(), &tvItem) != 0;
286
287 if ( !success )
288 {
289 wxLogSysError("TreeView_GetItem failed");
290
291 if (tvItem.pszText)
292 delete[] tvItem.pszText;
293
294 return FALSE;
295 }
296
297 wxConvertFromMSWTreeItem(info, tvItem);
298
299 if (tvItem.pszText)
300 delete[] tvItem.pszText;
301
302 return success;
303 }
304
305 bool wxTreeCtrl::SetItem(wxTreeItem& info)
306 {
307 TV_ITEM item;
308 wxConvertToMSWTreeItem(info, item);
309 return (::SendMessage((HWND) GetHWND(), TVM_SETITEM, 0, (LPARAM)&item) != 0);
310 }
311
312 int wxTreeCtrl::GetItemState(long item, long stateMask) const
313 {
314 wxTreeItem info;
315
316 info.m_mask = wxTREE_MASK_STATE ;
317 info.m_stateMask = stateMask;
318 info.m_itemId = item;
319
320 if (!GetItem(info))
321 return 0;
322
323 return info.m_state;
324 }
325
326 bool wxTreeCtrl::SetItemState(long item, long state, long stateMask)
327 {
328 wxTreeItem info;
329
330 info.m_mask = wxTREE_MASK_STATE ;
331 info.m_state = state;
332 info.m_stateMask = stateMask;
333 info.m_itemId = item;
334
335 return SetItem(info);
336 }
337
338 bool wxTreeCtrl::SetItemImage(long item, int image, int selImage)
339 {
340 wxTreeItem info;
341
342 info.m_mask = wxTREE_MASK_IMAGE ;
343 info.m_image = image;
344 if ( selImage > -1)
345 {
346 info.m_selectedImage = selImage;
347 info.m_mask |= wxTREE_MASK_SELECTED_IMAGE;
348 }
349 info.m_itemId = item;
350
351 return SetItem(info);
352 }
353
354 wxString wxTreeCtrl::GetItemText(long item) const
355 {
356 wxTreeItem info;
357
358 info.m_mask = wxTREE_MASK_TEXT ;
359 info.m_itemId = item;
360
361 if (!GetItem(info))
362 return wxString("");
363 return info.m_text;
364 }
365
366 void wxTreeCtrl::SetItemText(long item, const wxString& str)
367 {
368 wxTreeItem info;
369
370 info.m_mask = wxTREE_MASK_TEXT ;
371 info.m_itemId = item;
372 info.m_text = str;
373
374 SetItem(info);
375 }
376
377 long wxTreeCtrl::GetItemData(long item) const
378 {
379 wxTreeItem info;
380
381 info.m_mask = wxTREE_MASK_DATA ;
382 info.m_itemId = item;
383
384 if (!GetItem(info))
385 return 0;
386 return info.m_data;
387 }
388
389 bool wxTreeCtrl::SetItemData(long item, long data)
390 {
391 wxTreeItem info;
392
393 info.m_mask = wxTREE_MASK_DATA ;
394 info.m_itemId = item;
395 info.m_data = data;
396
397 return SetItem(info);
398 }
399
400 bool wxTreeCtrl::GetItemRect(long item, wxRectangle& rect, bool textOnly) const
401 {
402 RECT rect2;
403
404 *(HTREEITEM*)& rect2 = (HTREEITEM) item;
405 bool success = (::SendMessage((HWND) GetHWND(), TVM_GETITEMRECT, (WPARAM)textOnly,
406 (LPARAM)&rect2) != 0);
407
408 rect.x = rect2.left;
409 rect.y = rect2.top;
410 rect.width = rect2.right - rect2.left;
411 rect.height = rect2.bottom - rect2.left;
412 return success;
413 }
414
415 wxTextCtrl& wxTreeCtrl::GetEditControl(void) const
416 {
417 HWND hWnd = (HWND) TreeView_GetEditControl((HWND) GetHWND());
418 ((wxTreeCtrl *)this)->m_textCtrl.SetHWND((WXHWND) hWnd);
419 return (wxTextCtrl&) m_textCtrl;
420 }
421
422 // Operations
423 bool wxTreeCtrl::DeleteItem(long item)
424 {
425 return (TreeView_DeleteItem((HWND) GetHWND(), (HTREEITEM) item) != 0);
426 }
427
428 bool wxTreeCtrl::ExpandItem(long item, int action)
429 {
430 UINT mswAction = TVE_EXPAND;
431 switch ( action )
432 {
433 case wxTREE_EXPAND_EXPAND:
434 mswAction = TVE_EXPAND;
435 break;
436
437 case wxTREE_EXPAND_COLLAPSE:
438 mswAction = TVE_COLLAPSE;
439 break;
440
441 case wxTREE_EXPAND_COLLAPSE_RESET:
442 // @@@ it should also delete all the items! currently, if you do use this
443 // code your program will probaly crash. Feel free to remove this if
444 // it does work
445 wxFAIL_MSG("wxTREE_EXPAND_COLLAPSE_RESET probably doesn't work.");
446 mswAction = TVE_COLLAPSERESET;
447 break;
448
449 case wxTREE_EXPAND_TOGGLE:
450 mswAction = TVE_TOGGLE;
451 break;
452
453 default:
454 wxFAIL_MSG("unknown action in wxTreeCtrl::ExpandItem");
455 }
456
457 bool bOk = TreeView_Expand((HWND)GetHWND(), (HTREEITEM)item, mswAction) != 0;
458
459 // TreeView_Expand doesn't send TVN_EXPAND(ING) messages, so emulate them
460 if ( bOk ) {
461 wxTreeEvent event(wxEVT_NULL, m_windowId);
462 event.m_item.m_itemId = item;
463 event.m_item.m_mask =
464 event.m_item.m_stateMask = 0xffff; // get all
465 GetItem(event.m_item);
466
467 bool bIsExpanded = (event.m_item.m_state & wxTREE_STATE_EXPANDED) != 0;
468
469 event.m_code = action;
470 event.SetEventObject(this);
471
472 // @@@ return values of {EXPAND|COLLAPS}ING event handler is discarded
473 event.SetEventType(bIsExpanded ? wxEVT_COMMAND_TREE_ITEM_EXPANDING
474 : wxEVT_COMMAND_TREE_ITEM_COLLAPSING);
475 GetEventHandler()->ProcessEvent(event);
476
477 event.SetEventType(bIsExpanded ? wxEVT_COMMAND_TREE_ITEM_EXPANDED
478 : wxEVT_COMMAND_TREE_ITEM_COLLAPSED);
479 GetEventHandler()->ProcessEvent(event);
480 }
481
482 return bOk;
483 }
484
485 long wxTreeCtrl::InsertItem(long parent, wxTreeItem& info, long insertAfter)
486 {
487 TV_INSERTSTRUCT tvInsertStruct;
488 tvInsertStruct.hParent = (HTREEITEM) parent ;
489 tvInsertStruct.hInsertAfter = (HTREEITEM) insertAfter ;
490
491 wxConvertToMSWTreeItem(info, tvInsertStruct.item);
492
493 return (long) TreeView_InsertItem((HWND) GetHWND(), & tvInsertStruct);
494 }
495
496 long wxTreeCtrl::InsertItem(long parent, const wxString& label, int image, int selImage,
497 long insertAfter)
498 {
499 wxTreeItem info;
500 info.m_text = label;
501 info.m_mask = wxTREE_MASK_TEXT;
502 if ( image > -1 )
503 {
504 info.m_mask |= wxTREE_MASK_IMAGE | wxTREE_MASK_SELECTED_IMAGE;
505 info.m_image = image;
506 if ( selImage == -1 )
507 info.m_selectedImage = image;
508 else
509 info.m_selectedImage = selImage;
510 }
511
512 return InsertItem(parent, info, insertAfter);
513 }
514
515 bool wxTreeCtrl::SelectItem(long item)
516 {
517 return (TreeView_SelectItem((HWND) GetHWND(), (HTREEITEM) item) != 0);
518 }
519
520 bool wxTreeCtrl::ScrollTo(long item)
521 {
522 return (TreeView_SelectSetFirstVisible((HWND) GetHWND(), (HTREEITEM) item) != 0);
523 }
524
525 bool wxTreeCtrl::DeleteAllItems(void)
526 {
527 return (TreeView_DeleteAllItems((HWND) GetHWND()) != 0);
528 }
529
530 wxTextCtrl& wxTreeCtrl::Edit(long item)
531 {
532 HWND hWnd = (HWND) TreeView_EditLabel((HWND) GetHWND(), item);
533 m_textCtrl.SetHWND((WXHWND) hWnd);
534 return m_textCtrl;
535 }
536
537 long wxTreeCtrl::HitTest(const wxPoint& point, int& flags)
538 {
539 TV_HITTESTINFO hitTestInfo;
540 hitTestInfo.pt.x = (int) point.x;
541 hitTestInfo.pt.y = (int) point.y;
542
543 TreeView_HitTest((HWND) GetHWND(), & hitTestInfo);
544
545 flags = 0;
546 if ( hitTestInfo.flags & TVHT_ABOVE )
547 flags |= wxTREE_HITTEST_ABOVE;
548 if ( hitTestInfo.flags & TVHT_BELOW )
549 flags |= wxTREE_HITTEST_BELOW;
550 if ( hitTestInfo.flags & TVHT_NOWHERE )
551 flags |= wxTREE_HITTEST_NOWHERE;
552 if ( hitTestInfo.flags & TVHT_ONITEMBUTTON )
553 flags |= wxTREE_HITTEST_ONITEMBUTTON;
554 if ( hitTestInfo.flags & TVHT_ONITEMICON )
555 flags |= wxTREE_HITTEST_ONITEMICON;
556 if ( hitTestInfo.flags & TVHT_ONITEMINDENT )
557 flags |= wxTREE_HITTEST_ONITEMINDENT;
558 if ( hitTestInfo.flags & TVHT_ONITEMLABEL )
559 flags |= wxTREE_HITTEST_ONITEMLABEL;
560 if ( hitTestInfo.flags & TVHT_ONITEMRIGHT )
561 flags |= wxTREE_HITTEST_ONITEMRIGHT;
562 if ( hitTestInfo.flags & TVHT_ONITEMSTATEICON )
563 flags |= wxTREE_HITTEST_ONITEMSTATEICON;
564 if ( hitTestInfo.flags & TVHT_TOLEFT )
565 flags |= wxTREE_HITTEST_TOLEFT;
566 if ( hitTestInfo.flags & TVHT_TORIGHT )
567 flags |= wxTREE_HITTEST_TORIGHT;
568
569 return (long) hitTestInfo.hItem ;
570 }
571
572 /*
573 wxImageList *wxTreeCtrl::CreateDragImage(long item)
574 {
575 }
576 */
577
578 bool wxTreeCtrl::SortChildren(long item)
579 {
580 return (TreeView_SortChildren((HWND) GetHWND(), (HTREEITEM) item, 0) != 0);
581 }
582
583 bool wxTreeCtrl::EnsureVisible(long item)
584 {
585 return (TreeView_EnsureVisible((HWND) GetHWND(), (HTREEITEM) item) != 0);
586 }
587
588 bool wxTreeCtrl::MSWCommand(WXUINT cmd, WXWORD id)
589 {
590 if (cmd == EN_UPDATE)
591 {
592 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id);
593 event.SetEventObject( this );
594 ProcessCommand(event);
595 return TRUE;
596 }
597 else if (cmd == EN_KILLFOCUS)
598 {
599 wxCommandEvent event(wxEVT_KILL_FOCUS, id);
600 event.SetEventObject( this );
601 ProcessCommand(event);
602 return TRUE;
603 }
604 else return FALSE;
605 }
606
607 bool wxTreeCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam)
608 {
609 wxTreeEvent event(wxEVT_NULL, m_windowId);
610 wxEventType eventType = wxEVT_NULL;
611 NMHDR* hdr1 = (NMHDR*) lParam;
612 switch ( hdr1->code )
613 {
614 case TVN_BEGINDRAG:
615 {
616 eventType = wxEVT_COMMAND_TREE_BEGIN_DRAG;
617 NM_TREEVIEW* hdr = (NM_TREEVIEW*)lParam;
618 wxConvertFromMSWTreeItem(event.m_item, hdr->itemNew, (HWND) GetHWND());
619 event.m_pointDrag.x = hdr->ptDrag.x;
620 event.m_pointDrag.y = hdr->ptDrag.y;
621 break;
622 }
623 case TVN_BEGINLABELEDIT:
624 {
625 eventType = wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT;
626 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
627 wxConvertFromMSWTreeItem(event.m_item, info->item, (HWND) GetHWND());
628 break;
629 }
630 case TVN_BEGINRDRAG:
631 {
632 eventType = wxEVT_COMMAND_TREE_BEGIN_RDRAG;
633 NM_TREEVIEW* hdr = (NM_TREEVIEW*)lParam;
634 wxConvertFromMSWTreeItem(event.m_item, hdr->itemNew, (HWND) GetHWND());
635 event.m_pointDrag.x = hdr->ptDrag.x;
636 event.m_pointDrag.y = hdr->ptDrag.y;
637 break;
638 }
639 case TVN_DELETEITEM:
640 {
641 eventType = wxEVT_COMMAND_TREE_DELETE_ITEM;
642 NM_TREEVIEW* hdr = (NM_TREEVIEW*)lParam;
643 wxConvertFromMSWTreeItem(event.m_item, hdr->itemOld, (HWND) GetHWND());
644 event.m_pointDrag.x = hdr->ptDrag.x;
645 event.m_pointDrag.y = hdr->ptDrag.y;
646 break;
647 }
648 case TVN_ENDLABELEDIT:
649 {
650 eventType = wxEVT_COMMAND_TREE_END_LABEL_EDIT;
651 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
652 wxConvertFromMSWTreeItem(event.m_item, info->item, (HWND) GetHWND());
653 break;
654 }
655 case TVN_GETDISPINFO:
656 {
657 eventType = wxEVT_COMMAND_TREE_GET_INFO;
658 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
659 wxConvertFromMSWTreeItem(event.m_item, info->item, (HWND) GetHWND());
660 break;
661 }
662 case TVN_ITEMEXPANDING:
663 {
664 NM_TREEVIEW* hdr = (NM_TREEVIEW*)lParam;
665 wxConvertFromMSWTreeItem(event.m_item, hdr->itemNew, (HWND) GetHWND());
666
667 switch ( hdr->action )
668 {
669 case TVE_EXPAND:
670 eventType = wxEVT_COMMAND_TREE_ITEM_EXPANDING;
671 break;
672
673 case TVE_COLLAPSE:
674 eventType = wxEVT_COMMAND_TREE_ITEM_COLLAPSING;
675 break;
676
677 case TVE_COLLAPSERESET:
678 case TVE_TOGGLE:
679 wxLogDebug("unexpected code in TVN_ITEMEXPANDING message");
680 break;
681 }
682 break;
683 }
684
685 case TVN_ITEMEXPANDED:
686 {
687 NM_TREEVIEW* hdr = (NM_TREEVIEW*)lParam;
688 wxConvertFromMSWTreeItem(event.m_item, hdr->itemNew, (HWND) GetHWND());
689 switch ( hdr->action )
690 {
691 case TVE_EXPAND:
692 eventType = wxEVT_COMMAND_TREE_ITEM_EXPANDED;
693 break;
694
695 case TVE_COLLAPSE:
696 eventType = wxEVT_COMMAND_TREE_ITEM_COLLAPSED;
697 break;
698
699 case TVE_COLLAPSERESET:
700 case TVE_TOGGLE:
701 wxLogDebug("unexpected code in TVN_ITEMEXPANDED message");
702 break;
703 }
704 break;
705 }
706 case TVN_KEYDOWN:
707 {
708 eventType = wxEVT_COMMAND_TREE_KEY_DOWN;
709 TV_KEYDOWN *info = (TV_KEYDOWN *)lParam;
710 event.m_code = wxCharCodeMSWToWX(info->wVKey);
711 break;
712 }
713 case TVN_SELCHANGED:
714 {
715 eventType = wxEVT_COMMAND_TREE_SEL_CHANGED;
716 NM_TREEVIEW* hdr = (NM_TREEVIEW*)lParam;
717 wxConvertFromMSWTreeItem(event.m_item, hdr->itemNew, (HWND) GetHWND());
718 event.m_oldItem = (long) hdr->itemNew.hItem;
719
720 break;
721 }
722 case TVN_SELCHANGING:
723 {
724 eventType = wxEVT_COMMAND_TREE_SEL_CHANGING;
725 NM_TREEVIEW* hdr = (NM_TREEVIEW*)lParam;
726 wxConvertFromMSWTreeItem(event.m_item, hdr->itemNew, (HWND) GetHWND());
727 event.m_oldItem = (long) hdr->itemNew.hItem;
728 break;
729 }
730 case TVN_SETDISPINFO:
731 {
732 eventType = wxEVT_COMMAND_TREE_SET_INFO;
733 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
734 wxConvertFromMSWTreeItem(event.m_item, info->item, (HWND) GetHWND());
735 break;
736 }
737
738 default :
739 return wxControl::MSWNotify(wParam, lParam);
740 break;
741 }
742
743 event.SetEventObject(this);
744 event.SetEventType(eventType);
745
746 if ( !GetEventHandler()->ProcessEvent(event) )
747 return FALSE;
748
749 if (hdr1->code == TVN_GETDISPINFO)
750 {
751 TV_DISPINFO *info = (TV_DISPINFO *)lParam;
752 wxConvertToMSWTreeItem(event.m_item, info->item);
753 }
754
755 return TRUE;
756 }
757
758 // Tree item structure
759 wxTreeItem::wxTreeItem(void)
760 {
761 m_mask = 0;
762 m_itemId = 0;
763 m_state = 0;
764 m_stateMask = 0;
765 m_image = -1;
766 m_selectedImage = -1;
767 m_children = 0;
768 m_data = 0;
769 }
770
771 // If getFullInfo is TRUE, we explicitly query for more info if we haven't got it all.
772 static void wxConvertFromMSWTreeItem(wxTreeItem& info, TV_ITEM& tvItem, HWND getFullInfo)
773 {
774 info.m_data = tvItem.lParam;
775 info.m_mask = 0;
776 info.m_state = 0;
777 info.m_stateMask = 0;
778
779 long oldMask = tvItem.mask;
780
781 bool needText = FALSE;
782 if (getFullInfo != 0)
783 {
784 if ( tvItem.mask & TVIF_TEXT )
785 needText = FALSE;
786 else
787 needText = TRUE;
788
789 if ( needText )
790 {
791 tvItem.pszText = new char[513];
792 tvItem.cchTextMax = 512;
793 }
794 tvItem.mask |= TVIF_HANDLE | TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM ;
795 ::SendMessage(getFullInfo, TVM_GETITEM, 0, (LPARAM)& tvItem) ;
796 }
797
798 if ( tvItem.mask & TVIF_HANDLE )
799 {
800 info.m_mask |= wxTREE_MASK_HANDLE;
801 info.m_itemId = (long) tvItem.hItem;
802 }
803 if ( tvItem.mask & TVIF_STATE )
804 {
805 info.m_mask |= wxTREE_MASK_STATE;
806 if ( tvItem.stateMask & TVIS_BOLD)
807 {
808 info.m_stateMask |= wxTREE_STATE_BOLD ;
809 if ( tvItem.state & TVIS_BOLD )
810 info.m_state |= wxTREE_STATE_BOLD ;
811 }
812
813 if ( tvItem.stateMask & TVIS_CUT)
814 {
815 info.m_stateMask |= wxTREE_STATE_CUT ;
816 if ( tvItem.state & TVIS_CUT )
817 info.m_state |= wxTREE_STATE_CUT ;
818 }
819
820 if ( tvItem.stateMask & TVIS_DROPHILITED)
821 {
822 info.m_stateMask |= wxTREE_STATE_DROPHILITED ;
823 if ( tvItem.state & TVIS_DROPHILITED )
824 info.m_state |= wxTREE_STATE_DROPHILITED ;
825 }
826 if ( tvItem.stateMask & TVIS_EXPANDED)
827 {
828 info.m_stateMask |= wxTREE_STATE_EXPANDED ;
829 if ( tvItem.state & TVIS_EXPANDED )
830 info.m_state |= wxTREE_STATE_EXPANDED ;
831 }
832 if ( tvItem.stateMask & TVIS_EXPANDEDONCE)
833 {
834 info.m_stateMask |= wxTREE_STATE_EXPANDEDONCE ;
835 if ( tvItem.state & TVIS_EXPANDEDONCE )
836 info.m_state |= wxTREE_STATE_EXPANDEDONCE ;
837 }
838 if ( tvItem.stateMask & TVIS_FOCUSED)
839 {
840 info.m_stateMask |= wxTREE_STATE_FOCUSED ;
841 if ( tvItem.state & TVIS_FOCUSED )
842 info.m_state |= wxTREE_STATE_FOCUSED ;
843 }
844 if ( tvItem.stateMask & TVIS_SELECTED)
845 {
846 info.m_stateMask |= wxTREE_STATE_SELECTED ;
847 if ( tvItem.state & TVIS_SELECTED )
848 info.m_state |= wxTREE_STATE_SELECTED ;
849 }
850 }
851
852 if ( tvItem.mask & TVIF_TEXT )
853 {
854 info.m_mask |= wxTREE_MASK_TEXT;
855 info.m_text = tvItem.pszText;
856 }
857 if ( tvItem.mask & TVIF_IMAGE )
858 {
859 info.m_mask |= wxTREE_MASK_IMAGE;
860 info.m_image = tvItem.iImage;
861 }
862 if ( tvItem.mask & TVIF_SELECTEDIMAGE )
863 {
864 info.m_mask |= wxTREE_MASK_SELECTED_IMAGE;
865 info.m_selectedImage = tvItem.iSelectedImage;
866 }
867 if ( tvItem.mask & TVIF_CHILDREN )
868 {
869 info.m_mask |= wxTREE_MASK_CHILDREN;
870 info.m_children = tvItem.cChildren;
871 }
872 if ( tvItem.mask & TVIF_PARAM )
873 info.m_mask |= wxTREE_MASK_DATA;
874
875 if (needText)
876 {
877 if (tvItem.pszText)
878 delete[] tvItem.pszText;
879 }
880 tvItem.mask = oldMask ;
881 }
882
883 static void wxConvertToMSWTreeItem(wxTreeItem& info, TV_ITEM& tvItem)
884 {
885 tvItem.hItem = (HTREEITEM) info.m_itemId ;
886
887 tvItem.iImage = info.m_image ;
888 tvItem.iSelectedImage = info.m_selectedImage;
889 tvItem.cChildren = info.m_children;
890 tvItem.lParam = info.m_data;
891 tvItem.mask = 0;
892 tvItem.stateMask = 0;
893 tvItem.state = 0;
894
895 if (info.m_mask & wxTREE_MASK_HANDLE)
896 tvItem.mask |= TVIF_HANDLE ;
897 if (info.m_mask & wxTREE_MASK_STATE)
898 tvItem.mask |= TVIF_STATE ;
899 if (info.m_mask & wxTREE_MASK_TEXT)
900 {
901 tvItem.mask |= TVIF_TEXT ;
902 tvItem.pszText = (char *) (const char *)info.m_text ;
903 if ( tvItem.pszText )
904 tvItem.cchTextMax = info.m_text.Length();
905 else
906 tvItem.cchTextMax = 0;
907 }
908 if (info.m_mask & wxTREE_MASK_IMAGE)
909 tvItem.mask |= TVIF_IMAGE ;
910 if (info.m_mask & wxTREE_MASK_SELECTED_IMAGE)
911 tvItem.mask |= TVIF_SELECTEDIMAGE ;
912 if (info.m_mask & wxTREE_MASK_CHILDREN)
913 tvItem.mask |= TVIF_CHILDREN ;
914 if (info.m_mask & wxTREE_MASK_DATA)
915 tvItem.mask |= TVIF_PARAM ;
916
917 if (info.m_stateMask & wxTREE_STATE_BOLD)
918 {
919 tvItem.stateMask |= TVIS_BOLD ;
920 tvItem.state |= TVIS_BOLD;
921 }
922 if (info.m_stateMask & wxTREE_STATE_CUT)
923 {
924 tvItem.stateMask |= TVIS_CUT ;
925 if ( info.m_state & wxTREE_STATE_CUT )
926 tvItem.state |= TVIS_CUT;
927 }
928 if (info.m_stateMask & wxTREE_STATE_DROPHILITED)
929 {
930 tvItem.stateMask |= TVIS_DROPHILITED;
931 if ( info.m_state & wxTREE_STATE_DROPHILITED )
932 tvItem.state |= TVIS_DROPHILITED;
933 }
934 if (info.m_stateMask & wxTREE_STATE_EXPANDED)
935 {
936 tvItem.stateMask |= TVIS_EXPANDED;
937 if ( info.m_state & wxTREE_STATE_EXPANDED )
938 tvItem.state |= TVIS_EXPANDED;
939 }
940 if (info.m_stateMask & wxTREE_STATE_EXPANDEDONCE)
941 {
942 tvItem.stateMask |= TVIS_EXPANDEDONCE;
943 if ( info.m_state & wxTREE_STATE_EXPANDEDONCE )
944 tvItem.state |= TVIS_EXPANDEDONCE;
945 }
946 if (info.m_stateMask & wxTREE_STATE_FOCUSED)
947 {
948 tvItem.stateMask |= TVIS_FOCUSED;
949 if ( info.m_state & wxTREE_STATE_FOCUSED )
950 tvItem.state |= TVIS_FOCUSED;
951 }
952 if (info.m_stateMask & wxTREE_STATE_SELECTED)
953 {
954 tvItem.stateMask |= TVIS_SELECTED;
955 if ( info.m_state & wxTREE_STATE_SELECTED )
956 tvItem.state |= TVIS_SELECTED;
957 }
958 }
959
960 // Tree event
961 IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxCommandEvent)
962
963 wxTreeEvent::wxTreeEvent(wxEventType commandType, int id):
964 wxCommandEvent(commandType, id)
965 {
966 m_code = 0;
967 m_oldItem = 0;
968 }
969
970 #endif
971