Include order is wxprec.h=>defs.h=>platform.h=>setup.h so remove explicit setup.h...
[wxWidgets.git] / src / os2 / radiobut.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/radiobut.cpp
3 // Purpose: wxRadioButton
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/12/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include <stdio.h>
21 #include "wx/radiobut.h"
22 #include "wx/brush.h"
23 #include "wx/dcscreen.h"
24 #include "wx/settings.h"
25 #endif
26
27 #include "wx/os2/private.h"
28
29 IMPLEMENT_DYNAMIC_CLASS(wxRadioButton, wxControl)
30
31 extern void wxAssociateWinWithHandle( HWND hWnd
32 ,wxWindowOS2* pWin
33 );
34
35 void wxRadioButton::Init()
36 {
37 m_bFocusJustSet = FALSE;
38 } // end of wxRadioButton::Init
39
40 void wxRadioButton::Command (
41 wxCommandEvent& rEvent
42 )
43 {
44 SetValue ((rEvent.GetInt() != 0) );
45 ProcessCommand (rEvent);
46 } // end of wxRadioButton::Command
47
48 bool wxRadioButton::Create(
49 wxWindow* pParent
50 , wxWindowID vId
51 , const wxString& rsLabel
52 , const wxPoint& rPos
53 , const wxSize& rSize
54 , long lStyle
55 , const wxValidator& rValidator
56 , const wxString& rsName
57 )
58 {
59 if ( !CreateControl( pParent
60 ,vId
61 ,rPos
62 ,rSize
63 ,lStyle
64 ,rValidator
65 ,rsName))
66 return FALSE;
67
68 long lSstyle = WS_TABSTOP;
69
70 if (HasFlag(wxRB_GROUP))
71 lSstyle |= WS_GROUP;
72
73 //
74 // wxRB_SINGLE is a temporary workaround for the following problem: if you
75 // have 2 radiobuttons in the same group but which are not consecutive in
76 // the dialog, Windows can enter an infinite loop! The simplest way to
77 // reproduce it is to create radio button, then a panel and then another
78 // radio button: then checking the last button hangs the app.
79 //
80 // Ideally, we'd detect (and avoid) such situation automatically but for
81 // now, as I don't know how to do it, just allow the user to create
82 // BS_RADIOBUTTON buttons for such situations.
83 //
84 lSstyle |= HasFlag(wxRB_SINGLE) ? BS_RADIOBUTTON : BS_AUTORADIOBUTTON;
85
86 if (HasFlag(wxCLIP_SIBLINGS))
87 lSstyle |= WS_CLIPSIBLINGS;
88
89 if (!OS2CreateControl( _T("BUTTON")
90 ,lSstyle
91 ,rPos
92 ,rSize
93 ,rsLabel
94 ,0
95 ))
96 return FALSE;
97
98 wxAssociateWinWithHandle(m_hWnd, this);
99 if (HasFlag(wxRB_GROUP))
100 SetValue(TRUE);
101
102 SetFont(*wxSMALL_FONT);
103 SetSize( rPos.x
104 ,rPos.y
105 ,rSize.x
106 ,rSize.y
107 );
108 return TRUE;
109 } // end of wxRadioButton::Create
110
111 wxSize wxRadioButton::DoGetBestSize() const
112 {
113 // We should probably compute snRadioSize but it seems to be a constant
114 // independent of its label's font size and not made available by OS/2.
115 static int snRadioSize = RADIO_SIZE;
116
117 wxString sStr = wxGetWindowText(GetHwnd());
118 int nRadioWidth;
119 int nRadioHeight;
120
121 if (!sStr.empty())
122 {
123 GetTextExtent( sStr
124 ,&nRadioWidth
125 ,&nRadioHeight
126 );
127 nRadioWidth += snRadioSize;
128 if (nRadioHeight < snRadioSize)
129 nRadioHeight = snRadioSize;
130 }
131 else
132 {
133 nRadioWidth = snRadioSize;
134 nRadioHeight = snRadioSize;
135 }
136 return wxSize( nRadioWidth
137 ,nRadioHeight
138 );
139 } // end of wxRadioButton::DoGetBestSize
140
141 //
142 // Get single selection, for single choice list items
143 //
144 bool wxRadioButton::GetValue() const
145 {
146 return((::WinSendMsg((HWND) GetHWND(), BM_QUERYCHECK, (MPARAM)0L, (MPARAM)0L) != 0));
147 } // end of wxRadioButton::GetValue
148
149 bool wxRadioButton::OS2Command( WXUINT wParam, WXWORD WXUNUSED(wId) )
150 {
151 if (wParam != BN_CLICKED)
152 return false;
153
154 if (m_bFocusJustSet)
155 {
156 //
157 // See above: we want to ignore this event
158 //
159 m_bFocusJustSet = false;
160 }
161 else
162 {
163 bool bIsChecked = GetValue();
164
165 if (HasFlag(wxRB_SINGLE))
166 {
167 //
168 // When we use a "manual" radio button, we have to check the button
169 // ourselves -- but it's reset to unchecked state by the user code
170 // (presumably when another button is pressed)
171 //
172 if (!bIsChecked )
173 SetValue(TRUE);
174 }
175 wxCommandEvent rEvent( wxEVT_COMMAND_RADIOBUTTON_SELECTED, m_windowId );
176 rEvent.SetEventObject(this);
177 ProcessCommand(rEvent);
178 }
179 return true;
180 } // end of wxRadioButton::OS2Command
181
182 void wxRadioButton::SetFocus()
183 {
184 // when the radio button receives a WM_SETFOCUS message it generates a
185 // BN_CLICKED which is totally unexpected and leads to catastrophic results
186 // if you pop up a dialog from the radio button event handler as, when the
187 // dialog is dismissed, the focus is returned to the radio button which
188 // generates BN_CLICKED which leads to showing another dialog and so on
189 // without end!
190 //
191 // to avoid this, we drop the pseudo BN_CLICKED events generated when the
192 // button gains focus
193 m_bFocusJustSet = true;
194
195 wxControl::SetFocus();
196 }
197
198 void wxRadioButton::SetLabel(
199 const wxString& rsLabel
200 )
201 {
202 wxString sLabel = ::wxPMTextToLabel(rsLabel);
203 ::WinSetWindowText((HWND)GetHWND(), (const char *)sLabel.c_str());
204 } // end of wxRadioButton::SetLabel
205
206 void wxRadioButton::SetValue(
207 bool bValue
208 )
209 {
210 ::WinSendMsg((HWND)GetHWND(), BM_SETCHECK, (MPARAM)bValue, (MPARAM)0);
211 if (bValue)
212 {
213 const wxWindowList& rSiblings = GetParent()->GetChildren();
214 wxWindowList::compatibility_iterator nodeThis = rSiblings.Find(this);
215
216 wxCHECK_RET(nodeThis, _T("radio button not a child of its parent?"));
217
218 //
219 // If it's not the first item of the group ...
220 //
221 if ( !HasFlag(wxRB_GROUP) )
222 {
223 //
224 // ...turn off all radio buttons before this one
225 //
226 for ( wxWindowList::compatibility_iterator nodeBefore = nodeThis->GetPrevious();
227 nodeBefore;
228 nodeBefore = nodeBefore->GetPrevious() )
229 {
230 wxRadioButton* pBtn = wxDynamicCast( nodeBefore->GetData()
231 ,wxRadioButton
232 );
233 if (!pBtn)
234 {
235 //
236 // The radio buttons in a group must be consecutive, so there
237 // are no more of them
238 //
239 break;
240 }
241 pBtn->SetValue(FALSE);
242 if (pBtn->HasFlag(wxRB_GROUP))
243 {
244 //
245 // Even if there are other radio buttons before this one,
246 // they're not in the same group with us
247 //
248 break;
249 }
250 }
251 }
252
253 //
254 // ... and all after this one
255 //
256 for (wxWindowList::compatibility_iterator nodeAfter = nodeThis->GetNext();
257 nodeAfter;
258 nodeAfter = nodeAfter->GetNext())
259 {
260 wxRadioButton* pBtn = wxDynamicCast( nodeAfter->GetData()
261 ,wxRadioButton
262 );
263
264 if (!pBtn || pBtn->HasFlag(wxRB_GROUP) )
265 {
266 //
267 // No more buttons or the first button of the next group
268 //
269 break;
270 }
271 pBtn->SetValue(FALSE);
272 }
273 }
274 } // end of wxRadioButton::SetValue
275
276 MRESULT wxRadioButton::OS2WindowProc(
277 WXUINT uMsg
278 , WXWPARAM wParam
279 , WXLPARAM lParam
280 )
281 {
282 if (uMsg == WM_SETFOCUS)
283 {
284 m_bFocusJustSet = TRUE;
285
286 MRESULT mRc = wxControl::OS2WindowProc( uMsg
287 ,wParam
288 ,lParam
289 );
290
291 m_bFocusJustSet = FALSE;
292 return mRc;
293 }
294 return wxControl::OS2WindowProc( uMsg
295 ,wParam
296 ,lParam
297 );
298 } // end of wxRadioButton::OS2WindowProc