1 /////////////////////////////////////////////////////////////////////////////// 
   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" 
  15 #include "wx/window.h" 
  16 #include "wx/os2/private.h" 
  19 #include "wx/listbox.h" 
  20 #include "wx/settings.h" 
  30 #include "wx/dynarray.h" 
  36     #include  "wx/ownerdrw.h" 
  39   IMPLEMENT_DYNAMIC_CLASS(wxListBox
, wxControl
) 
  41 // ============================================================================ 
  42 // list box item declaration and implementation 
  43 // ============================================================================ 
  47 class wxListBoxItem 
: public wxOwnerDrawn
 
  50     wxListBoxItem(const wxString
& rsStr 
= ""); 
  53 wxListBoxItem::wxListBoxItem( 
  61     // No bitmaps/checkmarks 
  64 } // end of wxListBoxItem::wxListBoxItem 
  66 wxOwnerDrawn
* wxListBox::CreateItem( 
  70     return new wxListBoxItem(); 
  71 } // end of wxListBox::CreateItem 
  73 #endif  //USE_OWNER_DRAWN 
  75 // ============================================================================ 
  76 // list box control implementation 
  77 // ============================================================================ 
  80 wxListBox::wxListBox() 
  84 } // end of wxListBox::wxListBox 
  86 bool wxListBox::Create( 
  92 , const wxString                    asChoices
[] 
  95 , const wxValidator
&                rValidator
 
  97 , const wxString
&                   rsName
 
 106     SetValidator(rValidator
); 
 110         pParent
->AddChild(this); 
 112     wxSystemSettings                vSettings
; 
 114     SetBackgroundColour(vSettings
.GetSystemColour(wxSYS_COLOUR_WINDOW
)); 
 115     SetForegroundColour(pParent
->GetForegroundColour()); 
 117     m_windowId 
= (vId 
== -1) ? (int)NewControlId() : vId
; 
 121     int                             nWidth  
= rSize
.x
; 
 122     int                             nHeight 
= rSize
.y
; 
 124     m_windowStyle 
= lStyle
; 
 128     if (m_windowStyle 
& wxCLIP_SIBLINGS 
) 
 129         lStyle 
|= WS_CLIPSIBLINGS
; 
 130     if (m_windowStyle 
& wxLB_MULTIPLE
) 
 131         lStyle 
|= LS_MULTIPLESEL
; 
 132     else if (m_windowStyle 
& wxLB_EXTENDED
) 
 133         lStyle 
|= LS_EXTENDEDSEL
; 
 134     if (m_windowStyle 
& wxLB_HSCROLL
) 
 135         lStyle 
|= LS_HORZSCROLL
; 
 136     if (m_windowStyle 
& wxLB_OWNERDRAW
) 
 137         lStyle 
|= LS_OWNERDRAW
; 
 140     // Without this style, you get unexpected heights, so e.g. constraint layout 
 141     // doesn't work properly 
 143     lStyle 
|= LS_NOADJUSTPOS
; 
 146     // If the parent is a scrolled window the controls must 
 147     // have this style or they will overlap the scrollbars 
 150         if (pParent
->IsKindOf(CLASSINFO(wxScrolledWindow
)) || 
 151             pParent
->IsKindOf(CLASSINFO(wxGenericScrolledWindow
))) 
 152             lStyle 
|= WS_CLIPSIBLINGS
; 
 154     m_hWnd 
= (WXHWND
)::WinCreateWindow( GetWinHwnd(pParent
) // Parent 
 155                                        ,WC_LISTBOX          
// Default Listbox class 
 156                                        ,"LISTBOX"           // Control's name 
 157                                        ,lStyle              
// Initial Style 
 158                                        ,0, 0, 0, 0          // Position and size 
 159                                        ,GetWinHwnd(pParent
) // Owner 
 161                                        ,(HMENU
)m_windowId   
// Id 
 162                                        ,NULL                
// Control Data 
 163                                        ,NULL                
// Presentation Parameters 
 171     // Subclass again for purposes of dialog editing mode 
 177     for (lUi 
= 0; lUi 
< (LONG
)n
; lUi
++) 
 179         Append(asChoices
[lUi
]); 
 181     SetFont(pParent
->GetFont()); 
 184     // Set standard wxWindows colors for Listbox items and highlighting 
 188     vColour
.Set(wxString("WHITE")); 
 190     LONG                            lColor 
= (LONG
)vColour
.GetPixel(); 
 192     ::WinSetPresParam( m_hWnd
 
 193                       ,PP_HILITEFOREGROUNDCOLOR
 
 197     vColour
.Set(wxString("NAVY")); 
 198     lColor 
= (LONG
)vColour
.GetPixel(); 
 199     ::WinSetPresParam( m_hWnd
 
 200                       ,PP_HILITEBACKGROUNDCOLOR
 
 211 } // end of wxListBox::Create 
 213 wxListBox::~wxListBox() 
 215 #if wxUSE_OWNER_DRAWN 
 216     size_t                          lUiCount 
= m_aItems
.Count(); 
 218     while (lUiCount
-- != 0) 
 220         delete m_aItems
[lUiCount
]; 
 222 #endif // wxUSE_OWNER_DRAWN 
 223 } // end of wxListBox::~wxListBox 
 225 void wxListBox::SetupColours() 
 227     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW
)); 
 228     SetForegroundColour(GetParent()->GetForegroundColour()); 
 229 } // end of wxListBox::SetupColours 
 231 // ---------------------------------------------------------------------------- 
 232 // implementation of wxListBoxBase methods 
 233 // ---------------------------------------------------------------------------- 
 235 void wxListBox::DoSetFirstItem( 
 239     wxCHECK_RET( N 
>= 0 && N 
< m_nNumItems
, 
 240                  wxT("invalid index in wxListBox::SetFirstItem") ); 
 242     ::WinSendMsg(GetHwnd(), LM_SETTOPINDEX
, MPFROMLONG(N
), (MPARAM
)0); 
 243 } // end of wxListBox::DoSetFirstItem 
 245 void wxListBox::Delete( 
 249     wxCHECK_RET( N 
>= 0 && N 
< m_nNumItems
, 
 250                  wxT("invalid index in wxListBox::Delete") ); 
 252 #if wxUSE_OWNER_DRAWN 
 254     m_aItems
.RemoveAt(N
); 
 255 #else // !wxUSE_OWNER_DRAWN 
 256     if (HasClientObjectData()) 
 258         delete GetClientObject(N
); 
 260 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
 262     ::WinSendMsg(GetHwnd(), LM_DELETEITEM
, (MPARAM
)N
, (MPARAM
)0); 
 264 } // end of wxListBox::DoSetFirstItem 
 266 int wxListBox::DoAppend( 
 267   const wxString
&                   rsItem
 
 271     SHORT                           nIndexType 
= 0; 
 273     if (m_windowStyle 
& wxLB_SORT
) 
 274         nIndexType 
= LIT_SORTASCENDING
; 
 276         nIndexType 
= LIT_END
; 
 277     nIndex 
= (int)::WinSendMsg(GetHwnd(), LM_INSERTITEM
, (MPARAM
)nIndexType
, (MPARAM
)rsItem
.c_str()); 
 280 #if wxUSE_OWNER_DRAWN 
 281     if (m_windowStyle 
& wxLB_OWNERDRAW
) 
 283         wxOwnerDrawn
*               pNewItem 
= CreateItem(nIndex
); // dummy argument 
 285         pNewItem
->SetName(rsItem
); 
 286         m_aItems
.Add(pNewItem
); 
 287         ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE
, (MPARAM
)((SHORT
)nIndex
), MPFROMP(pNewItem
)); 
 288         pNewItem
