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