1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/listbox.cpp 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17 #include "wx/listbox.h" 
  20     #include "wx/dynarray.h" 
  21     #include "wx/settings.h" 
  25     #include "wx/dcscreen.h" 
  27     #include "wx/scrolwin.h" 
  29     #include "wx/window.h" 
  32 #include "wx/os2/dcclient.h" 
  33 #include "wx/os2/private.h" 
  39     #include  "wx/ownerdrw.h" 
  42 // ============================================================================ 
  43 // list box item declaration and implementation 
  44 // ============================================================================ 
  48 class wxListBoxItem 
: public wxOwnerDrawn
 
  51     wxListBoxItem(wxListBox 
*parent
) 
  52         { m_parent 
= parent
; } 
  54     wxListBox 
*GetParent() const 
  58         { return m_parent
->GetItemIndex(const_cast<wxListBoxItem
*>(this)); } 
  60     wxString 
GetName() const 
  61         { return m_parent
->GetString(GetIndex()); } 
  67 wxOwnerDrawn
* wxListBox::CreateItem( size_t WXUNUSED(n
) ) 
  69     return new wxListBoxItem(this); 
  70 } // end of wxListBox::CreateItem 
  72 #endif  //USE_OWNER_DRAWN 
  74 // ============================================================================ 
  75 // list box control implementation 
  76 // ============================================================================ 
  79 wxListBox::wxListBox() 
  83 } // end of wxListBox::wxListBox 
  85 bool wxListBox::Create( 
  90 , const wxArrayString
&              asChoices
 
  92 , const wxValidator
&                rValidator
 
  93 , const wxString
&                   rsName
 
  96     wxCArrayString 
chs(asChoices
); 
  98     return Create(pParent
, vId
, rPos
, rSize
, chs
.GetCount(), chs
.GetStrings(), 
  99                   lStyle
, rValidator
, rsName
); 
 102 bool wxListBox::Create( wxWindow
* pParent
, 
 107                         const wxString asChoices
[], 
 109                         const wxValidator
& rValidator
, 
 110                         const wxString
& rsName 
) 
 118     SetValidator(rValidator
); 
 122         pParent
->AddChild(this); 
 124     wxSystemSettings                vSettings
; 
 126     SetBackgroundColour(vSettings
.GetColour(wxSYS_COLOUR_WINDOW
)); 
 127     SetForegroundColour(pParent
->GetForegroundColour()); 
 129     m_windowId 
= (vId 
== -1) ? (int)NewControlId() : vId
; 
 133     int                             nWidth  
= rSize
.x
; 
 134     int                             nHeight 
= rSize
.y
; 
 136     m_windowStyle 
= lStyle
; 
 140     if (m_windowStyle 
& wxCLIP_SIBLINGS 
) 
 141         lStyle 
|= WS_CLIPSIBLINGS
; 
 142     if (m_windowStyle 
& wxLB_MULTIPLE
) 
 143         lStyle 
|= LS_MULTIPLESEL
; 
 144     else if (m_windowStyle 
& wxLB_EXTENDED
) 
 145         lStyle 
|= LS_EXTENDEDSEL
; 
 146     if (m_windowStyle 
& wxLB_HSCROLL
) 
 147         lStyle 
|= LS_HORZSCROLL
; 
 148     if (m_windowStyle 
& wxLB_OWNERDRAW
) 
 149         lStyle 
|= LS_OWNERDRAW
; 
 152     // Without this style, you get unexpected heights, so e.g. constraint layout 
 153     // doesn't work properly 
 155     lStyle 
|= LS_NOADJUSTPOS
; 
 157     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetWinHwnd(pParent
) // Parent 
 158                                        ,WC_LISTBOX          
// Default Listbox class 
 159                                        ,"LISTBOX"           // Control's name 
 160                                        ,lStyle              
// Initial Style 
 161                                        ,0, 0, 0, 0          // Position and size 
 162                                        ,GetWinHwnd(pParent
) // Owner 
 164                                        ,(HMENU
)m_windowId   
// Id 
 165                                        ,NULL                
// Control Data 
 166                                        ,NULL                
// Presentation Parameters 
 174     // Subclass again for purposes of dialog editing mode 
 180     for (lUi 
= 0; lUi 
< (LONG
)n
; lUi
++) 
 182         Append(asChoices
[lUi
]); 
 184     wxFont
*                          pTextFont 
= new wxFont( 10 
 192     // Set OS/2 system colours for Listbox items and highlighting 
 196     vColour 
= wxSystemSettingsNative::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
 198     LONG                            lColor 
= (LONG
)vColour
.GetPixel(); 
 200     ::WinSetPresParam( m_hWnd
 
 201                       ,PP_HILITEFOREGROUNDCOLOR
 
 205     vColour 
= wxSystemSettingsNative::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
 206     lColor 
= (LONG
)vColour
.GetPixel(); 
 207     ::WinSetPresParam( m_hWnd
 
 208                       ,PP_HILITEBACKGROUNDCOLOR
 
 222 } // end of wxListBox::Create 
 224 wxListBox::~wxListBox() 
 227 } // end of wxListBox::~wxListBox 
 229 void wxListBox::SetupColours() 
 231     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
 232     SetForegroundColour(GetParent()->GetForegroundColour()); 
 233 } // end of wxListBox::SetupColours 
 235 // ---------------------------------------------------------------------------- 
 236 // implementation of wxListBoxBase methods 
 237 // ---------------------------------------------------------------------------- 
 239 void wxListBox::DoSetFirstItem(int N
) 
 241     wxCHECK_RET( IsValid(N
), 
 242                  wxT("invalid index in wxListBox::SetFirstItem") ); 
 244     ::WinSendMsg(GetHwnd(), LM_SETTOPINDEX
, MPFROMLONG(N
), (MPARAM
)0); 
 245 } // end of wxListBox::DoSetFirstItem 
 247 void wxListBox::DoDeleteOneItem(unsigned int n
) 
 249     wxCHECK_RET( IsValid(n
), 
 250                  wxT("invalid index in wxListBox::Delete") ); 
 252 #if wxUSE_OWNER_DRAWN 
 254     m_aItems
