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