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