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