1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/carbon/choice.cpp 
   4 // Author:      Stefan Csomor 
   8 // Copyright:   (c) Stefan Csomor 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #include "wx/wxprec.h" 
  16 #include "wx/choice.h" 
  20     #include "wx/dcclient.h" 
  23 #include "wx/mac/uma.h" 
  25 extern MenuHandle 
NewUniqueMenu() ; 
  27 IMPLEMENT_DYNAMIC_CLASS(wxChoice
, wxControl
) 
  32     if ( HasClientObjectData() ) 
  34         unsigned int i
, max 
= GetCount(); 
  36         for ( i 
= 0; i 
< max
; ++i 
) 
  37             delete GetClientObject( i 
); 
  40     // DeleteMenu( m_macPopUpMenuId ) ; 
  41     // DisposeMenu( m_macPopUpMenuHandle ) ; 
  44 bool wxChoice::Create(wxWindow 
*parent
, 
  48     const wxArrayString
& choices
, 
  50     const wxValidator
& validator
, 
  51     const wxString
& name 
) 
  53     wxCArrayString 
chs( choices 
); 
  56         parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(), 
  57         style
, validator
, name 
); 
  60 bool wxChoice::Create(wxWindow 
*parent
, 
  65     const wxString choices
[], 
  67     const wxValidator
& validator
, 
  68     const wxString
& name 
) 
  70     m_macIsUserPane 
= false; 
  72     if ( !wxChoiceBase::Create( parent
, id
, pos
, size
, style
, validator
, name 
) ) 
  75     Rect bounds 
= wxMacGetBoundsForControl( this , pos 
, size 
); 
  77     m_peer 
= new wxMacControl( this ) ; 
  78     OSStatus err 
= CreatePopupButtonControl( 
  79         MAC_WXHWND(parent
->MacGetTopLevelWindowRef()) , &bounds 
, CFSTR("") , 
  80         -12345 , false /* no variable width */ , 0 , 0 , 0 , m_peer
->GetControlRefAddr() ); 
  83     m_macPopUpMenuHandle 
= NewUniqueMenu() ; 
  84     m_peer
->SetData
<MenuHandle
>( kControlNoPart 
, kControlPopupButtonMenuHandleTag 
, (MenuHandle
) m_macPopUpMenuHandle 
) ; 
  85     m_peer
->SetValueAndRange( n 
> 0 ? 1 : 0 , 0 , 0 ); 
  86     MacPostControlCreate( pos
, size 
); 
  89     if ( style 
& wxCB_SORT 
) 
  91         m_strings 
= wxArrayString( 1 ); 
  94     for ( int i 
= 0; i 
< n
; i
++ ) 
  99     // Set the first item as being selected 
 103     // Needed because it is a wxControlWithItems 
 104     SetInitialSize( size 
); 
 109 // ---------------------------------------------------------------------------- 
 110 // adding/deleting items to/from the list 
 111 // ---------------------------------------------------------------------------- 
 112 int wxChoice::DoAppend( const wxString
& item 
) 
 115     wxArrayString::iterator insertPoint
; 
 118     if (GetWindowStyle() & wxCB_SORT
) 
 120         insertPoint 
= std::lower_bound( m_strings
.begin(), m_strings
.end(), item 
); 
 121         index 
= insertPoint 
- m_strings
.begin(); 
 125         insertPoint 
= m_strings
.end(); 
 126         index 
= m_strings
.size(); 
 129     m_strings
.insert( insertPoint
, item 
); 
 131     unsigned int index 
= m_strings
.Add( item 
); 
 134     m_datas
.Insert( NULL 
, index 
); 
 135     UMAInsertMenuItem( MAC_WXHMENU( m_macPopUpMenuHandle 
), item
, m_font
.GetEncoding(), index 
); 
 136     DoSetItemClientData( index
, NULL 
); 
 137     m_peer
->SetMaximum( GetCount() ); 
 142 int wxChoice::DoInsert( const wxString
& item
, unsigned int pos 
) 
 144     wxCHECK_MSG( !(GetWindowStyle() & wxCB_SORT
), -1, wxT("wxChoice::DoInsert: can't insert into sorted list") ); 
 145     wxCHECK_MSG( IsValidInsert(pos
), -1, wxT("wxChoice::DoInsert: invalid index") ); 
 147     if (pos 
== GetCount()) 
 148         return DoAppend( item 
); 
 150     UMAInsertMenuItem( MAC_WXHMENU( m_macPopUpMenuHandle 
), item
, m_font
.GetEncoding(), pos 
); 
 151     m_strings
.Insert( item
, pos 
); 
 152     m_datas
.Insert( NULL
, pos 
); 
 153     DoSetItemClientData( pos
, NULL 
); 
 154     m_peer
->SetMaximum( GetCount() ); 
 159 void wxChoice::Delete(unsigned int n
) 
 161     wxCHECK_RET( IsValid(n
) , wxT("wxChoice::Delete: invalid index") ); 
 163     if ( HasClientObjectData() ) 
 164         delete GetClientObject( n 
); 
 166     ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle
) , n 
+ 1 ) ; 
 167     m_strings
.RemoveAt( n 
) ; 
 168     m_datas
.RemoveAt( n 
) ; 
 169     m_peer
->SetMaximum( GetCount() ) ; 
 172 void wxChoice::Clear() 
 175     for ( unsigned int i 
= 0 ; i 
< GetCount() ; i
++ ) 
 177         ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle
) , 1 ) ; 
 182     m_peer
->SetMaximum( 0 ) ; 
 185 void wxChoice::FreeData() 
 187     if ( HasClientObjectData() ) 
 189         unsigned int count 
