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