]> git.saurik.com Git - wxWidgets.git/blame - src/os2/button.cpp
revert unintended changes in previous commit
[wxWidgets.git] / src / os2 / button.cpp
CommitLineData
0e320a79 1/////////////////////////////////////////////////////////////////////////////
f1e01716 2// Name: src/os2/button.cpp
0e320a79 3// Purpose: wxButton
d88de032 4// Author: David Webster
0e320a79 5// Modified by:
d88de032 6// Created: 10/13/99
0e320a79 7// RCS-ID: $Id$
d88de032 8// Copyright: (c) David Webster
65571936 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
d88de032
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
f1e01716
WS
15#include "wx/button.h"
16
d88de032 17#ifndef WX_PRECOMP
1a75e76f 18 #include "wx/app.h"
d88de032
DW
19 #include "wx/brush.h"
20 #include "wx/panel.h"
21 #include "wx/bmpbuttn.h"
22 #include "wx/settings.h"
23 #include "wx/dcscreen.h"
a4a16252 24 #include "wx/scrolwin.h"
0e320a79
DW
25#endif
26
5f7bcb48 27#include "wx/stockitem.h"
d88de032 28#include "wx/os2/private.h"
0e320a79 29
987da0d4
DW
30#define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10)
31
32//
33// Should be at the very least less than winDEFAULT_BUTTON_MARGIN
34//
35#define FOCUS_MARGIN 3
36
37#ifndef BST_CHECKED
38#define BST_CHECKED 0x0001
39#endif
40
0e320a79 41IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
0e320a79
DW
42
43// Button
44
6670f564
WS
45bool wxButton::Create( wxWindow* pParent,
46 wxWindowID vId,
47 const wxString& rsLbl,
48 const wxPoint& rPos,
49 const wxSize& rSize,
50 long lStyle,
51 const wxValidator& rValidator,
52 const wxString& rsName)
0e320a79 53{
5f7bcb48
VS
54 wxString rsLabel(rsLbl);
55 if (rsLabel.empty() && wxIsStockID(vId))
56 rsLabel = wxGetStockLabel(vId);
d37bb826
SN
57
58 wxString sLabel = ::wxPMTextToLabel(rsLabel);
59
987da0d4 60 SetName(rsName);
5d4b632b 61#if wxUSE_VALIDATORS
987da0d4 62 SetValidator(rValidator);
5d4b632b 63#endif
987da0d4
DW
64 m_windowStyle = lStyle;
65 pParent->AddChild((wxButton *)this);
66 if (vId == -1)
0e320a79
DW
67 m_windowId = NewControlId();
68 else
987da0d4
DW
69 m_windowId = vId;
70 lStyle = WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON;
71
72 //
73 // OS/2 PM does not have Right/Left/Top/Bottom styles.
74 // We will have to define an additional style when we implement notebooks
75 // for a notebook page button
76 //
77 if (m_windowStyle & wxCLIP_SIBLINGS )
78 lStyle |= WS_CLIPSIBLINGS;
5d44b24e 79
987da0d4
DW
80 m_hWnd = (WXHWND)::WinCreateWindow( GetHwndOf(pParent) // Parent handle
81 ,WC_BUTTON // A Button class window
d37bb826 82 ,(PSZ)sLabel.c_str() // Button text
987da0d4
DW
83 ,lStyle // Button style
84 ,0, 0, 0, 0 // Location and size
85 ,GetHwndOf(pParent) // Owner handle
86 ,HWND_TOP // Top of Z-Order
87 ,vId // Identifier
88 ,NULL // No control data
89 ,NULL // No Presentation parameters
90 );
91 if (m_hWnd == 0)
92 {
f1e01716 93 return false;
987da0d4 94 }
0e320a79 95
987da0d4
DW
96 //
97 // Subclass again for purposes of dialog editing mode
98 //
99 SubclassWin(m_hWnd);
2c1e8f2e
DW
100 wxFont* pButtonFont = new wxFont( 8
101 ,wxSWISS
102 ,wxNORMAL
103 ,wxNORMAL
104 );
105 SetFont(*pButtonFont);
106 SetXComp(0);
107 SetYComp(0);
987da0d4
DW
108 SetSize( rPos.x
109 ,rPos.y
110 ,rSize.x
111 ,rSize.y
112 );
b3260bce 113 delete pButtonFont;
6670f564 114 return true;
987da0d4 115} // end of wxButton::Create
0e320a79 116
d88de032 117wxButton::~wxButton()
0e320a79 118{
987da0d4
DW
119 wxPanel* pPanel = wxDynamicCast(GetParent(), wxPanel);
120
121 if (pPanel)
d88de032 122 {
987da0d4 123 if (pPanel->GetDefaultItem() == this)
d88de032 124 {
987da0d4
DW
125 //
126 // Don't leave the panel with invalid default item
127 //
128 pPanel->SetDefaultItem(NULL);
d88de032
DW
129 }
130 }
987da0d4 131} // end of wxButton::~wxButton
d88de032
DW
132
133// ----------------------------------------------------------------------------
134// size management including autosizing
135// ----------------------------------------------------------------------------
136
e78c4d50 137wxSize wxButton::DoGetBestSize() const
d88de032 138{
987da0d4
DW
139 wxString rsLabel = wxGetWindowText(GetHWND());
140 int nWidthButton;
141 int nWidthChar;
142 int nHeightChar;
0d598bae 143 wxFont vFont = (wxFont)GetFont();
987da0d4
DW
144
145 GetTextExtent( rsLabel
146 ,&nWidthButton
147 ,NULL
148 );
149
150 wxGetCharSize( GetHWND()
151 ,&nWidthChar
152 ,&nHeightChar
0d598bae 153 ,&vFont
987da0d4
DW
154 );
155
156 //
157 // Add a margin - the button is wider than just its label
158 //
159 nWidthButton += 3 * nWidthChar;
160
161 //
162 // The button height is proportional to the height of the font used
163 //
164 int nHeightButton = BUTTON_HEIGHT_FROM_CHAR_HEIGHT(nHeightChar);
165
166 //
167 // Need a little extra to make it look right
168 //
9923c37d 169 nHeightButton += (int)(nHeightChar/1.5);
987da0d4 170
97d74dd2
DW
171 if (!HasFlag(wxBU_EXACTFIT))
172 {
173 wxSize vSize = GetDefaultSize();
987da0d4 174
97d74dd2
DW
175 if (nWidthButton > vSize.x)
176 vSize.x = nWidthButton;
177 if (nHeightButton > vSize.y)
178 vSize.y = nHeightButton;
179 return vSize;
180 }
181 return wxSize( nWidthButton
182 ,nHeightButton
183 );
987da0d4 184} // end of wxButton::DoGetBestSize
d88de032
DW
185
186/* static */
187wxSize wxButton::GetDefaultSize()
188{
987da0d4 189 static wxSize vSizeBtn;
d88de032 190
987da0d4 191 if (vSizeBtn.x == 0)
d88de032 192 {
987da0d4 193 wxScreenDC vDc;
d88de032 194
a756f210 195 vDc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
987da0d4
DW
196
197 //
198 // The size of a standard button in the dialog units is 50x14,
d88de032
DW
199 // translate this to pixels
200 // NB1: the multipliers come from the Windows convention
201 // NB2: the extra +1/+2 were needed to get the size be the same as the
202 // size of the buttons in the standard dialog - I don't know how
203 // this happens, but on my system this size is 75x23 in pixels and
204 // 23*8 isn't even divisible by 14... Would be nice to understand
205 // why these constants are needed though!
987da0d4
DW
206 vSizeBtn.x = (50 * (vDc.GetCharWidth() + 1))/4;
207 vSizeBtn.y = ((14 * vDc.GetCharHeight()) + 2)/8;
d88de032 208 }
987da0d4
DW
209 return vSizeBtn;
210} // end of wxButton::GetDefaultSize
d88de032 211
987da0d4
DW
212void wxButton::Command (
213 wxCommandEvent& rEvent
214)
d88de032 215{
987da0d4
DW
216 ProcessCommand (rEvent);
217} // end of wxButton::Command
d88de032
DW
218
219// ----------------------------------------------------------------------------
220// helpers
221// ----------------------------------------------------------------------------
222
223bool wxButton::SendClickEvent()
224{
987da0d4
DW
225 wxCommandEvent vEvent( wxEVT_COMMAND_BUTTON_CLICKED
226 ,GetId()
227 );
d88de032 228
987da0d4
DW
229 vEvent.SetEventObject(this);
230 return ProcessCommand(vEvent);
231} // end of wxButton::SendClickEvent
0e320a79
DW
232
233void wxButton::SetDefault()
234{
987da0d4 235 wxWindow* pParent = GetParent();
987da0d4 236
430974f8
DW
237 wxCHECK_RET( pParent, _T("button without parent?") );
238
239 //
77ffb593 240 // Set this one as the default button both for wxWidgets and Windows
430974f8
DW
241 //
242 wxWindow* pWinOldDefault = pParent->SetDefaultItem(this);
cfcebdb1 243
6670f564
WS
244 SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton), false);
245 SetDefaultStyle( this, true );
430974f8
DW
246} // end of wxButton::SetDefault
247
248void wxButton::SetTmpDefault()
249{
250 wxWindow* pParent = GetParent();
251
252 wxCHECK_RET( pParent, _T("button without parent?") );
253
254 wxWindow* pWinOldDefault = pParent->GetDefaultItem();
cfcebdb1 255
430974f8 256 pParent->SetTmpDefaultItem(this);
6670f564
WS
257 SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton), false);
258 SetDefaultStyle( this, true );
430974f8
DW
259} // end of wxButton::SetTmpDefault
260
261void wxButton::UnsetTmpDefault()
262{
263 wxWindow* pParent = GetParent();
264
265 wxCHECK_RET( pParent, _T("button without parent?") );
987da0d4 266
430974f8
DW
267 pParent->SetTmpDefaultItem(NULL);
268
269 wxWindow* pWinOldDefault = pParent->GetDefaultItem();
270
6670f564
WS
271 SetDefaultStyle( this, false );
272 SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton), true );
430974f8
DW
273} // end of wxButton::UnsetTmpDefault
274
cfcebdb1
DW
275void wxButton::SetDefaultStyle(
276 wxButton* pBtn
277, bool bOn
278)
430974f8 279{
430974f8 280 long lStyle;
cfcebdb1
DW
281 //
282 // We may be called with NULL pointer -- simpler to do the check here than
283 // in the caller which does wxDynamicCast()
284 //
285 if (!pBtn)
286 return;
430974f8 287
cfcebdb1
DW
288 //
289 // First, let DefDlgProc() know about the new default button
290 //
291 if (bOn)
292 {
293 if (!wxTheApp->IsActive())
294 return;
295
296 //
297 // In OS/2 the dialog/panel doesn't really know it has a default
298 // button, the default button simply has that style. We'll just
299 // simulate by setting focus to it
300 //
301 pBtn->SetFocus();
302 }
303 lStyle = ::WinQueryWindowULong(GetHwndOf(pBtn), QWL_STYLE);
304 if (!(lStyle & BS_DEFAULT) == bOn)
987da0d4 305 {
987da0d4
DW
306 if ((lStyle & BS_USERBUTTON) != BS_USERBUTTON)
307 {
cfcebdb1 308 if (bOn)
d00110f6 309 lStyle |= BS_DEFAULT;
cfcebdb1
DW
310 else
311 lStyle &= ~BS_DEFAULT;
312 ::WinSetWindowULong(GetHwndOf(pBtn), QWL_STYLE, lStyle);
987da0d4
DW
313 }
314 else
315 {
cfcebdb1
DW
316 //
317 // Redraw the button - it will notice itself that it's not the
987da0d4 318 // default one any longer
cfcebdb1
DW
319 //
320 pBtn->Refresh();
430974f8 321 }
987da0d4 322 }
430974f8 323} // end of wxButton::UpdateDefaultStyle
0e320a79 324
d88de032
DW
325// ----------------------------------------------------------------------------
326// event/message handlers
327// ----------------------------------------------------------------------------
0e320a79 328
6670f564 329bool wxButton::OS2Command(WXUINT uParam, WXWORD WXUNUSED(wId))
0e320a79 330{
6670f564 331 bool bProcessed = false;
987da0d4
DW
332
333 switch (uParam)
d88de032 334 {
987da0d4
DW
335 case BN_CLICKED: // normal buttons send this
336 case BN_DBLCLICKED: // owner-drawn ones also send this
337 bProcessed = SendClickEvent();
d88de032
DW
338 break;
339 }
6670f564 340
987da0d4
DW
341 return bProcessed;
342} // end of wxButton::OS2Command
343
6670f564
WS
344WXHBRUSH wxButton::OnCtlColor( WXHDC WXUNUSED(pDC),
345 WXHWND WXUNUSED(pWnd),
346 WXUINT WXUNUSED(nCtlColor),
347 WXUINT WXUNUSED(uMessage),
348 WXWPARAM WXUNUSED(wParam),
349 WXLPARAM WXUNUSED(lParam) )
987da0d4 350{
6670f564
WS
351 wxBrush* pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( GetBackgroundColour()
352 ,wxSOLID
353 );
987da0d4
DW
354
355 return (WXHBRUSH)pBackgroundBrush->GetResourceHandle();
356} // end of wxButton::OnCtlColor
357
358void wxButton::MakeOwnerDrawn()
0e320a79 359{
987da0d4 360 long lStyle = 0L;
d88de032 361
987da0d4
DW
362 lStyle = ::WinQueryWindowULong(GetHwnd(), QWL_STYLE);
363 if ((lStyle & BS_USERBUTTON) != BS_USERBUTTON)
364 {
365 //
366 // Make it so
367 //
368 lStyle |= BS_USERBUTTON;
369 ::WinSetWindowULong(GetHwnd(), QWL_STYLE, lStyle);
370 }
bc5a847c
DW
371} // end of wxButton::MakeOwnerDrawn
372
373WXDWORD wxButton::OS2GetStyle(
374 long lStyle
375, WXDWORD* pdwExstyle
376) const
377{
378 //
379 // Buttons never have an external border, they draw their own one
380 //
381 WXDWORD dwStyle = wxControl::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
382 ,pdwExstyle
383 );
384
385 //
386 // We must use WS_CLIPSIBLINGS with the buttons or they would draw over
387 // each other in any resizeable dialog which has more than one button in
388 // the bottom
389 //
390 dwStyle |= WS_CLIPSIBLINGS;
391 return dwStyle;
392} // end of wxButton::OS2GetStyle
987da0d4 393
6670f564
WS
394MRESULT wxButton::WindowProc( WXUINT uMsg,
395 WXWPARAM wParam,
396 WXLPARAM lParam )
987da0d4
DW
397{
398 //
430974f8
DW
399 // When we receive focus, we want to temporary become the default button in
400 // our parent panel so that pressing "Enter" would activate us -- and when
401 // losing it we should restore the previous default button as well
987da0d4
DW
402 //
403 if (uMsg == WM_SETFOCUS)
404 {
430974f8
DW
405 if (SHORT1FROMMP(lParam) == TRUE)
406 SetTmpDefault();
407 else
408 UnsetTmpDefault();
987da0d4
DW
409
410 //
411 // Let the default processign take place too
412 //
413 }
414
415 else if (uMsg == WM_BUTTON1DBLCLK)
416 {
417 //
418 // Emulate a click event to force an owner-drawn button to change its
419 // appearance - without this, it won't do it
420 //
421 (void)wxControl::OS2WindowProc( WM_BUTTON1DOWN
422 ,wParam
423 ,lParam
424 );
425
426 //
427 // And conitnue with processing the message normally as well
428 //
429 }
0e320a79 430
987da0d4
DW
431 //
432 // Let the base class do all real processing
433 //
434 return (wxControl::OS2WindowProc( uMsg
435 ,wParam
436 ,lParam
437 ));
bc5a847c 438} // end of wxWindowProc