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"
18 #include "wx/mac/uma.h"
20 IMPLEMENT_DYNAMIC_CLASS(wxChoice
, wxControl
)
22 extern MenuHandle
NewUniqueMenu() ;
26 if ( HasClientObjectData() )
28 size_t i
, max
= GetCount();
30 for ( i
= 0; i
< max
; ++i
)
31 delete GetClientObject(i
);
34 // DeleteMenu( m_macPopUpMenuId ) ;
35 // DisposeMenu( m_macPopUpMenuHandle ) ;
38 bool wxChoice::Create(wxWindow
*parent
, wxWindowID id
,
41 const wxArrayString
& choices
,
43 const wxValidator
& validator
,
46 wxCArrayString
chs(choices
);
48 return Create(parent
, id
, pos
, size
, chs
.GetCount(), chs
.GetStrings(),
49 style
, validator
, name
);
52 bool wxChoice::Create(wxWindow
*parent
, wxWindowID id
,
55 int n
, const wxString choices
[],
57 const wxValidator
& validator
,
60 m_macIsUserPane
= false ;
62 if ( !wxChoiceBase::Create(parent
, id
, pos
, size
, style
, validator
, name
) )
65 Rect bounds
= wxMacGetBoundsForControl( this , pos
, size
) ;
67 m_peer
= new wxMacControl(this) ;
68 verify_noerr ( CreatePopupButtonControl( MAC_WXHWND(parent
->MacGetTopLevelWindowRef()) , &bounds
, CFSTR("") ,
69 -12345 , false /* no variable width */ , 0 , 0 , 0 , m_peer
->GetControlRefAddr() ) );
72 m_macPopUpMenuHandle
= NewUniqueMenu() ;
73 m_peer
->SetData
<MenuHandle
>( kControlNoPart
, kControlPopupButtonMenuHandleTag
, (MenuHandle
) m_macPopUpMenuHandle
) ;
74 m_peer
->SetValueAndRange( n
> 0 ? 1 : 0 , 0 , 0 ) ;
75 MacPostControlCreate(pos
,size
) ;
78 if ( style
& wxCB_SORT
)
80 m_strings
= wxArrayString(1) ; // autosort
84 for ( int i
= 0; i
< n
; i
++ )
88 SetBestSize(size
); // Needed because it is a wxControlWithItems
92 // ----------------------------------------------------------------------------
93 // adding/deleting items to/from the list
94 // ----------------------------------------------------------------------------
95 int wxChoice::DoAppend(const wxString
& item
)
98 wxArrayString::iterator insertPoint
;
101 if (GetWindowStyle() & wxCB_SORT
)
103 insertPoint
= std::lower_bound( m_strings
.begin(), m_strings
.end(), item
);
104 index
= insertPoint
- m_strings
.begin();
108 insertPoint
= m_strings
.end();
109 index
= m_strings
.size();
112 m_strings
.insert( insertPoint
, item
);
114 size_t index
= m_strings
.Add( item
) ;
116 m_datas
.Insert( NULL
, index
) ;
117 UMAInsertMenuItem(MAC_WXHMENU( m_macPopUpMenuHandle
) , item
, m_font
.GetEncoding() , index
);
118 DoSetItemClientData( index
, NULL
) ;
119 m_peer
->SetMaximum( GetCount() ) ;
123 int wxChoice::DoInsert(const wxString
& item
, int pos
)
125 wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT
), -1, wxT("can't insert into sorted list"));
126 wxCHECK_MSG((pos
>=0) && (pos
<=GetCount()), -1, wxT("invalid index"));
128 if (pos
== GetCount())
129 return DoAppend(item
);
131 UMAInsertMenuItem(MAC_WXHMENU( m_macPopUpMenuHandle
) , item
, m_font
.GetEncoding() , pos
);
132 m_strings
.Insert( item
, pos
) ;
133 m_datas
.Insert( NULL
, pos
) ;
134 DoSetItemClientData( pos
, NULL
) ;
135 m_peer
->SetMaximum( GetCount() ) ;
139 void wxChoice::Delete(int n
)
141 wxCHECK_RET( n
< GetCount(), wxT("invalid item index in wxChoice::Delete") );
142 if ( HasClientObjectData() )
144 delete GetClientObject(n
);
146 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle
) , n
+ 1) ;
147 m_strings
.RemoveAt( n
) ;
148 m_datas
.RemoveAt( n
) ;
149 m_peer
->SetMaximum( GetCount() ) ;
152 void wxChoice::Clear()
155 for ( int i
= 0 ; i
< GetCount() ; i
++ )
157 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle
) , 1 ) ;
161 m_peer
->SetMaximum( 0 ) ;
164 void wxChoice::FreeData()
166 if ( HasClientObjectData() )
168 size_t count
= GetCount();
169 for ( size_t n
= 0; n
< count
; n
++ )
171 delete GetClientObject(n
);
176 // ----------------------------------------------------------------------------
178 // ----------------------------------------------------------------------------
179 int wxChoice::GetSelection() const
181 return m_peer
->GetValue() -1 ;
184 void wxChoice::SetSelection(int n
)
186 m_peer
->SetValue( n
+ 1 ) ;
189 // ----------------------------------------------------------------------------
190 // string list functions
191 // ----------------------------------------------------------------------------
193 int wxChoice::GetCount() const
195 return m_strings
.GetCount() ;
198 int wxChoice::FindString(const wxString
& s
, bool bCase
) const
200 return m_strings
.Index( s
, bCase
) ;
203 void wxChoice::SetString(int n
, const wxString
& s
)
206 // apple menu pos is 1-based
207 UMASetMenuItemText( MAC_WXHMENU(m_macPopUpMenuHandle
) , n
+ 1 , s
, wxFont::GetDefaultEncoding() ) ;
210 wxString
wxChoice::GetString(int n
) const
212 wxCHECK_MSG( n
>= 0 && (size_t)n
< m_strings
.GetCount(), wxEmptyString
,
213 _T("wxChoice::GetString(): invalid index") );
215 return m_strings
[n
] ;
218 // ----------------------------------------------------------------------------
220 // ----------------------------------------------------------------------------
221 void wxChoice::DoSetItemClientData( int n
, void* clientData
)
223 wxCHECK_RET( n
>= 0 && (size_t)n
< m_datas
.GetCount(),
224 wxT("invalid index in wxChoice::SetClientData") );
226 m_datas
[n
] = (char*) clientData
;
229 void *wxChoice::DoGetItemClientData(int n
) const
231 wxCHECK_MSG( n
>= 0 && (size_t)n
< m_datas
.GetCount(), NULL
,
232 wxT("invalid index in wxChoice::GetClientData") );
233 return (void *)m_datas
[n
];
236 void wxChoice::DoSetItemClientObject( int n
, wxClientData
* clientData
)
238 DoSetItemClientData(n
, clientData
);
241 wxClientData
* wxChoice::DoGetItemClientObject( int n
) const
243 return (wxClientData
*)DoGetItemClientData(n
);
246 wxInt32
wxChoice::MacControlHit(WXEVENTHANDLERREF
WXUNUSED(handler
) , WXEVENTREF
WXUNUSED(event
) )
248 wxCommandEvent
event(wxEVT_COMMAND_CHOICE_SELECTED
, m_windowId
);
249 int n
= GetSelection();
250 // actually n should be made sure by the os to be a valid selection, but ...
254 event
.SetString(GetStringSelection());
255 event
.SetEventObject(this);
256 if ( HasClientObjectData() )
257 event
.SetClientObject( GetClientObject(n
) );
258 else if ( HasClientUntypedData() )
259 event
.SetClientData( GetClientData(n
) );
260 ProcessCommand(event
);
265 wxSize
wxChoice::DoGetBestSize() const
267 int lbWidth
= GetCount() > 0 ? 20 : 100; // some defaults
272 GetThemeMetric(kThemeMetricPopupButtonHeight
, &metric
);
276 wxMacPortStateHelper
st( UMAGetWindowPort( (WindowRef
) MacGetTopLevelWindowRef() ) ) ;
279 ::TextFont( m_font
.MacGetFontNum() ) ;
280 ::TextSize( m_font
.MacGetFontSize() ) ;
281 ::TextFace( m_font
.MacGetFontStyle() ) ;
285 ::TextFont( kFontIDMonaco
) ;
289 // Find the widest line
290 for(int i
= 0; i
< GetCount(); i
++) {
291 wxString
str(GetString(i
));
295 ::GetThemeTextDimensions( wxMacCFStringHolder( str
, m_font
.GetEncoding() ) ,
296 kThemeCurrentPortFont
,
303 wLine
= ::TextWidth( str
.c_str() , 0 , str
.Length() ) ;
305 lbWidth
= wxMax(lbWidth
, wLine
);
307 // Add room for the popup arrow
308 lbWidth
+= 2 * lbHeight
;
309 // And just a bit more
310 int cx
= ::TextWidth( "X" , 0 , 1 ) ;
314 return wxSize(lbWidth
, lbHeight
);
317 #endif // wxUSE_CHOICE