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