->SetFont(GetFont()); 
 292 } // end of wxListBox::DoAppend 
 294 void wxListBox::DoSetItems( 
 295   const wxArrayString
&              raChoices
 
 296 , void**                            ppClientData
 
 299     BOOL                            bHideAndShow 
= IsShown(); 
 302     SHORT                           nIndexType 
= 0; 
 306         ::WinShowWindow(GetHwnd(), FALSE
); 
 308     ::WinSendMsg(GetHwnd(), LM_DELETEALL
, (MPARAM
)0, (MPARAM
)0); 
 309     m_nNumItems 
= raChoices
.GetCount(); 
 310     for (i 
= 0; i 
< m_nNumItems
; i
++) 
 313         if (m_windowStyle 
& wxLB_SORT
) 
 314             nIndexType 
= LIT_SORTASCENDING
; 
 316             nIndexType 
= LIT_END
; 
 317         ::WinSendMsg(GetHwnd(), LM_INSERTITEM
, (MPARAM
)nIndexType
, (MPARAM
)raChoices
[i
].c_str()); 
 321 #if wxUSE_OWNER_DRAWN 
 322             wxASSERT_MSG(ppClientData
[i
] == NULL
, 
 323                          wxT("Can't use client data with owner-drawn listboxes")); 
 324 #else // !wxUSE_OWNER_DRAWN 
 325             ::WinSendMsg(WinUtil_GetHwnd(), LM_SETITEMHANDLE
, MPFROMLONG(lCount
), MPFROMP(ppClientData
[i
])); 
 326 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
 330 #if wxUSE_OWNER_DRAWN 
 331     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 334         // First delete old items 
 336         size_t                      lUi 
= m_aItems
.Count(); 
 340             delete m_aItems
[lUi
]; 
 345         // Then create new ones 
 347         for (lUi 
= 0; lUi 
< (size_t)m_nNumItems
; lUi
++) 
 349             wxOwnerDrawn
*           pNewItem 
= CreateItem(lUi
); 
 351             pNewItem
->SetName(raChoices
[lUi
]); 
 352             m_aItems
.Add(pNewItem
); 
 353             ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE
, MPFROMLONG(lUi
), MPFROMP(pNewItem
)); 
 356 #endif // wxUSE_OWNER_DRAWN 
 357     ::WinShowWindow(GetHwnd(), TRUE
); 
 358 } // end of wxListBox::DoSetItems 
 360 int wxListBox::FindString( 
 361   const wxString
&                   rsString
 
 369     for (nPos 
= 0; nPos 
< m_nNumItems
; nPos
++) 
 371         lTextLength 
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH
, (MPARAM
)nPos
, (MPARAM
)0)); 
 372         zStr 
