]> git.saurik.com Git - wxWidgets.git/blame - src/motif/button.cpp
fix another memory leak in SetCommand() (coverity checker CID 52)
[wxWidgets.git] / src / motif / button.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: button.cpp
3// Purpose: wxButton
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
1248b41f
MB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
bcd055ae
JJ
15#ifdef __VMS
16#define XtDisplay XTDISPLAY
17#endif
18
f6045f99
GD
19#include "wx/defs.h"
20
4bb6408c
JS
21#include "wx/button.h"
22
338dd992
JJ
23#ifdef __VMS__
24#pragma message disable nosimpint
25#endif
02e8b2f9
JS
26#include <Xm/PushBG.h>
27#include <Xm/PushB.h>
338dd992
JJ
28#ifdef __VMS__
29#pragma message enable nosimpint
30#endif
02e8b2f9 31
5f7bcb48 32#include "wx/stockitem.h"
02e8b2f9 33#include "wx/motif/private.h"
e04b7e8e 34#include "wx/sysopt.h"
02e8b2f9
JS
35
36void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr);
37
4bb6408c 38IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
4bb6408c 39
e04b7e8e
MB
40#define MIN_WIDTH 78
41#define MIN_LARGE_HEIGHT 30
42
4bb6408c
JS
43// Button
44
5f7bcb48 45bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString& lbl,
2d120f83
JS
46 const wxPoint& pos,
47 const wxSize& size, long style,
48 const wxValidator& validator,
49 const wxString& name)
4bb6408c 50{
5f7bcb48
VS
51 wxString label(lbl);
52 if (label.empty() && wxIsStockID(id))
53 label = wxGetStockLabel(id);
54
458ca8c1
MB
55 if( !CreateControl( parent, id, pos, size, style, validator, name ) )
56 return false;
dfe1eee3 57
89c7e962 58 wxString label1(wxStripMenuCodes(label));
458ca8c1 59 wxXmString text( label1 );
dfe1eee3 60
02e8b2f9 61 Widget parentWidget = (Widget) parent->GetClientWidget();
dfe1eee3 62
02e8b2f9 63 /*
2d120f83
JS
64 * Patch Note (important)
65 * There is no major reason to put a defaultButtonThickness here.
66 * Not requesting it give the ability to put wxButton with a spacing
67 * as small as requested. However, if some button become a DefaultButton,
68 * other buttons are no more aligned -- This is why we set
69 * defaultButtonThickness of ALL buttons belonging to the same wxPanel,
70 * in the ::SetDefaultButton method.
71 */
02e8b2f9 72 m_mainWidget = (WXWidget) XtVaCreateManagedWidget ("button",
2d120f83
JS
73 xmPushButtonWidgetClass,
74 parentWidget,
73608949 75 wxFont::GetFontTag(), m_font.GetFontTypeC(XtDisplay(parentWidget)),
458ca8c1 76 XmNlabelString, text(),
84fb430b 77 XmNrecomputeSize, False,
458ca8c1
MB
78 // See comment for wxButton::SetDefault
79 // XmNdefaultButtonShadowThickness, 1,
2d120f83 80 NULL);
dfe1eee3 81
458ca8c1
MB
82 XtAddCallback ((Widget) m_mainWidget,
83 XmNactivateCallback, (XtCallbackProc) wxButtonCallback,
84 (XtPointer) this);
dfe1eee3 85
458ca8c1
MB
86 wxSize best = GetBestSize();
87 if( size.x != -1 ) best.x = size.x;
88 if( size.y != -1 ) best.y = size.y;
89
90 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
91 pos.x, pos.y, best.x, best.y);
dfe1eee3 92
0d57be45 93 ChangeBackgroundColour();
dfe1eee3 94
e04b7e8e 95 return true;
4bb6408c
JS
96}
97
458ca8c1
MB
98void wxButton::SetDefaultShadowThicknessAndResize()
99{
100 Widget buttonWidget = (Widget)GetMainWidget();
101 bool managed = XtIsManaged( buttonWidget );
102 if( managed )
103 XtUnmanageChild( buttonWidget );
104
105 XtVaSetValues( buttonWidget,
106 XmNdefaultButtonShadowThickness, 1,
107 NULL );
108
109 if( managed )
110 XtManageChild( buttonWidget );
111
84fb430b
MB
112 // this can't currently be done, because user code that calls SetDefault
113 // will break otherwise
114#if 0
458ca8c1
MB
115 wxSize best = GetBestSize(), actual = GetSize();
116 if( best.x < actual.x ) best.x = actual.x;
117 if( best.y < actual.y ) best.y = actual.y;
118
119 if( best != actual )
120 SetSize( best );
84fb430b 121#endif
4e025aa2 122 InvalidateBestSize();
458ca8c1
MB
123}
124
125
4bb6408c
JS
126void wxButton::SetDefault()
127{
dfe1eee3 128 wxWindow *parent = GetParent();
b0ee47ff 129 if ( parent )
d5f005cc 130 parent->SetDefaultItem(this);
dfe1eee3 131
458ca8c1
MB
132 // We initially do not set XmNdefaultShadowThickness, to have
133 // small buttons. Unfortunately, buttons are now mis-aligned. We
134 // try to correct this now -- setting this ressource to 1 for each
135 // button in the same row. Because it's very hard to find
136 // wxButton in the same row, correction is straighforward: we set
137 // resource for all wxButton in this parent (but not sub panels)
138
ac32ba44 139 for (wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst ();
fd304d98 140 node; node = node->GetNext ())
02e8b2f9 141 {
fd304d98
MB
142 wxWindow *win = node->GetData ();
143 wxButton *item = wxDynamicCast(win, wxButton);
144 if (item)
458ca8c1
MB
145 item->SetDefaultShadowThicknessAndResize();
146 }
147
148 XtVaSetValues ((Widget) parent->GetMainWidget(),
149 XmNdefaultButton, (Widget) GetMainWidget(),
150 NULL);
4bb6408c
JS
151}
152
e04b7e8e
MB
153static inline bool wxMotifLargeButtons()
154{
155 return wxSystemOptions::HasOption("motif.largebuttons")
156 && wxSystemOptions::GetOptionInt("motif.largebuttons") != 0;
157}
158
4d194d63
MB
159/* static */
160wxSize wxButton::GetDefaultSize()
161{
162 // TODO: check font size as in wxMSW ? MB
84fb430b 163 // Note: this is the button size (text + margin + shadow + defaultBorder)
e04b7e8e 164 return wxSize( MIN_WIDTH, MIN_LARGE_HEIGHT );
458ca8c1
MB
165}
166
167wxSize wxButton::DoGetBestSize() const
e04b7e8e
MB
168{
169 if( wxMotifLargeButtons() )
170 return OldGetBestSize();
171
172 wxSize best = wxControl::DoGetBestSize();
173
174 if( HasFlag( wxBU_EXACTFIT ) )
175 return best;
176 else if( best.x < MIN_WIDTH )
177 best.x = MIN_WIDTH;
178
179 return best;
180}
181
4e025aa2
MB
182wxSize wxButton::GetMinSize() const
183{
184 if( wxMotifLargeButtons() )
185 return OldGetMinSize();
186
187 return DoGetBestSize();
188}
189
190wxSize wxButton::OldGetMinSize() const
191{
192 return OldGetBestSize();
193}
194
e04b7e8e 195wxSize wxButton::OldGetBestSize() const
458ca8c1
MB
196{
197 Dimension xmargin, ymargin, highlight, shadow, defThickness;
198
199 XtVaGetValues( (Widget)m_mainWidget,
200 XmNmarginWidth, &xmargin,
201 XmNmarginHeight, &ymargin,
202 XmNhighlightThickness, &highlight,
203 XmNshadowThickness, &shadow,
204 XmNdefaultButtonShadowThickness, &defThickness,
205 NULL );
206
207 int x = 0; int y = 0;
208 GetTextExtent( GetLabel(), &x, &y );
209
210 int margin = highlight * 2 +
211 ( defThickness ? ( ( shadow + defThickness ) * 4 ) : ( shadow * 2 ) );
4e025aa2 212
458ca8c1
MB
213 wxSize best( x + xmargin * 2 + margin,
214 y + ymargin * 2 + margin );
215
216 // all buttons have at least the standard size unless the user explicitly
217 // wants them to be of smaller size and used wxBU_EXACTFIT style when
218 // creating the button
219 if( !HasFlag( wxBU_EXACTFIT ) )
220 {
221 wxSize def = GetDefaultSize();
222 int margin = highlight * 2 +
223 ( defThickness ? ( shadow * 4 + defThickness * 4 ) : 0 );
224 def.x += margin;
225 def.y += margin;
226
227 if( def.x > best.x )
228 best.x = def.x;
229 if( def.y > best.y )
230 best.y = def.y;
231 }
232
233 return best;
4d194d63
MB
234}
235
4bb6408c
JS
236void wxButton::Command (wxCommandEvent & event)
237{
238 ProcessCommand (event);
239}
240
f9e02ac7 241void wxButtonCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
02e8b2f9 242{
2d120f83
JS
243 if (!wxGetWindowFromTable(w))
244 // Widget has been deleted!
245 return;
dfe1eee3 246
2d120f83
JS
247 wxButton *item = (wxButton *) clientData;
248 wxCommandEvent event (wxEVT_COMMAND_BUTTON_CLICKED, item->GetId());
249 event.SetEventObject(item);
250 item->ProcessCommand (event);
02e8b2f9 251}