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