]> git.saurik.com Git - wxWidgets.git/blame - src/univ/radiobox.cpp
reSWIGged
[wxWidgets.git] / src / univ / radiobox.cpp
CommitLineData
1e6feb95
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: univ/radiobox.cpp
3// Purpose: wxRadioBox implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 11.09.00
7// RCS-ID: $Id$
442b35b5 8// Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
6aa89a22 9// Licence: wxWindows licence
1e6feb95
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
a3870b2f 21 #pragma implementation "univradiobox.h"
1e6feb95
VZ
22#endif
23
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
27 #pragma hdrstop
28#endif
29
30#if wxUSE_RADIOBOX
31
32#ifndef WX_PRECOMP
33 #include "wx/dcclient.h"
34 #include "wx/radiobox.h"
35 #include "wx/radiobut.h"
36 #include "wx/validate.h"
37#endif
38
d4e5272b
JS
39#include "wx/tooltip.h"
40
1e6feb95
VZ
41#include "wx/univ/theme.h"
42#include "wx/univ/renderer.h"
43#include "wx/univ/inphand.h"
44#include "wx/univ/colschem.h"
45
46// ----------------------------------------------------------------------------
47// constants
48// ----------------------------------------------------------------------------
49
50static const int BUTTON_BORDER_X = 2;
51static const int BUTTON_BORDER_Y = 4;
52
53static const int BOX_BORDER_X = 2;
54static const int BOX_BORDER_Y = 2;
55
56// ----------------------------------------------------------------------------
57// wxRadioBox event handler
58// ----------------------------------------------------------------------------
59
60class wxRadioHookHandler : public wxEvtHandler
61{
62public:
63 wxRadioHookHandler(wxRadioBox *radio) { m_radio = radio; }
64
65 virtual bool ProcessEvent(wxEvent& event)
66 {
67 // we intercept the command events from radio buttons
68 if ( event.GetEventType() == wxEVT_COMMAND_RADIOBUTTON_SELECTED )
69 {
70 m_radio->OnRadioButton(event);
71 }
72 else if ( event.GetEventType() == wxEVT_KEY_DOWN )
73 {
74 if ( m_radio->OnKeyDown((wxKeyEvent &)event) )
75 {
76 return TRUE;
77 }
78 }
79
80 // just pass it on
81 return GetNextHandler()->ProcessEvent(event);
82 }
83
84private:
85 wxRadioBox *m_radio;
86};
87
88// ============================================================================
89// implementation
90// ============================================================================
91
92IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
93
94// ----------------------------------------------------------------------------
95// wxRadioBox creation
96// ----------------------------------------------------------------------------
97
1169a919
JS
98wxRadioBox::wxRadioBox()
99{
100 Init();
101}
102
103wxRadioBox::wxRadioBox(wxWindow *parent,
104 wxWindowID id,
105 const wxString& title,
106 const wxPoint& pos,
107 const wxSize& size,
108 int n,
109 const wxString *choices,
110 int majorDim,
111 long style,
112 const wxValidator& val,
113 const wxString& name)
114{
115 Init();
116
117 (void)Create(parent, id, title, pos, size, n, choices, majorDim, style, val, name);
118}
119
1e6feb95
VZ
120void wxRadioBox::Init()
121{
122 m_selection = -1;
123 m_majorDim = 0;
124}
125
126bool wxRadioBox::Create(wxWindow *parent,
127 wxWindowID id,
128 const wxString& title,
129 const wxPoint& pos,
130 const wxSize& size,
131 int n,
132 const wxString *choices,
133 int majorDim,
134 long style,
135 const wxValidator& val,
136 const wxString& name)
137{
138 // for compatibility with the other ports which don't handle (yet?)
139 // wxRA_LEFTTORIGHT and wxRA_TOPTOBOTTOM flags, we add them ourselves if
140 // not specified
141 if ( !(style & (wxRA_LEFTTORIGHT | wxRA_TOPTOBOTTOM)) )
142 {
143 // horizontal radiobox use left to right layout
144 if ( style & wxRA_HORIZONTAL )
145 {
146 style |= wxRA_LEFTTORIGHT;
147 }
148 else if ( style & wxRA_VERTICAL )
149 {
150 style |= wxRA_TOPTOBOTTOM;
151 }
152 else
153 {
154 wxFAIL_MSG( _T("you must specify wxRA_XXX style!") );
155
156 // use default
157 style = wxRA_HORIZONTAL | wxRA_LEFTTORIGHT;
158 }
159 }
160
161 if ( !wxStaticBox::Create(parent, id, title, pos, size, style, name) )
162 return FALSE;
163
164#if wxUSE_VALIDATORS
165 SetValidator(val);
166#endif // wxUSE_VALIDATORS
167
168 Append(n, choices);
169
170 // majorDim default value is 0 which means make one row/column
171 SetMajorDim(majorDim == 0 ? n : majorDim);
172
173 if ( size == wxDefaultSize )
174 {
175 SetClientSize(DoGetBestClientSize());
176 }
177
d2699196
JS
178 // Need to move the radiobox in order to move the radio buttons
179 wxPoint actualPos = GetPosition();
180 wxSize actualSize = GetSize();
181 DoMoveWindow(actualPos.x, actualPos.y, actualSize.x, actualSize.y);
182
1e6feb95
VZ
183 // radiobox should already have selection so select at least one item
184 SetSelection(0);
185
186 return TRUE;
187}
188
189wxRadioBox::~wxRadioBox()
190{
191 // remove the event handlers we pushed on them from all buttons and delete
192 // the buttons themselves: this must be done as the user code expects them
193 // to disappear now and not some time later when they will be deleted by
194 // our (common) parent
195 size_t count = m_buttons.GetCount();
196 for ( size_t n = 0; n < count; n++ )
197 {
198 m_buttons[n]->PopEventHandler(TRUE /* delete it */);
199
200 delete m_buttons[n];
201 }
202}
203
204// ----------------------------------------------------------------------------
205// wxRadioBox init
206// ----------------------------------------------------------------------------
207
208void wxRadioBox::SetMajorDim(int majorDim)
209{
210 wxCHECK_RET( majorDim != 0, _T("major radiobox dimension can't be 0") );
211
212 m_majorDim = majorDim;
213
214 int minorDim = (GetCount() + m_majorDim - 1) / m_majorDim;
215
216 if ( GetWindowStyle() & wxRA_SPECIFY_COLS )
217 {
218 m_numCols = majorDim;
219 m_numRows = minorDim;
220 }
221 else // wxRA_SPECIFY_ROWS
222 {
223 m_numCols = minorDim;
224 m_numRows = majorDim;
225 }
226}
227
228void wxRadioBox::Append(int count, const wxString *choices)
229{
230 if ( !count )
231 return;
232
233 wxWindow *parent = GetParent();
234 m_buttons.Alloc(count);
235 for ( int n = 0; n < count; n++ )
236 {
237 // make the first button in the box the start of new group by giving it
238 // wxRB_GROUP style
239 wxRadioButton *btn = new wxRadioButton(parent, -1, choices[n],
240 wxDefaultPosition,
241 wxDefaultSize,
242 n == 0 ? wxRB_GROUP : 0);
243
244 // we want to get the events from the buttons to translate it into
245 btn->PushEventHandler(new wxRadioHookHandler(this));
246 m_buttons.Add(btn);
247 }
248}
249
250// ----------------------------------------------------------------------------
251// selection
252// ----------------------------------------------------------------------------
253
254void wxRadioBox::SetSelection(int n)
255{
256 wxCHECK_RET( IsValid(n), _T("invalid index in wxRadioBox::SetSelection") );
257
258 m_selection = n;
259
260 wxRadioButton *btn = m_buttons[n];
261
262 // the selected button is always focused in the radiobox
263 btn->SetFocus();
264
265 // this will also unselect the previously selected button in our group
266 btn->SetValue(TRUE);
267}
268
269int wxRadioBox::GetSelection() const
270{
271 return m_selection;
272}
273
274void wxRadioBox::SendRadioEvent()
275{
276 wxCHECK_RET( m_selection != -1, _T("no active radio button") );
277
278 wxCommandEvent event(wxEVT_COMMAND_RADIOBOX_SELECTED, GetId());
279 InitCommandEvent(event);
280 event.SetInt(m_selection);
281 event.SetString(GetString(m_selection));
282
283 Command(event);
284}
285
286void wxRadioBox::OnRadioButton(wxEvent& event)
287{
288 int n = m_buttons.Index((wxRadioButton *)event.GetEventObject());
289 wxCHECK_RET( n != wxNOT_FOUND, _T("click from alien radio button") );
290
291 m_selection = n;
292
293 SendRadioEvent();
294}
295
296// ----------------------------------------------------------------------------
297// methods forwarded to the buttons
298// ----------------------------------------------------------------------------
299
300wxString wxRadioBox::GetString(int n) const
301{
302 wxCHECK_MSG( IsValid(n), _T(""),
303 _T("invalid index in wxRadioBox::GetString") );
304
305 return m_buttons[n]->GetLabel();
306}
307
308void wxRadioBox::SetString(int n, const wxString& label)
309{
310 wxCHECK_RET( IsValid(n), _T("invalid index in wxRadioBox::SetString") );
311
312 m_buttons[n]->SetLabel(label);
313}
314
315void wxRadioBox::Enable(int n, bool enable)
316{
317 wxCHECK_RET( IsValid(n), _T("invalid index in wxRadioBox::Enable") );
318
319 m_buttons[n]->Enable(enable);
320}
321
322void wxRadioBox::Show(int n, bool show)
323{
324 wxCHECK_RET( IsValid(n), _T("invalid index in wxRadioBox::Show") );
325
326 m_buttons[n]->Show(show);
327}
328
329// ----------------------------------------------------------------------------
330// methods forwarded to the static box
331// ----------------------------------------------------------------------------
332
333bool wxRadioBox::Enable(bool enable)
334{
528a5fe4
VZ
335 if ( !wxStaticBox::Enable(enable) )
336 return FALSE;
337
338 // also enable/disable the buttons
339 size_t count = m_buttons.GetCount();
340 for ( size_t n = 0; n < count; n++ )
341 {
342 Enable(n, enable);
343 }
344
345 return TRUE;
1e6feb95
VZ
346}
347
348bool wxRadioBox::Show(bool show)
349{
528a5fe4
VZ
350 if ( !wxStaticBox::Show(show) )
351 return FALSE;
352
353 // also show/hide the buttons
354 size_t count = m_buttons.GetCount();
355 for ( size_t n = 0; n < count; n++ )
356 {
357 Show(n, show);
358 }
359
360 return TRUE;
1e6feb95
VZ
361}
362
363wxString wxRadioBox::GetLabel() const
364{
365 return wxStaticBox::GetLabel();
366}
367
368void wxRadioBox::SetLabel(const wxString& label)
369{
370 wxStaticBox::SetLabel(label);
371}
372
d4e5272b
JS
373#if wxUSE_TOOLTIPS
374void wxRadioBox::DoSetToolTip(wxToolTip *tooltip)
375{
376 wxControl::DoSetToolTip(tooltip);
377
378 // Also set them for all Radio Buttons
379 size_t count = m_buttons.GetCount();
380 for ( size_t n = 0; n < count; n++ )
381 {
382 if (tooltip)
383 m_buttons[n]->SetToolTip(tooltip->GetTip());
384 else
385 m_buttons[n]->SetToolTip(NULL);
386 }
387}
388#endif // wxUSE_TOOLTIPS
389
1e6feb95
VZ
390// ----------------------------------------------------------------------------
391// buttons positioning
392// ----------------------------------------------------------------------------
393
394wxSize wxRadioBox::GetMaxButtonSize() const
395{
396 int widthMax, heightMax, width, height;
397 widthMax = heightMax = 0;
398
399 int count = GetCount();
400 for ( int n = 0; n < count; n++ )
401 {
402 m_buttons[n]->GetBestSize(&width, &height);
403
404 if ( width > widthMax )
405 widthMax = width;
406 if ( height > heightMax )
407 heightMax = height;
408 }
409
410 return wxSize(widthMax + BUTTON_BORDER_X, heightMax + BUTTON_BORDER_Y);
411}
412
413wxSize wxRadioBox::DoGetBestClientSize() const
414{
415 wxSize sizeBtn = GetMaxButtonSize();
416
417 sizeBtn.x *= m_numCols;
418 sizeBtn.y *= m_numRows;
419
420 // add a border around all buttons
421 sizeBtn.x += 2*BOX_BORDER_X;
422 sizeBtn.y += 2*BOX_BORDER_Y;
423
424 // account for the area taken by static box
425 wxRect rect = GetBorderGeometry();
426 sizeBtn.x += rect.x + rect.width;
427 sizeBtn.y += rect.y + rect.height;
428
429 return sizeBtn;
430}
431
432void wxRadioBox::DoMoveWindow(int x0, int y0, int width, int height)
433{
434 wxStaticBox::DoMoveWindow(x0, y0, width, height);
435
436 wxSize sizeBtn = GetMaxButtonSize();
437 wxPoint ptOrigin = GetBoxAreaOrigin();
e3f3984b 438 wxPoint clientOrigin = GetParent() ? GetParent()->GetClientAreaOrigin() : wxPoint(0,0);
1e6feb95 439
e3f3984b
VS
440 x0 += ptOrigin.x + BOX_BORDER_X - clientOrigin.x;
441 y0 += ptOrigin.y + BOX_BORDER_Y - clientOrigin.y;
1e6feb95
VZ
442
443 int x = x0,
444 y = y0;
445
446 int count = GetCount();
447 for ( int n = 0; n < count; n++ )
448 {
449 m_buttons[n]->SetSize(x, y, sizeBtn.x, sizeBtn.y);
450
451 if ( GetWindowStyle() & wxRA_TOPTOBOTTOM )
452 {
453 // from top to bottom
454 if ( (n + 1) % m_numRows )
455 {
456 // continue in this column
457 y += sizeBtn.y;
458 }
459 else
460 {
461 // start a new column
462 x += sizeBtn.x;
463 y = y0;
464 }
465 }
466 else // wxRA_LEFTTORIGHT: mirror the code above
467 {
468 // from left to right
469 if ( (n + 1) % m_numCols )
470 {
471 // continue in this row
472 x += sizeBtn.x;
473 }
474 else
475 {
476 // start a new row
477 y += sizeBtn.y;
478 x = x0;
479 }
480 }
481 }
482}
483
484// ----------------------------------------------------------------------------
485// keyboard navigation
486// ----------------------------------------------------------------------------
487
488bool wxRadioBox::OnKeyDown(wxKeyEvent& event)
489{
490 wxDirection dir;
491 switch ( event.GetKeyCode() )
492 {
493 case WXK_UP:
494 dir = wxUP;
495 break;
496
497 case WXK_LEFT:
498 dir = wxLEFT;
499 break;
500
501 case WXK_DOWN:
502 dir = wxDOWN;
503 break;
504
505 case WXK_RIGHT:
506 dir = wxRIGHT;
507 break;
508
509 default:
510 return FALSE;
511 }
512
513 int selOld = GetSelection();
514 int selNew = GetNextItem(selOld, dir, GetWindowStyle());
515 if ( selNew != selOld )
516 {
517 SetSelection(selNew);
518
519 // emulate the button click
520 SendRadioEvent();
521 }
522
523 return TRUE;
524}
525
526#endif // wxUSE_RADIOBOX
527