]> git.saurik.com Git - wxWidgets.git/blob - src/os2/listctrl.cpp
removed now-unused wxSizer::GetMax/MinWindowSize helpers
[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 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
779 IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
780 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
781
782 IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
783
784 BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
785 EVT_PAINT(wxListCtrl::OnPaint)
786 END_EVENT_TABLE()
787
788 // ============================================================================
789 // implementation
790 // ============================================================================
791
792 // ----------------------------------------------------------------------------
793 // wxListCtrl construction
794 // ----------------------------------------------------------------------------
795
796 void wxListCtrl::Init ()
797 {
798 m_pImageListNormal = NULL;
799 m_pImageListSmall = NULL;
800 m_pImageListState = NULL;
801 m_bOwnsImageListNormal = false;
802 m_bOwnsImageListSmall = false;
803 m_bOwnsImageListState = false;
804 m_lBaseStyle = 0L;
805 m_nColCount = 0;
806 m_pTextCtrl = NULL;
807 m_bAnyInternalData = false;
808 m_bHasAnyAttr = false;
809 } // end of wxListCtrl::Init
810
811 bool wxListCtrl::Create ( wxWindow* pParent,
812 wxWindowID vId,
813 const wxPoint& rPos,
814 const wxSize& rSize,
815 long lStyle,
816 const wxValidator& rValidator,
817 const wxString& rsName )
818 {
819 int nX = rPos.x;
820 int nY = rPos.y;
821 int nWidth = rSize.x;
822 int nHeight = rSize.y;
823
824 #if wxUSE_VALIDATORS
825 SetValidator(rValidator);
826 #endif // wxUSE_VALIDATORS
827
828 SetName(rsName);
829 SetWindowStyleFlag(lStyle);
830 SetParent(pParent);
831 if (nWidth <= 0)
832 nWidth = 100;
833 if (nHeight <= 0)
834 nHeight = 30;
835 if (nX < 0)
836 nX = 0;
837 if (nY < 0)
838 nY = 0;
839
840 m_windowId = (vId == -1) ? NewControlId() : vId;
841
842 long lSstyle = WS_VISIBLE | WS_TABSTOP;
843
844 if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
845 lSstyle |= WS_CLIPSIBLINGS;
846 m_lBaseStyle = lSstyle;
847 if (!DoCreateControl( nX
848 ,nY
849 ,nWidth
850 ,nHeight
851 ))
852 return false;
853 if (pParent)
854 pParent->AddChild(this);
855 return true;
856 } // end of wxListCtrl::Create
857
858 bool wxListCtrl::DoCreateControl ( int nX, int nY,
859 int nWidth, int nHeight )
860 {
861 DWORD lWstyle = m_lBaseStyle;
862 long lOldStyle = 0; // Dummy
863
864 CNRINFO vCnrInfo;
865
866 lWstyle |= ConvertToOS2Style( lOldStyle
867 ,GetWindowStyleFlag()
868 );
869
870 m_hWnd = (WXHWND)::WinCreateWindow( GetParent()->GetHWND()
871 ,WC_CONTAINER
872 ,NULL
873 ,m_lBaseStyle
874 ,0, 0, 0, 0
875 ,GetParent()->GetHWND()
876 ,HWND_BOTTOM
877 ,(ULONG)m_windowId
878 ,NULL
879 ,NULL
880 );
881 if (!m_hWnd)
882 {
883 return false;
884 }
885
886 //
887 // Now set the display attributes of the container
888 //
889 if (!::WinSendMsg( GetHWND()
890 ,CM_QUERYCNRINFO
891 ,MPFROMP(&vCnrInfo)
892 ,(MPARAM)(USHORT)sizeof(CNRINFO)
893 ))
894 return false;
895 lWstyle = ConvertViewToOS2Style(GetWindowStyleFlag());
896 vCnrInfo.flWindowAttr |= lWstyle;
897 if (!::WinSendMsg( GetHWND()
898 ,CM_SETCNRINFO
899 ,MPFROMP(&vCnrInfo)
900 ,(MPARAM)CMA_FLWINDOWATTR
901 ))
902 return false;
903
904 //
905 // And now set needed arrangement flags
906 //
907 lWstyle = ConvertArrangeToOS2Style(GetWindowStyleFlag());
908 if (!::WinSendMsg( GetHWND()
909 ,CM_ARRANGE
910 ,(MPARAM)CMA_ARRANGEGRID
911 ,(MPARAM)lWstyle
912 ))
913 return false;
914 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
915 SetForegroundColour(GetParent()->GetForegroundColour());
916 SubclassWin(m_hWnd);
917 SetFont(*wxSMALL_FONT);
918 SetXComp(0);
919 SetYComp(0);
920 SetSize( nX, nY, nWidth, nHeight );
921 return true;
922 } // end of wxListCtrl::DoCreateControl
923
924 void wxListCtrl::UpdateStyle ()
925 {
926 if (GetHWND())
927 {
928 long lDummy;
929 DWORD dwStyleNew = ConvertToOS2Style( lDummy, GetWindowStyleFlag() );
930
931 dwStyleNew |= m_lBaseStyle;
932
933 //
934 // Get the current window style.
935 //
936 ULONG dwStyleOld = ::WinQueryWindowULong(GetHWND(), QWL_STYLE);
937
938 //
939 // Only set the window style if the view bits have changed.
940 //
941 if (dwStyleOld != dwStyleNew)
942 {
943 ::WinSetWindowULong(GetHWND(), QWL_STYLE, dwStyleNew);
944 }
945 }
946 } // end of wxListCtrl::UpdateStyle
947
948 void wxListCtrl::FreeAllInternalData ()
949 {
950 if (m_bAnyInternalData)
951 {
952 int n = GetItemCount();
953 int i = 0;
954
955 for (i = 0; i < n; i++)
956 DeleteInternalData(this, (long)i);
957 m_bAnyInternalData = false;
958 }
959 } // end of wxListCtrl::FreeAllInternalData
960
961 wxListCtrl::~wxListCtrl ()
962 {
963 FreeAllInternalData();
964 if (m_pTextCtrl )
965 {
966 m_pTextCtrl->SetHWND(0);
967 m_pTextCtrl->UnsubclassWin();
968 delete m_pTextCtrl;
969 m_pTextCtrl = NULL;
970 }
971
972 if (m_bOwnsImageListNormal)
973 delete m_pImageListNormal;
974 if (m_bOwnsImageListSmall)
975 delete m_pImageListSmall;
976 if (m_bOwnsImageListState)
977 delete m_pImageListState;
978 } // end of wxListCtrl::~wxListCtrl
979
980 // ----------------------------------------------------------------------------
981 // set/get/change style
982 // ----------------------------------------------------------------------------
983
984 // Add or remove a single window style
985 void wxListCtrl::SetSingleStyle (
986 long lStyle
987 , bool bAdd
988 )
989 {
990 long lFlag = GetWindowStyleFlag();
991
992 //
993 // Get rid of conflicting styles
994 //
995 if (bAdd)
996 {
997 if (lStyle & wxLC_MASK_TYPE)
998 lFlag = lFlag & ~wxLC_MASK_TYPE;
999 if (lStyle & wxLC_MASK_ALIGN )
1000 lFlag = lFlag & ~wxLC_MASK_ALIGN;
1001 if (lStyle & wxLC_MASK_SORT )
1002 lFlag = lFlag & ~wxLC_MASK_SORT;
1003 }
1004 if (lFlag & lStyle)
1005 {
1006 if (!bAdd)
1007 lFlag -= lStyle;
1008 }
1009 else
1010 {
1011 if (bAdd)
1012 {
1013 lFlag |= lStyle;
1014 }
1015 }
1016 m_windowStyle = lFlag;
1017 UpdateStyle();
1018 } // end of wxListCtrl::SetSingleStyle
1019
1020 // Set the whole window style
1021 void wxListCtrl::SetWindowStyleFlag (
1022 long lFlag
1023 )
1024 {
1025 m_windowStyle = lFlag;
1026 UpdateStyle();
1027 } // end of wxListCtrl::SetWindowStyleFlag
1028
1029 long wxListCtrl::ConvertToOS2Style (
1030 long& rOldStyle
1031 , long lStyle
1032 ) const
1033 {
1034 long lWstyle = 0L;
1035
1036 //
1037 // The only styles OS2 uses on creation are auto arrange, read only, and
1038 // and selection styles. This lib does not support OS/2 MINIRECORDCORE
1039 // or VERIFYPOINTER styles
1040 //
1041 if (lStyle & wxLC_AUTOARRANGE)
1042 lWstyle |= CCS_AUTOPOSITION;
1043 if (lStyle & wxLC_SINGLE_SEL)
1044 lWstyle |= CCS_SINGLESEL;
1045 else
1046 lWstyle |= CCS_EXTENDSEL;
1047 if (!(lStyle & wxLC_EDIT_LABELS))
1048 lWstyle |= CCS_READONLY;
1049 return lWstyle;
1050 } // end of wxListCtrl::ConvertToOS2Style
1051
1052 long wxListCtrl::ConvertArrangeToOS2Style (
1053 long lStyle
1054 )
1055 {
1056 long lWstyle = 0;
1057
1058 if (lStyle & wxLC_ALIGN_LEFT)
1059 {
1060 lWstyle |= CMA_LEFT;
1061 }
1062
1063 if (lStyle & wxLC_ALIGN_TOP)
1064 {
1065 lWstyle |= CMA_TOP;
1066 }
1067 return lWstyle;
1068 } // end of wxListCtrl::ConvertArrangeToOS2Style
1069
1070 long wxListCtrl::ConvertViewToOS2Style (
1071 long lStyle
1072 )
1073 {
1074 long lWstyle = CA_DRAWICON; // we will only use icons
1075
1076 if (lStyle & wxLC_ICON)
1077 {
1078 lWstyle |= CV_ICON;
1079 }
1080 if (lStyle & wxLC_SMALL_ICON)
1081 {
1082 lWstyle |= (CV_ICON | CV_MINI);
1083 }
1084 if (lStyle & wxLC_LIST)
1085 {
1086 lWstyle |= CV_TEXT;
1087 }
1088 if (lStyle & wxLC_REPORT)
1089 {
1090 lWstyle |= CV_DETAIL;
1091 }
1092 if (lStyle & wxLC_VIRTUAL)
1093 {
1094 lWstyle |= CA_OWNERDRAW;
1095 }
1096 if (lStyle & wxLC_AUTOARRANGE)
1097 {
1098 lWstyle |= CV_FLOW;
1099 }
1100 if (!(lStyle & wxLC_NO_HEADER))
1101 {
1102 lWstyle |= CA_DETAILSVIEWTITLES;
1103 }
1104 return lWstyle;
1105 } // end of wxListCtrl::ConvertViewToOS2Style
1106
1107 // ----------------------------------------------------------------------------
1108 // accessors
1109 // ----------------------------------------------------------------------------
1110
1111 // Sets the foreground, i.e. text, colour
1112 bool wxListCtrl::SetForegroundColour (const wxColour& rCol)
1113 {
1114 ULONG ulColor = wxColourToRGB(rCol);
1115
1116 if (!wxWindow::SetForegroundColour(rCol))
1117 return false;
1118
1119 ::WinSetPresParam( GetHWND()
1120 ,PP_FOREGROUNDCOLOR
1121 ,sizeof(ULONG)
1122 ,&ulColor
1123 );
1124 return true;
1125 } // end of wxListCtrl::SetForegroundColour
1126
1127 // Sets the background colour
1128 bool wxListCtrl::SetBackgroundColour ( const wxColour& rCol )
1129 {
1130 if (!wxWindow::SetBackgroundColour(rCol))
1131 return false;
1132
1133 //
1134 // We set the same colour for both the "empty" background and the items
1135 // background
1136 //
1137 ULONG ulColor = wxColourToRGB(rCol);
1138
1139 ::WinSetPresParam( GetHWND()
1140 ,PP_BACKGROUNDCOLOR
1141 ,sizeof(ULONG)
1142 ,&ulColor
1143 );
1144 return true;
1145 } // end of wxListCtrl::SetBackgroundColour
1146
1147 // Gets information about this column
1148 bool wxListCtrl::GetColumn ( int nCol, wxListItem& rItem ) const
1149 {
1150 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
1151
1152 if (!pFieldInfo)
1153 return false;
1154 rItem.SetWidth(pFieldInfo->cxWidth);
1155 if ((rItem.GetMask() & wxLIST_MASK_TEXT) &&
1156 (pFieldInfo->flData & CFA_STRING) &&
1157 (pFieldInfo->pUserData != NULL))
1158 {
1159 rItem.SetText((char*)pFieldInfo->pUserData);
1160 }
1161 if (rItem.GetMask() & wxLIST_MASK_FORMAT )
1162 {
1163 if (pFieldInfo->flData & CFA_LEFT)
1164 rItem.m_format = wxLIST_FORMAT_LEFT;
1165 else if (pFieldInfo->flData & CFA_RIGHT)
1166 rItem.m_format = wxLIST_FORMAT_RIGHT;
1167 else if (pFieldInfo->flData & CFA_CENTER)
1168 rItem.m_format = wxLIST_FORMAT_CENTRE;
1169 }
1170 return true;
1171 } // end of wxListCtrl::GetColumn
1172
1173 // Sets information about this column
1174 bool wxListCtrl::SetColumn ( int nCol, wxListItem& rItem )
1175 {
1176 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
1177 ConvertToOS2ListCol( nCol, rItem, pFieldInfo );
1178 //
1179 // Since we changed the field pointed to, we invalidate to see the result
1180 //
1181 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
1182 return true;
1183 } // end of wxListCtrl::SetColumn
1184
1185 // Gets the column width
1186 int wxListCtrl::GetColumnWidth ( int nCol ) const
1187 {
1188 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
1189
1190 if (!pFieldInfo)
1191 return 0;
1192 return((int)pFieldInfo->cxWidth);
1193 } // end of wxListCtrl::GetColumnWidth
1194
1195 // Sets the column width
1196 bool wxListCtrl::SetColumnWidth ( int nCol, int nWidth )
1197 {
1198 int nCol2 = nCol;
1199 int nWidth2 = nWidth;
1200
1201 if (GetWindowStyleFlag() & wxLC_LIST)
1202 nCol2 = -1;
1203
1204 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
1205 pFieldInfo->cxWidth = nWidth;
1206 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
1207 return true;
1208 } // end of wxListCtrl::SetColumnWidth
1209
1210 // Gets the number of items that can fit vertically in the
1211 // visible area of the list control (list or report view)
1212 // or the total number of items in the list control (icon
1213 // or small icon view)
1214 int wxListCtrl::GetCountPerPage () const
1215 {
1216 QUERYRECORDRECT vQueryRect;
1217 CNRINFO vCnrInfo;
1218 RECTL vRectRecord;
1219 RECTL vRectControl;
1220 int nCount;
1221
1222 if (!::WinSendMsg( GetHWND()
1223 ,CM_QUERYCNRINFO
1224 ,MPFROMP(&vCnrInfo)
1225 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1226 ))
1227 return 0;
1228 memset(&vQueryRect, '\0', sizeof(QUERYRECORDRECT));
1229 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1230 if (vCnrInfo.flWindowAttr & CV_ICON)
1231 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1232 else if (vCnrInfo.flWindowAttr & CV_NAME)
1233 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1234 else if (vCnrInfo.flWindowAttr & CV_TEXT)
1235 vQueryRect.fsExtent = CMA_TEXT;
1236 else if (vCnrInfo.flWindowAttr & CV_DETAIL)
1237 vQueryRect.fsExtent = CMA_TEXT;
1238 if (!::WinSendMsg( GetHWND()
1239 ,CM_QUERYRECORDRECT
1240 ,MPFROMP(&vRectRecord)
1241 ,MPFROMP(&vQueryRect)
1242 ))
1243 return 0;
1244 if (!::WinSendMsg( GetHWND()
1245 ,CM_QUERYVIEWPORTRECT
1246 ,MPFROMP(&vRectControl)
1247 ,MPFROM2SHORT(CMA_WINDOW, (USHORT)FALSE)
1248 ))
1249 return 0;
1250 nCount = (int)((int)((vRectControl.xRight - vRectControl.xLeft) / (vRectRecord.xRight - vRectRecord.xLeft)) *
1251 (int)((vRectControl.yTop - vRectControl.yBottom) / (vRectRecord.yTop - vRectRecord.yBottom))
1252 );
1253 if (nCount > (int)vCnrInfo.cFields)
1254 nCount = (int)vCnrInfo.cFields;
1255 return nCount;
1256 } // end of wxListCtrl::GetCountPerPage
1257
1258 // Gets the edit control for editing labels.
1259 wxTextCtrl* wxListCtrl::GetEditControl() const
1260 {
1261 return m_pTextCtrl;
1262 }
1263
1264 // Gets information about the item
1265 bool wxListCtrl::GetItem ( wxListItem& rInfo ) const
1266 {
1267 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
1268
1269 //
1270 // Give NULL as hwnd as we already have everything we need
1271 //
1272 ConvertFromOS2ListItem( NULL, rInfo, pRecord );
1273 return true;
1274 } // end of wxListCtrl::GetItem
1275
1276 // Sets information about the item
1277 bool wxListCtrl::SetItem ( wxListItem& rInfo )
1278 {
1279 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), rInfo.GetColumn() );
1280 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
1281
1282 ConvertToOS2ListItem( this
1283 ,rInfo
1284 ,pRecord
1285 ,pFieldInfo
1286 );
1287
1288 //
1289 // Check if setting attributes or lParam
1290 //
1291 if (rInfo.HasAttributes() || (rInfo.GetMask() & wxLIST_MASK_DATA))
1292 {
1293 //
1294 // Get internal item data
1295 // perhaps a cache here ?
1296 //
1297 CListItemInternalData* pData = GetInternalData( this
1298 ,rInfo.GetId()
1299 );
1300
1301 if (!pData)
1302 {
1303 //
1304 // Need to set it
1305 //
1306 m_bAnyInternalData = true;
1307 pData = new CListItemInternalData();
1308 pRecord->m_ulUserData = (unsigned long)pData;
1309 };
1310
1311 //
1312 // User data
1313 //
1314 if (rInfo.GetMask() & wxLIST_MASK_DATA)
1315 pData->m_lParam = (WXLPARAM)rInfo.GetData();
1316
1317 // attributes
1318 if (rInfo.HasAttributes())
1319 {
1320 if (pData->m_pAttr)
1321 *pData->m_pAttr = *rInfo.GetAttributes();
1322 else
1323 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
1324 }
1325 pData->m_pMyRecord = pRecord; // they point to each other
1326 }
1327
1328 //
1329 // We need to update the item immediately to show the new image
1330 //
1331 bool bUpdateNow = (rInfo.GetMask() & wxLIST_MASK_IMAGE) != 0;
1332
1333 //
1334 // Check whether it has any custom attributes
1335 //
1336 if (rInfo.HasAttributes())
1337 {
1338 m_bHasAnyAttr = true;
1339
1340 //
1341 // If the colour has changed, we must redraw the item
1342 //
1343 bUpdateNow = true;
1344 }
1345 if (::WinIsWindowVisible(GetHWND()))
1346 {
1347 ::WinSendMsg( GetHWND()
1348 ,CM_INVALIDATERECORD
1349 ,MPFROMP(pRecord)
1350 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1351 );
1352 RefreshItem(pRecord->m_ulItemId);
1353 }
1354 ::WinSendMsg( GetHWND()
1355 ,CM_INVALIDATEDETAILFIELDINFO
1356 ,NULL
1357 ,NULL
1358 );
1359 return true;
1360 } // end of wxListCtrl::SetItem
1361
1362 long wxListCtrl::SetItem (
1363 long lIndex
1364 , int nCol
1365 , const wxString& rsLabel
1366 , int nImageId
1367 )
1368 {
1369 wxListItem vInfo;
1370
1371 vInfo.m_text = rsLabel;
1372 vInfo.m_mask = wxLIST_MASK_TEXT;
1373 vInfo.m_itemId = lIndex;
1374 vInfo.m_col = nCol;
1375 if (nImageId > -1)
1376 {
1377 vInfo.m_image = nImageId;
1378 vInfo.m_mask |= wxLIST_MASK_IMAGE;
1379 }
1380 return SetItem(vInfo);
1381 } // end of wxListCtrl::SetItem
1382
1383 // Gets the item state
1384 int wxListCtrl::GetItemState (
1385 long lItem
1386 , long lStateMask
1387 ) const
1388 {
1389 wxListItem vInfo;
1390
1391 vInfo.m_mask = wxLIST_MASK_STATE;
1392 vInfo.m_stateMask = lStateMask;
1393 vInfo.m_itemId = lItem;
1394
1395 if (!GetItem(vInfo))
1396 return 0;
1397 return vInfo.m_state;
1398 } // end of wxListCtrl::GetItemState
1399
1400 // Sets the item state
1401 bool wxListCtrl::SetItemState ( long lItem, long lState, long lStateMask )
1402 {
1403 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1404
1405 //
1406 // Don't use SetItem() here as it doesn't work with the virtual list
1407 // controls
1408 //
1409 ConvertToOS2Flags( lState, pRecord );
1410
1411 //
1412 // for the virtual list controls we need to refresh the previously focused
1413 // item manually when changing focus without changing selection
1414 // programmatically because otherwise it keeps its focus rectangle until
1415 // next repaint (yet another comctl32 bug)
1416 //
1417 long lFocusOld;
1418
1419 if (IsVirtual() &&
1420 (lStateMask & wxLIST_STATE_FOCUSED) &&
1421 (lState & wxLIST_STATE_FOCUSED) )
1422 {
1423 lFocusOld = GetNextItem( -1
1424 ,wxLIST_NEXT_ALL
1425 ,wxLIST_STATE_FOCUSED
1426 );
1427 }
1428 else
1429 {
1430 lFocusOld = -1;
1431 }
1432 ::WinSendMsg( GetHWND()
1433 ,CM_INVALIDATERECORD
1434 ,MPFROMP(pRecord)
1435 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1436 );
1437
1438 if (lFocusOld != -1)
1439 {
1440 //
1441 // No need to refresh the item if it was previously selected, it would
1442 // only result in annoying flicker
1443 //
1444 if (!(GetItemState( lFocusOld
1445 ,wxLIST_STATE_SELECTED
1446 ) & wxLIST_STATE_SELECTED))
1447 {
1448 RefreshItem(lFocusOld);
1449 }
1450 }
1451 return true;
1452 } // end of wxListCtrl::SetItemState
1453
1454 // Sets the item image
1455 bool wxListCtrl::SetItemImage (
1456 long lItem
1457 , int nImage
1458 , int WXUNUSED(nSelImage))
1459 {
1460 return SetItemColumnInfo(lItem, 0, nImage);
1461 } // end of wxListCtrl::SetItemImage
1462
1463 // Sets the item image
1464 bool wxListCtrl::SetItemColumnImage (
1465 long lItem
1466 , long lColumn
1467 , int nImage
1468 {
1469 wxListItem vInfo;
1470
1471 vInfo.m_mask = wxLIST_MASK_IMAGE;
1472 vInfo.m_image = nImage;
1473 vInfo.m_itemId = lItem;
1474 vInfo.m_col = lColumn;
1475 return SetItem(vInfo);
1476 } // end of wxListCtrl::SetItemColumnImage
1477
1478 // Gets the item text
1479 wxString wxListCtrl::GetItemText (
1480 long lItem
1481 ) const
1482 {
1483 wxListItem vInfo;
1484
1485 vInfo.m_mask = wxLIST_MASK_TEXT;
1486 vInfo.m_itemId = lItem;
1487
1488 if (!GetItem(vInfo))
1489 return wxEmptyString;
1490 return vInfo.m_text;
1491 } // end of wxListCtrl::GetItemText
1492
1493 // Sets the item text
1494 void wxListCtrl::SetItemText (
1495 long lItem
1496 , const wxString& rsStr
1497 )
1498 {
1499 wxListItem vInfo;
1500
1501 vInfo.m_mask = wxLIST_MASK_TEXT;
1502 vInfo.m_itemId = lItem;
1503 vInfo.m_text = rsStr;
1504 SetItem(vInfo);
1505 } // end of wxListCtrl::SetItemText
1506
1507 // Gets the item data
1508 long wxListCtrl::GetItemData (
1509 long lItem
1510 ) const
1511 {
1512 wxListItem vInfo;
1513
1514 vInfo.m_mask = wxLIST_MASK_DATA;
1515 vInfo.m_itemId = lItem;
1516 if (!GetItem(vInfo))
1517 return 0;
1518 return vInfo.m_data;
1519 } // end of wxListCtrl::GetItemData
1520
1521 // Sets the item data
1522 bool wxListCtrl::SetItemPtrData (
1523 long lItem
1524 , wxUIntPtr lData
1525 )
1526 {
1527 wxListItem vInfo;
1528
1529 vInfo.m_mask = wxLIST_MASK_DATA;
1530 vInfo.m_itemId = lItem;
1531 vInfo.m_data = lData;
1532 return SetItem(vInfo);
1533 } // end of wxListCtrl::SetItemPtrData
1534
1535 // Gets the item rectangle
1536 bool wxListCtrl::GetItemRect ( long lItem,
1537 wxRect& rRect,
1538 int nCode ) const
1539 {
1540 bool bSuccess;
1541 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1542 QUERYRECORDRECT vQueryRect;
1543 RECTL vRect;
1544 int nHeight;
1545
1546 if (!pRecord)
1547 return false;
1548 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1549 vQueryRect.pRecord = &pRecord->m_vRecord;
1550 vQueryRect.fRightSplitWindow = TRUE;
1551 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1552 ::WinSendMsg( GetHWND()
1553 ,CM_QUERYRECORDRECT
1554 ,MPFROMP(&vRect)
1555 ,MPFROMP(&vQueryRect)
1556 );
1557 //
1558 // remember OS/2 is backwards
1559 //
1560 GetClientSize( NULL, &nHeight );
1561 rRect.x = vRect.xLeft;
1562 rRect.y = nHeight - vRect.yTop;
1563 rRect.width = vRect.xRight;
1564 rRect.height = nHeight - vRect.yBottom;
1565 bSuccess = true;
1566 return bSuccess;
1567 } // end of wxListCtrl::GetItemRect
1568
1569 // Gets the item position
1570 bool wxListCtrl::GetItemPosition ( long lItem, wxPoint& rPos ) const
1571 {
1572 bool bSuccess;
1573 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND() , lItem );
1574 QUERYRECORDRECT vQueryRect;
1575 RECTL vRect;
1576 int nHeight;
1577
1578 if (!pRecord)
1579 return false;
1580 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1581 vQueryRect.pRecord = &pRecord->m_vRecord;
1582 vQueryRect.fRightSplitWindow = TRUE;
1583 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1584 ::WinSendMsg( GetHWND()
1585 ,CM_QUERYRECORDRECT
1586 ,MPFROMP(&vRect)
1587 ,MPFROMP(&vQueryRect)
1588 );
1589 //
1590 // remember OS/2 is backwards
1591 //
1592 GetClientSize( NULL, &nHeight );
1593 rPos.x = vRect.xLeft;
1594 rPos.y = nHeight - vRect.yTop;
1595 bSuccess = true;
1596 return bSuccess;
1597 } // end of wxListCtrl::GetItemPosition
1598
1599 // Sets the item position.
1600 bool wxListCtrl::SetItemPosition ( long lItem, const wxPoint& rPos )
1601 {
1602 //
1603 // Items cannot be positioned in X/Y coord in OS/2
1604 //
1605 return false;
1606 } // end of wxListCtrl::SetItemPosition
1607
1608 // Gets the number of items in the list control
1609 int wxListCtrl::GetItemCount () const
1610 {
1611 CNRINFO vCnrInfo;
1612
1613 if (!::WinSendMsg( GetHWND()
1614 ,CM_QUERYCNRINFO
1615 ,MPFROMP(&vCnrInfo)
1616 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1617 ))
1618 return -1;
1619 return vCnrInfo.cRecords;
1620 } // end of wxListCtrl::GetItemCount
1621
1622 // Retrieves the spacing between icons in pixels.
1623 // If bIsSmall is true, gets the spacing for the small icon
1624 // view, otherwise the large icon view.
1625 int wxListCtrl::GetItemSpacing ( bool bIsSmall ) const
1626 {
1627 CNRINFO vCnrInfo;
1628
1629 if (!::WinSendMsg( GetHWND()
1630 ,CM_QUERYCNRINFO
1631 ,MPFROMP(&vCnrInfo)
1632 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1633 ))
1634 return -1;
1635 return vCnrInfo.cyLineSpacing;
1636 } // end of wxListCtrl::GetItemSpacing
1637
1638 void wxListCtrl::SetItemTextColour (
1639 long lItem
1640 , const wxColour& rCol
1641 )
1642 {
1643 wxListItem vInfo;
1644
1645 vInfo.m_itemId = lItem;
1646 vInfo.SetTextColour(rCol);
1647 SetItem(vInfo);
1648 } // end of wxListCtrl::SetItemTextColour
1649
1650 wxColour wxListCtrl::GetItemTextColour (
1651 long lItem
1652 ) const
1653 {
1654 wxListItem vInfo;
1655
1656 vInfo.m_itemId = lItem;
1657 GetItem(vInfo);
1658 return vInfo.GetTextColour();
1659 } // end of wxListCtrl::GetItemTextColour
1660
1661 void wxListCtrl::SetItemBackgroundColour (
1662 long lItem
1663 , const wxColour& rCol
1664 )
1665 {
1666 wxListItem vInfo;
1667
1668 vInfo.m_itemId = lItem;
1669 vInfo.SetBackgroundColour(rCol);
1670 SetItem(vInfo);
1671 } // end of wxListCtrl::SetItemBackgroundColour
1672
1673 wxColour wxListCtrl::GetItemBackgroundColour (
1674 long lItem
1675 ) const
1676 {
1677 wxListItem vInfo;
1678
1679 vInfo.m_itemId = lItem;
1680 GetItem(vInfo);
1681 return vInfo.GetBackgroundColour();
1682 } // end of wxListCtrl::GetItemBackgroundColour
1683
1684 // Gets the number of selected items in the list control
1685 int wxListCtrl::GetSelectedItemCount () const
1686 {
1687 PMYRECORD pRecord = NULL;
1688 int nCount = 0;
1689 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1690 ,CM_QUERYRECORDEMPHASIS
1691 ,(MPARAM)CMA_FIRST
1692 ,(MPARAM)CRA_SELECTED
1693 ));
1694 if (pRecord)
1695 nCount++;
1696 else
1697 return 0;
1698 while (pRecord)
1699 {
1700 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1701 ,CM_QUERYRECORDEMPHASIS
1702 ,MPFROMP(pRecord)
1703 ,(MPARAM)CRA_SELECTED
1704 ));
1705 if (pRecord)
1706 nCount++;
1707 }
1708 return nCount;
1709 } // end of wxListCtrl::GetSelectedItemCount
1710
1711 // Gets the text colour of the listview
1712 wxColour wxListCtrl::GetTextColour () const
1713 {
1714 wxColour vCol;
1715 ULONG ulColor;
1716
1717 ::WinQueryPresParam( GetHWND()
1718 ,PP_FOREGROUNDCOLOR
1719 ,0
1720 ,NULL
1721 ,sizeof(ULONG)
1722 ,&ulColor
1723 ,QPF_PURERGBCOLOR
1724 );
1725 vCol.Set(ulColor);
1726 return vCol;
1727 } // end of wxListCtrl::GetTextColour
1728
1729 // Sets the text colour of the listview
1730 void wxListCtrl::SetTextColour (
1731 const wxColour& rCol
1732 )
1733 {
1734 ULONG ulColor = wxColourToRGB(rCol);
1735
1736 ::WinSetPresParam( GetHWND()
1737 ,PP_FOREGROUNDCOLOR
1738 ,sizeof(ULONG)
1739 ,&ulColor
1740 );
1741 } // end of wxListCtrl::SetTextColour
1742
1743 // Gets the index of the topmost visible item when in
1744 // list or report view
1745 long wxListCtrl::GetTopItem () const
1746 {
1747 PMYRECORD pRecord = NULL;
1748 QUERYRECFROMRECT vQueryRect;
1749 RECTL vRect;
1750
1751 ::WinSendMsg( GetHWND()
1752 ,CM_QUERYVIEWPORTRECT
1753 ,MPFROMP(&vRect)
1754 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
1755 );
1756 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
1757 vQueryRect.rect = vRect;
1758 vQueryRect.fsSearch = CMA_PARTIAL;
1759
1760 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1761 ,CM_QUERYRECORDFROMRECT
1762 ,(MPARAM)CMA_FIRST
1763 ,MPFROMP(&vQueryRect)
1764 );
1765
1766 if (!pRecord)
1767 return -1L;
1768 return (long)pRecord->m_ulItemId;
1769 } // end of wxListCtrl::GetTopItem
1770
1771 // Searches for an item, starting from 'item'.
1772 // 'geometry' is one of
1773 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
1774 // 'state' is a state bit flag, one or more of
1775 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
1776 // item can be -1 to find the first item that matches the
1777 // specified flags.
1778 // Returns the item or -1 if unsuccessful.
1779 long wxListCtrl::GetNextItem (
1780 long lItem
1781 , int WXUNUSED(nGeom)
1782 , int WXUNUSED(nState)
1783 ) const
1784 {
1785 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1786 ,lItem
1787 );
1788
1789 pRecord = (PMYRECORD)pRecord->m_vRecord.preccNextRecord;
1790 if (pRecord)
1791 return((long)pRecord->m_ulItemId);
1792 return -1L;
1793 } // end of wxListCtrl::GetNextItem
1794
1795 wxImageList* wxListCtrl::GetImageList (
1796 int nWhich
1797 ) const
1798 {
1799 if (nWhich == wxIMAGE_LIST_NORMAL )
1800 {
1801 return m_pImageListNormal;
1802 }
1803 else if (nWhich == wxIMAGE_LIST_SMALL )
1804 {
1805 return m_pImageListSmall;
1806 }
1807 else if (nWhich == wxIMAGE_LIST_STATE )
1808 {
1809 return m_pImageListState;
1810 }
1811 return NULL;
1812 } // end of wxListCtrl::GetImageList
1813
1814 void wxListCtrl::SetImageList ( wxImageList* pImageList,
1815 int nWhich )
1816 {
1817 if (nWhich == wxIMAGE_LIST_NORMAL)
1818 {
1819 if (m_bOwnsImageListNormal)
1820 delete m_pImageListNormal;
1821 m_pImageListNormal = pImageList;
1822 m_bOwnsImageListNormal = false;
1823 }
1824 else if (nWhich == wxIMAGE_LIST_SMALL)
1825 {
1826 if (m_bOwnsImageListSmall)
1827 delete m_pImageListSmall;
1828 m_pImageListSmall = pImageList;
1829 m_bOwnsImageListSmall = false;
1830 }
1831 else if (nWhich == wxIMAGE_LIST_STATE)
1832 {
1833 if (m_bOwnsImageListState)
1834 delete m_pImageListState;
1835 m_pImageListState = pImageList;
1836 m_bOwnsImageListState = false;
1837 }
1838 } // end of wxListCtrl::SetImageList
1839
1840 void wxListCtrl::AssignImageList ( wxImageList* pImageList, int nWhich )
1841 {
1842 SetImageList( pImageList, nWhich );
1843
1844 if (nWhich == wxIMAGE_LIST_NORMAL )
1845 m_bOwnsImageListNormal = true;
1846 else if (nWhich == wxIMAGE_LIST_SMALL )
1847 m_bOwnsImageListSmall = true;
1848 else if (nWhich == wxIMAGE_LIST_STATE )
1849 m_bOwnsImageListState = true;
1850 } // end of wxListCtrl::AssignImageList
1851
1852 // ----------------------------------------------------------------------------
1853 // Operations
1854 // ----------------------------------------------------------------------------
1855
1856 // Arranges the items
1857 bool wxListCtrl::Arrange ( int nFlag )
1858 {
1859 ULONG ulType = 0L;
1860 ULONG ulFlags = 0L;
1861
1862 if (nFlag == wxLIST_ALIGN_SNAP_TO_GRID)
1863 {
1864 ulType = CMA_ARRANGEGRID;
1865 if (nFlag == wxLIST_ALIGN_LEFT)
1866 ulFlags |= CMA_LEFT;
1867 else if (nFlag == wxLIST_ALIGN_TOP)
1868 ulFlags |= CMA_TOP;
1869 else if (nFlag == wxLIST_ALIGN_DEFAULT)
1870 ulFlags |= CMA_LEFT;
1871 }
1872 else
1873 ulType = CMA_ARRANGESTANDARD;
1874 ::WinSendMsg( GetHWND()
1875 ,CM_ARRANGE
1876 ,(MPARAM)ulType
1877 ,(MPARAM)ulFlags
1878 );
1879 //
1880 // We do not support CMA_ARRANGESELECTED
1881 //
1882 return true;
1883 } // end of wxListCtrl::Arrange
1884
1885 // Deletes an item
1886 bool wxListCtrl::DeleteItem ( long lItem )
1887 {
1888 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1889 if (LONGFROMMR(::WinSendMsg( GetHWND()
1890 ,CM_REMOVERECORD
1891 ,(MPARAM)pRecord
1892 ,MPFROM2SHORT(1, CMA_FREE)
1893 )) == -1L)
1894 {
1895 return false;
1896 }
1897
1898 //
1899 // The virtual list control doesn't refresh itself correctly, help it
1900 //
1901 if (IsVirtual())
1902 {
1903 //
1904 // We need to refresh all the lines below the one which was deleted
1905 //
1906 wxRect vRectItem;
1907
1908 if (lItem > 0 && GetItemCount())
1909 {
1910 GetItemRect( lItem - 1
1911 ,vRectItem
1912 );
1913 }
1914 else
1915 {
1916 vRectItem.y = vRectItem.height = 0;
1917 }
1918 wxRect vRectWin = GetRect();
1919
1920 vRectWin.height = vRectWin.GetBottom() - vRectItem.GetBottom();
1921 vRectWin.y = vRectItem.GetBottom();
1922 RefreshRect(vRectWin);
1923 }
1924 return true;
1925 } // end of wxListCtrl::DeleteItem
1926
1927 // Deletes all items
1928 bool wxListCtrl::DeleteAllItems ()
1929 {
1930 return((LONG)::WinSendMsg( GetHWND()
1931 ,CM_REMOVERECORD
1932 ,NULL
1933 ,MPFROM2SHORT(0, CMA_FREE)
1934 ) != -1L);
1935 } // end of wxListCtrl::DeleteAllItems
1936
1937 // Deletes all items
1938 bool wxListCtrl::DeleteAllColumns ()
1939 {
1940 while (m_nColCount > 0)
1941 {
1942 DeleteColumn(m_nColCount - 1);
1943 m_nColCount--;
1944 }
1945
1946 wxASSERT_MSG(m_nColCount == 0, wxT("no columns should be left"));
1947 return true;
1948 } // end of wxListCtrl::DeleteAllColumns
1949
1950 // Deletes a column
1951 bool wxListCtrl::DeleteColumn ( int nCol )
1952 {
1953 bool bSuccess = false;
1954 PFIELDINFO pField = FindOS2ListFieldByColNum( GetHWND(), nCol );
1955 bSuccess = ((LONG)::WinSendMsg( GetHWND()
1956 ,CM_REMOVEDETAILFIELDINFO
1957 ,MPFROMP(pField)
1958 ,MPFROM2SHORT((SHORT)1, CMA_FREE)
1959 ) == -1L);
1960 if (bSuccess && (m_nColCount > 0))
1961 m_nColCount--;
1962 return bSuccess;
1963 } // end of wxListCtrl::DeleteColumn
1964
1965 // Clears items, and columns if there are any.
1966 void wxListCtrl::ClearAll ()
1967 {
1968 DeleteAllItems();
1969 if (m_nColCount > 0)
1970 DeleteAllColumns();
1971 } // end of wxListCtrl::ClearAll
1972
1973 //
1974 // OS/2 does not use a text control for its container labels. You merely
1975 // "open" a record for editting.
1976 //
1977 wxTextCtrl* wxListCtrl::EditLabel (
1978 long lItem
1979 , wxClassInfo* WXUNUSED(pTextControlClass)
1980 )
1981 {
1982 CNREDITDATA vEdit;
1983 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1984 ,lItem
1985 );
1986
1987 vEdit.cb = sizeof(CNREDITDATA);
1988 vEdit.hwndCnr = GetHWND();
1989 vEdit.pRecord = &pRecord->m_vRecord;
1990 vEdit.pFieldInfo = NULL;
1991 vEdit.ppszText = NULL;
1992 vEdit.cbText = 0;
1993 vEdit.id = 0;
1994
1995 ::WinSendMsg( GetHWND()
1996 ,CM_OPENEDIT
1997 ,MPFROMP(&vEdit)
1998 ,(MPARAM)0
1999 );
2000 return m_pTextCtrl;
2001 } // end of wxListCtrl::EditLabel
2002
2003 // End label editing, optionally cancelling the edit. Under OS/2 you close
2004 // the record for editting
2005 bool wxListCtrl::EndEditLabel ( bool WXUNUSED(bCancel) )
2006 {
2007 ::WinSendMsg( GetHWND()
2008 ,CM_CLOSEEDIT
2009 ,(MPARAM)0
2010 ,(MPARAM)0
2011 );
2012 return true;
2013 } // end of wxListCtrl::EndEditLabel
2014
2015 // Ensures this item is visible
2016 bool wxListCtrl::EnsureVisible ( long lItem )
2017 {
2018 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
2019 ::WinSendMsg( GetHWND()
2020 ,CM_INVALIDATERECORD
2021 ,MPFROMP(pRecord)
2022 ,MPFROM2SHORT((SHORT)1, CMA_NOREPOSITION)
2023 );
2024 return true;
2025 } // end of wxListCtrl::EnsureVisible
2026
2027 // Find an item whose label matches this string, starting from the item after 'start'
2028 // or the beginning if 'start' is -1.
2029 long wxListCtrl::FindItem (
2030 long lStart
2031 , const wxString& rsStr
2032 , bool bPartial
2033 )
2034 {
2035 CNRINFO vCnrInfo;
2036 SEARCHSTRING vSearch;
2037 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2038 ,lStart
2039 );
2040 ULONG ulFlag;
2041
2042
2043 if (!::WinSendMsg( GetHWND()
2044 ,CM_QUERYCNRINFO
2045 ,MPFROMP(&vCnrInfo)
2046 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2047 ))
2048 return -1L;
2049
2050 if (vCnrInfo.flWindowAttr & CV_ICON)
2051 ulFlag = CV_ICON;
2052 if (vCnrInfo.flWindowAttr & CV_NAME)
2053 ulFlag = CV_NAME;
2054 if (vCnrInfo.flWindowAttr & CV_TEXT)
2055 ulFlag = CV_TEXT;
2056 if (vCnrInfo.flWindowAttr & CV_DETAIL)
2057 ulFlag = CV_DETAIL;
2058 if (!bPartial)
2059 ulFlag |= CV_EXACTLENGTH;
2060
2061 vSearch.cb = sizeof(SEARCHSTRING);
2062 vSearch.pszSearch = (char*)rsStr.c_str();
2063 vSearch.fsPrefix = TRUE;
2064 vSearch.fsCaseSensitive = TRUE;
2065 vSearch.usView = ulFlag;
2066
2067 if (lStart == -1)
2068 {
2069 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2070 ,CM_SEARCHSTRING
2071 ,MPFROMP(&vSearch)
2072 ,(MPARAM)CMA_FIRST
2073 );
2074 }
2075 else
2076 {
2077 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2078 ,CM_SEARCHSTRING
2079 ,MPFROMP(&vSearch)
2080 ,MPFROMP(pRecord)
2081 );
2082 }
2083 if (!pRecord)
2084 return -1L;
2085 return pRecord->m_ulItemId;
2086 } // end of wxListCtrl::FindItem
2087
2088 // Find an item whose data matches this data, starting from the item after 'start'
2089 // or the beginning if 'start' is -1.
2090 long wxListCtrl::FindItem (
2091 long lStart
2092 , long lData
2093 )
2094 {
2095 long lIdx = lStart + 1;
2096 long lCount = GetItemCount();
2097
2098 while (lIdx < lCount)
2099 {
2100 if (GetItemData(lIdx) == lData)
2101 return lIdx;
2102 lIdx++;
2103 };
2104 return -1;
2105 } // end of wxListCtrl::FindItem
2106
2107 // Find an item nearest this position in the specified direction, starting from
2108 // the item after 'start' or the beginning if 'start' is -1.
2109 long wxListCtrl::FindItem (
2110 long lStart
2111 , const wxPoint& rPoint
2112 , int nDirection
2113 )
2114 {
2115 RECTL vRect;
2116 QUERYRECORDRECT vQueryRect;
2117 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2118 ,lStart
2119 );
2120 CNRINFO vCnrInfo;
2121 ULONG i;
2122 wxRect vLibRect;
2123
2124 if (!::WinSendMsg( GetHWND()
2125 ,CM_QUERYCNRINFO
2126 ,MPFROMP(&vCnrInfo)
2127 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2128 ))
2129 return -1L;
2130
2131 vQueryRect.cb = sizeof(QUERYRECORDRECT);
2132 vQueryRect.pRecord = &pRecord->m_vRecord;
2133 vQueryRect.fRightSplitWindow = TRUE;
2134 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
2135
2136 ::WinSendMsg( GetHWND()
2137 ,CM_QUERYRECORDRECT
2138 ,MPFROMP(&vRect)
2139 ,MPFROMP(&vQueryRect)
2140 );
2141 vLibRect.SetLeft(vRect.xLeft);
2142 vLibRect.SetTop(vRect.yTop);
2143 vLibRect.SetRight(vRect.xRight);
2144 vLibRect.SetBottom(vRect.yBottom);
2145 if (vLibRect.Contains(rPoint))
2146 return pRecord->m_ulItemId;
2147
2148 for (i = lStart + 1; i < vCnrInfo.cRecords; i++)
2149 {
2150 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
2151 ,CM_QUERYRECORD
2152 ,MPFROMP(pRecord)
2153 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
2154 ));
2155 vQueryRect.pRecord = (PRECORDCORE)pRecord;
2156 ::WinSendMsg( GetHWND()
2157 ,CM_QUERYRECORDRECT
2158 ,MPFROMP(&vRect)
2159 ,MPFROMP(&vQueryRect)
2160 );
2161 vLibRect.SetLeft(vRect.xLeft);
2162 vLibRect.SetTop(vRect.yTop);
2163 vLibRect.SetRight(vRect.xRight);
2164 vLibRect.SetBottom(vRect.yBottom);
2165 if (vLibRect.Contains(rPoint))
2166 return pRecord->m_ulItemId;
2167 }
2168 return -1L;
2169 } // end of wxListCtrl::FindItem
2170
2171 // Determines which item (if any) is at the specified point,
2172 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
2173 long wxListCtrl::HitTest (
2174 const wxPoint& rPoint
2175 , int& WXUNUSED(rFlags)
2176 )
2177 {
2178 PMYRECORD pRecord = NULL;
2179 QUERYRECFROMRECT vQueryRect;
2180 RECTL vRect;
2181 long lHeight;
2182
2183 //
2184 // Get height for OS/2 point conversion
2185 //
2186 ::WinSendMsg( GetHWND()
2187 ,CM_QUERYVIEWPORTRECT
2188 ,MPFROMP(&vRect)
2189 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
2190 );
2191 lHeight = vRect.yTop - vRect.yBottom;
2192
2193 //
2194 // For now just try and get a record in the general vicinity and forget
2195 // the flag
2196 //
2197 vRect.xLeft = rPoint.x - 2;
2198 vRect.xRight = rPoint.x + 2;
2199 vRect.yTop = (lHeight - rPoint.y) + 2;
2200 vRect.yBottom = (lHeight - rPoint.y) - 2;
2201
2202 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
2203 vQueryRect.rect = vRect;
2204 vQueryRect.fsSearch = CMA_PARTIAL;
2205
2206 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2207 ,CM_QUERYRECORDFROMRECT
2208 ,(MPARAM)CMA_FIRST
2209 ,MPFROMP(&vQueryRect)
2210 );
2211
2212 if (!pRecord)
2213 return -1L;
2214 return pRecord->m_ulItemId;
2215 } // end of wxListCtrl::HitTest
2216
2217 // Inserts an item, returning the index of the new item if successful,
2218 // -1 otherwise.
2219 long wxListCtrl::InsertItem (
2220 wxListItem& rInfo
2221 )
2222 {
2223 wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual controls") );
2224
2225 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
2226 ,rInfo.GetColumn()
2227 );
2228 PMYRECORD pRecordAfter = NULL;
2229 PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2230 ,CM_ALLOCRECORD
2231 ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
2232 ,MPFROMSHORT(1)
2233 );
2234
2235 ConvertToOS2ListItem( this
2236 ,rInfo
2237 ,pRecord
2238 ,pFieldInfo
2239 );
2240
2241 if (rInfo.GetId() > 0)
2242 pRecordAfter = FindOS2ListRecordByID( GetHWND()
2243 ,rInfo.GetId() - 1
2244 );
2245
2246 RECORDINSERT vInsert;
2247
2248 vInsert.cb = sizeof(RECORDINSERT);
2249 vInsert.pRecordParent = NULL;
2250 if (!pRecordAfter)
2251 vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
2252 else
2253 vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
2254 vInsert.zOrder = CMA_TOP;
2255 vInsert.cRecordsInsert = 1;
2256 vInsert.fInvalidateRecord = TRUE;
2257
2258 //
2259 // Check wether we need to allocate our internal data
2260 //
2261 bool bNeedInternalData = ((rInfo.GetMask() & wxLIST_MASK_DATA) ||
2262 rInfo.HasAttributes()
2263 );
2264 if (bNeedInternalData)
2265 {
2266 m_bAnyInternalData = true;
2267
2268 //
2269 // Internal stucture that manages data
2270 //
2271 CListItemInternalData* pData = new CListItemInternalData();
2272
2273 pRecord->m_ulUserData = (unsigned long)pData;
2274 if (rInfo.GetMask() & wxLIST_MASK_DATA)
2275 pData->m_lParam = (WXLPARAM)rInfo.GetData();
2276
2277 //
2278 // Check whether it has any custom attributes
2279 //
2280 if (rInfo.HasAttributes())
2281 {
2282 //
2283 // Take copy of attributes
2284 //
2285 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
2286 }
2287 }
2288 if (!::WinSendMsg( GetHWND()
2289 ,CM_INSERTRECORD
2290 ,MPFROMP(pRecord)
2291 ,MPFROMP(&vInsert)
2292 ))
2293 return -1;
2294 //
2295 // OS/2 must mannually bump the index's of following records
2296 //
2297 BumpRecordIds( GetHWND()
2298 ,pRecord
2299 );
2300 ::WinSendMsg( GetHWND()
2301 ,CM_INVALIDATEDETAILFIELDINFO
2302 ,NULL
2303 ,NULL
2304 );
2305 return pRecord->m_ulItemId;
2306 } // end of wxListCtrl::InsertItem
2307
2308 long wxListCtrl::InsertItem (
2309 long lIndex
2310 , const wxString& rsLabel
2311 )
2312 {
2313 wxListItem vInfo;
2314
2315 memset(&vInfo, '\0', sizeof(wxListItem));
2316 vInfo.m_text = rsLabel;
2317 vInfo.m_mask = wxLIST_MASK_TEXT;
2318 vInfo.m_itemId = lIndex;
2319 return InsertItem(vInfo);
2320 } // end of wxListCtrl::InsertItem
2321
2322 // Inserts an image item
2323 long wxListCtrl::InsertItem (
2324 long lIndex
2325 , int nImageIndex
2326 )
2327 {
2328 wxListItem vInfo;
2329
2330 vInfo.m_image = nImageIndex;
2331 vInfo.m_mask = wxLIST_MASK_IMAGE;
2332 vInfo.m_itemId = lIndex;
2333 return InsertItem(vInfo);
2334 } // end of wxListCtrl::InsertItem
2335
2336 // Inserts an image/string item
2337 long wxListCtrl::InsertItem (
2338 long lIndex
2339 , const wxString& rsLabel
2340 , int nImageIndex
2341 )
2342 {
2343 wxListItem vInfo;
2344
2345 vInfo.m_image = nImageIndex;
2346 vInfo.m_text = rsLabel;
2347 vInfo.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
2348 vInfo.m_itemId = lIndex;
2349 return InsertItem(vInfo);
2350 } // end of wxListCtrl::InsertItem
2351
2352 // For details view mode (only), inserts a column.
2353 long wxListCtrl::InsertColumn (
2354 long lCol
2355 , wxListItem& rItem
2356 )
2357 {
2358 bool bSuccess;
2359 PFIELDINFO pField = (PFIELDINFO)::WinSendMsg( GetHWND()
2360 ,CM_ALLOCDETAILFIELDINFO
2361 ,MPFROMLONG(1)
2362 ,NULL
2363 );
2364 PFIELDINFO pFieldAfter = FindOS2ListFieldByColNum ( GetHWND()
2365 ,lCol - 1
2366 );
2367 FIELDINFOINSERT vInsert;
2368
2369 ConvertToOS2ListCol ( lCol
2370 ,rItem
2371 ,pField
2372 );
2373
2374 vInsert.cb = sizeof(FIELDINFOINSERT);
2375 vInsert.pFieldInfoOrder = pFieldAfter;
2376 vInsert.fInvalidateFieldInfo = TRUE;
2377 vInsert.cFieldInfoInsert = 1;
2378
2379 bSuccess = ::WinSendMsg( GetHWND()
2380 ,CM_INSERTDETAILFIELDINFO
2381 ,MPFROMP(pField)
2382 ,MPFROMP(&vInsert)
2383 ) != (MRESULT)0;
2384 return bSuccess;
2385 } // end of wxListCtrl::InsertColumn
2386
2387 long wxListCtrl::InsertColumn (
2388 long lCol
2389 , const wxString& rsHeading
2390 , int nFormat
2391 , int nWidth
2392 )
2393 {
2394 wxListItem vItem;
2395
2396 vItem.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2397 vItem.m_text = rsHeading;
2398 if (nWidth > -1)
2399 {
2400 vItem.m_mask |= wxLIST_MASK_WIDTH;
2401 vItem.m_width = nWidth;
2402 }
2403 vItem.m_format = nFormat;
2404
2405 return InsertColumn( lCol
2406 ,vItem
2407 );
2408 } // end of wxListCtrl::InsertColumn
2409
2410 // scroll the control by the given number of pixels (exception: in list view,
2411 // dx is interpreted as number of columns)
2412 bool wxListCtrl::ScrollList ( int nDx, int nDy )
2413 {
2414 if (nDx > 0)
2415 ::WinSendMsg( GetHWND()
2416 ,CM_SCROLLWINDOW
2417 ,(MPARAM)CMA_HORIZONTAL
2418 ,(MPARAM)nDx
2419 );
2420 if (nDy > 0)
2421 ::WinSendMsg( GetHWND()
2422 ,CM_SCROLLWINDOW
2423 ,(MPARAM)CMA_VERTICAL
2424 ,(MPARAM)nDy
2425 );
2426 return true;
2427 } // end of wxListCtrl::ScrollList
2428
2429 bool wxListCtrl::SortItems ( wxListCtrlCompare fn, long lData )
2430 {
2431 SInternalDataSort vInternalData;
2432
2433 vInternalData.m_fnUser = fn;
2434 vInternalData.m_lData = lData;
2435
2436 // WPARAM cast is needed for mingw/cygwin
2437 if (!::WinSendMsg( GetHWND()
2438 ,CM_SORTRECORD
2439 ,(PFN)InternalDataCompareFunc
2440 ,(PVOID)&vInternalData
2441 ))
2442 {
2443 wxLogDebug(_T("CM_SORTRECORD failed"));
2444 return false;
2445 }
2446 return true;
2447 } // end of wxListCtrl::SortItems
2448
2449 // ----------------------------------------------------------------------------
2450 // message processing
2451 // ----------------------------------------------------------------------------
2452
2453 bool wxListCtrl::OS2Command ( WXUINT uCmd, WXWORD wId )
2454 {
2455 if (uCmd == CN_ENDEDIT)
2456 {
2457 wxCommandEvent vEvent( wxEVT_COMMAND_TEXT_UPDATED, wId );
2458
2459 vEvent.SetEventObject( this );
2460 ProcessCommand(vEvent);
2461 return true;
2462 }
2463 else if (uCmd == CN_KILLFOCUS)
2464 {
2465 wxCommandEvent vEvent( wxEVT_KILL_FOCUS, wId );
2466 vEvent.SetEventObject( this );
2467 ProcessCommand(vEvent);
2468 return true;
2469 }
2470 else
2471 return false;
2472 } // end of wxListCtrl::OS2Command
2473
2474 // Necessary for drawing hrules and vrules, if specified
2475 void wxListCtrl::OnPaint ( wxPaintEvent& rEvent )
2476 {
2477 wxPaintDC vDc(this);
2478 wxPen vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT)
2479 ,1
2480 ,wxSOLID
2481 );
2482 wxSize vClientSize = GetClientSize();
2483 wxRect vItemRect;
2484 int nItemCount = GetItemCount();
2485 int nCy = 0;
2486 int i;
2487 bool bDrawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
2488 bool bDrawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
2489
2490 wxControl::OnPaint(rEvent);
2491
2492 //
2493 // Reset the device origin since it may have been set
2494 //
2495 vDc.SetDeviceOrigin(0, 0);
2496 if (!bDrawHRules && !bDrawVRules)
2497 return;
2498 if ((GetWindowStyle() & wxLC_REPORT) == 0)
2499 return;
2500 vDc.SetPen(vPen);
2501 vDc.SetBrush(*wxTRANSPARENT_BRUSH);
2502
2503 if (bDrawHRules)
2504 {
2505 long lTop = GetTopItem();
2506
2507 for (i = lTop; i < lTop + GetCountPerPage() + 1; i++)
2508 {
2509 if (GetItemRect( i
2510 ,vItemRect
2511 ))
2512 {
2513 nCy = vItemRect.GetTop();
2514 if (i != 0) // Don't draw the first one
2515 {
2516 vDc.DrawLine( 0
2517 ,nCy
2518 ,vClientSize.x
2519 ,nCy
2520 );
2521 }
2522 // Draw last line
2523 if (i == nItemCount - 1)
2524 {
2525 nCy = vItemRect.GetBottom();
2526 vDc.DrawLine( 0
2527 ,nCy
2528 ,vClientSize.x
2529 ,nCy
2530 );
2531 }
2532 }
2533 }
2534 }
2535 i = nItemCount - 1;
2536 if (bDrawVRules && (i > -1))
2537 {
2538 wxRect vFirstItemRect;
2539
2540 GetItemRect( 0
2541 ,vFirstItemRect
2542 );
2543 if (GetItemRect( i
2544 ,vItemRect
2545 ))
2546 {
2547 int nCol;
2548 int nX = vItemRect.GetX();
2549
2550 for (nCol = 0; nCol < GetColumnCount(); nCol++)
2551 {
2552 int nColWidth = GetColumnWidth(nCol);
2553
2554 nX += nColWidth ;
2555 vDc.DrawLine( nX - 1
2556 ,vFirstItemRect.GetY() - 2
2557 ,nX - 1
2558 ,vItemRect.GetBottom()
2559 );
2560 }
2561 }
2562 }
2563 } // end of wxListCtrl::OnPaint
2564
2565 // ----------------------------------------------------------------------------
2566 // virtual list controls
2567 // ----------------------------------------------------------------------------
2568
2569 wxString wxListCtrl::OnGetItemText (
2570 long WXUNUSED(lItem)
2571 , long WXUNUSED(lCol)
2572 ) const
2573 {
2574 // this is a pure virtual function, in fact - which is not really pure
2575 // because the controls which are not virtual don't need to implement it
2576 wxFAIL_MSG( _T("not supposed to be called") );
2577 return wxEmptyString;
2578 } // end of wxListCtrl::OnGetItemText
2579
2580 int wxListCtrl::OnGetItemImage (
2581 long WXUNUSED(lItem)
2582 ) const
2583 {
2584 // same as above
2585 wxFAIL_MSG( _T("not supposed to be called") );
2586 return -1;
2587 } // end of wxListCtrl::OnGetItemImage
2588
2589 int wxListCtrl::OnGetItemColumnImage (
2590 long lItem,
2591 long lColumn
2592 ) const
2593 {
2594 if (!lColumn)
2595 return OnGetItemImage(lItem);
2596
2597 return -1;
2598 } // end of wxListCtrl::OnGetItemColumnImage
2599
2600 wxListItemAttr* wxListCtrl::OnGetItemAttr (
2601 long WXUNUSED_UNLESS_DEBUG(lItem)
2602 ) const
2603 {
2604 wxASSERT_MSG( lItem >= 0 && lItem < GetItemCount(),
2605 _T("invalid item index in OnGetItemAttr()") );
2606
2607 //
2608 // No attributes by default
2609 //
2610 return NULL;
2611 } // end of wxListCtrl::OnGetItemAttr
2612
2613 void wxListCtrl::SetItemCount (
2614 long lCount
2615 )
2616 {
2617 wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
2618
2619 //
2620 // Cannot explicitly set the record count in OS/2
2621 //
2622 } // end of wxListCtrl::SetItemCount
2623
2624 void wxListCtrl::RefreshItem (
2625 long lItem
2626 )
2627 {
2628 wxRect vRect;
2629
2630 GetItemRect( lItem
2631 ,vRect
2632 );
2633 RefreshRect(vRect);
2634 } // end of wxListCtrl::RefreshItem
2635
2636 void wxListCtrl::RefreshItems ( long lItemFrom, long lItemTo )
2637 {
2638 wxRect vRect1;
2639 wxRect vRect2;
2640
2641 GetItemRect( lItemFrom , vRect1 );
2642 GetItemRect( lItemTo , vRect2 );
2643
2644 wxRect vRect = vRect1;
2645
2646 vRect.height = vRect2.GetBottom() - vRect1.GetTop();
2647 RefreshRect(vRect);
2648 } // end of wxListCtrl::RefreshItems
2649
2650 MRESULT wxListCtrl::OS2WindowProc( WXUINT uMsg,
2651 WXWPARAM wParam,
2652 WXLPARAM lParam )
2653 {
2654 bool bProcessed = false;
2655 MRESULT lRc;
2656 wxListEvent vEvent( wxEVT_NULL
2657 ,m_windowId
2658 );
2659 wxEventType vEventType = wxEVT_NULL;
2660 PCNRDRAGINIT pDragInit = NULL;
2661 PCNREDITDATA pEditData = NULL;
2662 PNOTIFYRECORDENTER pNotifyEnter = NULL;
2663
2664 vEvent.SetEventObject(this);
2665 switch (uMsg)
2666 {
2667 case WM_CONTROL:
2668 //
2669 // First off let's set some internal data
2670 //
2671 switch(SHORT2FROMMP(wParam))
2672 {
2673 case CN_INITDRAG:
2674 case CN_DRAGOVER:
2675 case CN_DRAGAFTER:
2676 {
2677 CListItemInternalData* pInternaldata = (CListItemInternalData *)lParam;
2678
2679 if (pInternaldata)
2680 {
2681 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2682
2683 pItem->SetData((long)pInternaldata->m_lParam);
2684 }
2685 }
2686 break;
2687 }
2688 //
2689 // Now let's go through the codes we're interested in
2690 //
2691 switch(SHORT2FROMMP(wParam))
2692 {
2693 case CN_INITDRAG:
2694 pDragInit = (PCNRDRAGINIT)lParam;
2695 if (pDragInit)
2696 {
2697 PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
2698
2699 vEventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
2700 vEvent.m_itemIndex = pRecord->m_ulItemId;
2701 vEvent.m_pointDrag.x = pDragInit->x;
2702 vEvent.m_pointDrag.y = pDragInit->y;
2703 }
2704 break;
2705
2706 case CN_BEGINEDIT:
2707 pEditData = (PCNREDITDATA)lParam;
2708 if (pEditData)
2709 {
2710 vEventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
2711 ConvertFromOS2ListItem( GetHWND()
2712 ,(wxListItem &)vEvent.GetItem()
2713 ,(PMYRECORD)pEditData->pRecord
2714 );
2715 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2716 }
2717 break;
2718
2719 case CN_ENDEDIT:
2720 pEditData = (PCNREDITDATA)lParam;
2721 if (pEditData)
2722 {
2723 vEventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
2724 ConvertFromOS2ListItem( GetHWND()
2725 ,(wxListItem &)vEvent.GetItem()
2726 ,(PMYRECORD)pEditData->pRecord
2727 );
2728 if (pEditData->cbText == 0)
2729 return (MRESULT)FALSE;
2730 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2731 }
2732 break;
2733
2734 case CN_ENTER:
2735 pNotifyEnter = (PNOTIFYRECORDENTER)lParam;
2736 if (pNotifyEnter)
2737 {
2738 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2739 PMYRECORD pMyRecord = (PMYRECORD)pNotifyEnter->pRecord;
2740
2741 vEventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
2742 vEvent.m_itemIndex = pMyRecord->m_ulItemId;
2743 pItem->SetText(GetItemText(pMyRecord->m_ulItemId));
2744 pItem->SetData(GetItemData(pMyRecord->m_ulItemId));
2745 }
2746 break;
2747
2748 //
2749 // Add the CN_DROP messages for Direct Manipulation
2750 //
2751 }
2752 vEvent.SetEventType(vEventType);
2753 bProcessed = HandleWindowEvent(vEvent);
2754 break;
2755 }
2756 if (!bProcessed)
2757 lRc = wxControl::OS2WindowProc( uMsg
2758 ,wParam
2759 ,lParam
2760 );
2761 return lRc;
2762 } // end of wxListCtrl::WindowProc
2763
2764 #endif // wxUSE_LISTCTRL