]> git.saurik.com Git - wxWidgets.git/blame - src/palmos/dcclient.cpp
DC headers don't need to be in gtk/private.h
[wxWidgets.git] / src / palmos / dcclient.cpp
CommitLineData
ffecfa5a 1/////////////////////////////////////////////////////////////////////////////
e2731512 2// Name: src/palmos/dcclient.cpp
ffecfa5a 3// Purpose: wxClientDC class
e2731512 4// Author: William Osborne - minimal working wxPalmOS port
ffecfa5a
JS
5// Modified by:
6// Created: 10/13/04
e2731512 7// RCS-ID: $Id$
ffecfa5a
JS
8// Copyright: (c) William Osborne
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
ffecfa5a
JS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
df91131c 27#include "wx/dcclient.h"
e2fc40b4 28#include "wx/palmos/dcclient.h"
df91131c
WS
29
30#ifndef WX_PRECOMP
31 #include "wx/string.h"
e4db172a 32 #include "wx/log.h"
cdccdfab 33 #include "wx/window.h"
df91131c
WS
34#endif
35
ffecfa5a
JS
36// ----------------------------------------------------------------------------
37// array/list types
38// ----------------------------------------------------------------------------
39
40struct WXDLLEXPORT wxPaintDCInfo
41{
e2fc40b4 42 wxPaintDCInfo(wxWindow *win, wxPaintDCImpl *dc)
ffecfa5a 43 {
e2fc40b4
VZ
44 hwnd = win->GetHWND();
45 hdc = dc->GetHDC();
46 count = 1;
ffecfa5a
JS
47 }
48
e2fc40b4
VZ
49 WXHWND hwnd; // window for this DC
50 WXHDC hdc; // the DC handle
51 size_t count; // usage count
ffecfa5a
JS
52};
53
54#include "wx/arrimpl.cpp"
55
e2fc40b4 56WX_DEFINE_OBJARRAY(wxArrayDCInfo)
ffecfa5a
JS
57
58// ----------------------------------------------------------------------------
59// macros
60// ----------------------------------------------------------------------------
61
ffecfa5a
JS
62// ----------------------------------------------------------------------------
63// global variables
64// ----------------------------------------------------------------------------
65
66#ifdef __WXDEBUG__
e2fc40b4
VZ
67 // a global variable which we check to verify that wxPaintDC are only
68 // created in response to WM_PAINT message - doing this from elsewhere is a
69 // common programming error among wxWidgets programmers and might lead to
70 // very subtle and difficult to debug refresh/repaint bugs.
ffecfa5a
JS
71 int g_isPainting = 0;
72#endif // __WXDEBUG__
73
74// ===========================================================================
75// implementation
76// ===========================================================================
77
78// ----------------------------------------------------------------------------
e2fc40b4 79// wxWindowDCImpl
ffecfa5a
JS
80// ----------------------------------------------------------------------------
81
e2fc40b4
VZ
82IMPLEMENT_ABSTRACT_CLASS(wxWindowDCImpl, wxPalmDCImpl)
83
84wxWindowDCImpl::wxWindowDCImpl( wxDC *owner ) :
85 wxPalmDCImpl( owner )
ffecfa5a
JS
86{
87}
88
e2fc40b4
VZ
89wxWindowDCImpl::wxWindowDCImpl( wxDC *owner, wxWindow *window ) :
90 wxPalmDCImpl( owner )
ffecfa5a 91{
e2fc40b4 92 wxCHECK_RET( window, _T("invalid window in wxWindowDCImpl") );
ffecfa5a
JS
93}
94
e2fc40b4 95void wxWindowDCImpl::InitDC()
ffecfa5a 96{
e2fc40b4
VZ
97
98 // since we are a window dc we need to grab the palette from the window
99#if wxUSE_PALETTE
100 InitializePalette();
101#endif
ffecfa5a
JS
102}
103
e2fc40b4 104void wxWindowDCImpl::DoGetSize(int *width, int *height) const
ffecfa5a 105{
e2fc40b4
VZ
106 wxCHECK_RET( m_window, _T("wxWindowDCImpl without a window?") );
107
108 m_window->GetSize(width, height);
ffecfa5a
JS
109}
110
111// ----------------------------------------------------------------------------
e2fc40b4 112// wxClientDCImpl
ffecfa5a
JS
113// ----------------------------------------------------------------------------
114
e2fc40b4
VZ
115IMPLEMENT_ABSTRACT_CLASS(wxClientDCImpl, wxWindowDCImpl)
116
117wxClientDCImpl::wxClientDCImpl( wxDC *owner ) :
118 wxWindowDCImpl( owner )
ffecfa5a
JS
119{
120}
121
e2fc40b4
VZ
122wxClientDCImpl::wxClientDCImpl( wxDC *owner, wxWindow *window ) :
123 wxWindowDCImpl( owner )
ffecfa5a
JS
124{
125}
126
e2fc40b4 127void wxClientDCImpl::InitDC()
ffecfa5a 128{
e2fc40b4
VZ
129 wxWindowDCImpl::InitDC();
130
131 // in wxUniv build we must manually do some DC adjustments usually
132 // performed by Windows for us
133 //
134 // we also need to take the menu/toolbar manually into account under
135 // Windows CE because they're just another control there, not anything
136 // special as usually under Windows
137#if defined(__WXUNIVERSAL__) || defined(__WXWINCE__)
138 wxPoint ptOrigin = m_window->GetClientAreaOrigin();
139 if ( ptOrigin.x || ptOrigin.y )
140 {
141 // no need to shift DC origin if shift is null
142 SetDeviceOrigin(ptOrigin.x, ptOrigin.y);
143 }
144
145 // clip the DC to avoid overwriting the non client area
146 SetClippingRegion(wxPoint(0,0), m_window->GetClientSize());
147#endif // __WXUNIVERSAL__ || __WXWINCE__
ffecfa5a
JS
148}
149
e2fc40b4 150wxClientDCImpl::~wxClientDCImpl()
ffecfa5a
JS
151{
152}
153
e2fc40b4 154void wxClientDCImpl::DoGetSize(int *width, int *height) const
ffecfa5a 155{
e2fc40b4
VZ
156 wxCHECK_RET( m_window, _T("wxClientDCImpl without a window?") );
157
158 m_window->GetClientSize(width, height);
ffecfa5a
JS
159}
160
161// ----------------------------------------------------------------------------
e2fc40b4 162// wxPaintDCImpl
ffecfa5a
JS
163// ----------------------------------------------------------------------------
164
e2fc40b4
VZ
165// VZ: initial implementation (by JACS) only remembered the last wxPaintDC
166// created and tried to reuse it - this was supposed to take care of a
167// situation when a derived class OnPaint() calls base class OnPaint()
168// because in this case ::BeginPaint() shouldn't be called second time.
169//
170// I'm not sure how useful this is, however we must remember the HWND
171// associated with the last HDC as well - otherwise we may (and will!) try
172// to reuse the HDC for another HWND which is a nice recipe for disaster.
173//
174// So we store a list of windows for which we already have the DC and not
175// just one single hDC. This seems to work, but I'm really not sure about
176// the usefullness of the whole idea - IMHO it's much better to not call
177// base class OnPaint() at all, or, if we really want to allow it, add a
178// "wxPaintDC *" parameter to wxPaintEvent which should be used if it's
179// !NULL instead of creating a new DC.
180
181IMPLEMENT_ABSTRACT_CLASS(wxPaintDCImpl, wxClientDCImpl)
182
183wxArrayDCInfo wxPaintDCImpl::ms_cache;
184
185wxPaintDCImpl::wxPaintDCImpl( wxDC *owner ) :
186 wxClientDCImpl( owner )
ffecfa5a
JS
187{
188}
189
e2fc40b4
VZ
190wxPaintDCImpl::wxPaintDCImpl( wxDC *owner, wxWindow *window ) :
191 wxClientDCImpl( owner )
ffecfa5a 192{
e2fc40b4 193 wxCHECK_RET( window, wxT("NULL canvas in wxPaintDCImpl ctor") );
ffecfa5a 194
e2fc40b4
VZ
195#ifdef __WXDEBUG__
196 if ( g_isPainting <= 0 )
197 {
198 wxFAIL_MSG( wxT("wxPaintDCImpl may be created only in EVT_PAINT handler!") );
ffecfa5a 199
e2fc40b4
VZ
200 return;
201 }
202#endif // __WXDEBUG__
203
204 m_window = window;
205
206 // do we have a DC for this window in the cache?
207 wxPaintDCInfo *info = FindInCache();
208 if ( info )
209 {
210 m_hDC = info->hdc;
211 info->count++;
212 }
213 else // not in cache, create a new one
214 {
215 //m_hDC = (WXHDC)::BeginPaint(GetHwndOf(m_window), &g_paintStruct);
216 if (m_hDC)
217 ms_cache.Add(new wxPaintDCInfo(m_window, this));
218 }
219
220 // Note: at this point m_hDC can be NULL under MicroWindows, when dragging.
221 if (!GetHDC())
222 return;
223
224 // (re)set the DC parameters.
225 InitDC();
226
227 // the HDC can have a clipping box (which we didn't set), make sure our
228 // DoGetClippingBox() checks for it
229 m_clipping = true;
ffecfa5a
JS
230}
231
e2fc40b4 232wxPaintDCImpl::~wxPaintDCImpl()
ffecfa5a 233{
e2fc40b4
VZ
234 if ( m_hDC )
235 {
236 SelectOldObjects(m_hDC);
237
238 size_t index;
239 wxPaintDCInfo *info = FindInCache(&index);
240
241 wxCHECK_RET( info, wxT("existing DC should have a cache entry") );
ffecfa5a 242
e2fc40b4
VZ
243 if ( --info->count == 0 )
244 {
245 //::EndPaint(GetHwndOf(m_window), &g_paintStruct);
e2731512 246
e2fc40b4
VZ
247 ms_cache.RemoveAt(index);
248
249 // Reduce the number of bogus reports of non-freed memory
250 // at app exit
251 if (ms_cache.IsEmpty())
252 ms_cache.Clear();
253 }
254 //else: cached DC entry is still in use
255
256 // prevent the base class dtor from ReleaseDC()ing it again
257 m_hDC = 0;
258 }
259}
260
261wxPaintDCInfo *wxPaintDCImpl::FindInCache(size_t *index) const
ffecfa5a 262{
e2fc40b4
VZ
263 wxPaintDCInfo *info = NULL;
264 size_t nCache = ms_cache.GetCount();
265 for ( size_t n = 0; n < nCache; n++ )
266 {
267 wxPaintDCInfo *info1 = &ms_cache[n];
268 if ( info1->hwnd == m_window->GetHWND() )
269 {
270 info = info1;
271 if ( index )
272 *index = n;
273 break;
274 }
275 }
276
277 return info;
ffecfa5a
JS
278}
279
e2fc40b4
VZ
280// find the entry for this DC in the cache (keyed by the window)
281WXHDC wxPaintDCImpl::FindDCInCache(wxWindow* win)
ffecfa5a 282{
e2fc40b4
VZ
283 size_t nCache = ms_cache.GetCount();
284 for ( size_t n = 0; n < nCache; n++ )
285 {
286 wxPaintDCInfo *info = &ms_cache[n];
287 if ( info->hwnd == win->GetHWND() )
288 {
289 return info->hdc;
290 }
291 }
292 return 0;
ffecfa5a 293}