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