= GetCount(); 
 190         for ( unsigned int n 
= 0; n 
< count
; n
++ ) 
 192             delete GetClientObject( n 
); 
 197 // ---------------------------------------------------------------------------- 
 199 // ---------------------------------------------------------------------------- 
 200 int wxChoice::GetSelection() const 
 202     return m_peer
->GetValue() - 1 ; 
 205 void wxChoice::SetSelection( int n 
) 
 207     m_peer
->SetValue( n 
+ 1 ) ; 
 210 // ---------------------------------------------------------------------------- 
 211 // string list functions 
 212 // ---------------------------------------------------------------------------- 
 214 unsigned int wxChoice::GetCount() const 
 216     return m_strings
.GetCount() ; 
 219 int wxChoice::FindString( const wxString
& s
, bool bCase 
) const 
 222     // Avoid assert for non-default args passed to sorted array Index 
 223     if ( HasFlag(wxCB_SORT
) ) 
 227     return m_strings
.Index( s 
, bCase 
) ; 
 230 void wxChoice::SetString(unsigned int n
, const wxString
& s
) 
 232     wxCHECK_RET( IsValid(n
), wxT("wxChoice::SetString(): invalid index") ); 
 236     // apple menu pos is 1-based 
 237     UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle
) , n 
+ 1 , s 
, wxFont::GetDefaultEncoding() ) ; 
 240 wxString 
wxChoice::GetString(unsigned int n
) const 
 242     wxCHECK_MSG( IsValid(n
), wxEmptyString
, wxT("wxChoice::GetString(): invalid index") ); 
 244     return m_strings
[n
] ; 
 247 // ---------------------------------------------------------------------------- 
 249 // ---------------------------------------------------------------------------- 
 250 void wxChoice::DoSetItemClientData(unsigned int n
, void* clientData
) 
 252     wxCHECK_RET( IsValid(n
), wxT("wxChoice::DoSetItemClientData: invalid index") ); 
 254     m_datas
[n
] = (char*)clientData 
; 
 257 void * wxChoice::DoGetItemClientData(unsigned int n
) const 
 259     wxCHECK_MSG( IsValid(n
), NULL
, wxT("wxChoice::DoGetClientData: invalid index") ); 
 261     return (void *)m_datas
[n
]; 
 264 void wxChoice::DoSetItemClientObject(unsigned int n
, wxClientData
* clientData
) 
 266     DoSetItemClientData(n
, clientData
); 
 269 wxClientData
* wxChoice::DoGetItemClientObject(unsigned int n
) const 
 271     return (wxClientData
*)DoGetItemClientData( n 
) ; 
 274 wxInt32 
wxChoice::MacControlHit( WXEVENTHANDLERREF 
WXUNUSED(handler
) , WXEVENTREF 
WXUNUSED(event
) ) 
 276     wxCommandEvent 
event( wxEVT_COMMAND_CHOICE_SELECTED
, m_windowId 
); 
 278     // actually n should be made sure by the os to be a valid selection, but ... 
 279     int n 
= GetSelection(); 
 283         event
.SetString( GetStringSelection() ); 
 284         event
.SetEventObject( this ); 
 286         if ( HasClientObjectData() ) 
 287             event
.SetClientObject( GetClientObject( n 
) ); 
 288         else if ( HasClientUntypedData() ) 
 289             event
.SetClientData( GetClientData( n 
) ); 
 291         ProcessCommand( event 
); 
 297 wxSize 
wxChoice::DoGetBestSize() const 
 299     int lbWidth 
= GetCount() > 0 ? 20 : 100;  // some defaults 
 306     GetThemeMetric( kThemeMetricPopupButtonHeight 
, &metric 
); 
 311 #if wxMAC_USE_CORE_GRAPHICS 
 312         wxClientDC 
dc(const_cast<wxChoice
*>(this)); 
 314         wxMacPortStateHelper 
st( UMAGetWindowPort( (WindowRef
) MacGetTopLevelWindowRef() ) ) ; 
 317             ::TextFont( m_font
.MacGetFontNum() ) ; 
 318             ::TextSize( m_font
.MacGetFontSize() ) ; 
 319             ::TextFace( m_font
.MacGetFontStyle() ) ; 
 323             ::TextFont( kFontIDMonaco 
) ; 
 328         // Find the widest line 
 329         for(unsigned int i 
= 0; i 
< GetCount(); i
++) 
 331             wxString 
str(GetString(i
)); 
 332 #if wxMAC_USE_CORE_GRAPHICS 
 333             wxCoord width
, height 
; 
 334             dc
.GetTextExtent( str 
, &width
, &height
); 
 338             Point bounds 
= { 0, 0 } ; 
 341             ::GetThemeTextDimensions( wxMacCFStringHolder( str 
, m_font
.GetEncoding() ) , 
 342                 kThemeCurrentPortFont
, 
 350             wLine 
= ::TextWidth( str
.c_str() , 0 , str
.length() ) ; 
 353             lbWidth 
= wxMax( lbWidth
, wLine 
) ; 
 356         // Add room for the popup arrow 
 357         lbWidth 
+= 2 * lbHeight 
; 
 358 #if wxMAC_USE_CORE_GRAPHICS 
 359         wxCoord width
, height 
; 
 360         dc
.GetTextExtent( wxT("X"), &width
, &height
); 
 364         // And just a bit more 
 365         int cx 
= ::TextWidth( "X" , 0 , 1 ) ; 
 370     return wxSize( lbWidth
, lbHeight 
); 
 373 #endif // wxUSE_CHOICE