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