Added new __WXMOTIF20__ macro, which is true if the Motif version
[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 #ifdef __GNUG__
13 #pragma implementation "button.h"
14 #endif
15
16 #ifdef __VMS
17 #define XtDisplay XTDISPLAY
18 #endif
19
20 #include "wx/defs.h"
21
22 #include "wx/button.h"
23 #include "wx/utils.h"
24 #include "wx/panel.h"
25
26 #ifdef __VMS__
27 #pragma message disable nosimpint
28 #endif
29 #include <Xm/PushBG.h>
30 #include <Xm/PushB.h>
31 #ifdef __VMS__
32 #pragma message enable nosimpint
33 #endif
34
35 #include "wx/motif/private.h"
36
37 void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr);
38
39 IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
40
41 // Button
42
43 bool wxButton::Create(wxWindow *parent, wxWindowID id, const wxString& label,
44 const wxPoint& pos,
45 const wxSize& size, long style,
46 const wxValidator& validator,
47 const wxString& name)
48 {
49 if( !CreateControl( parent, id, pos, size, style, validator, name ) )
50 return false;
51
52 wxString label1(wxStripMenuCodes(label));
53 wxXmString text( label1 );
54
55 Widget parentWidget = (Widget) parent->GetClientWidget();
56
57 /*
58 * Patch Note (important)
59 * There is no major reason to put a defaultButtonThickness here.
60 * Not requesting it give the ability to put wxButton with a spacing
61 * as small as requested. However, if some button become a DefaultButton,
62 * other buttons are no more aligned -- This is why we set
63 * defaultButtonThickness of ALL buttons belonging to the same wxPanel,
64 * in the ::SetDefaultButton method.
65 */
66 m_mainWidget = (WXWidget) XtVaCreateManagedWidget ("button",
67 xmPushButtonWidgetClass,
68 parentWidget,
69 wxFont::GetFontTag(), m_font.GetFontType(XtDisplay(parentWidget)),
70 XmNlabelString, text(),
71 // See comment for wxButton::SetDefault
72 // XmNdefaultButtonShadowThickness, 1,
73 NULL);
74
75 XtAddCallback ((Widget) m_mainWidget,
76 XmNactivateCallback, (XtCallbackProc) wxButtonCallback,
77 (XtPointer) this);
78
79 SetCanAddEventHandler(TRUE);
80
81 wxSize best = GetBestSize();
82 if( size.x != -1 ) best.x = size.x;
83 if( size.y != -1 ) best.y = size.y;
84
85 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
86 pos.x, pos.y, best.x, best.y);
87
88 ChangeBackgroundColour();
89
90 return TRUE;
91 }
92
93 void wxButton::SetDefaultShadowThicknessAndResize()
94 {
95 Widget buttonWidget = (Widget)GetMainWidget();
96 bool managed = XtIsManaged( buttonWidget );
97 if( managed )
98 XtUnmanageChild( buttonWidget );
99
100 XtVaSetValues( buttonWidget,
101 XmNdefaultButtonShadowThickness, 1,
102 NULL );
103
104 if( managed )
105 XtManageChild( buttonWidget );
106
107 wxSize best = GetBestSize(), actual = GetSize();
108 if( best.x < actual.x ) best.x = actual.x;
109 if( best.y < actual.y ) best.y = actual.y;
110
111 if( best != actual )
112 SetSize( best );
113 }
114
115
116 void wxButton::SetDefault()
117 {
118 wxWindow *parent = GetParent();
119 if ( parent )
120 parent->SetDefaultItem(this);
121
122 // We initially do not set XmNdefaultShadowThickness, to have
123 // small buttons. Unfortunately, buttons are now mis-aligned. We
124 // try to correct this now -- setting this ressource to 1 for each
125 // button in the same row. Because it's very hard to find
126 // wxButton in the same row, correction is straighforward: we set
127 // resource for all wxButton in this parent (but not sub panels)
128
129 for (wxWindowList::Node * node = parent->GetChildren().GetFirst ();
130 node; node = node->GetNext ())
131 {
132 wxWindow *win = node->GetData ();
133 wxButton *item = wxDynamicCast(win, wxButton);
134 if (item)
135 item->SetDefaultShadowThicknessAndResize();
136 }
137
138 XtVaSetValues ((Widget) parent->GetMainWidget(),
139 XmNdefaultButton, (Widget) GetMainWidget(),
140 NULL);
141 }
142
143 /* static */
144 wxSize wxButton::GetDefaultSize()
145 {
146 // TODO: check font size as in wxMSW ? MB
147 // Note: this is only the button size (text + margin + shadow)
148 return wxSize(70,25);
149 }
150
151 wxSize wxButton::DoGetBestSize() const
152 {
153 Dimension xmargin, ymargin, highlight, shadow, defThickness;
154
155 XtVaGetValues( (Widget)m_mainWidget,
156 XmNmarginWidth, &xmargin,
157 XmNmarginHeight, &ymargin,
158 XmNhighlightThickness, &highlight,
159 XmNshadowThickness, &shadow,
160 XmNdefaultButtonShadowThickness, &defThickness,
161 NULL );
162
163 int x = 0; int y = 0;
164 GetTextExtent( GetLabel(), &x, &y );
165
166 int margin = highlight * 2 +
167 ( defThickness ? ( ( shadow + defThickness ) * 4 ) : ( shadow * 2 ) );
168 wxSize best( x + xmargin * 2 + margin,
169 y + ymargin * 2 + margin );
170
171 // all buttons have at least the standard size unless the user explicitly
172 // wants them to be of smaller size and used wxBU_EXACTFIT style when
173 // creating the button
174 if( !HasFlag( wxBU_EXACTFIT ) )
175 {
176 wxSize def = GetDefaultSize();
177 int margin = highlight * 2 +
178 ( defThickness ? ( shadow * 4 + defThickness * 4 ) : 0 );
179 def.x += margin;
180 def.y += margin;
181
182 if( def.x > best.x )
183 best.x = def.x;
184 if( def.y > best.y )
185 best.y = def.y;
186 }
187
188 return best;
189 }
190
191 void wxButton::Command (wxCommandEvent & event)
192 {
193 ProcessCommand (event);
194 }
195
196 void wxButtonCallback (Widget w, XtPointer clientData, XtPointer WXUNUSED(ptr))
197 {
198 if (!wxGetWindowFromTable(w))
199 // Widget has been deleted!
200 return;
201
202 wxButton *item = (wxButton *) clientData;
203 wxCommandEvent event (wxEVT_COMMAND_BUTTON_CLICKED, item->GetId());
204 event.SetEventObject(item);
205 item->ProcessCommand (event);
206 }