set m_isBeingDeleted to true (only) in SendDestroyEvent(); call it as early as possib...
[wxWidgets.git] / src / motif / bmpmotif.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/bmpmotif.cpp
3 // Purpose: wxBitmap
4 // Author: Julian Smart, originally in bitmap.cpp
5 // Modified by:
6 // Created: 25/03/2003
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/motif/bmpmotif.h"
16
17 #ifndef WX_PRECOMP
18 #include "wx/math.h"
19 #endif
20
21 #ifdef __VMS__
22 #pragma message disable nosimpint
23 #endif
24 #include <Xm/Xm.h>
25 #ifdef __VMS__
26 #pragma message enable nosimpint
27 #endif
28
29 #include "wx/motif/private.h"
30
31 #if wxHAVE_LIB_XPM
32 #include <X11/xpm.h>
33 #endif
34
35 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap );
36
37 static inline wxCharBuffer GetCacheImageName(WXImage image)
38 {
39 return wxString::Format(_T("wxBitmap_%p"), image).ToAscii();
40 }
41
42 wxBitmapCache::~wxBitmapCache()
43 {
44 if( m_display )
45 {
46 Screen* screen = DefaultScreenOfDisplay( (Display*)m_display );
47
48 if( m_labelPixmap )
49 XmDestroyPixmap( screen, (Pixmap)m_labelPixmap );
50
51 if( m_armPixmap )
52 XmDestroyPixmap( screen, (Pixmap)m_armPixmap );
53
54 if( m_insensPixmap )
55 XmDestroyPixmap( screen, (Pixmap)m_insensPixmap );
56
57 }
58
59 if( m_image )
60 {
61 XmUninstallImage( (XImage*)m_image );
62 XtFree( (char*)(XImage*)m_image );
63 }
64 }
65
66 void wxBitmapCache::SetBitmap( const wxBitmap& bitmap )
67 {
68 if ( !m_bitmap.IsSameAs(bitmap) )
69 {
70 InvalidateCache();
71 m_bitmap = bitmap;
72
73 if( m_image )
74 {
75 XmUninstallImage( (XImage*)m_image );
76 XtFree( (char*)(XImage*)m_image );
77 m_image = NULL;
78 }
79 }
80 }
81
82 void wxBitmapCache::InvalidateCache()
83 {
84 m_recalcPixmaps.label = true;
85 m_recalcPixmaps.arm = true;
86 m_recalcPixmaps.insens = true;
87 }
88
89 void wxBitmapCache::SetColoursChanged()
90 {
91 InvalidateCache();
92 }
93
94 void wxBitmapCache::CreateImageIfNeeded( WXWidget w )
95 {
96 if( m_image )
97 return;
98
99 m_display = w ?
100 (WXDisplay*)XtDisplay( (Widget)w ) :
101 (WXDisplay*)wxGetDisplay();
102
103 XImage *ximage = XGetImage( (Display*)m_display,
104 (Drawable)m_bitmap.GetDrawable(),
105 0, 0,
106 m_bitmap.GetWidth(), m_bitmap.GetHeight(),
107 AllPlanes, ZPixmap );
108
109 m_image = (WXImage*)ximage;
110
111 if( m_image )
112 {
113 XmInstallImage( ximage, GetCacheImageName(m_image).data() );
114 }
115 }
116
117 WXPixmap wxBitmapCache::GetPixmapFromCache(WXWidget w)
118 {
119 Widget widget = (Widget)w;
120 while( XmIsGadget( widget ) )
121 widget = XtParent( widget );
122
123 WXPixel fg, bg;
124 XtVaGetValues( widget,
125 XmNbackground, &bg,
126 XmNforeground, &fg,
127 NULL );
128
129 Screen* screen = DefaultScreenOfDisplay( (Display*)m_display );
130 return (WXPixmap)XmGetPixmap(screen, GetCacheImageName(m_image).data(), fg, bg);
131 }
132
133 WXPixmap wxBitmapCache::GetLabelPixmap( WXWidget w )
134 {
135 if( m_labelPixmap && !m_recalcPixmaps.label )
136 return m_labelPixmap;
137
138 CreateImageIfNeeded( w );
139
140 Screen* screen = DefaultScreenOfDisplay( (Display*)m_display );
141
142 if( m_labelPixmap )
143 XmDestroyPixmap( screen, (Pixmap)m_labelPixmap );
144
145 if( !m_image )
146 return (WXPixmap)NULL;
147
148 m_labelPixmap = GetPixmapFromCache(w);
149 m_recalcPixmaps.label = !m_labelPixmap;
150 return m_labelPixmap;
151 }
152
153 WXPixmap wxBitmapCache::GetArmPixmap( WXWidget w )
154 {
155 if( m_armPixmap && !m_recalcPixmaps.arm )
156 return m_armPixmap;
157
158 CreateImageIfNeeded( w );
159
160 Screen* screen = DefaultScreenOfDisplay( (Display*)m_display );
161
162 if( m_armPixmap )
163 XmDestroyPixmap( screen, (Pixmap)m_armPixmap );
164
165 if( !m_image )
166 return (WXPixmap)NULL;
167
168 m_armPixmap = GetPixmapFromCache(w);
169 m_recalcPixmaps.arm = !m_armPixmap;
170 return m_armPixmap;
171 }
172
173 WXPixmap wxBitmapCache::GetInsensPixmap( WXWidget w )
174 {
175 if( m_insensPixmap && !m_recalcPixmaps.insens )
176 return m_insensPixmap;
177
178 CreateImageIfNeeded( w );
179
180 Screen* screen = DefaultScreenOfDisplay( (Display*)m_display );
181
182 if( m_insensPixmap )
183 XmDestroyPixmap( screen, (Pixmap)m_insensPixmap );
184
185 if( !m_image )
186 return (WXPixmap)NULL;
187
188 m_insensPixmap =
189 (WXPixmap)XCreateInsensitivePixmap( (Display*)m_display,
190 (Pixmap)m_bitmap.GetDrawable() );
191
192 m_recalcPixmaps.insens = !m_insensPixmap;
193 return m_insensPixmap;
194 }
195
196 //////////////////////////////////////////////////////////////////////////////
197 // Utility function
198 //////////////////////////////////////////////////////////////////////////////
199
200 /****************************************************************************
201
202 NAME
203 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
204
205 SYNOPSIS
206 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
207
208 DESCRIPTION
209 This function creates a grayed-out copy of the argument pixmap, suitable
210 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
211
212 RETURN VALUES
213 The return value is the new Pixmap id or zero on error. Errors include
214 a NULL display argument or an invalid Pixmap argument.
215
216 ERRORS
217 If one of the XLib functions fail, it will produce a X error. The
218 default X error handler prints a diagnostic and calls exit().
219
220 SEE ALSO
221 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
222 XFillRectangle(3), exit(2)
223
224 AUTHOR
225 John R Veregge - john@puente.jpl.nasa.gov
226 Advanced Engineering and Prototyping Group (AEG)
227 Information Systems Technology Section (395)
228 Jet Propulsion Lab - Calif Institute of Technology
229
230 *****************************************************************************/
231
232 Pixmap
233 XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
234
235 {
236 static char stipple_data[] =
237 {
238 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
239 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
240 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
241 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
242 };
243 GC gc;
244 Pixmap ipixmap, stipple;
245 unsigned width, height, depth;
246
247 Window window; /* These return values */
248 unsigned border; /* from XGetGeometry() */
249 int x, y; /* are not needed. */
250
251 ipixmap = 0;
252
253 if ( NULL == display || 0 == pixmap )
254 return ipixmap;
255
256 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
257 &width, &height, &border, &depth )
258 )
259 return ipixmap; /* BadDrawable: probably an invalid pixmap */
260
261 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
262 */
263 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
264 if ( 0 != stipple )
265 {
266 gc = XCreateGC( display, pixmap, (XtGCMask)0, NULL );
267 if ( NULL != gc )
268 {
269 /* Create an identical copy of the argument pixmap.
270 */
271 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
272 if ( 0 != ipixmap )
273 {
274 /* Copy the argument pixmap into the new pixmap.
275 */
276 XCopyArea( display, pixmap, ipixmap,
277 gc, 0, 0, width, height, 0, 0 );
278
279 /* Refill the new pixmap using the stipple algorithm/pixmap.
280 */
281 XSetStipple( display, gc, stipple );
282 XSetFillStyle( display, gc, FillStippled );
283 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
284 }
285 XFreeGC( display, gc );
286 }
287 XFreePixmap( display, stipple );
288 }
289 return ipixmap;
290 }