set m_isBeingDeleted to true (only) in SendDestroyEvent(); call it as early as possib...
[wxWidgets.git] / src / motif / bmpbuttn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/bmpbuttn.cpp
3 // Purpose: wxBitmapButton
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 #include "wx/bmpbuttn.h"
16
17 #ifdef __VMS__
18 #pragma message disable nosimpint
19 #endif
20 #include <Xm/PushBG.h>
21 #include <Xm/PushB.h>
22 #ifdef __VMS__
23 #pragma message enable nosimpint
24 #endif
25
26 #include "wx/motif/private.h"
27
28 // Implemented in button.cpp
29 void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr);
30
31 // Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap );
32
33 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
34
35 wxBitmapButton::wxBitmapButton()
36 {
37 m_marginX = m_marginY = wxDEFAULT_BUTTON_MARGIN;
38 m_insensPixmap = (WXPixmap) 0;
39 }
40
41 bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
42 const wxBitmap& bitmap,
43 const wxPoint& pos,
44 const wxSize& size, long style,
45 const wxValidator& validator,
46 const wxString& name)
47 {
48 if( !CreateControl( parent, id, pos, size, style, validator, name ) )
49 return false;
50 PreCreation();
51
52 m_bmpNormal = m_bmpNormalOriginal = bitmap;
53 m_bmpSelected = m_bmpSelectedOriginal = bitmap;
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 Widget buttonWidget = XtVaCreateManagedWidget ("button",
67
68 // Gadget causes problems for default button operation.
69 #if wxUSE_GADGETS
70 xmPushButtonGadgetClass, parentWidget,
71 #else
72 xmPushButtonWidgetClass, parentWidget,
73 #endif
74 // See comment for wxButton::SetDefault
75 // XmNdefaultButtonShadowThickness, 1,
76 XmNrecomputeSize, False,
77 NULL);
78
79 m_mainWidget = (WXWidget) buttonWidget;
80
81 XtAddCallback (buttonWidget,
82 XmNactivateCallback, (XtCallbackProc) wxButtonCallback,
83 (XtPointer) this);
84
85 wxSize best = m_bmpNormal.Ok() ? GetBestSize() : wxSize(30, 30);
86 if( size.x != -1 ) best.x = size.x;
87 if( size.y != -1 ) best.y = size.y;
88
89 PostCreation();
90 DoSetBitmap();
91
92 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
93 pos.x, pos.y, best.x, best.y);
94
95 return true;
96 }
97
98 wxBitmapButton::~wxBitmapButton()
99 {
100 SetBitmapLabel(wxNullBitmap);
101
102 if (m_insensPixmap)
103 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) GetXDisplay()),
104 (Pixmap) m_insensPixmap);
105 }
106
107 void wxBitmapButton::SetBitmapLabel(const wxBitmap& bitmap)
108 {
109 m_bmpNormalOriginal = bitmap;
110 m_bmpNormal = bitmap;
111
112 DoSetBitmap();
113 }
114
115 void wxBitmapButton::SetBitmapSelected(const wxBitmap& sel)
116 {
117 m_bmpSelected = sel;
118 m_bmpSelectedOriginal = sel;
119
120 DoSetBitmap();
121 }
122
123 void wxBitmapButton::SetBitmapFocus(const wxBitmap& focus)
124 {
125 m_bmpFocus = focus;
126 // Not used in Motif
127 }
128
129 void wxBitmapButton::SetBitmapDisabled(const wxBitmap& disabled)
130 {
131 m_bmpDisabled = disabled;
132 m_bmpDisabledOriginal = disabled;
133
134 DoSetBitmap();
135 }
136
137 void wxBitmapButton::DoSetBitmap()
138 {
139 if (m_bmpNormalOriginal.Ok())
140 {
141 Pixmap pixmap = 0;
142 Pixmap insensPixmap = 0;
143 Pixmap armPixmap = 0;
144
145 // Must re-make the bitmap to have its transparent areas drawn
146 // in the current widget background colour.
147 if (m_bmpNormalOriginal.GetMask())
148 {
149 WXPixel backgroundPixel;
150 XtVaGetValues((Widget) m_mainWidget,
151 XmNbackground, &backgroundPixel,
152 NULL);
153
154 wxColour col;
155 col.SetPixel(backgroundPixel);
156
157 wxBitmap newBitmap =
158 wxCreateMaskedBitmap(m_bmpNormalOriginal, col);
159 m_bmpNormal = newBitmap;
160 m_bitmapCache.SetBitmap( m_bmpNormal );
161
162 pixmap = (Pixmap) m_bmpNormal.GetDrawable();
163 }
164 else
165 {
166 m_bitmapCache.SetBitmap( m_bmpNormal );
167 pixmap = (Pixmap) m_bitmapCache.GetLabelPixmap(m_mainWidget);
168 }
169
170 if (m_bmpDisabledOriginal.Ok())
171 {
172 if (m_bmpDisabledOriginal.GetMask())
173 {
174 WXPixel backgroundPixel;
175 XtVaGetValues((Widget) m_mainWidget,
176 XmNbackground, &backgroundPixel,
177 NULL);
178
179 wxColour col;
180 col.SetPixel(backgroundPixel);
181
182 wxBitmap newBitmap =
183 wxCreateMaskedBitmap(m_bmpDisabledOriginal, col);
184 m_bmpDisabled = newBitmap;
185
186 insensPixmap = (Pixmap) m_bmpDisabled.GetDrawable();
187 }
188 else
189 insensPixmap = (Pixmap) m_bitmapCache.GetInsensPixmap(m_mainWidget);
190 }
191 else
192 insensPixmap = (Pixmap) m_bitmapCache.GetInsensPixmap(m_mainWidget);
193
194 // Now make the bitmap representing the armed state
195 if (m_bmpSelectedOriginal.Ok())
196 {
197 if (m_bmpSelectedOriginal.GetMask())
198 {
199 WXPixel backgroundPixel;
200 XtVaGetValues((Widget) m_mainWidget,
201 XmNarmColor, &backgroundPixel,
202 NULL);
203
204 wxColour col;
205 col.SetPixel(backgroundPixel);
206
207 wxBitmap newBitmap =
208 wxCreateMaskedBitmap(m_bmpSelectedOriginal, col);
209 m_bmpSelected = newBitmap;
210
211 armPixmap = (Pixmap) m_bmpSelected.GetDrawable();
212 }
213 else
214 armPixmap = (Pixmap) m_bitmapCache.GetArmPixmap(m_mainWidget);
215 }
216 else
217 armPixmap = (Pixmap) m_bitmapCache.GetArmPixmap(m_mainWidget);
218
219 XtVaSetValues ((Widget) m_mainWidget,
220 XmNlabelPixmap, pixmap,
221 XmNlabelInsensitivePixmap, insensPixmap,
222 XmNarmPixmap, armPixmap,
223 XmNlabelType, XmPIXMAP,
224 NULL);
225 }
226 else
227 {
228 // Null bitmap: must not use current pixmap
229 // since it is no longer valid.
230 XtVaSetValues ((Widget) m_mainWidget,
231 XmNlabelType, XmSTRING,
232 XmNlabelPixmap, XmUNSPECIFIED_PIXMAP,
233 XmNlabelInsensitivePixmap, XmUNSPECIFIED_PIXMAP,
234 XmNarmPixmap, XmUNSPECIFIED_PIXMAP,
235 NULL);
236 }
237 }
238
239 void wxBitmapButton::ChangeBackgroundColour()
240 {
241 wxDoChangeBackgroundColour(m_mainWidget, m_backgroundColour, true);
242
243 // Must reset the bitmaps since the colours have changed.
244 DoSetBitmap();
245 }
246
247 wxSize wxBitmapButton::DoGetBestSize() const
248 {
249 wxSize ret( 30,30 );
250
251 if (m_bmpNormal.Ok())
252 {
253 int border = (GetWindowStyle() & wxNO_BORDER) ? 4 : 10;
254 ret.x = m_bmpNormal.GetWidth()+border;
255 ret.y = m_bmpNormal.GetHeight()+border;
256 }
257
258 return ret;
259 }