1 /////////////////////////////////////////////////////////////////////////////
2 // Name: univ/radiobox.cpp
3 // Purpose: wxRadioBox implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
29 #include "wx/dcclient.h"
30 #include "wx/radiobox.h"
31 #include "wx/radiobut.h"
32 #include "wx/validate.h"
33 #include "wx/arrstr.h"
36 #include "wx/tooltip.h"
38 #include "wx/univ/theme.h"
39 #include "wx/univ/renderer.h"
40 #include "wx/univ/inphand.h"
41 #include "wx/univ/colschem.h"
43 // ----------------------------------------------------------------------------
45 // ----------------------------------------------------------------------------
47 static const int BUTTON_BORDER_X
= 2;
48 static const int BUTTON_BORDER_Y
= 4;
50 static const int BOX_BORDER_X
= 2;
51 static const int BOX_BORDER_Y
= 2;
53 // ----------------------------------------------------------------------------
54 // wxRadioBox event handler
55 // ----------------------------------------------------------------------------
57 class wxRadioHookHandler
: public wxEvtHandler
60 wxRadioHookHandler(wxRadioBox
*radio
) { m_radio
= radio
; }
62 virtual bool ProcessEvent(wxEvent
& event
)
64 // we intercept the command events from radio buttons
65 if ( event
.GetEventType() == wxEVT_COMMAND_RADIOBUTTON_SELECTED
)
67 m_radio
->OnRadioButton(event
);
69 else if ( event
.GetEventType() == wxEVT_KEY_DOWN
)
71 if ( m_radio
->OnKeyDown((wxKeyEvent
&)event
) )
78 return GetNextHandler()->ProcessEvent(event
);
85 // ============================================================================
87 // ============================================================================
89 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
)
91 // ----------------------------------------------------------------------------
92 // wxRadioBox creation
93 // ----------------------------------------------------------------------------
95 void wxRadioBox::Init()
100 wxRadioBox::wxRadioBox(wxWindow
*parent
, wxWindowID id
, const wxString
& title
,
101 const wxPoint
& pos
, const wxSize
& size
,
102 const wxArrayString
& choices
,
103 int majorDim
, long style
,
104 const wxValidator
& val
, const wxString
& name
)
106 wxCArrayString
chs(choices
);
110 (void)Create(parent
, id
, title
, pos
, size
, chs
.GetCount(),
111 chs
.GetStrings(), majorDim
, style
, val
, name
);
114 bool wxRadioBox::Create(wxWindow
*parent
,
116 const wxString
& title
,
119 const wxArrayString
& choices
,
122 const wxValidator
& val
,
123 const wxString
& name
)
125 wxCArrayString
chs(choices
);
127 return Create(parent
, id
, title
, pos
, size
, chs
.GetCount(),
128 chs
.GetStrings(), majorDim
, style
, val
, name
);
131 bool wxRadioBox::Create(wxWindow
*parent
,
133 const wxString
& title
,
137 const wxString
*choices
,
140 const wxValidator
& wxVALIDATOR_PARAM(val
),
141 const wxString
& name
)
143 // for compatibility with the other ports which don't handle (yet?)
144 // wxRA_LEFTTORIGHT and wxRA_TOPTOBOTTOM flags, we add them ourselves if
146 if ( !(style
& (wxRA_LEFTTORIGHT
| wxRA_TOPTOBOTTOM
)) )
148 // horizontal radiobox use left to right layout
149 if ( style
& wxRA_HORIZONTAL
)
151 style
|= wxRA_LEFTTORIGHT
;
153 else if ( style
& wxRA_VERTICAL
)
155 style
|= wxRA_TOPTOBOTTOM
;
159 wxFAIL_MSG( _T("you must specify wxRA_XXX style!") );
162 style
= wxRA_HORIZONTAL
| wxRA_LEFTTORIGHT
;
166 if ( !wxStaticBox::Create(parent
, id
, title
, pos
, size
, style
, name
) )
171 #endif // wxUSE_VALIDATORS
175 // majorDim default value is 0 which means make one row/column
176 SetMajorDim(majorDim
== 0 ? n
: majorDim
, style
);
178 if ( size
== wxDefaultSize
)
180 SetClientSize(DoGetBestClientSize());
183 // Need to move the radiobox in order to move the radio buttons
184 wxPoint actualPos
= GetPosition();
185 wxSize actualSize
= GetSize();
186 DoMoveWindow(actualPos
.x
, actualPos
.y
, actualSize
.x
, actualSize
.y
);
188 // radiobox should already have selection so select at least one item
194 wxRadioBox::~wxRadioBox()
196 // remove the event handlers we pushed on them from all buttons and delete
197 // the buttons themselves: this must be done as the user code expects them
198 // to disappear now and not some time later when they will be deleted by
199 // our (common) parent
200 size_t count
= m_buttons
.GetCount();
201 for ( size_t n
= 0; n
< count
; n
++ )
203 m_buttons
[n
]->PopEventHandler(true /* delete it */);
209 // ----------------------------------------------------------------------------
211 // ----------------------------------------------------------------------------
213 void wxRadioBox::Append(int count
, const wxString
*choices
)
218 wxWindow
*parent
= GetParent();
219 m_buttons
.Alloc(count
);
220 for ( int n
= 0; n
< count
; n
++ )
222 // make the first button in the box the start of new group by giving it
224 wxRadioButton
*btn
= new wxRadioButton(parent
, wxID_ANY
, choices
[n
],
227 n
== 0 ? wxRB_GROUP
: 0);
229 // we want to get the events from the buttons to translate it into
230 btn
->PushEventHandler(new wxRadioHookHandler(this));
235 // ----------------------------------------------------------------------------
237 // ----------------------------------------------------------------------------
239 void wxRadioBox::SetSelection(int n
)
241 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::SetSelection") );
245 wxRadioButton
*btn
= m_buttons
[n
];
247 // the selected button is always focused in the radiobox
250 // this will also unselect the previously selected button in our group
254 int wxRadioBox::GetSelection() const
259 void wxRadioBox::SendRadioEvent()
261 wxCHECK_RET( m_selection
!= -1, _T("no active radio button") );
263 wxCommandEvent
event(wxEVT_COMMAND_RADIOBOX_SELECTED
, GetId());
264 InitCommandEvent(event
);
265 event
.SetInt(m_selection
);
266 event
.SetString(GetString(m_selection
));
271 void wxRadioBox::OnRadioButton(wxEvent
& event
)
273 int n
= m_buttons
.Index((wxRadioButton
*)event
.GetEventObject());
274 wxCHECK_RET( n
!= wxNOT_FOUND
, _T("click from alien radio button") );
281 // ----------------------------------------------------------------------------
282 // methods forwarded to the buttons
283 // ----------------------------------------------------------------------------
285 wxString
wxRadioBox::GetString(int n
) const
287 wxCHECK_MSG( IsValid(n
), wxEmptyString
,
288 _T("invalid index in wxRadioBox::GetString") );
290 return m_buttons
[n
]->GetLabel();
293 void wxRadioBox::SetString(int n
, const wxString
& label
)
295 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::SetString") );
297 m_buttons
[n
]->SetLabel(label
);
300 bool wxRadioBox::Enable(int n
, bool enable
)
302 wxCHECK_MSG( IsValid(n
), false, _T("invalid index in wxRadioBox::Enable") );
304 return m_buttons
[n
]->Enable(enable
);
307 bool wxRadioBox::IsItemEnabled(int n
) const
309 wxCHECK_MSG( IsValid(n
), false, _T("invalid index in wxRadioBox::IsItemEnabled") );
311 return m_buttons
[n
]->IsEnabled();
314 bool wxRadioBox::Show(int n
, bool show
)
316 wxCHECK_MSG( IsValid(n
), false, _T("invalid index in wxRadioBox::Show") );
318 return m_buttons
[n
]->Show(show
);
321 bool wxRadioBox::IsItemShown(int n
) const
323 wxCHECK_MSG( IsValid(n
), false, _T("invalid index in wxRadioBox::IsItemShown") );
325 return m_buttons
[n
]->IsShown();
328 // ----------------------------------------------------------------------------
329 // methods forwarded to the static box
330 // ----------------------------------------------------------------------------
332 bool wxRadioBox::Enable(bool enable
)
334 if ( !wxStaticBox::Enable(enable
) )
337 // also enable/disable the buttons
338 size_t count
= m_buttons
.GetCount();
339 for ( size_t n
= 0; n
< count
; n
++ )
347 bool wxRadioBox::Show(bool show
)
349 if ( !wxStaticBox::Show(show
) )
352 // also show/hide the buttons
353 size_t count
= m_buttons
.GetCount();
354 for ( size_t n
= 0; n
< count
; n
++ )
362 wxString
wxRadioBox::GetLabel() const
364 return wxStaticBox::GetLabel();
367 void wxRadioBox::SetLabel(const wxString
& label
)
369 wxStaticBox::SetLabel(label
);
373 void wxRadioBox::DoSetToolTip(wxToolTip
*tooltip
)
375 wxControl::DoSetToolTip(tooltip
);
377 // Also set them for all Radio Buttons
378 size_t count
= m_buttons
.GetCount();
379 for ( size_t n
= 0; n
< count
; n
++ )
382 m_buttons
[n
]->SetToolTip(tooltip
->GetTip());
384 m_buttons
[n
]->SetToolTip(NULL
);
387 #endif // wxUSE_TOOLTIPS
389 // ----------------------------------------------------------------------------
390 // buttons positioning
391 // ----------------------------------------------------------------------------
393 wxSize
wxRadioBox::GetMaxButtonSize() const
395 int widthMax
, heightMax
, width
= 0, height
= 0;
396 widthMax
= heightMax
= 0;
398 int count
= GetCount();
399 for ( int n
= 0; n
< count
; n
++ )
401 m_buttons
[n
]->GetBestSize(&width
, &height
);
403 if ( width
> widthMax
)
405 if ( height
> heightMax
)
409 return wxSize(widthMax
+ BUTTON_BORDER_X
, heightMax
+ BUTTON_BORDER_Y
);
412 wxSize
wxRadioBox::DoGetBestClientSize() const
414 wxSize sizeBtn
= GetMaxButtonSize();
416 sizeBtn
.x
*= GetColumnCount();
417 sizeBtn
.y
*= GetRowCount();
419 // add a border around all buttons
420 sizeBtn
.x
+= 2*BOX_BORDER_X
;
421 sizeBtn
.y
+= 2*BOX_BORDER_Y
;
423 // account for the area taken by static box
424 wxRect rect
= GetBorderGeometry();
425 sizeBtn
.x
+= rect
.x
+ rect
.width
;
426 sizeBtn
.y
+= rect
.y
+ rect
.height
;
431 void wxRadioBox::DoMoveWindow(int x0
, int y0
, int width
, int height
)
433 wxStaticBox::DoMoveWindow(x0
, y0
, width
, height
);
435 wxSize sizeBtn
= GetMaxButtonSize();
436 wxPoint ptOrigin
= GetBoxAreaOrigin();
437 wxPoint clientOrigin
= GetParent() ? GetParent()->GetClientAreaOrigin() : wxPoint(0,0);
439 x0
+= ptOrigin
.x
+ BOX_BORDER_X
- clientOrigin
.x
;
440 y0
+= ptOrigin
.y
+ BOX_BORDER_Y
- clientOrigin
.y
;
445 int count
= GetCount();
446 for ( int n
= 0; n
< count
; n
++ )
448 m_buttons
[n
]->SetSize(x
, y
, sizeBtn
.x
, sizeBtn
.y
);
450 if ( GetWindowStyle() & wxRA_TOPTOBOTTOM
)
452 // from top to bottom
453 if ( (n
+ 1) % GetRowCount() )
455 // continue in this column
460 // start a new column
465 else // wxRA_LEFTTORIGHT: mirror the code above
467 // from left to right
468 if ( (n
+ 1) % GetColumnCount() )
470 // continue in this row
483 // ----------------------------------------------------------------------------
484 // keyboard navigation
485 // ----------------------------------------------------------------------------
487 bool wxRadioBox::OnKeyDown(wxKeyEvent
& event
)
490 switch ( event
.GetKeyCode() )
512 int selOld
= GetSelection();
513 int selNew
= GetNextItem(selOld
, dir
, GetWindowStyle());
514 if ( selNew
!= selOld
)
516 SetSelection(selNew
);
518 // emulate the button click
525 #endif // wxUSE_RADIOBOX