]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/dcclient.cpp
implemented Freeze/Thaw() (patch 922156)
[wxWidgets.git] / src / os2 / dcclient.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: 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/string.h"
24#include "wx/log.h"
25#include "wx/window.h"
26#include "wx/app.h"
27
28#include "wx/os2/private.h"
29
30#include "wx/dcclient.h"
31
32// ----------------------------------------------------------------------------
33// array/list types
34// ----------------------------------------------------------------------------
35
36struct WXDLLEXPORT wxPaintDCInfo
37{
38 wxPaintDCInfo( wxWindow* pWin
39 ,wxDC* pDC
40 )
41 {
42 m_hWnd = pWin->GetHWND();
43 m_hDC = pDC->GetHDC();
44 m_nCount = 1;
45 }
46
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
51
52#include "wx/arrimpl.cpp"
53
54WX_DEFINE_OBJARRAY(wxArrayDCInfo);
55
56// ----------------------------------------------------------------------------
57// macros
58// ----------------------------------------------------------------------------
59
60 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
61 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
62 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
63
64// ----------------------------------------------------------------------------
65// global variables
66// ----------------------------------------------------------------------------
67
68static RECT g_paintStruct;
69
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__
77
78// ===========================================================================
79// implementation
80// ===========================================================================
81
82// ----------------------------------------------------------------------------
83// wxWindowDC
84// ----------------------------------------------------------------------------
85
86wxWindowDC::wxWindowDC()
87{
88 m_pCanvas = NULL;
89}
90
91wxWindowDC::wxWindowDC(
92 wxWindow* pTheCanvas
93)
94{
95 ERRORID vError;
96 wxString sError;
97
98 m_pCanvas = pTheCanvas;
99 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas) );
100
101 //
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
106 //
107 m_hPS = ::GpiCreatePS( vHabmain
108 ,m_hDC
109 ,&m_PageSize
110 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
111 );
112 ::GpiAssociate(m_hPS, NULLHANDLE);
113 ::GpiAssociate(m_hPS, m_hDC);
114
115 //
116 // Set the wxWindows color table
117 //
118 if (!::GpiCreateLogColorTable( m_hPS
119 ,0L
120 ,LCOLF_CONSECRGB
121 ,0L
122 ,(LONG)wxTheColourDatabase->m_nSize
123 ,(PLONG)wxTheColourDatabase->m_palTable
124 ))
125 {
126 vError = ::WinGetLastError(vHabmain);
127 sError = wxPMErrorToStr(vError);
128 wxLogError("Unable to set current color table. Error: %s\n", sError.c_str());
129 }
130 ::GpiCreateLogColorTable( m_hPS
131 ,0L
132 ,LCOLF_RGB
133 ,0L
134 ,0L
135 ,NULL
136 );
137 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
138 ,&m_vRclPaint
139 );
140 InitDC();
141} // end of wxWindowDC::wxWindowDC
142
143void wxWindowDC::InitDC()
144{
145
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);
151
152 //
153 // Default bg colour is pne of the window
154 //
155 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
156
157 wxColour vColor( wxT("BLACK") );
158 m_pen.SetColour(vColor);
159
160 vColor.Set( wxT("WHITE") );
161 m_brush.SetColour(vColor);
162 InitializePalette();
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
175} // end of wxWindowDC::InitDC
176
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
188// ----------------------------------------------------------------------------
189// wxClientDC
190// ----------------------------------------------------------------------------
191
192wxClientDC::wxClientDC()
193{
194 m_pCanvas = NULL;
195}
196
197wxClientDC::wxClientDC(
198 wxWindow* pTheCanvas
199)
200{
201 SIZEL vSizl = { 0,0};
202 ERRORID vError;
203 wxString sError;
204
205 m_pCanvas = pTheCanvas;
206
207 //
208 // default under PM is that Window and Client DC's are the same
209 //
210 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(pTheCanvas));
211 m_hPS = ::GpiCreatePS( wxGetInstance()
212 ,m_hDC
213 ,&vSizl
214 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
215 );
216
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);
228 wxLogError("Unable to set current color table. Error: %s\n", sError.c_str());
229 }
230 ::GpiCreateLogColorTable( m_hPS
231 ,0L
232 ,LCOLF_RGB
233 ,0L
234 ,0L
235 ,NULL
236 );
237 //
238 // Set the DC/PS rectangle
239 //
240 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
241 ,&m_vRclPaint
242 );
243 InitDC();
244} // end of wxClientDC::wxClientDC
245
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__
253 wxPoint ptOrigin = m_pCanvas->GetClientAreaOrigin();
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
261 SetClippingRegion(wxPoint(0, 0), m_pCanvas->GetClientSize());
262#endif // __WXUNIVERSAL__
263} // end of wxClientDC::InitDC
264
265wxClientDC::~wxClientDC()
266{
267} // end of wxClientDC::~wxClientDC
268
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
280// ----------------------------------------------------------------------------
281// wxPaintDC
282// ----------------------------------------------------------------------------
283
284wxArrayDCInfo wxPaintDC::ms_cache;
285
286wxPaintDC::wxPaintDC()
287{
288 m_pCanvas = NULL;
289 m_hDC = 0;
290}
291
292wxPaintDC::wxPaintDC(
293 wxWindow* pCanvas
294)
295{
296 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
297
298#ifdef __WXDEBUG__
299 if (g_isPainting <= 0)
300 {
301 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
302 return;
303 }
304#endif // __WXDEBUG__
305
306 m_pCanvas = pCanvas;
307
308 //
309 // Do we have a DC for this window in the cache?
310 //
311 wxPaintDCInfo* pInfo = FindInCache();
312
313 if (pInfo)
314 {
315 m_hDC = pInfo->m_hDC;
316 pInfo->m_nCount++;
317 }
318 else // not in cache, create a new one
319 {
320 HPS hPS;
321
322 m_hDC = ::WinOpenWindowDC(GetWinHwnd(m_pCanvas));
323 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
324 ,NULLHANDLE
325 ,&g_paintStruct
326 );
327 if(hPS)
328 {
329 ::GpiAssociate(hPS, m_hDC);
330 m_hOldPS = m_hPS;
331 m_hPS = hPS;
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 );
346
347 ::WinFillRect(hPS, &g_paintStruct, m_pCanvas->GetBackgroundColour().GetPixel());
348 ::WinQueryWindowRect( GetWinHwnd(m_pCanvas)
349 ,&m_vRclPaint
350 );
351 }
352
353 m_bIsPaintTime = TRUE;
354 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
355 }
356 InitDC();
357} // end of wxPaintDC::wxPaintDC
358
359wxPaintDC::~wxPaintDC()
360{
361 if ( m_hDC )
362 {
363 SelectOldObjects(m_hDC);
364
365 size_t nIndex;
366 wxPaintDCInfo* pInfo = FindInCache(&nIndex);
367
368 wxCHECK_RET( pInfo, wxT("existing DC should have a cache entry") );
369
370 if ( !--pInfo->m_nCount )
371 {
372 ::WinEndPaint(m_hPS);
373 m_hPS = m_hOldPS;
374 m_bIsPaintTime = FALSE;
375 ms_cache.RemoveAt(nIndex);
376 }
377 //else: cached DC entry is still in use
378
379 // prevent the base class dtor from ReleaseDC()ing it again
380 m_hDC = 0;
381 }
382}
383
384wxPaintDCInfo* wxPaintDC::FindInCache(
385 size_t* pIndex
386) const
387{
388 wxPaintDCInfo* pInfo = NULL;
389 size_t nCache = ms_cache.GetCount();
390
391 for (size_t n = 0; n < nCache; n++)
392 {
393 pInfo = &ms_cache[n];
394 if (pInfo->m_hWnd == m_pCanvas->GetHWND())
395 {
396 if (pIndex)
397 *pIndex = n;
398 break;
399 }
400 }
401 return pInfo;
402} // end of wxPaintDC::FindInCache
403
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