]> git.saurik.com Git - wxWidgets.git/blame - src/os2/listctrl.cpp
compilation fix after wxSizer::Remove() change
[wxWidgets.git] / src / os2 / listctrl.cpp
CommitLineData
c4f4cf89
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/os2/listctrl.cpp
3// Purpose: wxListCtrl
4// Author: David Webster
5// Modified by:
6// Created: 01/21/03
7// RCS-ID: $Id$
8// Copyright: (c) David Webster
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "listctrl.h"
22 #pragma implementation "listctrlbase.h"
23#endif
24
25// For compilers that support precompilation, includes "wx.h".
26#include "wx/wxprec.h"
27
28#ifdef __BORLANDC__
29 #pragma hdrstop
30#endif
31
32#if wxUSE_LISTCTRL
33
34#ifndef WX_PRECOMP
35 #include "wx/app.h"
36 #include "wx/intl.h"
37 #include "wx/log.h"
38 #include "wx/settings.h"
39#endif
40
41#include "wx/textctrl.h"
42#include "wx/imaglist.h"
43#include "wx/listctrl.h"
44#include "wx/dcclient.h"
45
46#include "wx/os2/private.h"
47
48//
49// FIELDOFFSET in DETAIL view as defined in the OS2TK45 simply doesn't work
50// We use this, which does!
51//
52#undef FIELDOFFSET
53#define FIELDOFFSET(type, field) ((ULONG)&(((type *)0)->field))
54
55// ----------------------------------------------------------------------------
56// private helper classes
57// ----------------------------------------------------------------------------
58
59/////////////////////////////////////////////////////////////////////////////
60// STRUCT SMYRECORD
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
65// instance.
66/////////////////////////////////////////////////////////////////////////////
67typedef struct _MYRECORD
68{
69 RECORDCORE m_vRecord;
70 unsigned long m_ulItemId;
71 unsigned long m_ulUserData;
72} MYRECORD, *PMYRECORD;
73
74/////////////////////////////////////////////////////////////////////////////
75// CLASS CListItemInternalData
76//
77// Problem:
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.
82//
83// Solution:
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).
88//
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.
91//
92// class CListItemInternalData
93// {
94// public:
95// GuiAdvCtrl_CListItemAttr* pAttr;
96// long lParam; // user data
97// };
98//
99// To conserve memory, a CListItemInternalData is only allocated for a
100// LV_ITEM if text attributes or user data(lparam) are being set.
101//
102// For OS/2, the lParam value points to whatever actual data we have
103/////////////////////////////////////////////////////////////////////////////
104class CListItemInternalData
105{
106public:
107
108 CListItemInternalData(): m_pAttr(NULL)
109 ,m_lParam(0)
110 {}
111
112 ~CListItemInternalData()
113 {
114 delete m_pAttr;
115 m_pAttr = NULL;
116 }
117
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
122
123/////////////////////////////////////////////////////////////////////////////
124// STRUCT SInternalDataSort
125//
126// Sort items.
127//
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.
132//
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.
136//
137// data is arbitrary data to be passed to the sort function.
138//
139// Internal structures for proxying the user compare function
140// so that we can pass it the *real* user data
141/////////////////////////////////////////////////////////////////////////////
142typedef struct internalDataSort
143{
144 wxListCtrlCompare m_fnUser;
145 long m_lData;
146} SInternalDataSort; // end of STRUCT SInternalDataSort
147
148// ----------------------------------------------------------------------------
149// private helper functions
150// ----------------------------------------------------------------------------
151
152/////////////////////////////////////////////////////////////////////////////
153//
154// FindOS2ListFieldByColNum
155//
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.
159//
160// PARAMETERS
161// hWnd -- window handle of container to search
162// lIndex -- index to set
163//
164// RETURN VALUE
165// pointer to the FIELDINFO struct at the index in the container record
166//
167/////////////////////////////////////////////////////////////////////////////
168PFIELDINFO FindOS2ListFieldByColNum (
169 HWND hWnd
170, long lIndex
171)
172{
173 PFIELDINFO pFieldInfo = NULL;
174 CNRINFO vCnrInfo;
175 ULONG i;
176
177 if (!::WinSendMsg( hWnd
178 ,CM_QUERYCNRINFO
179 ,MPFROMP(&vCnrInfo)
180 ,(MPARAM)(USHORT)sizeof(CNRINFO)
181 ))
182 return NULL;
183 for (i = 0; i < vCnrInfo.cFields; i++)
184 {
185 if (i == 0)
186 pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
187 ,CM_QUERYDETAILFIELDINFO
188 ,MPFROMP(pFieldInfo)
189 ,(MPARAM)CMA_FIRST
190 ));
191 else
192 pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
193 ,CM_QUERYDETAILFIELDINFO
194 ,MPFROMP(pFieldInfo)
195 ,(MPARAM)CMA_NEXT
196 ));
197 if (!pFieldInfo)
198 return NULL;
199 if (i == (ULONG)lIndex)
200 break;
201 }
202 if (!pFieldInfo)
203 return NULL;
204 return pFieldInfo;
205} // end of FindOS2ListFieldByColNum
206
207/////////////////////////////////////////////////////////////////////////////
208//
209// FindOS2ListRecordByID
210//
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.
214//
215// PARAMETERS
216// hWnd -- window handle of container to search
217// lItemId -- index to set
218//
219// RETURN VALUE
220// pointer to the internal RECORDCORE struct at the index in the container
221//
222/////////////////////////////////////////////////////////////////////////////
223PMYRECORD FindOS2ListRecordByID (
224 HWND hWnd
225, long lItemId
226)
227{
228 PMYRECORD pRecord = NULL;
229 CNRINFO vCnrInfo;
230 unsigned long i;
231
232 if (!::WinSendMsg( hWnd
233 ,CM_QUERYCNRINFO
234 ,MPFROMP(&vCnrInfo)
235 ,(MPARAM)(USHORT)sizeof(CNRINFO)
236 ))
237 return NULL;
238 for (i = 0; i < vCnrInfo.cRecords; i++)
239 {
240 if (i == 0)
241 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
242 ,CM_QUERYRECORD
243 ,MPFROMP(pRecord)
244 ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
245 ));
246 else
247 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
248 ,CM_QUERYRECORD
249 ,MPFROMP(pRecord)
250 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
251 ));
252 if (!pRecord)
253 return NULL;
254 if (pRecord->m_ulItemId == (ULONG)lItemId)
255 break;
256 }
257 return pRecord;
258} // end of FindOS2ListRecordByID
259
260/////////////////////////////////////////////////////////////////////////////
261//
262// BumpRecordIds
263//
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.
267//
268// PARAMETERS
269// hWnd -- window handle of container to search
270// pRecord -- record after which we starting bumping id's
271//
272// RETURN VALUE
273// none
274//
275/////////////////////////////////////////////////////////////////////////////
276void BumpRecordIds (
277 HWND hWnd
278, PMYRECORD pRecord
279)
280{
281 while(pRecord)
282 {
283 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
284 ,CM_QUERYRECORD
285 ,MPFROMP(pRecord)
286 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
287 ));
288 if (pRecord)
289 pRecord->m_ulItemId++;
290 }
291} // end of BumpRecordIds
292
293/////////////////////////////////////////////////////////////////////////////
294//
295// GetInternalData
296//
297// Get the internal data given a handle and an id
298//
299// PARAMETERS
300// hWnd -- window handle to the control in which item is located
301// lItemId -- ID to get
302//
303// RETURN VALUE
304// pointer to the internal data
305//
306// Note:
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/////////////////////////////////////////////////////////////////////////////
311CListItemInternalData* GetInternalData (
312 HWND hWnd
313, long lItemId
314)
315{
316 PMYRECORD pRecord = FindOS2ListRecordByID( hWnd
317 ,lItemId
318 );
319 //
320 // Internal user data is stored AFTER the last field of the RECORDCORE
321 //
322 if (!pRecord)
323 return NULL;
324 return((CListItemInternalData *)(pRecord->m_ulUserData));
325} // end of GetInternalData
326
327/////////////////////////////////////////////////////////////////////////////
328//
329// GetInternalData
330//
331// Get the internal data given a pointer to a list control and an id
332//
333// PARAMETERS
334// pCtl -- pointer to control inwhich item is located
335// lItemId -- ID to get
336//
337// RETURN VALUE
338// pointer to the internal data
339//
340/////////////////////////////////////////////////////////////////////////////
341CListItemInternalData* GetInternalData (
342 wxListCtrl* pCtl
343, long lItemId
344)
345{
346 return(GetInternalData( (HWND)pCtl->GetHWND()
347 ,lItemId
348 ));
349} // end of GetInternalData
350
351/////////////////////////////////////////////////////////////////////////////
352//
353// DeleteInternalData
354//
355// Delete the internal data for a record
356//
357// PARAMETERS
358// pCtl -- pointer to the list control containing the record
359// lItemId -- the record index to delete the internal data from
360//
361// RETURN VALUE
362// pointer to the internal data attribute
363//
364/////////////////////////////////////////////////////////////////////////////
365void DeleteInternalData (
366 wxListCtrl* pCtl
367, long lItemId
368)
369{
370 CListItemInternalData* pData = GetInternalData( pCtl
371 ,lItemId
372 );
373 if (pData)
374 {
375 if (pData->m_pMyRecord)
376 pData->m_pMyRecord->m_ulUserData = 0;
377 delete pData;
378 }
379} // end of DeleteInternalData
380
381// #pragma page "GetInternalDataAttr"
382/////////////////////////////////////////////////////////////////////////////
383//
384// GetInternalDataAttr
385//
386// Get the internal data item attribute given a pointer to a list control
387// and an id
388//
389// PARAMETERS
390// pCtl -- pointer to control to set
391// lItemId -- ID to set
392//
393// RETURN VALUE
394// pointer to the internal data attribute
395//
396/////////////////////////////////////////////////////////////////////////////
397wxListItemAttr* GetInternalDataAttr (
398 wxListCtrl* pCtl
399, long lItemId
400)
401{
402 CListItemInternalData* pData = GetInternalData( pCtl
403 ,lItemId
404 );
405
406 if (pData)
407 return(pData->m_pAttr);
408 else
409 return NULL;
410} // end of GetInternalDataAttr
411
412/////////////////////////////////////////////////////////////////////////////
413//
414// InternalDataCompareFunc
415//
416// This is compare function we pass to PM. It wraps the real compare
417// function in SInternalDataSort
418//
419// PARAMETERS
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.
423//
424// RETURN VALUE
425// pointer to the internal data attribute
426//
427/////////////////////////////////////////////////////////////////////////////
428SHORT EXPENTRY InternalDataCompareFunc (
429 PMYRECORD p1
430, PMYRECORD p2
431, PVOID pStorage
432)
433{
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);
439
440 return(pInternalData->m_fnUser( lD1
441 ,lD2
442 ,pInternalData->m_lData
443 ));
444} // end of InternalDataCompareFunc
445
446/////////////////////////////////////////////////////////////////////////////
447//
448// ConvertFromOS2ListItem
449//
450// Convert from an internal PM List item to a Toolkit List item
451//
452// PARAMETERS
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
456//
457// RETURN VALUE
458// none
459//
460/////////////////////////////////////////////////////////////////////////////
461void ConvertFromOS2ListItem (
462 HWND hWndListCtrl
463, wxListItem& rInfo
464, PMYRECORD pRecord
465)
466{
467 CListItemInternalData* pInternaldata = (CListItemInternalData *)pRecord->m_ulUserData;
468 bool bNeedText = FALSE;
469
470 if (pInternaldata)
471 rInfo.SetData(pInternaldata->m_lParam);
472
473 rInfo.SetMask(0);
474 rInfo.SetState(0);
475 rInfo.SetStateMask(0);
476 rInfo.SetId((long)pRecord->m_ulItemId);
477 if (hWndListCtrl != 0)
478 {
479 pRecord = FindOS2ListRecordByID( hWndListCtrl
480 ,rInfo.GetId()
481 );
482 }
483
484 //
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
488 //
489 if (pRecord->m_vRecord.flRecordAttr & CRA_DROPONABLE)
490 {
491 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DROPHILITED);
492 rInfo.SetState(rInfo.m_state | wxLIST_STATE_DROPHILITED);
493 }
494 if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED)
495 {
496 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SELECTED);
497 rInfo.SetState(rInfo.m_state | wxLIST_STATE_SELECTED);
498 }
499 if (pRecord->m_vRecord.flRecordAttr & CRA_DISABLED)
500 {
501 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DISABLED);
502 rInfo.SetState(rInfo.m_state | wxLIST_STATE_DISABLED);
503 }
504 if (pRecord->m_vRecord.flRecordAttr & CRA_FILTERED)
505 {
506 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_FILTERED);
507 rInfo.SetState(rInfo.m_state | wxLIST_STATE_FILTERED);
508 }
509 if (pRecord->m_vRecord.flRecordAttr & CRA_INUSE)
510 {
511 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_INUSE);
512 rInfo.SetState(rInfo.m_state | wxLIST_STATE_INUSE);
513 }
514 if (pRecord->m_vRecord.flRecordAttr & CRA_PICKED)
515 {
516 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_PICKED);
517 rInfo.SetState(rInfo.m_state | wxLIST_STATE_PICKED);
518 }
519 if (pRecord->m_vRecord.flRecordAttr & CRA_SOURCE)
520 {
521 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SOURCE);
522 rInfo.SetState(rInfo.m_state | wxLIST_STATE_SOURCE);
523 }
524
525 if (pRecord->m_vRecord.pszText != (PSZ)NULL)
526 {
527 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_TEXT);
528 rInfo.SetText(pRecord->m_vRecord.pszText);
529 }
530 if (pRecord->m_vRecord.pszIcon != (PSZ)NULL ||
531 pRecord->m_vRecord.pszName != (PSZ)NULL)
532 {
533 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_IMAGE);
534 rInfo.SetImage(pRecord->m_vRecord.hptrIcon);
535 }
536 if (pRecord->m_ulUserData)
537 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_DATA);
538} // end of ConvertFromOS2ListItem
539
540/////////////////////////////////////////////////////////////////////////////
541//
542// ConvertToOS2Flags
543//
544// Convert from an library states to OS states
545//
546// PARAMETERS
547// lState -- the state
548// pRecord -- the OS list control to use
549//
550// RETURN VALUE
551// none
552//
553/////////////////////////////////////////////////////////////////////////////
554void ConvertToOS2Flags (
555 long lState
556, PMYRECORD pRecord
557)
558{
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
574
575/////////////////////////////////////////////////////////////////////////////
576//
577// ConvertToOS2ListItem
578//
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.
582//
583// PARAMETERS
584// pCtrl -- the control to use
585// rInfo -- the item to convert
586// pRecord -- the OS list control to use, should be zeroed out
587//
588// RETURN VALUE
589// none
590//
591/////////////////////////////////////////////////////////////////////////////
592void ConvertToOS2ListItem (
593 const wxListCtrl* pCtrl
594, const wxListItem& rInfo
595, PMYRECORD pRecord
596)
597{
598 pRecord->m_ulItemId = (ULONG)rInfo.GetId();
599 if (rInfo.GetMask() & wxLIST_MASK_STATE)
600 {
601 ConvertToOS2Flags( rInfo.m_state
602 ,pRecord
603 );
604 }
605 if (pCtrl->GetWindowStyleFlag() & wxLC_ICON ||
606 pCtrl->GetWindowStyleFlag() & wxLC_SMALL_ICON)
607 {
608 pRecord->m_vRecord.pszIcon = (char*)rInfo.GetText().c_str();
609 }
610 if (pCtrl->GetWindowStyleFlag() & wxLC_LIST) // PM TEXT view
611 {
612 pRecord->m_vRecord.pszText = (char*)rInfo.GetText().c_str();
613 }
614 if (rInfo.GetMask() & wxLIST_MASK_IMAGE)
615 {
616 pRecord->m_vRecord.hptrIcon = (HPOINTER)rInfo.GetImage();
617 pRecord->m_vRecord.hptrMiniIcon = (HPOINTER)rInfo.m_miniImage;
618 }
619} // end of ConvertToOS2ListItem
620
621/////////////////////////////////////////////////////////////////////////////
622//
623// ConvertToOS2ListCol
624//
625// Convert from a library List column to an internal PM List column
626//
627// PARAMETERS
628// lCol -- the columnd to convert
629// rItem -- the item to convert
630// pField -- the OS list column to use
631//
632// RETURN VALUE
633// none
634//
635/////////////////////////////////////////////////////////////////////////////
636void ConvertToOS2ListCol (
637 long lCol
638, const wxListItem& rItem
639, PFIELDINFO pField
640)
641{
642 memset(pField, '\0', sizeof(FIELDINFO));
643 pField->cb = sizeof(FIELDINFO);
644 if (rItem.GetMask() & wxLIST_MASK_TEXT)
645 {
646 pField->flData |= CFA_STRING;
647 pField->pUserData = (void *)rItem.GetText().c_str();
648 }
649 if (rItem.GetMask() & wxLIST_MASK_FORMAT)
650 {
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;
657 }
658 if (rItem.GetMask() & wxLIST_MASK_WIDTH)
659 {
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
664 }
665} // end of ConvertToOS2ListCol
666
667// ----------------------------------------------------------------------------
668// events
669// ----------------------------------------------------------------------------
670
671DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
672DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
673DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
674DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
675DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
676DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
677DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
678DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
679DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
680DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
681DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
682DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
683DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
684DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK)
685DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG)
686DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING)
687DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG)
688DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
689DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
690DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
691DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED)
692DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
693
694IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
695IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
696IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
697
698IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
699
700BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
701 EVT_PAINT(wxListCtrl::OnPaint)
702END_EVENT_TABLE()
703
704// ============================================================================
705// implementation
706// ============================================================================
707
708// ----------------------------------------------------------------------------
709// wxListCtrl construction
710// ----------------------------------------------------------------------------
711
712void wxListCtrl::Init ()
713{
714 m_pImageListNormal = NULL;
715 m_pImageListSmall = NULL;
716 m_pImageListState = NULL;
717 m_bOwnsImageListNormal = FALSE;
718 m_bOwnsImageListSmall = FALSE;
719 m_bOwnsImageListState = FALSE;
720 m_lBaseStyle = 0L;
721 m_nColCount = 0;
722 m_pTextCtrl = NULL;
723 m_bAnyInternalData = FALSE;
724 m_bHasAnyAttr = FALSE;
725} // end of wxListCtrl::Init
726
727bool wxListCtrl::Create (
728 wxWindow* pParent
729, wxWindowID vId
730, const wxPoint& rPos
731, const wxSize& rSize
732, long lStyle
733, const wxValidator& rValidator
734, const wxString& rsName
735)
736{
737 int nX = rPos.x;
738 int nY = rPos.y;
739 int nWidth = rSize.x;
740 int nHeight = rSize.y;
741
742#if wxUSE_VALIDATORS
743 SetValidator(rValidator);
744#endif // wxUSE_VALIDATORS
745
746 SetName(rsName);
747 SetWindowStyleFlag(lStyle);
748 SetParent(pParent);
749 if (nWidth <= 0)
750 nWidth = 100;
751 if (nHeight <= 0)
752 nHeight = 30;
753 if (nX < 0)
754 nX = 0;
755 if (nY < 0)
756 nY = 0;
757
758 m_windowId = (vId == -1) ? NewControlId() : vId;
759
760 long lSstyle = WS_VISIBLE | WS_TABSTOP;
761
762 if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
763 lSstyle |= WS_CLIPSIBLINGS;
764 m_lBaseStyle = lSstyle;
765 if (!DoCreateControl( nX
766 ,nY
767 ,nWidth
768 ,nHeight
769 ))
770 return FALSE;
771 if (pParent)
772 pParent->AddChild(this);
773 return TRUE;
774} // end of wxListCtrl::Create
775
776bool wxListCtrl::DoCreateControl (
777 int nX
778, int nY
779, int nWidth
780, int nHeight
781)
782{
783 DWORD lWstyle = m_lBaseStyle;
784 long lOldStyle = 0; // Dummy
785
786 CNRINFO vCnrInfo;
787
788 lWstyle |= ConvertToOS2Style( lOldStyle
789 ,GetWindowStyleFlag()
790 );
791
792 m_hWnd = (WXHWND)::WinCreateWindow( GetParent()->GetHWND()
793 ,WC_CONTAINER
794 ,NULL
795 ,m_lBaseStyle
796 ,0, 0, 0, 0
797 ,GetParent()->GetHWND()
798 ,HWND_BOTTOM
799 ,(ULONG)m_windowId
800 ,NULL
801 ,NULL
802 );
803 if (!m_hWnd)
804 {
805 return FALSE;
806 }
807
808 //
809 // Now set the display attributes of the container
810 //
811 if (!::WinSendMsg( GetHWND()
812 ,CM_QUERYCNRINFO
813 ,MPFROMP(&vCnrInfo)
814 ,(MPARAM)(USHORT)sizeof(CNRINFO)
815 ))
816 lWstyle = ConvertViewToOS2Style(GetWindowStyleFlag());
817 vCnrInfo.flWindowAttr != lWstyle;
818 ::WinSendMsg( GetHWND()
819 ,CM_SETCNRINFO
820 ,MPFROMP(&vCnrInfo)
821 ,(MPARAM)CMA_FLWINDOWATTR
822 );
823
824 //
825 // And now set needed arrangement flags
826 //
827 lWstyle = ConvertArrangeToOS2Style(GetWindowStyleFlag());
828 ::WinSendMsg( GetHWND()
829 ,CM_ARRANGE
830 ,(MPARAM)CMA_ARRANGEGRID
831 ,(MPARAM)lWstyle
832 );
833 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
834 SetForegroundColour(GetParent()->GetForegroundColour());
835 SubclassWin(m_hWnd);
836 SetFont(*wxSMALL_FONT);
837 SetXComp(0);
838 SetYComp(0);
839 SetSize( nX
840 ,nY
841 ,nWidth
842 ,nHeight
843 );
844 return TRUE;
845} // end of wxListCtrl::DoCreateControl
846
847void wxListCtrl::UpdateStyle ()
848{
849 if (GetHWND())
850 {
851 long lDummy;
852 DWORD dwStyleNew = ConvertToOS2Style( lDummy
853 ,GetWindowStyleFlag()
854 );
855
856 dwStyleNew |= m_lBaseStyle;
857
858 //
859 // Get the current window style.
860 //
861 ULONG dwStyleOld = ::WinQueryWindowULong(GetHWND(), QWL_STYLE);
862
863 //
864 // Only set the window style if the view bits have changed.
865 //
866 if (dwStyleOld != dwStyleNew)
867 {
868 ::WinSetWindowULong(GetHWND(), QWL_STYLE, dwStyleNew);
869 }
870 }
871} // end of wxListCtrl::UpdateStyle
872
873void wxListCtrl::FreeAllInternalData ()
874{
875 if (m_bAnyInternalData)
876 {
877 int n = GetItemCount();
878 int i = 0;
879
880 for (i = 0; i < n; i++)
881 DeleteInternalData(this, (long)i);
882 m_bAnyInternalData = FALSE;
883 }
884} // end of wxListCtrl::FreeAllInternalData
885
886wxListCtrl::~wxListCtrl ()
887{
888 FreeAllInternalData();
889 if (m_pTextCtrl )
890 {
891 m_pTextCtrl->SetHWND(0);
892 m_pTextCtrl->UnsubclassWin();
893 delete m_pTextCtrl;
894 m_pTextCtrl = NULL;
895 }
896
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
904
905// ----------------------------------------------------------------------------
906// set/get/change style
907// ----------------------------------------------------------------------------
908
909// Add or remove a single window style
910void wxListCtrl::SetSingleStyle (
911 long lStyle
912, bool bAdd
913)
914{
915 long lFlag = GetWindowStyleFlag();
916
917 //
918 // Get rid of conflicting styles
919 //
920 if (bAdd)
921 {
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;
928 }
929 if (lFlag & lStyle)
930 {
931 if (!bAdd)
932 lFlag -= lStyle;
933 }
934 else
935 {
936 if (bAdd)
937 {
938 lFlag |= lStyle;
939 }
940 }
941 m_windowStyle = lFlag;
942 UpdateStyle();
943} // end of wxListCtrl::SetSingleStyle
944
945// Set the whole window style
946void wxListCtrl::SetWindowStyleFlag (
947 long lFlag
948)
949{
950 m_windowStyle = lFlag;
951 UpdateStyle();
952} // end of wxListCtrl::SetWindowStyleFlag
953
954long wxListCtrl::ConvertToOS2Style (
955 long& rOldStyle
956, long lStyle
957) const
958{
959 long lWstyle = 0L;
960
961 //
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
965 //
966 if (lStyle & wxLC_AUTOARRANGE)
967 lWstyle |= CCS_AUTOPOSITION;
968 if (lStyle & wxLC_SINGLE_SEL)
969 lWstyle |= CCS_SINGLESEL;
970 else
971 lWstyle |= CCS_EXTENDSEL;
972 if (!(lStyle & wxLC_EDIT_LABELS))
973 lWstyle |= CCS_READONLY;
974 return lWstyle;
975} // end of wxListCtrl::ConvertToOS2Style
976
977long wxListCtrl::ConvertArrangeToOS2Style (
978 long lStyle
979)
980{
981 long lWstyle = 0;
982
983 if (lStyle & wxLC_ALIGN_LEFT)
984 {
985 lWstyle |= CMA_LEFT;
986 }
987
988 if (lStyle & wxLC_ALIGN_TOP)
989 {
990 lWstyle |= CMA_TOP;
991 }
992 return lWstyle;
993} // end of wxListCtrl::ConvertArrangeToOS2Style
994
995long wxListCtrl::ConvertViewToOS2Style (
996 long lStyle
997)
998{
999 long lWstyle = CA_DRAWICON; // we will only use icons
1000
1001 if (lStyle & wxLC_ICON)
1002 {
1003 lWstyle |= CV_ICON;
1004 }
1005 if (lStyle & wxLC_SMALL_ICON)
1006 {
1007 lWstyle |= (CV_ICON | CV_MINI);
1008 }
1009 if (lStyle & wxLC_LIST)
1010 {
1011 lWstyle |= CV_TEXT;
1012 }
1013 if (lStyle & wxLC_REPORT)
1014 {
1015 lWstyle |= CV_DETAIL;
1016 }
1017 if (lStyle & wxLC_VIRTUAL)
1018 {
1019 lWstyle |= CA_OWNERDRAW;
1020 }
1021 if (lStyle & wxLC_AUTOARRANGE)
1022 {
1023 lWstyle |= CV_FLOW;
1024 }
1025 if (!(lStyle & wxLC_NO_HEADER))
1026 {
1027 lWstyle |= CA_DETAILSVIEWTITLES;
1028 }
1029 return lWstyle;
1030} // end of wxListCtrl::ConvertViewToOS2Style
1031
1032// ----------------------------------------------------------------------------
1033// accessors
1034// ----------------------------------------------------------------------------
1035
1036// Sets the foreground, i.e. text, colour
1037bool wxListCtrl::SetForegroundColour (
1038 const wxColour& rCol)
1039{
1040 ULONG ulColor = wxColourToRGB(rCol);
1041
1042 if (!wxWindow::SetForegroundColour(rCol))
1043 return FALSE;
1044
1045
1046 ::WinSetPresParam( GetHWND()
1047 ,PP_FOREGROUNDCOLOR
1048 ,sizeof(ULONG)
1049 ,&ulColor
1050 );
1051 return TRUE;
1052} // end of wxListCtrl::SetForegroundColour
1053
1054// Sets the background colour
1055bool wxListCtrl::SetBackgroundColour (
1056 const wxColour& rCol
1057)
1058{
1059 if (!wxWindow::SetBackgroundColour(rCol))
1060 return FALSE;
1061
1062 //
1063 // We set the same colour for both the "empty" background and the items
1064 // background
1065 //
1066 ULONG ulColor = wxColourToRGB(rCol);
1067
1068 ::WinSetPresParam( GetHWND()
1069 ,PP_BACKGROUNDCOLOR
1070 ,sizeof(ULONG)
1071 ,&ulColor
1072 );
1073 return TRUE;
1074} // end of wxListCtrl::SetBackgroundColour
1075
1076// Gets information about this column
1077bool wxListCtrl::GetColumn (
1078 int nCol
1079, wxListItem& rItem
1080) const
1081{
1082 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
1083 ,nCol
1084 );
1085
1086 if (!pFieldInfo)
1087 return FALSE;
1088 rItem.SetWidth(pFieldInfo->cxWidth);
1089 if ((rItem.GetMask() & wxLIST_MASK_TEXT) &&
1090 (pFieldInfo->flData & CFA_STRING) &&
1091 (pFieldInfo->pUserData != NULL))
1092 {
1093 rItem.SetText((char*)pFieldInfo->pUserData);
1094 }
1095 if (rItem.GetMask() & wxLIST_MASK_FORMAT )
1096 {
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;
1103 }
1104 return TRUE;
1105} // end of wxListCtrl::GetColumn
1106
1107// Sets information about this column
1108bool wxListCtrl::SetColumn (
1109 int nCol
1110, wxListItem& rItem
1111)
1112{
1113 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND()
1114 ,nCol
1115 );
1116 ConvertToOS2ListCol( nCol
1117 ,rItem
1118 ,pFieldInfo
1119 );
1120 //
1121 // Since we changed the field pointed to, we invalidate to see the result
1122 //
1123 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
1124 return TRUE;
1125} // end of wxListCtrl::SetColumn
1126
1127// Gets the column width
1128int wxListCtrl::GetColumnWidth (
1129 int nCol
1130) const
1131{
1132 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
1133 ,nCol
1134 );
1135
1136 if (!pFieldInfo)
1137 return 0;
1138 return((int)pFieldInfo->cxWidth);
1139} // end of wxListCtrl::GetColumnWidth
1140
1141// Sets the column width
1142bool wxListCtrl::SetColumnWidth (
1143 int nCol
1144, int nWidth
1145)
1146{
1147 int nCol2 = nCol;
1148 int nWidth2 = nWidth;
1149
1150 if (GetWindowStyleFlag() & wxLC_LIST)
1151 nCol2 = -1;
1152
1153 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND()
1154 ,nCol
1155 );
1156 pFieldInfo->cxWidth = nWidth;
1157 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
1158 return TRUE;
1159} // end of wxListCtrl::SetColumnWidth
1160
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)
1165int wxListCtrl::GetCountPerPage () const
1166{
1167 QUERYRECORDRECT vQueryRect;
1168 CNRINFO vCnrInfo;
1169 RECTL vRectRecord;
1170 RECTL vRectControl;
1171 int nCount;
1172
1173 if (!::WinSendMsg( GetHWND()
1174 ,CM_QUERYCNRINFO
1175 ,MPFROMP(&vCnrInfo)
1176 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1177 ))
1178 return 0;
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()
1190 ,CM_QUERYRECORDRECT
1191 ,MPFROMP(&vRectRecord)
1192 ,MPFROMP(&vQueryRect)
1193 ))
1194 return 0;
1195 if (!::WinSendMsg( GetHWND()
1196 ,CM_QUERYVIEWPORTRECT
1197 ,MPFROMP(&vRectControl)
1198 ,MPFROM2SHORT(CMA_WINDOW, (USHORT)FALSE)
1199 ))
1200 return 0;
1201 nCount = (int)((int)((vRectControl.xRight - vRectControl.xLeft) / (vRectRecord.xRight - vRectRecord.xLeft)) *
1202 (int)((vRectControl.yTop - vRectControl.yBottom) / (vRectRecord.yTop - vRectRecord.yBottom))
1203 );
1204 if (nCount > (int)vCnrInfo.cFields)
1205 nCount = (int)vCnrInfo.cFields;
1206 return nCount;
1207} // end of wxListCtrl::GetCountPerPage
1208
1209// Gets the edit control for editing labels.
1210wxTextCtrl* wxListCtrl::GetEditControl() const
1211{
1212 return m_pTextCtrl;
1213}
1214
1215// Gets information about the item
1216bool wxListCtrl::GetItem (
1217 wxListItem& rInfo
1218) const
1219{
1220 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1221 ,rInfo.GetId()
1222 );
1223
1224 //
1225 // Give NULL as hwnd as we already have everything we need
1226 //
1227 ConvertFromOS2ListItem( NULL
1228 ,rInfo
1229 ,pRecord
1230 );
1231 return TRUE;
1232} // end of wxListCtrl::GetItem
1233
1234// Sets information about the item
1235bool wxListCtrl::SetItem (
1236 wxListItem& rInfo
1237)
1238{
1239 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1240 ,rInfo.GetId()
1241 );
1242
1243 ConvertToOS2ListItem( this
1244 ,rInfo
1245 ,pRecord
1246 );
1247
1248 //
1249 // Check if setting attributes or lParam
1250 //
1251 if (rInfo.HasAttributes() || (rInfo.GetMask() & wxLIST_MASK_DATA))
1252 {
1253 //
1254 // Get internal item data
1255 // perhaps a cache here ?
1256 //
1257 CListItemInternalData* pData = GetInternalData( this
1258 ,rInfo.GetId()
1259 );
1260
1261 if (!pData)
1262 {
1263 //
1264 // Need to set it
1265 //
1266 m_bAnyInternalData = TRUE;
1267 pData = new CListItemInternalData();
1268 pRecord->m_ulUserData = (unsigned long)pData;
1269 };
1270
1271 //
1272 // User data
1273 //
1274 if (rInfo.GetMask() & wxLIST_MASK_DATA)
1275 pData->m_lParam = (WXLPARAM)rInfo.GetData();
1276
1277 // attributes
1278 if (rInfo.HasAttributes())
1279 {
1280 if (pData->m_pAttr)
1281 *pData->m_pAttr = *rInfo.GetAttributes();
1282 else
1283 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
1284 }
1285 }
1286
1287 //
1288 // We need to update the item immediately to show the new image
1289 //
1290 bool bUpdateNow = (rInfo.GetMask() & wxLIST_MASK_IMAGE) != 0;
1291
1292 //
1293 // Check whether it has any custom attributes
1294 //
1295 if (rInfo.HasAttributes())
1296 {
1297 m_bHasAnyAttr = TRUE;
1298
1299 //
1300 // If the colour has changed, we must redraw the item
1301 //
1302 bUpdateNow = TRUE;
1303 }
1304 ::WinSendMsg( GetHWND()
1305 ,CM_INVALIDATERECORD
1306 ,MPFROMP(pRecord)
1307 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1308 );
1309 RefreshItem(pRecord->m_ulItemId);
1310 return TRUE;
1311} // end of wxListCtrl::SetItem
1312
1313long wxListCtrl::SetItem (
1314 long lIndex
1315, int nCol
1316, const wxString& rsLabel
1317, int nImageId
1318)
1319{
1320 wxListItem vInfo;
1321
1322 vInfo.m_text = rsLabel;
1323 vInfo.m_mask = wxLIST_MASK_TEXT;
1324 vInfo.m_itemId = lIndex;
1325 vInfo.m_col = nCol;
1326 if (nImageId > -1)
1327 {
1328 vInfo.m_image = nImageId;
1329 vInfo.m_mask |= wxLIST_MASK_IMAGE;
1330 }
1331 return SetItem(vInfo);
1332} // end of wxListCtrl::SetItem
1333
1334// Gets the item state
1335int wxListCtrl::GetItemState (
1336 long lItem
1337, long lStateMask
1338) const
1339{
1340 wxListItem vInfo;
1341
1342 vInfo.m_mask = wxLIST_MASK_STATE;
1343 vInfo.m_stateMask = lStateMask;
1344 vInfo.m_itemId = lItem;
1345
1346 if (!GetItem(vInfo))
1347 return 0;
1348 return vInfo.m_state;
1349} // end of wxListCtrl::GetItemState
1350
1351// Sets the item state
1352bool wxListCtrl::SetItemState (
1353 long lItem
1354, long lState
1355, long lStateMask
1356)
1357{
1358 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1359 ,lItem
1360 );
1361
1362 //
1363 // Don't use SetItem() here as it doesn't work with the virtual list
1364 // controls
1365 //
1366 ConvertToOS2Flags( lState
1367 ,pRecord
1368 );
1369
1370 //
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)
1375 //
1376 long lFocusOld;
1377
1378 if (IsVirtual() &&
1379 (lStateMask & wxLIST_STATE_FOCUSED) &&
1380 (lState & wxLIST_STATE_FOCUSED) )
1381 {
1382 lFocusOld = GetNextItem( -1
1383 ,wxLIST_NEXT_ALL
1384 ,wxLIST_STATE_FOCUSED
1385 );
1386 }
1387 else
1388 {
1389 lFocusOld = -1;
1390 }
1391 ::WinSendMsg( GetHWND()
1392 ,CM_INVALIDATERECORD
1393 ,MPFROMP(pRecord)
1394 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1395 );
1396
1397 if (lFocusOld != -1)
1398 {
1399 //
1400 // No need to refresh the item if it was previously selected, it would
1401 // only result in annoying flicker
1402 //
1403 if (!(GetItemState( lFocusOld
1404 ,wxLIST_STATE_SELECTED
1405 ) & wxLIST_STATE_SELECTED))
1406 {
1407 RefreshItem(lFocusOld);
1408 }
1409 }
1410 return TRUE;
1411} // end of wxListCtrl::SetItemState
1412
1413// Sets the item image
1414bool wxListCtrl::SetItemImage (
1415 long lItem
1416, int nImage
1417, int WXUNUSED(nSelImage))
1418{
1419 wxListItem vInfo;
1420
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
1426
1427// Gets the item text
1428wxString wxListCtrl::GetItemText (
1429 long lItem
1430) const
1431{
1432 wxListItem vInfo;
1433
1434 vInfo.m_mask = wxLIST_MASK_TEXT;
1435 vInfo.m_itemId = lItem;
1436
1437 if (!GetItem(vInfo))
1438 return wxEmptyString;
1439 return vInfo.m_text;
1440} // end of wxListCtrl::GetItemText
1441
1442// Sets the item text
1443void wxListCtrl::SetItemText (
1444 long lItem
1445, const wxString& rsStr
1446)
1447{
1448 wxListItem vInfo;
1449
1450 vInfo.m_mask = wxLIST_MASK_TEXT;
1451 vInfo.m_itemId = lItem;
1452 vInfo.m_text = rsStr;
1453 SetItem(vInfo);
1454} // end of wxListCtrl::SetItemText
1455
1456// Gets the item data
1457long wxListCtrl::GetItemData (
1458 long lItem
1459) const
1460{
1461 wxListItem vInfo;
1462
1463 vInfo.m_mask = wxLIST_MASK_DATA;
1464 vInfo.m_itemId = lItem;
1465 if (!GetItem(vInfo))
1466 return 0;
1467 return vInfo.m_data;
1468} // end of wxListCtrl::GetItemData
1469
1470// Sets the item data
1471bool wxListCtrl::SetItemData (
1472 long lItem
1473, long lData
1474)
1475{
1476 wxListItem vInfo;
1477
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
1483
1484// Gets the item rectangle
1485bool wxListCtrl::GetItemRect (
1486 long lItem
1487, wxRect& rRect
1488, int nCode
1489) const
1490{
1491 bool bSuccess;
1492 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1493 ,lItem
1494 );
1495 QUERYRECORDRECT vQueryRect;
1496 RECTL vRect;
1497 int nHeight;
1498
1499 if (!pRecord)
1500 return FALSE;
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()
1506 ,CM_QUERYRECORDRECT
1507 ,MPFROMP(&vRect)
1508 ,MPFROMP(&vQueryRect)
1509 );
1510 //
1511 // remember OS/2 is backwards
1512 //
1513 GetClientSize( NULL
1514 ,&nHeight
1515 );
1516 rRect.x = vRect.xLeft;
1517 rRect.y = nHeight - vRect.yTop;
1518 rRect.width = vRect.xRight;
1519 rRect.height = nHeight - vRect.yBottom;
1520 bSuccess = TRUE;
1521 return bSuccess;
1522} // end of wxListCtrl::GetItemRect
1523
1524// Gets the item position
1525bool wxListCtrl::GetItemPosition (
1526 long lItem
1527, wxPoint& rPos
1528) const
1529{
1530 bool bSuccess;
1531 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1532 ,lItem
1533 );
1534 QUERYRECORDRECT vQueryRect;
1535 RECTL vRect;
1536 int nHeight;
1537
1538 if (!pRecord)
1539 return FALSE;
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()
1545 ,CM_QUERYRECORDRECT
1546 ,MPFROMP(&vRect)
1547 ,MPFROMP(&vQueryRect)
1548 );
1549 //
1550 // remember OS/2 is backwards
1551 //
1552 GetClientSize( NULL
1553 ,&nHeight
1554 );
1555 rPos.x = vRect.xLeft;
1556 rPos.y = nHeight - vRect.yTop;
1557 bSuccess = TRUE;
1558 return bSuccess;
1559} // end of wxListCtrl::GetItemPosition
1560
1561// Sets the item position.
1562bool wxListCtrl::SetItemPosition (
1563 long lItem
1564, const wxPoint& rPos
1565)
1566{
1567 //
1568 // Items cannot be positioned in X/Y coord in OS/2
1569 //
1570 return FALSE;
1571} // end of wxListCtrl::SetItemPosition
1572
1573// Gets the number of items in the list control
1574int wxListCtrl::GetItemCount () const
1575{
1576 CNRINFO vCnrInfo;
1577
1578 if (!::WinSendMsg( GetHWND()
1579 ,CM_QUERYCNRINFO
1580 ,MPFROMP(&vCnrInfo)
1581 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1582 ))
1583 return -1;
1584 return vCnrInfo.cRecords;
1585} // end of wxListCtrl::GetItemCount
1586
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.
1590int wxListCtrl::GetItemSpacing (
1591 bool bIsSmall
1592) const
1593{
1594 CNRINFO vCnrInfo;
1595
1596 if (!::WinSendMsg( GetHWND()
1597 ,CM_QUERYCNRINFO
1598 ,MPFROMP(&vCnrInfo)
1599 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1600 ))
1601 return -1;
1602 return vCnrInfo.cyLineSpacing;
1603} // end of wxListCtrl::GetItemSpacing
1604
1605void wxListCtrl::SetItemTextColour (
1606 long lItem
1607, const wxColour& rCol
1608)
1609{
1610 wxListItem vInfo;
1611
1612 vInfo.m_itemId = lItem;
1613 vInfo.SetTextColour(rCol);
1614 SetItem(vInfo);
1615} // end of wxListCtrl::SetItemTextColour
1616
1617wxColour wxListCtrl::GetItemTextColour (
1618 long lItem
1619) const
1620{
1621 wxListItem vInfo;
1622
1623 vInfo.m_itemId = lItem;
1624 GetItem(vInfo);
1625 return vInfo.GetTextColour();
1626} // end of wxListCtrl::GetItemTextColour
1627
1628void wxListCtrl::SetItemBackgroundColour (
1629 long lItem
1630, const wxColour& rCol
1631)
1632{
1633 wxListItem vInfo;
1634
1635 vInfo.m_itemId = lItem;
1636 vInfo.SetBackgroundColour(rCol);
1637 SetItem(vInfo);
1638} // end of wxListCtrl::SetItemBackgroundColour
1639
1640wxColour wxListCtrl::GetItemBackgroundColour (
1641 long lItem
1642) const
1643{
1644 wxListItem vInfo;
1645
1646 vInfo.m_itemId = lItem;
1647 GetItem(vInfo);
1648 return vInfo.GetBackgroundColour();
1649} // end of wxListCtrl::GetItemBackgroundColour
1650
1651// Gets the number of selected items in the list control
1652int wxListCtrl::GetSelectedItemCount () const
1653{
1654 PMYRECORD pRecord = NULL;
1655 int nCount = 0;
1656 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1657 ,CM_QUERYRECORDEMPHASIS
1658 ,(MPARAM)CMA_FIRST
1659 ,(MPARAM)CRA_SELECTED
1660 ));
1661 if (pRecord)
1662 nCount++;
1663 else
1664 return 0;
1665 while (pRecord)
1666 {
1667 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1668 ,CM_QUERYRECORDEMPHASIS
1669 ,MPFROMP(pRecord)
1670 ,(MPARAM)CRA_SELECTED
1671 ));
1672 if (pRecord)
1673 nCount++;
1674 }
1675 return nCount;
1676} // end of wxListCtrl::GetSelectedItemCount
1677
1678// Gets the text colour of the listview
1679wxColour wxListCtrl::GetTextColour () const
1680{
1681 wxColour vCol;
1682 ULONG ulColor;
1683
1684 ::WinQueryPresParam( GetHWND()
1685 ,PP_FOREGROUNDCOLOR
1686 ,0
1687 ,NULL
1688 ,sizeof(ULONG)
1689 ,&ulColor
1690 ,QPF_PURERGBCOLOR
1691 );
1692 vCol.Set(ulColor);
1693 return vCol;
1694} // end of wxListCtrl::GetTextColour
1695
1696// Sets the text colour of the listview
1697void wxListCtrl::SetTextColour (
1698 const wxColour& rCol
1699)
1700{
1701 ULONG ulColor = wxColourToRGB(rCol);
1702
1703 ::WinSetPresParam( GetHWND()
1704 ,PP_FOREGROUNDCOLOR
1705 ,sizeof(ULONG)
1706 ,&ulColor
1707 );
1708} // end of wxListCtrl::SetTextColour
1709
1710// Gets the index of the topmost visible item when in
1711// list or report view
1712long wxListCtrl::GetTopItem () const
1713{
1714 PMYRECORD pRecord = NULL;
1715 QUERYRECFROMRECT vQueryRect;
1716 RECTL vRect;
1717
1718 ::WinSendMsg( GetHWND()
1719 ,CM_QUERYVIEWPORTRECT
1720 ,MPFROMP(&vRect)
1721 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
1722 );
1723 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
1724 vQueryRect.rect = vRect;
1725 vQueryRect.fsSearch = CMA_PARTIAL;
1726
1727 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1728 ,CM_QUERYRECORDFROMRECT
1729 ,(MPARAM)CMA_FIRST
1730 ,MPFROMP(&vQueryRect)
1731 );
1732
1733 if (!pRecord)
1734 return -1L;
1735 return (long)pRecord->m_ulItemId;
1736} // end of wxListCtrl::GetTopItem
1737
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
1744// specified flags.
1745// Returns the item or -1 if unsuccessful.
1746long wxListCtrl::GetNextItem (
1747 long lItem
1748, int WXUNUSED(nGeom)
1749, int WXUNUSED(nState)
1750) const
1751{
1752 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1753 ,lItem
1754 );
1755
1756 pRecord = (PMYRECORD)pRecord->m_vRecord.preccNextRecord;
1757 if (pRecord)
1758 return((long)pRecord->m_ulItemId);
1759 return -1L;
1760} // end of wxListCtrl::GetNextItem
1761
1762wxImageList* wxListCtrl::GetImageList (
1763 int nWhich
1764) const
1765{
1766 if (nWhich == wxIMAGE_LIST_NORMAL )
1767 {
1768 return m_pImageListNormal;
1769 }
1770 else if (nWhich == wxIMAGE_LIST_SMALL )
1771 {
1772 return m_pImageListSmall;
1773 }
1774 else if (nWhich == wxIMAGE_LIST_STATE )
1775 {
1776 return m_pImageListState;
1777 }
1778 return NULL;
1779} // end of wxListCtrl::GetImageList
1780
1781void wxListCtrl::SetImageList (
1782 wxImageList* pImageList
1783, int nWhich
1784)
1785{
1786 if (nWhich == wxIMAGE_LIST_NORMAL)
1787 {
1788 if (m_bOwnsImageListNormal)
1789 delete m_pImageListNormal;
1790 m_pImageListNormal = pImageList;
1791 m_bOwnsImageListNormal = FALSE;
1792 }
1793 else if (nWhich == wxIMAGE_LIST_SMALL)
1794 {
1795 if (m_bOwnsImageListSmall)
1796 delete m_pImageListSmall;
1797 m_pImageListSmall = pImageList;
1798 m_bOwnsImageListSmall = FALSE;
1799 }
1800 else if (nWhich == wxIMAGE_LIST_STATE)
1801 {
1802 if (m_bOwnsImageListState)
1803 delete m_pImageListState;
1804 m_pImageListState = pImageList;
1805 m_bOwnsImageListState = FALSE;
1806 }
1807} // end of wxListCtrl::SetImageList
1808
1809void wxListCtrl::AssignImageList (
1810 wxImageList* pImageList
1811, int nWhich
1812)
1813{
1814 SetImageList( pImageList
1815 ,nWhich
1816 );
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
1824
1825// ----------------------------------------------------------------------------
1826// Operations
1827// ----------------------------------------------------------------------------
1828
1829// Arranges the items
1830bool wxListCtrl::Arrange (
1831 int nFlag
1832)
1833{
1834 ULONG ulType = 0L;
1835 ULONG ulFlags = 0L;
1836
1837 if (nFlag == wxLIST_ALIGN_SNAP_TO_GRID)
1838 {
1839 ulType = CMA_ARRANGEGRID;
1840 if (nFlag == wxLIST_ALIGN_LEFT)
1841 ulFlags |= CMA_LEFT;
1842 else if (nFlag == wxLIST_ALIGN_TOP)
1843 ulFlags |= CMA_TOP;
1844 else if (nFlag == wxLIST_ALIGN_DEFAULT)
1845 ulFlags |= CMA_LEFT;
1846 }
1847 else
1848 ulType = CMA_ARRANGESTANDARD;
1849 ::WinSendMsg( GetHWND()
1850 ,CM_ARRANGE
1851 ,(MPARAM)ulType
1852 ,(MPARAM)ulFlags
1853 );
1854 //
1855 // We do not support CMA_ARRANGESELECTED
1856 //
1857 return TRUE;
1858} // end of wxListCtrl::Arrange
1859
1860// Deletes an item
1861bool wxListCtrl::DeleteItem (
1862 long lItem
1863)
1864{
1865 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1866 ,lItem
1867 );
1868 if (LONGFROMMR(::WinSendMsg( GetHWND()
1869 ,CM_REMOVERECORD
1870 ,(MPARAM)pRecord
1871 ,MPFROM2SHORT(1, CMA_FREE)
1872 )) == -1L)
1873 {
1874 return FALSE;
1875 }
1876
1877 //
1878 // The virtual list control doesn't refresh itself correctly, help it
1879 //
1880 if (IsVirtual())
1881 {
1882 //
1883 // We need to refresh all the lines below the one which was deleted
1884 //
1885 wxRect vRectItem;
1886
1887 if (lItem > 0 && GetItemCount())
1888 {
1889 GetItemRect( lItem - 1
1890 ,vRectItem
1891 );
1892 }
1893 else
1894 {
1895 vRectItem.y = vRectItem.height = 0;
1896 }
1897 wxRect vRectWin = GetRect();
1898
1899 vRectWin.height = vRectWin.GetBottom() - vRectItem.GetBottom();
1900 vRectWin.y = vRectItem.GetBottom();
1901 RefreshRect(vRectWin);
1902 }
1903 return TRUE;
1904} // end of wxListCtrl::DeleteItem
1905
1906// Deletes all items
1907bool wxListCtrl::DeleteAllItems ()
1908{
1909 return((LONG)::WinSendMsg( GetHWND()
1910 ,CM_REMOVERECORD
1911 ,NULL
1912 ,MPFROM2SHORT(0, CMA_FREE)
1913 ) != -1L);
1914} // end of wxListCtrl::DeleteAllItems
1915
1916// Deletes all items
1917bool wxListCtrl::DeleteAllColumns ()
1918{
1919 while (m_nColCount > 0)
1920 {
1921 DeleteColumn(m_nColCount - 1);
1922 m_nColCount--;
1923 }
1924
1925 wxASSERT_MSG(m_nColCount == 0, wxT("no columns should be left"));
1926 return TRUE;
1927} // end of wxListCtrl::DeleteAllColumns
1928
1929// Deletes a column
1930bool wxListCtrl::DeleteColumn (
1931 int nCol
1932)
1933{
1934 bool bSuccess = FALSE;
1935 PFIELDINFO pField = FindOS2ListFieldByColNum( GetHWND()
1936 ,nCol
1937 );
1938 bSuccess = ((LONG)::WinSendMsg( GetHWND()
1939 ,CM_REMOVEDETAILFIELDINFO
1940 ,MPFROMP(pField)
1941 ,MPFROM2SHORT((SHORT)1, CMA_FREE)
1942 ) == -1L);
1943 if (bSuccess && (m_nColCount > 0))
1944 m_nColCount--;
1945 return bSuccess;
1946} // end of wxListCtrl::DeleteColumn
1947
1948// Clears items, and columns if there are any.
1949void wxListCtrl::ClearAll ()
1950{
1951 DeleteAllItems();
1952 if (m_nColCount > 0)
1953 DeleteAllColumns();
1954} // end of wxListCtrl::ClearAll
1955
1956//
1957// OS/2 does not use a text control for its container labels. You merely
1958// "open" a record for editting.
1959//
1960wxTextCtrl* wxListCtrl::EditLabel (
1961 long lItem
1962, wxClassInfo* WXUNUSED(pTextControlClass)
1963)
1964{
1965 CNREDITDATA vEdit;
1966 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1967 ,lItem
1968 );
1969
1970 vEdit.cb = sizeof(CNREDITDATA);
1971 vEdit.hwndCnr = GetHWND();
1972 vEdit.pRecord = &pRecord->m_vRecord;
1973 vEdit.pFieldInfo = NULL;
1974 vEdit.ppszText = NULL;
1975 vEdit.cbText = 0;
1976 vEdit.id = 0;
1977
1978 ::WinSendMsg( GetHWND()
1979 ,CM_OPENEDIT
1980 ,MPFROMP(&vEdit)
1981 ,(MPARAM)0
1982 );
1983 return m_pTextCtrl;
1984} // end of wxListCtrl::EditLabel
1985
1986// End label editing, optionally cancelling the edit. Under OS/2 you close
1987// the record for editting
1988bool wxListCtrl::EndEditLabel (
1989 bool WXUNUSED(bCancel)
1990)
1991{
1992 ::WinSendMsg( GetHWND()
1993 ,CM_CLOSEEDIT
1994 ,(MPARAM)0
1995 ,(MPARAM)0
1996 );
1997 return TRUE;
1998} // end of wxListCtrl::EndEditLabel
1999
2000// Ensures this item is visible
2001bool wxListCtrl::EnsureVisible (
2002 long lItem
2003)
2004{
2005 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2006 ,lItem
2007 );
2008 ::WinSendMsg( GetHWND()
2009 ,CM_INVALIDATERECORD
2010 ,MPFROMP(pRecord)
2011 ,MPFROM2SHORT((SHORT)1, CMA_NOREPOSITION)
2012 );
2013 return TRUE;
2014} // end of wxListCtrl::EnsureVisible
2015
2016// Find an item whose label matches this string, starting from the item after 'start'
2017// or the beginning if 'start' is -1.
2018long wxListCtrl::FindItem (
2019 long lStart
2020, const wxString& rsStr
2021, bool bPartial
2022)
2023{
2024 CNRINFO vCnrInfo;
2025 SEARCHSTRING vSearch;
2026 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2027 ,lStart
2028 );
2029 ULONG ulFlag;
2030
2031
2032 if (!::WinSendMsg( GetHWND()
2033 ,CM_QUERYCNRINFO
2034 ,MPFROMP(&vCnrInfo)
2035 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2036 ))
2037 return -1L;
2038
2039 if (vCnrInfo.flWindowAttr & CV_ICON)
2040 ulFlag = CV_ICON;
2041 if (vCnrInfo.flWindowAttr & CV_NAME)
2042 ulFlag = CV_NAME;
2043 if (vCnrInfo.flWindowAttr & CV_TEXT)
2044 ulFlag = CV_TEXT;
2045 if (vCnrInfo.flWindowAttr & CV_DETAIL)
2046 ulFlag = CV_DETAIL;
2047 if (!bPartial)
2048 ulFlag |= CV_EXACTLENGTH;
2049
2050 vSearch.cb = sizeof(SEARCHSTRING);
2051 vSearch.pszSearch = (char*)rsStr.c_str();
2052 vSearch.fsPrefix = TRUE;
2053 vSearch.fsCaseSensitive = TRUE;
2054 vSearch.usView = ulFlag;
2055
2056 if (lStart == -1)
2057 {
2058 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2059 ,CM_SEARCHSTRING
2060 ,MPFROMP(&vSearch)
2061 ,(MPARAM)CMA_FIRST
2062 );
2063 }
2064 else
2065 {
2066 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2067 ,CM_SEARCHSTRING
2068 ,MPFROMP(&vSearch)
2069 ,MPFROMP(pRecord)
2070 );
2071 }
2072 if (!pRecord)
2073 return -1L;
2074 return pRecord->m_ulItemId;
2075} // end of wxListCtrl::FindItem
2076
2077// Find an item whose data matches this data, starting from the item after 'start'
2078// or the beginning if 'start' is -1.
2079long wxListCtrl::FindItem (
2080 long lStart
2081, long lData
2082)
2083{
2084 long lIdx = lStart + 1;
2085 long lCount = GetItemCount();
2086
2087 while (lIdx < lCount)
2088 {
2089 if (GetItemData(lIdx) == lData)
2090 return lIdx;
2091 lIdx++;
2092 };
2093 return -1;
2094} // end of wxListCtrl::FindItem
2095
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.
2098long wxListCtrl::FindItem (
2099 long lStart
2100, const wxPoint& rPoint
2101, int nDirection
2102)
2103{
2104 RECTL vRect;
2105 QUERYRECORDRECT vQueryRect;
2106 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2107 ,lStart
2108 );
2109 CNRINFO vCnrInfo;
2110 ULONG i;
2111 wxRect vLibRect;
2112
2113 if (!::WinSendMsg( GetHWND()
2114 ,CM_QUERYCNRINFO
2115 ,MPFROMP(&vCnrInfo)
2116 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2117 ))
2118 return -1L;
2119
2120 vQueryRect.cb = sizeof(QUERYRECORDRECT);
2121 vQueryRect.pRecord = &pRecord->m_vRecord;
2122 vQueryRect.fRightSplitWindow = TRUE;
2123 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
2124
2125 ::WinSendMsg( GetHWND()
2126 ,CM_QUERYRECORDRECT
2127 ,MPFROMP(&vRect)
2128 ,MPFROMP(&vQueryRect)
2129 );
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;
2136
2137 for (i = lStart + 1; i < vCnrInfo.cRecords; i++)
2138 {
2139 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
2140 ,CM_QUERYRECORD
2141 ,MPFROMP(pRecord)
2142 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
2143 ));
2144 vQueryRect.pRecord = (PRECORDCORE)pRecord;
2145 ::WinSendMsg( GetHWND()
2146 ,CM_QUERYRECORDRECT
2147 ,MPFROMP(&vRect)
2148 ,MPFROMP(&vQueryRect)
2149 );
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;
2156 }
2157 return -1L;
2158} // end of wxListCtrl::FindItem
2159
2160// Determines which item (if any) is at the specified point,
2161// giving details in 'flags' (see wxLIST_HITTEST_... flags above)
2162long wxListCtrl::HitTest (
2163 const wxPoint& rPoint
2164, int& WXUNUSED(rFlags)
2165)
2166{
2167 PMYRECORD pRecord = NULL;
2168 QUERYRECFROMRECT vQueryRect;
2169 RECTL vRect;
2170 long lHeight;
2171
2172 //
2173 // Get height for OS/2 point conversion
2174 //
2175 ::WinSendMsg( GetHWND()
2176 ,CM_QUERYVIEWPORTRECT
2177 ,MPFROMP(&vRect)
2178 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
2179 );
2180 lHeight = vRect.yTop - vRect.yBottom;
2181
2182 //
2183 // For now just try and get a record in the general vicinity and forget
2184 // the flag
2185 //
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;
2190
2191 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
2192 vQueryRect.rect = vRect;
2193 vQueryRect.fsSearch = CMA_PARTIAL;
2194
2195 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2196 ,CM_QUERYRECORDFROMRECT
2197 ,(MPARAM)CMA_FIRST
2198 ,MPFROMP(&vQueryRect)
2199 );
2200
2201 if (!pRecord)
2202 return -1L;
2203 return pRecord->m_ulItemId;
2204} // end of wxListCtrl::HitTest
2205
2206// Inserts an item, returning the index of the new item if successful,
2207// -1 otherwise.
2208long wxListCtrl::InsertItem (
2209 wxListItem& rInfo
2210)
2211{
2212 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
2213
2214 PMYRECORD pRecordAfter = FindOS2ListRecordByID ( GetHWND()
2215 ,rInfo.GetId() - 1
2216 );
2217 PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2218 ,CM_ALLOCRECORD
2219 ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
2220 ,MPFROMLONG(1)
2221 );
2222 RECORDINSERT vInsert;
2223
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;
2230
2231 ConvertToOS2ListItem( this
2232 ,rInfo
2233 ,pRecord
2234 );
2235
2236 //
2237 // Check wether we need to allocate our internal data
2238 //
2239 bool bNeedInternalData = ((rInfo.GetMask() & wxLIST_MASK_DATA) ||
2240 rInfo.HasAttributes()
2241 );
2242 if (bNeedInternalData)
2243 {
2244 m_bAnyInternalData = TRUE;
2245
2246 //
2247 // Internal stucture that manages data
2248 //
2249 CListItemInternalData* pData = new CListItemInternalData();
2250
2251 pRecord->m_ulUserData = (unsigned long)pData;
2252 if (rInfo.GetMask() & wxLIST_MASK_DATA)
2253 pData->m_lParam = (WXLPARAM)rInfo.GetData();
2254
2255 //
2256 // Check whether it has any custom attributes
2257 //
2258 if (rInfo.HasAttributes())
2259 {
2260 //
2261 // Take copy of attributes
2262 //
2263 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
2264 }
2265 }
2266 ::WinSendMsg( GetHWND()
2267 ,CM_INSERTRECORD
2268 ,MPFROMP(pRecord)
4fd899b6 2269 ,MPFROMP(&vInsert)
c4f4cf89
DW
2270 );
2271 //
2272 // OS/2 must mannually bump the index's of following records
2273 //
2274 BumpRecordIds( GetHWND()
2275 ,pRecord
2276 );
2277 return pRecord->m_ulItemId;
2278} // end of wxListCtrl::InsertItem
2279
2280long wxListCtrl::InsertItem (
2281 long lIndex
2282, const wxString& rsLabel
2283)
2284{
2285 wxListItem vInfo;
2286
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
2292
2293// Inserts an image item
2294long wxListCtrl::InsertItem (
2295 long lIndex
2296, int nImageIndex
2297)
2298{
2299 wxListItem vInfo;
2300
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
2306
2307// Inserts an image/string item
2308long wxListCtrl::InsertItem (
2309 long lIndex
2310, const wxString& rsLabel
2311, int nImageIndex
2312)
2313{
2314 wxListItem vInfo;
2315
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
2322
2323// For details view mode (only), inserts a column.
2324long wxListCtrl::InsertColumn (
2325 long lCol
2326, wxListItem& rItem
2327)
2328{
2329 bool bSuccess;
2330 PFIELDINFO pField = (PFIELDINFO)::WinSendMsg( GetHWND()
2331 ,CM_ALLOCDETAILFIELDINFO
2332 ,MPFROMLONG(1)
2333 ,NULL
2334 );
2335 PFIELDINFO pFieldAfter = FindOS2ListFieldByColNum ( GetHWND()
2336 ,lCol - 1
2337 );
2338 FIELDINFOINSERT vInsert;
2339
2340 vInsert.cb = sizeof(FIELDINFOINSERT);
2341 vInsert.pFieldInfoOrder = pFieldAfter;
2342 vInsert.fInvalidateFieldInfo = TRUE;
2343 vInsert.cFieldInfoInsert = 1;
2344
2345 ConvertToOS2ListCol ( lCol
2346 ,rItem
2347 ,pField
2348 );
2349 bSuccess = ::WinSendMsg( GetHWND()
2350 ,CM_INSERTDETAILFIELDINFO
2351 ,MPFROMP(pField)
2352 ,MPFROMP(&vInsert)
2353 ) != (MRESULT)0;
2354 return bSuccess;
2355} // end of wxListCtrl::InsertColumn
2356
2357long wxListCtrl::InsertColumn (
2358 long lCol
2359, const wxString& rsHeading
2360, int nFormat
2361, int nWidth
2362)
2363{
2364 wxListItem vItem;
2365
2366 vItem.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2367 vItem.m_text = rsHeading;
2368 if (nWidth > -1)
2369 {
2370 vItem.m_mask |= wxLIST_MASK_WIDTH;
2371 vItem.m_width = nWidth;
2372 }
2373 vItem.m_format = nFormat;
2374
2375 return InsertColumn( lCol
2376 ,vItem
2377 );
2378} // end of wxListCtrl::InsertColumn
2379
2380// scroll the control by the given number of pixels (exception: in list view,
2381// dx is interpreted as number of columns)
2382bool wxListCtrl::ScrollList (
2383 int nDx
2384, int nDy
2385)
2386{
2387 if (nDx > 0)
2388 ::WinSendMsg( GetHWND()
2389 ,CM_SCROLLWINDOW
2390 ,(MPARAM)CMA_HORIZONTAL
2391 ,(MPARAM)nDx
2392 );
2393 if (nDy > 0)
2394 ::WinSendMsg( GetHWND()
2395 ,CM_SCROLLWINDOW
2396 ,(MPARAM)CMA_VERTICAL
2397 ,(MPARAM)nDy
2398 );
2399 return TRUE;
2400} // end of wxListCtrl::ScrollList
2401
2402bool wxListCtrl::SortItems (
2403 wxListCtrlCompare fn
2404, long lData
2405)
2406{
2407 SInternalDataSort vInternalData;
2408
2409 vInternalData.m_fnUser = fn;
2410 vInternalData.m_lData = lData;
2411
2412 // WPARAM cast is needed for mingw/cygwin
2413 if (!::WinSendMsg( GetHWND()
2414 ,CM_SORTRECORD
2415 ,(PFN)InternalDataCompareFunc
2416 ,(PVOID)&vInternalData
2417 ))
2418 {
2419 wxLogDebug(_T("CM_SORTRECORD failed"));
2420 return FALSE;
2421 }
2422 return TRUE;
2423} // end of wxListCtrl::SortItems
2424
2425// ----------------------------------------------------------------------------
2426// message processing
2427// ----------------------------------------------------------------------------
2428
2429bool wxListCtrl::OS2Command (
2430 WXUINT uCmd
2431, WXWORD wId
2432)
2433{
2434 if (uCmd == CN_ENDEDIT)
2435 {
2436 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
2437 ,wId
2438 );
2439
2440 vEvent.SetEventObject( this );
2441 ProcessCommand(vEvent);
2442 return TRUE;
2443 }
2444 else if (uCmd == CN_KILLFOCUS)
2445 {
2446 wxCommandEvent vEvent( wxEVT_KILL_FOCUS
2447 ,wId
2448 );
2449 vEvent.SetEventObject( this );
2450 ProcessCommand(vEvent);
2451 return TRUE;
2452 }
2453 else
2454 return FALSE;
2455} // end of wxListCtrl::OS2Command
2456
2457// Necessary for drawing hrules and vrules, if specified
2458void wxListCtrl::OnPaint (
2459 wxPaintEvent& rEvent
2460)
2461{
2462 wxPaintDC vDc(this);
2463 wxPen vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT)
2464 ,1
2465 ,wxSOLID
2466 );
2467 wxSize vClientSize = GetClientSize();
2468 wxRect vItemRect;
2469 int nItemCount = GetItemCount();
2470 int nCy = 0;
2471 int i;
2472 bool bDrawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
2473 bool bDrawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
2474
2475 wxControl::OnPaint(rEvent);
2476
2477 //
2478 // Reset the device origin since it may have been set
2479 //
2480 vDc.SetDeviceOrigin(0, 0);
2481 if (!bDrawHRules && !bDrawVRules)
2482 return;
2483 if ((GetWindowStyle() & wxLC_REPORT) == 0)
2484 return;
2485 vDc.SetPen(vPen);
2486 vDc.SetBrush(*wxTRANSPARENT_BRUSH);
2487
2488 if (bDrawHRules)
2489 {
2490 long lTop = GetTopItem();
2491
2492 for (i = lTop; i < lTop + GetCountPerPage() + 1; i++)
2493 {
2494 if (GetItemRect( i
2495 ,vItemRect
2496 ))
2497 {
2498 nCy = vItemRect.GetTop();
2499 if (i != 0) // Don't draw the first one
2500 {
2501 vDc.DrawLine( 0
2502 ,nCy
2503 ,vClientSize.x
2504 ,nCy
2505 );
2506 }
2507 // Draw last line
2508 if (i == nItemCount - 1)
2509 {
2510 nCy = vItemRect.GetBottom();
2511 vDc.DrawLine( 0
2512 ,nCy
2513 ,vClientSize.x
2514 ,nCy
2515 );
2516 }
2517 }
2518 }
2519 }
2520 i = nItemCount - 1;
2521 if (bDrawVRules && (i > -1))
2522 {
2523 wxRect vFirstItemRect;
2524
2525 GetItemRect( 0
2526 ,vFirstItemRect
2527 );
2528 if (GetItemRect( i
2529 ,vItemRect
2530 ))
2531 {
2532 int nCol;
2533 int nX = vItemRect.GetX();
2534
2535 for (nCol = 0; nCol < GetColumnCount(); nCol++)
2536 {
2537 int nColWidth = GetColumnWidth(nCol);
2538
2539 nX += nColWidth ;
2540 vDc.DrawLine( nX - 1
2541 ,vFirstItemRect.GetY() - 2
2542 ,nX - 1
2543 ,vItemRect.GetBottom()
2544 );
2545 }
2546 }
2547 }
2548} // end of wxListCtrl::OnPaint
2549
2550// ----------------------------------------------------------------------------
2551// virtual list controls
2552// ----------------------------------------------------------------------------
2553
2554wxString wxListCtrl::OnGetItemText (
2555 long WXUNUSED(lItem)
2556, long WXUNUSED(lCol)
2557) const
2558{
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
2564
2565int wxListCtrl::OnGetItemImage (
2566 long WXUNUSED(lItem)
2567) const
2568{
2569 // same as above
2570 wxFAIL_MSG( _T("not supposed to be called") );
2571 return -1;
2572} // end of wxListCtrl::OnGetItemImage
2573
2574wxListItemAttr* wxListCtrl::OnGetItemAttr (
2575 long WXUNUSED_UNLESS_DEBUG(lItem)
2576) const
2577{
2578 wxASSERT_MSG( lItem >= 0 && lItem < GetItemCount(),
2579 _T("invalid item index in OnGetItemAttr()") );
2580
2581 //
2582 // No attributes by default
2583 //
2584 return NULL;
2585} // end of wxListCtrl::OnGetItemAttr
2586
2587void wxListCtrl::SetItemCount (
2588 long lCount
2589)
2590{
2591 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
2592
2593 //
2594 // Cannot explicitly set the record count in OS/2
2595 //
2596} // end of wxListCtrl::SetItemCount
2597
2598void wxListCtrl::RefreshItem (
2599 long lItem
2600)
2601{
2602 wxRect vRect;
2603
2604 GetItemRect( lItem
2605 ,vRect
2606 );
2607 RefreshRect(vRect);
2608} // end of wxListCtrl::RefreshItem
2609
2610void wxListCtrl::RefreshItems (
2611 long lItemFrom
2612, long lItemTo
2613)
2614{
2615 wxRect vRect1;
2616 wxRect vRect2;
2617
2618 GetItemRect( lItemFrom
2619 ,vRect1
2620 );
2621 GetItemRect( lItemTo
2622 ,vRect2
2623 );
2624
2625 wxRect vRect = vRect1;
2626
2627 vRect.height = vRect2.GetBottom() - vRect1.GetTop();
2628 RefreshRect(vRect);
2629} // end of wxListCtrl::RefreshItems
2630
2631MRESULT wxListCtrl::OS2WindowProc(
2632 WXUINT uMsg
2633, WXWPARAM wParam
2634, WXLPARAM lParam
2635)
2636{
2637 bool bProcessed = FALSE;
2638 MRESULT lRc;
2639 wxListEvent vEvent( wxEVT_NULL
2640 ,m_windowId
2641 );
2642 wxEventType vEventType = wxEVT_NULL;
2643 PCNRDRAGINIT pDragInit = NULL;
2644 PCNREDITDATA pEditData = NULL;
2645 PNOTIFYRECORDENTER pNotifyEnter = NULL;
2646
2647 vEvent.SetEventObject(this);
2648 switch (uMsg)
2649 {
2650 case WM_CONTROL:
2651 //
2652 // First off let's set some internal data
2653 //
2654 switch(SHORT2FROMMP(wParam))
2655 {
2656 case CN_INITDRAG:
2657 case CN_DRAGOVER:
2658 case CN_DRAGAFTER:
2659 {
2660 CListItemInternalData* pInternaldata = (CListItemInternalData *)lParam;
2661
2662 if (pInternaldata)
2663 {
2664 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2665
2666 pItem->SetData((long)pInternaldata->m_lParam);
2667 }
2668 }
2669 break;
2670 }
2671 //
2672 // Now let's go through the codes we're interested in
2673 //
2674 switch(SHORT2FROMMP(wParam))
2675 {
2676 case CN_INITDRAG:
2677 pDragInit = (PCNRDRAGINIT)lParam;
2678 if (pDragInit)
2679 {
2680 PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
2681
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;
2686 }
2687 break;
2688
2689 case CN_BEGINEDIT:
2690 pEditData = (PCNREDITDATA)lParam;
2691 if (pEditData)
2692 {
2693 vEventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
2694 ConvertFromOS2ListItem( GetHWND()
2695 ,(wxListItem &)vEvent.GetItem()
2696 ,(PMYRECORD)pEditData->pRecord
2697 );
2698 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2699 }
2700 break;
2701
2702 case CN_ENDEDIT:
2703 pEditData = (PCNREDITDATA)lParam;
2704 if (pEditData)
2705 {
2706 vEventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
2707 ConvertFromOS2ListItem( GetHWND()
2708 ,(wxListItem &)vEvent.GetItem()
2709 ,(PMYRECORD)pEditData->pRecord
2710 );
2711 if (pEditData->cbText == 0)
2712 return (MRESULT)FALSE;
2713 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2714 }
2715 break;
2716
2717 case CN_ENTER:
2718 pNotifyEnter = (PNOTIFYRECORDENTER)lParam;
2719 if (pNotifyEnter)
2720 {
2721 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2722 PMYRECORD pMyRecord = (PMYRECORD)pNotifyEnter->pRecord;
2723
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));
2728 }
2729 break;
2730
2731 //
2732 // Add the CN_DROP messages for Direct Manipulation
2733 //
2734 }
2735 vEvent.SetEventType(vEventType);
2736 bProcessed = GetEventHandler()->ProcessEvent(vEvent);
2737 break;
2738 }
2739 if (!bProcessed)
2740 lRc = wxControl::OS2WindowProc( uMsg
2741 ,wParam
2742 ,lParam
2743 );
2744 return lRc;
2745} // end of wxListCtrl::WindowProc
2746
2747#endif // wxUSE_LISTCTRL