]> git.saurik.com Git - wxWidgets.git/blame - src/msw/region.cpp
Various changes to make pop up menus work
[wxWidgets.git] / src / msw / region.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
789295bf 2// Name: msw/region.cpp
2bda0e17
KB
3// Purpose: Region handling for wxWindows/X11
4// Author: Markus Holzem
a3b46648 5// Modified by:
2bda0e17 6// Created: Fri Oct 24 10:46:34 MET 1997
789295bf 7// RCS-ID: $Id$
2bda0e17
KB
8// Copyright: (c) 1997 Julian Smart and Markus Holzem
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "region.h"
14#endif
15
a3b46648 16// For compilers that support precompilation, includes "wx.h".
2bda0e17
KB
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#include "wx/msw/region.h"
24#include "wx/gdicmn.h"
25
0c589ad0 26#include "wx/window.h"
789295bf 27#include "wx/msw/private.h"
2bda0e17 28
2c40e41c
VZ
29IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
30IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
2bda0e17
KB
31
32//-----------------------------------------------------------------------------
33// wxRegionRefData implementation
34//-----------------------------------------------------------------------------
35
789295bf
VZ
36class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
37{
2bda0e17 38public:
789295bf
VZ
39 wxRegionRefData()
40 {
b823f5a1 41 m_region = 0;
789295bf 42 }
2bda0e17 43
789295bf
VZ
44 wxRegionRefData(const wxRegionRefData& data)
45 {
04ef50df 46#if defined(__WIN32__) && !defined(__WXMICROWIN__)
2bda0e17
KB
47 DWORD noBytes = ::GetRegionData(data.m_region, 0, NULL);
48 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
789295bf 49 ::GetRegionData(data.m_region, noBytes, rgnData);
2bda0e17
KB
50 m_region = ::ExtCreateRegion(NULL, noBytes, rgnData);
51 delete[] (char*) rgnData;
52#else
53 RECT rect;
54 ::GetRgnBox(data.m_region, &rect);
55 m_region = ::CreateRectRgnIndirect(&rect);
56#endif
789295bf 57 }
2bda0e17 58
789295bf
VZ
59 ~wxRegionRefData()
60 {
61 ::DeleteObject(m_region);
2bda0e17 62 m_region = 0;
789295bf 63 }
2bda0e17 64
789295bf 65 HRGN m_region;
2bda0e17
KB
66};
67
68#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
69
70//-----------------------------------------------------------------------------
71// wxRegion
72//-----------------------------------------------------------------------------
73
789295bf 74/*
2bda0e17
KB
75 * Create an empty region.
76 */
789295bf 77wxRegion::wxRegion()
2bda0e17 78{
f7bd3a7d 79 m_refData = (wxRegionRefData *)NULL;
2bda0e17
KB
80}
81
81d66cf3
JS
82wxRegion::wxRegion(WXHRGN hRegion)
83{
84 m_refData = new wxRegionRefData;
85 M_REGION = (HRGN) hRegion;
86}
87
9b1801c1 88wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
2bda0e17
KB
89{
90 m_refData = new wxRegionRefData;
91 M_REGION = ::CreateRectRgn(x, y, x + w, y + h);
92}
93
94wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
95{
96 m_refData = new wxRegionRefData;
97 M_REGION = ::CreateRectRgn(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y);
98}
99
100wxRegion::wxRegion(const wxRect& rect)
101{
102 m_refData = new wxRegionRefData;
bc2e39e3 103 M_REGION = ::CreateRectRgn(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
2bda0e17
KB
104}
105
5549e9f7
VZ
106wxRegion::wxRegion(size_t n, const wxPoint *points, int fillStyle)
107{
c67d6888
JS
108#ifdef __WXMICROWIN__
109 m_refData = NULL;
110 M_REGION = NULL;
111#else
5549e9f7
VZ
112 m_refData = new wxRegionRefData;
113 M_REGION = ::CreatePolygonRgn
114 (
115 (POINT*)points,
116 n,
117 fillStyle == wxODDEVEN_RULE ? ALTERNATE : WINDING
118 );
c67d6888 119#endif
5549e9f7
VZ
120}
121
789295bf 122wxRegion::~wxRegion()
2bda0e17
KB
123{
124 // m_refData unrefed in ~wxObject
125}
126
02576308 127wxObjectRefData *wxRegion::CreateRefData() const
0fb067bb
VZ
128{
129 return new wxRegionRefData;
130}
131
b8027888 132wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
0fb067bb
VZ
133{
134 return new wxRegionRefData(*(wxRegionRefData *)data);
135}
136
2bda0e17 137//-----------------------------------------------------------------------------
789295bf 138// Modify region
2bda0e17
KB
139//-----------------------------------------------------------------------------
140
789295bf
VZ
141// Clear current region
142void wxRegion::Clear()
2bda0e17 143{
789295bf 144 UnRef();
2bda0e17
KB
145}
146
0fb067bb
VZ
147bool wxRegion::Offset(wxCoord x, wxCoord y)
148{
149 if ( !x && !y )
150 {
151 // nothing to do
152 return TRUE;
153 }
154
155 AllocExclusive();
156
157 if ( ::OffsetRgn(GetHrgn(), x, y) == ERROR )
158 {
159 wxLogLastError(_T("OffsetRgn"));
160
161 return FALSE;
162 }
163
164 return TRUE;
165}
166
789295bf 167// Combine rectangle (x, y, w, h) with this.
9b1801c1 168bool wxRegion::Combine(wxCoord x, wxCoord y, wxCoord width, wxCoord height, wxRegionOp op)
2bda0e17 169{
0fb067bb 170 AllocExclusive();
2bda0e17
KB
171
172 HRGN rectRegion = ::CreateRectRgn(x, y, x + width, y + height);
173
174 int mode = 0;
175 switch (op)
176 {
177 case wxRGN_AND: mode = RGN_AND; break ;
178 case wxRGN_OR: mode = RGN_OR; break ;
179 case wxRGN_XOR: mode = RGN_XOR; break ;
180 case wxRGN_DIFF: mode = RGN_DIFF; break ;
181 case wxRGN_COPY:
182 default:
183 mode = RGN_COPY; break ;
184 }
185
0fb067bb
VZ
186 bool success = ::CombineRgn(M_REGION, M_REGION, rectRegion, mode) != ERROR;
187 if ( !success )
188 {
189 wxLogLastError(_T("CombineRgn"));
190 }
2bda0e17
KB
191
192 ::DeleteObject(rectRegion);
193
194 return success;
195}
196
789295bf 197// Union /e region with this.
2bda0e17
KB
198bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
199{
789295bf
VZ
200 if (region.Empty())
201 return FALSE;
202
0fb067bb 203 AllocExclusive();
2bda0e17
KB
204
205 int mode = 0;
206 switch (op)
207 {
208 case wxRGN_AND: mode = RGN_AND; break ;
209 case wxRGN_OR: mode = RGN_OR; break ;
210 case wxRGN_XOR: mode = RGN_XOR; break ;
211 case wxRGN_DIFF: mode = RGN_DIFF; break ;
212 case wxRGN_COPY:
213 default:
214 mode = RGN_COPY; break ;
215 }
216
789295bf 217 return (ERROR != ::CombineRgn(M_REGION, M_REGION, ((wxRegionRefData*)region.m_refData)->m_region, mode));
2bda0e17
KB
218}
219
220bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
221{
222 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
223}
224
225//-----------------------------------------------------------------------------
789295bf 226// Information on region
2bda0e17
KB
227//-----------------------------------------------------------------------------
228
229// Outer bounds of region
9b1801c1 230void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
2bda0e17 231{
2c40e41c
VZ
232 if (m_refData)
233 {
2bda0e17
KB
234 RECT rect;
235 ::GetRgnBox(M_REGION, & rect);
789295bf
VZ
236 x = rect.left;
237 y = rect.top;
238 w = rect.right - rect.left;
239 h = rect.bottom - rect.top;
2c40e41c
VZ
240 }
241 else
242 {
789295bf
VZ
243 x = y = w = h = 0;
244 }
2bda0e17
KB
245}
246
789295bf 247wxRect wxRegion::GetBox() const
2bda0e17 248{
9b1801c1 249 wxCoord x, y, w, h;
2bda0e17
KB
250 GetBox(x, y, w, h);
251 return wxRect(x, y, w, h);
252}
253
254// Is region empty?
789295bf 255bool wxRegion::Empty() const
2bda0e17 256{
9b1801c1 257 wxCoord x, y, w, h;
2bda0e17
KB
258 GetBox(x, y, w, h);
259
2c40e41c 260 return (w == 0) && (h == 0);
2bda0e17
KB
261}
262
263//-----------------------------------------------------------------------------
789295bf 264// Tests
2bda0e17
KB
265//-----------------------------------------------------------------------------
266
267// Does the region contain the point (x,y)?
9b1801c1 268wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y) const
2bda0e17 269{
789295bf
VZ
270 if (!m_refData)
271 return wxOutRegion;
2bda0e17
KB
272
273 if (::PtInRegion(M_REGION, (int) x, (int) y))
274 return wxInRegion;
275 else
276 return wxOutRegion;
277}
278
279// Does the region contain the point pt?
280wxRegionContain wxRegion::Contains(const wxPoint& pt) const
281{
789295bf
VZ
282 if (!m_refData)
283 return wxOutRegion;
2bda0e17
KB
284
285 if (::PtInRegion(M_REGION, (int) pt.x, (int) pt.y))
286 return wxInRegion;
287 else
288 return wxOutRegion;
289}
290
291// Does the region contain the rectangle (x, y, w, h)?
9b1801c1 292wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y, wxCoord w, wxCoord h) const
2bda0e17 293{
789295bf
VZ
294 if (!m_refData)
295 return wxOutRegion;
2bda0e17
KB
296
297 RECT rect;
298 rect.left = x;
299 rect.top = y;
300 rect.right = x + w;
301 rect.bottom = y + h;
302
303 if (::RectInRegion(M_REGION, & rect))
304 return wxInRegion;
305 else
306 return wxOutRegion;
307}
308
309// Does the region contain the rectangle rect
310wxRegionContain wxRegion::Contains(const wxRect& rect) const
311{
789295bf
VZ
312 if (!m_refData)
313 return wxOutRegion;
2bda0e17 314
9b1801c1 315 wxCoord x, y, w, h;
2bda0e17
KB
316 x = rect.x;
317 y = rect.y;
318 w = rect.GetWidth();
319 h = rect.GetHeight();
320 return Contains(x, y, w, h);
321}
322
a724d789
JS
323// Get internal region handle
324WXHRGN wxRegion::GetHRGN() const
325{
326 if (!m_refData)
327 return (WXHRGN) 0;
328 return (WXHRGN) M_REGION;
329}
330
2bda0e17 331///////////////////////////////////////////////////////////////////////////////
789295bf
VZ
332// //
333// wxRegionIterator //
334// //
2bda0e17
KB
335///////////////////////////////////////////////////////////////////////////////
336
789295bf 337/*
2bda0e17
KB
338 * Initialize empty iterator
339 */
789295bf 340wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
2bda0e17
KB
341{
342}
343
789295bf 344wxRegionIterator::~wxRegionIterator()
2bda0e17
KB
345{
346 if (m_rects)
347 delete[] m_rects;
348}
349
789295bf 350/*
2bda0e17
KB
351 * Initialize iterator for region
352 */
353wxRegionIterator::wxRegionIterator(const wxRegion& region)
354{
355 m_rects = NULL;
356
789295bf 357 Reset(region);
2bda0e17
KB
358}
359
789295bf 360/*
2bda0e17
KB
361 * Reset iterator for a new /e region.
362 */
363void wxRegionIterator::Reset(const wxRegion& region)
364{
789295bf
VZ
365 m_current = 0;
366 m_region = region;
2bda0e17
KB
367
368 if (m_rects)
369 delete[] m_rects;
370
371 m_rects = NULL;
372
789295bf
VZ
373 if (m_region.Empty())
374 m_numRects = 0;
375 else
2bda0e17
KB
376 {
377#if defined(__WIN32__)
378 DWORD noBytes = ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, 0, NULL);
379 RGNDATA *rgnData = (RGNDATA*) new char[noBytes];
789295bf 380 ::GetRegionData(((wxRegionRefData*)region.m_refData)->m_region, noBytes, rgnData);
2bda0e17
KB
381
382 RGNDATAHEADER* header = (RGNDATAHEADER*) rgnData;
383
384 m_rects = new wxRect[header->nCount];
385
cba2db0c 386 RECT* rect = (RECT*) ((char*)rgnData + sizeof(RGNDATAHEADER)) ;
c86f1403 387 size_t i;
2bda0e17
KB
388 for (i = 0; i < header->nCount; i++)
389 {
390 m_rects[i] = wxRect(rect->left, rect->top,
391 rect->right - rect->left, rect->bottom - rect->top);
cba2db0c 392 rect ++; // Advances pointer by sizeof(RECT)
2bda0e17
KB
393 }
394
395 m_numRects = header->nCount;
396
397 delete[] (char*) rgnData;
398#else
399 RECT rect;
400 ::GetRgnBox(((wxRegionRefData*)region.m_refData)->m_region, &rect);
401 m_rects = new wxRect[1];
402 m_rects[0].x = rect.left;
403 m_rects[0].y = rect.top;
404 m_rects[0].width = rect.right - rect.left;
405 m_rects[0].height = rect.bottom - rect.top;
406
407 m_numRects = 1;
408#endif
409 }
410}
411
789295bf 412/*
2bda0e17
KB
413 * Increment iterator. The rectangle returned is the one after the
414 * incrementation.
415 */
789295bf 416void wxRegionIterator::operator ++ ()
2bda0e17 417{
789295bf
VZ
418 if (m_current < m_numRects)
419 ++m_current;
2bda0e17
KB
420}
421
789295bf 422/*
2bda0e17
KB
423 * Increment iterator. The rectangle returned is the one before the
424 * incrementation.
425 */
426void wxRegionIterator::operator ++ (int)
427{
789295bf
VZ
428 if (m_current < m_numRects)
429 ++m_current;
2bda0e17
KB
430}
431
9b1801c1 432wxCoord wxRegionIterator::GetX() const
2bda0e17 433{
789295bf
VZ
434 if (m_current < m_numRects)
435 return m_rects[m_current].x;
436 return 0;
2bda0e17
KB
437}
438
9b1801c1 439wxCoord wxRegionIterator::GetY() const
2bda0e17 440{
789295bf
VZ
441 if (m_current < m_numRects)
442 return m_rects[m_current].y;
443 return 0;
2bda0e17
KB
444}
445
9b1801c1 446wxCoord wxRegionIterator::GetW() const
2bda0e17 447{
789295bf
VZ
448 if (m_current < m_numRects)
449 return m_rects[m_current].width ;
450 return 0;
2bda0e17
KB
451}
452
9b1801c1 453wxCoord wxRegionIterator::GetH() const
2bda0e17 454{
789295bf
VZ
455 if (m_current < m_numRects)
456 return m_rects[m_current].height;
457 return 0;
2bda0e17
KB
458}
459