]> git.saurik.com Git - wxWidgets.git/blame - src/msw/radiobut.cpp
fixed wxBase and GUI separation for sockets code
[wxWidgets.git] / src / msw / radiobut.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
1e6feb95 2// Name: msw/radiobut.cpp
2bda0e17
KB
3// Purpose: wxRadioButton
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa
JS
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
5f199b71
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
c9baf9d7 21#pragma implementation "radiobut.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
c9baf9d7 28#pragma hdrstop
2bda0e17
KB
29#endif
30
1e6feb95
VZ
31#if wxUSE_RADIOBTN
32
2bda0e17 33#ifndef WX_PRECOMP
c9baf9d7
RL
34#include "wx/radiobut.h"
35#include "wx/settings.h"
36#include "wx/brush.h"
37#include "wx/dcscreen.h"
2bda0e17
KB
38#endif
39
40#include "wx/msw/private.h"
41
5f199b71
VZ
42// ============================================================================
43// wxRadioButton implementation
44// ============================================================================
45
46// ----------------------------------------------------------------------------
47// wxRadioButton creation
48// ----------------------------------------------------------------------------
49
2bda0e17 50IMPLEMENT_DYNAMIC_CLASS(wxRadioButton, wxControl)
2bda0e17 51
066f1b7a
SC
52/*
53 TODO PROPERTIES
54
55 label
56 value (bool , 0 )
57*/
58
5f199b71 59void wxRadioButton::Init()
621793f4 60{
5f199b71 61 m_focusJustSet = FALSE;
621793f4
JS
62}
63
5f199b71
VZ
64bool wxRadioButton::Create(wxWindow *parent,
65 wxWindowID id,
66 const wxString& label,
67 const wxPoint& pos,
68 const wxSize& size,
69 long style,
70 const wxValidator& validator,
71 const wxString& name)
2bda0e17 72{
5f199b71
VZ
73 if ( !CreateControl(parent, id, pos, size, style, validator, name) )
74 return FALSE;
2bda0e17 75
2b5f62a0
VZ
76 long msStyle = WS_TABSTOP;
77 if ( HasFlag(wxRB_GROUP) )
78 msStyle |= WS_GROUP;
79
80 /*
81 wxRB_SINGLE is a temporary workaround for the following problem: if you
82 have 2 radiobuttons in the same group but which are not consecutive in
83 the dialog, Windows can enter an infinite loop! The simplest way to
84 reproduce it is to create radio button, then a panel and then another
85 radio button: then checking the last button hangs the app.
2bda0e17 86
2b5f62a0
VZ
87 Ideally, we'd detect (and avoid) such situation automatically but for
88 now, as I don't know how to do it, just allow the user to create
89 BS_RADIOBUTTON buttons for such situations.
90 */
91 msStyle |= HasFlag(wxRB_SINGLE) ? BS_RADIOBUTTON : BS_AUTORADIOBUTTON;
2bda0e17 92
5f199b71 93 if ( HasFlag(wxCLIP_SIBLINGS) )
b0766406
JS
94 msStyle |= WS_CLIPSIBLINGS;
95
5f199b71
VZ
96 if ( !MSWCreateControl(_T("BUTTON"), msStyle, pos, size, label, 0) )
97 return FALSE;
b0766406 98
5f199b71
VZ
99 // for compatibility with wxGTK, the first radio button in a group is
100 // always checked (this makes sense anyhow as you need to ensure that at
101 // least one button in the group is checked and this is the simlpest way to
102 // do it)
103 if ( HasFlag(wxRB_GROUP) )
104 SetValue(TRUE);
c085e333 105
5f199b71 106 return TRUE;
2bda0e17
KB
107}
108
5f199b71
VZ
109// ----------------------------------------------------------------------------
110// wxRadioButton functions
111// ----------------------------------------------------------------------------
2bda0e17 112
5f199b71 113void wxRadioButton::SetValue(bool value)
2bda0e17 114{
5f199b71 115 // BST_CHECKED is defined as 1, BST_UNCHECKED as 0, so we can just pass
2b5f62a0 116 // value as is (we don't use BST_XXX here as they're not defined for Win16)
5f199b71 117 (void)::SendMessage(GetHwnd(), BM_SETCHECK, (WPARAM)value, 0L);
2b5f62a0
VZ
118
119 // if we set the value of one radio button we also must clear all the other
120 // buttons in the same group: Windows doesn't do it automatically
121 if ( value )
122 {
123 const wxWindowList& siblings = GetParent()->GetChildren();
222ed1d6 124 wxWindowList::compatibility_iterator nodeThis = siblings.Find(this);
2b5f62a0
VZ
125 wxCHECK_RET( nodeThis, _T("radio button not a child of its parent?") );
126
2b17e391
VZ
127 // if it's not the first item of the group ...
128 if ( !HasFlag(wxRB_GROUP) )
2b5f62a0 129 {
2b17e391 130 // ... turn off all radio buttons before it
222ed1d6 131 for ( wxWindowList::compatibility_iterator nodeBefore = nodeThis->GetPrevious();
2b17e391
VZ
132 nodeBefore;
133 nodeBefore = nodeBefore->GetPrevious() )
2b5f62a0 134 {
2b17e391
VZ
135 wxRadioButton *btn = wxDynamicCast(nodeBefore->GetData(),
136 wxRadioButton);
137 if ( !btn )
138 {
139 // the radio buttons in a group must be consecutive, so
140 // there are no more of them
141 break;
142 }
143
144 btn->SetValue(FALSE);
145
146 if ( btn->HasFlag(wxRB_GROUP) )
147 {
148 // even if there are other radio buttons before this one,
149 // they're not in the same group with us
150 break;
151 }
2b5f62a0
VZ
152 }
153 }
154
2b17e391 155 // ... and also turn off all buttons after this one
222ed1d6 156 for ( wxWindowList::compatibility_iterator nodeAfter = nodeThis->GetNext();
2b5f62a0
VZ
157 nodeAfter;
158 nodeAfter = nodeAfter->GetNext() )
159 {
160 wxRadioButton *btn = wxDynamicCast(nodeAfter->GetData(),
161 wxRadioButton);
162
163 if ( !btn || btn->HasFlag(wxRB_GROUP) )
164 {
165 // no more buttons or the first button of the next group
166 break;
167 }
168
169 btn->SetValue(FALSE);
170 }
171 }
2bda0e17
KB
172}
173
5f199b71 174bool wxRadioButton::GetValue() const
2bda0e17 175{
5f199b71
VZ
176 // NB: this will also return TRUE for BST_INDETERMINATE value if we ever
177 // have 3-state radio buttons
178 return ::SendMessage(GetHwnd(), BM_GETCHECK, 0, 0L) != 0;
2bda0e17
KB
179}
180
5f199b71
VZ
181// ----------------------------------------------------------------------------
182// wxRadioButton event processing
183// ----------------------------------------------------------------------------
184
185void wxRadioButton::Command (wxCommandEvent& event)
2bda0e17 186{
5f199b71
VZ
187 SetValue(event.m_commandInt != 0);
188 ProcessCommand(event);
2bda0e17
KB
189}
190
5f199b71 191void wxRadioButton::SetFocus()
2bda0e17 192{
5f199b71
VZ
193 // when the radio button receives a WM_SETFOCUS message it generates a
194 // BN_CLICKED which is totally unexpected and leads to catastrophic results
195 // if you pop up a dialog from the radio button event handler as, when the
196 // dialog is dismissed, the focus is returned to the radio button which
197 // generates BN_CLICKED which leads to showing another dialog and so on
198 // without end!
199 //
2b5f62a0 200 // to avoid this, we drop the pseudo BN_CLICKED events generated when the
5f199b71
VZ
201 // button gains focus
202 m_focusJustSet = TRUE;
203
204 wxControl::SetFocus();
2bda0e17
KB
205}
206
5f199b71 207bool wxRadioButton::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
f6bcfd97 208{
5f199b71
VZ
209 if ( param != BN_CLICKED )
210 return FALSE;
211
212 if ( m_focusJustSet )
f6bcfd97 213 {
5f199b71
VZ
214 // see above: we want to ignore this event
215 m_focusJustSet = FALSE;
f6bcfd97 216 }
5f199b71
VZ
217 else // a real clicked event
218 {
2b5f62a0
VZ
219 bool isChecked = GetValue();
220
221 if ( HasFlag(wxRB_SINGLE) )
222 {
223 // when we use a "manual" radio button, we have to check the button
224 // ourselves -- but it's reset to unchecked state by the user code
225 // (presumably when another button is pressed)
226 if ( !isChecked )
227 SetValue(TRUE);
228 }
229
5f199b71
VZ
230 wxCommandEvent event(wxEVT_COMMAND_RADIOBUTTON_SELECTED, GetId());
231 event.SetEventObject( this );
2b5f62a0 232 event.SetInt(isChecked);
f6bcfd97 233
5f199b71
VZ
234 ProcessCommand(event);
235 }
f6bcfd97 236
5f199b71 237 return TRUE;
f6bcfd97 238}
2bda0e17 239
5f199b71
VZ
240// ----------------------------------------------------------------------------
241// wxRadioButton geometry
242// ----------------------------------------------------------------------------
243
244wxSize wxRadioButton::DoGetBestSize() const
2bda0e17 245{
5f199b71 246 static int s_radioSize = 0;
2bda0e17 247
5f199b71
VZ
248 if ( !s_radioSize )
249 {
250 wxScreenDC dc;
251 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
2bda0e17 252
5f199b71
VZ
253 s_radioSize = dc.GetCharHeight();
254 }
2bda0e17 255
5f199b71 256 wxString str = GetLabel();
2bda0e17 257
5f199b71
VZ
258 int wRadio, hRadio;
259 if ( !str.empty() )
260 {
261 GetTextExtent(str, &wRadio, &hRadio);
262 wRadio += s_radioSize + GetCharWidth();
2bda0e17 263
5f199b71
VZ
264 if ( hRadio < s_radioSize )
265 hRadio = s_radioSize;
266 }
267 else
268 {
269 wRadio = s_radioSize;
270 hRadio = s_radioSize;
271 }
2bda0e17 272
5f199b71 273 return wxSize(wRadio, hRadio);
2bda0e17
KB
274}
275
aca78774
JS
276long wxRadioButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
277{
278 if (nMsg == WM_SETFOCUS)
279 {
280 m_focusJustSet = TRUE;
281
282 long ret = wxControl::MSWWindowProc(nMsg, wParam, lParam);
283
284 m_focusJustSet = FALSE;
285
286 return ret;
287 }
2b5f62a0 288 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
aca78774
JS
289}
290
1e6feb95 291#endif // wxUSE_RADIOBTN