]>
Commit | Line | Data |
---|---|---|
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 | 39 | struct 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 | 57 | WX_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 | 71 | static 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 | 89 | wxWindowDC::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 |
96 | wxWindowDC::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 | 158 | void 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 |
192 | void 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 | 207 | wxClientDC::wxClientDC() |
0e320a79 | 208 | { |
26ac77db | 209 | m_pCanvas = NULL; |
23e4b7d8 | 210 | } |
0e320a79 | 211 | |
e99762c0 DW |
212 | wxClientDC::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 |
261 | void 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 | ||
280 | wxClientDC::~wxClientDC() | |
281 | { | |
282 | } // end of wxClientDC::~wxClientDC | |
283 | ||
bc5a847c DW |
284 | void 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 |
299 | wxArrayDCInfo wxPaintDC::ms_cache; |
300 | ||
301 | wxPaintDC::wxPaintDC() | |
302 | { | |
f6bcfd97 | 303 | m_pCanvas = NULL; |
23e4b7d8 DW |
304 | m_hDC = 0; |
305 | } | |
0e320a79 | 306 | |
7e99520b DW |
307 | wxPaintDC::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 | 374 | wxPaintDC::~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 |
399 | wxPaintDCInfo* 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) |
420 | WXHDC 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 |