]> git.saurik.com Git - wxWidgets.git/blob - src/os2/treectrl.cpp
Fix another crash when conversion fails in Unix PostScript code.
[wxWidgets.git] / src / os2 / treectrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/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 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_TREECTRL
27
28 #include "wx/treectrl.h"
29
30 #ifndef WX_PRECOMP
31 #include "wx/dynarray.h"
32 #include "wx/log.h"
33 #include "wx/app.h"
34 #include "wx/settings.h"
35 #endif
36
37 #include "wx/os2/private.h"
38
39 #include "wx/imaglist.h"
40
41 // a macro to hide the ugliness of nested casts
42 #define HITEM(item) (HTREEITEM)(WXHTREEITEM)(item)
43
44 // the native control doesn't support multiple selections under MSW and we
45 // have 2 ways to emulate them: either using TVS_CHECKBOXES style and let
46 // checkboxes be the selection status (checked == selected) or by really
47 // emulating everything, i.e. intercepting mouse and key events &c. The first
48 // approach is much easier but doesn't work with comctl32.dll < 4.71 and also
49 // looks quite ugly.
50 #define wxUSE_CHECKBOXES_IN_MULTI_SEL_TREE 0
51
52 // ----------------------------------------------------------------------------
53 // private functions
54 // ----------------------------------------------------------------------------
55
56 // ----------------------------------------------------------------------------
57 // private classes
58 // ----------------------------------------------------------------------------
59
60 typedef struct _MYRECORD
61 {
62 RECORDCORE m_vRecord;
63 ULONG m_ulItemId;
64 ULONG m_ulUserData;
65 } MYRECORD, *PMYRECORD;
66
67 struct wxTreeViewItem : public MYRECORD
68 {
69 wxTreeViewItem(const wxTreeItemId& rItem)
70 {
71 m_ulItemId = (ULONG)rItem.m_pItem;
72 }
73 }; // end of STRUCT wxTreeViewItem
74
75 class wxTreeItemInternalData
76 {
77 public:
78
79 wxTreeItemInternalData() {}
80 ~wxTreeItemInternalData()
81 {
82 wxDELETE(m_pAttr);
83 }
84
85 wxTreeItemAttr* m_pAttr;
86 WXLPARAM m_lParam; // user data
87 #if defined(C_CM_COS232)
88 PMYRECORD m_pMyRecord; // so we can set the m_ulUserData to 0 when this is deleted
89 #endif
90 }; // end of CLASS wxTreeItemInternalData
91
92 void BumpTreeRecordIds (
93 HWND hWnd
94 , PMYRECORD pRecord
95 )
96 {
97 while(pRecord)
98 {
99 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
100 ,CM_QUERYRECORD
101 ,MPFROMP(pRecord)
102 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
103 ));
104 if (pRecord)
105 pRecord->m_ulItemId++;
106 }
107 } // end of BumpTreeRecordIds
108
109 PMYRECORD FindOS2TreeRecordByID (
110 HWND hWnd
111 , long lItemId
112 )
113 {
114 PMYRECORD pRecord = NULL;
115 CNRINFO vCnrInfo;
116 unsigned long i;
117
118 if (!::WinSendMsg( hWnd
119 ,CM_QUERYCNRINFO
120 ,MPFROMP(&vCnrInfo)
121 ,(MPARAM)(USHORT)sizeof(CNRINFO)
122 ))
123 return NULL;
124 for (i = 0; i < vCnrInfo.cRecords; i++)
125 {
126 if (i == 0)
127 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
128 ,CM_QUERYRECORD
129 ,MPFROMP(pRecord)
130 ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
131 ));
132 else
133 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
134 ,CM_QUERYRECORD
135 ,MPFROMP(pRecord)
136 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
137 ));
138 if (!pRecord)
139 return NULL;
140 if (pRecord->m_ulItemId == (ULONG)lItemId)
141 break;
142 }
143 return pRecord;
144 } // end of FindOS2ListRecordByID
145
146
147
148 class wxTreeTraversal
149 {
150 public:
151 wxTreeTraversal(const wxTreeCtrl* pTree)
152 {
153 m_pTree = pTree;
154 }
155
156 //
157 // Do traverse the tree: visit all items (recursively by default) under the
158 // given one; return true if all items were traversed or false if the
159 // traversal was aborted because OnVisit returned false
160 //
161 bool DoTraverse( const wxTreeItemId& rRoot
162 ,bool bRecursively = true
163 );
164
165 //
166 // Override this function to do whatever is needed for each item, return
167 // false to stop traversing
168 //
169 virtual bool OnVisit(const wxTreeItemId& rItem) = 0;
170
171 protected:
172 const wxTreeCtrl* GetTree(void) const { return m_pTree; }
173
174 private:
175 bool Traverse( const wxTreeItemId& rRoot
176 ,bool bRecursively
177 );
178
179 const wxTreeCtrl* m_pTree;
180 wxDECLARE_NO_COPY_CLASS(wxTreeTraversal);
181 }; // end of CLASS wxTreeTraversal
182
183 //
184 // Internal class for getting the selected items
185 //
186 class TraverseSelections : public wxTreeTraversal
187 {
188 public:
189 TraverseSelections( const wxTreeCtrl* pTree
190 ,wxArrayTreeItemIds& raSelections
191 )
192 : wxTreeTraversal(pTree)
193 , m_aSelections(raSelections)
194 {
195 m_aSelections.Empty();
196 DoTraverse(pTree->GetRootItem());
197 }
198
199 virtual bool OnVisit(const wxTreeItemId& rItem)
200 {
201 //
202 // Can't visit a virtual node.
203 //
204 if ((GetTree()->GetRootItem() == rItem) && (GetTree()->GetWindowStyle() & wxTR_HIDE_ROOT))
205 {
206 return true;
207 }
208 PMYRECORD pRecord = FindOS2TreeRecordByID( (HWND)GetTree()->GetHWND()
209 ,rItem.m_pItem
210 );
211 if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED)
212 {
213 m_aSelections.Add(rItem);
214 }
215 return true;
216 }
217
218 size_t GetCount(void) const { return m_aSelections.GetCount(); }
219
220 private:
221 wxArrayTreeItemIds& m_aSelections;
222 }; // end of CLASS TraverseSelections
223
224 //
225 // Internal class for counting tree items
226 //
227 class TraverseCounter : public wxTreeTraversal
228 {
229 public:
230 TraverseCounter( const wxTreeCtrl* pTree
231 ,const wxTreeItemId& rRoot
232 ,bool bRecursively
233 )
234 : wxTreeTraversal(pTree)
235 {
236 m_nCount = 0;
237 DoTraverse(rRoot, bRecursively);
238 }
239
240 virtual bool OnVisit(const wxTreeItemId& WXUNUSED(rItem))
241 {
242 m_nCount++;
243 return true;
244 }
245
246 size_t GetCount(void) const { return m_nCount; }
247
248 private:
249 size_t m_nCount;
250 }; // end of CLASS TraverseCounter
251
252 // ----------------------------------------------------------------------------
253 // wxWin macros
254 // ----------------------------------------------------------------------------
255
256 // ----------------------------------------------------------------------------
257 // constants
258 // ----------------------------------------------------------------------------
259
260 // indices in gs_expandEvents table below
261 enum
262 {
263 IDX_COLLAPSE,
264 IDX_EXPAND,
265 IDX_WHAT_MAX
266 };
267
268 enum
269 {
270 IDX_DONE,
271 IDX_DOING,
272 IDX_HOW_MAX
273 };
274
275 // handy table for sending events - it has to be initialized during run-time
276 // now so can't be const any more
277 static /* const */ wxEventType gs_expandEvents[IDX_WHAT_MAX][IDX_HOW_MAX];
278
279 /*
280 but logically it's a const table with the following entries:
281 =
282 {
283 { wxEVT_TREE_ITEM_COLLAPSED, wxEVT_TREE_ITEM_COLLAPSING },
284 { wxEVT_TREE_ITEM_EXPANDED, wxEVT_TREE_ITEM_EXPANDING }
285 };
286 */
287
288 // ============================================================================
289 // implementation
290 // ============================================================================
291
292 // ----------------------------------------------------------------------------
293 // tree traversal
294 // ----------------------------------------------------------------------------
295
296 bool wxTreeTraversal::DoTraverse (
297 const wxTreeItemId& rRoot
298 , bool bRecursively
299 )
300 {
301 if (!OnVisit(rRoot))
302 return false;
303
304 return Traverse( rRoot
305 ,bRecursively
306 );
307 } // end of wxTreeTraversal::DoTraverse
308
309 bool wxTreeTraversal::Traverse (
310 const wxTreeItemId& rRoot
311 , bool bRecursively
312 )
313 {
314 long lCookie;
315 wxTreeItemId vChild = m_pTree->GetFirstChild( rRoot
316 ,lCookie
317 );
318 while (vChild.IsOk())
319 {
320 //
321 // Depth first traversal
322 //
323 if (bRecursively && !Traverse(vChild, true))
324 return false;
325 if (!OnVisit(vChild))
326 return false;
327 vChild = m_pTree->GetNextChild( rRoot
328 ,lCookie
329 );
330 }
331 return true;
332 } // end of wxTreeTraversal::Traverse
333
334 // ----------------------------------------------------------------------------
335 // construction and destruction
336 // ----------------------------------------------------------------------------
337
338 void wxTreeCtrl::Init ()
339 {
340 m_pImageListNormal = NULL;
341 m_pImageListState = NULL;
342 m_bOwnsImageListNormal = false;
343 m_bOwnsImageListState = false;
344 m_bHasAnyAttr = false;
345 m_pDragImage = NULL;
346
347 //
348 // Initialize the global array of events now as it can't be done statically
349 // with the wxEVT_XXX values being allocated during run-time only
350 //
351 gs_expandEvents[IDX_COLLAPSE][IDX_DONE] = wxEVT_TREE_ITEM_COLLAPSED;
352 gs_expandEvents[IDX_COLLAPSE][IDX_DOING] = wxEVT_TREE_ITEM_COLLAPSING;
353 gs_expandEvents[IDX_EXPAND][IDX_DONE] = wxEVT_TREE_ITEM_EXPANDED;
354 gs_expandEvents[IDX_EXPAND][IDX_DOING] = wxEVT_TREE_ITEM_EXPANDING;
355 } // end of wxTreeCtrl::Init
356
357 bool wxTreeCtrl::Create (
358 wxWindow* pParent
359 , wxWindowID vId
360 , const wxPoint& rPos
361 , const wxSize& rSize
362 , long lStyle
363 , const wxValidator& rValidator
364 , const wxString& rsName
365 )
366 {
367 CNRINFO vCnrInfo;
368
369 Init();
370 if (!CreateControl( pParent
371 ,vId
372 ,rPos
373 ,rSize
374 ,lStyle
375 ,rValidator
376 ,rsName
377 ))
378 return false;
379
380 DWORD dwStyle = WS_VISIBLE | WS_TABSTOP;
381
382 if (m_windowStyle & wxCLIP_SIBLINGS)
383 dwStyle |= WS_CLIPSIBLINGS;
384
385 // Create the tree control.
386 if (!OS2CreateControl( "CONTAINER"
387 ,dwStyle
388 ))
389 return false;
390
391 //
392 // Now set the display attributes to show a TREE/ICON view of the
393 // OS/2 Container
394 //
395 if (!::WinSendMsg( GetHWND()
396 ,CM_QUERYCNRINFO
397 ,MPFROMP(&vCnrInfo)
398 ,(MPARAM)(USHORT)sizeof(CNRINFO)
399 ))
400
401 vCnrInfo.flWindowAttr = CV_TREE|CV_ICON;
402 vCnrInfo.flWindowAttr |= CA_DRAWBITMAP;
403 if (m_windowStyle & wxTR_NO_LINES)
404 vCnrInfo.flWindowAttr |= CA_TREELINE;
405
406 ::WinSendMsg( GetHWND()
407 ,CM_SETCNRINFO
408 ,MPFROMP(&vCnrInfo)
409 ,(MPARAM)CMA_FLWINDOWATTR
410 );
411
412 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
413 SetForegroundColour(wxWindow::GetParent()->GetForegroundColour());
414 SetFont(*wxSMALL_FONT);
415 SetXComp(0);
416 SetYComp(0);
417 SetSize( rPos.x
418 ,rPos.y
419 ,rSize.x
420 ,rSize.y
421 );
422 return true;
423 } // end of wxTreeCtrl::Create
424
425 wxTreeCtrl::~wxTreeCtrl ()
426 {
427 //
428 // Delete any attributes
429 //
430 if (m_bHasAnyAttr)
431 {
432 for (wxNode* pNode = m_vAttrs.Next(); pNode; pNode = m_vAttrs.Next())
433 {
434 delete (wxTreeItemAttr *)pNode->Data();
435 }
436 m_bHasAnyAttr = false;
437 }
438 DeleteTextCtrl();
439
440 //
441 // Delete user data to prevent memory leaks
442 // also deletes hidden root node storage.
443 //
444 DeleteAllItems();
445 if (m_bOwnsImageListNormal)
446 delete m_pImageListNormal;
447 if (m_bOwnsImageListState)
448 delete m_pImageListState;
449 } // end of wxTreeCtrl::~wxTreeCtrl
450
451 // ----------------------------------------------------------------------------
452 // accessors
453 // ----------------------------------------------------------------------------
454
455 //
456 // simple wrappers which add error checking in debug mode. These methods
457 // assume the items are properly filled out already. If not, you get errors
458 //
459 bool wxTreeCtrl::DoGetItem (
460 wxTreeViewItem* pTvItem
461 ) const
462 {
463 PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
464 ,pTvItem->m_ulItemId
465 );
466
467 if (!pRecord)
468 {
469 wxLogLastError(wxT("Item not obtained"));
470 return false;
471 }
472 return true;
473 } // end of wxTreeCtrl::DoGetItem
474
475 void wxTreeCtrl::DoSetItem (
476 wxTreeViewItem* pTvItem
477 )
478 {
479 //
480 // Just invalidate the record to redisplay it
481 //
482 if (!::WinSendMsg( GetHWND()
483 ,CM_INVALIDATERECORD
484 ,MPFROMP(pTvItem)
485 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
486 ));
487 {
488 wxLogLastError(wxT("CM_INVALIDATERECORD"));
489 }
490 } // end of wxTreeCtrl::DoSetItem
491
492 unsigned int wxTreeCtrl::GetCount () const
493 {
494 CNRINFO vCnrInfo;
495
496 ::WinSendMsg( GetHWND()
497 ,CM_QUERYCNRINFO
498 ,MPFROMP(&vCnrInfo)
499 ,(MPARAM)(USHORT)sizeof(CNRINFO)
500 );
501
502 return (unsigned int)vCnrInfo.cRecords;
503 } // end of wxTreeCtrl::GetCount
504
505 unsigned int wxTreeCtrl::GetIndent () const
506 {
507 CNRINFO vCnrInfo;
508
509 ::WinSendMsg( GetHWND()
510 ,CM_QUERYCNRINFO
511 ,MPFROMP(&vCnrInfo)
512 ,(MPARAM)(USHORT)sizeof(CNRINFO)
513 );
514 return (unsigned int)vCnrInfo.cxTreeIndent;
515 } // end of wxTreeCtrl::GetIndent
516
517 void wxTreeCtrl::SetIndent (
518 unsigned int uIndent
519 )
520 {
521 CNRINFO vCnrInfo;
522
523 ::WinSendMsg( GetHWND()
524 ,CM_QUERYCNRINFO
525 ,MPFROMP(&vCnrInfo)
526 ,(MPARAM)(USHORT)sizeof(CNRINFO)
527 );
528 vCnrInfo.cxTreeIndent = (LONG)uIndent;
529 ::WinSendMsg( GetHWND()
530 ,CM_SETCNRINFO
531 ,MPFROMP(&vCnrInfo)
532 ,(MPARAM)CMA_CXTREEINDENT
533 );
534 } // end of wxTreeCtrl::SetIndent
535
536 wxImageList* wxTreeCtrl::GetImageList () const
537 {
538 return m_pImageListNormal;
539 } // end of wxTreeCtrl::GetImageList
540
541 wxImageList* wxTreeCtrl::GetStateImageList () const
542 {
543 return m_pImageListNormal;
544 } // end of wxTreeCtrl::GetStateImageList
545
546 //
547 // The SETS of imagelists really do nothing under OS2 as a RECORDCORE
548 // struct has the icon imbedded in it that it uses for the icon being
549 // displayed via the TREEITEMDESC member. Provided for interface
550 // compatibility only
551 //
552 void wxTreeCtrl::SetAnyImageList (
553 wxImageList* WXUNUSED(pImageList)
554 , int WXUNUSED(nWhich)
555 )
556 {
557 } // end of wxTreeCtrl::SetAnyImageList
558
559 void wxTreeCtrl::SetImageList (
560 wxImageList* WXUNUSED(pImageList)
561 )
562 {
563 if (m_bOwnsImageListNormal)
564 delete m_pImageListNormal;
565 m_bOwnsImageListNormal = false;
566 } // end of wxTreeCtrl::SetImageList
567
568 void wxTreeCtrl::SetStateImageList (
569 wxImageList* WXUNUSED(pImageList)
570 )
571 {
572 if (m_bOwnsImageListState)
573 delete m_pImageListState;
574 m_bOwnsImageListState = false;
575 } // end of wxTreeCtrl::SetStateImageList
576
577 void wxTreeCtrl::AssignImageList (
578 wxImageList* WXUNUSED(pImageList)
579 )
580 {
581 m_bOwnsImageListNormal = true;
582 } // end of wxTreeCtrl::AssignImageList
583
584 void wxTreeCtrl::AssignStateImageList (
585 wxImageList* WXUNUSED(pImageList)
586 )
587 {
588 m_bOwnsImageListState = true;
589 } // end of wxTreeCtrl::AssignStateImageList
590
591 size_t wxTreeCtrl::GetChildrenCount (
592 const wxTreeItemId& rItem
593 , bool bRecursively
594 ) const
595 {
596 TraverseCounter vCounter( this
597 ,rItem
598 ,bRecursively
599 );
600 return vCounter.GetCount() - 1;
601 } // end of wxTreeCtrl::GetChildrenCount
602
603 // ----------------------------------------------------------------------------
604 // control colours
605 // ----------------------------------------------------------------------------
606
607 bool wxTreeCtrl::SetBackgroundColour (
608 const wxColour& rColour
609 )
610 {
611 ULONG ulColor = wxColourToRGB(rColour);
612
613 if ( !wxWindowBase::SetBackgroundColour(rColour) )
614 return false;
615 ::WinSetPresParam( GetHWND()
616 ,PP_BACKGROUNDCOLOR
617 ,sizeof(ULONG)
618 ,&ulColor
619 );
620 return true;
621 } // end of wxTreeCtrl::SetBackgroundColour
622
623 bool wxTreeCtrl::SetForegroundColour (
624 const wxColour& rColour
625 )
626 {
627 ULONG ulColor = wxColourToRGB(rColour);
628
629 if (!wxWindowBase::SetForegroundColour(rColour))
630 return false;
631 ::WinSetPresParam( GetHWND()
632 ,PP_FOREGROUNDCOLOR
633 ,sizeof(ULONG)
634 ,&ulColor
635 );
636 return true;
637 } // end of wxTreeCtrl::SetForegroundColour
638
639 // ----------------------------------------------------------------------------
640 // Item access
641 // ----------------------------------------------------------------------------
642
643 wxString wxTreeCtrl::GetItemText (
644 const wxTreeItemId& rItem
645 ) const
646 {
647 wxChar zBuf[512]; // the size is arbitrary...
648 wxTreeViewItem vTvItem(rItem);
649
650 if (!DoGetItem(&vTvItem))
651 {
652 //
653 // Don't return some garbage which was on stack, but an empty string
654 //
655 zBuf[0] = wxT('\0');
656 }
657 else
658 strcpy(zBuf, vTvItem.m_vRecord.pszTree);
659 return wxString(zBuf);
660 } // end of wxTreeCtrl::GetItemText
661
662 void wxTreeCtrl::SetItemText (
663 const wxTreeItemId& rItem
664 , const wxString& rsText
665 )
666 {
667 wxTreeViewItem vTvItem(rItem);
668
669 vTvItem.m_vRecord.pszTree = (wxChar *)rsText.c_str(); // conversion is ok
670 DoSetItem(&vTvItem);
671 } // end of wxTreeCtrl::SetItemText
672
673 //
674 // These functions under OS/2 PM are not needed. OS/2 containers in tree view
675 // provide for storing a custom expanded and collapsed icons and selected
676 // and non selected icons, natively. For instance, by default, a disk display
677 // will display a tree list of folder icons with "+" icons (collapsed) beside
678 // those folder which contain child members. Double clicking a folder changes
679 // the closed folder icon to an open folder icon with hatched selection
680 // highlighting indicating an ICON view container of the folder is open
681 // elsewhere on the desktop. So the below is not really needed, but we will
682 // simply return the appropriate icon requested out of OS/2's native PM
683 // data structures.
684 //
685 int wxTreeCtrl::DoGetItemImageFromData (
686 const wxTreeItemId& WXUNUSED(rItem)
687 , wxTreeItemIcon nWhich
688 ) const
689 {
690 //
691 // Image handles stored in CNRINFO.
692 //
693 CNRINFO vCnrInfo;
694
695 ::WinSendMsg( GetHWND()
696 ,CM_QUERYCNRINFO
697 ,MPFROMP(&vCnrInfo)
698 ,(MPARAM)(USHORT)sizeof(CNRINFO)
699 );
700
701 //
702 // We really only have two to chose from. If not custom (set in CNRINFO
703 // then return the handle to system bitmap). OS/2 automatically provides
704 // in_use and selected bitmaps/icons
705 //
706 switch(nWhich)
707 {
708 case wxTreeItemIcon_Normal:
709 if (vCnrInfo.hbmCollapsed == NULLHANDLE)
710 return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEPLUS);
711 return vCnrInfo.hbmCollapsed;
712
713
714 case wxTreeItemIcon_Expanded:
715 if (vCnrInfo.hbmExpanded == NULLHANDLE)
716 return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEMINUS);
717 return vCnrInfo.hbmExpanded;
718
719 default:
720 return vCnrInfo.hbmCollapsed;
721 }
722 }
723
724 void wxTreeCtrl::DoSetItemImageFromData (
725 const wxTreeItemId& WXUNUSED(rItem)
726 , int nImage
727 , wxTreeItemIcon nWhich
728 ) const
729 {
730 //
731 // Image handles stored in CNRINFO.
732 //
733 CNRINFO vCnrInfo;
734
735 ::WinSendMsg( GetHWND()
736 ,CM_QUERYCNRINFO
737 ,MPFROMP(&vCnrInfo)
738 ,(MPARAM)(USHORT)sizeof(CNRINFO)
739 );
740 if (nWhich == wxTreeItemIcon_Normal)
741 vCnrInfo.hbmCollapsed = (HBITMAP)nImage;
742 if (nWhich == wxTreeItemIcon_Expanded)
743 vCnrInfo.hbmExpanded = (HBITMAP)nImage;
744 ::WinSendMsg( GetHWND()
745 ,CM_SETCNRINFO
746 ,MPFROMP(&vCnrInfo)
747 ,(MPARAM)CMA_TREEBITMAP
748 );
749 } // end of wxTreeCtrl::DoSetItemImageFromData
750
751 // Useless for OS/2
752 void wxTreeCtrl::DoSetItemImages (
753 const wxTreeItemId& rItem
754 , int nImage
755 , int nImageSel
756 )
757 {
758 } // end of wxTreeCtrl::DoSetItemImages
759
760 int wxTreeCtrl::GetItemImage (
761 const wxTreeItemId& rItem
762 , wxTreeItemIcon nWhich
763 ) const
764 {
765 if (HasIndirectData(rItem))
766 {
767 return DoGetItemImageFromData( rItem
768 ,nWhich
769 );
770 }
771
772 CNRINFO vCnrInfo;
773
774 ::WinSendMsg( GetHWND()
775 ,CM_QUERYCNRINFO
776 ,MPFROMP(&vCnrInfo)
777 ,(MPARAM)(USHORT)sizeof(CNRINFO)
778 );
779 switch (nWhich)
780 {
781 default:
782 wxFAIL_MSG( wxT("unknown tree item image type") );
783
784 case wxTreeItemIcon_Normal:
785 if (vCnrInfo.hbmCollapsed == NULLHANDLE)
786 return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEPLUS);
787 return vCnrInfo.hbmCollapsed;
788
789
790 case wxTreeItemIcon_Expanded:
791 if (vCnrInfo.hbmExpanded == NULLHANDLE)
792 return (int)::WinGetSysBitmap(HWND_DESKTOP, SBMP_TREEMINUS);
793 return vCnrInfo.hbmExpanded;
794
795 case wxTreeItemIcon_Selected:
796 case wxTreeItemIcon_SelectedExpanded:
797 return -1;
798 }
799 }
800
801 void wxTreeCtrl::SetItemImage (
802 const wxTreeItemId& WXUNUSED(rItem)
803 , int nImage
804 , wxTreeItemIcon nWhich
805 )
806 {
807 CNRINFO vCnrInfo;
808
809 ::WinSendMsg( GetHWND()
810 ,CM_QUERYCNRINFO
811 ,MPFROMP(&vCnrInfo)
812 ,(MPARAM)(USHORT)sizeof(CNRINFO)
813 );
814 switch (nWhich)
815 {
816 case wxTreeItemIcon_Normal:
817 vCnrInfo.hbmCollapsed = (HBITMAP)nImage;
818 break;
819
820 case wxTreeItemIcon_Expanded:
821 vCnrInfo.hbmExpanded = (HBITMAP)nImage;
822 break;
823
824 default:
825 wxFAIL_MSG( wxT("unknown tree item image type") );
826 }
827 ::WinSendMsg( GetHWND()
828 ,CM_SETCNRINFO
829 ,MPFROMP(&vCnrInfo)
830 ,(MPARAM)CMA_TREEBITMAP
831 );
832 } // end of wxTreeCtrl::SetItemImage
833
834 wxTreeItemData* wxTreeCtrl::GetItemData (
835 const wxTreeItemId& rItem
836 ) const
837 {
838 wxTreeViewItem vTvItem(rItem);
839
840 if (!DoGetItem(&vTvItem))
841 {
842 return NULL;
843 }
844
845 return (wxTreeItemData *)vTvItem.m_ulUserData;
846 } // end of wxTreeCtrl::GetItemData
847
848 void wxTreeCtrl::SetItemData (
849 const wxTreeItemId& rItem
850 , wxTreeItemData* pData
851 )
852 {
853 //
854 // first, associate this piece of data with this item
855 if (pData)
856 {
857 pData->SetId(rItem);
858 }
859
860 wxTreeViewItem vTvItem(rItem);
861
862 vTvItem.m_ulUserData = (ULONG)pData;
863 DoSetItem(&vTvItem);
864 } // end of wxTreeCtrl::SetItemData
865
866 // The following two do nothing under OS/2
867 void wxTreeCtrl::SetIndirectItemData (
868 const wxTreeItemId& WXUNUSED(rItem)
869 , wxTreeItemIndirectData* WXUNUSED(pData)
870 )
871 {
872 } // end of wxTreeCtrl::SetIndirectItemData
873
874 bool wxTreeCtrl::HasIndirectData (
875 const wxTreeItemId& WXUNUSED(rItem)
876 ) const
877 {
878 return false;
879 } // end of wxTreeCtrl::HasIndirectData
880
881 // Irreleveant under OS/2 --- item either has child records or it doesn't.
882 void wxTreeCtrl::SetItemHasChildren (
883 const wxTreeItemId& WXUNUSED(rItem)
884 , bool WXUNUSED(bHas)
885 )
886 {
887 } // end of wxTreeCtrl::SetItemHasChildren
888
889 // Irreleveant under OS/2 --- function of the font in PM
890 void wxTreeCtrl::SetItemBold (
891 const wxTreeItemId& WXUNUSED(rItem)
892 , bool WXUNUSED(bBold)
893 )
894 {
895 } // end of wxTreeCtrl::SetItemBold
896
897 void wxTreeCtrl::SetItemDropHighlight (
898 const wxTreeItemId& rItem
899 , bool bHighlight
900 )
901 {
902 wxTreeViewItem vTvItem(rItem);
903
904 ::WinSendMsg( GetHWND()
905 ,CM_SETRECORDEMPHASIS
906 ,MPFROMP(&vTvItem)
907 ,MPFROM2SHORT(bHighlight, CRA_SELECTED)
908 );
909 DoSetItem(&vTvItem);
910 } // end of wxTreeCtrl::SetItemDropHighlight
911
912 void wxTreeCtrl::RefreshItem (
913 const wxTreeItemId& rItem
914 )
915 {
916 wxTreeViewItem vTvItem(rItem);
917
918 //
919 // This just does a record invalidate causing it to be re-displayed
920 //
921 DoSetItem(&vTvItem);
922 } // end of wxTreeCtrl::RefreshItem
923
924 wxColour wxTreeCtrl::GetItemTextColour (
925 const wxTreeItemId& rItem
926 ) const
927 {
928 long lId = (long)rItem.m_pItem;
929 wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
930
931 if (!pAttr)
932 {
933 return wxNullColour;
934 }
935 return pAttr->GetTextColour();
936 } // end of wxTreeCtrl::GetItemTextColour
937
938 wxColour wxTreeCtrl::GetItemBackgroundColour (
939 const wxTreeItemId& rItem
940 ) const
941 {
942 long lId = (long)rItem.m_pItem;
943 wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
944
945 if (!pAttr)
946 {
947 return wxNullColour;
948 }
949 return pAttr->GetBackgroundColour();
950 } // end of wxTreeCtrl::GetItemBackgroundColour
951
952 wxFont wxTreeCtrl::GetItemFont (
953 const wxTreeItemId& rItem
954 ) const
955 {
956 long lId = (long)rItem.m_pItem;
957 wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
958
959 if (!pAttr)
960 {
961 return wxNullFont;
962 }
963 return pAttr->GetFont();
964 } // end of wxTreeCtrl::GetItemFont
965
966 void wxTreeCtrl::SetItemTextColour (
967 const wxTreeItemId& rItem
968 , const wxColour& rCol
969 )
970 {
971 m_bHasAnyAttr = true;
972
973 long lId = (long)rItem.m_pItem;
974 wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
975
976 if (!pAttr)
977 {
978 pAttr = new wxTreeItemAttr;
979 m_vAttrs.Put(lId, (wxObject *)pAttr);
980 }
981 pAttr->SetTextColour(rCol);
982 RefreshItem(rItem);
983 } // end of wxTreeCtrl::SetItemTextColour
984
985 void wxTreeCtrl::SetItemBackgroundColour (
986 const wxTreeItemId& rItem
987 , const wxColour& rCol
988 )
989 {
990 m_bHasAnyAttr = true;
991
992 long lId = (long)rItem.m_pItem;
993 wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
994
995 if (!pAttr)
996 {
997 pAttr = new wxTreeItemAttr;
998 m_vAttrs.Put(lId, (wxObject *)pAttr);
999 }
1000 pAttr->SetBackgroundColour(rCol);
1001 RefreshItem(rItem);
1002 } // end of wxTreeCtrl::SetItemBackgroundColour
1003
1004 void wxTreeCtrl::SetItemFont (
1005 const wxTreeItemId& rItem
1006 , const wxFont& rFont
1007 )
1008 {
1009 m_bHasAnyAttr = true;
1010
1011 long lId = (long)rItem.m_pItem;
1012 wxTreeItemAttr* pAttr = (wxTreeItemAttr *)m_vAttrs.Get(lId);
1013
1014 if (!pAttr)
1015 {
1016 pAttr = new wxTreeItemAttr;
1017 m_vAttrs.Put(lId, (wxObject *)pAttr);
1018 }
1019 pAttr->SetFont(rFont);
1020 RefreshItem(rItem);
1021 } // end of wxTreeCtrl::SetItemFont
1022
1023 // ----------------------------------------------------------------------------
1024 // Item status
1025 // ----------------------------------------------------------------------------
1026
1027 bool wxTreeCtrl::IsVisible (
1028 const wxTreeItemId& rItem
1029 ) const
1030 {
1031 // Bug in Gnu-Win32 headers, so don't use the macro TreeView_GetItemRect
1032 RECTL vRectRecord;
1033 RECTL vRectContainer;
1034 wxRect vWxRectRecord;
1035 wxRect vWxRectContainer;
1036 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1037 ,rItem.m_pItem
1038 );
1039 QUERYRECORDRECT vQuery;
1040
1041 vQuery.cb = sizeof(QUERYRECORDRECT);
1042 vQuery.pRecord = (PRECORDCORE)pRecord;
1043 vQuery.fRightSplitWindow = FALSE;
1044 vQuery.fsExtent = CMA_TREEICON;
1045
1046 ::WinSendMsg( GetHWND()
1047 ,CM_QUERYVIEWPORTRECT
1048 ,MPFROMP(&vRectContainer)
1049 ,MPFROM2SHORT(CMA_WINDOW, FALSE)
1050 );
1051 ::WinSendMsg( GetHWND()
1052 ,CM_QUERYRECORDRECT
1053 ,MPFROMP(&vRectRecord)
1054 ,MPFROMP(&vQuery)
1055 );
1056 vWxRectRecord.SetLeft(vRectRecord.xLeft);
1057 vWxRectRecord.SetTop(vRectRecord.yTop);
1058 vWxRectRecord.SetRight(vRectRecord.xRight);
1059 vWxRectRecord.SetBottom(vRectRecord.yBottom);
1060
1061 vWxRectContainer.SetLeft(vRectContainer.xLeft);
1062 vWxRectContainer.SetTop(vRectContainer.yTop);
1063 vWxRectContainer.SetRight(vRectContainer.xRight);
1064 vWxRectContainer.SetBottom(vRectContainer.yBottom);
1065 return (vWxRectContainer.Contains(wxPoint(vWxRectRecord.x, vWxRectRecord.y)));
1066 } // end of wxTreeCtrl::IsVisible
1067
1068 bool wxTreeCtrl::ItemHasChildren (
1069 const wxTreeItemId& rItem
1070 ) const
1071 {
1072 wxTreeViewItem vTvItem(rItem);
1073 DoGetItem(&vTvItem);
1074
1075 //
1076 // A tree record with children will have one of these attributes
1077 //
1078 return (vTvItem.m_vRecord.flRecordAttr & CRA_EXPANDED ||
1079 vTvItem.m_vRecord.flRecordAttr & CRA_COLLAPSED) != 0;
1080 }
1081
1082 bool wxTreeCtrl::IsExpanded (
1083 const wxTreeItemId& rItem
1084 ) const
1085 {
1086 wxTreeViewItem vTvItem(rItem);
1087 DoGetItem(&vTvItem);
1088
1089 return (vTvItem.m_vRecord.flRecordAttr & CRA_EXPANDED) != 0;
1090 } // end of wxTreeCtrl::IsExpanded
1091
1092 bool wxTreeCtrl::IsSelected (
1093 const wxTreeItemId& rItem
1094 ) const
1095 {
1096 wxTreeViewItem vTvItem(rItem);
1097 DoGetItem(&vTvItem);
1098
1099 return (vTvItem.m_vRecord.flRecordAttr & CRA_SELECTED) != 0;
1100 } // end of wxTreeCtrl::IsSelected
1101
1102 // Not supported
1103 bool wxTreeCtrl::IsBold (
1104 const wxTreeItemId& rItem
1105 ) const
1106 {
1107 return false;
1108 } // end of wxTreeCtrl::IsBold
1109
1110 // ----------------------------------------------------------------------------
1111 // navigation
1112 // ----------------------------------------------------------------------------
1113
1114 wxTreeItemId wxTreeCtrl::GetRootItem () const
1115 {
1116 PMYRECORD pRecord = NULL;
1117
1118 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1119 ,CM_QUERYRECORD
1120 ,MPFROMP(pRecord)
1121 ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
1122 ));
1123
1124 if (!pRecord)
1125 return wxTreeItemId(-1L);
1126 return wxTreeItemId((long)pRecord->m_ulItemId);
1127 } // end of wxTreeCtrl::GetRootItem
1128
1129 wxTreeItemId wxTreeCtrl::GetSelection () const
1130 {
1131 wxCHECK_MSG( !(m_windowStyle & wxTR_MULTIPLE), (long)(WXHTREEITEM)0,
1132 wxT("this only works with single selection controls") );
1133
1134 PMYRECORD pRecord = NULL;
1135
1136 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1137 ,CM_QUERYRECORDEMPHASIS
1138 ,MPARAM(CMA_FIRST)
1139 ,MPARAM(CRA_SELECTED)
1140 ));
1141 if (!pRecord)
1142 return wxTreeItemId(-1L);
1143 return wxTreeItemId((long)pRecord->m_ulItemId);
1144 } // end of wxTreeCtrl::GetSelection
1145
1146 wxTreeItemId wxTreeCtrl::GetItemParent (
1147 const wxTreeItemId& rItem
1148 ) const
1149 {
1150 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1151 ,rItem.m_pItem
1152 );
1153
1154 if (!pRecord)
1155 return wxTreeItemId(-1L);
1156 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1157 ,CM_QUERYRECORD
1158 ,MPFROMP(pRecord)
1159 ,MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER)
1160 ));
1161 if (!pRecord)
1162 return wxTreeItemId(-1L);
1163 return wxTreeItemId((long)pRecord->m_ulItemId);
1164 } // end of wxTreeCtrl::GetItemParent
1165
1166 wxTreeItemId wxTreeCtrl::GetFirstChild (
1167 const wxTreeItemId& rItem
1168 , long& rCookie
1169 ) const
1170 {
1171 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1172 ,rItem.m_pItem
1173 );
1174
1175 if (!pRecord)
1176 return wxTreeItemId(-1L);
1177 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1178 ,CM_QUERYRECORD
1179 ,MPFROMP(pRecord)
1180 ,MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER)
1181 ));
1182 if (!pRecord)
1183 return wxTreeItemId(-1L);
1184 //
1185 // Remember the last child returned in 'cookie'
1186 //
1187 rCookie = (long)pRecord->m_ulItemId;
1188 return wxTreeItemId(rCookie);
1189 } // end of wxTreeCtrl::GetFirstChild
1190
1191 wxTreeItemId wxTreeCtrl::GetNextChild (
1192 const wxTreeItemId& WXUNUSED(rItem)
1193 , long& rCookie
1194 ) const
1195 {
1196 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1197 ,rCookie
1198 );
1199
1200 if (!pRecord)
1201 return wxTreeItemId(-1L);
1202 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1203 ,CM_QUERYRECORD
1204 ,MPFROMP(pRecord)
1205 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
1206 ));
1207 if (!pRecord)
1208 return wxTreeItemId(-1L);
1209 rCookie = (long)pRecord->m_ulItemId;
1210 return wxTreeItemId(rCookie);
1211 } // end of wxTreeCtrl::GetNextChild
1212
1213 wxTreeItemId wxTreeCtrl::GetLastChild (
1214 const wxTreeItemId& rItem
1215 ) const
1216 {
1217 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1218 ,rItem.m_pItem
1219 );
1220
1221 if (!pRecord)
1222 return wxTreeItemId(-1L);
1223 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1224 ,CM_QUERYRECORD
1225 ,MPFROMP(pRecord)
1226 ,MPFROM2SHORT(CMA_LASTCHILD, CMA_ITEMORDER)
1227 ));
1228 if (!pRecord)
1229 return wxTreeItemId(-1L);
1230 return wxTreeItemId((long)pRecord->m_ulItemId);
1231 } // end of wxTreeCtrl::GetLastChild
1232
1233 wxTreeItemId wxTreeCtrl::GetNextSibling (
1234 const wxTreeItemId& rItem
1235 ) const
1236 {
1237 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1238 ,rItem.m_pItem
1239 );
1240
1241 if (!pRecord)
1242 return wxTreeItemId(-1L);
1243 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1244 ,CM_QUERYRECORD
1245 ,MPFROMP(pRecord)
1246 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
1247 ));
1248 if (!pRecord)
1249 return wxTreeItemId(-1L);
1250 return wxTreeItemId((long)pRecord->m_ulItemId);
1251 } // end of wxTreeCtrl::GetNextSibling
1252
1253 wxTreeItemId wxTreeCtrl::GetPrevSibling (
1254 const wxTreeItemId& rItem
1255 ) const
1256 {
1257 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1258 ,rItem.m_pItem
1259 );
1260
1261 if (!pRecord)
1262 return wxTreeItemId(-1L);
1263 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1264 ,CM_QUERYRECORD
1265 ,MPFROMP(pRecord)
1266 ,MPFROM2SHORT(CMA_PREV, CMA_ITEMORDER)
1267 ));
1268 if (!pRecord)
1269 return wxTreeItemId(-1L);
1270 return wxTreeItemId((long)pRecord->m_ulItemId);
1271 } // end of wxTreeCtrl::GetPrevSibling
1272
1273 wxTreeItemId wxTreeCtrl::GetFirstVisibleItem () const
1274 {
1275 PMYRECORD pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1276 ,CM_QUERYRECORD
1277 ,MPFROMP(pRecord)
1278 ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
1279 ));
1280 if (!pRecord)
1281 return wxTreeItemId(-1L);
1282
1283 if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
1284 return wxTreeItemId((long)pRecord->m_ulItemId);
1285 while(pRecord)
1286 {
1287 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1288 ,CM_QUERYRECORD
1289 ,MPFROMP(pRecord)
1290 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
1291 ));
1292 if (!pRecord)
1293 return wxTreeItemId(-1L);
1294 if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
1295 return wxTreeItemId((long)pRecord->m_ulItemId);
1296 }
1297 return wxTreeItemId(-1L);
1298 } // end of wxTreeCtrl::GetFirstVisibleItem
1299
1300 wxTreeItemId wxTreeCtrl::GetNextVisible (
1301 const wxTreeItemId& rItem
1302 ) const
1303 {
1304 wxASSERT_MSG(IsVisible(rItem), wxT("The item you call GetNextVisible() for must be visible itself!"));
1305
1306 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1307 ,rItem.m_pItem
1308 );
1309
1310 if (!pRecord)
1311 return wxTreeItemId(-1L);
1312 while(pRecord)
1313 {
1314 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1315 ,CM_QUERYRECORD
1316 ,MPFROMP(pRecord)
1317 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
1318 ));
1319 if (!pRecord)
1320 return wxTreeItemId(-1L);
1321 if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
1322 return wxTreeItemId((long)pRecord->m_ulItemId);
1323 }
1324 return wxTreeItemId(-1L);
1325 } // end of wxTreeCtrl::GetNextVisible
1326
1327 wxTreeItemId wxTreeCtrl::GetPrevVisible (
1328 const wxTreeItemId& rItem
1329 ) const
1330 {
1331 wxASSERT_MSG( IsVisible(rItem), wxT("The item you call GetPrevVisible() for must be visible itself!"));
1332
1333 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1334 ,rItem.m_pItem
1335 );
1336
1337 if (!pRecord)
1338 return wxTreeItemId(-1L);
1339 while(pRecord)
1340 {
1341 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1342 ,CM_QUERYRECORD
1343 ,MPFROMP(pRecord)
1344 ,MPFROM2SHORT(CMA_PREV, CMA_ITEMORDER)
1345 ));
1346 if (!pRecord)
1347 return wxTreeItemId(-1L);
1348 if (IsVisible(wxTreeItemId((long)pRecord->m_ulItemId)))
1349 return wxTreeItemId((long)pRecord->m_ulItemId);
1350 }
1351 return wxTreeItemId(-1L);
1352 } // end of wxTreeCtrl::GetPrevVisible
1353
1354 // ----------------------------------------------------------------------------
1355 // multiple selections emulation -- under OS/2 checked tree items is not
1356 // supported, but multisel is. So we'll just check for selections here.
1357 // ----------------------------------------------------------------------------
1358
1359 bool wxTreeCtrl::IsItemChecked (
1360 const wxTreeItemId& rItem
1361 ) const
1362 {
1363 wxTreeViewItem vTvItem(rItem);
1364
1365 DoGetItem(&vTvItem);
1366 return (vTvItem.m_vRecord.flRecordAttr & CRA_SELECTED);
1367 } // end of wxTreeCtrl::IsItemChecked
1368
1369 void wxTreeCtrl::SetItemCheck (
1370 const wxTreeItemId& rItem
1371 , bool bCheck
1372 )
1373 {
1374 wxTreeViewItem vTvItem(rItem);
1375
1376 DoGetItem(&vTvItem);
1377 ::WinSendMsg( GetHWND()
1378 ,CM_SETRECORDEMPHASIS
1379 ,MPFROMP(&vTvItem)
1380 ,MPFROM2SHORT(TRUE, CRA_SELECTED)
1381 );
1382 DoSetItem(&vTvItem);
1383 } // end of wxTreeCtrl::SetItemCheck
1384
1385 size_t wxTreeCtrl::GetSelections (
1386 wxArrayTreeItemIds& raSelections
1387 ) const
1388 {
1389 TraverseSelections vSelector( this
1390 ,raSelections
1391 );
1392 return vSelector.GetCount();
1393 } // end of wxTreeCtrl::GetSelections
1394
1395 // ----------------------------------------------------------------------------
1396 // Usual operations
1397 // ----------------------------------------------------------------------------
1398
1399 wxTreeItemId wxTreeCtrl::DoInsertItem (
1400 const wxTreeItemId& rParent
1401 , wxTreeItemId vInsertAfter
1402 , const wxString& rsText
1403 , int nImage
1404 , int selectedImage
1405 , wxTreeItemData* pData
1406 )
1407 {
1408 PMYRECORD pRecordAfter = FindOS2TreeRecordByID( GetHWND()
1409 ,vInsertAfter.m_pItem
1410 );
1411
1412 PMYRECORD pRecordParent = FindOS2TreeRecordByID( GetHWND()
1413 ,rParent.m_pItem
1414 );
1415
1416 PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1417 ,CM_ALLOCRECORD
1418 ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
1419 ,MPFROMLONG(1)
1420 );
1421 RECORDINSERT vInsert;
1422
1423 vInsert.cb = sizeof(RECORDINSERT);
1424 if (rParent.m_pItem == 0L)
1425 {
1426 if (vInsertAfter.m_pItem == -1)
1427 vInsert.pRecordOrder = (PRECORDCORE)CMA_END;
1428 else
1429 vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
1430 vInsert.pRecordParent = NULL;
1431 }
1432 else
1433 {
1434 if (vInsertAfter.m_pItem == 0)
1435 vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
1436 else if (vInsertAfter.m_pItem == -1)
1437 vInsert.pRecordOrder = (PRECORDCORE)CMA_END;
1438 else
1439 vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
1440 vInsert.pRecordParent = (PRECORDCORE)pRecordParent;
1441 }
1442 vInsert.fInvalidateRecord = TRUE;
1443 vInsert.zOrder = CMA_TOP;
1444 vInsert.cRecordsInsert = 1;
1445
1446 pRecord->m_vRecord.pszTree = (wxChar*)rsText.c_str();
1447 pRecord->m_vRecord.hbmBitmap = nImage;
1448 pRecord->m_ulItemId = pRecordAfter->m_ulItemId + 1;
1449 if (pData != NULL)
1450 {
1451 pRecord->m_ulUserData = (ULONG)pData;
1452 }
1453 ::WinSendMsg( GetHWND()
1454 ,CM_INSERTRECORD
1455 ,MPFROMP(pRecord)
1456 ,MPFROMP(&vInsert)
1457 );
1458
1459 //
1460 // OS/2 must mannually bump the index's of following records
1461 //
1462 BumpTreeRecordIds( GetHWND()
1463 ,pRecord
1464 );
1465 if (pData != NULL)
1466 {
1467 //
1468 // Associate the application tree item with PM tree item handle
1469 //
1470 pData->SetId((long)pRecord->m_ulItemId);
1471 }
1472 return wxTreeItemId((long)pRecord->m_ulItemId);
1473 }
1474
1475 wxTreeItemId wxTreeCtrl::AddRoot (
1476 const wxString& rsText
1477 , int nImage
1478 , int nSelectedImage
1479 , wxTreeItemData* pData)
1480 {
1481
1482 return DoInsertItem( wxTreeItemId((long)0)
1483 ,wxTreeItemId((long)-1)
1484 ,rsText
1485 ,nImage
1486 ,nSelectedImage
1487 ,pData
1488 );
1489 } // end of wxTreeCtrl::AddRoot
1490
1491 wxTreeItemId wxTreeCtrl::PrependItem (
1492 const wxTreeItemId& rParent
1493 , const wxString& rsText
1494 , int nImage
1495 , int nSelectedImage
1496 , wxTreeItemData* pData
1497 )
1498 {
1499 return DoInsertItem( rParent
1500 ,wxTreeItemId((long)0)
1501 ,rsText
1502 ,nImage
1503 ,nSelectedImage
1504 ,pData
1505 );
1506 } // end of wxTreeCtrl::PrependItem
1507
1508 wxTreeItemId wxTreeCtrl::InsertItem (
1509 const wxTreeItemId& rParent
1510 , const wxTreeItemId& rIdPrevious
1511 , const wxString& rsText
1512 , int nImage
1513 , int nSelectedImage
1514 , wxTreeItemData* pData
1515 )
1516 {
1517 return DoInsertItem( rParent
1518 ,rIdPrevious
1519 ,rsText
1520 ,nImage
1521 ,nSelectedImage
1522 ,pData
1523 );
1524 } // end of wxTreeCtrl::InsertItem
1525
1526 wxTreeItemId wxTreeCtrl::InsertItem (
1527 const wxTreeItemId& rParent
1528 , size_t nIndex
1529 , const wxString& rsText
1530 , int nImage
1531 , int nSelectedImage
1532 , wxTreeItemData* pData
1533 )
1534 {
1535 return DoInsertItem( rParent
1536 ,wxTreeItemId((long)nIndex)
1537 ,rsText
1538 ,nImage
1539 ,nSelectedImage
1540 ,pData
1541 );
1542 } // end of wxTreeCtrl::InsertItem
1543
1544 wxTreeItemId wxTreeCtrl::AppendItem (
1545 const wxTreeItemId& rParent
1546 , const wxString& rsText
1547 , int nImage
1548 , int nSelectedImage
1549 , wxTreeItemData* pData
1550 )
1551 {
1552 return DoInsertItem( rParent
1553 ,wxTreeItemId((long)-1)
1554 ,rsText
1555 ,nImage
1556 ,nSelectedImage
1557 ,pData
1558 );
1559 } // end of wxTreeCtrl::AppendItem
1560
1561 void wxTreeCtrl::Delete (
1562 const wxTreeItemId& rItem
1563 )
1564 {
1565 //
1566 // OS/2 does not generate DELETEITEM events so do it here
1567 //
1568 wxEventType vEventType = wxEVT_NULL;
1569 wxTreeEvent vEvent( wxEVT_NULL
1570 ,m_windowId
1571 );
1572 PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
1573 ,rItem.m_pItem
1574 );
1575 vEvent.SetEventObject(this);
1576 ::WinSendMsg( GetHWND()
1577 ,CM_REMOVERECORD
1578 ,MPFROMP(pRecord)
1579 ,(MPARAM)(CMA_FREE | CMA_INVALIDATE)
1580 );
1581 vEvent.m_item = rItem.m_pItem;
1582 if (m_bHasAnyAttr)
1583 {
1584 delete (wxTreeItemAttr *)m_vAttrs.Delete((long)rItem.m_pItem);
1585 }
1586 vEvent.SetEventType(vEventType);
1587 HandleWindowEvent(vEvent);
1588 } // end of wxTreeCtrl::Delete
1589
1590 // delete all children (but don't delete the item itself)
1591 void wxTreeCtrl::DeleteChildren (
1592 const wxTreeItemId& rItem
1593 )
1594 {
1595 long lCookie;
1596 wxArrayLong aChildren;
1597 wxTreeItemId vChild = GetFirstChild( rItem
1598 ,lCookie
1599 );
1600
1601 while (vChild.IsOk())
1602 {
1603 aChildren.Add((long)(WXHTREEITEM)vChild);
1604 vChild = GetNextChild( rItem
1605 ,lCookie
1606 );
1607 }
1608
1609 size_t nCount = aChildren.Count();
1610
1611 for (size_t n = 0; n < nCount; n++)
1612 {
1613 Delete(aChildren[n]);
1614 }
1615 } // end of wxTreeCtrl::DeleteChildren
1616
1617 void wxTreeCtrl::DeleteAllItems ()
1618 {
1619 ::WinSendMsg( GetHWND()
1620 ,CM_REMOVERECORD
1621 ,NULL // Remove all
1622 ,(MPARAM)(CMA_FREE | CMA_INVALIDATE)
1623 );
1624 } // end of wxTreeCtrl::DeleteAllItems
1625
1626 void wxTreeCtrl::DoExpand (
1627 const wxTreeItemId& rItem
1628 , int nFlag
1629 )
1630 {
1631 PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
1632 ,rItem.m_pItem
1633 );
1634 switch(nFlag)
1635 {
1636 case wxTREE_EXPAND_EXPAND:
1637 ::WinSendMsg( GetHWND()
1638 ,CM_EXPANDTREE
1639 ,MPFROMP(pRecord)
1640 ,NULL
1641 );
1642 break;
1643
1644 case wxTREE_EXPAND_COLLAPSE:
1645 ::WinSendMsg( GetHWND()
1646 ,CM_COLLAPSETREE
1647 ,MPFROMP(pRecord)
1648 ,NULL
1649 );
1650 break;
1651
1652 case wxTREE_EXPAND_COLLAPSE_RESET:
1653 ::WinSendMsg( GetHWND()
1654 ,CM_COLLAPSETREE
1655 ,MPFROMP(pRecord)
1656 ,NULL
1657 );
1658 DeleteChildren(rItem);
1659 break;
1660
1661 case wxTREE_EXPAND_TOGGLE:
1662 if (pRecord->m_vRecord.flRecordAttr & CRA_COLLAPSED)
1663 ::WinSendMsg( GetHWND()
1664 ,CM_EXPANDTREE
1665 ,MPFROMP(pRecord)
1666 ,NULL
1667 );
1668 else if (pRecord->m_vRecord.flRecordAttr & CRA_EXPANDED)
1669 ::WinSendMsg( GetHWND()
1670 ,CM_COLLAPSETREE
1671 ,MPFROMP(pRecord)
1672 ,NULL
1673 );
1674 break;
1675
1676 }
1677 } // end of wxTreeCtrl::DoExpand
1678
1679 void wxTreeCtrl::Expand (
1680 const wxTreeItemId& rItem
1681 )
1682 {
1683 DoExpand( rItem
1684 ,wxTREE_EXPAND_EXPAND
1685 );
1686 } // end of wxTreeCtrl::Expand
1687
1688 void wxTreeCtrl::Collapse (
1689 const wxTreeItemId& rItem
1690 )
1691 {
1692 DoExpand( rItem
1693 ,wxTREE_EXPAND_COLLAPSE
1694 );
1695 } // end of wxTreeCtrl::Collapse
1696
1697 void wxTreeCtrl::CollapseAndReset (
1698 const wxTreeItemId& rItem
1699 )
1700 {
1701 DoExpand( rItem
1702 ,wxTREE_EXPAND_COLLAPSE_RESET
1703 );
1704 } // end of wxTreeCtrl::CollapseAndReset
1705
1706 void wxTreeCtrl::Toggle (
1707 const wxTreeItemId& rItem
1708 )
1709 {
1710 DoExpand( rItem
1711 ,wxTREE_EXPAND_TOGGLE
1712 );
1713 } // end of wxTreeCtrl::Toggle
1714
1715 void wxTreeCtrl::Unselect ()
1716 {
1717 wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE),
1718 wxT("doesn't make sense, may be you want UnselectAll()?") );
1719
1720 //
1721 // Just remove the selection
1722 //
1723 SelectItem(wxTreeItemId((long)0));
1724 } // end of wxTreeCtrl::Unselect
1725
1726 void wxTreeCtrl::UnselectAll ()
1727 {
1728 if (m_windowStyle & wxTR_MULTIPLE)
1729 {
1730 wxArrayTreeItemIds aSelections;
1731 size_t nCount = GetSelections(aSelections);
1732
1733 for (size_t n = 0; n < nCount; n++)
1734 {
1735 SetItemCheck( aSelections[n]
1736 ,false
1737 );
1738 }
1739 }
1740 else
1741 {
1742 //
1743 // Just remove the selection
1744 //
1745 Unselect();
1746 }
1747 } // end of wxTreeCtrl::UnselectAll
1748
1749 void wxTreeCtrl::SelectItem (
1750 const wxTreeItemId& rItem
1751 )
1752 {
1753 SetItemCheck(rItem);
1754 } // end of wxTreeCtrl::SelectItem
1755
1756 void wxTreeCtrl::EnsureVisible (
1757 const wxTreeItemId& rItem
1758 )
1759 {
1760 wxTreeViewItem vTvItem(rItem);
1761
1762 DoGetItem(&vTvItem);
1763 if (!::WinSendMsg( GetHWND()
1764 ,CM_INVALIDATERECORD
1765 ,MPFROMP(&vTvItem)
1766 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1767 ));
1768 } // end of wxTreeCtrl::EnsureVisible
1769
1770 void wxTreeCtrl::ScrollTo (
1771 const wxTreeItemId& rItem
1772 )
1773 {
1774 wxTreeViewItem vTvItem(rItem);
1775
1776 DoGetItem(&vTvItem);
1777 if (!::WinSendMsg( GetHWND()
1778 ,CM_INVALIDATERECORD
1779 ,MPFROMP(&vTvItem)
1780 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1781 ));
1782 }
1783
1784 wxTextCtrl* wxTreeCtrl::EditLabel (
1785 const wxTreeItemId& rItem
1786 , wxClassInfo* WXUNUSED(pTextControlClass)
1787 )
1788 {
1789 CNREDITDATA vEdit;
1790 PMYRECORD pRecord = FindOS2TreeRecordByID( GetHWND()
1791 ,rItem.m_pItem
1792 );
1793
1794 vEdit.cb = sizeof(CNREDITDATA);
1795 vEdit.hwndCnr = GetHWND();
1796 vEdit.pRecord = &pRecord->m_vRecord;
1797 vEdit.pFieldInfo = NULL;
1798 vEdit.ppszText = NULL;
1799 vEdit.cbText = 0;
1800 vEdit.id = 0;
1801
1802 ::WinSendMsg( GetHWND()
1803 ,CM_OPENEDIT
1804 ,MPFROMP(&vEdit)
1805 ,(MPARAM)0
1806 );
1807 return NULL;
1808 } // end of wxTreeCtrl::EditLabel
1809
1810 // End label editing, optionally cancelling the edit
1811 void wxTreeCtrl::EndEditLabel (
1812 const wxTreeItemId& WXUNUSED(rItem)
1813 , bool WXUNUSED(bDiscardChanges)
1814 )
1815 {
1816 ::WinSendMsg( GetHWND()
1817 ,CM_CLOSEEDIT
1818 ,(MPARAM)0
1819 ,(MPARAM)0
1820 );
1821 } // end of wxTreeCtrl::EndEditLabel
1822
1823 wxTreeItemId wxTreeCtrl::HitTest (
1824 const wxPoint& rPoint
1825 , int& WXUNUSED(rFlags)
1826 )
1827 {
1828 PMYRECORD pRecord = NULL;
1829 QUERYRECFROMRECT vQueryRect;
1830 RECTL vRect;
1831 long lHeight;
1832
1833 //
1834 // Get height for OS/2 point conversion
1835 //
1836 ::WinSendMsg( GetHWND()
1837 ,CM_QUERYVIEWPORTRECT
1838 ,MPFROMP(&vRect)
1839 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
1840 );
1841 lHeight = vRect.yTop - vRect.yBottom;
1842
1843 //
1844 // For now just try and get a record in the general vicinity and forget
1845 // the flag
1846 //
1847 vRect.xLeft = rPoint.x - 2;
1848 vRect.xRight = rPoint.x + 2;
1849 vRect.yTop = (lHeight - rPoint.y) + 2;
1850 vRect.yBottom = (lHeight - rPoint.y) - 2;
1851
1852 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
1853 vQueryRect.rect = vRect;
1854 vQueryRect.fsSearch = CMA_PARTIAL;
1855
1856 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1857 ,CM_QUERYRECORDFROMRECT
1858 ,(MPARAM)CMA_FIRST
1859 ,MPFROMP(&vQueryRect)
1860 );
1861
1862 if (!pRecord)
1863 return -1L;
1864 return wxTreeItemId((long)pRecord->m_ulItemId);
1865 } // end of wxTreeCtrl::HitTest
1866
1867 bool wxTreeCtrl::GetBoundingRect (
1868 const wxTreeItemId& rItem
1869 , wxRect& rRect
1870 , bool bTextOnly
1871 ) const
1872 {
1873 RECTL vRectRecord;
1874 PMYRECORD pRecord = FindOS2TreeRecordByID ( GetHWND()
1875 ,rItem.m_pItem
1876 );
1877 QUERYRECORDRECT vQuery;
1878
1879 vQuery.cb = sizeof(QUERYRECORDRECT);
1880 vQuery.pRecord = (PRECORDCORE)pRecord;
1881 vQuery.fRightSplitWindow = FALSE;
1882 if (bTextOnly)
1883 vQuery.fsExtent = CMA_TEXT;
1884 else
1885 vQuery.fsExtent = CMA_TREEICON | CMA_TEXT;
1886
1887 if (!::WinSendMsg( GetHWND()
1888 ,CM_QUERYRECORDRECT
1889 ,MPFROMP(&vRectRecord)
1890 ,MPFROMP(&vQuery)
1891 ))
1892 return false;
1893 rRect.SetLeft(vRectRecord.xLeft);
1894 rRect.SetTop(vRectRecord.yTop);
1895 rRect.SetRight(vRectRecord.xRight);
1896 rRect.SetBottom(vRectRecord.yBottom);
1897 return true;
1898 } // end of wxTreeCtrl::GetBoundingRect
1899
1900 // ----------------------------------------------------------------------------
1901 // sorting stuff
1902 // ----------------------------------------------------------------------------
1903
1904 SHORT EXPENTRY InternalDataCompareTreeFunc (
1905 PMYRECORD p1
1906 , PMYRECORD p2
1907 , PVOID pStorage
1908 )
1909 {
1910 wxCHECK_MSG( p1 && p2, 0,
1911 wxT("sorting tree without data doesn't make sense") );
1912
1913 wxTreeCtrl* pTree = (wxTreeCtrl*)pStorage;
1914
1915 return pTree->OnCompareItems( p1->m_ulItemId
1916 ,p2->m_ulItemId
1917 );
1918 } // end of wxTreeSortHelper::Compare
1919
1920 int wxTreeCtrl::OnCompareItems (
1921 const wxTreeItemId& rItem1
1922 , const wxTreeItemId& rItem2
1923 )
1924 {
1925 return wxStrcmp( GetItemText(rItem1)
1926 ,GetItemText(rItem2)
1927 );
1928 } // end of wxTreeCtrl::OnCompareItems
1929
1930 void wxTreeCtrl::SortChildren (
1931 const wxTreeItemId& rItem
1932 )
1933 {
1934 ::WinSendMsg( GetHWND()
1935 ,CM_SORTRECORD
1936 ,(PFN)InternalDataCompareTreeFunc
1937 ,NULL
1938 );
1939 } // end of wxTreeCtrl::SortChildren
1940
1941 // ----------------------------------------------------------------------------
1942 // implementation
1943 // ----------------------------------------------------------------------------
1944
1945 bool wxTreeCtrl::OS2Command (
1946 WXUINT uCmd
1947 , WXWORD wId
1948 )
1949 {
1950 if (uCmd == CN_ENDEDIT)
1951 {
1952 wxCommandEvent vEvent( wxEVT_TEXT
1953 ,wId
1954 );
1955
1956 vEvent.SetEventObject( this );
1957 ProcessCommand(vEvent);
1958 return true;
1959 }
1960 else if (uCmd == CN_KILLFOCUS)
1961 {
1962 wxCommandEvent vEvent( wxEVT_KILL_FOCUS
1963 ,wId
1964 );
1965 vEvent.SetEventObject( this );
1966 ProcessCommand(vEvent);
1967 return true;
1968 }
1969 else
1970 return false;
1971 } // end of wxTreeCtrl::OS2Command
1972
1973 //
1974 // TODO: Fully implement direct manipulation when I figure it out
1975 //
1976 MRESULT wxTreeCtrl::OS2WindowProc (
1977 WXUINT uMsg
1978 , WXWPARAM wParam
1979 , WXLPARAM lParam
1980 )
1981 {
1982 bool bProcessed = false;
1983 MRESULT mRc = 0;
1984 wxTreeEvent vEvent( wxEVT_NULL
1985 ,m_windowId
1986 );
1987 wxEventType vEventType = wxEVT_NULL;
1988 PCNRDRAGINIT pDragInit = NULL;
1989 PCNREDITDATA pEditData = NULL;
1990 PNOTIFYRECORDENTER pNotifyEnter = NULL;
1991
1992 vEvent.SetEventObject(this);
1993 switch (uMsg)
1994 {
1995 case WM_CONTROL:
1996 switch(SHORT2FROMMP(wParam))
1997 {
1998 case CN_INITDRAG:
1999 pDragInit = (PCNRDRAGINIT)lParam;
2000 if (pDragInit)
2001 {
2002 PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
2003
2004 vEventType = wxEVT_TREE_BEGIN_DRAG;
2005 vEvent.m_item = pRecord->m_ulItemId;
2006 vEvent.m_pointDrag.x = pDragInit->x;
2007 vEvent.m_pointDrag.y = pDragInit->y;
2008 }
2009 break;
2010
2011 case CN_BEGINEDIT:
2012 pEditData = (PCNREDITDATA)lParam;
2013 if (pEditData)
2014 {
2015 PMYRECORD pRecord = (PMYRECORD)pEditData->pRecord;
2016
2017 vEventType = wxEVT_TREE_BEGIN_LABEL_EDIT;
2018 vEvent.m_item = pRecord->m_ulItemId;
2019 vEvent.m_label = pRecord->m_vRecord.pszTree;
2020 vEvent.m_editCancelled = false;
2021 }
2022 break;
2023
2024 case CN_ENDEDIT:
2025 pEditData = (PCNREDITDATA)lParam;
2026 if (pEditData)
2027 {
2028 PMYRECORD pRecord = (PMYRECORD)pEditData->pRecord;
2029
2030 vEventType = wxEVT_TREE_END_LABEL_EDIT;
2031 vEvent.m_item = pRecord->m_ulItemId;
2032 vEvent.m_label = pRecord->m_vRecord.pszTree;
2033 if (pRecord->m_vRecord.pszTree == NULL)
2034 {
2035 vEvent.m_editCancelled = true;
2036 }
2037 else
2038 {
2039 vEvent.m_editCancelled = false;
2040 }
2041 }
2042 break;
2043
2044 case CN_EXPANDTREE:
2045 {
2046 PMYRECORD pRecord = (PMYRECORD)lParam;
2047
2048 vEventType = gs_expandEvents[IDX_EXPAND][IDX_DONE];
2049 vEvent.m_item = pRecord->m_ulItemId;
2050 }
2051 break;
2052 }
2053 vEvent.SetEventType(vEventType);
2054 bProcessed = HandleWindowEvent(vEvent);
2055 break;
2056 }
2057 if (!bProcessed)
2058 mRc = wxControl::OS2WindowProc( uMsg
2059 ,wParam
2060 ,lParam
2061 );
2062 return mRc;
2063 } // end of wxTreeCtrl::OS2WindowProc
2064
2065 #endif // wxUSE_TREECTRL