Include wx/app.h according to precompiled headers of wx/wx.h (with other minor cleaning).
[wxWidgets.git] / src / os2 / dcclient.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/dcclient.cpp
3 // Purpose: wxClientDC class
4 // Author: David Webster
5 // Modified by:
6 // Created: 09/21/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #include "wx/dcclient.h"
24
25 #ifndef WX_PRECOMP
26 #include "wx/string.h"
27 #include "wx/log.h"
28 #include "wx/app.h"
29 #endif
30
31 #include "wx/window.h"
32
33 #include "wx/os2/private.h"
34
35 // ----------------------------------------------------------------------------
36 // array/list types
37 // ----------------------------------------------------------------------------
38
39 struct WXDLLEXPORT wxPaintDCInfo
40 {
41 wxPaintDCInfo( wxWindow* pWin
42 ,wxDC* pDC
43 )
44 {
45 m_hWnd = pWin->GetHWND();
46 m_hDC = pDC->GetHDC();
47 m_nCount = 1;
48 }
49
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
54
55 #include "wx/arrimpl.cpp"
56
57 WX_DEFINE_OBJARRAY(wxArrayDCInfo);
58
59 // ----------------------------------------------------------------------------
60 // macros
61 // ----------------------------------------------------------------------------
62
63 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
64 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
65 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
66
67 // ----------------------------------------------------------------------------
68 // global variables
69 // ----------------------------------------------------------------------------
70
71 static RECT g_paintStruct;
72
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
76 // common programming error among wxWidgets programmers and might lead to
77 // very subtle and difficult to debug refresh/repaint bugs.
78 int g_isPainting = 0;
79 #endif // __WXDEBUG__
80
81 // ===========================================================================
82 // implementation
83 // ===========================================================================
84
85 // ----------------------------------------------------------------------------
86 // wxWindowDC
87 // ----------------------------------------------------------------------------
88
89 wxWindowDC::wxWindowDC()
90 {
91 m_pCanvas = NULL;
92 m_PageSize.cx = m_PageSize.cy = 0;
93
94 }
95
96 wxWindowDC::wxWindowDC(
97 wxWindow* pTheCanvas
98 )
99 {
100 ERRORID vError;
101 wxString sError;
102 int nWidth, nHeight;
103
104 m_pCanvas = pTheCanvas;
105 DoGetSize(&nWidth, &nHeight);
106 m_PageSize.cx = nWidth;
107 m_PageSize.cy = nHeight;
108 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
109
110 //
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
115 //
116 m_hPS = ::GpiCreatePS( vHabmain
117 ,m_hDC
118 ,&m_PageSize
119 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
120 );
121 if (!m_hPS)
122 {
123 vError = ::WinGetLastError(vHabmain);
124 sError = wxPMErrorToStr(vError);
125 wxLogError(_T("Unable to create presentation space. Error: %s\n"), sError.c_str());
126 }
127 ::GpiAssociate(m_hPS, NULLHANDLE);
128 ::GpiAssociate(m_hPS, m_hDC);
129
130 //
131 // Set the wxWidgets color table
132 //
133 if (!::GpiCreateLogColorTable( m_hPS
134 ,0L
135 ,LCOLF_CONSECRGB
136 ,0L
137 ,(LONG)wxTheColourDatabase->m_nSize
138 ,(PLONG)wxTheColourDatabase->m_palTable
139 ))
140 {
141 vError = ::WinGetLastError(vHabmain);
142 sError = wxPMErrorToStr(vError);
143 wxLogError(_T("Unable to set current color table. Error: %s\n"), sError.c_str());
144 }
145 ::GpiCreateLogColorTable( m_hPS
146 ,0L
147 ,LCOLF_RGB
148 ,0L
149 ,0L
150 ,NULL
151 );
152 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
153 ,&m_vRclPaint
154 );
155 InitDC();
156 } // end of wxWindowDC::wxWindowDC
157
158 void wxWindowDC::InitDC()
159 {
160
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);
166
167 //
168 // Default bg colour is pne of the window
169 //
170 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
171
172 wxColour vColor( wxT("BLACK") );
173 m_pen.SetColour(vColor);
174
175 vColor.Set( wxT("WHITE") );
176 m_brush.SetColour(vColor);
177 InitializePalette();
178 wxFont* pFont = new wxFont( 10
179 ,wxMODERN
180 ,wxNORMAL
181 ,wxBOLD
182 );
183 SetFont(*pFont);
184 delete pFont;
185 //
186 // OS/2 default vertical character alignment needs to match the other OS's
187 //
188 ::GpiSetTextAlignment((HPS)GetHPS(), TA_NORMAL_HORIZ, TA_BOTTOM);
189
190 } // end of wxWindowDC::InitDC
191
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
203 // ----------------------------------------------------------------------------
204 // wxClientDC
205 // ----------------------------------------------------------------------------
206
207 wxClientDC::wxClientDC()
208 {
209 m_pCanvas = NULL;
210 }
211
212 wxClientDC::wxClientDC(
213 wxWindow* pTheCanvas
214 )
215 {
216 SIZEL vSizl = { 0,0};
217 ERRORID vError;
218 wxString sError;
219
220 m_pCanvas = pTheCanvas;
221
222 //
223 // default under PM is that Window and Client DC's are the same
224 //
225 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
226 m_hPS = ::GpiCreatePS( wxGetInstance()
227 ,m_hDC
228 ,&vSizl
229 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
230 );
231
232 // Set the wxWidgets color table
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);
243 wxLogError(_T("Unable to set current color table. Error: %s\n"), sError.c_str());
244 }
245 ::GpiCreateLogColorTable( m_hPS
246 ,0L
247 ,LCOLF_RGB
248 ,0L
249 ,0L
250 ,NULL
251 );
252 //
253 // Set the DC/PS rectangle
254 //
255 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
256 ,&m_vRclPaint
257 );
258 InitDC();
259 } // end of wxClientDC::wxClientDC
260
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__
268 wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
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
276 SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
277 #endif // __WXUNIVERSAL__
278 } // end of wxClientDC::InitDC
279
280 wxClientDC::~wxClientDC()
281 {
282 } // end of wxClientDC::~wxClientDC
283
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
295 // ----------------------------------------------------------------------------
296 // wxPaintDC
297 // ----------------------------------------------------------------------------
298
299 wxArrayDCInfo wxPaintDC::ms_cache;
300
301 wxPaintDC::wxPaintDC()
302 {
303 m_pCanvas = NULL;
304 m_hDC = 0;
305 }
306
307 wxPaintDC::wxPaintDC(
308 wxWindow* pCanvas
309 )
310 {
311 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
312
313 #ifdef __WXDEBUG__
314 if (g_isPainting <= 0)
315 {
316 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
317 return;
318 }
319 #endif // __WXDEBUG__
320
321 m_pCanvas = pCanvas;
322
323 //
324 // Do we have a DC for this window in the cache?
325 //
326 wxPaintDCInfo* pInfo = FindInCache();
327
328 if (pInfo)
329 {
330 m_hDC = pInfo->m_hDC;
331 pInfo->m_nCount++;
332 }
333 else // not in cache, create a new one
334 {
335 HPS hPS;
336
337 m_hDC = ::WinOpenWindowDC(GetWinHwnd(m_pCanvas));
338 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
339 ,NULLHANDLE
340 ,&g_paintStruct
341 );
342 if(hPS)
343 {
344 ::GpiAssociate(hPS, m_hDC);
345 m_hOldPS = m_hPS;
346 m_hPS = hPS;
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 );
361
362 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
363 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
364 ,&m_vRclPaint
365 );
366 }
367
368 m_bIsPaintTime = true;
369 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
370 }
371 InitDC();
372 } // end of wxPaintDC::wxPaintDC
373
374 wxPaintDC::~wxPaintDC()
375 {
376 if ( m_hDC )
377 {
378 SelectOldObjects(m_hDC);
379
380 size_t nIndex;
381 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
382
383 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
384
385 if ( !--pInfo->m_nCount )
386 {
387 ::WinEndPaint(m_hPS);
388 m_hPS = m_hOldPS;
389 m_bIsPaintTime = false;
390 ms_cache.RemoveAt(nIndex);
391 }
392 //else: cached DC entry is still in use
393
394 // prevent the base class dtor from ReleaseDC()ing it again
395 m_hDC = 0;
396 }
397 }
398
399 wxPaintDCInfo* wxPaintDC::FindInCache(
400 size_t* pIndex
401 ) const
402 {
403 wxPaintDCInfo* pInfo = NULL;
404 size_t nCache = ms_cache.GetCount();
405
406 for (size_t n = 0; n < nCache; n++)
407 {
408 pInfo = &ms_cache[n];
409 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
410 {
411 if (pIndex)
412 *pIndex = n;
413 break;
414 }
415 }
416 return pInfo;
417 } // end of wxPaintDC::FindInCache
418
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