1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/listctrl.cpp
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
21 #pragma implementation "listctrl.h"
22 #pragma implementation "listctrlbase.h"
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
38 #include "wx/settings.h"
41 #include "wx/textctrl.h"
42 #include "wx/imaglist.h"
43 #include "wx/listctrl.h"
44 #include "wx/dcclient.h"
46 #include "wx/os2/private.h"
49 // FIELDOFFSET in DETAIL view as defined in the OS2TK45 simply doesn't work
50 // We use this, which does!
53 #define FIELDOFFSET(type, field) ((ULONG)&(((type *)0)->field))
55 // ----------------------------------------------------------------------------
56 // private helper classes
57 // ----------------------------------------------------------------------------
59 /////////////////////////////////////////////////////////////////////////////
61 // Under OS/2 we have to use our own RECORDCORE based struct if we have
62 // user data to store in a PM Container Control (and CListCtrl is a PM
63 // Container in ICON, NAME, TEXT or DETAILview). m_ulUserData is a four
64 // byte value containing a pointer to our CListIntemInternalData class
66 /////////////////////////////////////////////////////////////////////////////
67 typedef struct _MYRECORD
70 unsigned long m_ulItemId
;
71 unsigned long m_ulUserData
;
72 } MYRECORD
, *PMYRECORD
;
74 /////////////////////////////////////////////////////////////////////////////
75 // CLASS CListItemInternalData
78 // The MSW version had problems with SetTextColour() et al as the
79 // CListItemAttr's were stored keyed on the item index. If a item was
80 // inserted anywhere but the end of the list the the text attributes
81 // (colour etc) for the following items were out of sync.
84 // Under MSW the only way to associate data with a
85 // List item independant of its position in the list is to store a pointer
86 // to it in its lParam attribute. However user programs are already using
87 // this (via the SetItemData() GetItemData() calls).
89 // However what we can do is store a pointer to a structure which contains
90 // the attributes we want *and* a lParam for the users data, e.g.
92 // class CListItemInternalData
95 // GuiAdvCtrl_CListItemAttr* pAttr;
96 // long lParam; // user data
99 // To conserve memory, a CListItemInternalData is only allocated for a
100 // LV_ITEM if text attributes or user data(lparam) are being set.
102 // For OS/2, the lParam value points to whatever actual data we have
103 /////////////////////////////////////////////////////////////////////////////
104 class CListItemInternalData
108 CListItemInternalData(): m_pAttr(NULL
)
112 ~CListItemInternalData()
118 wxListItemAttr
* m_pAttr
;
119 WXLPARAM m_lParam
; // user data
120 PMYRECORD m_pMyRecord
; // so we can set the m_ulUserData to 0 when this is deleted
121 }; // end of CLASS CListItemInternalData
123 /////////////////////////////////////////////////////////////////////////////
124 // STRUCT SInternalDataSort
128 // fn is a function which takes 3 long arguments: item1, item2, data.
129 // item1 is the long data associated with a first item (NOT the index).
130 // item2 is the long data associated with a second item (NOT the index).
131 // data is the same value as passed to SortItems.
133 // The return value is a negative number if the first item should precede the
134 // second item, a positive number of the second item should precede the first,
135 // or zero if the two items are equivalent.
137 // data is arbitrary data to be passed to the sort function.
139 // Internal structures for proxying the user compare function
140 // so that we can pass it the *real* user data
141 /////////////////////////////////////////////////////////////////////////////
142 typedef struct internalDataSort
144 wxListCtrlCompare m_fnUser
;
146 } SInternalDataSort
; // end of STRUCT SInternalDataSort
148 // ----------------------------------------------------------------------------
149 // private helper functions
150 // ----------------------------------------------------------------------------
152 /////////////////////////////////////////////////////////////////////////////
154 // FindOS2ListFieldByColNum
156 // There is no way, under OS/2 to get a field in a container by index,
157 // directly, so you must get the first one, then cycle through the list
158 // until you get to where you want to be.
161 // hWnd -- window handle of container to search
162 // lIndex -- index to set
165 // pointer to the FIELDINFO struct at the index in the container record
167 /////////////////////////////////////////////////////////////////////////////
168 PFIELDINFO
FindOS2ListFieldByColNum (
173 PFIELDINFO pFieldInfo
= NULL
;
177 if (!::WinSendMsg( hWnd
180 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
183 for (i
= 0; i
< vCnrInfo
.cFields
; i
++)
186 pFieldInfo
= (PFIELDINFO
)PVOIDFROMMR(::WinSendMsg( hWnd
187 ,CM_QUERYDETAILFIELDINFO
192 pFieldInfo
= (PFIELDINFO
)PVOIDFROMMR(::WinSendMsg( hWnd
193 ,CM_QUERYDETAILFIELDINFO
199 if (i
== (ULONG
)lIndex
)
205 } // end of FindOS2ListFieldByColNum
207 /////////////////////////////////////////////////////////////////////////////
209 // FindOS2ListRecordByID
211 // There is no way, under OS/2 to get a record in a container by index,
212 // directly, so you must get the first one, then cycle through the list
213 // until you get to where you want to be.
216 // hWnd -- window handle of container to search
217 // lItemId -- index to set
220 // pointer to the internal RECORDCORE struct at the index in the container
222 /////////////////////////////////////////////////////////////////////////////
223 PMYRECORD
FindOS2ListRecordByID (
228 PMYRECORD pRecord
= NULL
;
232 if (!::WinSendMsg( hWnd
235 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
238 for (i
= 0; i
< vCnrInfo
.cRecords
; i
++)
241 pRecord
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( hWnd
244 ,MPFROM2SHORT(CMA_FIRST
, CMA_ITEMORDER
)
247 pRecord
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( hWnd
250 ,MPFROM2SHORT(CMA_NEXT
, CMA_ITEMORDER
)
254 if (pRecord
->m_ulItemId
== (ULONG
)lItemId
)
258 } // end of FindOS2ListRecordByID
260 /////////////////////////////////////////////////////////////////////////////
264 // Since OS/2 does not keep native record id's but wx insists on inserting
265 // and selecting via ID's, when we insert a record in the middle we need
266 // to bump the id's of each record after the one we just inserted.
269 // hWnd -- window handle of container to search
270 // pRecord -- record after which we starting bumping id's
275 /////////////////////////////////////////////////////////////////////////////
283 pRecord
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( hWnd
286 ,MPFROM2SHORT(CMA_NEXT
, CMA_ITEMORDER
)
289 pRecord
->m_ulItemId
++;
291 } // end of BumpRecordIds
293 /////////////////////////////////////////////////////////////////////////////
297 // Get the internal data given a handle and an id
300 // hWnd -- window handle to the control in which item is located
301 // lItemId -- ID to get
304 // pointer to the internal data
307 // Under OS/2 PM a container item cannot be obtained via a simple index or
308 // id retrieval. We have to walk the record list if we are looking for
309 // a record at a specific index location
310 /////////////////////////////////////////////////////////////////////////////
311 CListItemInternalData
* GetInternalData (
316 PMYRECORD pRecord
= FindOS2ListRecordByID( hWnd
320 // Internal user data is stored AFTER the last field of the RECORDCORE
324 return((CListItemInternalData
*)(pRecord
->m_ulUserData
));
325 } // end of GetInternalData
327 /////////////////////////////////////////////////////////////////////////////
331 // Get the internal data given a pointer to a list control and an id
334 // pCtl -- pointer to control inwhich item is located
335 // lItemId -- ID to get
338 // pointer to the internal data
340 /////////////////////////////////////////////////////////////////////////////
341 CListItemInternalData
* GetInternalData (
346 return(GetInternalData( (HWND
)pCtl
->GetHWND()
349 } // end of GetInternalData
351 /////////////////////////////////////////////////////////////////////////////
353 // DeleteInternalData
355 // Delete the internal data for a record
358 // pCtl -- pointer to the list control containing the record
359 // lItemId -- the record index to delete the internal data from
362 // pointer to the internal data attribute
364 /////////////////////////////////////////////////////////////////////////////
365 void DeleteInternalData (
370 CListItemInternalData
* pData
= GetInternalData( pCtl
375 if (pData
->m_pMyRecord
)
376 pData
->m_pMyRecord
->m_ulUserData
= 0;
379 } // end of DeleteInternalData
381 // #pragma page "GetInternalDataAttr"
382 /////////////////////////////////////////////////////////////////////////////
384 // GetInternalDataAttr
386 // Get the internal data item attribute given a pointer to a list control
390 // pCtl -- pointer to control to set
391 // lItemId -- ID to set
394 // pointer to the internal data attribute
396 /////////////////////////////////////////////////////////////////////////////
397 wxListItemAttr
* GetInternalDataAttr (
402 CListItemInternalData
* pData
= GetInternalData( pCtl
407 return(pData
->m_pAttr
);
410 } // end of GetInternalDataAttr
412 /////////////////////////////////////////////////////////////////////////////
414 // InternalDataCompareFunc
416 // This is compare function we pass to PM. It wraps the real compare
417 // function in SInternalDataSort
420 // p1 -- is the first record structure to compare
421 // p2 -- is the second record structure to compare
422 // lStorage -- is the same value as passed to SortItems.
425 // pointer to the internal data attribute
427 /////////////////////////////////////////////////////////////////////////////
428 SHORT EXPENTRY
InternalDataCompareFunc (
434 SInternalDataSort
* pInternalData
= (SInternalDataSort
*)pStorage
;
435 CListItemInternalData
* pData1
= (CListItemInternalData
*)p1
->m_ulUserData
;
436 CListItemInternalData
* pData2
= (CListItemInternalData
*)p2
->m_ulUserData
;
437 long lD1
= (pData1
== NULL
? 0 : (long)pData1
->m_lParam
);
438 long lD2
= (pData2
== NULL
? 0 : (long)pData2
->m_lParam
);
440 return(pInternalData
->m_fnUser( lD1
442 ,pInternalData
->m_lData
444 } // end of InternalDataCompareFunc
446 /////////////////////////////////////////////////////////////////////////////
448 // ConvertFromOS2ListItem
450 // Convert from an internal PM List item to a Toolkit List item
453 // hWndListCtrl -- the control's windows handle
454 // rInfo -- the library list control to convert to
455 // pRecord -- the OS list control to convert from
460 /////////////////////////////////////////////////////////////////////////////
461 void ConvertFromOS2ListItem (
467 CListItemInternalData
* pInternaldata
= (CListItemInternalData
*)pRecord
->m_ulUserData
;
468 bool bNeedText
= FALSE
;
471 rInfo
.SetData(pInternaldata
->m_lParam
);
475 rInfo
.SetStateMask(0);
476 rInfo
.SetId((long)pRecord
->m_ulItemId
);
477 if (hWndListCtrl
!= 0)
479 pRecord
= FindOS2ListRecordByID( hWndListCtrl
485 // The wxListItem class is really set up to handle the WIN32 list item
486 // and OS/2 are not as complicated. Just set both state members to the
487 // same thing under OS/2
489 if (pRecord
->m_vRecord
.flRecordAttr
& CRA_DROPONABLE
)
491 rInfo
.SetStateMask(rInfo
.m_stateMask
| wxLIST_STATE_DROPHILITED
);
492 rInfo
.SetState(rInfo
.m_state
| wxLIST_STATE_DROPHILITED
);
494 if (pRecord
->m_vRecord
.flRecordAttr
& CRA_SELECTED
)
496 rInfo
.SetStateMask(rInfo
.m_stateMask
| wxLIST_STATE_SELECTED
);
497 rInfo
.SetState(rInfo
.m_state
| wxLIST_STATE_SELECTED
);
499 if (pRecord
->m_vRecord
.flRecordAttr
& CRA_DISABLED
)
501 rInfo
.SetStateMask(rInfo
.m_stateMask
| wxLIST_STATE_DISABLED
);
502 rInfo
.SetState(rInfo
.m_state
| wxLIST_STATE_DISABLED
);
504 if (pRecord
->m_vRecord
.flRecordAttr
& CRA_FILTERED
)
506 rInfo
.SetStateMask(rInfo
.m_stateMask
| wxLIST_STATE_FILTERED
);
507 rInfo
.SetState(rInfo
.m_state
| wxLIST_STATE_FILTERED
);
509 if (pRecord
->m_vRecord
.flRecordAttr
& CRA_INUSE
)
511 rInfo
.SetStateMask(rInfo
.m_stateMask
| wxLIST_STATE_INUSE
);
512 rInfo
.SetState(rInfo
.m_state
| wxLIST_STATE_INUSE
);
514 if (pRecord
->m_vRecord
.flRecordAttr
& CRA_PICKED
)
516 rInfo
.SetStateMask(rInfo
.m_stateMask
| wxLIST_STATE_PICKED
);
517 rInfo
.SetState(rInfo
.m_state
| wxLIST_STATE_PICKED
);
519 if (pRecord
->m_vRecord
.flRecordAttr
& CRA_SOURCE
)
521 rInfo
.SetStateMask(rInfo
.m_stateMask
| wxLIST_STATE_SOURCE
);
522 rInfo
.SetState(rInfo
.m_state
| wxLIST_STATE_SOURCE
);
525 if (pRecord
->m_vRecord
.pszText
!= (PSZ
)NULL
)
527 rInfo
.SetMask(rInfo
.GetMask() | wxLIST_MASK_TEXT
);
528 rInfo
.SetText(pRecord
->m_vRecord
.pszText
);
530 if (pRecord
->m_vRecord
.pszIcon
!= (PSZ
)NULL
||
531 pRecord
->m_vRecord
.pszName
!= (PSZ
)NULL
)
533 rInfo
.SetMask(rInfo
.GetMask() | wxLIST_MASK_IMAGE
);
534 rInfo
.SetImage(pRecord
->m_vRecord
.hptrIcon
);
536 if (pRecord
->m_ulUserData
)
537 rInfo
.SetMask(rInfo
.GetMask() | wxLIST_MASK_DATA
);
538 } // end of ConvertFromOS2ListItem
540 /////////////////////////////////////////////////////////////////////////////
544 // Convert from an library states to OS states
547 // lState -- the state
548 // pRecord -- the OS list control to use
553 /////////////////////////////////////////////////////////////////////////////
554 void ConvertToOS2Flags (
559 if (lState
& wxLIST_STATE_DROPHILITED
)
560 pRecord
->m_vRecord
.flRecordAttr
|= CRA_DROPONABLE
;
561 if (lState
& wxLIST_STATE_SELECTED
)
562 pRecord
->m_vRecord
.flRecordAttr
|= CRA_SELECTED
;
563 if (lState
& wxLIST_STATE_DISABLED
)
564 pRecord
->m_vRecord
.flRecordAttr
|= CRA_DISABLED
;
565 if (lState
& wxLIST_STATE_FILTERED
)
566 pRecord
->m_vRecord
.flRecordAttr
|= CRA_FILTERED
;
567 if (lState
& wxLIST_STATE_INUSE
)
568 pRecord
->m_vRecord
.flRecordAttr
|= CRA_INUSE
;
569 if (lState
& wxLIST_STATE_PICKED
)
570 pRecord
->m_vRecord
.flRecordAttr
|= CRA_PICKED
;
571 if (lState
& wxLIST_STATE_SOURCE
)
572 pRecord
->m_vRecord
.flRecordAttr
|= CRA_SOURCE
;
573 } // end of ConvertToOS2Flags
575 /////////////////////////////////////////////////////////////////////////////
577 // ConvertToOS2ListItem
579 // Convert from a library List item to an internal OS2 List item. We set
580 // only the fields we need to set. Some of them are set by the API when
581 // they are added to the container.
584 // pCtrl -- the control to use
585 // rInfo -- the item to convert
586 // pRecord -- the OS list control to use, should be zeroed out
591 /////////////////////////////////////////////////////////////////////////////
592 void ConvertToOS2ListItem (
593 const wxListCtrl
* pCtrl
594 , const wxListItem
& rInfo
598 pRecord
->m_ulItemId
= (ULONG
)rInfo
.GetId();
599 if (rInfo
.GetMask() & wxLIST_MASK_STATE
)
601 ConvertToOS2Flags( rInfo
.m_state
605 if (pCtrl
->GetWindowStyleFlag() & wxLC_ICON
||
606 pCtrl
->GetWindowStyleFlag() & wxLC_SMALL_ICON
)
608 pRecord
->m_vRecord
.pszIcon
= (char*)rInfo
.GetText().c_str();
610 if (pCtrl
->GetWindowStyleFlag() & wxLC_LIST
) // PM TEXT view
612 pRecord
->m_vRecord
.pszText
= (char*)rInfo
.GetText().c_str();
614 if (rInfo
.GetMask() & wxLIST_MASK_IMAGE
)
616 pRecord
->m_vRecord
.hptrIcon
= (HPOINTER
)rInfo
.GetImage();
617 pRecord
->m_vRecord
.hptrMiniIcon
= (HPOINTER
)rInfo
.m_miniImage
;
619 } // end of ConvertToOS2ListItem
621 /////////////////////////////////////////////////////////////////////////////
623 // ConvertToOS2ListCol
625 // Convert from a library List column to an internal PM List column
628 // lCol -- the columnd to convert
629 // rItem -- the item to convert
630 // pField -- the OS list column to use
635 /////////////////////////////////////////////////////////////////////////////
636 void ConvertToOS2ListCol (
638 , const wxListItem
& rItem
642 memset(pField
, '\0', sizeof(FIELDINFO
));
643 pField
->cb
= sizeof(FIELDINFO
);
644 if (rItem
.GetMask() & wxLIST_MASK_TEXT
)
646 pField
->flData
|= CFA_STRING
;
647 pField
->pUserData
= (void *)rItem
.GetText().c_str();
649 if (rItem
.GetMask() & wxLIST_MASK_FORMAT
)
651 if (rItem
.m_format
== wxLIST_FORMAT_LEFT
)
652 pField
->flData
|= CFA_LEFT
;
653 else if (rItem
.m_format
== wxLIST_FORMAT_RIGHT
)
654 pField
->flData
|= CFA_RIGHT
;
655 else if (rItem
.m_format
== wxLIST_FORMAT_CENTRE
)
656 pField
->flData
|= CFA_CENTER
;
658 if (rItem
.GetMask() & wxLIST_MASK_WIDTH
)
660 if (!(rItem
.GetWidth() == wxLIST_AUTOSIZE
||
661 rItem
.GetWidth() == wxLIST_AUTOSIZE_USEHEADER
))
662 pField
->cxWidth
= rItem
.GetWidth();
663 // else: OS/2 automatically sets the width if created with the approppriate style
665 } // end of ConvertToOS2ListCol
667 // ----------------------------------------------------------------------------
669 // ----------------------------------------------------------------------------
671 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG
)
672 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG
)
673 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
)
674 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT
)
675 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM
)
676 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
)
677 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO
)
678 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO
)
679 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED
)
680 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED
)
681 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN
)
682 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM
)
683 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK
)
684 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
)
685 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
)
686 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING
)
687 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG
)
688 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
)
689 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
)
690 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED
)
691 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED
)
692 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT
)
694 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
)
695 IMPLEMENT_DYNAMIC_CLASS(wxListView
, wxListCtrl
)
696 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
)
698 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
)
700 BEGIN_EVENT_TABLE(wxListCtrl
, wxControl
)
701 EVT_PAINT(wxListCtrl::OnPaint
)
704 // ============================================================================
706 // ============================================================================
708 // ----------------------------------------------------------------------------
709 // wxListCtrl construction
710 // ----------------------------------------------------------------------------
712 void wxListCtrl::Init ()
714 m_pImageListNormal
= NULL
;
715 m_pImageListSmall
= NULL
;
716 m_pImageListState
= NULL
;
717 m_bOwnsImageListNormal
= FALSE
;
718 m_bOwnsImageListSmall
= FALSE
;
719 m_bOwnsImageListState
= FALSE
;
723 m_bAnyInternalData
= FALSE
;
724 m_bHasAnyAttr
= FALSE
;
725 } // end of wxListCtrl::Init
727 bool wxListCtrl::Create (
730 , const wxPoint
& rPos
731 , const wxSize
& rSize
733 , const wxValidator
& rValidator
734 , const wxString
& rsName
739 int nWidth
= rSize
.x
;
740 int nHeight
= rSize
.y
;
743 SetValidator(rValidator
);
744 #endif // wxUSE_VALIDATORS
747 SetWindowStyleFlag(lStyle
);
758 m_windowId
= (vId
== -1) ? NewControlId() : vId
;
760 long lSstyle
= WS_VISIBLE
| WS_TABSTOP
;
762 if (GetWindowStyleFlag() & wxCLIP_SIBLINGS
)
763 lSstyle
|= WS_CLIPSIBLINGS
;
764 m_lBaseStyle
= lSstyle
;
765 if (!DoCreateControl( nX
772 pParent
->AddChild(this);
774 } // end of wxListCtrl::Create
776 bool wxListCtrl::DoCreateControl (
783 DWORD lWstyle
= m_lBaseStyle
;
784 long lOldStyle
= 0; // Dummy
788 lWstyle
|= ConvertToOS2Style( lOldStyle
789 ,GetWindowStyleFlag()
792 m_hWnd
= (WXHWND
)::WinCreateWindow( GetParent()->GetHWND()
797 ,GetParent()->GetHWND()
809 // Now set the display attributes of the container
811 if (!::WinSendMsg( GetHWND()
814 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
816 lWstyle
= ConvertViewToOS2Style(GetWindowStyleFlag());
817 vCnrInfo
.flWindowAttr
!= lWstyle
;
818 ::WinSendMsg( GetHWND()
821 ,(MPARAM
)CMA_FLWINDOWATTR
825 // And now set needed arrangement flags
827 lWstyle
= ConvertArrangeToOS2Style(GetWindowStyleFlag());
828 ::WinSendMsg( GetHWND()
830 ,(MPARAM
)CMA_ARRANGEGRID
833 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
));
834 SetForegroundColour(GetParent()->GetForegroundColour());
836 SetFont(*wxSMALL_FONT
);
845 } // end of wxListCtrl::DoCreateControl
847 void wxListCtrl::UpdateStyle ()
852 DWORD dwStyleNew
= ConvertToOS2Style( lDummy
853 ,GetWindowStyleFlag()
856 dwStyleNew
|= m_lBaseStyle
;
859 // Get the current window style.
861 ULONG dwStyleOld
= ::WinQueryWindowULong(GetHWND(), QWL_STYLE
);
864 // Only set the window style if the view bits have changed.
866 if (dwStyleOld
!= dwStyleNew
)
868 ::WinSetWindowULong(GetHWND(), QWL_STYLE
, dwStyleNew
);
871 } // end of wxListCtrl::UpdateStyle
873 void wxListCtrl::FreeAllInternalData ()
875 if (m_bAnyInternalData
)
877 int n
= GetItemCount();
880 for (i
= 0; i
< n
; i
++)
881 DeleteInternalData(this, (long)i
);
882 m_bAnyInternalData
= FALSE
;
884 } // end of wxListCtrl::FreeAllInternalData
886 wxListCtrl::~wxListCtrl ()
888 FreeAllInternalData();
891 m_pTextCtrl
->SetHWND(0);
892 m_pTextCtrl
->UnsubclassWin();
897 if (m_bOwnsImageListNormal
)
898 delete m_pImageListNormal
;
899 if (m_bOwnsImageListSmall
)
900 delete m_pImageListSmall
;
901 if (m_bOwnsImageListState
)
902 delete m_pImageListState
;
903 } // end of wxListCtrl::~wxListCtrl
905 // ----------------------------------------------------------------------------
906 // set/get/change style
907 // ----------------------------------------------------------------------------
909 // Add or remove a single window style
910 void wxListCtrl::SetSingleStyle (
915 long lFlag
= GetWindowStyleFlag();
918 // Get rid of conflicting styles
922 if (lStyle
& wxLC_MASK_TYPE
)
923 lFlag
= lFlag
& ~wxLC_MASK_TYPE
;
924 if (lStyle
& wxLC_MASK_ALIGN
)
925 lFlag
= lFlag
& ~wxLC_MASK_ALIGN
;
926 if (lStyle
& wxLC_MASK_SORT
)
927 lFlag
= lFlag
& ~wxLC_MASK_SORT
;
941 m_windowStyle
= lFlag
;
943 } // end of wxListCtrl::SetSingleStyle
945 // Set the whole window style
946 void wxListCtrl::SetWindowStyleFlag (
950 m_windowStyle
= lFlag
;
952 } // end of wxListCtrl::SetWindowStyleFlag
954 long wxListCtrl::ConvertToOS2Style (
962 // The only styles OS2 uses on creation are auto arrange, read only, and
963 // and selection styles. This lib does not support OS/2 MINIRECORDCORE
964 // or VERIFYPOINTER styles
966 if (lStyle
& wxLC_AUTOARRANGE
)
967 lWstyle
|= CCS_AUTOPOSITION
;
968 if (lStyle
& wxLC_SINGLE_SEL
)
969 lWstyle
|= CCS_SINGLESEL
;
971 lWstyle
|= CCS_EXTENDSEL
;
972 if (!(lStyle
& wxLC_EDIT_LABELS
))
973 lWstyle
|= CCS_READONLY
;
975 } // end of wxListCtrl::ConvertToOS2Style
977 long wxListCtrl::ConvertArrangeToOS2Style (
983 if (lStyle
& wxLC_ALIGN_LEFT
)
988 if (lStyle
& wxLC_ALIGN_TOP
)
993 } // end of wxListCtrl::ConvertArrangeToOS2Style
995 long wxListCtrl::ConvertViewToOS2Style (
999 long lWstyle
= CA_DRAWICON
; // we will only use icons
1001 if (lStyle
& wxLC_ICON
)
1005 if (lStyle
& wxLC_SMALL_ICON
)
1007 lWstyle
|= (CV_ICON
| CV_MINI
);
1009 if (lStyle
& wxLC_LIST
)
1013 if (lStyle
& wxLC_REPORT
)
1015 lWstyle
|= CV_DETAIL
;
1017 if (lStyle
& wxLC_VIRTUAL
)
1019 lWstyle
|= CA_OWNERDRAW
;
1021 if (lStyle
& wxLC_AUTOARRANGE
)
1025 if (!(lStyle
& wxLC_NO_HEADER
))
1027 lWstyle
|= CA_DETAILSVIEWTITLES
;
1030 } // end of wxListCtrl::ConvertViewToOS2Style
1032 // ----------------------------------------------------------------------------
1034 // ----------------------------------------------------------------------------
1036 // Sets the foreground, i.e. text, colour
1037 bool wxListCtrl::SetForegroundColour (
1038 const wxColour
& rCol
)
1040 ULONG ulColor
= wxColourToRGB(rCol
);
1042 if (!wxWindow::SetForegroundColour(rCol
))
1046 ::WinSetPresParam( GetHWND()
1052 } // end of wxListCtrl::SetForegroundColour
1054 // Sets the background colour
1055 bool wxListCtrl::SetBackgroundColour (
1056 const wxColour
& rCol
1059 if (!wxWindow::SetBackgroundColour(rCol
))
1063 // We set the same colour for both the "empty" background and the items
1066 ULONG ulColor
= wxColourToRGB(rCol
);
1068 ::WinSetPresParam( GetHWND()
1074 } // end of wxListCtrl::SetBackgroundColour
1076 // Gets information about this column
1077 bool wxListCtrl::GetColumn (
1082 PFIELDINFO pFieldInfo
= FindOS2ListFieldByColNum ( GetHWND()
1088 rItem
.SetWidth(pFieldInfo
->cxWidth
);
1089 if ((rItem
.GetMask() & wxLIST_MASK_TEXT
) &&
1090 (pFieldInfo
->flData
& CFA_STRING
) &&
1091 (pFieldInfo
->pUserData
!= NULL
))
1093 rItem
.SetText((char*)pFieldInfo
->pUserData
);
1095 if (rItem
.GetMask() & wxLIST_MASK_FORMAT
)
1097 if (pFieldInfo
->flData
& CFA_LEFT
)
1098 rItem
.m_format
= wxLIST_FORMAT_LEFT
;
1099 else if (pFieldInfo
->flData
& CFA_RIGHT
)
1100 rItem
.m_format
= wxLIST_FORMAT_RIGHT
;
1101 else if (pFieldInfo
->flData
& CFA_CENTER
)
1102 rItem
.m_format
= wxLIST_FORMAT_CENTRE
;
1105 } // end of wxListCtrl::GetColumn
1107 // Sets information about this column
1108 bool wxListCtrl::SetColumn (
1113 PFIELDINFO pFieldInfo
= FindOS2ListFieldByColNum( GetHWND()
1116 ConvertToOS2ListCol( nCol
1121 // Since we changed the field pointed to, we invalidate to see the result
1123 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO
, NULL
, NULL
);
1125 } // end of wxListCtrl::SetColumn
1127 // Gets the column width
1128 int wxListCtrl::GetColumnWidth (
1132 PFIELDINFO pFieldInfo
= FindOS2ListFieldByColNum ( GetHWND()
1138 return((int)pFieldInfo
->cxWidth
);
1139 } // end of wxListCtrl::GetColumnWidth
1141 // Sets the column width
1142 bool wxListCtrl::SetColumnWidth (
1148 int nWidth2
= nWidth
;
1150 if (GetWindowStyleFlag() & wxLC_LIST
)
1153 PFIELDINFO pFieldInfo
= FindOS2ListFieldByColNum( GetHWND()
1156 pFieldInfo
->cxWidth
= nWidth
;
1157 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO
, NULL
, NULL
);
1159 } // end of wxListCtrl::SetColumnWidth
1161 // Gets the number of items that can fit vertically in the
1162 // visible area of the list control (list or report view)
1163 // or the total number of items in the list control (icon
1164 // or small icon view)
1165 int wxListCtrl::GetCountPerPage () const
1167 QUERYRECORDRECT vQueryRect
;
1173 if (!::WinSendMsg( GetHWND()
1176 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
1179 memset(&vQueryRect
, '\0', sizeof(QUERYRECORDRECT
));
1180 vQueryRect
.cb
= sizeof(QUERYRECORDRECT
);
1181 if (vCnrInfo
.flWindowAttr
& CV_ICON
)
1182 vQueryRect
.fsExtent
= CMA_ICON
| CMA_TEXT
;
1183 else if (vCnrInfo
.flWindowAttr
& CV_NAME
)
1184 vQueryRect
.fsExtent
= CMA_ICON
| CMA_TEXT
;
1185 else if (vCnrInfo
.flWindowAttr
& CV_TEXT
)
1186 vQueryRect
.fsExtent
= CMA_TEXT
;
1187 else if (vCnrInfo
.flWindowAttr
& CV_DETAIL
)
1188 vQueryRect
.fsExtent
= CMA_TEXT
;
1189 if (!::WinSendMsg( GetHWND()
1191 ,MPFROMP(&vRectRecord
)
1192 ,MPFROMP(&vQueryRect
)
1195 if (!::WinSendMsg( GetHWND()
1196 ,CM_QUERYVIEWPORTRECT
1197 ,MPFROMP(&vRectControl
)
1198 ,MPFROM2SHORT(CMA_WINDOW
, (USHORT
)FALSE
)
1201 nCount
= (int)((int)((vRectControl
.xRight
- vRectControl
.xLeft
) / (vRectRecord
.xRight
- vRectRecord
.xLeft
)) *
1202 (int)((vRectControl
.yTop
- vRectControl
.yBottom
) / (vRectRecord
.yTop
- vRectRecord
.yBottom
))
1204 if (nCount
> (int)vCnrInfo
.cFields
)
1205 nCount
= (int)vCnrInfo
.cFields
;
1207 } // end of wxListCtrl::GetCountPerPage
1209 // Gets the edit control for editing labels.
1210 wxTextCtrl
* wxListCtrl::GetEditControl() const
1215 // Gets information about the item
1216 bool wxListCtrl::GetItem (
1220 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1225 // Give NULL as hwnd as we already have everything we need
1227 ConvertFromOS2ListItem( NULL
1232 } // end of wxListCtrl::GetItem
1234 // Sets information about the item
1235 bool wxListCtrl::SetItem (
1239 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1243 ConvertToOS2ListItem( this
1249 // Check if setting attributes or lParam
1251 if (rInfo
.HasAttributes() || (rInfo
.GetMask() & wxLIST_MASK_DATA
))
1254 // Get internal item data
1255 // perhaps a cache here ?
1257 CListItemInternalData
* pData
= GetInternalData( this
1266 m_bAnyInternalData
= TRUE
;
1267 pData
= new CListItemInternalData();
1268 pRecord
->m_ulUserData
= (unsigned long)pData
;
1274 if (rInfo
.GetMask() & wxLIST_MASK_DATA
)
1275 pData
->m_lParam
= (WXLPARAM
)rInfo
.GetData();
1278 if (rInfo
.HasAttributes())
1281 *pData
->m_pAttr
= *rInfo
.GetAttributes();
1283 pData
->m_pAttr
= new wxListItemAttr(*rInfo
.GetAttributes());
1288 // We need to update the item immediately to show the new image
1290 bool bUpdateNow
= (rInfo
.GetMask() & wxLIST_MASK_IMAGE
) != 0;
1293 // Check whether it has any custom attributes
1295 if (rInfo
.HasAttributes())
1297 m_bHasAnyAttr
= TRUE
;
1300 // If the colour has changed, we must redraw the item
1304 ::WinSendMsg( GetHWND()
1305 ,CM_INVALIDATERECORD
1307 ,MPFROM2SHORT(1, CMA_ERASE
| CMA_REPOSITION
| CMA_TEXTCHANGED
)
1309 RefreshItem(pRecord
->m_ulItemId
);
1311 } // end of wxListCtrl::SetItem
1313 long wxListCtrl::SetItem (
1316 , const wxString
& rsLabel
1322 vInfo
.m_text
= rsLabel
;
1323 vInfo
.m_mask
= wxLIST_MASK_TEXT
;
1324 vInfo
.m_itemId
= lIndex
;
1328 vInfo
.m_image
= nImageId
;
1329 vInfo
.m_mask
|= wxLIST_MASK_IMAGE
;
1331 return SetItem(vInfo
);
1332 } // end of wxListCtrl::SetItem
1334 // Gets the item state
1335 int wxListCtrl::GetItemState (
1342 vInfo
.m_mask
= wxLIST_MASK_STATE
;
1343 vInfo
.m_stateMask
= lStateMask
;
1344 vInfo
.m_itemId
= lItem
;
1346 if (!GetItem(vInfo
))
1348 return vInfo
.m_state
;
1349 } // end of wxListCtrl::GetItemState
1351 // Sets the item state
1352 bool wxListCtrl::SetItemState (
1358 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1363 // Don't use SetItem() here as it doesn't work with the virtual list
1366 ConvertToOS2Flags( lState
1371 // for the virtual list controls we need to refresh the previously focused
1372 // item manually when changing focus without changing selection
1373 // programmatically because otherwise it keeps its focus rectangle until
1374 // next repaint (yet another comctl32 bug)
1379 (lStateMask
& wxLIST_STATE_FOCUSED
) &&
1380 (lState
& wxLIST_STATE_FOCUSED
) )
1382 lFocusOld
= GetNextItem( -1
1384 ,wxLIST_STATE_FOCUSED
1391 ::WinSendMsg( GetHWND()
1392 ,CM_INVALIDATERECORD
1394 ,MPFROM2SHORT(1, CMA_ERASE
| CMA_REPOSITION
| CMA_TEXTCHANGED
)
1397 if (lFocusOld
!= -1)
1400 // No need to refresh the item if it was previously selected, it would
1401 // only result in annoying flicker
1403 if (!(GetItemState( lFocusOld
1404 ,wxLIST_STATE_SELECTED
1405 ) & wxLIST_STATE_SELECTED
))
1407 RefreshItem(lFocusOld
);
1411 } // end of wxListCtrl::SetItemState
1413 // Sets the item image
1414 bool wxListCtrl::SetItemImage (
1417 , int WXUNUSED(nSelImage
))
1421 vInfo
.m_mask
= wxLIST_MASK_IMAGE
;
1422 vInfo
.m_image
= nImage
;
1423 vInfo
.m_itemId
= lItem
;
1424 return SetItem(vInfo
);
1425 } // end of wxListCtrl::SetItemImage
1427 // Gets the item text
1428 wxString
wxListCtrl::GetItemText (
1434 vInfo
.m_mask
= wxLIST_MASK_TEXT
;
1435 vInfo
.m_itemId
= lItem
;
1437 if (!GetItem(vInfo
))
1438 return wxEmptyString
;
1439 return vInfo
.m_text
;
1440 } // end of wxListCtrl::GetItemText
1442 // Sets the item text
1443 void wxListCtrl::SetItemText (
1445 , const wxString
& rsStr
1450 vInfo
.m_mask
= wxLIST_MASK_TEXT
;
1451 vInfo
.m_itemId
= lItem
;
1452 vInfo
.m_text
= rsStr
;
1454 } // end of wxListCtrl::SetItemText
1456 // Gets the item data
1457 long wxListCtrl::GetItemData (
1463 vInfo
.m_mask
= wxLIST_MASK_DATA
;
1464 vInfo
.m_itemId
= lItem
;
1465 if (!GetItem(vInfo
))
1467 return vInfo
.m_data
;
1468 } // end of wxListCtrl::GetItemData
1470 // Sets the item data
1471 bool wxListCtrl::SetItemData (
1478 vInfo
.m_mask
= wxLIST_MASK_DATA
;
1479 vInfo
.m_itemId
= lItem
;
1480 vInfo
.m_data
= lData
;
1481 return SetItem(vInfo
);
1482 } // end of wxListCtrl::SetItemData
1484 // Gets the item rectangle
1485 bool wxListCtrl::GetItemRect (
1492 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1495 QUERYRECORDRECT vQueryRect
;
1501 vQueryRect
.cb
= sizeof(QUERYRECORDRECT
);
1502 vQueryRect
.pRecord
= &pRecord
->m_vRecord
;
1503 vQueryRect
.fRightSplitWindow
= TRUE
;
1504 vQueryRect
.fsExtent
= CMA_ICON
| CMA_TEXT
;
1505 ::WinSendMsg( GetHWND()
1508 ,MPFROMP(&vQueryRect
)
1511 // remember OS/2 is backwards
1516 rRect
.x
= vRect
.xLeft
;
1517 rRect
.y
= nHeight
- vRect
.yTop
;
1518 rRect
.width
= vRect
.xRight
;
1519 rRect
.height
= nHeight
- vRect
.yBottom
;
1522 } // end of wxListCtrl::GetItemRect
1524 // Gets the item position
1525 bool wxListCtrl::GetItemPosition (
1531 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1534 QUERYRECORDRECT vQueryRect
;
1540 vQueryRect
.cb
= sizeof(QUERYRECORDRECT
);
1541 vQueryRect
.pRecord
= &pRecord
->m_vRecord
;
1542 vQueryRect
.fRightSplitWindow
= TRUE
;
1543 vQueryRect
.fsExtent
= CMA_ICON
| CMA_TEXT
;
1544 ::WinSendMsg( GetHWND()
1547 ,MPFROMP(&vQueryRect
)
1550 // remember OS/2 is backwards
1555 rPos
.x
= vRect
.xLeft
;
1556 rPos
.y
= nHeight
- vRect
.yTop
;
1559 } // end of wxListCtrl::GetItemPosition
1561 // Sets the item position.
1562 bool wxListCtrl::SetItemPosition (
1564 , const wxPoint
& rPos
1568 // Items cannot be positioned in X/Y coord in OS/2
1571 } // end of wxListCtrl::SetItemPosition
1573 // Gets the number of items in the list control
1574 int wxListCtrl::GetItemCount () const
1578 if (!::WinSendMsg( GetHWND()
1581 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
1584 return vCnrInfo
.cRecords
;
1585 } // end of wxListCtrl::GetItemCount
1587 // Retrieves the spacing between icons in pixels.
1588 // If small is TRUE, gets the spacing for the small icon
1589 // view, otherwise the large icon view.
1590 int wxListCtrl::GetItemSpacing (
1596 if (!::WinSendMsg( GetHWND()
1599 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
1602 return vCnrInfo
.cyLineSpacing
;
1603 } // end of wxListCtrl::GetItemSpacing
1605 void wxListCtrl::SetItemTextColour (
1607 , const wxColour
& rCol
1612 vInfo
.m_itemId
= lItem
;
1613 vInfo
.SetTextColour(rCol
);
1615 } // end of wxListCtrl::SetItemTextColour
1617 wxColour
wxListCtrl::GetItemTextColour (
1623 vInfo
.m_itemId
= lItem
;
1625 return vInfo
.GetTextColour();
1626 } // end of wxListCtrl::GetItemTextColour
1628 void wxListCtrl::SetItemBackgroundColour (
1630 , const wxColour
& rCol
1635 vInfo
.m_itemId
= lItem
;
1636 vInfo
.SetBackgroundColour(rCol
);
1638 } // end of wxListCtrl::SetItemBackgroundColour
1640 wxColour
wxListCtrl::GetItemBackgroundColour (
1646 vInfo
.m_itemId
= lItem
;
1648 return vInfo
.GetBackgroundColour();
1649 } // end of wxListCtrl::GetItemBackgroundColour
1651 // Gets the number of selected items in the list control
1652 int wxListCtrl::GetSelectedItemCount () const
1654 PMYRECORD pRecord
= NULL
;
1656 pRecord
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( GetHWND()
1657 ,CM_QUERYRECORDEMPHASIS
1659 ,(MPARAM
)CRA_SELECTED
1667 pRecord
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( GetHWND()
1668 ,CM_QUERYRECORDEMPHASIS
1670 ,(MPARAM
)CRA_SELECTED
1676 } // end of wxListCtrl::GetSelectedItemCount
1678 // Gets the text colour of the listview
1679 wxColour
wxListCtrl::GetTextColour () const
1684 ::WinQueryPresParam( GetHWND()
1694 } // end of wxListCtrl::GetTextColour
1696 // Sets the text colour of the listview
1697 void wxListCtrl::SetTextColour (
1698 const wxColour
& rCol
1701 ULONG ulColor
= wxColourToRGB(rCol
);
1703 ::WinSetPresParam( GetHWND()
1708 } // end of wxListCtrl::SetTextColour
1710 // Gets the index of the topmost visible item when in
1711 // list or report view
1712 long wxListCtrl::GetTopItem () const
1714 PMYRECORD pRecord
= NULL
;
1715 QUERYRECFROMRECT vQueryRect
;
1718 ::WinSendMsg( GetHWND()
1719 ,CM_QUERYVIEWPORTRECT
1721 ,MPFROM2SHORT(CMA_WINDOW
, TRUE
)
1723 vQueryRect
.cb
= sizeof(QUERYRECFROMRECT
);
1724 vQueryRect
.rect
= vRect
;
1725 vQueryRect
.fsSearch
= CMA_PARTIAL
;
1727 pRecord
= (PMYRECORD
)::WinSendMsg( GetHWND()
1728 ,CM_QUERYRECORDFROMRECT
1730 ,MPFROMP(&vQueryRect
)
1735 return (long)pRecord
->m_ulItemId
;
1736 } // end of wxListCtrl::GetTopItem
1738 // Searches for an item, starting from 'item'.
1739 // 'geometry' is one of
1740 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
1741 // 'state' is a state bit flag, one or more of
1742 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
1743 // item can be -1 to find the first item that matches the
1745 // Returns the item or -1 if unsuccessful.
1746 long wxListCtrl::GetNextItem (
1748 , int WXUNUSED(nGeom
)
1749 , int WXUNUSED(nState
)
1752 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1756 pRecord
= (PMYRECORD
)pRecord
->m_vRecord
.preccNextRecord
;
1758 return((long)pRecord
->m_ulItemId
);
1760 } // end of wxListCtrl::GetNextItem
1762 wxImageList
* wxListCtrl::GetImageList (
1766 if (nWhich
== wxIMAGE_LIST_NORMAL
)
1768 return m_pImageListNormal
;
1770 else if (nWhich
== wxIMAGE_LIST_SMALL
)
1772 return m_pImageListSmall
;
1774 else if (nWhich
== wxIMAGE_LIST_STATE
)
1776 return m_pImageListState
;
1779 } // end of wxListCtrl::GetImageList
1781 void wxListCtrl::SetImageList (
1782 wxImageList
* pImageList
1786 if (nWhich
== wxIMAGE_LIST_NORMAL
)
1788 if (m_bOwnsImageListNormal
)
1789 delete m_pImageListNormal
;
1790 m_pImageListNormal
= pImageList
;
1791 m_bOwnsImageListNormal
= FALSE
;
1793 else if (nWhich
== wxIMAGE_LIST_SMALL
)
1795 if (m_bOwnsImageListSmall
)
1796 delete m_pImageListSmall
;
1797 m_pImageListSmall
= pImageList
;
1798 m_bOwnsImageListSmall
= FALSE
;
1800 else if (nWhich
== wxIMAGE_LIST_STATE
)
1802 if (m_bOwnsImageListState
)
1803 delete m_pImageListState
;
1804 m_pImageListState
= pImageList
;
1805 m_bOwnsImageListState
= FALSE
;
1807 } // end of wxListCtrl::SetImageList
1809 void wxListCtrl::AssignImageList (
1810 wxImageList
* pImageList
1814 SetImageList( pImageList
1817 if (nWhich
== wxIMAGE_LIST_NORMAL
)
1818 m_bOwnsImageListNormal
= TRUE
;
1819 else if (nWhich
== wxIMAGE_LIST_SMALL
)
1820 m_bOwnsImageListSmall
= TRUE
;
1821 else if (nWhich
== wxIMAGE_LIST_STATE
)
1822 m_bOwnsImageListState
= TRUE
;
1823 } // end of wxListCtrl::AssignImageList
1825 // ----------------------------------------------------------------------------
1827 // ----------------------------------------------------------------------------
1829 // Arranges the items
1830 bool wxListCtrl::Arrange (
1837 if (nFlag
== wxLIST_ALIGN_SNAP_TO_GRID
)
1839 ulType
= CMA_ARRANGEGRID
;
1840 if (nFlag
== wxLIST_ALIGN_LEFT
)
1841 ulFlags
|= CMA_LEFT
;
1842 else if (nFlag
== wxLIST_ALIGN_TOP
)
1844 else if (nFlag
== wxLIST_ALIGN_DEFAULT
)
1845 ulFlags
|= CMA_LEFT
;
1848 ulType
= CMA_ARRANGESTANDARD
;
1849 ::WinSendMsg( GetHWND()
1855 // We do not support CMA_ARRANGESELECTED
1858 } // end of wxListCtrl::Arrange
1861 bool wxListCtrl::DeleteItem (
1865 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1868 if (LONGFROMMR(::WinSendMsg( GetHWND()
1871 ,MPFROM2SHORT(1, CMA_FREE
)
1878 // The virtual list control doesn't refresh itself correctly, help it
1883 // We need to refresh all the lines below the one which was deleted
1887 if (lItem
> 0 && GetItemCount())
1889 GetItemRect( lItem
- 1
1895 vRectItem
.y
= vRectItem
.height
= 0;
1897 wxRect vRectWin
= GetRect();
1899 vRectWin
.height
= vRectWin
.GetBottom() - vRectItem
.GetBottom();
1900 vRectWin
.y
= vRectItem
.GetBottom();
1901 RefreshRect(vRectWin
);
1904 } // end of wxListCtrl::DeleteItem
1906 // Deletes all items
1907 bool wxListCtrl::DeleteAllItems ()
1909 return((LONG
)::WinSendMsg( GetHWND()
1912 ,MPFROM2SHORT(0, CMA_FREE
)
1914 } // end of wxListCtrl::DeleteAllItems
1916 // Deletes all items
1917 bool wxListCtrl::DeleteAllColumns ()
1919 while (m_nColCount
> 0)
1921 DeleteColumn(m_nColCount
- 1);
1925 wxASSERT_MSG(m_nColCount
== 0, wxT("no columns should be left"));
1927 } // end of wxListCtrl::DeleteAllColumns
1930 bool wxListCtrl::DeleteColumn (
1934 bool bSuccess
= FALSE
;
1935 PFIELDINFO pField
= FindOS2ListFieldByColNum( GetHWND()
1938 bSuccess
= ((LONG
)::WinSendMsg( GetHWND()
1939 ,CM_REMOVEDETAILFIELDINFO
1941 ,MPFROM2SHORT((SHORT
)1, CMA_FREE
)
1943 if (bSuccess
&& (m_nColCount
> 0))
1946 } // end of wxListCtrl::DeleteColumn
1948 // Clears items, and columns if there are any.
1949 void wxListCtrl::ClearAll ()
1952 if (m_nColCount
> 0)
1954 } // end of wxListCtrl::ClearAll
1957 // OS/2 does not use a text control for its container labels. You merely
1958 // "open" a record for editting.
1960 wxTextCtrl
* wxListCtrl::EditLabel (
1962 , wxClassInfo
* WXUNUSED(pTextControlClass
)
1966 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
1970 vEdit
.cb
= sizeof(CNREDITDATA
);
1971 vEdit
.hwndCnr
= GetHWND();
1972 vEdit
.pRecord
= &pRecord
->m_vRecord
;
1973 vEdit
.pFieldInfo
= NULL
;
1974 vEdit
.ppszText
= NULL
;
1978 ::WinSendMsg( GetHWND()
1984 } // end of wxListCtrl::EditLabel
1986 // End label editing, optionally cancelling the edit. Under OS/2 you close
1987 // the record for editting
1988 bool wxListCtrl::EndEditLabel (
1989 bool WXUNUSED(bCancel
)
1992 ::WinSendMsg( GetHWND()
1998 } // end of wxListCtrl::EndEditLabel
2000 // Ensures this item is visible
2001 bool wxListCtrl::EnsureVisible (
2005 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
2008 ::WinSendMsg( GetHWND()
2009 ,CM_INVALIDATERECORD
2011 ,MPFROM2SHORT((SHORT
)1, CMA_NOREPOSITION
)
2014 } // end of wxListCtrl::EnsureVisible
2016 // Find an item whose label matches this string, starting from the item after 'start'
2017 // or the beginning if 'start' is -1.
2018 long wxListCtrl::FindItem (
2020 , const wxString
& rsStr
2025 SEARCHSTRING vSearch
;
2026 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
2032 if (!::WinSendMsg( GetHWND()
2035 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
2039 if (vCnrInfo
.flWindowAttr
& CV_ICON
)
2041 if (vCnrInfo
.flWindowAttr
& CV_NAME
)
2043 if (vCnrInfo
.flWindowAttr
& CV_TEXT
)
2045 if (vCnrInfo
.flWindowAttr
& CV_DETAIL
)
2048 ulFlag
|= CV_EXACTLENGTH
;
2050 vSearch
.cb
= sizeof(SEARCHSTRING
);
2051 vSearch
.pszSearch
= (char*)rsStr
.c_str();
2052 vSearch
.fsPrefix
= TRUE
;
2053 vSearch
.fsCaseSensitive
= TRUE
;
2054 vSearch
.usView
= ulFlag
;
2058 pRecord
= (PMYRECORD
)::WinSendMsg( GetHWND()
2066 pRecord
= (PMYRECORD
)::WinSendMsg( GetHWND()
2074 return pRecord
->m_ulItemId
;
2075 } // end of wxListCtrl::FindItem
2077 // Find an item whose data matches this data, starting from the item after 'start'
2078 // or the beginning if 'start' is -1.
2079 long wxListCtrl::FindItem (
2084 long lIdx
= lStart
+ 1;
2085 long lCount
= GetItemCount();
2087 while (lIdx
< lCount
)
2089 if (GetItemData(lIdx
) == lData
)
2094 } // end of wxListCtrl::FindItem
2096 // Find an item nearest this position in the specified direction, starting from
2097 // the item after 'start' or the beginning if 'start' is -1.
2098 long wxListCtrl::FindItem (
2100 , const wxPoint
& rPoint
2105 QUERYRECORDRECT vQueryRect
;
2106 PMYRECORD pRecord
= FindOS2ListRecordByID( GetHWND()
2113 if (!::WinSendMsg( GetHWND()
2116 ,(MPARAM
)(USHORT
)sizeof(CNRINFO
)
2120 vQueryRect
.cb
= sizeof(QUERYRECORDRECT
);
2121 vQueryRect
.pRecord
= &pRecord
->m_vRecord
;
2122 vQueryRect
.fRightSplitWindow
= TRUE
;
2123 vQueryRect
.fsExtent
= CMA_ICON
| CMA_TEXT
;
2125 ::WinSendMsg( GetHWND()
2128 ,MPFROMP(&vQueryRect
)
2130 vLibRect
.SetLeft(vRect
.xLeft
);
2131 vLibRect
.SetTop(vRect
.yTop
);
2132 vLibRect
.SetRight(vRect
.xRight
);
2133 vLibRect
.SetBottom(vRect
.yBottom
);
2134 if (vLibRect
.Inside(rPoint
))
2135 return pRecord
->m_ulItemId
;
2137 for (i
= lStart
+ 1; i
< vCnrInfo
.cRecords
; i
++)
2139 pRecord
= (PMYRECORD
)PVOIDFROMMR(::WinSendMsg( GetHWND()
2142 ,MPFROM2SHORT(CMA_NEXT
, CMA_ITEMORDER
)
2144 vQueryRect
.pRecord
= (PRECORDCORE
)pRecord
;
2145 ::WinSendMsg( GetHWND()
2148 ,MPFROMP(&vQueryRect
)
2150 vLibRect
.SetLeft(vRect
.xLeft
);
2151 vLibRect
.SetTop(vRect
.yTop
);
2152 vLibRect
.SetRight(vRect
.xRight
);
2153 vLibRect
.SetBottom(vRect
.yBottom
);
2154 if (vLibRect
.Inside(rPoint
))
2155 return pRecord
->m_ulItemId
;
2158 } // end of wxListCtrl::FindItem
2160 // Determines which item (if any) is at the specified point,
2161 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
2162 long wxListCtrl::HitTest (
2163 const wxPoint
& rPoint
2164 , int& WXUNUSED(rFlags
)
2167 PMYRECORD pRecord
= NULL
;
2168 QUERYRECFROMRECT vQueryRect
;
2173 // Get height for OS/2 point conversion
2175 ::WinSendMsg( GetHWND()
2176 ,CM_QUERYVIEWPORTRECT
2178 ,MPFROM2SHORT(CMA_WINDOW
, TRUE
)
2180 lHeight
= vRect
.yTop
- vRect
.yBottom
;
2183 // For now just try and get a record in the general vicinity and forget
2186 vRect
.xLeft
= rPoint
.x
- 2;
2187 vRect
.xRight
= rPoint
.x
+ 2;
2188 vRect
.yTop
= (lHeight
- rPoint
.y
) + 2;
2189 vRect
.yBottom
= (lHeight
- rPoint
.y
) - 2;
2191 vQueryRect
.cb
= sizeof(QUERYRECFROMRECT
);
2192 vQueryRect
.rect
= vRect
;
2193 vQueryRect
.fsSearch
= CMA_PARTIAL
;
2195 pRecord
= (PMYRECORD
)::WinSendMsg( GetHWND()
2196 ,CM_QUERYRECORDFROMRECT
2198 ,MPFROMP(&vQueryRect
)
2203 return pRecord
->m_ulItemId
;
2204 } // end of wxListCtrl::HitTest
2206 // Inserts an item, returning the index of the new item if successful,
2208 long wxListCtrl::InsertItem (
2212 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
2214 PMYRECORD pRecordAfter
= FindOS2ListRecordByID ( GetHWND()
2217 PMYRECORD pRecord
= (PMYRECORD
)::WinSendMsg( GetHWND()
2219 ,MPFROMLONG(sizeof(MYRECORD
) - sizeof(RECORDCORE
))
2222 RECORDINSERT vInsert
;
2224 vInsert
.cb
= sizeof(RECORDINSERT
);
2225 vInsert
.pRecordOrder
= (PRECORDCORE
)pRecordAfter
;
2226 vInsert
.pRecordParent
= NULL
;
2227 vInsert
.fInvalidateRecord
= TRUE
;
2228 vInsert
.zOrder
= CMA_TOP
;
2229 vInsert
.cRecordsInsert
= 1;
2231 ConvertToOS2ListItem( this
2237 // Check wether we need to allocate our internal data
2239 bool bNeedInternalData
= ((rInfo
.GetMask() & wxLIST_MASK_DATA
) ||
2240 rInfo
.HasAttributes()
2242 if (bNeedInternalData
)
2244 m_bAnyInternalData
= TRUE
;
2247 // Internal stucture that manages data
2249 CListItemInternalData
* pData
= new CListItemInternalData();
2251 pRecord
->m_ulUserData
= (unsigned long)pData
;
2252 if (rInfo
.GetMask() & wxLIST_MASK_DATA
)
2253 pData
->m_lParam
= (WXLPARAM
)rInfo
.GetData();
2256 // Check whether it has any custom attributes
2258 if (rInfo
.HasAttributes())
2261 // Take copy of attributes
2263 pData
->m_pAttr
= new wxListItemAttr(*rInfo
.GetAttributes());
2266 ::WinSendMsg( GetHWND()
2272 // OS/2 must mannually bump the index's of following records
2274 BumpRecordIds( GetHWND()
2277 return pRecord
->m_ulItemId
;
2278 } // end of wxListCtrl::InsertItem
2280 long wxListCtrl::InsertItem (
2282 , const wxString
& rsLabel
2287 vInfo
.m_text
= rsLabel
;
2288 vInfo
.m_mask
= wxLIST_MASK_TEXT
;
2289 vInfo
.m_itemId
= lIndex
;
2290 return InsertItem(vInfo
);
2291 } // end of wxListCtrl::InsertItem
2293 // Inserts an image item
2294 long wxListCtrl::InsertItem (
2301 vInfo
.m_image
= nImageIndex
;
2302 vInfo
.m_mask
= wxLIST_MASK_IMAGE
;
2303 vInfo
.m_itemId
= lIndex
;
2304 return InsertItem(vInfo
);
2305 } // end of wxListCtrl::InsertItem
2307 // Inserts an image/string item
2308 long wxListCtrl::InsertItem (
2310 , const wxString
& rsLabel
2316 vInfo
.m_image
= nImageIndex
;
2317 vInfo
.m_text
= rsLabel
;
2318 vInfo
.m_mask
= wxLIST_MASK_IMAGE
| wxLIST_MASK_TEXT
;
2319 vInfo
.m_itemId
= lIndex
;
2320 return InsertItem(vInfo
);
2321 } // end of wxListCtrl::InsertItem
2323 // For details view mode (only), inserts a column.
2324 long wxListCtrl::InsertColumn (
2330 PFIELDINFO pField
= (PFIELDINFO
)::WinSendMsg( GetHWND()
2331 ,CM_ALLOCDETAILFIELDINFO
2335 PFIELDINFO pFieldAfter
= FindOS2ListFieldByColNum ( GetHWND()
2338 FIELDINFOINSERT vInsert
;
2340 vInsert
.cb
= sizeof(FIELDINFOINSERT
);
2341 vInsert
.pFieldInfoOrder
= pFieldAfter
;
2342 vInsert
.fInvalidateFieldInfo
= TRUE
;
2343 vInsert
.cFieldInfoInsert
= 1;
2345 ConvertToOS2ListCol ( lCol
2349 bSuccess
= ::WinSendMsg( GetHWND()
2350 ,CM_INSERTDETAILFIELDINFO
2355 } // end of wxListCtrl::InsertColumn
2357 long wxListCtrl::InsertColumn (
2359 , const wxString
& rsHeading
2366 vItem
.m_mask
= wxLIST_MASK_TEXT
| wxLIST_MASK_FORMAT
;
2367 vItem
.m_text
= rsHeading
;
2370 vItem
.m_mask
|= wxLIST_MASK_WIDTH
;
2371 vItem
.m_width
= nWidth
;
2373 vItem
.m_format
= nFormat
;
2375 return InsertColumn( lCol
2378 } // end of wxListCtrl::InsertColumn
2380 // scroll the control by the given number of pixels (exception: in list view,
2381 // dx is interpreted as number of columns)
2382 bool wxListCtrl::ScrollList (
2388 ::WinSendMsg( GetHWND()
2390 ,(MPARAM
)CMA_HORIZONTAL
2394 ::WinSendMsg( GetHWND()
2396 ,(MPARAM
)CMA_VERTICAL
2400 } // end of wxListCtrl::ScrollList
2402 bool wxListCtrl::SortItems (
2403 wxListCtrlCompare fn
2407 SInternalDataSort vInternalData
;
2409 vInternalData
.m_fnUser
= fn
;
2410 vInternalData
.m_lData
= lData
;
2412 // WPARAM cast is needed for mingw/cygwin
2413 if (!::WinSendMsg( GetHWND()
2415 ,(PFN
)InternalDataCompareFunc
2416 ,(PVOID
)&vInternalData
2419 wxLogDebug(_T("CM_SORTRECORD failed"));
2423 } // end of wxListCtrl::SortItems
2425 // ----------------------------------------------------------------------------
2426 // message processing
2427 // ----------------------------------------------------------------------------
2429 bool wxListCtrl::OS2Command (
2434 if (uCmd
== CN_ENDEDIT
)
2436 wxCommandEvent
vEvent( wxEVT_COMMAND_TEXT_UPDATED
2440 vEvent
.SetEventObject( this );
2441 ProcessCommand(vEvent
);
2444 else if (uCmd
== CN_KILLFOCUS
)
2446 wxCommandEvent
vEvent( wxEVT_KILL_FOCUS
2449 vEvent
.SetEventObject( this );
2450 ProcessCommand(vEvent
);
2455 } // end of wxListCtrl::OS2Command
2457 // Necessary for drawing hrules and vrules, if specified
2458 void wxListCtrl::OnPaint (
2459 wxPaintEvent
& rEvent
2462 wxPaintDC
vDc(this);
2463 wxPen
vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT
)
2467 wxSize vClientSize
= GetClientSize();
2469 int nItemCount
= GetItemCount();
2472 bool bDrawHRules
= ((GetWindowStyle() & wxLC_HRULES
) != 0);
2473 bool bDrawVRules
= ((GetWindowStyle() & wxLC_VRULES
) != 0);
2475 wxControl::OnPaint(rEvent
);
2478 // Reset the device origin since it may have been set
2480 vDc
.SetDeviceOrigin(0, 0);
2481 if (!bDrawHRules
&& !bDrawVRules
)
2483 if ((GetWindowStyle() & wxLC_REPORT
) == 0)
2486 vDc
.SetBrush(*wxTRANSPARENT_BRUSH
);
2490 long lTop
= GetTopItem();
2492 for (i
= lTop
; i
< lTop
+ GetCountPerPage() + 1; i
++)
2498 nCy
= vItemRect
.GetTop();
2499 if (i
!= 0) // Don't draw the first one
2508 if (i
== nItemCount
- 1)
2510 nCy
= vItemRect
.GetBottom();
2521 if (bDrawVRules
&& (i
> -1))
2523 wxRect vFirstItemRect
;
2533 int nX
= vItemRect
.GetX();
2535 for (nCol
= 0; nCol
< GetColumnCount(); nCol
++)
2537 int nColWidth
= GetColumnWidth(nCol
);
2540 vDc
.DrawLine( nX
- 1
2541 ,vFirstItemRect
.GetY() - 2
2543 ,vItemRect
.GetBottom()
2548 } // end of wxListCtrl::OnPaint
2550 // ----------------------------------------------------------------------------
2551 // virtual list controls
2552 // ----------------------------------------------------------------------------
2554 wxString
wxListCtrl::OnGetItemText (
2555 long WXUNUSED(lItem
)
2556 , long WXUNUSED(lCol
)
2559 // this is a pure virtual function, in fact - which is not really pure
2560 // because the controls which are not virtual don't need to implement it
2561 wxFAIL_MSG( _T("not supposed to be called") );
2562 return wxEmptyString
;
2563 } // end of wxListCtrl::OnGetItemText
2565 int wxListCtrl::OnGetItemImage (
2566 long WXUNUSED(lItem
)
2570 wxFAIL_MSG( _T("not supposed to be called") );
2572 } // end of wxListCtrl::OnGetItemImage
2574 wxListItemAttr
* wxListCtrl::OnGetItemAttr (
2575 long WXUNUSED_UNLESS_DEBUG(lItem
)
2578 wxASSERT_MSG( lItem
>= 0 && lItem
< GetItemCount(),
2579 _T("invalid item index in OnGetItemAttr()") );
2582 // No attributes by default
2585 } // end of wxListCtrl::OnGetItemAttr
2587 void wxListCtrl::SetItemCount (
2591 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
2594 // Cannot explicitly set the record count in OS/2
2596 } // end of wxListCtrl::SetItemCount
2598 void wxListCtrl::RefreshItem (
2608 } // end of wxListCtrl::RefreshItem
2610 void wxListCtrl::RefreshItems (
2618 GetItemRect( lItemFrom
2621 GetItemRect( lItemTo
2625 wxRect vRect
= vRect1
;
2627 vRect
.height
= vRect2
.GetBottom() - vRect1
.GetTop();
2629 } // end of wxListCtrl::RefreshItems
2631 MRESULT
wxListCtrl::OS2WindowProc(
2637 bool bProcessed
= FALSE
;
2639 wxListEvent
vEvent( wxEVT_NULL
2642 wxEventType vEventType
= wxEVT_NULL
;
2643 PCNRDRAGINIT pDragInit
= NULL
;
2644 PCNREDITDATA pEditData
= NULL
;
2645 PNOTIFYRECORDENTER pNotifyEnter
= NULL
;
2647 vEvent
.SetEventObject(this);
2652 // First off let's set some internal data
2654 switch(SHORT2FROMMP(wParam
))
2660 CListItemInternalData
* pInternaldata
= (CListItemInternalData
*)lParam
;
2664 wxListItem
* pItem
= (wxListItem
*)&vEvent
.GetItem();
2666 pItem
->SetData((long)pInternaldata
->m_lParam
);
2672 // Now let's go through the codes we're interested in
2674 switch(SHORT2FROMMP(wParam
))
2677 pDragInit
= (PCNRDRAGINIT
)lParam
;
2680 PMYRECORD pRecord
= (PMYRECORD
)pDragInit
->pRecord
;
2682 vEventType
= wxEVT_COMMAND_LIST_BEGIN_RDRAG
;
2683 vEvent
.m_itemIndex
= pRecord
->m_ulItemId
;
2684 vEvent
.m_pointDrag
.x
= pDragInit
->x
;
2685 vEvent
.m_pointDrag
.y
= pDragInit
->y
;
2690 pEditData
= (PCNREDITDATA
)lParam
;
2693 vEventType
= wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
;
2694 ConvertFromOS2ListItem( GetHWND()
2695 ,(wxListItem
&)vEvent
.GetItem()
2696 ,(PMYRECORD
)pEditData
->pRecord
2698 vEvent
.m_itemIndex
= vEvent
.GetItem().GetId();
2703 pEditData
= (PCNREDITDATA
)lParam
;
2706 vEventType
= wxEVT_COMMAND_LIST_END_LABEL_EDIT
;
2707 ConvertFromOS2ListItem( GetHWND()
2708 ,(wxListItem
&)vEvent
.GetItem()
2709 ,(PMYRECORD
)pEditData
->pRecord
2711 if (pEditData
->cbText
== 0)
2712 return (MRESULT
)FALSE
;
2713 vEvent
.m_itemIndex
= vEvent
.GetItem().GetId();
2718 pNotifyEnter
= (PNOTIFYRECORDENTER
)lParam
;
2721 wxListItem
* pItem
= (wxListItem
*)&vEvent
.GetItem();
2722 PMYRECORD pMyRecord
= (PMYRECORD
)pNotifyEnter
->pRecord
;
2724 vEventType
= wxEVT_COMMAND_LIST_ITEM_ACTIVATED
;
2725 vEvent
.m_itemIndex
= pMyRecord
->m_ulItemId
;
2726 pItem
->SetText(GetItemText(pMyRecord
->m_ulItemId
));
2727 pItem
->SetData(GetItemData(pMyRecord
->m_ulItemId
));
2732 // Add the CN_DROP messages for Direct Manipulation
2735 vEvent
.SetEventType(vEventType
);
2736 bProcessed
= GetEventHandler()->ProcessEvent(vEvent
);
2740 lRc
= wxControl::OS2WindowProc( uMsg
2745 } // end of wxListCtrl::WindowProc
2747 #endif // wxUSE_LISTCTRL