= new char[lTextLength 
+ 1]; 
 373         ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT
, MPFROM2SHORT(nPos
, (SHORT
)lTextLength
), (MPARAM
)zStr
); 
 374         if (rsString 
== (char*)zStr
) 
 382 } // end of wxListBox::FindString 
 384 void wxListBox::Clear() 
 386 #if wxUSE_OWNER_DRAWN 
 387     size_t                          lUiCount 
= m_aItems
.Count(); 
 389     while (lUiCount
-- != 0) 
 391         delete m_aItems
[lUiCount
]; 
 395 #else // !wxUSE_OWNER_DRAWN 
 396     if (HasClientObjectData()) 
 398         for (size_t n 
= 0; n 
< (size_t)m_lNumItems
; n
++) 
 400             delete GetClientObject(n
); 
 403 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
 404     ::WinSendMsg(GetHwnd(), LM_DELETEALL
, (MPARAM
)0, (MPARAM
)0); 
 407 } // end of wxListBox::Clear 
 409 void wxListBox::SetSelection( 
 414     wxCHECK_RET( N 
>= 0 && N 
< m_nNumItems
, 
 415                  wxT("invalid index in wxListBox::SetSelection") ); 
 416     ::WinSendMsg( GetHwnd() 
 421 } // end of wxListBox::SetSelection 
 423 bool wxListBox::IsSelected( 
 427     wxCHECK_MSG( N 
>= 0 && N 
< m_nNumItems
, FALSE
, 
 428                  wxT("invalid index in wxListBox::Selected") ); 
 432     lItem 
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION
, (MPARAM
)N
, (MPARAM
)0)); 
 433     return (lItem 
!= LIT_NONE
); 
 434 } // end of wxListBox::IsSelected 
 436 wxClientData
