]> git.saurik.com Git - wxWidgets.git/blame - src/univ/checkbox.cpp
Yielding from a non-gui thread needs to bail out, otherwise we end up
[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
62IMPLEMENT_DYNAMIC_CLASS(wxCheckBox, wxControl)
63
64// ----------------------------------------------------------------------------
65// wxCheckBox
66// ----------------------------------------------------------------------------
67
68void wxCheckBox::Init()
69{
a290fa5a 70 m_isPressed = false;
1e6feb95
VZ
71 m_status = Status_Unchecked;
72}
73
74bool wxCheckBox::Create(wxWindow *parent,
75 wxWindowID id,
76 const wxString &label,
77 const wxPoint &pos,
78 const wxSize &size,
79 long style,
80 const wxValidator& validator,
81 const wxString &name)
82{
61fef19b 83 if ( !wxControl::Create(parent, id, pos, size, style, validator, name) )
a290fa5a 84 return false;
1e6feb95
VZ
85
86 SetLabel(label);
170acdc9 87 SetInitialSize(size);
1e6feb95
VZ
88
89 CreateInputHandler(wxINP_HANDLER_CHECKBOX);
90
a290fa5a 91 return true;
1e6feb95
VZ
92}
93
94// ----------------------------------------------------------------------------
95// checkbox interface
96// ----------------------------------------------------------------------------
97
98bool wxCheckBox::GetValue() const
99{
415a0ff1 100 return (Get3StateValue() != wxCHK_UNCHECKED);
1e6feb95
VZ
101}
102
103void wxCheckBox::SetValue(bool value)
104{
415a0ff1 105 Set3StateValue( value ? wxCHK_CHECKED : wxCHK_UNCHECKED );
1e6feb95
VZ
106}
107
108void wxCheckBox::OnCheck()
109{
110 // we do nothing here
111}
112
113// ----------------------------------------------------------------------------
114// indicator bitmaps
115// ----------------------------------------------------------------------------
116
117wxBitmap wxCheckBox::GetBitmap(State state, Status status) const
118{
119 wxBitmap bmp = m_bitmaps[state][status];
120 if ( !bmp.Ok() )
121 bmp = m_bitmaps[State_Normal][status];
122
123 return bmp;
124}
125
126void wxCheckBox::SetBitmap(const wxBitmap& bmp, State state, Status status)
127{
128 m_bitmaps[state][status] = bmp;
129}
130
131// ----------------------------------------------------------------------------
132// drawing
133// ----------------------------------------------------------------------------
134
135wxCheckBox::State wxCheckBox::GetState(int flags) const
136{
137 if ( flags & wxCONTROL_DISABLED )
138 return State_Disabled;
139 else if ( flags & wxCONTROL_PRESSED )
140 return State_Pressed;
141 else if ( flags & wxCONTROL_CURRENT )
142 return State_Current;
143 else
144 return State_Normal;
145}
146
147void wxCheckBox::DoDraw(wxControlRenderer *renderer)
148{
149 int flags = GetStateFlags();
150
151 wxDC& dc = renderer->GetDC();
152 dc.SetFont(GetFont());
153 dc.SetTextForeground(GetForegroundColour());
154
415a0ff1
WS
155 switch ( Get3StateValue() )
156 {
51e298bb
WS
157 case wxCHK_CHECKED: flags |= wxCONTROL_CHECKED; break;
158 case wxCHK_UNDETERMINED: flags |= wxCONTROL_UNDETERMINED; break;
159 default: /* do nothing */ break;
415a0ff1 160 }
1e6feb95 161
62e1ba75
JS
162 wxBitmap bitmap(GetBitmap(GetState(flags), m_status));
163
1e6feb95
VZ
164 renderer->GetRenderer()->
165 DrawCheckButton(dc,
166 GetLabel(),
62e1ba75 167 bitmap,
1e6feb95
VZ
168 renderer->GetRect(),
169 flags,
170 GetWindowStyle() & wxALIGN_RIGHT ? wxALIGN_RIGHT
171 : wxALIGN_LEFT,
172 GetAccelIndex());
173}
174
175// ----------------------------------------------------------------------------
176// geometry calculations
177// ----------------------------------------------------------------------------
178
179wxSize wxCheckBox::GetBitmapSize() const
180{
181 wxBitmap bmp = GetBitmap(State_Normal, Status_Checked);
182 return bmp.Ok() ? wxSize(bmp.GetWidth(), bmp.GetHeight())
183 : GetRenderer()->GetCheckBitmapSize();
184}
185
186wxSize wxCheckBox::DoGetBestClientSize() const
187{
188 wxClientDC dc(wxConstCast(this, wxCheckBox));
189 dc.SetFont(GetFont());
190 wxCoord width, height;
191 dc.GetMultiLineTextExtent(GetLabel(), &width, &height);
192
193 wxSize sizeBmp = GetBitmapSize();
194 if ( height < sizeBmp.y )
195 height = sizeBmp.y;
196
0ea27349
WS
197#if defined(wxUNIV_COMPATIBLE_MSW) && wxUNIV_COMPATIBLE_MSW
198 // FIXME: flag nowhere defined so perhaps should be removed?
199
1e6feb95
VZ
200 // this looks better but is different from what wxMSW does
201 height += GetCharHeight()/2;
202#endif // wxUNIV_COMPATIBLE_MSW
203
204 width += sizeBmp.x + 2*GetCharWidth();
205
206 return wxSize(width, height);
207}
208
209// ----------------------------------------------------------------------------
210// checkbox actions
211// ----------------------------------------------------------------------------
212
415a0ff1
WS
213void wxCheckBox::DoSet3StateValue(wxCheckBoxState state)
214{
215 Status status;
216 switch ( state )
217 {
218 case wxCHK_UNCHECKED: status = Status_Unchecked; break;
219 case wxCHK_CHECKED: status = Status_Checked; break;
220 default: wxFAIL_MSG(_T("Unknown checkbox state"));
221 case wxCHK_UNDETERMINED: status = Status_3rdState; break;
222 }
223 if ( status != m_status )
224 {
225 m_status = status;
226
227 if ( m_status == Status_Checked )
228 {
229 // invoke the hook
230 OnCheck();
231 }
232
233 Refresh();
234 }
235}
236
237wxCheckBoxState wxCheckBox::DoGet3StateValue() const
238{
239 switch ( m_status )
240 {
241 case Status_Checked: return wxCHK_CHECKED;
242 case Status_Unchecked: return wxCHK_UNCHECKED;
51e298bb 243 default: /* go further */ break;
415a0ff1
WS
244 }
245 return wxCHK_UNDETERMINED;
246}
247
1e6feb95
VZ
248void wxCheckBox::Press()
249{
250 if ( !m_isPressed )
251 {
a290fa5a 252 m_isPressed = true;
1e6feb95
VZ
253
254 Refresh();
255 }
256}
257
258void wxCheckBox::Release()
259{
260 if ( m_isPressed )
261 {
a290fa5a 262 m_isPressed = false;
1e6feb95
VZ
263
264 Refresh();
265 }
266}
267
268void wxCheckBox::Toggle()
269{
a290fa5a 270 m_isPressed = false;
1e6feb95 271
415a0ff1
WS
272 Status status = m_status;
273
274 switch ( Get3StateValue() )
275 {
276 case wxCHK_CHECKED:
277 Set3StateValue(Is3rdStateAllowedForUser() ? wxCHK_UNDETERMINED : wxCHK_UNCHECKED);
278 break;
279
280 case wxCHK_UNCHECKED:
281 Set3StateValue(wxCHK_CHECKED);
282 break;
283
284 case wxCHK_UNDETERMINED:
285 Set3StateValue(wxCHK_UNCHECKED);
286 break;
287 }
288
289 if( status != m_status )
290 SendEvent();
1e6feb95
VZ
291}
292
293void wxCheckBox::ChangeValue(bool value)
294{
295 SetValue(value);
296
297 SendEvent();
298}
299
300void wxCheckBox::SendEvent()
301{
302 wxCommandEvent event(wxEVT_COMMAND_CHECKBOX_CLICKED, GetId());
303 InitCommandEvent(event);
415a0ff1
WS
304 wxCheckBoxState state = Get3StateValue();
305
306 // If the style flag to allow the user setting the undetermined state
307 // is not set, then skip the undetermined state and set it to unchecked.
308 if ( state == wxCHK_UNDETERMINED && !Is3rdStateAllowedForUser() )
309 {
310 state = wxCHK_UNCHECKED;
311 Set3StateValue(state);
312 }
313
314 event.SetInt(state);
1e6feb95
VZ
315 Command(event);
316}
317
318// ----------------------------------------------------------------------------
319// input handling
320// ----------------------------------------------------------------------------
321
322bool wxCheckBox::PerformAction(const wxControlAction& action,
323 long numArg,
324 const wxString& strArg)
325{
326 if ( action == wxACTION_BUTTON_PRESS )
327 Press();
328 else if ( action == wxACTION_BUTTON_RELEASE )
329 Release();
330 if ( action == wxACTION_CHECKBOX_CHECK )
a290fa5a 331 ChangeValue(true);
1e6feb95 332 else if ( action == wxACTION_CHECKBOX_CLEAR )
a290fa5a 333 ChangeValue(false);
1e6feb95
VZ
334 else if ( action == wxACTION_CHECKBOX_TOGGLE )
335 Toggle();
336 else
337 return wxControl::PerformAction(action, numArg, strArg);
338
a290fa5a 339 return true;
1e6feb95
VZ
340}
341
9467bdb7
VZ
342/* static */
343wxInputHandler *wxCheckBox::CreateStdInputHandler(wxInputHandler *handlerDef)
344{
345 static wxStdCheckboxInputHandler s_handler(handlerDef);
346
347 return &s_handler;
348}
349
1e6feb95
VZ
350// ----------------------------------------------------------------------------
351// wxStdCheckboxInputHandler
352// ----------------------------------------------------------------------------
353
9467bdb7
VZ
354wxStdCheckboxInputHandler::wxStdCheckboxInputHandler(wxInputHandler *def)
355 : wxStdInputHandler(wxButton::GetStdInputHandler(def))
1e6feb95
VZ
356{
357}
358
23645bfa 359bool wxStdCheckboxInputHandler::HandleActivation(wxInputConsumer *consumer,
61fef19b 360 bool WXUNUSED(activated))
1e6feb95
VZ
361{
362 // only the focused checkbox appearance changes when the app gains/loses
363 // activation
23645bfa 364 return consumer->GetInputWindow()->IsFocused();
1e6feb95
VZ
365}
366
367#endif // wxUSE_CHECKBOX