Include wx/dcclient.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / os2 / listctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/listctrl.cpp
3 // Purpose: wxListCtrl
4 // Author: David Webster
5 // Modified by:
6 // Created: 01/21/03
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
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 #include "wx/dcclient.h"
35 #endif
36
37 #include "wx/textctrl.h"
38 #include "wx/imaglist.h"
39 #include "wx/listctrl.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
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
59 // byte value containing a pointer to our CListIntemInternalData class
60 // instance.
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.
67 // the wxWidgets wxLC_REPORT view, relies on STATIC structure for its
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.
71 // wxWidgets is dynamic in nature, however. We insert columns, one at a
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.
85 /////////////////////////////////////////////////////////////////////////////
86 typedef struct _MYRECORD
87 {
88 RECORDCORE m_vRecord;
89 unsigned long m_ulItemId;
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;
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
114 // List item independent of its position in the list is to store a pointer
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 /////////////////////////////////////////////////////////////////////////////
133 class CListItemInternalData
134 {
135 public:
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 /////////////////////////////////////////////////////////////////////////////
171 typedef 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 /////////////////////////////////////////////////////////////////////////////
197 PFIELDINFO 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 /////////////////////////////////////////////////////////////////////////////
252 PMYRECORD 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 /////////////////////////////////////////////////////////////////////////////
305 void 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 /////////////////////////////////////////////////////////////////////////////
340 CListItemInternalData* 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 /////////////////////////////////////////////////////////////////////////////
370 CListItemInternalData* 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 /////////////////////////////////////////////////////////////////////////////
394 void 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 /////////////////////////////////////////////////////////////////////////////
426 wxListItemAttr* 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 /////////////////////////////////////////////////////////////////////////////
457 SHORT 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 /////////////////////////////////////////////////////////////////////////////
490 void 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 /////////////////////////////////////////////////////////////////////////////
583 void 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
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
617 //
618 // RETURN VALUE
619 // none
620 //
621 /////////////////////////////////////////////////////////////////////////////
622 void ConvertToOS2ListItem (
623 const wxListCtrl* pCtrl
624 , const wxListItem& rInfo
625 , PMYRECORD pRecord
626 , PFIELDINFO pFieldInfo
627 )
628 {
629 pRecord->m_ulItemId = (ULONG)rInfo.GetId();
630 pRecord->m_vRecord.cb = sizeof(RECORDCORE);
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 }
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 }
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 /////////////////////////////////////////////////////////////////////////////
734 void ConvertToOS2ListCol (
735 long lCol
736 , const wxListItem& rItem
737 , PFIELDINFO pField
738 )
739 {
740 memset(pField, '\0', sizeof(FIELDINFO));
741 pField->cb = sizeof(FIELDINFO);
742
743 //
744 // Default some settings
745 //
746 pField->flData = CFA_HORZSEPARATOR | CFA_SEPARATOR;
747 pField->flTitle = CFA_CENTER;
748
749 if (rItem.GetMask() & wxLIST_MASK_TEXT)
750 {
751 pField->flData |= CFA_STRING;
752 pField->pTitleData = (PVOID)rItem.GetText().c_str(); // text is column title not data
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 }
763 else
764 pField->flData |= CFA_CENTER; // Just ensure the default is centered
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 }
772
773 //
774 // Still need to set the actual data
775 //
776 pField->offStruct = 0;
777 } // end of ConvertToOS2ListCol
778
779 // ----------------------------------------------------------------------------
780 // events
781 // ----------------------------------------------------------------------------
782
783 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG)
784 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG)
785 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
786 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
787 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
788 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
789 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
790 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
791 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
792 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
793 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
794 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
795 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
796 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK)
797 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG)
798 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING)
799 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG)
800 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
801 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
802 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
803 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED)
804 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
805
806 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
807 IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
808 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
809
810 IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
811
812 BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
813 EVT_PAINT(wxListCtrl::OnPaint)
814 END_EVENT_TABLE()
815
816 // ============================================================================
817 // implementation
818 // ============================================================================
819
820 // ----------------------------------------------------------------------------
821 // wxListCtrl construction
822 // ----------------------------------------------------------------------------
823
824 void 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
839 bool 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
888 bool 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 ))
928 return FALSE;
929 lWstyle = ConvertViewToOS2Style(GetWindowStyleFlag());
930 vCnrInfo.flWindowAttr |= lWstyle;
931 if (!::WinSendMsg( GetHWND()
932 ,CM_SETCNRINFO
933 ,MPFROMP(&vCnrInfo)
934 ,(MPARAM)CMA_FLWINDOWATTR
935 ))
936 return FALSE;
937
938 //
939 // And now set needed arrangement flags
940 //
941 lWstyle = ConvertArrangeToOS2Style(GetWindowStyleFlag());
942 if (!::WinSendMsg( GetHWND()
943 ,CM_ARRANGE
944 ,(MPARAM)CMA_ARRANGEGRID
945 ,(MPARAM)lWstyle
946 ))
947 return FALSE;
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
962 void 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
988 void 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
1001 wxListCtrl::~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
1025 void 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
1061 void wxListCtrl::SetWindowStyleFlag (
1062 long lFlag
1063 )
1064 {
1065 m_windowStyle = lFlag;
1066 UpdateStyle();
1067 } // end of wxListCtrl::SetWindowStyleFlag
1068
1069 long 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
1092 long 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
1110 long 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
1152 bool 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
1170 bool 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
1192 bool 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
1223 bool 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
1243 int 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
1257 bool 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)
1280 int 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.
1325 wxTextCtrl* wxListCtrl::GetEditControl() const
1326 {
1327 return m_pTextCtrl;
1328 }
1329
1330 // Gets information about the item
1331 bool 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
1350 bool wxListCtrl::SetItem (
1351 wxListItem& rInfo
1352 )
1353 {
1354 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
1355 ,rInfo.GetColumn()
1356 );
1357 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1358 ,rInfo.GetId()
1359 );
1360
1361 ConvertToOS2ListItem( this
1362 ,rInfo
1363 ,pRecord
1364 ,pFieldInfo
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 }
1404 pData->m_pMyRecord = pRecord; // they point to each other
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 }
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 }
1433 ::WinSendMsg( GetHWND()
1434 ,CM_INVALIDATEDETAILFIELDINFO
1435 ,NULL
1436 ,NULL
1437 );
1438 return TRUE;
1439 } // end of wxListCtrl::SetItem
1440
1441 long 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
1463 int 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
1480 bool 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
1542 bool wxListCtrl::SetItemImage (
1543 long lItem
1544 , int nImage
1545 , int WXUNUSED(nSelImage))
1546 {
1547 return SetItemColumnInfo(lItem, 0, nImage);
1548 } // end of wxListCtrl::SetItemImage
1549
1550 // Sets the item image
1551 bool wxListCtrl::SetItemColumnImage (
1552 long lItem
1553 , long lColumn
1554 , int nImage
1555 {
1556 wxListItem vInfo;
1557
1558 vInfo.m_mask = wxLIST_MASK_IMAGE;
1559 vInfo.m_image = nImage;
1560 vInfo.m_itemId = lItem;
1561 vInfo.m_col = lColumn;
1562 return SetItem(vInfo);
1563 } // end of wxListCtrl::SetItemColumnImage
1564
1565 // Gets the item text
1566 wxString wxListCtrl::GetItemText (
1567 long lItem
1568 ) const
1569 {
1570 wxListItem vInfo;
1571
1572 vInfo.m_mask = wxLIST_MASK_TEXT;
1573 vInfo.m_itemId = lItem;
1574
1575 if (!GetItem(vInfo))
1576 return wxEmptyString;
1577 return vInfo.m_text;
1578 } // end of wxListCtrl::GetItemText
1579
1580 // Sets the item text
1581 void wxListCtrl::SetItemText (
1582 long lItem
1583 , const wxString& rsStr
1584 )
1585 {
1586 wxListItem vInfo;
1587
1588 vInfo.m_mask = wxLIST_MASK_TEXT;
1589 vInfo.m_itemId = lItem;
1590 vInfo.m_text = rsStr;
1591 SetItem(vInfo);
1592 } // end of wxListCtrl::SetItemText
1593
1594 // Gets the item data
1595 long wxListCtrl::GetItemData (
1596 long lItem
1597 ) const
1598 {
1599 wxListItem vInfo;
1600
1601 vInfo.m_mask = wxLIST_MASK_DATA;
1602 vInfo.m_itemId = lItem;
1603 if (!GetItem(vInfo))
1604 return 0;
1605 return vInfo.m_data;
1606 } // end of wxListCtrl::GetItemData
1607
1608 // Sets the item data
1609 bool wxListCtrl::SetItemData (
1610 long lItem
1611 , long lData
1612 )
1613 {
1614 wxListItem vInfo;
1615
1616 vInfo.m_mask = wxLIST_MASK_DATA;
1617 vInfo.m_itemId = lItem;
1618 vInfo.m_data = lData;
1619 return SetItem(vInfo);
1620 } // end of wxListCtrl::SetItemData
1621
1622 // Gets the item rectangle
1623 bool wxListCtrl::GetItemRect (
1624 long lItem
1625 , wxRect& rRect
1626 , int nCode
1627 ) const
1628 {
1629 bool bSuccess;
1630 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1631 ,lItem
1632 );
1633 QUERYRECORDRECT vQueryRect;
1634 RECTL vRect;
1635 int nHeight;
1636
1637 if (!pRecord)
1638 return FALSE;
1639 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1640 vQueryRect.pRecord = &pRecord->m_vRecord;
1641 vQueryRect.fRightSplitWindow = TRUE;
1642 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1643 ::WinSendMsg( GetHWND()
1644 ,CM_QUERYRECORDRECT
1645 ,MPFROMP(&vRect)
1646 ,MPFROMP(&vQueryRect)
1647 );
1648 //
1649 // remember OS/2 is backwards
1650 //
1651 GetClientSize( NULL
1652 ,&nHeight
1653 );
1654 rRect.x = vRect.xLeft;
1655 rRect.y = nHeight - vRect.yTop;
1656 rRect.width = vRect.xRight;
1657 rRect.height = nHeight - vRect.yBottom;
1658 bSuccess = TRUE;
1659 return bSuccess;
1660 } // end of wxListCtrl::GetItemRect
1661
1662 // Gets the item position
1663 bool wxListCtrl::GetItemPosition (
1664 long lItem
1665 , wxPoint& rPos
1666 ) const
1667 {
1668 bool bSuccess;
1669 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1670 ,lItem
1671 );
1672 QUERYRECORDRECT vQueryRect;
1673 RECTL vRect;
1674 int nHeight;
1675
1676 if (!pRecord)
1677 return FALSE;
1678 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1679 vQueryRect.pRecord = &pRecord->m_vRecord;
1680 vQueryRect.fRightSplitWindow = TRUE;
1681 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1682 ::WinSendMsg( GetHWND()
1683 ,CM_QUERYRECORDRECT
1684 ,MPFROMP(&vRect)
1685 ,MPFROMP(&vQueryRect)
1686 );
1687 //
1688 // remember OS/2 is backwards
1689 //
1690 GetClientSize( NULL
1691 ,&nHeight
1692 );
1693 rPos.x = vRect.xLeft;
1694 rPos.y = nHeight - vRect.yTop;
1695 bSuccess = TRUE;
1696 return bSuccess;
1697 } // end of wxListCtrl::GetItemPosition
1698
1699 // Sets the item position.
1700 bool wxListCtrl::SetItemPosition (
1701 long lItem
1702 , const wxPoint& rPos
1703 )
1704 {
1705 //
1706 // Items cannot be positioned in X/Y coord in OS/2
1707 //
1708 return FALSE;
1709 } // end of wxListCtrl::SetItemPosition
1710
1711 // Gets the number of items in the list control
1712 int wxListCtrl::GetItemCount () const
1713 {
1714 CNRINFO vCnrInfo;
1715
1716 if (!::WinSendMsg( GetHWND()
1717 ,CM_QUERYCNRINFO
1718 ,MPFROMP(&vCnrInfo)
1719 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1720 ))
1721 return -1;
1722 return vCnrInfo.cRecords;
1723 } // end of wxListCtrl::GetItemCount
1724
1725 // Retrieves the spacing between icons in pixels.
1726 // If small is TRUE, gets the spacing for the small icon
1727 // view, otherwise the large icon view.
1728 int wxListCtrl::GetItemSpacing (
1729 bool bIsSmall
1730 ) const
1731 {
1732 CNRINFO vCnrInfo;
1733
1734 if (!::WinSendMsg( GetHWND()
1735 ,CM_QUERYCNRINFO
1736 ,MPFROMP(&vCnrInfo)
1737 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1738 ))
1739 return -1;
1740 return vCnrInfo.cyLineSpacing;
1741 } // end of wxListCtrl::GetItemSpacing
1742
1743 void wxListCtrl::SetItemTextColour (
1744 long lItem
1745 , const wxColour& rCol
1746 )
1747 {
1748 wxListItem vInfo;
1749
1750 vInfo.m_itemId = lItem;
1751 vInfo.SetTextColour(rCol);
1752 SetItem(vInfo);
1753 } // end of wxListCtrl::SetItemTextColour
1754
1755 wxColour wxListCtrl::GetItemTextColour (
1756 long lItem
1757 ) const
1758 {
1759 wxListItem vInfo;
1760
1761 vInfo.m_itemId = lItem;
1762 GetItem(vInfo);
1763 return vInfo.GetTextColour();
1764 } // end of wxListCtrl::GetItemTextColour
1765
1766 void wxListCtrl::SetItemBackgroundColour (
1767 long lItem
1768 , const wxColour& rCol
1769 )
1770 {
1771 wxListItem vInfo;
1772
1773 vInfo.m_itemId = lItem;
1774 vInfo.SetBackgroundColour(rCol);
1775 SetItem(vInfo);
1776 } // end of wxListCtrl::SetItemBackgroundColour
1777
1778 wxColour wxListCtrl::GetItemBackgroundColour (
1779 long lItem
1780 ) const
1781 {
1782 wxListItem vInfo;
1783
1784 vInfo.m_itemId = lItem;
1785 GetItem(vInfo);
1786 return vInfo.GetBackgroundColour();
1787 } // end of wxListCtrl::GetItemBackgroundColour
1788
1789 // Gets the number of selected items in the list control
1790 int wxListCtrl::GetSelectedItemCount () const
1791 {
1792 PMYRECORD pRecord = NULL;
1793 int nCount = 0;
1794 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1795 ,CM_QUERYRECORDEMPHASIS
1796 ,(MPARAM)CMA_FIRST
1797 ,(MPARAM)CRA_SELECTED
1798 ));
1799 if (pRecord)
1800 nCount++;
1801 else
1802 return 0;
1803 while (pRecord)
1804 {
1805 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1806 ,CM_QUERYRECORDEMPHASIS
1807 ,MPFROMP(pRecord)
1808 ,(MPARAM)CRA_SELECTED
1809 ));
1810 if (pRecord)
1811 nCount++;
1812 }
1813 return nCount;
1814 } // end of wxListCtrl::GetSelectedItemCount
1815
1816 // Gets the text colour of the listview
1817 wxColour wxListCtrl::GetTextColour () const
1818 {
1819 wxColour vCol;
1820 ULONG ulColor;
1821
1822 ::WinQueryPresParam( GetHWND()
1823 ,PP_FOREGROUNDCOLOR
1824 ,0
1825 ,NULL
1826 ,sizeof(ULONG)
1827 ,&ulColor
1828 ,QPF_PURERGBCOLOR
1829 );
1830 vCol.Set(ulColor);
1831 return vCol;
1832 } // end of wxListCtrl::GetTextColour
1833
1834 // Sets the text colour of the listview
1835 void wxListCtrl::SetTextColour (
1836 const wxColour& rCol
1837 )
1838 {
1839 ULONG ulColor = wxColourToRGB(rCol);
1840
1841 ::WinSetPresParam( GetHWND()
1842 ,PP_FOREGROUNDCOLOR
1843 ,sizeof(ULONG)
1844 ,&ulColor
1845 );
1846 } // end of wxListCtrl::SetTextColour
1847
1848 // Gets the index of the topmost visible item when in
1849 // list or report view
1850 long wxListCtrl::GetTopItem () const
1851 {
1852 PMYRECORD pRecord = NULL;
1853 QUERYRECFROMRECT vQueryRect;
1854 RECTL vRect;
1855
1856 ::WinSendMsg( GetHWND()
1857 ,CM_QUERYVIEWPORTRECT
1858 ,MPFROMP(&vRect)
1859 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
1860 );
1861 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
1862 vQueryRect.rect = vRect;
1863 vQueryRect.fsSearch = CMA_PARTIAL;
1864
1865 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1866 ,CM_QUERYRECORDFROMRECT
1867 ,(MPARAM)CMA_FIRST
1868 ,MPFROMP(&vQueryRect)
1869 );
1870
1871 if (!pRecord)
1872 return -1L;
1873 return (long)pRecord->m_ulItemId;
1874 } // end of wxListCtrl::GetTopItem
1875
1876 // Searches for an item, starting from 'item'.
1877 // 'geometry' is one of
1878 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
1879 // 'state' is a state bit flag, one or more of
1880 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
1881 // item can be -1 to find the first item that matches the
1882 // specified flags.
1883 // Returns the item or -1 if unsuccessful.
1884 long wxListCtrl::GetNextItem (
1885 long lItem
1886 , int WXUNUSED(nGeom)
1887 , int WXUNUSED(nState)
1888 ) const
1889 {
1890 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1891 ,lItem
1892 );
1893
1894 pRecord = (PMYRECORD)pRecord->m_vRecord.preccNextRecord;
1895 if (pRecord)
1896 return((long)pRecord->m_ulItemId);
1897 return -1L;
1898 } // end of wxListCtrl::GetNextItem
1899
1900 wxImageList* wxListCtrl::GetImageList (
1901 int nWhich
1902 ) const
1903 {
1904 if (nWhich == wxIMAGE_LIST_NORMAL )
1905 {
1906 return m_pImageListNormal;
1907 }
1908 else if (nWhich == wxIMAGE_LIST_SMALL )
1909 {
1910 return m_pImageListSmall;
1911 }
1912 else if (nWhich == wxIMAGE_LIST_STATE )
1913 {
1914 return m_pImageListState;
1915 }
1916 return NULL;
1917 } // end of wxListCtrl::GetImageList
1918
1919 void wxListCtrl::SetImageList (
1920 wxImageList* pImageList
1921 , int nWhich
1922 )
1923 {
1924 if (nWhich == wxIMAGE_LIST_NORMAL)
1925 {
1926 if (m_bOwnsImageListNormal)
1927 delete m_pImageListNormal;
1928 m_pImageListNormal = pImageList;
1929 m_bOwnsImageListNormal = FALSE;
1930 }
1931 else if (nWhich == wxIMAGE_LIST_SMALL)
1932 {
1933 if (m_bOwnsImageListSmall)
1934 delete m_pImageListSmall;
1935 m_pImageListSmall = pImageList;
1936 m_bOwnsImageListSmall = FALSE;
1937 }
1938 else if (nWhich == wxIMAGE_LIST_STATE)
1939 {
1940 if (m_bOwnsImageListState)
1941 delete m_pImageListState;
1942 m_pImageListState = pImageList;
1943 m_bOwnsImageListState = FALSE;
1944 }
1945 } // end of wxListCtrl::SetImageList
1946
1947 void wxListCtrl::AssignImageList (
1948 wxImageList* pImageList
1949 , int nWhich
1950 )
1951 {
1952 SetImageList( pImageList
1953 ,nWhich
1954 );
1955 if (nWhich == wxIMAGE_LIST_NORMAL )
1956 m_bOwnsImageListNormal = TRUE;
1957 else if (nWhich == wxIMAGE_LIST_SMALL )
1958 m_bOwnsImageListSmall = TRUE;
1959 else if (nWhich == wxIMAGE_LIST_STATE )
1960 m_bOwnsImageListState = TRUE;
1961 } // end of wxListCtrl::AssignImageList
1962
1963 // ----------------------------------------------------------------------------
1964 // Operations
1965 // ----------------------------------------------------------------------------
1966
1967 // Arranges the items
1968 bool wxListCtrl::Arrange (
1969 int nFlag
1970 )
1971 {
1972 ULONG ulType = 0L;
1973 ULONG ulFlags = 0L;
1974
1975 if (nFlag == wxLIST_ALIGN_SNAP_TO_GRID)
1976 {
1977 ulType = CMA_ARRANGEGRID;
1978 if (nFlag == wxLIST_ALIGN_LEFT)
1979 ulFlags |= CMA_LEFT;
1980 else if (nFlag == wxLIST_ALIGN_TOP)
1981 ulFlags |= CMA_TOP;
1982 else if (nFlag == wxLIST_ALIGN_DEFAULT)
1983 ulFlags |= CMA_LEFT;
1984 }
1985 else
1986 ulType = CMA_ARRANGESTANDARD;
1987 ::WinSendMsg( GetHWND()
1988 ,CM_ARRANGE
1989 ,(MPARAM)ulType
1990 ,(MPARAM)ulFlags
1991 );
1992 //
1993 // We do not support CMA_ARRANGESELECTED
1994 //
1995 return TRUE;
1996 } // end of wxListCtrl::Arrange
1997
1998 // Deletes an item
1999 bool wxListCtrl::DeleteItem (
2000 long lItem
2001 )
2002 {
2003 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2004 ,lItem
2005 );
2006 if (LONGFROMMR(::WinSendMsg( GetHWND()
2007 ,CM_REMOVERECORD
2008 ,(MPARAM)pRecord
2009 ,MPFROM2SHORT(1, CMA_FREE)
2010 )) == -1L)
2011 {
2012 return FALSE;
2013 }
2014
2015 //
2016 // The virtual list control doesn't refresh itself correctly, help it
2017 //
2018 if (IsVirtual())
2019 {
2020 //
2021 // We need to refresh all the lines below the one which was deleted
2022 //
2023 wxRect vRectItem;
2024
2025 if (lItem > 0 && GetItemCount())
2026 {
2027 GetItemRect( lItem - 1
2028 ,vRectItem
2029 );
2030 }
2031 else
2032 {
2033 vRectItem.y = vRectItem.height = 0;
2034 }
2035 wxRect vRectWin = GetRect();
2036
2037 vRectWin.height = vRectWin.GetBottom() - vRectItem.GetBottom();
2038 vRectWin.y = vRectItem.GetBottom();
2039 RefreshRect(vRectWin);
2040 }
2041 return TRUE;
2042 } // end of wxListCtrl::DeleteItem
2043
2044 // Deletes all items
2045 bool wxListCtrl::DeleteAllItems ()
2046 {
2047 return((LONG)::WinSendMsg( GetHWND()
2048 ,CM_REMOVERECORD
2049 ,NULL
2050 ,MPFROM2SHORT(0, CMA_FREE)
2051 ) != -1L);
2052 } // end of wxListCtrl::DeleteAllItems
2053
2054 // Deletes all items
2055 bool wxListCtrl::DeleteAllColumns ()
2056 {
2057 while (m_nColCount > 0)
2058 {
2059 DeleteColumn(m_nColCount - 1);
2060 m_nColCount--;
2061 }
2062
2063 wxASSERT_MSG(m_nColCount == 0, wxT("no columns should be left"));
2064 return TRUE;
2065 } // end of wxListCtrl::DeleteAllColumns
2066
2067 // Deletes a column
2068 bool wxListCtrl::DeleteColumn (
2069 int nCol
2070 )
2071 {
2072 bool bSuccess = FALSE;
2073 PFIELDINFO pField = FindOS2ListFieldByColNum( GetHWND()
2074 ,nCol
2075 );
2076 bSuccess = ((LONG)::WinSendMsg( GetHWND()
2077 ,CM_REMOVEDETAILFIELDINFO
2078 ,MPFROMP(pField)
2079 ,MPFROM2SHORT((SHORT)1, CMA_FREE)
2080 ) == -1L);
2081 if (bSuccess && (m_nColCount > 0))
2082 m_nColCount--;
2083 return bSuccess;
2084 } // end of wxListCtrl::DeleteColumn
2085
2086 // Clears items, and columns if there are any.
2087 void wxListCtrl::ClearAll ()
2088 {
2089 DeleteAllItems();
2090 if (m_nColCount > 0)
2091 DeleteAllColumns();
2092 } // end of wxListCtrl::ClearAll
2093
2094 //
2095 // OS/2 does not use a text control for its container labels. You merely
2096 // "open" a record for editting.
2097 //
2098 wxTextCtrl* wxListCtrl::EditLabel (
2099 long lItem
2100 , wxClassInfo* WXUNUSED(pTextControlClass)
2101 )
2102 {
2103 CNREDITDATA vEdit;
2104 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2105 ,lItem
2106 );
2107
2108 vEdit.cb = sizeof(CNREDITDATA);
2109 vEdit.hwndCnr = GetHWND();
2110 vEdit.pRecord = &pRecord->m_vRecord;
2111 vEdit.pFieldInfo = NULL;
2112 vEdit.ppszText = NULL;
2113 vEdit.cbText = 0;
2114 vEdit.id = 0;
2115
2116 ::WinSendMsg( GetHWND()
2117 ,CM_OPENEDIT
2118 ,MPFROMP(&vEdit)
2119 ,(MPARAM)0
2120 );
2121 return m_pTextCtrl;
2122 } // end of wxListCtrl::EditLabel
2123
2124 // End label editing, optionally cancelling the edit. Under OS/2 you close
2125 // the record for editting
2126 bool wxListCtrl::EndEditLabel (
2127 bool WXUNUSED(bCancel)
2128 )
2129 {
2130 ::WinSendMsg( GetHWND()
2131 ,CM_CLOSEEDIT
2132 ,(MPARAM)0
2133 ,(MPARAM)0
2134 );
2135 return TRUE;
2136 } // end of wxListCtrl::EndEditLabel
2137
2138 // Ensures this item is visible
2139 bool wxListCtrl::EnsureVisible (
2140 long lItem
2141 )
2142 {
2143 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2144 ,lItem
2145 );
2146 ::WinSendMsg( GetHWND()
2147 ,CM_INVALIDATERECORD
2148 ,MPFROMP(pRecord)
2149 ,MPFROM2SHORT((SHORT)1, CMA_NOREPOSITION)
2150 );
2151 return TRUE;
2152 } // end of wxListCtrl::EnsureVisible
2153
2154 // Find an item whose label matches this string, starting from the item after 'start'
2155 // or the beginning if 'start' is -1.
2156 long wxListCtrl::FindItem (
2157 long lStart
2158 , const wxString& rsStr
2159 , bool bPartial
2160 )
2161 {
2162 CNRINFO vCnrInfo;
2163 SEARCHSTRING vSearch;
2164 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2165 ,lStart
2166 );
2167 ULONG ulFlag;
2168
2169
2170 if (!::WinSendMsg( GetHWND()
2171 ,CM_QUERYCNRINFO
2172 ,MPFROMP(&vCnrInfo)
2173 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2174 ))
2175 return -1L;
2176
2177 if (vCnrInfo.flWindowAttr & CV_ICON)
2178 ulFlag = CV_ICON;
2179 if (vCnrInfo.flWindowAttr & CV_NAME)
2180 ulFlag = CV_NAME;
2181 if (vCnrInfo.flWindowAttr & CV_TEXT)
2182 ulFlag = CV_TEXT;
2183 if (vCnrInfo.flWindowAttr & CV_DETAIL)
2184 ulFlag = CV_DETAIL;
2185 if (!bPartial)
2186 ulFlag |= CV_EXACTLENGTH;
2187
2188 vSearch.cb = sizeof(SEARCHSTRING);
2189 vSearch.pszSearch = (char*)rsStr.c_str();
2190 vSearch.fsPrefix = TRUE;
2191 vSearch.fsCaseSensitive = TRUE;
2192 vSearch.usView = ulFlag;
2193
2194 if (lStart == -1)
2195 {
2196 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2197 ,CM_SEARCHSTRING
2198 ,MPFROMP(&vSearch)
2199 ,(MPARAM)CMA_FIRST
2200 );
2201 }
2202 else
2203 {
2204 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2205 ,CM_SEARCHSTRING
2206 ,MPFROMP(&vSearch)
2207 ,MPFROMP(pRecord)
2208 );
2209 }
2210 if (!pRecord)
2211 return -1L;
2212 return pRecord->m_ulItemId;
2213 } // end of wxListCtrl::FindItem
2214
2215 // Find an item whose data matches this data, starting from the item after 'start'
2216 // or the beginning if 'start' is -1.
2217 long wxListCtrl::FindItem (
2218 long lStart
2219 , long lData
2220 )
2221 {
2222 long lIdx = lStart + 1;
2223 long lCount = GetItemCount();
2224
2225 while (lIdx < lCount)
2226 {
2227 if (GetItemData(lIdx) == lData)
2228 return lIdx;
2229 lIdx++;
2230 };
2231 return -1;
2232 } // end of wxListCtrl::FindItem
2233
2234 // Find an item nearest this position in the specified direction, starting from
2235 // the item after 'start' or the beginning if 'start' is -1.
2236 long wxListCtrl::FindItem (
2237 long lStart
2238 , const wxPoint& rPoint
2239 , int nDirection
2240 )
2241 {
2242 RECTL vRect;
2243 QUERYRECORDRECT vQueryRect;
2244 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2245 ,lStart
2246 );
2247 CNRINFO vCnrInfo;
2248 ULONG i;
2249 wxRect vLibRect;
2250
2251 if (!::WinSendMsg( GetHWND()
2252 ,CM_QUERYCNRINFO
2253 ,MPFROMP(&vCnrInfo)
2254 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2255 ))
2256 return -1L;
2257
2258 vQueryRect.cb = sizeof(QUERYRECORDRECT);
2259 vQueryRect.pRecord = &pRecord->m_vRecord;
2260 vQueryRect.fRightSplitWindow = TRUE;
2261 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
2262
2263 ::WinSendMsg( GetHWND()
2264 ,CM_QUERYRECORDRECT
2265 ,MPFROMP(&vRect)
2266 ,MPFROMP(&vQueryRect)
2267 );
2268 vLibRect.SetLeft(vRect.xLeft);
2269 vLibRect.SetTop(vRect.yTop);
2270 vLibRect.SetRight(vRect.xRight);
2271 vLibRect.SetBottom(vRect.yBottom);
2272 if (vLibRect.Inside(rPoint))
2273 return pRecord->m_ulItemId;
2274
2275 for (i = lStart + 1; i < vCnrInfo.cRecords; i++)
2276 {
2277 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
2278 ,CM_QUERYRECORD
2279 ,MPFROMP(pRecord)
2280 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
2281 ));
2282 vQueryRect.pRecord = (PRECORDCORE)pRecord;
2283 ::WinSendMsg( GetHWND()
2284 ,CM_QUERYRECORDRECT
2285 ,MPFROMP(&vRect)
2286 ,MPFROMP(&vQueryRect)
2287 );
2288 vLibRect.SetLeft(vRect.xLeft);
2289 vLibRect.SetTop(vRect.yTop);
2290 vLibRect.SetRight(vRect.xRight);
2291 vLibRect.SetBottom(vRect.yBottom);
2292 if (vLibRect.Inside(rPoint))
2293 return pRecord->m_ulItemId;
2294 }
2295 return -1L;
2296 } // end of wxListCtrl::FindItem
2297
2298 // Determines which item (if any) is at the specified point,
2299 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
2300 long wxListCtrl::HitTest (
2301 const wxPoint& rPoint
2302 , int& WXUNUSED(rFlags)
2303 )
2304 {
2305 PMYRECORD pRecord = NULL;
2306 QUERYRECFROMRECT vQueryRect;
2307 RECTL vRect;
2308 long lHeight;
2309
2310 //
2311 // Get height for OS/2 point conversion
2312 //
2313 ::WinSendMsg( GetHWND()
2314 ,CM_QUERYVIEWPORTRECT
2315 ,MPFROMP(&vRect)
2316 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
2317 );
2318 lHeight = vRect.yTop - vRect.yBottom;
2319
2320 //
2321 // For now just try and get a record in the general vicinity and forget
2322 // the flag
2323 //
2324 vRect.xLeft = rPoint.x - 2;
2325 vRect.xRight = rPoint.x + 2;
2326 vRect.yTop = (lHeight - rPoint.y) + 2;
2327 vRect.yBottom = (lHeight - rPoint.y) - 2;
2328
2329 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
2330 vQueryRect.rect = vRect;
2331 vQueryRect.fsSearch = CMA_PARTIAL;
2332
2333 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2334 ,CM_QUERYRECORDFROMRECT
2335 ,(MPARAM)CMA_FIRST
2336 ,MPFROMP(&vQueryRect)
2337 );
2338
2339 if (!pRecord)
2340 return -1L;
2341 return pRecord->m_ulItemId;
2342 } // end of wxListCtrl::HitTest
2343
2344 // Inserts an item, returning the index of the new item if successful,
2345 // -1 otherwise.
2346 long wxListCtrl::InsertItem (
2347 wxListItem& rInfo
2348 )
2349 {
2350 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
2351
2352 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
2353 ,rInfo.GetColumn()
2354 );
2355 PMYRECORD pRecordAfter = NULL;
2356 PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2357 ,CM_ALLOCRECORD
2358 ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
2359 ,MPFROMSHORT(1)
2360 );
2361
2362 ConvertToOS2ListItem( this
2363 ,rInfo
2364 ,pRecord
2365 ,pFieldInfo
2366 );
2367
2368 if (rInfo.GetId() > 0)
2369 pRecordAfter = FindOS2ListRecordByID( GetHWND()
2370 ,rInfo.GetId() - 1
2371 );
2372
2373 RECORDINSERT vInsert;
2374
2375 vInsert.cb = sizeof(RECORDINSERT);
2376 vInsert.pRecordParent = NULL;
2377 if (!pRecordAfter)
2378 vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
2379 else
2380 vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
2381 vInsert.zOrder = CMA_TOP;
2382 vInsert.cRecordsInsert = 1;
2383 vInsert.fInvalidateRecord = TRUE;
2384
2385 //
2386 // Check wether we need to allocate our internal data
2387 //
2388 bool bNeedInternalData = ((rInfo.GetMask() & wxLIST_MASK_DATA) ||
2389 rInfo.HasAttributes()
2390 );
2391 if (bNeedInternalData)
2392 {
2393 m_bAnyInternalData = TRUE;
2394
2395 //
2396 // Internal stucture that manages data
2397 //
2398 CListItemInternalData* pData = new CListItemInternalData();
2399
2400 pRecord->m_ulUserData = (unsigned long)pData;
2401 if (rInfo.GetMask() & wxLIST_MASK_DATA)
2402 pData->m_lParam = (WXLPARAM)rInfo.GetData();
2403
2404 //
2405 // Check whether it has any custom attributes
2406 //
2407 if (rInfo.HasAttributes())
2408 {
2409 //
2410 // Take copy of attributes
2411 //
2412 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
2413 }
2414 }
2415 if (!::WinSendMsg( GetHWND()
2416 ,CM_INSERTRECORD
2417 ,MPFROMP(pRecord)
2418 ,MPFROMP(&vInsert)
2419 ))
2420 return -1;
2421 //
2422 // OS/2 must mannually bump the index's of following records
2423 //
2424 BumpRecordIds( GetHWND()
2425 ,pRecord
2426 );
2427 ::WinSendMsg( GetHWND()
2428 ,CM_INVALIDATEDETAILFIELDINFO
2429 ,NULL
2430 ,NULL
2431 );
2432 return pRecord->m_ulItemId;
2433 } // end of wxListCtrl::InsertItem
2434
2435 long wxListCtrl::InsertItem (
2436 long lIndex
2437 , const wxString& rsLabel
2438 )
2439 {
2440 wxListItem vInfo;
2441
2442 memset(&vInfo, '\0', sizeof(wxListItem));
2443 vInfo.m_text = rsLabel;
2444 vInfo.m_mask = wxLIST_MASK_TEXT;
2445 vInfo.m_itemId = lIndex;
2446 return InsertItem(vInfo);
2447 } // end of wxListCtrl::InsertItem
2448
2449 // Inserts an image item
2450 long wxListCtrl::InsertItem (
2451 long lIndex
2452 , int nImageIndex
2453 )
2454 {
2455 wxListItem vInfo;
2456
2457 vInfo.m_image = nImageIndex;
2458 vInfo.m_mask = wxLIST_MASK_IMAGE;
2459 vInfo.m_itemId = lIndex;
2460 return InsertItem(vInfo);
2461 } // end of wxListCtrl::InsertItem
2462
2463 // Inserts an image/string item
2464 long wxListCtrl::InsertItem (
2465 long lIndex
2466 , const wxString& rsLabel
2467 , int nImageIndex
2468 )
2469 {
2470 wxListItem vInfo;
2471
2472 vInfo.m_image = nImageIndex;
2473 vInfo.m_text = rsLabel;
2474 vInfo.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
2475 vInfo.m_itemId = lIndex;
2476 return InsertItem(vInfo);
2477 } // end of wxListCtrl::InsertItem
2478
2479 // For details view mode (only), inserts a column.
2480 long wxListCtrl::InsertColumn (
2481 long lCol
2482 , wxListItem& rItem
2483 )
2484 {
2485 bool bSuccess;
2486 PFIELDINFO pField = (PFIELDINFO)::WinSendMsg( GetHWND()
2487 ,CM_ALLOCDETAILFIELDINFO
2488 ,MPFROMLONG(1)
2489 ,NULL
2490 );
2491 PFIELDINFO pFieldAfter = FindOS2ListFieldByColNum ( GetHWND()
2492 ,lCol - 1
2493 );
2494 FIELDINFOINSERT vInsert;
2495
2496 ConvertToOS2ListCol ( lCol
2497 ,rItem
2498 ,pField
2499 );
2500
2501 vInsert.cb = sizeof(FIELDINFOINSERT);
2502 vInsert.pFieldInfoOrder = pFieldAfter;
2503 vInsert.fInvalidateFieldInfo = TRUE;
2504 vInsert.cFieldInfoInsert = 1;
2505
2506 bSuccess = ::WinSendMsg( GetHWND()
2507 ,CM_INSERTDETAILFIELDINFO
2508 ,MPFROMP(pField)
2509 ,MPFROMP(&vInsert)
2510 ) != (MRESULT)0;
2511 return bSuccess;
2512 } // end of wxListCtrl::InsertColumn
2513
2514 long wxListCtrl::InsertColumn (
2515 long lCol
2516 , const wxString& rsHeading
2517 , int nFormat
2518 , int nWidth
2519 )
2520 {
2521 wxListItem vItem;
2522
2523 vItem.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2524 vItem.m_text = rsHeading;
2525 if (nWidth > -1)
2526 {
2527 vItem.m_mask |= wxLIST_MASK_WIDTH;
2528 vItem.m_width = nWidth;
2529 }
2530 vItem.m_format = nFormat;
2531
2532 return InsertColumn( lCol
2533 ,vItem
2534 );
2535 } // end of wxListCtrl::InsertColumn
2536
2537 // scroll the control by the given number of pixels (exception: in list view,
2538 // dx is interpreted as number of columns)
2539 bool wxListCtrl::ScrollList (
2540 int nDx
2541 , int nDy
2542 )
2543 {
2544 if (nDx > 0)
2545 ::WinSendMsg( GetHWND()
2546 ,CM_SCROLLWINDOW
2547 ,(MPARAM)CMA_HORIZONTAL
2548 ,(MPARAM)nDx
2549 );
2550 if (nDy > 0)
2551 ::WinSendMsg( GetHWND()
2552 ,CM_SCROLLWINDOW
2553 ,(MPARAM)CMA_VERTICAL
2554 ,(MPARAM)nDy
2555 );
2556 return TRUE;
2557 } // end of wxListCtrl::ScrollList
2558
2559 bool wxListCtrl::SortItems (
2560 wxListCtrlCompare fn
2561 , long lData
2562 )
2563 {
2564 SInternalDataSort vInternalData;
2565
2566 vInternalData.m_fnUser = fn;
2567 vInternalData.m_lData = lData;
2568
2569 // WPARAM cast is needed for mingw/cygwin
2570 if (!::WinSendMsg( GetHWND()
2571 ,CM_SORTRECORD
2572 ,(PFN)InternalDataCompareFunc
2573 ,(PVOID)&vInternalData
2574 ))
2575 {
2576 wxLogDebug(_T("CM_SORTRECORD failed"));
2577 return FALSE;
2578 }
2579 return TRUE;
2580 } // end of wxListCtrl::SortItems
2581
2582 // ----------------------------------------------------------------------------
2583 // message processing
2584 // ----------------------------------------------------------------------------
2585
2586 bool wxListCtrl::OS2Command (
2587 WXUINT uCmd
2588 , WXWORD wId
2589 )
2590 {
2591 if (uCmd == CN_ENDEDIT)
2592 {
2593 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED
2594 ,wId
2595 );
2596
2597 vEvent.SetEventObject( this );
2598 ProcessCommand(vEvent);
2599 return TRUE;
2600 }
2601 else if (uCmd == CN_KILLFOCUS)
2602 {
2603 wxCommandEvent vEvent( wxEVT_KILL_FOCUS
2604 ,wId
2605 );
2606 vEvent.SetEventObject( this );
2607 ProcessCommand(vEvent);
2608 return TRUE;
2609 }
2610 else
2611 return FALSE;
2612 } // end of wxListCtrl::OS2Command
2613
2614 // Necessary for drawing hrules and vrules, if specified
2615 void wxListCtrl::OnPaint (
2616 wxPaintEvent& rEvent
2617 )
2618 {
2619 wxPaintDC vDc(this);
2620 wxPen vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT)
2621 ,1
2622 ,wxSOLID
2623 );
2624 wxSize vClientSize = GetClientSize();
2625 wxRect vItemRect;
2626 int nItemCount = GetItemCount();
2627 int nCy = 0;
2628 int i;
2629 bool bDrawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
2630 bool bDrawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
2631
2632 wxControl::OnPaint(rEvent);
2633
2634 //
2635 // Reset the device origin since it may have been set
2636 //
2637 vDc.SetDeviceOrigin(0, 0);
2638 if (!bDrawHRules && !bDrawVRules)
2639 return;
2640 if ((GetWindowStyle() & wxLC_REPORT) == 0)
2641 return;
2642 vDc.SetPen(vPen);
2643 vDc.SetBrush(*wxTRANSPARENT_BRUSH);
2644
2645 if (bDrawHRules)
2646 {
2647 long lTop = GetTopItem();
2648
2649 for (i = lTop; i < lTop + GetCountPerPage() + 1; i++)
2650 {
2651 if (GetItemRect( i
2652 ,vItemRect
2653 ))
2654 {
2655 nCy = vItemRect.GetTop();
2656 if (i != 0) // Don't draw the first one
2657 {
2658 vDc.DrawLine( 0
2659 ,nCy
2660 ,vClientSize.x
2661 ,nCy
2662 );
2663 }
2664 // Draw last line
2665 if (i == nItemCount - 1)
2666 {
2667 nCy = vItemRect.GetBottom();
2668 vDc.DrawLine( 0
2669 ,nCy
2670 ,vClientSize.x
2671 ,nCy
2672 );
2673 }
2674 }
2675 }
2676 }
2677 i = nItemCount - 1;
2678 if (bDrawVRules && (i > -1))
2679 {
2680 wxRect vFirstItemRect;
2681
2682 GetItemRect( 0
2683 ,vFirstItemRect
2684 );
2685 if (GetItemRect( i
2686 ,vItemRect
2687 ))
2688 {
2689 int nCol;
2690 int nX = vItemRect.GetX();
2691
2692 for (nCol = 0; nCol < GetColumnCount(); nCol++)
2693 {
2694 int nColWidth = GetColumnWidth(nCol);
2695
2696 nX += nColWidth ;
2697 vDc.DrawLine( nX - 1
2698 ,vFirstItemRect.GetY() - 2
2699 ,nX - 1
2700 ,vItemRect.GetBottom()
2701 );
2702 }
2703 }
2704 }
2705 } // end of wxListCtrl::OnPaint
2706
2707 // ----------------------------------------------------------------------------
2708 // virtual list controls
2709 // ----------------------------------------------------------------------------
2710
2711 wxString wxListCtrl::OnGetItemText (
2712 long WXUNUSED(lItem)
2713 , long WXUNUSED(lCol)
2714 ) const
2715 {
2716 // this is a pure virtual function, in fact - which is not really pure
2717 // because the controls which are not virtual don't need to implement it
2718 wxFAIL_MSG( _T("not supposed to be called") );
2719 return wxEmptyString;
2720 } // end of wxListCtrl::OnGetItemText
2721
2722 int wxListCtrl::OnGetItemImage (
2723 long WXUNUSED(lItem)
2724 ) const
2725 {
2726 // same as above
2727 wxFAIL_MSG( _T("not supposed to be called") );
2728 return -1;
2729 } // end of wxListCtrl::OnGetItemImage
2730
2731 int wxListCtrl::OnGetItemColumnImage (
2732 long lItem,
2733 long lColumn
2734 ) const
2735 {
2736 if (!lColumn)
2737 return OnGetItemImage(lItem);
2738
2739 return -1;
2740 } // end of wxListCtrl::OnGetItemColumnImage
2741
2742 wxListItemAttr* wxListCtrl::OnGetItemAttr (
2743 long WXUNUSED_UNLESS_DEBUG(lItem)
2744 ) const
2745 {
2746 wxASSERT_MSG( lItem >= 0 && lItem < GetItemCount(),
2747 _T("invalid item index in OnGetItemAttr()") );
2748
2749 //
2750 // No attributes by default
2751 //
2752 return NULL;
2753 } // end of wxListCtrl::OnGetItemAttr
2754
2755 void wxListCtrl::SetItemCount (
2756 long lCount
2757 )
2758 {
2759 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
2760
2761 //
2762 // Cannot explicitly set the record count in OS/2
2763 //
2764 } // end of wxListCtrl::SetItemCount
2765
2766 void wxListCtrl::RefreshItem (
2767 long lItem
2768 )
2769 {
2770 wxRect vRect;
2771
2772 GetItemRect( lItem
2773 ,vRect
2774 );
2775 RefreshRect(vRect);
2776 } // end of wxListCtrl::RefreshItem
2777
2778 void wxListCtrl::RefreshItems (
2779 long lItemFrom
2780 , long lItemTo
2781 )
2782 {
2783 wxRect vRect1;
2784 wxRect vRect2;
2785
2786 GetItemRect( lItemFrom
2787 ,vRect1
2788 );
2789 GetItemRect( lItemTo
2790 ,vRect2
2791 );
2792
2793 wxRect vRect = vRect1;
2794
2795 vRect.height = vRect2.GetBottom() - vRect1.GetTop();
2796 RefreshRect(vRect);
2797 } // end of wxListCtrl::RefreshItems
2798
2799 MRESULT wxListCtrl::OS2WindowProc(
2800 WXUINT uMsg
2801 , WXWPARAM wParam
2802 , WXLPARAM lParam
2803 )
2804 {
2805 bool bProcessed = FALSE;
2806 MRESULT lRc;
2807 wxListEvent vEvent( wxEVT_NULL
2808 ,m_windowId
2809 );
2810 wxEventType vEventType = wxEVT_NULL;
2811 PCNRDRAGINIT pDragInit = NULL;
2812 PCNREDITDATA pEditData = NULL;
2813 PNOTIFYRECORDENTER pNotifyEnter = NULL;
2814
2815 vEvent.SetEventObject(this);
2816 switch (uMsg)
2817 {
2818 case WM_CONTROL:
2819 //
2820 // First off let's set some internal data
2821 //
2822 switch(SHORT2FROMMP(wParam))
2823 {
2824 case CN_INITDRAG:
2825 case CN_DRAGOVER:
2826 case CN_DRAGAFTER:
2827 {
2828 CListItemInternalData* pInternaldata = (CListItemInternalData *)lParam;
2829
2830 if (pInternaldata)
2831 {
2832 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2833
2834 pItem->SetData((long)pInternaldata->m_lParam);
2835 }
2836 }
2837 break;
2838 }
2839 //
2840 // Now let's go through the codes we're interested in
2841 //
2842 switch(SHORT2FROMMP(wParam))
2843 {
2844 case CN_INITDRAG:
2845 pDragInit = (PCNRDRAGINIT)lParam;
2846 if (pDragInit)
2847 {
2848 PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
2849
2850 vEventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
2851 vEvent.m_itemIndex = pRecord->m_ulItemId;
2852 vEvent.m_pointDrag.x = pDragInit->x;
2853 vEvent.m_pointDrag.y = pDragInit->y;
2854 }
2855 break;
2856
2857 case CN_BEGINEDIT:
2858 pEditData = (PCNREDITDATA)lParam;
2859 if (pEditData)
2860 {
2861 vEventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
2862 ConvertFromOS2ListItem( GetHWND()
2863 ,(wxListItem &)vEvent.GetItem()
2864 ,(PMYRECORD)pEditData->pRecord
2865 );
2866 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2867 }
2868 break;
2869
2870 case CN_ENDEDIT:
2871 pEditData = (PCNREDITDATA)lParam;
2872 if (pEditData)
2873 {
2874 vEventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
2875 ConvertFromOS2ListItem( GetHWND()
2876 ,(wxListItem &)vEvent.GetItem()
2877 ,(PMYRECORD)pEditData->pRecord
2878 );
2879 if (pEditData->cbText == 0)
2880 return (MRESULT)FALSE;
2881 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2882 }
2883 break;
2884
2885 case CN_ENTER:
2886 pNotifyEnter = (PNOTIFYRECORDENTER)lParam;
2887 if (pNotifyEnter)
2888 {
2889 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2890 PMYRECORD pMyRecord = (PMYRECORD)pNotifyEnter->pRecord;
2891
2892 vEventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
2893 vEvent.m_itemIndex = pMyRecord->m_ulItemId;
2894 pItem->SetText(GetItemText(pMyRecord->m_ulItemId));
2895 pItem->SetData(GetItemData(pMyRecord->m_ulItemId));
2896 }
2897 break;
2898
2899 //
2900 // Add the CN_DROP messages for Direct Manipulation
2901 //
2902 }
2903 vEvent.SetEventType(vEventType);
2904 bProcessed = GetEventHandler()->ProcessEvent(vEvent);
2905 break;
2906 }
2907 if (!bProcessed)
2908 lRc = wxControl::OS2WindowProc( uMsg
2909 ,wParam
2910 ,lParam
2911 );
2912 return lRc;
2913 } // end of wxListCtrl::WindowProc
2914
2915 #endif // wxUSE_LISTCTRL