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