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