]> git.saurik.com Git - wxWidgets.git/blob - src/univ/checkbox.cpp
don't compare invalid iterators/node pointers
[wxWidgets.git] / src / univ / checkbox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/univ/checkbox.cpp
3 // Purpose: wxCheckBox implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 25.08.00
7 // RCS-ID: $Id$
8 // Copyright: (c) 2000 SciTech Software, Inc. (www.scitechsoft.com)
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_CHECKBOX
27
28 #ifndef WX_PRECOMP
29 #include "wx/dcclient.h"
30 #include "wx/checkbox.h"
31 #include "wx/validate.h"
32
33 #include "wx/button.h" // for wxACTION_BUTTON_XXX
34 #endif
35
36 #include "wx/univ/theme.h"
37 #include "wx/univ/renderer.h"
38 #include "wx/univ/inphand.h"
39 #include "wx/univ/colschem.h"
40
41 // ============================================================================
42 // implementation
43 // ============================================================================
44
45 IMPLEMENT_DYNAMIC_CLASS(wxCheckBox, wxControl)
46
47 // ----------------------------------------------------------------------------
48 // wxCheckBox
49 // ----------------------------------------------------------------------------
50
51 void wxCheckBox::Init()
52 {
53 m_isPressed = false;
54 m_status = Status_Unchecked;
55 }
56
57 bool wxCheckBox::Create(wxWindow *parent,
58 wxWindowID id,
59 const wxString &label,
60 const wxPoint &pos,
61 const wxSize &size,
62 long style,
63 const wxValidator& validator,
64 const wxString &name)
65 {
66 if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
67 return false;
68
69 SetLabel(label);
70 SetBestSize(size);
71
72 CreateInputHandler(wxINP_HANDLER_CHECKBOX);
73
74 return true;
75 }
76
77 // ----------------------------------------------------------------------------
78 // checkbox interface
79 // ----------------------------------------------------------------------------
80
81 bool wxCheckBox::GetValue() const
82 {
83 return (Get3StateValue() != wxCHK_UNCHECKED);
84 }
85
86 void wxCheckBox::SetValue(bool value)
87 {
88 Set3StateValue( value ? wxCHK_CHECKED : wxCHK_UNCHECKED );
89 }
90
91 void wxCheckBox::OnCheck()
92 {
93 // we do nothing here
94 }
95
96 // ----------------------------------------------------------------------------
97 // indicator bitmaps
98 // ----------------------------------------------------------------------------
99
100 wxBitmap wxCheckBox::GetBitmap(State state, Status status) const
101 {
102 wxBitmap bmp = m_bitmaps[state][status];
103 if ( !bmp.Ok() )
104 bmp = m_bitmaps[State_Normal][status];
105
106 return bmp;
107 }
108
109 void wxCheckBox::SetBitmap(const wxBitmap& bmp, State state, Status status)
110 {
111 m_bitmaps[state][status] = bmp;
112 }
113
114 // ----------------------------------------------------------------------------
115 // drawing
116 // ----------------------------------------------------------------------------
117
118 wxCheckBox::State wxCheckBox::GetState(int flags) const
119 {
120 if ( flags & wxCONTROL_DISABLED )
121 return State_Disabled;
122 else if ( flags & wxCONTROL_PRESSED )
123 return State_Pressed;
124 else if ( flags & wxCONTROL_CURRENT )
125 return State_Current;
126 else
127 return State_Normal;
128 }
129
130 void wxCheckBox::DoDraw(wxControlRenderer *renderer)
131 {
132 int flags = GetStateFlags();
133
134 wxDC& dc = renderer->GetDC();
135 dc.SetFont(GetFont());
136 dc.SetTextForeground(GetForegroundColour());
137
138 switch ( Get3StateValue() )
139 {
140 case wxCHK_CHECKED: flags |= wxCONTROL_CHECKED; break;
141 case wxCHK_UNDETERMINED: flags |= wxCONTROL_UNDETERMINED; break;
142 default: /* do nothing */ break;
143 }
144
145 wxBitmap bitmap(GetBitmap(GetState(flags), m_status));
146
147 renderer->GetRenderer()->
148 DrawCheckButton(dc,
149 GetLabel(),
150 bitmap,
151 renderer->GetRect(),
152 flags,
153 GetWindowStyle() & wxALIGN_RIGHT ? wxALIGN_RIGHT
154 : wxALIGN_LEFT,
155 GetAccelIndex());
156 }
157
158 // ----------------------------------------------------------------------------
159 // geometry calculations
160 // ----------------------------------------------------------------------------
161
162 wxSize wxCheckBox::GetBitmapSize() const
163 {
164 wxBitmap bmp = GetBitmap(State_Normal, Status_Checked);
165 return bmp.Ok() ? wxSize(bmp.GetWidth(), bmp.GetHeight())
166 : GetRenderer()->GetCheckBitmapSize();
167 }
168
169 wxSize wxCheckBox::DoGetBestClientSize() const
170 {
171 wxClientDC dc(wxConstCast(this, wxCheckBox));
172 dc.SetFont(GetFont());
173 wxCoord width, height;
174 dc.GetMultiLineTextExtent(GetLabel(), &width, &height);
175
176 wxSize sizeBmp = GetBitmapSize();
177 if ( height < sizeBmp.y )
178 height = sizeBmp.y;
179
180 #if defined(wxUNIV_COMPATIBLE_MSW) && wxUNIV_COMPATIBLE_MSW
181 // FIXME: flag nowhere defined so perhaps should be removed?
182
183 // this looks better but is different from what wxMSW does
184 height += GetCharHeight()/2;
185 #endif // wxUNIV_COMPATIBLE_MSW
186
187 width += sizeBmp.x + 2*GetCharWidth();
188
189 return wxSize(width, height);
190 }
191
192 // ----------------------------------------------------------------------------
193 // checkbox actions
194 // ----------------------------------------------------------------------------
195
196 void wxCheckBox::DoSet3StateValue(wxCheckBoxState state)
197 {
198 Status status;
199 switch ( state )
200 {
201 case wxCHK_UNCHECKED: status = Status_Unchecked; break;
202 case wxCHK_CHECKED: status = Status_Checked; break;
203 default: wxFAIL_MSG(_T("Unknown checkbox state"));
204 case wxCHK_UNDETERMINED: status = Status_3rdState; break;
205 }
206 if ( status != m_status )
207 {
208 m_status = status;
209
210 if ( m_status == Status_Checked )
211 {
212 // invoke the hook
213 OnCheck();
214 }
215
216 Refresh();
217 }
218 }
219
220 wxCheckBoxState wxCheckBox::DoGet3StateValue() const
221 {
222 switch ( m_status )
223 {
224 case Status_Checked: return wxCHK_CHECKED;
225 case Status_Unchecked: return wxCHK_UNCHECKED;
226 default: /* go further */ break;
227 }
228 return wxCHK_UNDETERMINED;
229 }
230
231 void wxCheckBox::Press()
232 {
233 if ( !m_isPressed )
234 {
235 m_isPressed = true;
236
237 Refresh();
238 }
239 }
240
241 void wxCheckBox::Release()
242 {
243 if ( m_isPressed )
244 {
245 m_isPressed = false;
246
247 Refresh();
248 }
249 }
250
251 void wxCheckBox::Toggle()
252 {
253 m_isPressed = false;
254
255 Status status = m_status;
256
257 switch ( Get3StateValue() )
258 {
259 case wxCHK_CHECKED:
260 Set3StateValue(Is3rdStateAllowedForUser() ? wxCHK_UNDETERMINED : wxCHK_UNCHECKED);
261 break;
262
263 case wxCHK_UNCHECKED:
264 Set3StateValue(wxCHK_CHECKED);
265 break;
266
267 case wxCHK_UNDETERMINED:
268 Set3StateValue(wxCHK_UNCHECKED);
269 break;
270 }
271
272 if( status != m_status )
273 SendEvent();
274 }
275
276 void wxCheckBox::ChangeValue(bool value)
277 {
278 SetValue(value);
279
280 SendEvent();
281 }
282
283 void wxCheckBox::SendEvent()
284 {
285 wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, GetId());
286 InitCommandEvent(event);
287 wxCheckBoxState state = Get3StateValue();
288
289 // If the style flag to allow the user setting the undetermined state
290 // is not set, then skip the undetermined state and set it to unchecked.
291 if ( state == wxCHK_UNDETERMINED && !Is3rdStateAllowedForUser() )
292 {
293 state = wxCHK_UNCHECKED;
294 Set3StateValue(state);
295 }
296
297 event.SetInt(state);
298 Command(event);
299 }
300
301 // ----------------------------------------------------------------------------
302 // input handling
303 // ----------------------------------------------------------------------------
304
305 bool wxCheckBox::PerformAction(const wxControlAction& action,
306 long numArg,
307 const wxString& strArg)
308 {
309 if ( action == wxACTION_BUTTON_PRESS )
310 Press();
311 else if ( action == wxACTION_BUTTON_RELEASE )
312 Release();
313 if ( action == wxACTION_CHECKBOX_CHECK )
314 ChangeValue(true);
315 else if ( action == wxACTION_CHECKBOX_CLEAR )
316 ChangeValue(false);
317 else if ( action == wxACTION_CHECKBOX_TOGGLE )
318 Toggle();
319 else
320 return wxControl::PerformAction(action, numArg, strArg);
321
322 return true;
323 }
324
325 // ----------------------------------------------------------------------------
326 // wxStdCheckboxInputHandler
327 // ----------------------------------------------------------------------------
328
329 wxStdCheckboxInputHandler::wxStdCheckboxInputHandler(wxInputHandler *inphand)
330 : wxStdButtonInputHandler(inphand)
331 {
332 }
333
334 bool wxStdCheckboxInputHandler::HandleActivation(wxInputConsumer *consumer,
335 bool WXUNUSED(activated))
336 {
337 // only the focused checkbox appearance changes when the app gains/loses
338 // activation
339 return consumer->GetInputWindow()->IsFocused();
340 }
341
342 #endif // wxUSE_CHECKBOX