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
);
363 // And just a bit more
364 int cx
= ::TextWidth( "X" , 0 , 1 ) ;
369 return wxSize( lbWidth
, lbHeight
);
372 #endif // wxUSE_CHOICE