/////////////////////////////////////////////////////////////////////////////
-// Name: listctrl.cpp
-// Purpose: wxListCtrl. See also Robert's generic wxListCtrl
-// Author: AUTHOR
+// Name: src/os2/listctrl.cpp
+// Purpose: wxListCtrl
+// Author: David Webster
// Modified by:
-// Created: ??/??/98
+// Created: 01/21/03
// RCS-ID: $Id$
-// Copyright: (c) AUTHOR
-// Licence: wxWindows licence
+// Copyright: (c) David Webster
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#ifdef __GNUG__
-#pragma implementation "listctrl.h"
-#endif
+// ============================================================================
+// declarations
+// ============================================================================
-#include "wx/stubs/textctrl.h"
-#include "wx/stubs/listctrl.h"
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
-#if !USE_SHARED_LIBRARY
-IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
-IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+#if wxUSE_LISTCTRL
+
+#ifndef WX_PRECOMP
+ #include "wx/app.h"
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/settings.h"
+ #include "wx/dcclient.h"
+ #include "wx/textctrl.h"
#endif
-wxListCtrl::wxListCtrl()
+#include "wx/imaglist.h"
+#include "wx/listctrl.h"
+
+#include "wx/os2/private.h"
+
+//
+// FIELDOFFSET in DETAIL view as defined in the OS2TK45 simply doesn't work
+// We use this, which does!
+//
+#undef FIELDOFFSET
+#define FIELDOFFSET(type, field) ((ULONG)&(((type *)0)->field))
+
+// ----------------------------------------------------------------------------
+// private helper classes
+// ----------------------------------------------------------------------------
+
+/////////////////////////////////////////////////////////////////////////////
+// STRUCT SMYRECORD
+// Under OS/2 we have to use our own RECORDCORE based struct if we have
+// user data to store in a PM Container Control (and wxListCtrl is a PM
+// Container in ICON, NAME, TEXT or DETAIL view). m_ulUserData is a four
+// byte value containing a pointer to our CListIntemInternalData class
+// instance.
+//
+// And now for the big time OS/2 Kludge. In traditional OS/2 PM
+// applications using containers, programmers determine BEFORE creation
+// how many records the view will have, initially, and how many columns
+// the detail view of the container will have, as the container represents
+// a known data block. Thus the OS/2 PM CV_DETAIL view, i.e.
+// the wxWidgets wxLC_REPORT view, relies on STATIC structure for its
+// columnar data. It gets the data to display by telling it the specific
+// offset of the field in the struct containing the displayable data. That
+// data has be of OS/2 Types, PSZ (char string), CDATE or CTIME format.
+// wxWidgets is dynamic in nature, however. We insert columns, one at a
+// time and do not know how many until the app is done inserting them. So
+// for OS/2 I have to set a max allowable since they are fixed. We return
+// an error to the app if they include more than we can handle.
+//
+// For example to display the data "Col 4 of Item 6" in a report view, I'd
+// have to do:
+// pRecord->m_pzColumn4 = "Col 4 of Item 6";
+// pField->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn4);
+// and then call the PM API to set it.
+//
+// This really stinks but I can't use a pointer to another struct as the
+// FIELDOFFSET call could only tell OS/2 the four byte value offset of
+// pointer field and it would display giberish in the column.
+/////////////////////////////////////////////////////////////////////////////
+typedef struct _MYRECORD
{
- m_imageListNormal = NULL;
- m_imageListSmall = NULL;
- m_imageListState = NULL;
- m_baseStyle = 0;
- m_colCount = 0;
-}
+ RECORDCORE m_vRecord;
+ unsigned long m_ulItemId;
+ unsigned long m_ulUserData; //actually a pointer value to real data (a CListItemInternalData class instance)
+ PSZ m_pzColumn1;
+ PSZ m_pzColumn2;
+ PSZ m_pzColumn3;
+ PSZ m_pzColumn4;
+ PSZ m_pzColumn5;
+ PSZ m_pzColumn6;
+ PSZ m_pzColumn7;
+ PSZ m_pzColumn8;
+ PSZ m_pzColumn9;
+ PSZ m_pzColumn10;
+} MYRECORD, *PMYRECORD;
-bool wxListCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
- long style, const wxValidator& validator, const wxString& name)
+/////////////////////////////////////////////////////////////////////////////
+// CLASS CListItemInternalData
+//
+// Problem:
+// The MSW version had problems with SetTextColour() et al as the
+// CListItemAttr's were stored keyed on the item index. If a item was
+// inserted anywhere but the end of the list the the text attributes
+// (colour etc) for the following items were out of sync.
+//
+// Solution:
+// Under MSW the only way to associate data with a
+// List item independent of its position in the list is to store a pointer
+// to it in its lParam attribute. However user programs are already using
+// this (via the SetItemData() GetItemData() calls).
+//
+// However what we can do is store a pointer to a structure which contains
+// the attributes we want *and* a lParam for the users data, e.g.
+//
+// class CListItemInternalData
+// {
+// public:
+// GuiAdvCtrl_CListItemAttr* pAttr;
+// long lParam; // user data
+// };
+//
+// To conserve memory, a CListItemInternalData is only allocated for a
+// LV_ITEM if text attributes or user data(lparam) are being set.
+//
+// For OS/2, the lParam value points to whatever actual data we have
+/////////////////////////////////////////////////////////////////////////////
+class CListItemInternalData
{
- m_imageListNormal = NULL;
- m_imageListSmall = NULL;
- m_imageListState = NULL;
- m_colCount = 0;
+public:
- SetValidator(validator);
- SetName(name);
+ CListItemInternalData(): m_pAttr(NULL)
+ ,m_lParam(0)
+ {}
- m_windowStyle = style;
+ ~CListItemInternalData()
+ {
+ delete m_pAttr;
+ m_pAttr = NULL;
+ }
- SetParent(parent);
+ wxListItemAttr* m_pAttr;
+ WXLPARAM m_lParam; // user data
+ PMYRECORD m_pMyRecord; // so we can set the m_ulUserData to 0 when this is deleted
+}; // end of CLASS CListItemInternalData
- m_windowId = (id == -1) ? NewControlId() : id;
+/////////////////////////////////////////////////////////////////////////////
+// STRUCT SInternalDataSort
+//
+// Sort items.
+//
+// fn is a function which takes 3 long arguments: item1, item2, data.
+// item1 is the long data associated with a first item (NOT the index).
+// item2 is the long data associated with a second item (NOT the index).
+// data is the same value as passed to SortItems.
+//
+// The return value is a negative number if the first item should precede the
+// second item, a positive number of the second item should precede the first,
+// or zero if the two items are equivalent.
+//
+// data is arbitrary data to be passed to the sort function.
+//
+// Internal structures for proxying the user compare function
+// so that we can pass it the *real* user data
+/////////////////////////////////////////////////////////////////////////////
+typedef struct internalDataSort
+{
+ wxListCtrlCompare m_fnUser;
+ long m_lData;
+} SInternalDataSort; // end of STRUCT SInternalDataSort
- if (parent) parent->AddChild(this);
+// ----------------------------------------------------------------------------
+// private helper functions
+// ----------------------------------------------------------------------------
- // TODO create list control
- return TRUE;
-}
+/////////////////////////////////////////////////////////////////////////////
+//
+// FindOS2ListFieldByColNum
+//
+// There is no way, under OS/2 to get a field in a container by index,
+// directly, so you must get the first one, then cycle through the list
+// until you get to where you want to be.
+//
+// PARAMETERS
+// hWnd -- window handle of container to search
+// lIndex -- index to set
+//
+// RETURN VALUE
+// pointer to the FIELDINFO struct at the index in the container record
+//
+/////////////////////////////////////////////////////////////////////////////
+PFIELDINFO FindOS2ListFieldByColNum (
+ HWND hWnd
+, long lIndex
+)
+{
+ PFIELDINFO pFieldInfo = NULL;
+ CNRINFO vCnrInfo;
+ ULONG i;
+
+ if (!::WinSendMsg( hWnd
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return NULL;
+ for (i = 0; i < vCnrInfo.cFields; i++)
+ {
+ if (i == 0)
+ pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
+ ,CM_QUERYDETAILFIELDINFO
+ ,MPFROMP(pFieldInfo)
+ ,(MPARAM)CMA_FIRST
+ ));
+ else
+ pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
+ ,CM_QUERYDETAILFIELDINFO
+ ,MPFROMP(pFieldInfo)
+ ,(MPARAM)CMA_NEXT
+ ));
+ if (!pFieldInfo)
+ return NULL;
+ if (i == (ULONG)lIndex)
+ break;
+ }
+ if (!pFieldInfo)
+ return NULL;
+ return pFieldInfo;
+} // end of FindOS2ListFieldByColNum
-wxListCtrl::~wxListCtrl()
+/////////////////////////////////////////////////////////////////////////////
+//
+// FindOS2ListRecordByID
+//
+// There is no way, under OS/2 to get a record in a container by index,
+// directly, so you must get the first one, then cycle through the list
+// until you get to where you want to be.
+//
+// PARAMETERS
+// hWnd -- window handle of container to search
+// lItemId -- index to set
+//
+// RETURN VALUE
+// pointer to the internal RECORDCORE struct at the index in the container
+//
+/////////////////////////////////////////////////////////////////////////////
+PMYRECORD FindOS2ListRecordByID (
+ HWND hWnd
+, long lItemId
+)
{
-}
+ PMYRECORD pRecord = NULL;
+ CNRINFO vCnrInfo;
+ unsigned long i;
+
+ if (!::WinSendMsg( hWnd
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return NULL;
+ for (i = 0; i < vCnrInfo.cRecords; i++)
+ {
+ if (i == 0)
+ pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
+ ,CM_QUERYRECORD
+ ,MPFROMP(pRecord)
+ ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
+ ));
+ else
+ pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
+ ,CM_QUERYRECORD
+ ,MPFROMP(pRecord)
+ ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
+ ));
+ if (!pRecord)
+ return NULL;
+ if (pRecord->m_ulItemId == (ULONG)lItemId)
+ break;
+ }
+ return pRecord;
+} // end of FindOS2ListRecordByID
-// Add or remove a single window style
-void wxListCtrl::SetSingleStyle(long style, bool add)
-{
- long flag = GetWindowStyleFlag();
-
- // Get rid of conflicting styles
- if ( add )
- {
- if ( style & wxLC_MASK_TYPE)
- flag = flag & ~wxLC_MASK_TYPE ;
- if ( style & wxLC_MASK_ALIGN )
- flag = flag & ~wxLC_MASK_ALIGN ;
- if ( style & wxLC_MASK_SORT )
- flag = flag & ~wxLC_MASK_SORT ;
+/////////////////////////////////////////////////////////////////////////////
+//
+// BumpRecordIds
+//
+// Since OS/2 does not keep native record id's but wx insists on inserting
+// and selecting via ID's, when we insert a record in the middle we need
+// to bump the id's of each record after the one we just inserted.
+//
+// PARAMETERS
+// hWnd -- window handle of container to search
+// pRecord -- record after which we starting bumping id's
+//
+// RETURN VALUE
+// none
+//
+/////////////////////////////////////////////////////////////////////////////
+void BumpRecordIds (
+ HWND hWnd
+, PMYRECORD pRecord
+)
+{
+ while(pRecord)
+ {
+ pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
+ ,CM_QUERYRECORD
+ ,MPFROMP(pRecord)
+ ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
+ ));
+ if (pRecord)
+ pRecord->m_ulItemId++;
+ }
+} // end of BumpRecordIds
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GetInternalData
+//
+// Get the internal data given a handle and an id
+//
+// PARAMETERS
+// hWnd -- window handle to the control in which item is located
+// lItemId -- ID to get
+//
+// RETURN VALUE
+// pointer to the internal data
+//
+// Note:
+// Under OS/2 PM a container item cannot be obtained via a simple index or
+// id retrieval. We have to walk the record list if we are looking for
+// a record at a specific index location
+/////////////////////////////////////////////////////////////////////////////
+CListItemInternalData* GetInternalData (
+ HWND hWnd
+, long lItemId
+)
+{
+ PMYRECORD pRecord = FindOS2ListRecordByID( hWnd
+ ,lItemId
+ );
+ //
+ // Internal user data is stored AFTER the last field of the RECORDCORE
+ //
+ if (!pRecord)
+ return NULL;
+ return((CListItemInternalData *)(pRecord->m_ulUserData));
+} // end of GetInternalData
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// GetInternalData
+//
+// Get the internal data given a pointer to a list control and an id
+//
+// PARAMETERS
+// pCtl -- pointer to control inwhich item is located
+// lItemId -- ID to get
+//
+// RETURN VALUE
+// pointer to the internal data
+//
+/////////////////////////////////////////////////////////////////////////////
+CListItemInternalData* GetInternalData (
+ wxListCtrl* pCtl
+, long lItemId
+)
+{
+ return(GetInternalData( (HWND)pCtl->GetHWND()
+ ,lItemId
+ ));
+} // end of GetInternalData
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DeleteInternalData
+//
+// Delete the internal data for a record
+//
+// PARAMETERS
+// pCtl -- pointer to the list control containing the record
+// lItemId -- the record index to delete the internal data from
+//
+// RETURN VALUE
+// pointer to the internal data attribute
+//
+/////////////////////////////////////////////////////////////////////////////
+void DeleteInternalData (
+ wxListCtrl* pCtl
+, long lItemId
+)
+{
+ CListItemInternalData* pData = GetInternalData( pCtl
+ ,lItemId
+ );
+ if (pData)
+ {
+ if (pData->m_pMyRecord)
+ pData->m_pMyRecord->m_ulUserData = 0;
+ delete pData;
+ }
+} // end of DeleteInternalData
+
+// #pragma page "GetInternalDataAttr"
+/////////////////////////////////////////////////////////////////////////////
+//
+// GetInternalDataAttr
+//
+// Get the internal data item attribute given a pointer to a list control
+// and an id
+//
+// PARAMETERS
+// pCtl -- pointer to control to set
+// lItemId -- ID to set
+//
+// RETURN VALUE
+// pointer to the internal data attribute
+//
+/////////////////////////////////////////////////////////////////////////////
+wxListItemAttr* GetInternalDataAttr (
+ wxListCtrl* pCtl
+, long lItemId
+)
+{
+ CListItemInternalData* pData = GetInternalData( pCtl
+ ,lItemId
+ );
+
+ if (pData)
+ return(pData->m_pAttr);
+ else
+ return NULL;
+} // end of GetInternalDataAttr
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// InternalDataCompareFunc
+//
+// This is compare function we pass to PM. It wraps the real compare
+// function in SInternalDataSort
+//
+// PARAMETERS
+// p1 -- is the first record structure to compare
+// p2 -- is the second record structure to compare
+// lStorage -- is the same value as passed to SortItems.
+//
+// RETURN VALUE
+// pointer to the internal data attribute
+//
+/////////////////////////////////////////////////////////////////////////////
+SHORT EXPENTRY InternalDataCompareFunc (
+ PMYRECORD p1
+, PMYRECORD p2
+, PVOID pStorage
+)
+{
+ SInternalDataSort* pInternalData = (SInternalDataSort *)pStorage;
+ CListItemInternalData* pData1 = (CListItemInternalData *)p1->m_ulUserData;
+ CListItemInternalData* pData2 = (CListItemInternalData *)p2->m_ulUserData;
+ long lD1 = (pData1 == NULL ? 0 : (long)pData1->m_lParam);
+ long lD2 = (pData2 == NULL ? 0 : (long)pData2->m_lParam);
+
+ return(pInternalData->m_fnUser( lD1
+ ,lD2
+ ,pInternalData->m_lData
+ ));
+} // end of InternalDataCompareFunc
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// ConvertFromOS2ListItem
+//
+// Convert from an internal PM List item to a Toolkit List item
+//
+// PARAMETERS
+// hWndListCtrl -- the control's windows handle
+// rInfo -- the library list control to convert to
+// pRecord -- the OS list control to convert from
+//
+// RETURN VALUE
+// none
+//
+/////////////////////////////////////////////////////////////////////////////
+void ConvertFromOS2ListItem ( HWND hWndListCtrl,
+ wxListItem& rInfo,
+ PMYRECORD pRecord )
+{
+ CListItemInternalData* pInternaldata = (CListItemInternalData *)pRecord->m_ulUserData;
+ bool bNeedText = false;
+
+ if (pInternaldata)
+ rInfo.SetData(pInternaldata->m_lParam);
+
+ rInfo.SetMask(0);
+ rInfo.SetState(0);
+ rInfo.SetStateMask(0);
+ rInfo.SetId((long)pRecord->m_ulItemId);
+ if (hWndListCtrl != 0)
+ {
+ pRecord = FindOS2ListRecordByID( hWndListCtrl
+ ,rInfo.GetId()
+ );
+ }
+
+ //
+ // The wxListItem class is really set up to handle the WIN32 list item
+ // and OS/2 are not as complicated. Just set both state members to the
+ // same thing under OS/2
+ //
+ if (pRecord->m_vRecord.flRecordAttr & CRA_DROPONABLE)
+ {
+ rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DROPHILITED);
+ rInfo.SetState(rInfo.m_state | wxLIST_STATE_DROPHILITED);
+ }
+ if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED)
+ {
+ rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SELECTED);
+ rInfo.SetState(rInfo.m_state | wxLIST_STATE_SELECTED);
+ }
+ if (pRecord->m_vRecord.flRecordAttr & CRA_DISABLED)
+ {
+ rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DISABLED);
+ rInfo.SetState(rInfo.m_state | wxLIST_STATE_DISABLED);
+ }
+ if (pRecord->m_vRecord.flRecordAttr & CRA_FILTERED)
+ {
+ rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_FILTERED);
+ rInfo.SetState(rInfo.m_state | wxLIST_STATE_FILTERED);
+ }
+ if (pRecord->m_vRecord.flRecordAttr & CRA_INUSE)
+ {
+ rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_INUSE);
+ rInfo.SetState(rInfo.m_state | wxLIST_STATE_INUSE);
+ }
+ if (pRecord->m_vRecord.flRecordAttr & CRA_PICKED)
+ {
+ rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_PICKED);
+ rInfo.SetState(rInfo.m_state | wxLIST_STATE_PICKED);
+ }
+ if (pRecord->m_vRecord.flRecordAttr & CRA_SOURCE)
+ {
+ rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SOURCE);
+ rInfo.SetState(rInfo.m_state | wxLIST_STATE_SOURCE);
+ }
+
+ if (pRecord->m_vRecord.pszText != (PSZ)NULL)
+ {
+ rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_TEXT);
+ rInfo.SetText(pRecord->m_vRecord.pszText);
+ }
+ if (pRecord->m_vRecord.pszIcon != (PSZ)NULL ||
+ pRecord->m_vRecord.pszName != (PSZ)NULL)
+ {
+ rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_IMAGE);
+ rInfo.SetImage(pRecord->m_vRecord.hptrIcon);
+ }
+ if (pRecord->m_ulUserData)
+ rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_DATA);
+} // end of ConvertFromOS2ListItem
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// ConvertToOS2Flags
+//
+// Convert from an library states to OS states
+//
+// PARAMETERS
+// lState -- the state
+// pRecord -- the OS list control to use
+//
+// RETURN VALUE
+// none
+//
+/////////////////////////////////////////////////////////////////////////////
+void ConvertToOS2Flags (
+ long lState
+, PMYRECORD pRecord
+)
+{
+ if (lState & wxLIST_STATE_DROPHILITED)
+ pRecord->m_vRecord.flRecordAttr |= CRA_DROPONABLE;
+ if (lState & wxLIST_STATE_SELECTED)
+ pRecord->m_vRecord.flRecordAttr |= CRA_SELECTED;
+ if (lState & wxLIST_STATE_DISABLED)
+ pRecord->m_vRecord.flRecordAttr |= CRA_DISABLED;
+ if (lState & wxLIST_STATE_FILTERED)
+ pRecord->m_vRecord.flRecordAttr |= CRA_FILTERED;
+ if (lState & wxLIST_STATE_INUSE)
+ pRecord->m_vRecord.flRecordAttr |= CRA_INUSE;
+ if (lState & wxLIST_STATE_PICKED)
+ pRecord->m_vRecord.flRecordAttr |= CRA_PICKED;
+ if (lState & wxLIST_STATE_SOURCE)
+ pRecord->m_vRecord.flRecordAttr |= CRA_SOURCE;
+} // end of ConvertToOS2Flags
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// ConvertToOS2ListItem
+//
+// Convert from a library List item to an internal OS2 List item. We set
+// only the fields we need to set. Some of them are set by the API when
+// they are added to the container.
+//
+// PARAMETERS
+// pCtrl -- the control to use
+// rInfo -- the item to convert
+// pRecord -- the OS list control to use, should be zeroed out
+// pFieldinfo -- a field struct that may contain columnar data for detail view
+//
+// RETURN VALUE
+// none
+//
+/////////////////////////////////////////////////////////////////////////////
+void ConvertToOS2ListItem (
+ const wxListCtrl* pCtrl
+, const wxListItem& rInfo
+, PMYRECORD pRecord
+, PFIELDINFO pFieldInfo
+)
+{
+ pRecord->m_ulItemId = (ULONG)rInfo.GetId();
+ pRecord->m_vRecord.cb = sizeof(RECORDCORE);
+ if (rInfo.GetMask() & wxLIST_MASK_STATE)
+ {
+ ConvertToOS2Flags( rInfo.m_state
+ ,pRecord
+ );
+ }
+ if (pCtrl->GetWindowStyleFlag() & wxLC_ICON ||
+ pCtrl->GetWindowStyleFlag() & wxLC_SMALL_ICON)
+ {
+ pRecord->m_vRecord.pszIcon = (char*)rInfo.GetText().c_str();
+ }
+ if (pCtrl->GetWindowStyleFlag() & wxLC_LIST) // PM TEXT view
+ {
+ pRecord->m_vRecord.pszText = (char*)rInfo.GetText().c_str();
+ }
+ //
+ // In the case of a report view the text will be the data in the lead column
+ // ???? Don't know why, but that is how it works in other ports.
+ //
+ if (pCtrl->GetWindowStyleFlag() & wxLC_REPORT)
+ {
+ if (pFieldInfo)
+ {
+ switch(rInfo.GetColumn())
+ {
+ case 0:
+ pRecord->m_pzColumn1 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn1);
+ break;
+
+ case 1:
+ pRecord->m_pzColumn2 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn2);
+ break;
+
+ case 2:
+ pRecord->m_pzColumn3 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn3);
+ break;
+
+ case 3:
+ pRecord->m_pzColumn4 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn4);
+ break;
+
+ case 4:
+ pRecord->m_pzColumn5 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn5);
+ break;
+
+ case 5:
+ pRecord->m_pzColumn6 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn6);
+ break;
+
+ case 6:
+ pRecord->m_pzColumn7 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn7);
+ break;
+
+ case 7:
+ pRecord->m_pzColumn8 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn8);
+ break;
+
+ case 8:
+ pRecord->m_pzColumn9 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn9);
+ break;
+
+ case 9:
+ pRecord->m_pzColumn10 = (char*)rInfo.GetText().c_str();
+ pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn10);
+ break;
+
+ default:
+ wxFAIL_MSG( _T("wxOS2 does not support more than 10 columns in REPORT view") );
+ break;
+ }
}
+ }
+ if (rInfo.GetMask() & wxLIST_MASK_IMAGE)
+ {
+ pRecord->m_vRecord.hptrIcon = (HPOINTER)rInfo.GetImage();
+ pRecord->m_vRecord.hptrMiniIcon = (HPOINTER)rInfo.m_miniImage;
+ }
+} // end of ConvertToOS2ListItem
- if ( flag & style )
- {
- if ( !add )
- flag -= style;
- }
- else
- {
- if ( add )
- {
- flag |= style;
- }
- }
-
- m_windowStyle = flag;
-
- /* TODO RecreateWindow(); */
-}
+/////////////////////////////////////////////////////////////////////////////
+//
+// ConvertToOS2ListCol
+//
+// Convert from a library List column to an internal PM List column
+//
+// PARAMETERS
+// lCol -- the columnd to convert
+// rItem -- the item to convert
+// pField -- the OS list column to use
+//
+// RETURN VALUE
+// none
+//
+/////////////////////////////////////////////////////////////////////////////
+void ConvertToOS2ListCol (
+ long lCol
+, const wxListItem& rItem
+, PFIELDINFO pField
+)
+{
+ memset(pField, '\0', sizeof(FIELDINFO));
+ pField->cb = sizeof(FIELDINFO);
+
+ //
+ // Default some settings
+ //
+ pField->flData = CFA_HORZSEPARATOR | CFA_SEPARATOR;
+ pField->flTitle = CFA_CENTER;
+
+ if (rItem.GetMask() & wxLIST_MASK_TEXT)
+ {
+ pField->flData |= CFA_STRING;
+ pField->pTitleData = (PVOID)rItem.GetText().c_str(); // text is column title not data
+ }
+ if (rItem.GetMask() & wxLIST_MASK_FORMAT)
+ {
+ if (rItem.m_format == wxLIST_FORMAT_LEFT)
+ pField->flData |= CFA_LEFT;
+ else if (rItem.m_format == wxLIST_FORMAT_RIGHT)
+ pField->flData |= CFA_RIGHT;
+ else if (rItem.m_format == wxLIST_FORMAT_CENTRE)
+ pField->flData |= CFA_CENTER;
+ }
+ else
+ pField->flData |= CFA_CENTER; // Just ensure the default is centered
+ if (rItem.GetMask() & wxLIST_MASK_WIDTH)
+ {
+ if (!(rItem.GetWidth() == wxLIST_AUTOSIZE ||
+ rItem.GetWidth() == wxLIST_AUTOSIZE_USEHEADER))
+ pField->cxWidth = rItem.GetWidth();
+ // else: OS/2 automatically sets the width if created with the approppriate style
+ }
+
+ //
+ // Still need to set the actual data
+ //
+ pField->offStruct = 0;
+} // end of ConvertToOS2ListCol
+
+
+IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
+IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
+IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
+
+IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
+
+BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
+ EVT_PAINT(wxListCtrl::OnPaint)
+END_EVENT_TABLE()
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxListCtrl construction
+// ----------------------------------------------------------------------------
+
+void wxListCtrl::Init ()
+{
+ m_pImageListNormal = NULL;
+ m_pImageListSmall = NULL;
+ m_pImageListState = NULL;
+ m_bOwnsImageListNormal = false;
+ m_bOwnsImageListSmall = false;
+ m_bOwnsImageListState = false;
+ m_lBaseStyle = 0L;
+ m_nColCount = 0;
+ m_pTextCtrl = NULL;
+ m_bAnyInternalData = false;
+ m_bHasAnyAttr = false;
+} // end of wxListCtrl::Init
+
+bool wxListCtrl::Create ( wxWindow* pParent,
+ wxWindowID vId,
+ const wxPoint& rPos,
+ const wxSize& rSize,
+ long lStyle,
+ const wxValidator& rValidator,
+ const wxString& rsName )
+{
+ int nX = rPos.x;
+ int nY = rPos.y;
+ int nWidth = rSize.x;
+ int nHeight = rSize.y;
+
+#if wxUSE_VALIDATORS
+ SetValidator(rValidator);
+#endif // wxUSE_VALIDATORS
+
+ SetName(rsName);
+ SetWindowStyleFlag(lStyle);
+ SetParent(pParent);
+ if (nWidth <= 0)
+ nWidth = 100;
+ if (nHeight <= 0)
+ nHeight = 30;
+ if (nX < 0)
+ nX = 0;
+ if (nY < 0)
+ nY = 0;
+
+ m_windowId = (vId == -1) ? NewControlId() : vId;
+
+ long lSstyle = WS_VISIBLE | WS_TABSTOP;
+
+ if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
+ lSstyle |= WS_CLIPSIBLINGS;
+ m_lBaseStyle = lSstyle;
+ if (!DoCreateControl( nX
+ ,nY
+ ,nWidth
+ ,nHeight
+ ))
+ return false;
+ if (pParent)
+ pParent->AddChild(this);
+ return true;
+} // end of wxListCtrl::Create
+
+bool wxListCtrl::DoCreateControl ( int nX, int nY,
+ int nWidth, int nHeight )
+{
+ DWORD lWstyle = m_lBaseStyle;
+ long lOldStyle = 0; // Dummy
+
+ CNRINFO vCnrInfo;
+
+ lWstyle |= ConvertToOS2Style( lOldStyle
+ ,GetWindowStyleFlag()
+ );
+
+ m_hWnd = (WXHWND)::WinCreateWindow( GetParent()->GetHWND()
+ ,WC_CONTAINER
+ ,NULL
+ ,m_lBaseStyle
+ ,0, 0, 0, 0
+ ,GetParent()->GetHWND()
+ ,HWND_BOTTOM
+ ,(ULONG)m_windowId
+ ,NULL
+ ,NULL
+ );
+ if (!m_hWnd)
+ {
+ return false;
+ }
+
+ //
+ // Now set the display attributes of the container
+ //
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return false;
+ lWstyle = ConvertViewToOS2Style(GetWindowStyleFlag());
+ vCnrInfo.flWindowAttr |= lWstyle;
+ if (!::WinSendMsg( GetHWND()
+ ,CM_SETCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)CMA_FLWINDOWATTR
+ ))
+ return false;
+
+ //
+ // And now set needed arrangement flags
+ //
+ lWstyle = ConvertArrangeToOS2Style(GetWindowStyleFlag());
+ if (!::WinSendMsg( GetHWND()
+ ,CM_ARRANGE
+ ,(MPARAM)CMA_ARRANGEGRID
+ ,(MPARAM)lWstyle
+ ))
+ return false;
+ SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ SetForegroundColour(GetParent()->GetForegroundColour());
+ SubclassWin(m_hWnd);
+ SetFont(*wxSMALL_FONT);
+ SetXComp(0);
+ SetYComp(0);
+ SetSize( nX, nY, nWidth, nHeight );
+ return true;
+} // end of wxListCtrl::DoCreateControl
+
+void wxListCtrl::UpdateStyle ()
+{
+ if (GetHWND())
+ {
+ long lDummy;
+ DWORD dwStyleNew = ConvertToOS2Style( lDummy, GetWindowStyleFlag() );
+
+ dwStyleNew |= m_lBaseStyle;
+
+ //
+ // Get the current window style.
+ //
+ ULONG dwStyleOld = ::WinQueryWindowULong(GetHWND(), QWL_STYLE);
+
+ //
+ // Only set the window style if the view bits have changed.
+ //
+ if (dwStyleOld != dwStyleNew)
+ {
+ ::WinSetWindowULong(GetHWND(), QWL_STYLE, dwStyleNew);
+ }
+ }
+} // end of wxListCtrl::UpdateStyle
+
+void wxListCtrl::FreeAllInternalData ()
+{
+ if (m_bAnyInternalData)
+ {
+ int n = GetItemCount();
+ int i = 0;
+
+ for (i = 0; i < n; i++)
+ DeleteInternalData(this, (long)i);
+ m_bAnyInternalData = false;
+ }
+} // end of wxListCtrl::FreeAllInternalData
+
+wxListCtrl::~wxListCtrl ()
+{
+ FreeAllInternalData();
+ if (m_pTextCtrl )
+ {
+ m_pTextCtrl->SetHWND(0);
+ m_pTextCtrl->UnsubclassWin();
+ delete m_pTextCtrl;
+ m_pTextCtrl = NULL;
+ }
+
+ if (m_bOwnsImageListNormal)
+ delete m_pImageListNormal;
+ if (m_bOwnsImageListSmall)
+ delete m_pImageListSmall;
+ if (m_bOwnsImageListState)
+ delete m_pImageListState;
+} // end of wxListCtrl::~wxListCtrl
+
+// ----------------------------------------------------------------------------
+// set/get/change style
+// ----------------------------------------------------------------------------
+
+// Add or remove a single window style
+void wxListCtrl::SetSingleStyle (
+ long lStyle
+, bool bAdd
+)
+{
+ long lFlag = GetWindowStyleFlag();
+
+ //
+ // Get rid of conflicting styles
+ //
+ if (bAdd)
+ {
+ if (lStyle & wxLC_MASK_TYPE)
+ lFlag = lFlag & ~wxLC_MASK_TYPE;
+ if (lStyle & wxLC_MASK_ALIGN )
+ lFlag = lFlag & ~wxLC_MASK_ALIGN;
+ if (lStyle & wxLC_MASK_SORT )
+ lFlag = lFlag & ~wxLC_MASK_SORT;
+ }
+ if (lFlag & lStyle)
+ {
+ if (!bAdd)
+ lFlag -= lStyle;
+ }
+ else
+ {
+ if (bAdd)
+ {
+ lFlag |= lStyle;
+ }
+ }
+ m_windowStyle = lFlag;
+ UpdateStyle();
+} // end of wxListCtrl::SetSingleStyle
// Set the whole window style
-void wxListCtrl::SetWindowStyleFlag(long flag)
+void wxListCtrl::SetWindowStyleFlag (
+ long lFlag
+)
+{
+ m_windowStyle = lFlag;
+ UpdateStyle();
+} // end of wxListCtrl::SetWindowStyleFlag
+
+long wxListCtrl::ConvertToOS2Style (
+ long& rOldStyle
+, long lStyle
+) const
{
- m_windowStyle = flag;
+ long lWstyle = 0L;
+
+ //
+ // The only styles OS2 uses on creation are auto arrange, read only, and
+ // and selection styles. This lib does not support OS/2 MINIRECORDCORE
+ // or VERIFYPOINTER styles
+ //
+ if (lStyle & wxLC_AUTOARRANGE)
+ lWstyle |= CCS_AUTOPOSITION;
+ if (lStyle & wxLC_SINGLE_SEL)
+ lWstyle |= CCS_SINGLESEL;
+ else
+ lWstyle |= CCS_EXTENDSEL;
+ if (!(lStyle & wxLC_EDIT_LABELS))
+ lWstyle |= CCS_READONLY;
+ return lWstyle;
+} // end of wxListCtrl::ConvertToOS2Style
+
+long wxListCtrl::ConvertArrangeToOS2Style (
+ long lStyle
+)
+{
+ long lWstyle = 0;
- /* TODO RecreateWindow(); */
-}
+ if (lStyle & wxLC_ALIGN_LEFT)
+ {
+ lWstyle |= CMA_LEFT;
+ }
+
+ if (lStyle & wxLC_ALIGN_TOP)
+ {
+ lWstyle |= CMA_TOP;
+ }
+ return lWstyle;
+} // end of wxListCtrl::ConvertArrangeToOS2Style
+
+long wxListCtrl::ConvertViewToOS2Style (
+ long lStyle
+)
+{
+ long lWstyle = CA_DRAWICON; // we will only use icons
+
+ if (lStyle & wxLC_ICON)
+ {
+ lWstyle |= CV_ICON;
+ }
+ if (lStyle & wxLC_SMALL_ICON)
+ {
+ lWstyle |= (CV_ICON | CV_MINI);
+ }
+ if (lStyle & wxLC_LIST)
+ {
+ lWstyle |= CV_TEXT;
+ }
+ if (lStyle & wxLC_REPORT)
+ {
+ lWstyle |= CV_DETAIL;
+ }
+ if (lStyle & wxLC_VIRTUAL)
+ {
+ lWstyle |= CA_OWNERDRAW;
+ }
+ if (lStyle & wxLC_AUTOARRANGE)
+ {
+ lWstyle |= CV_FLOW;
+ }
+ if (!(lStyle & wxLC_NO_HEADER))
+ {
+ lWstyle |= CA_DETAILSVIEWTITLES;
+ }
+ return lWstyle;
+} // end of wxListCtrl::ConvertViewToOS2Style
+
+// ----------------------------------------------------------------------------
+// accessors
+// ----------------------------------------------------------------------------
+
+// Sets the foreground, i.e. text, colour
+bool wxListCtrl::SetForegroundColour (const wxColour& rCol)
+{
+ ULONG ulColor = wxColourToRGB(rCol);
+
+ if (!wxWindow::SetForegroundColour(rCol))
+ return false;
+
+ ::WinSetPresParam( GetHWND()
+ ,PP_FOREGROUNDCOLOR
+ ,sizeof(ULONG)
+ ,&ulColor
+ );
+ return true;
+} // end of wxListCtrl::SetForegroundColour
+// Sets the background colour
+bool wxListCtrl::SetBackgroundColour ( const wxColour& rCol )
+{
+ if (!wxWindow::SetBackgroundColour(rCol))
+ return false;
+
+ //
+ // We set the same colour for both the "empty" background and the items
+ // background
+ //
+ ULONG ulColor = wxColourToRGB(rCol);
+
+ ::WinSetPresParam( GetHWND()
+ ,PP_BACKGROUNDCOLOR
+ ,sizeof(ULONG)
+ ,&ulColor
+ );
+ return true;
+} // end of wxListCtrl::SetBackgroundColour
// Gets information about this column
-bool wxListCtrl::GetColumn(int col, wxListItem& item) const
+bool wxListCtrl::GetColumn ( int nCol, wxListItem& rItem ) const
{
- // TODO
- return FALSE;
-}
+ PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
+
+ if (!pFieldInfo)
+ return false;
+ rItem.SetWidth(pFieldInfo->cxWidth);
+ if ((rItem.GetMask() & wxLIST_MASK_TEXT) &&
+ (pFieldInfo->flData & CFA_STRING) &&
+ (pFieldInfo->pUserData != NULL))
+ {
+ rItem.SetText((char*)pFieldInfo->pUserData);
+ }
+ if (rItem.GetMask() & wxLIST_MASK_FORMAT )
+ {
+ if (pFieldInfo->flData & CFA_LEFT)
+ rItem.m_format = wxLIST_FORMAT_LEFT;
+ else if (pFieldInfo->flData & CFA_RIGHT)
+ rItem.m_format = wxLIST_FORMAT_RIGHT;
+ else if (pFieldInfo->flData & CFA_CENTER)
+ rItem.m_format = wxLIST_FORMAT_CENTRE;
+ }
+ return true;
+} // end of wxListCtrl::GetColumn
// Sets information about this column
-bool wxListCtrl::SetColumn(int col, wxListItem& item)
+bool wxListCtrl::SetColumn ( int nCol, wxListItem& rItem )
{
- // TODO
- return FALSE;
-}
+ PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
+ ConvertToOS2ListCol( nCol, rItem, pFieldInfo );
+ //
+ // Since we changed the field pointed to, we invalidate to see the result
+ //
+ ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
+ return true;
+} // end of wxListCtrl::SetColumn
// Gets the column width
-int wxListCtrl::GetColumnWidth(int col) const
+int wxListCtrl::GetColumnWidth ( int nCol ) const
{
- // TODO
- return 0;
-}
+ PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
+
+ if (!pFieldInfo)
+ return 0;
+ return((int)pFieldInfo->cxWidth);
+} // end of wxListCtrl::GetColumnWidth
// Sets the column width
-bool wxListCtrl::SetColumnWidth(int col, int width)
+bool wxListCtrl::SetColumnWidth ( int nCol, int nWidth )
{
- // TODO
- return FALSE;
-}
+ int nCol2 = nCol;
+ int nWidth2 = nWidth;
+
+ if (GetWindowStyleFlag() & wxLC_LIST)
+ nCol2 = -1;
+
+ PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
+ pFieldInfo->cxWidth = nWidth;
+ ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
+ return true;
+} // end of wxListCtrl::SetColumnWidth
// Gets the number of items that can fit vertically in the
// visible area of the list control (list or report view)
// or the total number of items in the list control (icon
// or small icon view)
-int wxListCtrl::GetCountPerPage() const
+int wxListCtrl::GetCountPerPage () const
{
- // TODO
- return 0;
-}
+ QUERYRECORDRECT vQueryRect;
+ CNRINFO vCnrInfo;
+ RECTL vRectRecord;
+ RECTL vRectControl;
+ int nCount;
+
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return 0;
+ memset(&vQueryRect, '\0', sizeof(QUERYRECORDRECT));
+ vQueryRect.cb = sizeof(QUERYRECORDRECT);
+ if (vCnrInfo.flWindowAttr & CV_ICON)
+ vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
+ else if (vCnrInfo.flWindowAttr & CV_NAME)
+ vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
+ else if (vCnrInfo.flWindowAttr & CV_TEXT)
+ vQueryRect.fsExtent = CMA_TEXT;
+ else if (vCnrInfo.flWindowAttr & CV_DETAIL)
+ vQueryRect.fsExtent = CMA_TEXT;
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDRECT
+ ,MPFROMP(&vRectRecord)
+ ,MPFROMP(&vQueryRect)
+ ))
+ return 0;
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYVIEWPORTRECT
+ ,MPFROMP(&vRectControl)
+ ,MPFROM2SHORT(CMA_WINDOW, (USHORT)FALSE)
+ ))
+ return 0;
+ nCount = (int)((int)((vRectControl.xRight - vRectControl.xLeft) / (vRectRecord.xRight - vRectRecord.xLeft)) *
+ (int)((vRectControl.yTop - vRectControl.yBottom) / (vRectRecord.yTop - vRectRecord.yBottom))
+ );
+ if (nCount > (int)vCnrInfo.cFields)
+ nCount = (int)vCnrInfo.cFields;
+ return nCount;
+} // end of wxListCtrl::GetCountPerPage
// Gets the edit control for editing labels.
wxTextCtrl* wxListCtrl::GetEditControl() const
{
- return m_textCtrl;
+ return m_pTextCtrl;
}
// Gets information about the item
-bool wxListCtrl::GetItem(wxListItem& info) const
+bool wxListCtrl::GetItem ( wxListItem& rInfo ) const
{
- // TODO
- return FALSE;
-}
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
+
+ //
+ // Give NULL as hwnd as we already have everything we need
+ //
+ ConvertFromOS2ListItem( NULL, rInfo, pRecord );
+ return true;
+} // end of wxListCtrl::GetItem
// Sets information about the item
-bool wxListCtrl::SetItem(wxListItem& info)
+bool wxListCtrl::SetItem ( wxListItem& rInfo )
{
- // TODO
- return FALSE;
-}
-
-long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
-{
- wxListItem info;
- info.m_text = label;
- info.m_mask = wxLIST_MASK_TEXT;
- info.m_itemId = index;
- info.m_col = col;
- if ( imageId > -1 )
- {
- info.m_image = imageId;
- info.m_mask |= wxLIST_MASK_IMAGE;
- }
- return SetItem(info);
-}
+ PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), rInfo.GetColumn() );
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
+
+ ConvertToOS2ListItem( this
+ ,rInfo
+ ,pRecord
+ ,pFieldInfo
+ );
+
+ //
+ // Check if setting attributes or lParam
+ //
+ if (rInfo.HasAttributes() || (rInfo.GetMask() & wxLIST_MASK_DATA))
+ {
+ //
+ // Get internal item data
+ // perhaps a cache here ?
+ //
+ CListItemInternalData* pData = GetInternalData( this
+ ,rInfo.GetId()
+ );
+
+ if (!pData)
+ {
+ //
+ // Need to set it
+ //
+ m_bAnyInternalData = true;
+ pData = new CListItemInternalData();
+ pRecord->m_ulUserData = (unsigned long)pData;
+ };
+
+ //
+ // User data
+ //
+ if (rInfo.GetMask() & wxLIST_MASK_DATA)
+ pData->m_lParam = (WXLPARAM)rInfo.GetData();
+
+ // attributes
+ if (rInfo.HasAttributes())
+ {
+ if (pData->m_pAttr)
+ *pData->m_pAttr = *rInfo.GetAttributes();
+ else
+ pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
+ }
+ pData->m_pMyRecord = pRecord; // they point to each other
+ }
+
+ //
+ // We need to update the item immediately to show the new image
+ //
+ bool bUpdateNow = (rInfo.GetMask() & wxLIST_MASK_IMAGE) != 0;
+
+ //
+ // Check whether it has any custom attributes
+ //
+ if (rInfo.HasAttributes())
+ {
+ m_bHasAnyAttr = true;
+
+ //
+ // If the colour has changed, we must redraw the item
+ //
+ bUpdateNow = true;
+ }
+ if (::WinIsWindowVisible(GetHWND()))
+ {
+ ::WinSendMsg( GetHWND()
+ ,CM_INVALIDATERECORD
+ ,MPFROMP(pRecord)
+ ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
+ );
+ RefreshItem(pRecord->m_ulItemId);
+ }
+ ::WinSendMsg( GetHWND()
+ ,CM_INVALIDATEDETAILFIELDINFO
+ ,NULL
+ ,NULL
+ );
+ return true;
+} // end of wxListCtrl::SetItem
+
+long wxListCtrl::SetItem (
+ long lIndex
+, int nCol
+, const wxString& rsLabel
+, int nImageId
+)
+{
+ wxListItem vInfo;
+ vInfo.m_text = rsLabel;
+ vInfo.m_mask = wxLIST_MASK_TEXT;
+ vInfo.m_itemId = lIndex;
+ vInfo.m_col = nCol;
+ if (nImageId > -1)
+ {
+ vInfo.m_image = nImageId;
+ vInfo.m_mask |= wxLIST_MASK_IMAGE;
+ }
+ return SetItem(vInfo);
+} // end of wxListCtrl::SetItem
// Gets the item state
-int wxListCtrl::GetItemState(long item, long stateMask) const
+int wxListCtrl::GetItemState (
+ long lItem
+, long lStateMask
+) const
{
- wxListItem info;
+ wxListItem vInfo;
- info.m_mask = wxLIST_MASK_STATE ;
- info.m_stateMask = stateMask;
- info.m_itemId = item;
+ vInfo.m_mask = wxLIST_MASK_STATE;
+ vInfo.m_stateMask = lStateMask;
+ vInfo.m_itemId = lItem;
- if (!GetItem(info))
- return 0;
-
- return info.m_state;
-}
+ if (!GetItem(vInfo))
+ return 0;
+ return vInfo.m_state;
+} // end of wxListCtrl::GetItemState
// Sets the item state
-bool wxListCtrl::SetItemState(long item, long state, long stateMask)
+bool wxListCtrl::SetItemState ( long lItem, long lState, long lStateMask )
{
- wxListItem info;
-
- info.m_mask = wxLIST_MASK_STATE ;
- info.m_state = state;
- info.m_stateMask = stateMask;
- info.m_itemId = item;
-
- return SetItem(info);
-}
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
+
+ //
+ // Don't use SetItem() here as it doesn't work with the virtual list
+ // controls
+ //
+ ConvertToOS2Flags( lState, pRecord );
+
+ //
+ // for the virtual list controls we need to refresh the previously focused
+ // item manually when changing focus without changing selection
+ // programmatically because otherwise it keeps its focus rectangle until
+ // next repaint (yet another comctl32 bug)
+ //
+ long lFocusOld;
+
+ if (IsVirtual() &&
+ (lStateMask & wxLIST_STATE_FOCUSED) &&
+ (lState & wxLIST_STATE_FOCUSED) )
+ {
+ lFocusOld = GetNextItem( -1
+ ,wxLIST_NEXT_ALL
+ ,wxLIST_STATE_FOCUSED
+ );
+ }
+ else
+ {
+ lFocusOld = -1;
+ }
+ ::WinSendMsg( GetHWND()
+ ,CM_INVALIDATERECORD
+ ,MPFROMP(pRecord)
+ ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
+ );
+
+ if (lFocusOld != -1)
+ {
+ //
+ // No need to refresh the item if it was previously selected, it would
+ // only result in annoying flicker
+ //
+ if (!(GetItemState( lFocusOld
+ ,wxLIST_STATE_SELECTED
+ ) & wxLIST_STATE_SELECTED))
+ {
+ RefreshItem(lFocusOld);
+ }
+ }
+ return true;
+} // end of wxListCtrl::SetItemState
// Sets the item image
-bool wxListCtrl::SetItemImage(long item, int image, int selImage)
+bool wxListCtrl::SetItemImage (
+ long lItem
+, int nImage
+, int WXUNUSED(nSelImage))
{
- wxListItem info;
+ return SetItemColumnInfo(lItem, 0, nImage);
+} // end of wxListCtrl::SetItemImage
- info.m_mask = wxLIST_MASK_IMAGE ;
- info.m_image = image;
- info.m_itemId = item;
+// Sets the item image
+bool wxListCtrl::SetItemColumnImage (
+ long lItem
+, long lColumn
+, int nImage
+{
+ wxListItem vInfo;
- return SetItem(info);
-}
+ vInfo.m_mask = wxLIST_MASK_IMAGE;
+ vInfo.m_image = nImage;
+ vInfo.m_itemId = lItem;
+ vInfo.m_col = lColumn;
+ return SetItem(vInfo);
+} // end of wxListCtrl::SetItemColumnImage
// Gets the item text
-wxString wxListCtrl::GetItemText(long item) const
+wxString wxListCtrl::GetItemText (
+ long lItem
+) const
{
- wxListItem info;
+ wxListItem vInfo;
- info.m_mask = wxLIST_MASK_TEXT ;
- info.m_itemId = item;
+ vInfo.m_mask = wxLIST_MASK_TEXT;
+ vInfo.m_itemId = lItem;
- if (!GetItem(info))
- return wxString("");
- return info.m_text;
-}
+ if (!GetItem(vInfo))
+ return wxEmptyString;
+ return vInfo.m_text;
+} // end of wxListCtrl::GetItemText
// Sets the item text
-void wxListCtrl::SetItemText(long item, const wxString& str)
+void wxListCtrl::SetItemText (
+ long lItem
+, const wxString& rsStr
+)
{
- wxListItem info;
+ wxListItem vInfo;
- info.m_mask = wxLIST_MASK_TEXT ;
- info.m_itemId = item;
- info.m_text = str;
-
- SetItem(info);
-}
+ vInfo.m_mask = wxLIST_MASK_TEXT;
+ vInfo.m_itemId = lItem;
+ vInfo.m_text = rsStr;
+ SetItem(vInfo);
+} // end of wxListCtrl::SetItemText
// Gets the item data
-long wxListCtrl::GetItemData(long item) const
+long wxListCtrl::GetItemData (
+ long lItem
+) const
{
- wxListItem info;
+ wxListItem vInfo;
- info.m_mask = wxLIST_MASK_DATA ;
- info.m_itemId = item;
-
- if (!GetItem(info))
- return 0;
- return info.m_data;
-}
+ vInfo.m_mask = wxLIST_MASK_DATA;
+ vInfo.m_itemId = lItem;
+ if (!GetItem(vInfo))
+ return 0;
+ return vInfo.m_data;
+} // end of wxListCtrl::GetItemData
// Sets the item data
-bool wxListCtrl::SetItemData(long item, long data)
+bool wxListCtrl::SetItemData (
+ long lItem
+, long lData
+)
{
- wxListItem info;
+ wxListItem vInfo;
- info.m_mask = wxLIST_MASK_DATA ;
- info.m_itemId = item;
- info.m_data = data;
-
- return SetItem(info);
-}
+ vInfo.m_mask = wxLIST_MASK_DATA;
+ vInfo.m_itemId = lItem;
+ vInfo.m_data = lData;
+ return SetItem(vInfo);
+} // end of wxListCtrl::SetItemData
// Gets the item rectangle
-bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const
+bool wxListCtrl::GetItemRect ( long lItem,
+ wxRect& rRect,
+ int nCode ) const
{
- // TODO
- return FALSE;
-}
+ bool bSuccess;
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
+ QUERYRECORDRECT vQueryRect;
+ RECTL vRect;
+ int nHeight;
+
+ if (!pRecord)
+ return false;
+ vQueryRect.cb = sizeof(QUERYRECORDRECT);
+ vQueryRect.pRecord = &pRecord->m_vRecord;
+ vQueryRect.fRightSplitWindow = TRUE;
+ vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
+ ::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDRECT
+ ,MPFROMP(&vRect)
+ ,MPFROMP(&vQueryRect)
+ );
+ //
+ // remember OS/2 is backwards
+ //
+ GetClientSize( NULL, &nHeight );
+ rRect.x = vRect.xLeft;
+ rRect.y = nHeight - vRect.yTop;
+ rRect.width = vRect.xRight;
+ rRect.height = nHeight - vRect.yBottom;
+ bSuccess = true;
+ return bSuccess;
+} // end of wxListCtrl::GetItemRect
// Gets the item position
-bool wxListCtrl::GetItemPosition(long item, wxPoint& pos) const
+bool wxListCtrl::GetItemPosition ( long lItem, wxPoint& rPos ) const
{
- // TODO
- return FALSE;
-}
+ bool bSuccess;
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND() , lItem );
+ QUERYRECORDRECT vQueryRect;
+ RECTL vRect;
+ int nHeight;
+
+ if (!pRecord)
+ return false;
+ vQueryRect.cb = sizeof(QUERYRECORDRECT);
+ vQueryRect.pRecord = &pRecord->m_vRecord;
+ vQueryRect.fRightSplitWindow = TRUE;
+ vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
+ ::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDRECT
+ ,MPFROMP(&vRect)
+ ,MPFROMP(&vQueryRect)
+ );
+ //
+ // remember OS/2 is backwards
+ //
+ GetClientSize( NULL, &nHeight );
+ rPos.x = vRect.xLeft;
+ rPos.y = nHeight - vRect.yTop;
+ bSuccess = true;
+ return bSuccess;
+} // end of wxListCtrl::GetItemPosition
// Sets the item position.
-bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos)
+bool wxListCtrl::SetItemPosition ( long lItem, const wxPoint& rPos )
{
- // TODO
- return FALSE;
-}
+ //
+ // Items cannot be positioned in X/Y coord in OS/2
+ //
+ return false;
+} // end of wxListCtrl::SetItemPosition
// Gets the number of items in the list control
-int wxListCtrl::GetItemCount() const
+int wxListCtrl::GetItemCount () const
{
- // TODO
- return FALSE;
-}
+ CNRINFO vCnrInfo;
+
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return -1;
+ return vCnrInfo.cRecords;
+} // end of wxListCtrl::GetItemCount
// Retrieves the spacing between icons in pixels.
-// If small is TRUE, gets the spacing for the small icon
+// If bIsSmall is true, gets the spacing for the small icon
// view, otherwise the large icon view.
-int wxListCtrl::GetItemSpacing(bool isSmall) const
+int wxListCtrl::GetItemSpacing ( bool bIsSmall ) const
{
- // TODO
- return FALSE;
-}
+ CNRINFO vCnrInfo;
+
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return -1;
+ return vCnrInfo.cyLineSpacing;
+} // end of wxListCtrl::GetItemSpacing
+
+void wxListCtrl::SetItemTextColour (
+ long lItem
+, const wxColour& rCol
+)
+{
+ wxListItem vInfo;
+
+ vInfo.m_itemId = lItem;
+ vInfo.SetTextColour(rCol);
+ SetItem(vInfo);
+} // end of wxListCtrl::SetItemTextColour
+
+wxColour wxListCtrl::GetItemTextColour (
+ long lItem
+) const
+{
+ wxListItem vInfo;
+
+ vInfo.m_itemId = lItem;
+ GetItem(vInfo);
+ return vInfo.GetTextColour();
+} // end of wxListCtrl::GetItemTextColour
+
+void wxListCtrl::SetItemBackgroundColour (
+ long lItem
+, const wxColour& rCol
+)
+{
+ wxListItem vInfo;
+
+ vInfo.m_itemId = lItem;
+ vInfo.SetBackgroundColour(rCol);
+ SetItem(vInfo);
+} // end of wxListCtrl::SetItemBackgroundColour
+
+wxColour wxListCtrl::GetItemBackgroundColour (
+ long lItem
+) const
+{
+ wxListItem vInfo;
+
+ vInfo.m_itemId = lItem;
+ GetItem(vInfo);
+ return vInfo.GetBackgroundColour();
+} // end of wxListCtrl::GetItemBackgroundColour
// Gets the number of selected items in the list control
-int wxListCtrl::GetSelectedItemCount() const
+int wxListCtrl::GetSelectedItemCount () const
{
- // TODO
- return FALSE;
-}
+ PMYRECORD pRecord = NULL;
+ int nCount = 0;
+ pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDEMPHASIS
+ ,(MPARAM)CMA_FIRST
+ ,(MPARAM)CRA_SELECTED
+ ));
+ if (pRecord)
+ nCount++;
+ else
+ return 0;
+ while (pRecord)
+ {
+ pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDEMPHASIS
+ ,MPFROMP(pRecord)
+ ,(MPARAM)CRA_SELECTED
+ ));
+ if (pRecord)
+ nCount++;
+ }
+ return nCount;
+} // end of wxListCtrl::GetSelectedItemCount
// Gets the text colour of the listview
-wxColour wxListCtrl::GetTextColour() const
+wxColour wxListCtrl::GetTextColour () const
{
- // TODO
- return wxColour();
-}
+ wxColour vCol;
+ ULONG ulColor;
+
+ ::WinQueryPresParam( GetHWND()
+ ,PP_FOREGROUNDCOLOR
+ ,0
+ ,NULL
+ ,sizeof(ULONG)
+ ,&ulColor
+ ,QPF_PURERGBCOLOR
+ );
+ vCol.Set(ulColor);
+ return vCol;
+} // end of wxListCtrl::GetTextColour
// Sets the text colour of the listview
-void wxListCtrl::SetTextColour(const wxColour& col)
+void wxListCtrl::SetTextColour (
+ const wxColour& rCol
+)
{
- // TODO
-}
+ ULONG ulColor = wxColourToRGB(rCol);
+
+ ::WinSetPresParam( GetHWND()
+ ,PP_FOREGROUNDCOLOR
+ ,sizeof(ULONG)
+ ,&ulColor
+ );
+} // end of wxListCtrl::SetTextColour
// Gets the index of the topmost visible item when in
// list or report view
-long wxListCtrl::GetTopItem() const
+long wxListCtrl::GetTopItem () const
{
- // TODO
- return 0;
-}
+ PMYRECORD pRecord = NULL;
+ QUERYRECFROMRECT vQueryRect;
+ RECTL vRect;
+
+ ::WinSendMsg( GetHWND()
+ ,CM_QUERYVIEWPORTRECT
+ ,MPFROMP(&vRect)
+ ,MPFROM2SHORT(CMA_WINDOW, TRUE)
+ );
+ vQueryRect.cb = sizeof(QUERYRECFROMRECT);
+ vQueryRect.rect = vRect;
+ vQueryRect.fsSearch = CMA_PARTIAL;
+
+ pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDFROMRECT
+ ,(MPARAM)CMA_FIRST
+ ,MPFROMP(&vQueryRect)
+ );
+
+ if (!pRecord)
+ return -1L;
+ return (long)pRecord->m_ulItemId;
+} // end of wxListCtrl::GetTopItem
// Searches for an item, starting from 'item'.
// 'geometry' is one of
// item can be -1 to find the first item that matches the
// specified flags.
// Returns the item or -1 if unsuccessful.
-long wxListCtrl::GetNextItem(long item, int geom, int state) const
+long wxListCtrl::GetNextItem (
+ long lItem
+, int WXUNUSED(nGeom)
+, int WXUNUSED(nState)
+) const
{
- // TODO
- return 0;
-}
-
-wxImageList *wxListCtrl::GetImageList(int which) const
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
+ ,lItem
+ );
+
+ pRecord = (PMYRECORD)pRecord->m_vRecord.preccNextRecord;
+ if (pRecord)
+ return((long)pRecord->m_ulItemId);
+ return -1L;
+} // end of wxListCtrl::GetNextItem
+
+wxImageList* wxListCtrl::GetImageList (
+ int nWhich
+) const
{
- if ( which == wxIMAGE_LIST_NORMAL )
+ if (nWhich == wxIMAGE_LIST_NORMAL )
{
- return m_imageListNormal;
- }
- else if ( which == wxIMAGE_LIST_SMALL )
+ return m_pImageListNormal;
+ }
+ else if (nWhich == wxIMAGE_LIST_SMALL )
{
- return m_imageListSmall;
- }
- else if ( which == wxIMAGE_LIST_STATE )
+ return m_pImageListSmall;
+ }
+ else if (nWhich == wxIMAGE_LIST_STATE )
{
- return m_imageListState;
- }
- return NULL;
-}
+ return m_pImageListState;
+ }
+ return NULL;
+} // end of wxListCtrl::GetImageList
-void wxListCtrl::SetImageList(wxImageList *imageList, int which)
+void wxListCtrl::SetImageList ( wxImageList* pImageList,
+ int nWhich )
{
- int flags = 0;
- if ( which == wxIMAGE_LIST_NORMAL )
+ if (nWhich == wxIMAGE_LIST_NORMAL)
{
- m_imageListNormal = imageList;
- }
- else if ( which == wxIMAGE_LIST_SMALL )
+ if (m_bOwnsImageListNormal)
+ delete m_pImageListNormal;
+ m_pImageListNormal = pImageList;
+ m_bOwnsImageListNormal = false;
+ }
+ else if (nWhich == wxIMAGE_LIST_SMALL)
{
- m_imageListSmall = imageList;
- }
- else if ( which == wxIMAGE_LIST_STATE )
+ if (m_bOwnsImageListSmall)
+ delete m_pImageListSmall;
+ m_pImageListSmall = pImageList;
+ m_bOwnsImageListSmall = false;
+ }
+ else if (nWhich == wxIMAGE_LIST_STATE)
{
- m_imageListState = imageList;
- }
- // TODO set image list
-}
+ if (m_bOwnsImageListState)
+ delete m_pImageListState;
+ m_pImageListState = pImageList;
+ m_bOwnsImageListState = false;
+ }
+} // end of wxListCtrl::SetImageList
+
+void wxListCtrl::AssignImageList ( wxImageList* pImageList, int nWhich )
+{
+ SetImageList( pImageList, nWhich );
+
+ if (nWhich == wxIMAGE_LIST_NORMAL )
+ m_bOwnsImageListNormal = true;
+ else if (nWhich == wxIMAGE_LIST_SMALL )
+ m_bOwnsImageListSmall = true;
+ else if (nWhich == wxIMAGE_LIST_STATE )
+ m_bOwnsImageListState = true;
+} // end of wxListCtrl::AssignImageList
+// ----------------------------------------------------------------------------
// Operations
-////////////////////////////////////////////////////////////////////////////
+// ----------------------------------------------------------------------------
// Arranges the items
-bool wxListCtrl::Arrange(int flag)
+bool wxListCtrl::Arrange ( int nFlag )
{
- // TODO
- return FALSE;
-}
+ ULONG ulType = 0L;
+ ULONG ulFlags = 0L;
+
+ if (nFlag == wxLIST_ALIGN_SNAP_TO_GRID)
+ {
+ ulType = CMA_ARRANGEGRID;
+ if (nFlag == wxLIST_ALIGN_LEFT)
+ ulFlags |= CMA_LEFT;
+ else if (nFlag == wxLIST_ALIGN_TOP)
+ ulFlags |= CMA_TOP;
+ else if (nFlag == wxLIST_ALIGN_DEFAULT)
+ ulFlags |= CMA_LEFT;
+ }
+ else
+ ulType = CMA_ARRANGESTANDARD;
+ ::WinSendMsg( GetHWND()
+ ,CM_ARRANGE
+ ,(MPARAM)ulType
+ ,(MPARAM)ulFlags
+ );
+ //
+ // We do not support CMA_ARRANGESELECTED
+ //
+ return true;
+} // end of wxListCtrl::Arrange
// Deletes an item
-bool wxListCtrl::DeleteItem(long item)
+bool wxListCtrl::DeleteItem ( long lItem )
{
- // TODO
- return FALSE;
-}
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
+ if (LONGFROMMR(::WinSendMsg( GetHWND()
+ ,CM_REMOVERECORD
+ ,(MPARAM)pRecord
+ ,MPFROM2SHORT(1, CMA_FREE)
+ )) == -1L)
+ {
+ return false;
+ }
+
+ //
+ // The virtual list control doesn't refresh itself correctly, help it
+ //
+ if (IsVirtual())
+ {
+ //
+ // We need to refresh all the lines below the one which was deleted
+ //
+ wxRect vRectItem;
+
+ if (lItem > 0 && GetItemCount())
+ {
+ GetItemRect( lItem - 1
+ ,vRectItem
+ );
+ }
+ else
+ {
+ vRectItem.y = vRectItem.height = 0;
+ }
+ wxRect vRectWin = GetRect();
+
+ vRectWin.height = vRectWin.GetBottom() - vRectItem.GetBottom();
+ vRectWin.y = vRectItem.GetBottom();
+ RefreshRect(vRectWin);
+ }
+ return true;
+} // end of wxListCtrl::DeleteItem
// Deletes all items
-bool wxListCtrl::DeleteAllItems()
+bool wxListCtrl::DeleteAllItems ()
{
- // TODO
- return FALSE;
-}
+ return((LONG)::WinSendMsg( GetHWND()
+ ,CM_REMOVERECORD
+ ,NULL
+ ,MPFROM2SHORT(0, CMA_FREE)
+ ) != -1L);
+} // end of wxListCtrl::DeleteAllItems
// Deletes all items
-bool wxListCtrl::DeleteAllColumns()
+bool wxListCtrl::DeleteAllColumns ()
{
- // TODO
- return FALSE;
-}
+ while (m_nColCount > 0)
+ {
+ DeleteColumn(m_nColCount - 1);
+ m_nColCount--;
+ }
+
+ wxASSERT_MSG(m_nColCount == 0, wxT("no columns should be left"));
+ return true;
+} // end of wxListCtrl::DeleteAllColumns
// Deletes a column
-bool wxListCtrl::DeleteColumn(int col)
+bool wxListCtrl::DeleteColumn ( int nCol )
{
- // TODO
- return FALSE;
-}
+ bool bSuccess = false;
+ PFIELDINFO pField = FindOS2ListFieldByColNum( GetHWND(), nCol );
+ bSuccess = ((LONG)::WinSendMsg( GetHWND()
+ ,CM_REMOVEDETAILFIELDINFO
+ ,MPFROMP(pField)
+ ,MPFROM2SHORT((SHORT)1, CMA_FREE)
+ ) == -1L);
+ if (bSuccess && (m_nColCount > 0))
+ m_nColCount--;
+ return bSuccess;
+} // end of wxListCtrl::DeleteColumn
// Clears items, and columns if there are any.
-void wxListCtrl::ClearAll()
+void wxListCtrl::ClearAll ()
{
DeleteAllItems();
- if ( m_colCount > 0 )
+ if (m_nColCount > 0)
DeleteAllColumns();
-}
-
-// Edit the label
-wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
+} // end of wxListCtrl::ClearAll
+
+//
+// OS/2 does not use a text control for its container labels. You merely
+// "open" a record for editting.
+//
+wxTextCtrl* wxListCtrl::EditLabel (
+ long lItem
+, wxClassInfo* WXUNUSED(pTextControlClass)
+)
{
- // TODO
- return NULL;
-}
-
-// End label editing, optionally cancelling the edit
-bool wxListCtrl::EndEditLabel(bool cancel)
+ CNREDITDATA vEdit;
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
+ ,lItem
+ );
+
+ vEdit.cb = sizeof(CNREDITDATA);
+ vEdit.hwndCnr = GetHWND();
+ vEdit.pRecord = &pRecord->m_vRecord;
+ vEdit.pFieldInfo = NULL;
+ vEdit.ppszText = NULL;
+ vEdit.cbText = 0;
+ vEdit.id = 0;
+
+ ::WinSendMsg( GetHWND()
+ ,CM_OPENEDIT
+ ,MPFROMP(&vEdit)
+ ,(MPARAM)0
+ );
+ return m_pTextCtrl;
+} // end of wxListCtrl::EditLabel
+
+// End label editing, optionally cancelling the edit. Under OS/2 you close
+// the record for editting
+bool wxListCtrl::EndEditLabel ( bool WXUNUSED(bCancel) )
{
- // TODO
- return FALSE;
-}
+ ::WinSendMsg( GetHWND()
+ ,CM_CLOSEEDIT
+ ,(MPARAM)0
+ ,(MPARAM)0
+ );
+ return true;
+} // end of wxListCtrl::EndEditLabel
// Ensures this item is visible
-bool wxListCtrl::EnsureVisible(long item)
+bool wxListCtrl::EnsureVisible ( long lItem )
{
- // TODO
- return FALSE;
-}
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
+ ::WinSendMsg( GetHWND()
+ ,CM_INVALIDATERECORD
+ ,MPFROMP(pRecord)
+ ,MPFROM2SHORT((SHORT)1, CMA_NOREPOSITION)
+ );
+ return true;
+} // end of wxListCtrl::EnsureVisible
// Find an item whose label matches this string, starting from the item after 'start'
// or the beginning if 'start' is -1.
-long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
+long wxListCtrl::FindItem (
+ long lStart
+, const wxString& rsStr
+, bool bPartial
+)
{
- // TODO
- return FALSE;
-}
+ CNRINFO vCnrInfo;
+ SEARCHSTRING vSearch;
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
+ ,lStart
+ );
+ ULONG ulFlag;
+
+
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return -1L;
+
+ if (vCnrInfo.flWindowAttr & CV_ICON)
+ ulFlag = CV_ICON;
+ if (vCnrInfo.flWindowAttr & CV_NAME)
+ ulFlag = CV_NAME;
+ if (vCnrInfo.flWindowAttr & CV_TEXT)
+ ulFlag = CV_TEXT;
+ if (vCnrInfo.flWindowAttr & CV_DETAIL)
+ ulFlag = CV_DETAIL;
+ if (!bPartial)
+ ulFlag |= CV_EXACTLENGTH;
+
+ vSearch.cb = sizeof(SEARCHSTRING);
+ vSearch.pszSearch = (char*)rsStr.c_str();
+ vSearch.fsPrefix = TRUE;
+ vSearch.fsCaseSensitive = TRUE;
+ vSearch.usView = ulFlag;
+
+ if (lStart == -1)
+ {
+ pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
+ ,CM_SEARCHSTRING
+ ,MPFROMP(&vSearch)
+ ,(MPARAM)CMA_FIRST
+ );
+ }
+ else
+ {
+ pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
+ ,CM_SEARCHSTRING
+ ,MPFROMP(&vSearch)
+ ,MPFROMP(pRecord)
+ );
+ }
+ if (!pRecord)
+ return -1L;
+ return pRecord->m_ulItemId;
+} // end of wxListCtrl::FindItem
// Find an item whose data matches this data, starting from the item after 'start'
// or the beginning if 'start' is -1.
-long wxListCtrl::FindItem(long start, long data)
+long wxListCtrl::FindItem (
+ long lStart
+, long lData
+)
{
- // TODO
- return 0;
-}
+ long lIdx = lStart + 1;
+ long lCount = GetItemCount();
+
+ while (lIdx < lCount)
+ {
+ if (GetItemData(lIdx) == lData)
+ return lIdx;
+ lIdx++;
+ };
+ return -1;
+} // end of wxListCtrl::FindItem
// Find an item nearest this position in the specified direction, starting from
// the item after 'start' or the beginning if 'start' is -1.
-long wxListCtrl::FindItem(long start, const wxPoint& pt, int direction)
+long wxListCtrl::FindItem (
+ long lStart
+, const wxPoint& rPoint
+, int nDirection
+)
{
- // TODO
- return 0;
-}
+ RECTL vRect;
+ QUERYRECORDRECT vQueryRect;
+ PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
+ ,lStart
+ );
+ CNRINFO vCnrInfo;
+ ULONG i;
+ wxRect vLibRect;
+
+ if (!::WinSendMsg( GetHWND()
+ ,CM_QUERYCNRINFO
+ ,MPFROMP(&vCnrInfo)
+ ,(MPARAM)(USHORT)sizeof(CNRINFO)
+ ))
+ return -1L;
+
+ vQueryRect.cb = sizeof(QUERYRECORDRECT);
+ vQueryRect.pRecord = &pRecord->m_vRecord;
+ vQueryRect.fRightSplitWindow = TRUE;
+ vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
+
+ ::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDRECT
+ ,MPFROMP(&vRect)
+ ,MPFROMP(&vQueryRect)
+ );
+ vLibRect.SetLeft(vRect.xLeft);
+ vLibRect.SetTop(vRect.yTop);
+ vLibRect.SetRight(vRect.xRight);
+ vLibRect.SetBottom(vRect.yBottom);
+ if (vLibRect.Contains(rPoint))
+ return pRecord->m_ulItemId;
+
+ for (i = lStart + 1; i < vCnrInfo.cRecords; i++)
+ {
+ pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORD
+ ,MPFROMP(pRecord)
+ ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
+ ));
+ vQueryRect.pRecord = (PRECORDCORE)pRecord;
+ ::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDRECT
+ ,MPFROMP(&vRect)
+ ,MPFROMP(&vQueryRect)
+ );
+ vLibRect.SetLeft(vRect.xLeft);
+ vLibRect.SetTop(vRect.yTop);
+ vLibRect.SetRight(vRect.xRight);
+ vLibRect.SetBottom(vRect.yBottom);
+ if (vLibRect.Contains(rPoint))
+ return pRecord->m_ulItemId;
+ }
+ return -1L;
+} // end of wxListCtrl::FindItem
// Determines which item (if any) is at the specified point,
// giving details in 'flags' (see wxLIST_HITTEST_... flags above)
-long wxListCtrl::HitTest(const wxPoint& point, int& flags)
+long wxListCtrl::HitTest (
+ const wxPoint& rPoint
+, int& WXUNUSED(rFlags)
+)
{
- // TODO
- return 0;
-}
+ PMYRECORD pRecord = NULL;
+ QUERYRECFROMRECT vQueryRect;
+ RECTL vRect;
+ long lHeight;
+
+ //
+ // Get height for OS/2 point conversion
+ //
+ ::WinSendMsg( GetHWND()
+ ,CM_QUERYVIEWPORTRECT
+ ,MPFROMP(&vRect)
+ ,MPFROM2SHORT(CMA_WINDOW, TRUE)
+ );
+ lHeight = vRect.yTop - vRect.yBottom;
+
+ //
+ // For now just try and get a record in the general vicinity and forget
+ // the flag
+ //
+ vRect.xLeft = rPoint.x - 2;
+ vRect.xRight = rPoint.x + 2;
+ vRect.yTop = (lHeight - rPoint.y) + 2;
+ vRect.yBottom = (lHeight - rPoint.y) - 2;
+
+ vQueryRect.cb = sizeof(QUERYRECFROMRECT);
+ vQueryRect.rect = vRect;
+ vQueryRect.fsSearch = CMA_PARTIAL;
+
+ pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
+ ,CM_QUERYRECORDFROMRECT
+ ,(MPARAM)CMA_FIRST
+ ,MPFROMP(&vQueryRect)
+ );
+
+ if (!pRecord)
+ return -1L;
+ return pRecord->m_ulItemId;
+} // end of wxListCtrl::HitTest
// Inserts an item, returning the index of the new item if successful,
// -1 otherwise.
-long wxListCtrl::InsertItem(wxListItem& info)
+long wxListCtrl::InsertItem (
+ wxListItem& rInfo
+)
{
- // TODO
- return 0;
-}
-
-long wxListCtrl::InsertItem(long index, const wxString& label)
+ wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
+
+ PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
+ ,rInfo.GetColumn()
+ );
+ PMYRECORD pRecordAfter = NULL;
+ PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
+ ,CM_ALLOCRECORD
+ ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
+ ,MPFROMSHORT(1)
+ );
+
+ ConvertToOS2ListItem( this
+ ,rInfo
+ ,pRecord
+ ,pFieldInfo
+ );
+
+ if (rInfo.GetId() > 0)
+ pRecordAfter = FindOS2ListRecordByID( GetHWND()
+ ,rInfo.GetId() - 1
+ );
+
+ RECORDINSERT vInsert;
+
+ vInsert.cb = sizeof(RECORDINSERT);
+ vInsert.pRecordParent = NULL;
+ if (!pRecordAfter)
+ vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
+ else
+ vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
+ vInsert.zOrder = CMA_TOP;
+ vInsert.cRecordsInsert = 1;
+ vInsert.fInvalidateRecord = TRUE;
+
+ //
+ // Check wether we need to allocate our internal data
+ //
+ bool bNeedInternalData = ((rInfo.GetMask() & wxLIST_MASK_DATA) ||
+ rInfo.HasAttributes()
+ );
+ if (bNeedInternalData)
+ {
+ m_bAnyInternalData = true;
+
+ //
+ // Internal stucture that manages data
+ //
+ CListItemInternalData* pData = new CListItemInternalData();
+
+ pRecord->m_ulUserData = (unsigned long)pData;
+ if (rInfo.GetMask() & wxLIST_MASK_DATA)
+ pData->m_lParam = (WXLPARAM)rInfo.GetData();
+
+ //
+ // Check whether it has any custom attributes
+ //
+ if (rInfo.HasAttributes())
+ {
+ //
+ // Take copy of attributes
+ //
+ pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
+ }
+ }
+ if (!::WinSendMsg( GetHWND()
+ ,CM_INSERTRECORD
+ ,MPFROMP(pRecord)
+ ,MPFROMP(&vInsert)
+ ))
+ return -1;
+ //
+ // OS/2 must mannually bump the index's of following records
+ //
+ BumpRecordIds( GetHWND()
+ ,pRecord
+ );
+ ::WinSendMsg( GetHWND()
+ ,CM_INVALIDATEDETAILFIELDINFO
+ ,NULL
+ ,NULL
+ );
+ return pRecord->m_ulItemId;
+} // end of wxListCtrl::InsertItem
+
+long wxListCtrl::InsertItem (
+ long lIndex
+, const wxString& rsLabel
+)
{
- wxListItem info;
- info.m_text = label;
- info.m_mask = wxLIST_MASK_TEXT;
- info.m_itemId = index;
- return InsertItem(info);
-}
+ wxListItem vInfo;
+
+ memset(&vInfo, '\0', sizeof(wxListItem));
+ vInfo.m_text = rsLabel;
+ vInfo.m_mask = wxLIST_MASK_TEXT;
+ vInfo.m_itemId = lIndex;
+ return InsertItem(vInfo);
+} // end of wxListCtrl::InsertItem
// Inserts an image item
-long wxListCtrl::InsertItem(long index, int imageIndex)
+long wxListCtrl::InsertItem (
+ long lIndex
+, int nImageIndex
+)
{
- wxListItem info;
- info.m_image = imageIndex;
- info.m_mask = wxLIST_MASK_IMAGE;
- info.m_itemId = index;
- return InsertItem(info);
-}
+ wxListItem vInfo;
-// Inserts an image/string item
-long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
-{
- wxListItem info;
- info.m_image = imageIndex;
- info.m_text = label;
- info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
- info.m_itemId = index;
- return InsertItem(info);
-}
+ vInfo.m_image = nImageIndex;
+ vInfo.m_mask = wxLIST_MASK_IMAGE;
+ vInfo.m_itemId = lIndex;
+ return InsertItem(vInfo);
+} // end of wxListCtrl::InsertItem
-// For list view mode (only), inserts a column.
-long wxListCtrl::InsertColumn(long col, wxListItem& item)
+// Inserts an image/string item
+long wxListCtrl::InsertItem (
+ long lIndex
+, const wxString& rsLabel
+, int nImageIndex
+)
{
- // TODO
- return 0;
-}
+ wxListItem vInfo;
+
+ vInfo.m_image = nImageIndex;
+ vInfo.m_text = rsLabel;
+ vInfo.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
+ vInfo.m_itemId = lIndex;
+ return InsertItem(vInfo);
+} // end of wxListCtrl::InsertItem
+
+// For details view mode (only), inserts a column.
+long wxListCtrl::InsertColumn (
+ long lCol
+, wxListItem& rItem
+)
+{
+ bool bSuccess;
+ PFIELDINFO pField = (PFIELDINFO)::WinSendMsg( GetHWND()
+ ,CM_ALLOCDETAILFIELDINFO
+ ,MPFROMLONG(1)
+ ,NULL
+ );
+ PFIELDINFO pFieldAfter = FindOS2ListFieldByColNum ( GetHWND()
+ ,lCol - 1
+ );
+ FIELDINFOINSERT vInsert;
+
+ ConvertToOS2ListCol ( lCol
+ ,rItem
+ ,pField
+ );
+
+ vInsert.cb = sizeof(FIELDINFOINSERT);
+ vInsert.pFieldInfoOrder = pFieldAfter;
+ vInsert.fInvalidateFieldInfo = TRUE;
+ vInsert.cFieldInfoInsert = 1;
+
+ bSuccess = ::WinSendMsg( GetHWND()
+ ,CM_INSERTDETAILFIELDINFO
+ ,MPFROMP(pField)
+ ,MPFROMP(&vInsert)
+ ) != (MRESULT)0;
+ return bSuccess;
+} // end of wxListCtrl::InsertColumn
+
+long wxListCtrl::InsertColumn (
+ long lCol
+, const wxString& rsHeading
+, int nFormat
+, int nWidth
+)
+{
+ wxListItem vItem;
-long wxListCtrl::InsertColumn(long col, const wxString& heading, int format,
- int width)
+ vItem.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
+ vItem.m_text = rsHeading;
+ if (nWidth > -1)
+ {
+ vItem.m_mask |= wxLIST_MASK_WIDTH;
+ vItem.m_width = nWidth;
+ }
+ vItem.m_format = nFormat;
+
+ return InsertColumn( lCol
+ ,vItem
+ );
+} // end of wxListCtrl::InsertColumn
+
+// scroll the control by the given number of pixels (exception: in list view,
+// dx is interpreted as number of columns)
+bool wxListCtrl::ScrollList ( int nDx, int nDy )
+{
+ if (nDx > 0)
+ ::WinSendMsg( GetHWND()
+ ,CM_SCROLLWINDOW
+ ,(MPARAM)CMA_HORIZONTAL
+ ,(MPARAM)nDx
+ );
+ if (nDy > 0)
+ ::WinSendMsg( GetHWND()
+ ,CM_SCROLLWINDOW
+ ,(MPARAM)CMA_VERTICAL
+ ,(MPARAM)nDy
+ );
+ return true;
+} // end of wxListCtrl::ScrollList
+
+bool wxListCtrl::SortItems ( wxListCtrlCompare fn, long lData )
{
- wxListItem item;
- item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
- item.m_text = heading;
- if ( width > -1 )
- {
- item.m_mask |= wxLIST_MASK_WIDTH;
- item.m_width = width;
- }
- item.m_format = format;
+ SInternalDataSort vInternalData;
- return InsertColumn(col, item);
-}
+ vInternalData.m_fnUser = fn;
+ vInternalData.m_lData = lData;
+
+ // WPARAM cast is needed for mingw/cygwin
+ if (!::WinSendMsg( GetHWND()
+ ,CM_SORTRECORD
+ ,(PFN)InternalDataCompareFunc
+ ,(PVOID)&vInternalData
+ ))
+ {
+ wxLogDebug(_T("CM_SORTRECORD failed"));
+ return false;
+ }
+ return true;
+} // end of wxListCtrl::SortItems
-// Scrolls the list control. If in icon, small icon or report view mode,
-// x specifies the number of pixels to scroll. If in list view mode, x
-// specifies the number of columns to scroll.
-// If in icon, small icon or list view mode, y specifies the number of pixels
-// to scroll. If in report view mode, y specifies the number of lines to scroll.
-bool wxListCtrl::ScrollList(int dx, int dy)
+// ----------------------------------------------------------------------------
+// message processing
+// ----------------------------------------------------------------------------
+
+bool wxListCtrl::OS2Command ( WXUINT uCmd, WXWORD wId )
{
- // TODO
- return FALSE;
-}
+ if (uCmd == CN_ENDEDIT)
+ {
+ wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, wId );
-// Sort items.
+ vEvent.SetEventObject( this );
+ ProcessCommand(vEvent);
+ return true;
+ }
+ else if (uCmd == CN_KILLFOCUS)
+ {
+ wxCommandEvent vEvent( wxEVT_KILL_FOCUS, wId );
+ vEvent.SetEventObject( this );
+ ProcessCommand(vEvent);
+ return true;
+ }
+ else
+ return false;
+} // end of wxListCtrl::OS2Command
+
+// Necessary for drawing hrules and vrules, if specified
+void wxListCtrl::OnPaint ( wxPaintEvent& rEvent )
+{
+ wxPaintDC vDc(this);
+ wxPen vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT)
+ ,1
+ ,wxSOLID
+ );
+ wxSize vClientSize = GetClientSize();
+ wxRect vItemRect;
+ int nItemCount = GetItemCount();
+ int nCy = 0;
+ int i;
+ bool bDrawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
+ bool bDrawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
+
+ wxControl::OnPaint(rEvent);
+
+ //
+ // Reset the device origin since it may have been set
+ //
+ vDc.SetDeviceOrigin(0, 0);
+ if (!bDrawHRules && !bDrawVRules)
+ return;
+ if ((GetWindowStyle() & wxLC_REPORT) == 0)
+ return;
+ vDc.SetPen(vPen);
+ vDc.SetBrush(*wxTRANSPARENT_BRUSH);
+
+ if (bDrawHRules)
+ {
+ long lTop = GetTopItem();
+
+ for (i = lTop; i < lTop + GetCountPerPage() + 1; i++)
+ {
+ if (GetItemRect( i
+ ,vItemRect
+ ))
+ {
+ nCy = vItemRect.GetTop();
+ if (i != 0) // Don't draw the first one
+ {
+ vDc.DrawLine( 0
+ ,nCy
+ ,vClientSize.x
+ ,nCy
+ );
+ }
+ // Draw last line
+ if (i == nItemCount - 1)
+ {
+ nCy = vItemRect.GetBottom();
+ vDc.DrawLine( 0
+ ,nCy
+ ,vClientSize.x
+ ,nCy
+ );
+ }
+ }
+ }
+ }
+ i = nItemCount - 1;
+ if (bDrawVRules && (i > -1))
+ {
+ wxRect vFirstItemRect;
+
+ GetItemRect( 0
+ ,vFirstItemRect
+ );
+ if (GetItemRect( i
+ ,vItemRect
+ ))
+ {
+ int nCol;
+ int nX = vItemRect.GetX();
+
+ for (nCol = 0; nCol < GetColumnCount(); nCol++)
+ {
+ int nColWidth = GetColumnWidth(nCol);
+
+ nX += nColWidth ;
+ vDc.DrawLine( nX - 1
+ ,vFirstItemRect.GetY() - 2
+ ,nX - 1
+ ,vItemRect.GetBottom()
+ );
+ }
+ }
+ }
+} // end of wxListCtrl::OnPaint
-// fn is a function which takes 3 long arguments: item1, item2, data.
-// item1 is the long data associated with a first item (NOT the index).
-// item2 is the long data associated with a second item (NOT the index).
-// data is the same value as passed to SortItems.
-// The return value is a negative number if the first item should precede the second
-// item, a positive number of the second item should precede the first,
-// or zero if the two items are equivalent.
+// ----------------------------------------------------------------------------
+// virtual list controls
+// ----------------------------------------------------------------------------
-// data is arbitrary data to be passed to the sort function.
-bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
+wxString wxListCtrl::OnGetItemText (
+ long WXUNUSED(lItem)
+, long WXUNUSED(lCol)
+) const
{
- // TODO
- return FALSE;
-}
+ // this is a pure virtual function, in fact - which is not really pure
+ // because the controls which are not virtual don't need to implement it
+ wxFAIL_MSG( _T("not supposed to be called") );
+ return wxEmptyString;
+} // end of wxListCtrl::OnGetItemText
+
+int wxListCtrl::OnGetItemImage (
+ long WXUNUSED(lItem)
+) const
+{
+ // same as above
+ wxFAIL_MSG( _T("not supposed to be called") );
+ return -1;
+} // end of wxListCtrl::OnGetItemImage
+
+int wxListCtrl::OnGetItemColumnImage (
+ long lItem,
+ long lColumn
+) const
+{
+ if (!lColumn)
+ return OnGetItemImage(lItem);
-// List item structure
-wxListItem::wxListItem()
+ return -1;
+} // end of wxListCtrl::OnGetItemColumnImage
+
+wxListItemAttr* wxListCtrl::OnGetItemAttr (
+ long WXUNUSED_UNLESS_DEBUG(lItem)
+) const
{
- m_mask = 0;
- m_itemId = 0;
- m_col = 0;
- m_state = 0;
- m_stateMask = 0;
- m_image = 0;
- m_data = 0;
+ wxASSERT_MSG( lItem >= 0 && lItem < GetItemCount(),
+ _T("invalid item index in OnGetItemAttr()") );
- m_format = wxLIST_FORMAT_CENTRE;
- m_width = 0;
-}
+ //
+ // No attributes by default
+ //
+ return NULL;
+} // end of wxListCtrl::OnGetItemAttr
+
+void wxListCtrl::SetItemCount (
+ long lCount
+)
+{
+ wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
-// List event
-IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxCommandEvent)
+ //
+ // Cannot explicitly set the record count in OS/2
+ //
+} // end of wxListCtrl::SetItemCount
-wxListEvent::wxListEvent(wxEventType commandType, int id):
- wxCommandEvent(commandType, id)
+void wxListCtrl::RefreshItem (
+ long lItem
+)
{
- m_code = 0;
- m_itemIndex = 0;
- m_col = 0;
- m_cancelled = FALSE;
-}
+ wxRect vRect;
+
+ GetItemRect( lItem
+ ,vRect
+ );
+ RefreshRect(vRect);
+} // end of wxListCtrl::RefreshItem
+
+void wxListCtrl::RefreshItems ( long lItemFrom, long lItemTo )
+{
+ wxRect vRect1;
+ wxRect vRect2;
+
+ GetItemRect( lItemFrom , vRect1 );
+ GetItemRect( lItemTo , vRect2 );
+ wxRect vRect = vRect1;
+
+ vRect.height = vRect2.GetBottom() - vRect1.GetTop();
+ RefreshRect(vRect);
+} // end of wxListCtrl::RefreshItems
+
+MRESULT wxListCtrl::OS2WindowProc( WXUINT uMsg,
+ WXWPARAM wParam,
+ WXLPARAM lParam )
+{
+ bool bProcessed = false;
+ MRESULT lRc;
+ wxListEvent vEvent( wxEVT_NULL
+ ,m_windowId
+ );
+ wxEventType vEventType = wxEVT_NULL;
+ PCNRDRAGINIT pDragInit = NULL;
+ PCNREDITDATA pEditData = NULL;
+ PNOTIFYRECORDENTER pNotifyEnter = NULL;
+
+ vEvent.SetEventObject(this);
+ switch (uMsg)
+ {
+ case WM_CONTROL:
+ //
+ // First off let's set some internal data
+ //
+ switch(SHORT2FROMMP(wParam))
+ {
+ case CN_INITDRAG:
+ case CN_DRAGOVER:
+ case CN_DRAGAFTER:
+ {
+ CListItemInternalData* pInternaldata = (CListItemInternalData *)lParam;
+
+ if (pInternaldata)
+ {
+ wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
+
+ pItem->SetData((long)pInternaldata->m_lParam);
+ }
+ }
+ break;
+ }
+ //
+ // Now let's go through the codes we're interested in
+ //
+ switch(SHORT2FROMMP(wParam))
+ {
+ case CN_INITDRAG:
+ pDragInit = (PCNRDRAGINIT)lParam;
+ if (pDragInit)
+ {
+ PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
+
+ vEventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
+ vEvent.m_itemIndex = pRecord->m_ulItemId;
+ vEvent.m_pointDrag.x = pDragInit->x;
+ vEvent.m_pointDrag.y = pDragInit->y;
+ }
+ break;
+
+ case CN_BEGINEDIT:
+ pEditData = (PCNREDITDATA)lParam;
+ if (pEditData)
+ {
+ vEventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
+ ConvertFromOS2ListItem( GetHWND()
+ ,(wxListItem &)vEvent.GetItem()
+ ,(PMYRECORD)pEditData->pRecord
+ );
+ vEvent.m_itemIndex = vEvent.GetItem().GetId();
+ }
+ break;
+
+ case CN_ENDEDIT:
+ pEditData = (PCNREDITDATA)lParam;
+ if (pEditData)
+ {
+ vEventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
+ ConvertFromOS2ListItem( GetHWND()
+ ,(wxListItem &)vEvent.GetItem()
+ ,(PMYRECORD)pEditData->pRecord
+ );
+ if (pEditData->cbText == 0)
+ return (MRESULT)FALSE;
+ vEvent.m_itemIndex = vEvent.GetItem().GetId();
+ }
+ break;
+
+ case CN_ENTER:
+ pNotifyEnter = (PNOTIFYRECORDENTER)lParam;
+ if (pNotifyEnter)
+ {
+ wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
+ PMYRECORD pMyRecord = (PMYRECORD)pNotifyEnter->pRecord;
+
+ vEventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
+ vEvent.m_itemIndex = pMyRecord->m_ulItemId;
+ pItem->SetText(GetItemText(pMyRecord->m_ulItemId));
+ pItem->SetData(GetItemData(pMyRecord->m_ulItemId));
+ }
+ break;
+
+ //
+ // Add the CN_DROP messages for Direct Manipulation
+ //
+ }
+ vEvent.SetEventType(vEventType);
+ bProcessed = GetEventHandler()->ProcessEvent(vEvent);
+ break;
+ }
+ if (!bProcessed)
+ lRc = wxControl::OS2WindowProc( uMsg
+ ,wParam
+ ,lParam
+ );
+ return lRc;
+} // end of wxListCtrl::WindowProc
+
+#endif // wxUSE_LISTCTRL