.RemoveAt(n
); 
 255 #endif // wxUSE_OWNER_DRAWN 
 257     ::WinSendMsg(GetHwnd(), LM_DELETEITEM
, (MPARAM
)n
, (MPARAM
)0); 
 259 } // end of wxListBox::DoSetFirstItem 
 261 int wxListBox::DoInsertItems(const wxArrayStringsAdapter 
& items
, 
 264                              wxClientDataType type
) 
 268     bool incrementPos 
= false; 
 271         lIndexType 
= LIT_SORTASCENDING
; 
 272     else if (pos 
== GetCount()) 
 273         lIndexType 
= LIT_END
; 
 276         lIndexType 
= (LONG
)pos
; 
 282     unsigned int count 
= items
.GetCount(); 
 283     for (unsigned int i 
= 0; i 
< count
; i
++) 
 285         n 
= (int)::WinSendMsg(GetHwnd(), LM_INSERTITEM
, (MPARAM
)lIndexType
, (MPARAM
)items
[i
].wx_str()); 
 288             wxLogLastError(wxT("WinSendMsg(LM_INSERTITEM)")); 
 294 #if wxUSE_OWNER_DRAWN 
 295         if (HasFlag(wxLB_OWNERDRAW
)) 
 297             wxOwnerDrawn
* pNewItem 
= CreateItem(n
); // dummy argument 
 298             pNewItem
->SetFont(GetFont()); 
 299             m_aItems
