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