* wxListBox::DoGetItemClientObject( 
 440     return (wxClientData 
*)DoGetItemClientData(n
); 
 443 void* wxListBox::DoGetItemClientData( 
 447     wxCHECK_MSG( n 
>= 0 && n 
< m_nNumItems
, NULL
, 
 448                  wxT("invalid index in wxListBox::GetClientData") ); 
 450     return((void *)::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE
, MPFROMLONG(n
), (MPARAM
)0)); 
 451 } // end of wxListBox::DoGetItemClientData 
 453 void wxListBox::DoSetItemClientObject( 
 455 , wxClientData
*                     pClientData
 
 458     DoSetItemClientData( n
 
 461 } // end of wxListBox::DoSetItemClientObject 
 463 void wxListBox::DoSetItemClientData( 
 468     wxCHECK_RET( n 
>= 0 && n 
< m_nNumItems
, 
 469                  wxT("invalid index in wxListBox::SetClientData") ); 
 471 #if wxUSE_OWNER_DRAWN 
 472     if ( m_windowStyle 
& wxLB_OWNERDRAW 
) 
 475         // Client data must be pointer to wxOwnerDrawn, otherwise we would crash 
 476         // in OnMeasure/OnDraw. 
 478         wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes")); 
 480 #endif // wxUSE_OWNER_DRAWN 
 482     ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE
, MPFROMLONG(n
), MPFROMP(pClientData
)); 
 483 } // end of wxListBox::DoSetItemClientData 
 485 bool wxListBox::HasMultipleSelection() const 
 487     return (m_windowStyle 
& wxLB_MULTIPLE
) || (m_windowStyle 
& wxLB_EXTENDED
); 
 488 } // end of wxListBox::HasMultipleSelection 
 490 int wxListBox::GetSelections( 
 491   wxArrayInt
&                       raSelections
 
 498     raSelections
.Empty(); 
 499     if (HasMultipleSelection()) 
 501         lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 507         if (lItem 
!= LIT_NONE
) 
 510             while ((lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 519             raSelections
.Alloc(nCount
); 
 520             lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 527             raSelections
.Add((int)lItem
); 
 528             while ((lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 535                 raSelections
.Add((int)lItem
); 
 541     else  // single-selection listbox 
 543         lItem 
= LONGFROMMR(::WinSendMsg( GetHwnd() 
 549         raSelections
.Add((int)lItem
); 
 553 } // end of wxListBox::GetSelections 
 555 int wxListBox::GetSelection() const 
 557     wxCHECK_MSG( !HasMultipleSelection(), 
 559                  wxT("GetSelection() can't be used with multiple-selection " 
 560                     "listboxes, use GetSelections() instead.") ); 
 562     return(LONGFROMMR(::WinSendMsg( GetHwnd() 
 568 } // end of wxListBox::GetSelection 
 570 wxString 
wxListBox::GetString( 
 578     wxCHECK_MSG( N 
>= 0 && N 
< m_nNumItems
, "", 
 579                  wxT("invalid index in wxListBox::GetClientData") ); 
 581     lLen 
= LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH
, (MPARAM
)N
, (MPARAM
)0)); 
 582     zBuf 
= new char[lLen 
+ 1]; 
 583     ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT
, MPFROM2SHORT((SHORT
)N
, (SHORT
)lLen
), (MPARAM
)zBuf
); 
 588 } // end of wxListBox::GetString 
 590 void wxListBox::DoInsertItems( 
 591   const wxArrayString
&              asItems
 
 595     wxCHECK_RET( nPos 
>= 0 && nPos 
<= m_nNumItems
, 
 596                  wxT("invalid index in wxListBox::InsertItems") ); 
 598     int                             nItems 
= asItems
.GetCount(); 
 600     for (int i 
= 0; i 
< nItems
; i
++) 
 601         ::WinSendMsg(GetHwnd(), LM_INSERTITEM
, MPFROMLONG((LONG
)(i 
+ nPos
)), (MPARAM
)asItems
[i
].c_str()); 
 602     m_nNumItems 
+= nItems
; 
 603 } // end of wxListBox::DoInsertItems 
 605 void wxListBox::SetString( 
 607 , const wxString
&                   rsString
 
 610     wxCHECK_RET( N 
>= 0 && N 
< m_nNumItems
, 
 611                  wxT("invalid index in wxListBox::SetString") ); 
 614     // Remember the state of the item 
 616     bool                            bWasSelected 
= IsSelected(N
); 
 617     void*                           pOldData 
= NULL
; 
 618     wxClientData
*                   pOldObjData 
= NULL
; 
 620     if (m_clientDataItemsType 
== wxClientData_Void
) 
 621         pOldData 
= GetClientData(N
); 
 622     else if (m_clientDataItemsType 
== wxClientData_Object
) 
 623         pOldObjData 
= GetClientObject(N
); 
 626     // Delete and recreate it 
 628     ::WinSendMsg( GetHwnd() 
 636     if (N 
== m_nNumItems 
- 1) 
 639     ::WinSendMsg( GetHwnd() 
 642                  ,(MPARAM
)rsString
.c_str() 
 646     // Restore the client data 
 652     else if (pOldObjData
) 
 658     // We may have lost the selection 
 663 #if wxUSE_OWNER_DRAWN 
 664     if (m_windowStyle 
& wxLB_OWNERDRAW
) 
 666         // Update item's text 
 668         m_aItems
[N
]->SetName(rsString
); 
 669 #endif  //USE_OWNER_DRAWN 
 670 } // end of wxListBox::SetString 
 672 int wxListBox::GetCount() const 
 677 // ---------------------------------------------------------------------------- 
 679 // ---------------------------------------------------------------------------- 
 681 wxSize 
wxListBox::DoGetBestSize() const 
 684     // Find the widest string 
 691     for (int i 
= 0; i 
< m_nNumItems
; i
++) 
 693         wxString                    
vStr(GetString(i
)); 
 699         if (nLine 
> nListbox
) 
 704     // Give it some reasonable default value if there are no strings in the 
 711     // The listbox should be slightly larger than the widest string 
 713     wxGetCharSize( GetHWND() 
 720     int                             hListbox 
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy
) * (wxMax(m_nNumItems
, 7)); 
 722     return wxSize( nListbox
 
 725 } // end of wxListBox::DoGetBestSize 
 727 // ---------------------------------------------------------------------------- 
 729 // ---------------------------------------------------------------------------- 
 731 bool wxListBox::OS2Command( 
 733 , WXWORD                            
WXUNUSED(wId
)) 
 735     wxEventType                     eEvtType
; 
 737     if (uParam 
== LN_SELECT
) 
 739         eEvtType 
= wxEVT_COMMAND_LISTBOX_SELECTED
; 
 741     if (uParam 
== LN_ENTER
) 
 743         eEvtType 
= wxEVT_COMMAND_LISTBOX_DOUBLECLICKED
; 
 748         // Some event we're not interested in 
 752     wxCommandEvent                  
vEvent( eEvtType
 
 756     vEvent
.SetEventObject(this); 
 758     wxArrayInt                      aSelections
; 
 760     int                             nCount 
= GetSelections(aSelections
); 
 765         if (HasClientObjectData()) 
 766             vEvent
.SetClientObject(GetClientObject(n
)); 
 767         else if ( HasClientUntypedData() ) 
 768             vEvent
.SetClientData(GetClientData(n
)); 
 769         vEvent
.SetString(GetString(n
)); 
 775     vEvent
.m_commandInt 
= n
; 
 776     return GetEventHandler()->ProcessEvent(vEvent
); 
 777 } // end of wxListBox::OS2Command 
 779 // ---------------------------------------------------------------------------- 
 780 // wxCheckListBox support 
 781 // ---------------------------------------------------------------------------- 
 783 #if wxUSE_OWNER_DRAWN 
 789 #define OWNER_DRAWN_LISTBOX_EXTRA_SPACE    (1) 
 791 bool wxListBox::OS2OnMeasure(WXMEASUREITEMSTRUCT 
*item
) 
 794     // TODO: Get to this eventually 
 799 bool wxListBox::OS2OnDraw(WXDRAWITEMSTRUCT 
*item
) 
 802     // TODO: Get to this eventually 
 806 #endif // ndef for wxUSE_OWNER_DRAWN 
 808 #endif // ndef for wxUSE_LISTBOX