]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dcclient.cpp
Updated distribution stuff
[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"
0e320a79 26
ce44c50e 27#include "wx/os2/private.h"
0e320a79 28
23e4b7d8 29#include "wx/dcclient.h"
0e320a79 30
23e4b7d8
DW
31// ----------------------------------------------------------------------------
32// array/list types
33// ----------------------------------------------------------------------------
0e320a79 34
23e4b7d8 35struct WXDLLEXPORT wxPaintDCInfo
0e320a79 36{
23e4b7d8
DW
37 wxPaintDCInfo(wxWindow *win, wxDC *dc)
38 {
39 hwnd = win->GetHWND();
40 hdc = dc->GetHDC();
41 count = 1;
42 }
0e320a79 43
23e4b7d8
DW
44 WXHWND hwnd; // window for this DC
45 WXHDC hdc; // the DC handle
46 size_t count; // usage count
0e320a79
DW
47};
48
23e4b7d8 49#include "wx/arrimpl.cpp"
1408104d 50
23e4b7d8 51WX_DEFINE_OBJARRAY(wxArrayDCInfo);
1408104d 52
23e4b7d8
DW
53// ----------------------------------------------------------------------------
54// macros
55// ----------------------------------------------------------------------------
0e320a79 56
23e4b7d8
DW
57 IMPLEMENT_DYNAMIC_CLASS(wxWindowDC, wxDC)
58 IMPLEMENT_DYNAMIC_CLASS(wxClientDC, wxWindowDC)
59 IMPLEMENT_DYNAMIC_CLASS(wxPaintDC, wxWindowDC)
0e320a79 60
23e4b7d8
DW
61// ----------------------------------------------------------------------------
62// global variables
63// ----------------------------------------------------------------------------
1408104d 64
ce44c50e 65static RECT g_paintStruct;
1408104d 66
23e4b7d8
DW
67#ifdef __WXDEBUG__
68 // a global variable which we check to verify that wxPaintDC are only
69 // created in resopnse to WM_PAINT message - doing this from elsewhere is a
70 // common programming error among wxWindows programmers and might lead to
71 // very subtle and difficult to debug refresh/repaint bugs.
72 int g_isPainting = 0;
73#endif // __WXDEBUG__
1408104d 74
23e4b7d8
DW
75// ===========================================================================
76// implementation
77// ===========================================================================
1408104d 78
23e4b7d8
DW
79// ----------------------------------------------------------------------------
80// wxWindowDC
81// ----------------------------------------------------------------------------
0e320a79 82
23e4b7d8 83wxWindowDC::wxWindowDC()
0e320a79 84{
26ac77db 85 m_pCanvas = NULL;
23e4b7d8 86}
0e320a79 87
23e4b7d8 88wxWindowDC::wxWindowDC(wxWindow *the_canvas)
0e320a79 89{
26ac77db
DW
90 ERRORID vError;
91 wxString sError;
1408104d 92
26ac77db
DW
93 m_pCanvas = the_canvas;
94 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(the_canvas) );
95 m_nDCCount++;
23e4b7d8 96 //
26ac77db
DW
97 // default under PM is that Window and Client DC's are the same
98 // so we offer a separate Presentation Space to use for the
99 // entire window. Otherwise, calling BeginPaint will just create
100 // chached-micro client presentation space
23e4b7d8 101 //
26ac77db
DW
102 m_hPS = GpiCreatePS( m_hab
103 ,m_hDC
104 ,&m_PageSize
105 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
106 );
107 ::GpiAssociate(m_hPS, NULLHANDLE);
108 ::GpiAssociate(m_hPS, m_hDC);
109 // Set the wxWindows color table
110 if (!::GpiCreateLogColorTable( m_hPS
111 ,0L
112 ,LCOLF_CONSECRGB
113 ,0L
114 ,(LONG)wxTheColourDatabase->m_nSize
115 ,(PLONG)wxTheColourDatabase->m_palTable
116 ))
7e99520b 117 {
26ac77db
DW
118 vError = ::WinGetLastError(vHabmain);
119 sError = wxPMErrorToStr(vError);
120 wxLogError("Unable to set current color table. Error: %s\n", sError);
7e99520b 121 }
26ac77db
DW
122 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
123}
1408104d 124
26ac77db
DW
125wxWindowDC::~wxWindowDC()
126{
127 if (m_pCanvas && m_hDC)
128 {
129 SelectOldObjects(m_hDC);
130
131 //
132 // In PM one does not explicitly close or release an open WindowDC
133 // They automatically close with the window, unless explicitly detached
134 // but we need to destroy our PS
135 //
136 if(m_hPS)
137 {
138 ::GpiAssociate(m_hPS, NULLHANDLE);
139 ::GpiDestroyPS(m_hPS);
140 }
141 m_hPS = NULLHANDLE;
142 m_hDC = NULLHANDLE;
143 }
144 m_nDCCount--;
23e4b7d8 145}
0e320a79 146
23e4b7d8
DW
147// ----------------------------------------------------------------------------
148// wxClientDC
149// ----------------------------------------------------------------------------
0e320a79 150
23e4b7d8 151wxClientDC::wxClientDC()
0e320a79 152{
26ac77db 153 m_pCanvas = NULL;
23e4b7d8 154}
0e320a79 155
23e4b7d8 156wxClientDC::wxClientDC(wxWindow *the_canvas)
0e320a79 157{
7e99520b 158 SIZEL vSizl = { 0,0};
26ac77db
DW
159 ERRORID vError;
160 wxString sError;
0e320a79 161
7e99520b 162 m_pCanvas = the_canvas;
1408104d 163
7e99520b
DW
164 //
165 // default under PM is that Window and Client DC's are the same
166 //
167 m_hDC = (WXHDC) ::WinOpenWindowDC(GetWinHwnd(the_canvas));
168 m_hPS = ::GpiCreatePS( wxGetInstance()
169 ,m_hDC
f44fdfb0 170 ,&vSizl
7e99520b
DW
171 ,PU_PELS | GPIF_LONG | GPIA_ASSOC
172 );
173
26ac77db
DW
174 // Set the wxWindows color table
175 if (!::GpiCreateLogColorTable( m_hPS
176 ,0L
177 ,LCOLF_CONSECRGB
178 ,0L
179 ,(LONG)wxTheColourDatabase->m_nSize
180 ,(PLONG)wxTheColourDatabase->m_palTable
181 ))
182 {
183 vError = ::WinGetLastError(vHabmain);
184 sError = wxPMErrorToStr(vError);
185 wxLogError("Unable to set current color table. Error: %s\n", sError);
186 }
7e99520b
DW
187 //
188 // Default mode is BM_LEAVEALONE so we make no call Set the mix
189 //
190 SetBackground(wxBrush( m_pCanvas->GetBackgroundColour()
191 ,wxSOLID
192 )
193 );
23e4b7d8 194}
0e320a79 195
23e4b7d8 196wxClientDC::~wxClientDC()
0e320a79 197{
26ac77db
DW
198 if ( m_pCanvas && GetHdc() )
199 {
200 SelectOldObjects(m_hDC);
ce44c50e 201
26ac77db
DW
202 //
203 // We don't explicitly release Device contexts in PM and
204 // the cached micro PS is already gone
205 //
206 m_hDC = 0;
207 }
23e4b7d8 208}
0e320a79 209
23e4b7d8
DW
210// ----------------------------------------------------------------------------
211// wxPaintDC
212// ----------------------------------------------------------------------------
213
214// VZ: initial implementation (by JACS) only remembered the last wxPaintDC
215// created and tried to reuse - this was supposed to take care of a
216// situation when a derived class OnPaint() calls base class OnPaint()
217// because in this case ::BeginPaint() shouldn't be called second time.
218//
219// I'm not sure how useful this is, however we must remember the HWND
220// associated with the last HDC as well - otherwise we may (and will!) try
221// to reuse the HDC for another HWND which is a nice recipe for disaster.
222//
223// So we store a list of windows for which we already have the DC and not
224// just one single hDC. This seems to work, but I'm really not sure about
225// the usefullness of the whole idea - IMHO it's much better to not call
226// base class OnPaint() at all, or, if we really want to allow it, add a
227// "wxPaintDC *" parameter to wxPaintEvent which should be used if it's
228// !NULL instead of creating a new DC.
229
230wxArrayDCInfo wxPaintDC::ms_cache;
231
232wxPaintDC::wxPaintDC()
233{
f6bcfd97 234 m_pCanvas = NULL;
23e4b7d8
DW
235 m_hDC = 0;
236}
0e320a79 237
7e99520b
DW
238wxPaintDC::wxPaintDC(
239 wxWindow* pCanvas
240)
0e320a79 241{
f44fdfb0 242 wxCHECK_RET(pCanvas, wxT("NULL canvas in wxPaintDC ctor"));
26ac77db 243 RECTL vRect;
1408104d 244
23e4b7d8 245#ifdef __WXDEBUG__
7e99520b 246 if (g_isPainting <= 0)
23e4b7d8 247 {
223d09f6 248 wxFAIL_MSG( wxT("wxPaintDC may be created only in EVT_PAINT handler!") );
23e4b7d8
DW
249 return;
250 }
251#endif // __WXDEBUG__
0e320a79 252
7e99520b 253 m_pCanvas = pCanvas;
1408104d 254
7e99520b
DW
255 //
256 // Do we have a DC for this window in the cache?
257 //
258 wxPaintDCInfo* pInfo = FindInCache();
259
260 if (pInfo)
0e320a79 261 {
7e99520b
DW
262 m_hDC = pInfo->hdc;
263 pInfo->count++;
23e4b7d8
DW
264 }
265 else // not in cache, create a new one
266 {
7e99520b
DW
267 HPS hPS;
268
269 hPS = ::WinBeginPaint( GetWinHwnd(m_pCanvas)
270 ,NULLHANDLE
271 ,&g_paintStruct
272 );
273 if(hPS)
274 {
275 m_hOldPS = m_hPS;
276 m_hPS = hPS;
26ac77db
DW
277 ::GpiCreateLogColorTable( m_hPS
278 ,0L
279 ,LCOLF_CONSECRGB
280 ,0L
281 ,(LONG)wxTheColourDatabase->m_nSize
282 ,(PLONG)wxTheColourDatabase->m_palTable
283 );
284 ::GpiCreateLogColorTable( m_hPS
285 ,0L
286 ,LCOLF_RGB
287 ,0L
288 ,0L
289 ,NULL
290 );
7e99520b
DW
291 }
292 m_bIsPaintTime = TRUE;
293 m_hDC = (WXHDC) -1; // to satisfy those anonizmous efforts
294 m_vRclPaint = g_paintStruct;
f6bcfd97 295 ms_cache.Add(new wxPaintDCInfo(m_pCanvas, this));
0e320a79 296 }
f6bcfd97 297 SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID));
0e320a79
DW
298}
299
23e4b7d8 300wxPaintDC::~wxPaintDC()
0e320a79 301{
23e4b7d8
DW
302 if ( m_hDC )
303 {
304 SelectOldObjects(m_hDC);
0e320a79 305
23e4b7d8
DW
306 size_t index;
307 wxPaintDCInfo *info = FindInCache(&index);
0e320a79 308
223d09f6 309 wxCHECK_RET( info, wxT("existing DC should have a cache entry") );
0e320a79 310
23e4b7d8
DW
311 if ( !--info->count )
312 {
ce44c50e 313 ::WinEndPaint(m_hPS);
f44fdfb0 314 m_hPS = m_hOldPS;
7e99520b 315 m_bIsPaintTime = FALSE;
23e4b7d8
DW
316 ms_cache.Remove(index);
317 }
318 //else: cached DC entry is still in use
0e320a79 319
23e4b7d8
DW
320 // prevent the base class dtor from ReleaseDC()ing it again
321 m_hDC = 0;
0e320a79
DW
322 }
323}
324
23e4b7d8 325wxPaintDCInfo *wxPaintDC::FindInCache(size_t *index) const
0e320a79 326{
23e4b7d8
DW
327 wxPaintDCInfo *info = NULL;
328 size_t nCache = ms_cache.GetCount();
329 for ( size_t n = 0; n < nCache; n++ )
0e320a79 330 {
23e4b7d8 331 info = &ms_cache[n];
f6bcfd97 332 if ( info->hwnd == m_pCanvas->GetHWND() )
23e4b7d8
DW
333 {
334 if ( index )
335 *index = n;
336 break;
337 }
0e320a79
DW
338 }
339
23e4b7d8
DW
340 return info;
341}