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