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