]> git.saurik.com Git - wxWidgets.git/blob - src/motif/button.cpp
Fixed event handling bug as suggested by Lech Wiktor Piotrowski.
[wxWidgets.git] / src / motif / button.cpp
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
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __VMS
16 #define XtDisplay XTDISPLAY
17 #endif
18
19 #include "wx/defs.h"
20
21 #include "wx/button.h"
22
23 #ifdef __VMS__
24 #pragma message disable nosimpint
25 #endif
26 #include <Xm/PushBG.h>
27 #include <Xm/PushB.h>
28 #ifdef __VMS__
29 #pragma message enable nosimpint
30 #endif
31
32 #include "wx/stockitem.h"
33 #include "wx/motif/private.h"
34 #include "wx/sysopt.h"
35
36 void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr);
37
38 IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
39
40 #define MIN_WIDTH 78
41 #define MIN_LARGE_HEIGHT 30
42
43 // Button
44
45 bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString& lbl,
46 const wxPoint& pos,
47 const wxSize& size, long style,
48 const wxValidator& validator,
49 const wxString& name)
50 {
51 wxString label(lbl);
52 if (label.empty() && wxIsStockID(id))
53 label = wxGetStockLabel(id);
54
55 if( !CreateControl( parent, id, pos, size, style, validator, name ) )
56 return false;
57
58 wxString label1(wxStripMenuCodes(label));
59 wxXmString text( label1 );
60
61 Widget parentWidget = (Widget) parent->GetClientWidget();
62
63 /*
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 */
72 m_mainWidget = (WXWidget) XtVaCreateManagedWidget ("button",
73 xmPushButtonWidgetClass,
74 parentWidget,
75 wxFont::GetFontTag(), m_font.GetFontTypeC(XtDisplay(parentWidget)),
76 XmNlabelString, text(),
77 XmNrecomputeSize, False,
78 // See comment for wxButton::SetDefault
79 // XmNdefaultButtonShadowThickness, 1,
80 NULL);
81
82 XtAddCallback ((Widget) m_mainWidget,
83 XmNactivateCallback, (XtCallbackProc) wxButtonCallback,
84 (XtPointer) this);
85
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);
92
93 ChangeBackgroundColour();
94
95 return true;
96 }
97
98 void 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
112 // this can't currently be done, because user code that calls SetDefault
113 // will break otherwise
114 #if 0
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 );
121 #endif
122 InvalidateBestSize();
123 }
124
125
126 void wxButton::SetDefault()
127 {
128 wxWindow *parent = GetParent();
129 if ( parent )
130 parent->SetDefaultItem(this);
131
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
139 for (wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst ();
140 node; node = node->GetNext ())
141 {
142 wxWindow *win = node->GetData ();
143 wxButton *item = wxDynamicCast(win, wxButton);
144 if (item)
145 item->SetDefaultShadowThicknessAndResize();
146 }
147
148 XtVaSetValues ((Widget) parent->GetMainWidget(),
149 XmNdefaultButton, (Widget) GetMainWidget(),
150 NULL);
151 }
152
153 static inline bool wxMotifLargeButtons()
154 {
155 return wxSystemOptions::HasOption("motif.largebuttons")
156 && wxSystemOptions::GetOptionInt("motif.largebuttons") != 0;
157 }
158
159 /* static */
160 wxSize wxButton::GetDefaultSize()
161 {
162 // TODO: check font size as in wxMSW ? MB
163 // Note: this is the button size (text + margin + shadow + defaultBorder)
164 return wxSize( MIN_WIDTH, MIN_LARGE_HEIGHT );
165 }
166
167 wxSize wxButton::DoGetBestSize() const
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
182 wxSize wxButton::GetMinSize() const
183 {
184 if( wxMotifLargeButtons() )
185 return OldGetMinSize();
186
187 return DoGetBestSize();
188 }
189
190 wxSize wxButton::OldGetMinSize() const
191 {
192 return OldGetBestSize();
193 }
194
195 wxSize wxButton::OldGetBestSize() const
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 ) );
212
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;
234 }
235
236 void wxButton::Command (wxCommandEvent & event)
237 {
238 ProcessCommand (event);
239 }
240
241 void wxButtonCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
242 {
243 if (!wxGetWindowFromTable(w))
244 // Widget has been deleted!
245 return;
246
247 wxButton *item = (wxButton *) clientData;
248 wxCommandEvent event (wxEVT_COMMAND_BUTTON_CLICKED, item->GetId());
249 event.SetEventObject(item);
250 item->ProcessCommand (event);
251 }