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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "univradiobox.h"
24 #include "wx/wxprec.h"
33 #include "wx/dcclient.h"
34 #include "wx/radiobox.h"
35 #include "wx/radiobut.h"
36 #include "wx/validate.h"
37 #include "wx/arrstr.h"
40 #include "wx/tooltip.h"
42 #include "wx/univ/theme.h"
43 #include "wx/univ/renderer.h"
44 #include "wx/univ/inphand.h"
45 #include "wx/univ/colschem.h"
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 static const int BUTTON_BORDER_X
= 2;
52 static const int BUTTON_BORDER_Y
= 4;
54 static const int BOX_BORDER_X
= 2;
55 static const int BOX_BORDER_Y
= 2;
57 // ----------------------------------------------------------------------------
58 // wxRadioBox event handler
59 // ----------------------------------------------------------------------------
61 class wxRadioHookHandler
: public wxEvtHandler
64 wxRadioHookHandler(wxRadioBox
*radio
) { m_radio
= radio
; }
66 virtual bool ProcessEvent(wxEvent
& event
)
68 // we intercept the command events from radio buttons
69 if ( event
.GetEventType() == wxEVT_COMMAND_RADIOBUTTON_SELECTED
)
71 m_radio
->OnRadioButton(event
);
73 else if ( event
.GetEventType() == wxEVT_KEY_DOWN
)
75 if ( m_radio
->OnKeyDown((wxKeyEvent
&)event
) )
82 return GetNextHandler()->ProcessEvent(event
);
89 // ============================================================================
91 // ============================================================================
93 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
)
95 // ----------------------------------------------------------------------------
96 // wxRadioBox creation
97 // ----------------------------------------------------------------------------
99 void wxRadioBox::Init()
105 wxRadioBox::wxRadioBox(wxWindow
*parent
, wxWindowID id
, const wxString
& title
,
106 const wxPoint
& pos
, const wxSize
& size
,
107 const wxArrayString
& choices
,
108 int majorDim
, long style
,
109 const wxValidator
& val
, const wxString
& name
)
111 wxCArrayString
chs(choices
);
115 (void)Create(parent
, id
, title
, pos
, size
, chs
.GetCount(),
116 chs
.GetStrings(), majorDim
, style
, val
, name
);
119 bool wxRadioBox::Create(wxWindow
*parent
,
121 const wxString
& title
,
124 const wxArrayString
& choices
,
127 const wxValidator
& val
,
128 const wxString
& name
)
130 wxCArrayString
chs(choices
);
132 return Create(parent
, id
, title
, pos
, size
, chs
.GetCount(),
133 chs
.GetStrings(), majorDim
, style
, val
, name
);
136 bool wxRadioBox::Create(wxWindow
*parent
,
138 const wxString
& title
,
142 const wxString
*choices
,
145 const wxValidator
& val
,
146 const wxString
& name
)
148 // for compatibility with the other ports which don't handle (yet?)
149 // wxRA_LEFTTORIGHT and wxRA_TOPTOBOTTOM flags, we add them ourselves if
151 if ( !(style
& (wxRA_LEFTTORIGHT
| wxRA_TOPTOBOTTOM
)) )
153 // horizontal radiobox use left to right layout
154 if ( style
& wxRA_HORIZONTAL
)
156 style
|= wxRA_LEFTTORIGHT
;
158 else if ( style
& wxRA_VERTICAL
)
160 style
|= wxRA_TOPTOBOTTOM
;
164 wxFAIL_MSG( _T("you must specify wxRA_XXX style!") );
167 style
= wxRA_HORIZONTAL
| wxRA_LEFTTORIGHT
;
171 if ( !wxStaticBox::Create(parent
, id
, title
, pos
, size
, style
, name
) )
176 #endif // wxUSE_VALIDATORS
180 // majorDim default value is 0 which means make one row/column
181 SetMajorDim(majorDim
== 0 ? n
: majorDim
);
183 if ( size
== wxDefaultSize
)
185 SetClientSize(DoGetBestClientSize());
188 // Need to move the radiobox in order to move the radio buttons
189 wxPoint actualPos
= GetPosition();
190 wxSize actualSize
= GetSize();
191 DoMoveWindow(actualPos
.x
, actualPos
.y
, actualSize
.x
, actualSize
.y
);
193 // radiobox should already have selection so select at least one item
199 wxRadioBox::~wxRadioBox()
201 // remove the event handlers we pushed on them from all buttons and delete
202 // the buttons themselves: this must be done as the user code expects them
203 // to disappear now and not some time later when they will be deleted by
204 // our (common) parent
205 size_t count
= m_buttons
.GetCount();
206 for ( size_t n
= 0; n
< count
; n
++ )
208 m_buttons
[n
]->PopEventHandler(TRUE
/* delete it */);
214 // ----------------------------------------------------------------------------
216 // ----------------------------------------------------------------------------
218 void wxRadioBox::SetMajorDim(int majorDim
)
220 wxCHECK_RET( majorDim
!= 0, _T("major radiobox dimension can't be 0") );
222 m_majorDim
= majorDim
;
224 int minorDim
= (GetCount() + m_majorDim
- 1) / m_majorDim
;
226 if ( GetWindowStyle() & wxRA_SPECIFY_COLS
)
228 m_numCols
= majorDim
;
229 m_numRows
= minorDim
;
231 else // wxRA_SPECIFY_ROWS
233 m_numCols
= minorDim
;
234 m_numRows
= majorDim
;
238 void wxRadioBox::Append(int count
, const wxString
*choices
)
243 wxWindow
*parent
= GetParent();
244 m_buttons
.Alloc(count
);
245 for ( int n
= 0; n
< count
; n
++ )
247 // make the first button in the box the start of new group by giving it
249 wxRadioButton
*btn
= new wxRadioButton(parent
, -1, choices
[n
],
252 n
== 0 ? wxRB_GROUP
: 0);
254 // we want to get the events from the buttons to translate it into
255 btn
->PushEventHandler(new wxRadioHookHandler(this));
260 // ----------------------------------------------------------------------------
262 // ----------------------------------------------------------------------------
264 void wxRadioBox::SetSelection(int n
)
266 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::SetSelection") );
270 wxRadioButton
*btn
= m_buttons
[n
];
272 // the selected button is always focused in the radiobox
275 // this will also unselect the previously selected button in our group
279 int wxRadioBox::GetSelection() const
284 void wxRadioBox::SendRadioEvent()
286 wxCHECK_RET( m_selection
!= -1, _T("no active radio button") );
288 wxCommandEvent
event(wxEVT_COMMAND_RADIOBOX_SELECTED
, GetId());
289 InitCommandEvent(event
);
290 event
.SetInt(m_selection
);
291 event
.SetString(GetString(m_selection
));
296 void wxRadioBox::OnRadioButton(wxEvent
& event
)
298 int n
= m_buttons
.Index((wxRadioButton
*)event
.GetEventObject());
299 wxCHECK_RET( n
!= wxNOT_FOUND
, _T("click from alien radio button") );
306 // ----------------------------------------------------------------------------
307 // methods forwarded to the buttons
308 // ----------------------------------------------------------------------------
310 wxString
wxRadioBox::GetString(int n
) const
312 wxCHECK_MSG( IsValid(n
), _T(""),
313 _T("invalid index in wxRadioBox::GetString") );
315 return m_buttons
[n
]->GetLabel();
318 void wxRadioBox::SetString(int n
, const wxString
& label
)
320 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::SetString") );
322 m_buttons
[n
]->SetLabel(label
);
325 void wxRadioBox::Enable(int n
, bool enable
)
327 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::Enable") );
329 m_buttons
[n
]->Enable(enable
);
332 void wxRadioBox::Show(int n
, bool show
)
334 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::Show") );
336 m_buttons
[n
]->Show(show
);
339 // ----------------------------------------------------------------------------
340 // methods forwarded to the static box
341 // ----------------------------------------------------------------------------
343 bool wxRadioBox::Enable(bool enable
)
345 if ( !wxStaticBox::Enable(enable
) )
348 // also enable/disable the buttons
349 size_t count
= m_buttons
.GetCount();
350 for ( size_t n
= 0; n
< count
; n
++ )
358 bool wxRadioBox::Show(bool show
)
360 if ( !wxStaticBox::Show(show
) )
363 // also show/hide the buttons
364 size_t count
= m_buttons
.GetCount();
365 for ( size_t n
= 0; n
< count
; n
++ )
373 wxString
wxRadioBox::GetLabel() const
375 return wxStaticBox::GetLabel();
378 void wxRadioBox::SetLabel(const wxString
& label
)
380 wxStaticBox::SetLabel(label
);
384 void wxRadioBox::DoSetToolTip(wxToolTip
*tooltip
)
386 wxControl::DoSetToolTip(tooltip
);
388 // Also set them for all Radio Buttons
389 size_t count
= m_buttons
.GetCount();
390 for ( size_t n
= 0; n
< count
; n
++ )
393 m_buttons
[n
]->SetToolTip(tooltip
->GetTip());
395 m_buttons
[n
]->SetToolTip(NULL
);
398 #endif // wxUSE_TOOLTIPS
400 // ----------------------------------------------------------------------------
401 // buttons positioning
402 // ----------------------------------------------------------------------------
404 wxSize
wxRadioBox::GetMaxButtonSize() const
406 int widthMax
, heightMax
, width
, height
;
407 widthMax
= heightMax
= 0;
409 int count
= GetCount();
410 for ( int n
= 0; n
< count
; n
++ )
412 m_buttons
[n
]->GetBestSize(&width
, &height
);
414 if ( width
> widthMax
)
416 if ( height
> heightMax
)
420 return wxSize(widthMax
+ BUTTON_BORDER_X
, heightMax
+ BUTTON_BORDER_Y
);
423 wxSize
wxRadioBox::DoGetBestClientSize() const
425 wxSize sizeBtn
= GetMaxButtonSize();
427 sizeBtn
.x
*= m_numCols
;
428 sizeBtn
.y
*= m_numRows
;
430 // add a border around all buttons
431 sizeBtn
.x
+= 2*BOX_BORDER_X
;
432 sizeBtn
.y
+= 2*BOX_BORDER_Y
;
434 // account for the area taken by static box
435 wxRect rect
= GetBorderGeometry();
436 sizeBtn
.x
+= rect
.x
+ rect
.width
;
437 sizeBtn
.y
+= rect
.y
+ rect
.height
;
442 void wxRadioBox::DoMoveWindow(int x0
, int y0
, int width
, int height
)
444 wxStaticBox::DoMoveWindow(x0
, y0
, width
, height
);
446 wxSize sizeBtn
= GetMaxButtonSize();
447 wxPoint ptOrigin
= GetBoxAreaOrigin();
448 wxPoint clientOrigin
= GetParent() ? GetParent()->GetClientAreaOrigin() : wxPoint(0,0);
450 x0
+= ptOrigin
.x
+ BOX_BORDER_X
- clientOrigin
.x
;
451 y0
+= ptOrigin
.y
+ BOX_BORDER_Y
- clientOrigin
.y
;
456 int count
= GetCount();
457 for ( int n
= 0; n
< count
; n
++ )
459 m_buttons
[n
]->SetSize(x
, y
, sizeBtn
.x
, sizeBtn
.y
);
461 if ( GetWindowStyle() & wxRA_TOPTOBOTTOM
)
463 // from top to bottom
464 if ( (n
+ 1) % m_numRows
)
466 // continue in this column
471 // start a new column
476 else // wxRA_LEFTTORIGHT: mirror the code above
478 // from left to right
479 if ( (n
+ 1) % m_numCols
)
481 // continue in this row
494 // ----------------------------------------------------------------------------
495 // keyboard navigation
496 // ----------------------------------------------------------------------------
498 bool wxRadioBox::OnKeyDown(wxKeyEvent
& event
)
501 switch ( event
.GetKeyCode() )
523 int selOld
= GetSelection();
524 int selNew
= GetNextItem(selOld
, dir
, GetWindowStyle());
525 if ( selNew
!= selOld
)
527 SetSelection(selNew
);
529 // emulate the button click
536 #endif // wxUSE_RADIOBOX