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