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