.Insert(pNewItem
, n
); 
 302         AssignNewItemClientData(n
, clientData
, i
, type
); 
 309 } // end of wxListBox::DoInsertAppendItemsWithData 
 311 void wxListBox::DoClear() 
 313 #if wxUSE_OWNER_DRAWN 
 314     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 316         WX_CLEAR_ARRAY(m_aItems
); 
 318 #endif // wxUSE_OWNER_DRAWN 
 319     ::WinSendMsg(GetHwnd(), LM_DELETEALL
, (MPARAM
)0, (MPARAM
)0); 
 322 } // end of wxListBox::Clear 
 324 void wxListBox::DoSetSelection( int N
, bool bSelect
) 
 326     wxCHECK_RET( IsValid(N
), 
 327                  wxT("invalid index in wxListBox::SetSelection") ); 
 328     ::WinSendMsg( GetHwnd() 
 333     if(m_windowStyle 
& wxLB_OWNERDRAW
) 
 335 } // end of wxListBox::SetSelection 
 337 bool wxListBox::IsSelected( int N 
) const 
 339     wxCHECK_MSG( IsValid(N
), false, 
 340                  wxT("invalid index in wxListBox::Selected") ); 
 344     if (GetWindowStyleFlag() & wxLB_EXTENDED
) 
 347             lItem 
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)LIT_FIRST
, (MPARAM
)0)); 
 349             lItem 
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)(N 
- 1), (MPARAM
)0)); 
 353         lItem 
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)LIT_FIRST
, (MPARAM
)0)); 
 355     return (lItem 
== (LONG
)N 
&& lItem 
!= LIT_NONE
); 
 356 } // end of wxListBox::IsSelected 
 358 void* wxListBox::DoGetItemClientData(unsigned int n
) const 
 360     wxCHECK_MSG( IsValid(n
), NULL
, 
 361                  wxT("invalid index in wxListBox::GetClientData") ); 
 363     return((void *)::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE
, MPFROMLONG(n
), (MPARAM
)0)); 
 364 } // end of wxListBox::DoGetItemClientData 
 366 void wxListBox::DoSetItemClientData(unsigned int n
, void* pClientData
) 
 368     wxCHECK_RET( IsValid(n
), 
 369                  wxT("invalid index in wxListBox::SetClientData") ); 
 371     ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE
, MPFROMLONG(n
), MPFROMP(pClientData
)); 
 372 } // end of wxListBox::DoSetItemClientData 
 374 bool wxListBox::HasMultipleSelection() const 
 376     return (m_windowStyle 
& wxLB_MULTIPLE
) || (m_windowStyle 
& wxLB_EXTENDED
); 
 377 } // end of wxListBox::HasMultipleSelection 
 379 int wxListBox::GetSelections( wxArrayInt
& raSelections 
) const 
 385     raSelections
