]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/univ/button.cpp
Updated documentation according to recent array changes.
[wxWidgets.git] / src / univ / button.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: univ/button.cpp
3// Purpose: wxButton
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 14.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#ifdef __GNUG__
21 #pragma implementation "univbutton.h"
22#endif
23
24#include "wx/wxprec.h"
25
26#ifdef __BORLANDC__
27 #pragma hdrstop
28#endif
29
30#if wxUSE_BUTTON
31
32#ifndef WX_PRECOMP
33 #include "wx/dcclient.h"
34 #include "wx/dcscreen.h"
35 #include "wx/button.h"
36 #include "wx/validate.h"
37#endif
38
39#include "wx/univ/renderer.h"
40#include "wx/univ/inphand.h"
41#include "wx/univ/theme.h"
42#include "wx/univ/colschem.h"
43
44// ----------------------------------------------------------------------------
45// constants
46// ----------------------------------------------------------------------------
47
48// default margins around the image
49static const wxCoord DEFAULT_BTN_MARGIN_X = 0; // We should give space for the border, at least.
50static const wxCoord DEFAULT_BTN_MARGIN_Y = 0;
51
52// ============================================================================
53// implementation
54// ============================================================================
55
56IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
57
58// ----------------------------------------------------------------------------
59// creation
60// ----------------------------------------------------------------------------
61
62void wxButton::Init()
63{
64 m_isPressed =
65 m_isDefault = FALSE;
66}
67
68bool wxButton::Create(wxWindow *parent,
69 wxWindowID id,
70 const wxBitmap& bitmap,
71 const wxString &label,
72 const wxPoint &pos,
73 const wxSize &size,
74 long style,
75 const wxValidator& validator,
76 const wxString &name)
77{
78 // center label by default
79 if ( !(style & wxALIGN_MASK) )
80 {
81 style |= wxALIGN_CENTRE_HORIZONTAL | wxALIGN_CENTRE_VERTICAL;
82 }
83
84 if ( !wxControl::Create(parent, id, pos, size, style, wxDefaultValidator, name) )
85 return FALSE;
86
87 SetLabel(label);
88 SetImageLabel(bitmap);
89 // SetBestSize(size); -- called by SetImageLabel()
90
91 CreateInputHandler(wxINP_HANDLER_BUTTON);
92
93 return TRUE;
94}
95
96wxButton::~wxButton()
97{
98}
99
100// ----------------------------------------------------------------------------
101// size management
102// ----------------------------------------------------------------------------
103
104/* static */
105wxSize wxButtonBase::GetDefaultSize()
106{
107 static wxSize s_sizeBtn;
108
109 if ( s_sizeBtn.x == 0 )
110 {
111 wxScreenDC dc;
112
113 // this corresponds more or less to wxMSW standard in Win32 theme (see
114 // wxWin32Renderer::AdjustSize())
115 s_sizeBtn.x = 8*dc.GetCharWidth();
116 s_sizeBtn.y = (11*dc.GetCharHeight())/10 + 2;
117 }
118
119 return s_sizeBtn;
120}
121
122wxSize wxButton::DoGetBestClientSize() const
123{
124 wxClientDC dc(wxConstCast(this, wxButton));
125 wxCoord width, height;
126 dc.GetMultiLineTextExtent(GetLabel(), &width, &height);
127
128 if ( m_bitmap.Ok() )
129 {
130 // allocate extra space for the bitmap
131 wxCoord heightBmp = m_bitmap.GetHeight() + 2*m_marginBmpY;
132 if ( height < heightBmp )
133 height = heightBmp;
134
135 width += m_bitmap.GetWidth() + 2*m_marginBmpX;
136 }
137
138 // for compatibility with other ports, the buttons default size is never
139 // less than the standard one
140#ifndef __WXX11__
141 if ( !(GetWindowStyle() & wxBU_EXACTFIT) )
142 {
143 wxSize szDef = GetDefaultSize();
144 if ( width < szDef.x )
145 width = szDef.x;
146 }
147#endif
148
149 return wxSize(width, height);
150}
151
152// ----------------------------------------------------------------------------
153// drawing
154// ----------------------------------------------------------------------------
155
156void wxButton::DoDraw(wxControlRenderer *renderer)
157{
158 if ( !(GetWindowStyle() & wxBORDER_NONE) )
159 {
160 renderer->DrawButtonBorder();
161 }
162
163 renderer->DrawLabel(m_bitmap, m_marginBmpX, m_marginBmpY);
164}
165
166bool wxButton::DoDrawBackground(wxDC& dc)
167{
168 wxRect rect;
169 wxSize size = GetSize();
170 rect.width = size.x;
171 rect.height = size.y;
172
173 if ( GetBackgroundBitmap().Ok() )
174 {
175 // get the bitmap and the flags
176 int alignment;
177 wxStretch stretch;
178 wxBitmap bmp = GetBackgroundBitmap(&alignment, &stretch);
179 wxControlRenderer::DrawBitmap(dc, bmp, rect, alignment, stretch);
180 }
181 else
182 {
183 m_renderer->DrawButtonSurface(dc, wxTHEME_BG_COLOUR(this),
184 rect, GetStateFlags());
185 }
186
187 return TRUE;
188}
189
190// ----------------------------------------------------------------------------
191// input processing
192// ----------------------------------------------------------------------------
193
194void wxButton::Press()
195{
196 if ( !m_isPressed )
197 {
198 m_isPressed = TRUE;
199
200 Refresh();
201 }
202}
203
204void wxButton::Release()
205{
206 if ( m_isPressed )
207 {
208 m_isPressed = FALSE;
209
210 Refresh();
211 }
212}
213
214void wxButton::Toggle()
215{
216 if ( m_isPressed )
217 Release();
218 else
219 Press();
220
221 if ( !m_isPressed )
222 {
223 // releasing button after it had been pressed generates a click event
224 Click();
225 }
226}
227
228void wxButton::Click()
229{
230 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
231 InitCommandEvent(event);
232 Command(event);
233}
234
235bool wxButton::PerformAction(const wxControlAction& action,
236 long numArg,
237 const wxString& strArg)
238{
239 if ( action == wxACTION_BUTTON_TOGGLE )
240 Toggle();
241 else if ( action == wxACTION_BUTTON_CLICK )
242 Click();
243 else if ( action == wxACTION_BUTTON_PRESS )
244 Press();
245 else if ( action == wxACTION_BUTTON_RELEASE )
246 Release();
247 else
248 return wxControl::PerformAction(action, numArg, strArg);
249
250 return TRUE;
251}
252
253// ----------------------------------------------------------------------------
254// misc
255// ----------------------------------------------------------------------------
256
257void wxButton::SetImageLabel(const wxBitmap& bitmap)
258{
259 m_bitmap = bitmap;
260
261 SetImageMargins(DEFAULT_BTN_MARGIN_X, DEFAULT_BTN_MARGIN_Y);
262}
263
264void wxButton::SetImageMargins(wxCoord x, wxCoord y)
265{
266 m_marginBmpX = x + 2;
267 m_marginBmpY = y + 2;
268
269 SetBestSize(wxDefaultSize);
270}
271
272void wxButton::SetDefault()
273{
274 m_isDefault = TRUE;
275}
276
277// ============================================================================
278// wxStdButtonInputHandler
279// ============================================================================
280
281wxStdButtonInputHandler::wxStdButtonInputHandler(wxInputHandler *handler)
282 : wxStdInputHandler(handler)
283{
284 m_winCapture = NULL;
285 m_winHasMouse = FALSE;
286}
287
288bool wxStdButtonInputHandler::HandleKey(wxInputConsumer *consumer,
289 const wxKeyEvent& event,
290 bool pressed)
291{
292 int keycode = event.GetKeyCode();
293 if ( keycode == WXK_SPACE || keycode == WXK_RETURN )
294 {
295 consumer->PerformAction(wxACTION_BUTTON_TOGGLE);
296
297 return TRUE;
298 }
299
300 return wxStdInputHandler::HandleKey(consumer, event, pressed);
301}
302
303bool wxStdButtonInputHandler::HandleMouse(wxInputConsumer *consumer,
304 const wxMouseEvent& event)
305{
306 // the button has 2 states: pressed and normal with the following
307 // transitions between them:
308 //
309 // normal -> left down -> capture mouse and go to pressed state
310 // pressed -> left up inside -> generate click -> go to normal
311 // outside ------------------>
312 //
313 // the other mouse buttons are ignored
314 if ( event.Button(1) )
315 {
316 if ( event.LeftDown() || event.LeftDClick() )
317 {
318 m_winCapture = consumer->GetInputWindow();
319 m_winCapture->CaptureMouse();
320 m_winHasMouse = TRUE;
321
322 consumer->PerformAction(wxACTION_BUTTON_PRESS);
323
324 return TRUE;
325 }
326 else if ( event.LeftUp() )
327 {
328 if ( m_winCapture )
329 {
330 m_winCapture->ReleaseMouse();
331 m_winCapture = NULL;
332 }
333
334 if ( m_winHasMouse )
335 {
336 // this will generate a click event
337 consumer->PerformAction(wxACTION_BUTTON_TOGGLE);
338
339 return TRUE;
340 }
341 //else: the mouse was released outside the window, this doesn't
342 // count as a click
343 }
344 //else: don't do anything special about the double click
345 }
346
347 return wxStdInputHandler::HandleMouse(consumer, event);
348}
349
350bool wxStdButtonInputHandler::HandleMouseMove(wxInputConsumer *consumer,
351 const wxMouseEvent& event)
352{
353 // we only have to do something when the mouse leaves/enters the pressed
354 // button and don't care about the other ones
355 if ( event.GetEventObject() == m_winCapture )
356 {
357 // leaving the button should remove its pressed state
358 if ( event.Leaving() )
359 {
360 // remember that the mouse is now outside
361 m_winHasMouse = FALSE;
362
363 // we do have a pressed button, so release it
364 consumer->GetInputWindow()->SetCurrent(FALSE);
365 consumer->PerformAction(wxACTION_BUTTON_RELEASE);
366
367 return TRUE;
368 }
369 // and entering it back should make it pressed again if it had been
370 // pressed
371 else if ( event.Entering() )
372 {
373 // the mouse is (back) inside the button
374 m_winHasMouse = TRUE;
375
376 // we did have a pressed button which we released when leaving the
377 // window, press it again
378 consumer->GetInputWindow()->SetCurrent(TRUE);
379 consumer->PerformAction(wxACTION_BUTTON_PRESS);
380
381 return TRUE;
382 }
383 }
384
385 return wxStdInputHandler::HandleMouseMove(consumer, event);
386}
387
388bool wxStdButtonInputHandler::HandleFocus(wxInputConsumer *consumer,
389 const wxFocusEvent& event)
390{
391 // buttons change appearance when they get/lose focus, so return TRUE to
392 // refresh
393 return TRUE;
394}
395
396bool wxStdButtonInputHandler::HandleActivation(wxInputConsumer *consumer,
397 bool activated)
398{
399 // the default button changes appearance when the app is [de]activated, so
400 // return TRUE to refresh
401 return wxStaticCast(consumer->GetInputWindow(), wxButton)->IsDefault();
402}
403
404#endif // wxUSE_BUTTON
405