]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dcclient.cpp
Added wxBufferedDC class.
[wxWidgets.git] / src / os2 / dcclient.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: dcclient.cpp
3// Purpose: wxClientDC class
f0a56ab0 4// Author: David Webster
0e320a79 5// Modified by:
f0a56ab0 6// Created: 09/21/99
0e320a79 7// RCS-ID: $Id$
f0a56ab0 8// Copyright: (c) David Webster
23e4b7d8 9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
23e4b7d8
DW
12// ===========================================================================
13// declarations
14// ===========================================================================
0e320a79 15
23e4b7d8
DW
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
0e320a79 19
23e4b7d8
DW
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
0e320a79 22
23e4b7d8
DW
23#include "wx/string.h"
24#include "wx/log.h"
25#include "wx/window.h"
3417f661 26#include "wx/app.h"
0e320a79 27
ce44c50e 28#include "wx/os2/private.h"
0e320a79 29
23e4b7d8 30#include "wx/dcclient.h"
0e320a79 31
23e4b7d8
DW
32// ----------------------------------------------------------------------------
33// array/list types
34// ----------------------------------------------------------------------------
0e320a79 35
23e4b7d8 36struct WXDLLEXPORT wxPaintDCInfo
0e320a79 37{
e99762c0
DW
38 wxPaintDCInfo( wxWindow* pWin
39 ,wxDC* pDC
40 )
23e4b7d8 41 {
e99762c0
DW
42 m_hWnd = pWin->GetHWND();
43 m_hDC = pDC->GetHDC();
44 m_nCount = 1;
23e4b7d8 45 }
0e320a79 46
e99762c0
DW
47 WXHWND m_hWnd; // window for this DC
48 WXHDC m_hDC; // the DC handle
49 size_t m_nCount; // usage count
50}; // end of wxPaintDCInfot
0e320a79 51
23e4b7d8 52#include "wx/arrimpl.cpp"
1408104d 53
23e4b7d8 54WX_DEFINE_OBJARRAY(wxArrayDCInfo);
1408104d 55
23e4b7d8
DW
56// ----------------------------------------------------------------------------
57// macros
58// ----------------------------------------------------------------------------
0e320a79 59
23e4b7d8
DW
60 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
61 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
62 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
0e320a79 63
23e4b7d8
DW
64// ----------------------------------------------------------------------------
65// global variables
66// ----------------------------------------------------------------------------
1408104d 67
ce44c50e 68static RECT g_paintStruct;
1408104d 69
23e4b7d8
DW
70#ifdef __WXDEBUG__
71 // a global variable which we check to verify that wxPaintDC are only
72 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
73 // common programming error among wxWindows programmers and might lead to
74 // very subtle and difficult to debug refresh/repaint bugs.
75 int g_isPainting = 0;
76#endif // __WXDEBUG__
1408104d 77
23e4b7d8
DW
78// ===========================================================================
79// implementation
80// ===========================================================================
1408104d 81
23e4b7d8
DW
82// ----------------------------------------------------------------------------
83// wxWindowDC
84// ----------------------------------------------------------------------------
0e320a79 85
23e4b7d8 86wxWindowDC::wxWindowDC()
0e320a79 87{
26ac77db 88 m_pCanvas = NULL;
23e4b7d8 89}
0e320a79 90
e99762c0
DW
91wxWindowDC::wxWindowDC(
92 wxWindow* pTheCanvas
93)
0e320a79 94{
26ac77db
DW
95 ERRORID vError;
96 wxString sError;
1408104d 97
e99762c0
DW
98 m_pCanvas = pTheCanvas;
99 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
e1a688e4 100
23e4b7d8 101 //
26ac77db
DW
102 // default under PM is that Window and Client DC's are the same
103 // so we offer a separate Presentation Space to use for the
104 // entire window. Otherwise, calling BeginPaint will just create
105 // chached-micro client presentation space
23e4b7d8 106 //
e1a688e4
DW
107 m_hPS = ::GpiCreatePS( vHabmain
108 ,m_hDC
109 ,&m_PageSize
110 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
111 );
26ac77db
DW
112 ::GpiAssociate(m_hPS, NULLHANDLE);
113 ::GpiAssociate(m_hPS, m_hDC);
e1a688e4
DW
114
115 //
26ac77db 116 // Set the wxWindows color table
e1a688e4 117 //
26ac77db
DW
118 if (!::GpiCreateLogColorTable( m_hPS
119 ,0L
120 ,LCOLF_CONSECRGB
121 ,0L
122 ,(LONG)wxTheColourDatabase->m_nSize
123 ,(PLONG)wxTheColourDatabase->m_palTable
124 ))
7e99520b 125 {
26ac77db
DW
126 vError = ::WinGetLastError(vHabmain);
127 sError = wxPMErrorToStr(vError);
128 wxLogError("Unable to set current color table. Error: %s\n", sError);
7e99520b 129 }
5afb9458
DW
130 ::GpiCreateLogColorTable( m_hPS
131 ,0L
132 ,LCOLF_RGB
133 ,0L
134 ,0L
135 ,NULL
136 );
5afb9458
DW
137 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
138 ,&m_vRclPaint
139 );
e1a688e4
DW
140 InitDC();
141} // end of wxWindowDC::wxWindowDC
1408104d 142
e1a688e4 143void wxWindowDC::InitDC()
26ac77db 144{
2b0ec34b
DW
145 wxColour vColor;
146
147 vColor.InitFromName("BLACK");
148 m_pen.SetColour(vColor);
149 vColor.Set("WHITE");
150 m_brush.SetColour(vColor);
e1a688e4
DW
151 //
152 // The background mode is only used for text background and is set in
153 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT,
154 //
155 ::GpiSetBackMix(GetHPS(), BM_LEAVEALONE);
26ac77db 156
e1a688e4
DW
157 //
158 // Default bg colour is pne of the window
159 //
160 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
161} // end of wxWindowDC::InitDC
0e320a79 162
bc5a847c
DW
163void wxWindowDC::DoGetSize(
164 int* pnWidth
165, int* pnHeight
166) const
167{
168 wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
169 m_pCanvas->GetSize( pnWidth
170 ,pnHeight
171 );
172} // end of wxWindowDC::DoGetSize
173
23e4b7d8
DW
174// ----------------------------------------------------------------------------
175// wxClientDC
176// ----------------------------------------------------------------------------
0e320a79 177
23e4b7d8 178wxClientDC::wxClientDC()
0e320a79 179{
26ac77db 180 m_pCanvas = NULL;
23e4b7d8 181}
0e320a79 182
e99762c0
DW
183wxClientDC::wxClientDC(
184 wxWindow* pTheCanvas
185)
0e320a79 186{
7e99520b 187 SIZEL vSizl = { 0,0};
26ac77db
DW
188 ERRORID vError;
189 wxString sError;
0e320a79 190
e99762c0 191 m_pCanvas = pTheCanvas;
1408104d 192
7e99520b
DW
193 //
194 // default under PM is that Window and Client DC's are the same
195 //
e99762c0 196 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
7e99520b
DW
197 m_hPS = ::GpiCreatePS( wxGetInstance()
198 ,m_hDC
f44fdfb0 199 ,&vSizl
7e99520b
DW
200 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
201 );
202
26ac77db
DW
203 // Set the wxWindows color table
204 if (!::GpiCreateLogColorTable( m_hPS
205 ,0L
206 ,LCOLF_CONSECRGB
207 ,0L
208 ,(LONG)wxTheColourDatabase->m_nSize
209 ,(PLONG)wxTheColourDatabase->m_palTable
210 ))
211 {
212 vError = ::WinGetLastError(vHabmain);
213 sError = wxPMErrorToStr(vError);
214 wxLogError("Unable to set current color table. Error: %s\n", sError);
215 }
5afb9458
DW
216 ::GpiCreateLogColorTable( m_hPS
217 ,0L
218 ,LCOLF_RGB
219 ,0L
220 ,0L
221 ,NULL
222 );
7e99520b 223 //
5afb9458
DW
224 // Set the DC/PS rectangle
225 //
226 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
227 ,&m_vRclPaint
228 );
e1a688e4 229 InitDC();
e99762c0 230} // end of wxClientDC::wxClientDC
0e320a79 231
0367c1c0
DW
232void wxClientDC::InitDC()
233{
234 wxWindowDC::InitDC();
235
236 // in wxUniv build we must manually do some DC adjustments usually
237 // performed by Windows for us
238#ifdef __WXUNIVERSAL__
19193a2c 239 wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
0367c1c0
DW
240 if ( ptOrigin.x || ptOrigin.y )
241 {
242 // no need to shift DC origin if shift is null
243 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
244 }
245
246 // clip the DC to avoid overwriting the non client area
19193a2c 247 SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
0367c1c0
DW
248#endif // __WXUNIVERSAL__
249} // end of wxClientDC::InitDC
250
251wxClientDC::~wxClientDC()
252{
253} // end of wxClientDC::~wxClientDC
254
bc5a847c
DW
255void wxClientDC::DoGetSize(
256 int* pnWidth
257, int* pnHeight
258) const
259{
260 wxCHECK_RET( m_pCanvas, _T("wxWindowDC without a window?") );
261 m_pCanvas->GetClientSize( pnWidth
262 ,pnHeight
263 );
264} // end of wxClientDC::DoGetSize
265
23e4b7d8
DW
266// ----------------------------------------------------------------------------
267// wxPaintDC
268// ----------------------------------------------------------------------------
269
23e4b7d8
DW
270wxArrayDCInfo wxPaintDC::ms_cache;
271
272wxPaintDC::wxPaintDC()
273{
f6bcfd97 274 m_pCanvas = NULL;
23e4b7d8
DW
275 m_hDC = 0;
276}
0e320a79 277
7e99520b
DW
278wxPaintDC::wxPaintDC(
279 wxWindow* pCanvas
280)
0e320a79 281{
f44fdfb0 282 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
1408104d 283
23e4b7d8 284#ifdef __WXDEBUG__
7e99520b 285 if (g_isPainting <= 0)
23e4b7d8 286 {
223d09f6 287 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
23e4b7d8
DW
288 return;
289 }
290#endif // __WXDEBUG__
0e320a79 291
7e99520b 292 m_pCanvas = pCanvas;
1408104d 293
7e99520b
DW
294 //
295 // Do we have a DC for this window in the cache?
296 //
297 wxPaintDCInfo* pInfo = FindInCache();
298
299 if (pInfo)
0e320a79 300 {
e99762c0
DW
301 m_hDC = pInfo->m_hDC;
302 pInfo->m_nCount++;
23e4b7d8
DW
303 }
304 else // not in cache, create a new one
305 {
7e99520b
DW
306 HPS hPS;
307
308 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
309 ,NULLHANDLE
310 ,&g_paintStruct
311 );
312 if(hPS)
313 {
314 m_hOldPS = m_hPS;
315 m_hPS = hPS;
26ac77db
DW
316 ::GpiCreateLogColorTable( m_hPS
317 ,0L
318 ,LCOLF_CONSECRGB
319 ,0L
320 ,(LONG)wxTheColourDatabase->m_nSize
321 ,(PLONG)wxTheColourDatabase->m_palTable
322 );
323 ::GpiCreateLogColorTable( m_hPS
324 ,0L
325 ,LCOLF_RGB
326 ,0L
327 ,0L
328 ,NULL
329 );
8d854fa9
DW
330
331 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
eeff964a
DW
332 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
333 ,&m_vRclPaint
334 );
7e99520b 335 }
e99762c0 336
7e99520b
DW
337 m_bIsPaintTime = TRUE;
338 m_hDC = (WXHDC) -1; // to satisfy those anonizmous efforts
f6bcfd97 339 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
0e320a79 340 }
e1a688e4
DW
341 InitDC();
342} // end of wxPaintDC::wxPaintDC
0e320a79 343
23e4b7d8 344wxPaintDC::~wxPaintDC()
0e320a79 345{
23e4b7d8
DW
346 if ( m_hDC )
347 {
348 SelectOldObjects(m_hDC);
0e320a79 349
e99762c0
DW
350 size_t nIndex;
351 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
0e320a79 352
e99762c0 353 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
0e320a79 354
e99762c0 355 if ( !--pInfo->m_nCount )
23e4b7d8 356 {
ce44c50e 357 ::WinEndPaint(m_hPS);
f44fdfb0 358 m_hPS = m_hOldPS;
7e99520b 359 m_bIsPaintTime = FALSE;
893758d5 360 ms_cache.RemoveAt(nIndex);
23e4b7d8
DW
361 }
362 //else: cached DC entry is still in use
0e320a79 363
23e4b7d8
DW
364 // prevent the base class dtor from ReleaseDC()ing it again
365 m_hDC = 0;
0e320a79
DW
366 }
367}
368
e99762c0
DW
369wxPaintDCInfo* wxPaintDC::FindInCache(
370 size_t* pIndex
371) const
0e320a79 372{
e99762c0
DW
373 wxPaintDCInfo* pInfo = NULL;
374 size_t nCache = ms_cache.GetCount();
375
376 for (size_t n = 0; n < nCache; n++)
0e320a79 377 {
e99762c0
DW
378 pInfo = &ms_cache[n];
379 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
23e4b7d8 380 {
e99762c0
DW
381 if (pIndex)
382 *pIndex = n;
23e4b7d8
DW
383 break;
384 }
0e320a79 385 }
e99762c0
DW
386 return pInfo;
387} // end of wxPaintDC::FindInCache
0e320a79 388
e1a688e4
DW
389// find the entry for this DC in the cache (keyed by the window)
390WXHDC wxPaintDC::FindDCInCache(
391 wxWindow* pWin
392)
393{
394 wxPaintDCInfo* pInfo = NULL;
395 size_t nCache = ms_cache.GetCount();
396
397 for (size_t n = 0; n < nCache; n++)
398 {
399 pInfo = &ms_cache[n];
400 if (pInfo->m_hWnd == pWin->GetHWND())
401 {
402 return pInfo->m_hDC;
403 }
404 }
405 return 0;
406} // end of wxPaintDC::FindInCache
407