]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/radiobox.cpp
don't call TB_GETITEMRECT with invalid tool index
[wxWidgets.git] / src / mac / carbon / radiobox.cpp
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$
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
25 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
26
27
28 BEGIN_EVENT_TABLE(wxRadioBox, wxControl)
29 EVT_RADIOBUTTON( wxID_ANY , wxRadioBox::OnRadioButton )
30 END_EVENT_TABLE()
31
32
33 void 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
46 wxRadioBox::wxRadioBox()
47 {
48 m_noItems = 0;
49 m_noRowsOrCols = 0;
50 m_radioButtonCycle = NULL;
51 }
52
53 wxRadioBox::~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
76 bool 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
90 bool 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_labelOrig = 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 //
149 bool 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 //
168 bool 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
184 bool 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 //
202 wxString wxRadioBox::GetLabel() const
203 {
204 return wxControl::GetLabel();
205 }
206
207 // Returns the label for the given button
208 //
209 wxString 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 //
229 int 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 //
247 void wxRadioBox::SetLabel(const wxString& label)
248 {
249 return wxControl::SetLabel( label );
250 }
251
252 // Sets the label of a given button
253 //
254 void 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 //
273 void 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 //
294 bool 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 //
312 bool 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
328 bool 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 //
347 void wxRadioBox::Command( wxCommandEvent& event )
348 {
349 SetSelection( event.GetInt() );
350 ProcessCommand( event );
351 }
352
353 // Sets the selected button to receive keyboard input
354 //
355 void 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
372 void 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
483 wxSize 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