.Empty(); 
 386     if (HasMultipleSelection()) 
 388         lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 394         if (lItem 
!= LIT_NONE
) 
 397             while ((lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 406             raSelections
.Alloc(nCount
); 
 407             lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 414             raSelections
.Add((int)lItem
); 
 415             while ((lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 422                 raSelections
.Add((int)lItem
); 
 427     else  // single-selection listbox 
 429         lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 435         raSelections
.Add((int)lItem
); 
 439 } // end of wxListBox::GetSelections 
 441 int wxListBox::GetSelection() const 
 443     wxCHECK_MSG( !HasMultipleSelection(), 
 445                  wxT("GetSelection() can't be used with multiple-selection " 
 446                     "listboxes, use GetSelections() instead.") ); 
 448     return(LONGFROMMR(::WinSendMsg( GetHwnd() 
 454 } // end of wxListBox::GetSelection 
 456 wxString 
wxListBox::GetString(unsigned int n
) const 
 462     wxCHECK_MSG( IsValid(n
), wxEmptyString
, 
 463                  wxT("invalid index in wxListBox::GetClientData") ); 
 465     lLen 
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH
, (MPARAM
)n
, (MPARAM
)0)); 
 466     zBuf 
= new wxChar
[lLen 
+ 1]; 
 467     ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT
, MPFROM2SHORT((SHORT
)n
, (SHORT
)lLen
), (MPARAM
)zBuf
); 
 472 } // end of wxListBox::GetString 
 474 void wxListBox::SetString(unsigned int n
, const wxString
& rsString
) 
 476     wxCHECK_RET( IsValid(n
), 
 477                  wxT("invalid index in wxListBox::SetString") ); 
 480     // Remember the state of the item 
 482     bool           bWasSelected 
= IsSelected(n
); 
 483     void*          pOldData 
= NULL
; 
 484     wxClientData
*  pOldObjData 
= NULL
; 
 486     if ( HasClientUntypedData() ) 
 487         pOldData 
= GetClientData(n
); 
 488     else if ( HasClientObjectData() ) 
 489         pOldObjData 
= GetClientObject(n
); 
 492     // Delete and recreate it 
 494     ::WinSendMsg( GetHwnd() 
 502     if (n 
== (m_nNumItems 
- 1)) 
 505     ::WinSendMsg( GetHwnd() 
 508                  ,(MPARAM
)rsString
.wx_str() 
 512     // Restore the client data 
 515         SetClientData(n
, pOldData
); 
 516     else if (pOldObjData
) 
 517         SetClientObject(n
, pOldObjData
); 
 520     // We may have lost the selection 
 524 } // end of wxListBox::SetString 
 526 unsigned int wxListBox::GetCount() const 
 531 // ---------------------------------------------------------------------------- 
 533 // ---------------------------------------------------------------------------- 
 535 wxSize 
wxListBox::DoGetBestSize() const 
 538     // Find the widest string 
 544     wxFont     vFont 
= (wxFont
)GetFont(); 
 546     for (unsigned int i 
= 0; i 
< m_nNumItems
; i
++) 
 548         wxString 
vStr(GetString(i
)); 
 550         GetTextExtent( vStr
, &nLine
, NULL 
); 
 551         if (nLine 
> nListbox
) 
 556     // Give it some reasonable default value if there are no strings in the 
 563     // The listbox should be slightly larger than the widest string 
 565     wxGetCharSize( GetHWND() 
 572     int hListbox 
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy
) * (wxMax(m_nNumItems
, 7)); 
 574     return wxSize( nListbox
 
 577 } // end of wxListBox::DoGetBestSize 
 579 // ---------------------------------------------------------------------------- 
 581 // ---------------------------------------------------------------------------- 
 583 bool wxListBox::OS2Command( 
 585 , WXWORD                            
WXUNUSED(wId
)) 
 587     wxEventType                     eEvtType
; 
 589     if (uParam 
== LN_SELECT
) 
 591         eEvtType 
= wxEVT_COMMAND_LISTBOX_SELECTED
; 
 593     else if (uParam 
== LN_ENTER
) 
 595         eEvtType 
= wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
; 
 600         // Some event we're not interested in 
 604     wxCommandEvent                  
vEvent( eEvtType
 
 608     vEvent
.SetEventObject(this); 
 610     wxArrayInt aSelections
; 
 612     int        nCount 
= GetSelections(aSelections
); 
 617         if (HasClientObjectData()) 
 618             vEvent
.SetClientObject(GetClientObject(n
)); 
 619         else if ( HasClientUntypedData() ) 
 620             vEvent
.SetClientData(GetClientData(n
)); 
 621         vEvent
.SetString(GetString(n
)); 
 628     return HandleWindowEvent(vEvent
); 
 629 } // end of wxListBox::OS2Command 
 631 // ---------------------------------------------------------------------------- 
 632 // wxCheckListBox support 
 633 // ---------------------------------------------------------------------------- 
 635 #if wxUSE_OWNER_DRAWN 
 641 #define OWNER_DRAWN_LISTBOX_EXTRA_SPACE    (1) 
 643 long wxListBox::OS2OnMeasure(WXMEASUREITEMSTRUCT
* pItem
) 
 646         pItem 
= (WXMEASUREITEMSTRUCT
*)new OWNERITEM
; 
 648     POWNERITEM                      pMeasureStruct 
= (POWNERITEM
)pItem
; 
 652     // Only owner-drawn control should receive this message 
 654     wxCHECK( ((m_windowStyle 
& wxLB_OWNERDRAW
) == wxLB_OWNERDRAW
), FALSE 
); 
 656     vDc
.SetFont(GetFont()); 
 665     pMeasureStruct
->rclItem
.xRight 
= (USHORT
)vWidth
; 
 666     pMeasureStruct
->rclItem
.xLeft  
= 0; 
 667     pMeasureStruct
->rclItem
.yTop   
= 0; 
 668     pMeasureStruct
->rclItem
.yBottom 
= 0; 
 670     vHeight 
= (wxCoord
)(vDc
.GetCharHeight() * 2.5); 
 671     pMeasureStruct
->rclItem
.yTop  
= (USHORT
)vHeight
; 
 673     return long(MRFROM2SHORT((USHORT
)vHeight
, (USHORT
)vWidth
)); 
 674 } // end of wxListBox::OS2OnMeasure 
 676 bool wxListBox::OS2OnDraw ( 
 677   WXDRAWITEMSTRUCT
*                 pItem
 
 680     POWNERITEM                      pDrawStruct 
= (POWNERITEM
)pItem
; 
 685     // Only owner-drawn control should receive this message 
 687     wxCHECK(((m_windowStyle 
& wxLB_OWNERDRAW
) == wxLB_OWNERDRAW
), false); 
 691     // The item may be -1 for an empty listbox 
 693     if (pDrawStruct
->idItem 
== -1L) 
 696     wxListBoxItem
* pData 
= (wxListBoxItem
*)m_aItems
[pDrawStruct
->idItem
]; 
 698     wxClientDC    
vDc(this); 
 699     wxPMDCImpl 
*impl 
= (wxPMDCImpl
*) vDc
.GetImpl(); 
 700     wxPoint 
pt1( pDrawStruct
->rclItem
.xLeft
, pDrawStruct
->rclItem
.yTop 
); 
 701     wxPoint 
pt2( pDrawStruct
->rclItem
.xRight
, pDrawStruct
->rclItem
.yBottom 
); 
 702     wxRect  
vRect( pt1
, pt2 
); 
 704     impl
->SetHPS(pDrawStruct
->hps
); 
 706     if (pDrawStruct
->fsAttribute 
== pDrawStruct
->fsAttributeOld
) 
 709         // Entire Item needs to be redrawn (either it has reappeared from 
 710         // behind another window or is being displayed for the first time 
 712         eAction 
= wxOwnerDrawn::wxODDrawAll
; 
 714         if (pDrawStruct
->fsAttribute 
& MIA_HILITED
) 
 717             // If it is currently selected we let the system handle it 
 719             eStatus 
|= wxOwnerDrawn::wxODSelected
; 
 721         if (pDrawStruct
->fsAttribute 
& MIA_CHECKED
) 
 724             // If it is currently checked we draw our own 
 726             eStatus 
|= wxOwnerDrawn::wxODChecked
; 
 727             pDrawStruct
->fsAttributeOld 
= pDrawStruct
->fsAttribute 
&= ~MIA_CHECKED
; 
 729         if (pDrawStruct
->fsAttribute 
& MIA_DISABLED
) 
 732             // If it is currently disabled we let the system handle it 
 734             eStatus 
|= wxOwnerDrawn::wxODDisabled
; 
 737         // Don't really care about framed (indicationg focus) or NoDismiss 
 742         if (pDrawStruct
->fsAttribute 
& MIA_HILITED
) 
 744             eAction 
= wxOwnerDrawn::wxODDrawAll
; 
 745             eStatus 
|= wxOwnerDrawn::wxODSelected
; 
 747             // Keep the system from trying to highlight with its bogus colors 
 749             pDrawStruct
->fsAttributeOld 
= pDrawStruct
->fsAttribute 
&= ~MIA_HILITED
; 
 751         else if (!(pDrawStruct
->fsAttribute 
& MIA_HILITED
)) 
 753             eAction 
= wxOwnerDrawn::wxODDrawAll
; 
 756             // Keep the system from trying to highlight with its bogus colors 
 758             pDrawStruct
->fsAttribute 
= pDrawStruct
->fsAttributeOld 
&= ~MIA_HILITED
; 
 763             // For now we don't care about anything else 
 764             // just ignore the entire message! 
 769     return pData
->OnDrawItem( vDc
 
 771                              ,(wxOwnerDrawn::wxODAction
)eAction
 
 772                              ,(wxOwnerDrawn::wxODStatus
)(eStatus 
| wxOwnerDrawn::wxODHidePrefix
) 
 774 } // end of wxListBox::OS2OnDraw 
 776 #endif // ndef for wxUSE_OWNER_DRAWN 
 778 #endif // wxUSE_LISTBOX