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