1///////////////////////////////////////////////////////////////////////////// 2// Name: src/mac/classic/choice.cpp 3// Purpose: wxChoice 4// Author: Stefan Csomor 5// Modified by: 6// Created: 1998-01-01 7// RCS-ID: $Id: choice.cpp 39205 2006-05-18 07:13:20Z ABX $ 8// Copyright: (c) Stefan Csomor 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12#include "wx/wxprec.h" 13 14#if wxUSE_CHOICE 15 16#include "wx/choice.h" 17 18#ifndef WX_PRECOMP 19 #include "wx/menu.h" 20#endif 21 22#include "wx/mac/uma.h" 23 24IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl) 25 26extern MenuHandle NewUniqueMenu() ; 27 28wxChoice::~wxChoice() 29{ 30 if ( HasClientObjectData() ) 31 { 32 unsigned int i, max = GetCount(); 33 34 for ( i = 0; i < max; ++i ) 35 delete GetClientObject(i); 36 } 37 38 // DeleteMenu( m_macPopUpMenuId ) ; 39 // DisposeMenu( m_macPopUpMenuHandle ) ; 40} 41 42bool wxChoice::Create(wxWindow *parent, wxWindowID id, 43 const wxPoint& pos, 44 const wxSize& size, 45 const wxArrayString& choices, 46 long style, 47 const wxValidator& validator, 48 const wxString& name) 49{ 50 wxCArrayString chs(choices); 51 52 return Create(parent, id, pos, size, chs.GetCount(), chs.GetStrings(), 53 style, validator, name); 54} 55 56bool wxChoice::Create(wxWindow *parent, wxWindowID id, 57 const wxPoint& pos, 58 const wxSize& size, 59 int n, const wxString choices[], 60 long style, 61 const wxValidator& validator, 62 const wxString& name) 63{ 64 if ( !wxChoiceBase::Create(parent, id, pos, size, style, validator, name) ) 65 return false; 66 67 Rect bounds ; 68 Str255 title ; 69 70 MacPreControlCreate( parent , id , wxEmptyString , pos , size ,style, validator , name , &bounds , title ) ; 71 m_macControl = (WXWidget) ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false , 0 , -12345 , 0 , 72 kControlPopupButtonProc + kControlPopupFixedWidthVariant , (long) this ) ; 73 74 m_macPopUpMenuHandle = NewUniqueMenu() ; 75 SetControlData( (ControlHandle) m_macControl , kControlNoPart , kControlPopupButtonMenuHandleTag , sizeof( MenuHandle ) , (char*) &m_macPopUpMenuHandle) ; 76 SetControl32BitMinimum( (ControlHandle) m_macControl , 0 ) ; 77 SetControl32BitMaximum( (ControlHandle) m_macControl , 0) ; 78 if ( n > 0 ) 79 SetControl32BitValue( (ControlHandle) m_macControl , 1 ) ; 80 MacPostControlCreate() ; 81 // TODO wxCB_SORT 82 for ( int i = 0; i < n; i++ ) 83 { 84 Append(choices[i]); 85 } 86 return true; 87} 88 89// ---------------------------------------------------------------------------- 90// adding/deleting items to/from the list 91// ---------------------------------------------------------------------------- 92int wxChoice::DoAppend(const wxString& item) 93{ 94 UMAAppendMenuItem(MAC_WXHMENU( m_macPopUpMenuHandle ) , item, m_font.GetEncoding() ); 95 m_strings.Add( item ) ; 96 m_datas.Add( NULL ) ; 97 int index = m_strings.GetCount() - 1 ; 98 DoSetItemClientData( index , NULL ) ; 99 SetControl32BitMaximum( (ControlHandle) m_macControl , GetCount()) ; 100 return index ; 101} 102 103int wxChoice::DoInsert(const wxString& item, unsigned int pos) 104{ 105 wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list")); 106 wxCHECK_MSG(IsValidInsert(pos), -1, wxT("invalid index")); 107 108 if (pos == GetCount()) 109 return DoAppend(item); 110 111 UMAAppendMenuItem(MAC_WXHMENU( m_macPopUpMenuHandle ) , item, m_font.GetEncoding() ); 112 m_strings.Insert( item, pos ) ; 113 m_datas.Insert( NULL, pos ) ; 114 DoSetItemClientData( pos , NULL ) ; 115 SetControl32BitMaximum( (ControlHandle) m_macControl , pos) ; 116 return pos ; 117} 118 119void wxChoice::Delete(unsigned int n) 120{ 121 wxCHECK_RET( IsValid(n), wxT("invalid item index in wxChoice::Delete") ); 122 if ( HasClientObjectData() ) 123 { 124 delete GetClientObject(n); 125 } 126 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , n + 1) ; 127 m_strings.RemoveAt( n ) ; 128 m_datas.RemoveAt( n ) ; 129 SetControl32BitMaximum( (ControlHandle) m_macControl , GetCount()) ; 130} 131 132void wxChoice::Clear() 133{ 134 FreeData(); 135 for ( unsigned int i = 0 ; i < GetCount() ; i++ ) 136 { 137 ::DeleteMenuItem( MAC_WXHMENU(m_macPopUpMenuHandle) , 1 ) ; 138 } 139 m_strings.Empty() ; 140 m_datas.Empty() ; 141 SetControl32BitMaximum( (ControlHandle) m_macControl , 0 ) ; 142} 143 144void wxChoice::FreeData() 145{ 146 if ( HasClientObjectData() ) 147 { 148 unsigned int count = GetCount(); 149 for ( unsigned int n = 0; n < count; n++ ) 150 { 151 delete GetClientObject(n); 152 } 153 } 154} 155 156// ---------------------------------------------------------------------------- 157// selection 158// ---------------------------------------------------------------------------- 159int wxChoice::GetSelection() const 160{ 161 return GetControl32BitValue( (ControlHandle) m_macControl ) -1 ; 162} 163 164void wxChoice::SetSelection(int n) 165{ 166 SetControl32BitValue( (ControlHandle) m_macControl , n + 1 ) ; 167} 168 169// ---------------------------------------------------------------------------- 170// string list functions 171// ---------------------------------------------------------------------------- 172 173unsigned int wxChoice::GetCount() const 174{ 175 return m_strings.GetCount() ; 176} 177 178void wxChoice::SetString(unsigned int n, const wxString& s) 179{ 180 wxFAIL_MSG(wxT("wxChoice::SetString() not yet implemented")); 181#if 0 // should do this, but no Insert() so far 182 Delete(n); 183 Insert(n + 1, s); 184#endif 185} 186 187wxString wxChoice::GetString(unsigned int n) const 188{ 189 wxCHECK_MSG( IsValid(n), wxEmptyString, 190 _T("wxChoice::GetString(): invalid index") ); 191 192 return m_strings[n] ; 193} 194 195// ---------------------------------------------------------------------------- 196// client data 197// ---------------------------------------------------------------------------- 198void wxChoice::DoSetItemClientData(unsigned int n, void* clientData) 199{ 200 wxCHECK_RET( n >= 0 && (unsigned int)n < m_datas.GetCount(), 201 wxT("invalid index in wxChoice::SetClientData") ); 202 203 m_datas[n] = (char*) clientData ; 204} 205 206void *wxChoice::DoGetItemClientData(unsigned int n) const 207{ 208 wxCHECK_MSG( n >= 0 && (unsigned int)n < m_datas.GetCount(), NULL, 209 wxT("invalid index in wxChoice::GetClientData") ); 210 return (void *)m_datas[n]; 211} 212 213void wxChoice::DoSetItemClientObject(unsigned int n, wxClientData* clientData) 214{ 215 DoSetItemClientData(n, clientData); 216} 217 218wxClientData* wxChoice::DoGetItemClientObject(unsigned int n) const 219{ 220 return (wxClientData *)DoGetItemClientData(n); 221} 222 223void wxChoice::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED(mouseStillDown)) 224{ 225 wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, m_windowId ); 226 int n = GetSelection(); 227 // actually n should be made sure by the os to be a valid selection, but ... 228 if ( n > -1 ) 229 { 230 event.SetInt( n ); 231 event.SetString(GetStringSelection()); 232 event.SetEventObject(this); 233 if ( HasClientObjectData() ) 234 event.SetClientObject( GetClientObject(n) ); 235 else if ( HasClientUntypedData() ) 236 event.SetClientData( GetClientData(n) ); 237 ProcessCommand(event); 238 } 239} 240 241wxSize wxChoice::DoGetBestSize() const 242{ 243 int lbWidth = GetCount() > 0 ? 20 : 100; // some defaults 244 int lbHeight = 20; 245 int wLine; 246#if TARGET_CARBON 247 long metric ; 248 GetThemeMetric(kThemeMetricPopupButtonHeight , &metric ); 249 lbHeight = metric ; 250#endif 251 { 252 wxMacPortStateHelper st( UMAGetWindowPort( (WindowRef) MacGetRootWindow() ) ) ; 253 if ( m_font.Ok() ) 254 { 255 ::TextFont( m_font.GetMacFontNum() ) ; 256 ::TextSize( m_font.GetMacFontSize() ) ; 257 ::TextFace( m_font.GetMacFontStyle() ) ; 258 } 259 else 260 { 261 ::TextFont( kFontIDMonaco ) ; 262 ::TextSize( 9 ); 263 ::TextFace( 0 ) ; 264 } 265 // Find the widest line 266 for(unsigned int i = 0; i < GetCount(); i++) { 267 wxString str(GetString(i)); 268 #if wxUSE_UNICODE 269 Point bounds={0,0} ; 270 SInt16 baseline ; 271 ::GetThemeTextDimensions( wxMacCFStringHolder( str , m_font.GetEncoding() ) , 272 kThemeCurrentPortFont, 273 kThemeStateActive, 274 false, 275 &bounds, 276 &baseline ); 277 wLine = bounds.h ; 278 #else 279 wLine = ::TextWidth( str.c_str() , 0 , str.length() ) ; 280 #endif 281 lbWidth = wxMax(lbWidth, wLine); 282 } 283 // Add room for the popup arrow 284 lbWidth += 2 * lbHeight ; 285 // And just a bit more 286 int cx = ::TextWidth( "X" , 0 , 1 ) ; 287 lbWidth += cx ; 288 289 } 290 return wxSize(lbWidth, lbHeight); 291} 292 293#endif // wxUSE_CHOICE 294