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