]> git.saurik.com Git - wxWidgets.git/blame - src/osx/radiobox_osx.cpp
guarding open combo box against AppDefined NSEvents issued by wxEventLoop::WakeUp...
[wxWidgets.git] / src / osx / radiobox_osx.cpp
CommitLineData
489468fe 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/osx/radiobox_osx.cpp
489468fe
SC
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
524c47aa 23#include "wx/osx/private.h"
489468fe 24
ae255e29
SC
25// regarding layout: note that there are differences in inter-control
26// spacing between InterfaceBuild and the Human Interface Guidelines, we stick
27// to the latter, as those are also used eg in the System Preferences Dialogs
28
489468fe
SC
29IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
30
31
32BEGIN_EVENT_TABLE(wxRadioBox, wxControl)
33 EVT_RADIOBUTTON( wxID_ANY , wxRadioBox::OnRadioButton )
34END_EVENT_TABLE()
35
36
37void wxRadioBox::OnRadioButton( wxCommandEvent &outer )
38{
39 if ( outer.IsChecked() )
40 {
ce7fe42e 41 wxCommandEvent event( wxEVT_RADIOBOX, m_windowId );
489468fe
SC
42 int i = GetSelection() ;
43 event.SetInt(i);
44 event.SetString(GetString(i));
45 event.SetEventObject( this );
46 ProcessCommand(event);
47 }
48}
49
50wxRadioBox::wxRadioBox()
51{
52 m_noItems = 0;
53 m_noRowsOrCols = 0;
54 m_radioButtonCycle = NULL;
55}
56
57wxRadioBox::~wxRadioBox()
58{
c6212a0c 59 SendDestroyEvent();
489468fe
SC
60
61 wxRadioButton *next, *current;
62
63 current = m_radioButtonCycle->NextInCycle();
64 if (current != NULL)
65 {
66 while (current != m_radioButtonCycle)
67 {
68 next = current->NextInCycle();
69 delete current;
70
71 current = next;
72 }
73
74 delete current;
75 }
76}
77
78// Create the radiobox for two-step construction
79
80bool wxRadioBox::Create( wxWindow *parent,
81 wxWindowID id, const wxString& label,
82 const wxPoint& pos, const wxSize& size,
83 const wxArrayString& choices,
84 int majorDim, long style,
85 const wxValidator& val, const wxString& name )
86{
87 wxCArrayString chs(choices);
88
89 return Create(
90 parent, id, label, pos, size, chs.GetCount(),
91 chs.GetStrings(), majorDim, style, val, name);
92}
93
94bool wxRadioBox::Create( wxWindow *parent,
95 wxWindowID id, const wxString& label,
96 const wxPoint& pos, const wxSize& size,
97 int n, const wxString choices[],
98 int majorDim, long style,
99 const wxValidator& val, const wxString& name )
d15694e8
SC
100{
101 DontCreatePeer();
102
489468fe
SC
103 if ( !wxControl::Create( parent, id, pos, size, style, val, name ) )
104 return false;
105
d15694e8
SC
106 // during construction we must keep this at 0, otherwise GetBestSize fails
107 m_noItems = 0;
489468fe
SC
108 m_noRowsOrCols = majorDim;
109 m_radioButtonCycle = NULL;
110
111 SetMajorDim( majorDim == 0 ? n : majorDim, style );
112
113 m_labelOrig = m_label = label;
114
22756322 115 SetPeer(wxWidgetImpl::CreateGroupBox( this, parent, id, label, pos, size, style, GetExtraStyle() ));
489468fe 116
d15694e8 117 for (int i = 0; i < n; i++)
489468fe
SC
118 {
119 wxRadioButton *radBtn = new wxRadioButton(
120 this,
121 wxID_ANY,
122 GetLabelText(choices[i]),
123 wxPoint( 5, 20 * i + 10 ),
124 wxDefaultSize,
125 i == 0 ? wxRB_GROUP : 0 );
126
127 if ( i == 0 )
128 m_radioButtonCycle = radBtn;
129// m_radioButtonCycle = radBtn->AddInCycle( m_radioButtonCycle );
130 }
131
d15694e8
SC
132 // as all radiobuttons have been set-up, set the correct dimensions
133 m_noItems = (unsigned int)n;
134 SetMajorDim( majorDim == 0 ? n : majorDim, style );
135
489468fe 136 SetSelection( 0 );
d15694e8
SC
137 InvalidateBestSize();
138 SetInitialSize( size );
489468fe
SC
139 MacPostControlCreate( pos, size );
140
141 return true;
142}
143
144// Enables or disables the entire radiobox
145//
146bool wxRadioBox::Enable(bool enable)
147{
148 wxRadioButton *current;
149
150 if (!wxControl::Enable( enable ))
151 return false;
152
153 current = m_radioButtonCycle;
154 for (unsigned int i = 0; i < m_noItems; i++)
155 {
156 current->Enable( enable );
157 current = current->NextInCycle();
158 }
159
160 return true;
161}
162
163// Enables or disables an given button
164//
165bool wxRadioBox::Enable(unsigned int item, bool enable)
166{
167 if (!IsValid( item ))
168 return false;
169
170 unsigned int i = 0;
171 wxRadioButton *current = m_radioButtonCycle;
172 while (i != item)
173 {
174 i++;
175 current = current->NextInCycle();
176 }
177
178 return current->Enable( enable );
179}
180
181bool wxRadioBox::IsItemEnabled(unsigned int item) const
182{
183 if (!IsValid( item ))
184 return false;
185
186 unsigned int i = 0;
187 wxRadioButton *current = m_radioButtonCycle;
188 while (i != item)
189 {
190 i++;
191 current = current->NextInCycle();
192 }
193
194 return current->IsEnabled();
195}
196
197// Returns the radiobox label
198//
199wxString wxRadioBox::GetLabel() const
200{
201 return wxControl::GetLabel();
202}
203
204// Returns the label for the given button
205//
206wxString wxRadioBox::GetString(unsigned int item) const
207{
208 wxRadioButton *current;
209
210 if (!IsValid( item ))
211 return wxEmptyString;
212
213 unsigned int i = 0;
214 current = m_radioButtonCycle;
215 while (i != item)
216 {
217 i++;
218 current = current->NextInCycle();
219 }
220
221 return current->GetLabel();
222}
223
224// Returns the zero-based position of the selected button
225//
226int wxRadioBox::GetSelection() const
227{
228 int i;
229 wxRadioButton *current;
230
231 i = 0;
232 current = m_radioButtonCycle;
233 while (!current->GetValue())
234 {
235 i++;
236 current = current->NextInCycle();
237 }
238
239 return i;
240}
241
242// Sets the radiobox label
243//
244void wxRadioBox::SetLabel(const wxString& label)
245{
246 return wxControl::SetLabel( label );
247}
248
249// Sets the label of a given button
250//
251void wxRadioBox::SetString(unsigned int item,const wxString& label)
252{
253 if (!IsValid( item ))
254 return;
255
256 unsigned int i = 0;
257 wxRadioButton *current = m_radioButtonCycle;
258 while (i != item)
259 {
260 i++;
261 current = current->NextInCycle();
262 }
263
264 return current->SetLabel( label );
265}
266
267// Sets a button by passing the desired position. This does not cause
ce7fe42e 268// wxEVT_RADIOBOX event to get emitted
489468fe
SC
269//
270void wxRadioBox::SetSelection(int item)
271{
272 int i;
273 wxRadioButton *current;
274
275 if (!IsValid( item ))
276 return;
277
278 i = 0;
279 current = m_radioButtonCycle;
280 while (i != item)
281 {
282 i++;
283 current = current->NextInCycle();
284 }
285
286 current->SetValue( true );
287}
288
289// Shows or hides the entire radiobox
290//
291bool wxRadioBox::Show(bool show)
292{
293 wxRadioButton *current;
294
295 current = m_radioButtonCycle;
296 for (unsigned int i=0; i<m_noItems; i++)
297 {
298 current->Show( show );
299 current = current->NextInCycle();
300 }
301
302 wxControl::Show( show );
303
304 return true;
305}
306
307// Shows or hides the given button
308//
309bool wxRadioBox::Show(unsigned int item, bool show)
310{
311 if (!IsValid( item ))
312 return false;
313
314 unsigned int i = 0;
315 wxRadioButton *current = m_radioButtonCycle;
316 while (i != item)
317 {
318 i++;
319 current = current->NextInCycle();
320 }
321
322 return current->Show( show );
323}
324
325bool wxRadioBox::IsItemShown(unsigned int item) const
326{
327 if (!IsValid( item ))
328 return false;
329
330 unsigned int i = 0;
331 wxRadioButton *current = m_radioButtonCycle;
332 while (i != item)
333 {
334 i++;
335 current = current->NextInCycle();
336 }
337
338 return current->IsShown();
339}
340
341
342// Simulates the effect of the user issuing a command to the item
343//
344void wxRadioBox::Command( wxCommandEvent& event )
345{
346 SetSelection( event.GetInt() );
347 ProcessCommand( event );
348}
349
350// Sets the selected button to receive keyboard input
351//
352void wxRadioBox::SetFocus()
353{
354 wxRadioButton *current;
355
356 current = m_radioButtonCycle;
357 while (!current->GetValue())
358 {
359 current = current->NextInCycle();
360 }
361
362 current->SetFocus();
363}
364
365// Simulates the effect of the user issuing a command to the item
366//
ae255e29
SC
367#if wxOSX_USE_CARBON
368 #define RADIO_SIZE 20
369#else
370 // Cocoa has an additional border are of about 3 pixels
371 #define RADIO_SIZE 23
372#endif
489468fe
SC
373
374void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
375{
376 int i;
377 wxRadioButton *current;
378
379 // define the position
380
381 int x_current, y_current;
382 int x_offset, y_offset;
383 int widthOld, heightOld;
384
385 GetSize( &widthOld, &heightOld );
386 GetPosition( &x_current, &y_current );
387
388 x_offset = x;
389 y_offset = y;
390 if (!(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
391 {
392 if (x == wxDefaultCoord)
393 x_offset = x_current;
394 if (y == wxDefaultCoord)
395 y_offset = y_current;
396 }
397
398 // define size
399 int charWidth, charHeight;
400 int maxWidth, maxHeight;
401 int eachWidth[128], eachHeight[128];
402 int totWidth, totHeight;
403
404 GetTextExtent(
405 wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
406 &charWidth, &charHeight );
407
408 charWidth /= 52;
409
410 maxWidth = -1;
411 maxHeight = -1;
ae255e29
SC
412 wxSize bestSizeRadio ;
413 if ( m_radioButtonCycle )
414 bestSizeRadio = m_radioButtonCycle->GetBestSize();
03647350 415
489468fe
SC
416 for (unsigned int i = 0 ; i < m_noItems; i++)
417 {
418 GetTextExtent(GetString(i), &eachWidth[i], &eachHeight[i] );
ae255e29
SC
419 eachWidth[i] = eachWidth[i] + RADIO_SIZE;
420 eachHeight[i] = wxMax( eachHeight[i], bestSizeRadio.y );
489468fe
SC
421
422 if (maxWidth < eachWidth[i])
423 maxWidth = eachWidth[i];
424 if (maxHeight < eachHeight[i])
425 maxHeight = eachHeight[i];
426 }
427
ae255e29 428 // according to HIG (official space - 3 Pixels Diff between Frame and Layout size)
03647350 429 int space = 3;
ae255e29
SC
430 if ( GetWindowVariant() == wxWINDOW_VARIANT_MINI )
431 space = 2;
03647350 432
ae255e29 433 totHeight = GetRowCount() * maxHeight + (GetRowCount() - 1) * space;
489468fe
SC
434 totWidth = GetColumnCount() * (maxWidth + charWidth);
435
436 wxSize sz = DoGetSizeFromClientSize( wxSize( totWidth, totHeight ) ) ;
c6212a0c 437
489468fe
SC
438 // change the width / height only when specified
439 if ( width == wxDefaultCoord )
440 {
441 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
442 width = sz.x;
443 else
444 width = widthOld;
445 }
446
447 if ( height == wxDefaultCoord )
448 {
449 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
450 height = sz.y;
451 else
452 height = heightOld;
453 }
454
455 wxControl::DoSetSize( x_offset, y_offset, width, height, wxSIZE_AUTO );
456
457 // arrange radio buttons
458 int x_start, y_start;
459
0c530e5a
SC
460 x_start = ( width - sz.x ) / 2;
461 y_start = ( height - sz.y ) / 2;
489468fe
SC
462
463 x_offset = x_start;
464 y_offset = y_start;
465
466 current = m_radioButtonCycle;
467 for (i = 0 ; i < (int)m_noItems; i++)
468 {
469 // not to do for the zero button!
470 if ((i > 0) && ((i % GetMajorDim()) == 0))
471 {
472 if (m_windowStyle & wxRA_SPECIFY_ROWS)
473 {
474 x_offset += maxWidth + charWidth;
475 y_offset = y_start;
476 }
477 else
478 {
479 x_offset = x_start;
ae255e29 480 y_offset += maxHeight + space;
489468fe
SC
481 }
482 }
483
ae255e29 484 current->SetSize( x_offset, y_offset, eachWidth[i], eachHeight[i] );
489468fe
SC
485 current = current->NextInCycle();
486
487 if (m_windowStyle & wxRA_SPECIFY_ROWS)
03647350 488 y_offset += maxHeight + space;
489468fe
SC
489 else
490 x_offset += maxWidth + charWidth;
491 }
492}
493
494wxSize wxRadioBox::DoGetBestSize() const
495{
496 int charWidth, charHeight;
497 int maxWidth, maxHeight;
498 int eachWidth, eachHeight;
499 int totWidth, totHeight;
500
501 wxFont font = GetFont(); // GetParent()->GetFont()
502 GetTextExtent(
503 wxT("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"),
504 &charWidth, &charHeight, NULL, NULL, &font );
505
506 charWidth /= 52;
507
508 maxWidth = -1;
509 maxHeight = -1;
510
ae255e29
SC
511 wxSize bestSizeRadio ;
512 if ( m_radioButtonCycle )
513 bestSizeRadio = m_radioButtonCycle->GetBestSize();
514
489468fe
SC
515 for (unsigned int i = 0 ; i < m_noItems; i++)
516 {
517 GetTextExtent(GetString(i), &eachWidth, &eachHeight, NULL, NULL, &font );
ae255e29
SC
518 eachWidth = (eachWidth + RADIO_SIZE);
519 eachHeight = wxMax(eachHeight, bestSizeRadio.y );
489468fe
SC
520 if (maxWidth < eachWidth)
521 maxWidth = eachWidth;
522 if (maxHeight < eachHeight)
523 maxHeight = eachHeight;
524 }
525
ae255e29 526 // according to HIG (official space - 3 Pixels Diff between Frame and Layout size)
03647350 527 int space = 3;
ae255e29
SC
528 if ( GetWindowVariant() == wxWINDOW_VARIANT_MINI )
529 space = 2;
03647350 530
ae255e29 531 totHeight = GetRowCount() * maxHeight + (GetRowCount() - 1) * space;
489468fe
SC
532 totWidth = GetColumnCount() * (maxWidth + charWidth);
533
534 wxSize sz = DoGetSizeFromClientSize( wxSize( totWidth, totHeight ) );
535 totWidth = sz.x;
536 totHeight = sz.y;
c6212a0c 537
0c530e5a
SC
538 // optimum size is an additional 5 pt border to all sides
539 totWidth += 10;
540 totHeight += 10;
489468fe
SC
541
542 // handle radio box title as well
543 GetTextExtent( GetLabel(), &eachWidth, NULL );
544 eachWidth = (int)(eachWidth + RADIO_SIZE) + 3 * charWidth;
545 if (totWidth < eachWidth)
546 totWidth = eachWidth;
547
548 return wxSize( totWidth, totHeight );
549}
550
bbd8f8af
SC
551bool wxRadioBox::SetFont(const wxFont& font)
552{
553 bool retval = wxWindowBase::SetFont( font );
554
555 // dont' update the native control, it has its own small font
03647350 556
ae255e29 557 // should we iterate over the children ?
bbd8f8af
SC
558
559 return retval;
560}
561
489468fe 562#endif // wxUSE_RADIOBOX