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