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