1///////////////////////////////////////////////////////////////////////////// 2// Name: src/mac/carbon/radiobox.cpp 3// Purpose: wxRadioBox 4// Author: Stefan Csomor 5// Modified by: JS Lair (99/11/15) first implementation 6// Created: 1998-01-01 7// RCS-ID: $Id: radiobox.cpp 49544 2007-10-31 01:58:25Z KO $ 8// Copyright: (c) Stefan Csomor 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12#include "wx/wxprec.h" 13 14#if wxUSE_RADIOBOX 15 16#include "wx/radiobox.h" 17 18#ifndef WX_PRECOMP 19 #include "wx/radiobut.h" 20 #include "wx/arrstr.h" 21#endif 22 23#include "wx/mac/uma.h" 24 25IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl) 26 27 28BEGIN_EVENT_TABLE(wxRadioBox, wxControl) 29 EVT_RADIOBUTTON( wxID_ANY , wxRadioBox::OnRadioButton ) 30END_EVENT_TABLE() 31 32 33void wxRadioBox::OnRadioButton( wxCommandEvent &outer ) 34{ 35 if ( outer.IsChecked() ) 36 { 37 wxCommandEvent event( wxEVT_COMMAND_RADIOBOX_SELECTED, m_windowId ); 38 int i = GetSelection() ; 39 event.SetInt(i); 40 event.SetString(GetString(i)); 41 event.SetEventObject( this ); 42 ProcessCommand(event); 43 } 44} 45 46wxRadioBox::wxRadioBox() 47{ 48 m_noItems = 0; 49 m_noRowsOrCols = 0; 50 m_radioButtonCycle = NULL; 51} 52 53wxRadioBox::~wxRadioBox() 54{ 55 m_isBeingDeleted = true; 56 57 wxRadioButton *next, *current; 58 59 current = m_radioButtonCycle->NextInCycle(); 60 if (current != NULL) 61 { 62 while (current != m_radioButtonCycle) 63 { 64 next = current->NextInCycle(); 65 delete current; 66 67 current = next; 68 } 69 70 delete current; 71 } 72} 73 74// Create the radiobox for two-step construction 75 76bool wxRadioBox::Create( wxWindow *parent, 77 wxWindowID id, const wxString& label, 78 const wxPoint& pos, const wxSize& size, 79 const wxArrayString& choices, 80 int majorDim, long style, 81 const wxValidator& val, const wxString& name ) 82{ 83 wxCArrayString chs(choices); 84 85 return Create( 86 parent, id, label, pos, size, chs.GetCount(), 87 chs.GetStrings(), majorDim, style, val, name); 88} 89 90bool wxRadioBox::Create( wxWindow *parent, 91 wxWindowID id, const wxString& label, 92 const wxPoint& pos, const wxSize& size, 93 int n, const wxString choices[], 94 int majorDim, long style, 95 const wxValidator& val, const wxString& name ) 96{ 97 m_macIsUserPane = false ; 98 99 if ( !wxControl::Create( parent, id, pos, size, style, val, name ) ) 100 return false; 101 102 int i; 103 104 m_noItems = (unsigned int)n; 105 m_noRowsOrCols = majorDim; 106 m_radioButtonCycle = NULL; 107 108 SetMajorDim( majorDim == 0 ? n : majorDim, style ); 109 110 m_label = label; 111 112 Rect bounds = wxMacGetBoundsForControl( this, pos, size ); 113 if ( bounds.right <= bounds.left ) 114 bounds.right = bounds.left + 100; 115 if ( bounds.bottom <= bounds.top ) 116 bounds.bottom = bounds.top + 100; 117 118 m_peer = new wxMacControl( this ); 119 120 OSStatus err = CreateGroupBoxControl( 121 MAC_WXHWND(parent->MacGetTopLevelWindowRef()), 122 &bounds, CFSTR("") , true /*primary*/, 123 m_peer->GetControlRefAddr() ); 124 verify_noerr( err ); 125 126 for (i = 0; i < n; i++) 127 { 128 wxRadioButton *radBtn = new wxRadioButton( 129 this, 130 wxID_ANY, 131 GetLabelText(choices[i]), 132 wxPoint( 5, 20 * i + 10 ), 133 wxDefaultSize, 134 i == 0 ? wxRB_GROUP : 0 ); 135 136 if ( i == 0 ) 137 m_radioButtonCycle = radBtn; 138// m_radioButtonCycle = radBtn->AddInCycle( m_radioButtonCycle ); 139 } 140 141 SetSelection( 0 ); 142 MacPostControlCreate( pos, size ); 143 144 return true; 145} 146 147// Enables or disables the entire radiobox 148// 149bool wxRadioBox::Enable(bool enable) 150{ 151 wxRadioButton *current; 152 153 if (!wxControl::Enable( enable )) 154 return false; 155 156 current = m_radioButtonCycle; 157 for (unsigned int i = 0; i < m_noItems; i++) 158 { 159 current->Enable( enable ); 160 current = current->NextInCycle(); 161 } 162 163 return true; 164} 165 166// Enables or disables an given button 167// 168bool wxRadioBox::Enable(unsigned int item, bool enable) 169{ 170 if (!IsValid( item )) 171 return false; 172 173 unsigned int i = 0; 174 wxRadioButton *current = m_radioButtonCycle; 175 while (i != item) 176 { 177 i++; 178 current = current->NextInCycle(); 179 } 180 181 return current->Enable( enable ); 182} 183 184bool wxRadioBox::IsItemEnabled(unsigned int item) const 185{ 186 if (!IsValid( item )) 187 return false; 188 189 unsigned int i = 0; 190 wxRadioButton *current = m_radioButtonCycle; 191 while (i != item) 192 { 193 i++; 194 current = current->NextInCycle(); 195 } 196 197 return current->IsEnabled(); 198} 199 200// Returns the radiobox label 201// 202wxString wxRadioBox::GetLabel() const 203{ 204 return wxControl::GetLabel(); 205} 206 207// Returns the label for the given button 208// 209wxString wxRadioBox::GetString(unsigned int item) const 210{ 211 wxRadioButton *current; 212 213 if (!IsValid( item )) 214 return wxEmptyString; 215 216 unsigned int i = 0; 217 current = m_radioButtonCycle; 218 while (i != item) 219 { 220 i++; 221 current = current->NextInCycle(); 222 } 223 224 return current->GetLabel(); 225} 226 227// Returns the zero-based position of the selected button 228// 229int wxRadioBox::GetSelection() const 230{ 231 int i; 232 wxRadioButton *current; 233 234 i = 0; 235 current = m_radioButtonCycle; 236 while (!current->GetValue()) 237 { 238 i++; 239 current = current->NextInCycle(); 240 } 241 242 return i; 243} 244 245// Sets the radiobox label 246// 247void wxRadioBox::SetLabel(const wxString& label) 248{ 249 return wxControl::SetLabel( label ); 250} 251 252// Sets the label of a given button 253// 254void wxRadioBox::SetString(unsigned int item,const wxString& label) 255{ 256 if (!IsValid( item )) 257 return; 258 259 unsigned int i = 0; 260 wxRadioButton *current = m_radioButtonCycle; 261 while (i != item) 262 { 263 i++; 264 current = current->NextInCycle(); 265 } 266 267 return current->SetLabel( label ); 268} 269 270// Sets a button by passing the desired position. This does not cause 271// wxEVT_COMMAND_RADIOBOX_SELECTED event to get emitted 272// 273void wxRadioBox::SetSelection(int item) 274{ 275 int i; 276 wxRadioButton *current; 277 278 if (!IsValid( item )) 279 return; 280 281 i = 0; 282 current = m_radioButtonCycle; 283 while (i != item) 284 { 285 i++; 286 current = current->NextInCycle(); 287 } 288 289 current->SetValue( true ); 290} 291 292// Shows or hides the entire radiobox 293// 294bool wxRadioBox::Show(bool show) 295{ 296 wxRadioButton *current; 297 298 current = m_radioButtonCycle; 299 for (unsigned int i=0; i<m_noItems; i++) 300 { 301 current->Show( show ); 302 current = current->NextInCycle(); 303 } 304 305 wxControl::Show( show ); 306 307 return true; 308} 309 310// Shows or hides the given button 311// 312bool wxRadioBox::Show(unsigned int item, bool show) 313{ 314 if (!IsValid( item )) 315 return false; 316 317 unsigned int i = 0; 318 wxRadioButton *current = m_radioButtonCycle; 319 while (i != item) 320 { 321 i++; 322 current = current->NextInCycle(); 323 } 324 325 return current->Show( show ); 326} 327 328bool wxRadioBox::IsItemShown(unsigned int item) const 329{ 330 if (!IsValid( item )) 331 return false; 332 333 unsigned int i = 0; 334 wxRadioButton *current = m_radioButtonCycle; 335 while (i != item) 336 { 337 i++; 338 current = current->NextInCycle(); 339 } 340 341 return current->IsShown(); 342} 343 344 345// Simulates the effect of the user issuing a command to the item 346// 347void wxRadioBox::Command( wxCommandEvent& event ) 348{ 349 SetSelection( event.GetInt() ); 350 ProcessCommand( event ); 351} 352 353// Sets the selected button to receive keyboard input 354// 355void wxRadioBox::SetFocus() 356{ 357 wxRadioButton *current; 358 359 current = m_radioButtonCycle; 360 while (!current->GetValue()) 361 { 362 current = current->NextInCycle(); 363 } 364 365 current->SetFocus(); 366} 367 368// Simulates the effect of the user issuing a command to the item 369// 370#define RADIO_SIZE 20 371 372void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags) 373{ 374 int i; 375 wxRadioButton *current; 376 377 // define the position 378 379 int x_current, y_current; 380 int x_offset, y_offset; 381 int widthOld, heightOld; 382 383 GetSize( &widthOld, &heightOld ); 384 GetPosition( &x_current, &y_current ); 385 386 x_offset = x; 387 y_offset = y; 388 if (!(sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) 389 { 390 if (x == wxDefaultCoord) 391 x_offset = x_current; 392 if (y == wxDefaultCoord) 393 y_offset = y_current; 394 } 395 396 // define size 397 int charWidth, charHeight; 398 int maxWidth, maxHeight; 399 int eachWidth[128], eachHeight[128]; 400 int totWidth, totHeight; 401 402 GetTextExtent( 403 wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 404 &charWidth, &charHeight ); 405 406 charWidth /= 52; 407 408 maxWidth = -1; 409 maxHeight = -1; 410 for (unsigned int i = 0 ; i < m_noItems; i++) 411 { 412 GetTextExtent(GetString(i), &eachWidth[i], &eachHeight[i] ); 413 eachWidth[i] = (int)(eachWidth[i] + RADIO_SIZE); 414 eachHeight[i] = (int)((3 * eachHeight[i]) / 2); 415 416 if (maxWidth < eachWidth[i]) 417 maxWidth = eachWidth[i]; 418 if (maxHeight < eachHeight[i]) 419 maxHeight = eachHeight[i]; 420 } 421 422 totHeight = GetRowCount() * maxHeight; 423 totWidth = GetColumnCount() * (maxWidth + charWidth); 424 425 wxSize sz = DoGetSizeFromClientSize( wxSize( totWidth, totHeight ) ) ; 426 427 // change the width / height only when specified 428 if ( width == wxDefaultCoord ) 429 { 430 if ( sizeFlags & wxSIZE_AUTO_WIDTH ) 431 width = sz.x; 432 else 433 width = widthOld; 434 } 435 436 if ( height == wxDefaultCoord ) 437 { 438 if ( sizeFlags & wxSIZE_AUTO_HEIGHT ) 439 height = sz.y; 440 else 441 height = heightOld; 442 } 443 444 wxControl::DoSetSize( x_offset, y_offset, width, height, wxSIZE_AUTO ); 445 446 // arrange radio buttons 447 int x_start, y_start; 448 449 x_start = 0; 450 y_start = 0; 451 452 x_offset = x_start; 453 y_offset = y_start; 454 455 current = m_radioButtonCycle; 456 for (i = 0 ; i < (int)m_noItems; i++) 457 { 458 // not to do for the zero button! 459 if ((i > 0) && ((i % GetMajorDim()) == 0)) 460 { 461 if (m_windowStyle & wxRA_SPECIFY_ROWS) 462 { 463 x_offset += maxWidth + charWidth; 464 y_offset = y_start; 465 } 466 else 467 { 468 x_offset = x_start; 469 y_offset += maxHeight ; //+ charHeight / 2 470 } 471 } 472 473 current->SetSize( x_offset, y_offset, eachWidth[i], eachHeight[i]); 474 current = current->NextInCycle(); 475 476 if (m_windowStyle & wxRA_SPECIFY_ROWS) 477 y_offset += maxHeight ; // + charHeight / 2 478 else 479 x_offset += maxWidth + charWidth; 480 } 481} 482 483wxSize wxRadioBox::DoGetBestSize() const 484{ 485 int charWidth, charHeight; 486 int maxWidth, maxHeight; 487 int eachWidth, eachHeight; 488 int totWidth, totHeight; 489 490 wxFont font = GetFont(); // GetParent()->GetFont() 491 GetTextExtent( 492 wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 493 &charWidth, &charHeight, NULL, NULL, &font ); 494 495 charWidth /= 52; 496 497 maxWidth = -1; 498 maxHeight = -1; 499 500 for (unsigned int i = 0 ; i < m_noItems; i++) 501 { 502 GetTextExtent(GetString(i), &eachWidth, &eachHeight, NULL, NULL, &font ); 503 eachWidth = (int)(eachWidth + RADIO_SIZE); 504 eachHeight = (int)((3 * eachHeight) / 2); 505 if (maxWidth < eachWidth) 506 maxWidth = eachWidth; 507 if (maxHeight < eachHeight) 508 maxHeight = eachHeight; 509 } 510 511 totHeight = GetRowCount() * maxHeight; 512 totWidth = GetColumnCount() * (maxWidth + charWidth); 513 514 wxSize sz = DoGetSizeFromClientSize( wxSize( totWidth, totHeight ) ); 515 totWidth = sz.x; 516 totHeight = sz.y; 517 518 // handle radio box title as well 519 GetTextExtent( GetLabel(), &eachWidth, NULL ); 520 eachWidth = (int)(eachWidth + RADIO_SIZE) + 3 * charWidth; 521 if (totWidth < eachWidth) 522 totWidth = eachWidth; 523 524 return wxSize( totWidth, totHeight ); 525} 526 527#endif // wxUSE_RADIOBOX 528