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 license
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
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"
39 #include "wx/univ/theme.h"
40 #include "wx/univ/renderer.h"
41 #include "wx/univ/inphand.h"
42 #include "wx/univ/colschem.h"
44 // ----------------------------------------------------------------------------
46 // ----------------------------------------------------------------------------
48 static const int BUTTON_BORDER_X
= 2;
49 static const int BUTTON_BORDER_Y
= 4;
51 static const int BOX_BORDER_X
= 2;
52 static const int BOX_BORDER_Y
= 2;
54 // ----------------------------------------------------------------------------
55 // wxRadioBox event handler
56 // ----------------------------------------------------------------------------
58 class wxRadioHookHandler
: public wxEvtHandler
61 wxRadioHookHandler(wxRadioBox
*radio
) { m_radio
= radio
; }
63 virtual bool ProcessEvent(wxEvent
& event
)
65 // we intercept the command events from radio buttons
66 if ( event
.GetEventType() == wxEVT_COMMAND_RADIOBUTTON_SELECTED
)
68 m_radio
->OnRadioButton(event
);
70 else if ( event
.GetEventType() == wxEVT_KEY_DOWN
)
72 if ( m_radio
->OnKeyDown((wxKeyEvent
&)event
) )
79 return GetNextHandler()->ProcessEvent(event
);
86 // ============================================================================
88 // ============================================================================
90 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
)
92 // ----------------------------------------------------------------------------
93 // wxRadioBox creation
94 // ----------------------------------------------------------------------------
96 void wxRadioBox::Init()
102 bool wxRadioBox::Create(wxWindow
*parent
,
104 const wxString
& title
,
108 const wxString
*choices
,
111 const wxValidator
& val
,
112 const wxString
& name
)
114 // for compatibility with the other ports which don't handle (yet?)
115 // wxRA_LEFTTORIGHT and wxRA_TOPTOBOTTOM flags, we add them ourselves if
117 if ( !(style
& (wxRA_LEFTTORIGHT
| wxRA_TOPTOBOTTOM
)) )
119 // horizontal radiobox use left to right layout
120 if ( style
& wxRA_HORIZONTAL
)
122 style
|= wxRA_LEFTTORIGHT
;
124 else if ( style
& wxRA_VERTICAL
)
126 style
|= wxRA_TOPTOBOTTOM
;
130 wxFAIL_MSG( _T("you must specify wxRA_XXX style!") );
133 style
= wxRA_HORIZONTAL
| wxRA_LEFTTORIGHT
;
137 if ( !wxStaticBox::Create(parent
, id
, title
, pos
, size
, style
, name
) )
142 #endif // wxUSE_VALIDATORS
146 // majorDim default value is 0 which means make one row/column
147 SetMajorDim(majorDim
== 0 ? n
: majorDim
);
149 if ( size
== wxDefaultSize
)
151 SetClientSize(DoGetBestClientSize());
154 // radiobox should already have selection so select at least one item
160 wxRadioBox::~wxRadioBox()
162 // remove the event handlers we pushed on them from all buttons and delete
163 // the buttons themselves: this must be done as the user code expects them
164 // to disappear now and not some time later when they will be deleted by
165 // our (common) parent
166 size_t count
= m_buttons
.GetCount();
167 for ( size_t n
= 0; n
< count
; n
++ )
169 m_buttons
[n
]->PopEventHandler(TRUE
/* delete it */);
175 // ----------------------------------------------------------------------------
177 // ----------------------------------------------------------------------------
179 void wxRadioBox::SetMajorDim(int majorDim
)
181 wxCHECK_RET( majorDim
!= 0, _T("major radiobox dimension can't be 0") );
183 m_majorDim
= majorDim
;
185 int minorDim
= (GetCount() + m_majorDim
- 1) / m_majorDim
;
187 if ( GetWindowStyle() & wxRA_SPECIFY_COLS
)
189 m_numCols
= majorDim
;
190 m_numRows
= minorDim
;
192 else // wxRA_SPECIFY_ROWS
194 m_numCols
= minorDim
;
195 m_numRows
= majorDim
;
199 void wxRadioBox::Append(int count
, const wxString
*choices
)
204 wxWindow
*parent
= GetParent();
205 m_buttons
.Alloc(count
);
206 for ( int n
= 0; n
< count
; n
++ )
208 // make the first button in the box the start of new group by giving it
210 wxRadioButton
*btn
= new wxRadioButton(parent
, -1, choices
[n
],
213 n
== 0 ? wxRB_GROUP
: 0);
215 // we want to get the events from the buttons to translate it into
216 btn
->PushEventHandler(new wxRadioHookHandler(this));
221 // ----------------------------------------------------------------------------
223 // ----------------------------------------------------------------------------
225 void wxRadioBox::SetSelection(int n
)
227 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::SetSelection") );
231 wxRadioButton
*btn
= m_buttons
[n
];
233 // the selected button is always focused in the radiobox
236 // this will also unselect the previously selected button in our group
240 int wxRadioBox::GetSelection() const
245 void wxRadioBox::SendRadioEvent()
247 wxCHECK_RET( m_selection
!= -1, _T("no active radio button") );
249 wxCommandEvent
event(wxEVT_COMMAND_RADIOBOX_SELECTED
, GetId());
250 InitCommandEvent(event
);
251 event
.SetInt(m_selection
);
252 event
.SetString(GetString(m_selection
));
257 void wxRadioBox::OnRadioButton(wxEvent
& event
)
259 int n
= m_buttons
.Index((wxRadioButton
*)event
.GetEventObject());
260 wxCHECK_RET( n
!= wxNOT_FOUND
, _T("click from alien radio button") );
267 // ----------------------------------------------------------------------------
268 // methods forwarded to the buttons
269 // ----------------------------------------------------------------------------
271 wxString
wxRadioBox::GetString(int n
) const
273 wxCHECK_MSG( IsValid(n
), _T(""),
274 _T("invalid index in wxRadioBox::GetString") );
276 return m_buttons
[n
]->GetLabel();
279 void wxRadioBox::SetString(int n
, const wxString
& label
)
281 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::SetString") );
283 m_buttons
[n
]->SetLabel(label
);
286 void wxRadioBox::Enable(int n
, bool enable
)
288 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::Enable") );
290 m_buttons
[n
]->Enable(enable
);
293 void wxRadioBox::Show(int n
, bool show
)
295 wxCHECK_RET( IsValid(n
), _T("invalid index in wxRadioBox::Show") );
297 m_buttons
[n
]->Show(show
);
300 // ----------------------------------------------------------------------------
301 // methods forwarded to the static box
302 // ----------------------------------------------------------------------------
304 bool wxRadioBox::Enable(bool enable
)
306 if ( !wxStaticBox::Enable(enable
) )
309 // also enable/disable the buttons
310 size_t count
= m_buttons
.GetCount();
311 for ( size_t n
= 0; n
< count
; n
++ )
319 bool wxRadioBox::Show(bool show
)
321 if ( !wxStaticBox::Show(show
) )
324 // also show/hide the buttons
325 size_t count
= m_buttons
.GetCount();
326 for ( size_t n
= 0; n
< count
; n
++ )
334 wxString
wxRadioBox::GetLabel() const
336 return wxStaticBox::GetLabel();
339 void wxRadioBox::SetLabel(const wxString
& label
)
341 wxStaticBox::SetLabel(label
);
344 // ----------------------------------------------------------------------------
345 // buttons positioning
346 // ----------------------------------------------------------------------------
348 wxSize
wxRadioBox::GetMaxButtonSize() const
350 int widthMax
, heightMax
, width
, height
;
351 widthMax
= heightMax
= 0;
353 int count
= GetCount();
354 for ( int n
= 0; n
< count
; n
++ )
356 m_buttons
[n
]->GetBestSize(&width
, &height
);
358 if ( width
> widthMax
)
360 if ( height
> heightMax
)
364 return wxSize(widthMax
+ BUTTON_BORDER_X
, heightMax
+ BUTTON_BORDER_Y
);
367 wxSize
wxRadioBox::DoGetBestClientSize() const
369 wxSize sizeBtn
= GetMaxButtonSize();
371 sizeBtn
.x
*= m_numCols
;
372 sizeBtn
.y
*= m_numRows
;
374 // add a border around all buttons
375 sizeBtn
.x
+= 2*BOX_BORDER_X
;
376 sizeBtn
.y
+= 2*BOX_BORDER_Y
;
378 // account for the area taken by static box
379 wxRect rect
= GetBorderGeometry();
380 sizeBtn
.x
+= rect
.x
+ rect
.width
;
381 sizeBtn
.y
+= rect
.y
+ rect
.height
;
386 void wxRadioBox::DoMoveWindow(int x0
, int y0
, int width
, int height
)
388 wxStaticBox::DoMoveWindow(x0
, y0
, width
, height
);
390 wxSize sizeBtn
= GetMaxButtonSize();
391 wxPoint ptOrigin
= GetBoxAreaOrigin();
392 wxPoint clientOrigin
= GetParent() ? GetParent()->GetClientAreaOrigin() : wxPoint(0,0);
394 x0
+= ptOrigin
.x
+ BOX_BORDER_X
- clientOrigin
.x
;
395 y0
+= ptOrigin
.y
+ BOX_BORDER_Y
- clientOrigin
.y
;
400 int count
= GetCount();
401 for ( int n
= 0; n
< count
; n
++ )
403 m_buttons
[n
]->SetSize(x
, y
, sizeBtn
.x
, sizeBtn
.y
);
405 if ( GetWindowStyle() & wxRA_TOPTOBOTTOM
)
407 // from top to bottom
408 if ( (n
+ 1) % m_numRows
)
410 // continue in this column
415 // start a new column
420 else // wxRA_LEFTTORIGHT: mirror the code above
422 // from left to right
423 if ( (n
+ 1) % m_numCols
)
425 // continue in this row
438 // ----------------------------------------------------------------------------
439 // keyboard navigation
440 // ----------------------------------------------------------------------------
442 bool wxRadioBox::OnKeyDown(wxKeyEvent
& event
)
445 switch ( event
.GetKeyCode() )
467 int selOld
= GetSelection();
468 int selNew
= GetNextItem(selOld
, dir
, GetWindowStyle());
469 if ( selNew
!= selOld
)
471 SetSelection(selNew
);
473 // emulate the button click
480 #endif // wxUSE_RADIOBOX