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