inherit the original layout direction (patch 1554810); also refactored a little to...
[wxWidgets.git] / include / wx / dcbuffer.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: wx/dcbuffer.h
3 // Purpose: wxBufferedDC class
4 // Author: Ron Lee <ron@debian.org>
5 // Modified by: Vadim Zeitlin (refactored, added bg preservation)
6 // Created: 16/03/02
7 // RCS-ID: $Id$
8 // Copyright: (c) Ron Lee
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_DCBUFFER_H_
13 #define _WX_DCBUFFER_H_
14
15 #include "wx/dcmemory.h"
16 #include "wx/dcclient.h"
17 #include "wx/window.h"
18
19 // Split platforms into two groups - those which have well-working
20 // double-buffering by default, and those which do not.
21 #if defined(__WXMAC__) || defined(__WXGTK20__) || defined(__WXDFB__)
22 #define wxALWAYS_NATIVE_DOUBLE_BUFFER 1
23 #else
24 #define wxALWAYS_NATIVE_DOUBLE_BUFFER 0
25 #endif
26
27
28 // ----------------------------------------------------------------------------
29 // Double buffering helper.
30 // ----------------------------------------------------------------------------
31
32 // Assumes the buffer bitmap covers the entire scrolled window,
33 // and prepares the window DC accordingly
34 #define wxBUFFER_VIRTUAL_AREA 0x01
35
36 // Assumes the buffer bitmap only covers the client area;
37 // does not prepare the window DC
38 #define wxBUFFER_CLIENT_AREA 0x02
39
40 class WXDLLEXPORT wxBufferedDC : public wxMemoryDC
41 {
42 public:
43 // Default ctor, must subsequently call Init for two stage construction.
44 wxBufferedDC()
45 : m_dc(NULL),
46 m_buffer(NULL),
47 m_style(0)
48 {
49 }
50
51 // Construct a wxBufferedDC using a user supplied buffer.
52 wxBufferedDC(wxDC *dc,
53 const wxBitmap &buffer = wxNullBitmap,
54 int style = wxBUFFER_CLIENT_AREA)
55 : m_dc(dc),
56 m_buffer(&buffer),
57 m_style(style)
58 {
59 UseBuffer();
60 }
61
62 // Construct a wxBufferedDC with an internal buffer of 'area'
63 // (where area is usually something like the size of the window
64 // being buffered)
65 wxBufferedDC(wxDC *dc, const wxSize &area, int style = wxBUFFER_CLIENT_AREA)
66 : m_dc(dc),
67 m_buffer(NULL),
68 m_style(style)
69
70 {
71 UseBuffer(area.x, area.y);
72 }
73
74 // default copy ctor ok.
75
76 // The usually desired action in the dtor is to blit the buffer.
77 virtual ~wxBufferedDC()
78 {
79 if ( m_dc )
80 UnMask();
81 }
82
83 // These reimplement the actions of the ctors for two stage creation, but
84 // are not used by the ctors themselves to save a few cpu cycles.
85 void Init(wxDC *dc,
86 const wxBitmap& buffer = wxNullBitmap,
87 int style = wxBUFFER_CLIENT_AREA)
88 {
89 InitCommon(dc, style);
90
91 m_buffer = &buffer;
92
93 UseBuffer();
94 }
95
96 void Init(wxDC *dc, const wxSize &area, int style = wxBUFFER_CLIENT_AREA)
97 {
98 InitCommon(dc, style);
99
100 UseBuffer(area.x, area.y);
101 }
102
103 // Blits the buffer to the dc, and detaches the dc from the buffer (so it
104 // can be effectively used once only).
105 //
106 // Usually called in the dtor or by the dtor of derived classes if the
107 // BufferedDC must blit before the derived class (which may own the dc it's
108 // blitting to) is destroyed.
109 void UnMask()
110 {
111 wxCHECK_RET( m_dc, _T("No underlying DC in wxBufferedDC") );
112
113 wxCoord x = 0,
114 y = 0;
115
116 if ( m_style & wxBUFFER_CLIENT_AREA )
117 GetDeviceOrigin(&x, &y);
118
119 m_dc->Blit(0, 0, m_buffer->GetWidth(), m_buffer->GetHeight(),
120 this, -x, -y );
121 m_dc = NULL;
122 }
123
124 // Set and get the style
125 void SetStyle(int style) { m_style = style; }
126 int GetStyle() const { return m_style; }
127
128 private:
129 // common part of Init()s
130 void InitCommon(wxDC *dc, int style)
131 {
132 wxASSERT_MSG( !m_dc && !m_buffer, _T("wxBufferedDC already initialised") );
133 wxCHECK_RET( dc, _T("can't associate NULL DC with wxBufferedDC") );
134
135 m_dc = dc;
136 m_style = style;
137
138 // inherit the same layout direction as the original DC
139 SetLayoutDirection(dc->GetLayoutDirection());
140 }
141
142 // check that the bitmap is valid and use it
143 void UseBuffer(wxCoord w = -1, wxCoord h = -1);
144
145 // the underlying DC to which we copy everything drawn on this one in
146 // UnMask()
147 //
148 // NB: Without the existence of a wxNullDC, this must be a pointer, else it
149 // could probably be a reference.
150 wxDC *m_dc;
151
152 // the buffer (selected in this DC)
153 const wxBitmap *m_buffer;
154
155 // the buffering style
156 int m_style;
157
158 DECLARE_DYNAMIC_CLASS(wxBufferedDC)
159 DECLARE_NO_COPY_CLASS(wxBufferedDC)
160 };
161
162
163 // ----------------------------------------------------------------------------
164 // Double buffered PaintDC.
165 // ----------------------------------------------------------------------------
166
167 // Creates a double buffered wxPaintDC, optionally allowing the
168 // user to specify their own buffer to use.
169 class WXDLLEXPORT wxBufferedPaintDC : public wxBufferedDC
170 {
171 public:
172 // If no bitmap is supplied by the user, a temporary one will be created.
173 wxBufferedPaintDC(wxWindow *window, const wxBitmap& buffer, int style = wxBUFFER_CLIENT_AREA)
174 : m_paintdc(window)
175 {
176 // If we're buffering the virtual window, scale the paint DC as well
177 if (style & wxBUFFER_VIRTUAL_AREA)
178 window->PrepareDC( m_paintdc );
179
180 if( buffer != wxNullBitmap )
181 Init(&m_paintdc, buffer, style);
182 else
183 Init(&m_paintdc, window->GetClientSize(), style);
184 }
185
186 // If no bitmap is supplied by the user, a temporary one will be created.
187 wxBufferedPaintDC(wxWindow *window, int style = wxBUFFER_CLIENT_AREA)
188 : m_paintdc(window)
189 {
190 // If we're using the virtual window, scale the paint DC as well
191 if (style & wxBUFFER_VIRTUAL_AREA)
192 window->PrepareDC( m_paintdc );
193
194 Init(&m_paintdc, window->GetClientSize(), style);
195 }
196
197 // default copy ctor ok.
198
199 virtual ~wxBufferedPaintDC()
200 {
201 // We must UnMask here, else by the time the base class
202 // does it, the PaintDC will have already been destroyed.
203 UnMask();
204 }
205
206 private:
207 wxPaintDC m_paintdc;
208
209 DECLARE_ABSTRACT_CLASS(wxBufferedPaintDC)
210 DECLARE_NO_COPY_CLASS(wxBufferedPaintDC)
211 };
212
213
214
215 //
216 // wxAutoBufferedPaintDC is a wxPaintDC in toolkits which have double-
217 // buffering by default. Otherwise it is a wxBufferedPaintDC. Thus,
218 // you can only expect it work with a simple constructor that
219 // accepts single wxWindow* argument.
220 //
221 #if wxALWAYS_NATIVE_DOUBLE_BUFFER
222 #define wxAutoBufferedPaintDCBase wxPaintDC
223 #else
224 #define wxAutoBufferedPaintDCBase wxBufferedPaintDC
225 #endif
226
227
228 #ifdef __WXDEBUG__
229
230 class wxAutoBufferedPaintDC : public wxAutoBufferedPaintDCBase
231 {
232 public:
233
234 wxAutoBufferedPaintDC(wxWindow* win)
235 : wxAutoBufferedPaintDCBase(win)
236 {
237 TestWinStyle(win);
238 }
239
240 virtual ~wxAutoBufferedPaintDC() { }
241
242 private:
243
244 void TestWinStyle(wxWindow* win)
245 {
246 // Help the user to get the double-buffering working properly.
247 wxASSERT_MSG( win->GetBackgroundStyle() == wxBG_STYLE_CUSTOM,
248 wxT("In constructor, you need to call SetBackgroundStyle(wxBG_STYLE_CUSTOM), ")
249 wxT("and also, if needed, paint the background manually in the paint event handler."));
250 }
251
252 DECLARE_NO_COPY_CLASS(wxAutoBufferedPaintDC)
253 };
254
255 #else // !__WXDEBUG__
256
257 // In release builds, just use typedef
258 typedef wxAutoBufferedPaintDCBase wxAutoBufferedPaintDC;
259
260 #endif
261
262
263 // Check if the window is natively double buffered and will return a wxPaintDC
264 // if it is, a wxBufferedPaintDC otherwise. It is the caller's responsibility
265 // to delete the wxDC pointer when finished with it.
266 inline wxDC* wxAutoBufferedPaintDCFactory(wxWindow* window)
267 {
268 if ( window->IsDoubleBuffered() )
269 return new wxPaintDC(window);
270 else
271 return new wxBufferedPaintDC(window);
272 }
273
274
275 #endif // _WX_DCBUFFER_H_