]> git.saurik.com Git - wxWidgets.git/blame - src/mgl/region.cpp
since DoScreenToClient and ClientToScreen in toplvlcmn are implemented by calling...
[wxWidgets.git] / src / mgl / region.cpp
CommitLineData
32b8ec41
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: region.cpp
3// Purpose: Region handling for wxWindows/MGL
4// Author: Vaclav Slavik
5// RCS-ID: $Id$
8f7b34a8 6// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
32b8ec41
VZ
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "region.h"
12#endif
13
14// For compilers that support precompilation, includes "wx.h".
15#include "wx/wxprec.h"
16
17#ifdef __BORLANDC__
18#pragma hdrstop
19#endif
20
21#include "wx/region.h"
22#include "wx/gdicmn.h"
23#include "wx/thread.h"
24
25#include <mgraph.hpp>
26
27#include "wx/listimpl.cpp"
28WX_DEFINE_LIST(wxRegionRectList)
29
30IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
31IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
32
33//-----------------------------------------------------------------------------
34// wxRegionRefData implementation
35//-----------------------------------------------------------------------------
36
37class WXDLLEXPORT wxRegionRefData : public wxGDIRefData
38{
39public:
40 wxRegionRefData()
41 {
42 }
43
44 wxRegionRefData(const wxRegionRefData& data)
45 {
46 m_region = data.m_region;
47 }
48
49 ~wxRegionRefData()
50 {
51 }
52
53 MGLRegion m_region;
54};
55
56#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
57#define M_REGION_OF(r) (((wxRegionRefData*)(r.m_refData))->m_region)
58
59//-----------------------------------------------------------------------------
60// wxRegion
61//-----------------------------------------------------------------------------
62
63/*
64 * Create an empty region.
65 */
66wxRegion::wxRegion()
67{
68 m_refData = (wxRegionRefData *)NULL;
69}
70
71wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
72{
73 m_refData = new wxRegionRefData;
74 MGLRect rect(x, y, x + w, y + h);
75 M_REGION = rect;
76}
77
78wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
79{
80 m_refData = new wxRegionRefData;
08c4a8a9 81 MGLRect rect(topLeft.x, topLeft.y, bottomRight.x+1, bottomRight.y+1);
32b8ec41
VZ
82 M_REGION = rect;
83}
84
85wxRegion::wxRegion(const wxRect& r)
86{
87 m_refData = new wxRegionRefData;
08c4a8a9 88 MGLRect rect(r.GetLeft(), r.GetTop(), r.GetRight()+1, r.GetBottom()+1);
32b8ec41
VZ
89 M_REGION = rect;
90}
91
92wxRegion::wxRegion(const MGLRegion& region)
93{
94 m_refData = new wxRegionRefData;
95 M_REGION = region;
96}
97
98wxRegion::~wxRegion()
99{
100 // m_refData unrefed in ~wxObject
101}
102
103const MGLRegion& wxRegion::GetMGLRegion() const
104{
105 return M_REGION;
106}
107
108//-----------------------------------------------------------------------------
109// Modify region
110//-----------------------------------------------------------------------------
111
112// Clear current region
113void wxRegion::Clear()
114{
115 UnRef();
116}
117
118
119//-----------------------------------------------------------------------------
120// Information on region
121//-----------------------------------------------------------------------------
122
123// Outer bounds of region
124void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
125{
126 if (m_refData)
127 {
128 rect_t rect;
129 rect = M_REGION.getBounds();
130 x = rect.left;
131 y = rect.top;
132 w = rect.right - rect.left;
133 h = rect.bottom - rect.top;
134 }
135 else
136 {
137 x = y = w = h = 0;
138 }
139}
140
141wxRect wxRegion::GetBox() const
142{
143 wxCoord x, y, w, h;
144 GetBox(x, y, w, h);
145 return wxRect(x, y, w, h);
146}
147
148// Is region empty?
149bool wxRegion::Empty() const
150{
151 if (!m_refData) return TRUE;
152 return M_REGION.isEmpty();
153}
154
155//-----------------------------------------------------------------------------
156// Modifications
157//-----------------------------------------------------------------------------
158
159// Union rectangle or region with this.
160bool wxRegion::Union(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
161{
162 Unshare();
163 M_REGION += MGLRect(x, y, x + width, y + height);
164 return TRUE;
165}
166
167bool wxRegion::Union(const wxRegion& region)
168{
169 Unshare();
170 M_REGION += M_REGION_OF(region);
171 return TRUE;
172}
173
174// Intersect rectangle or region with this.
175bool wxRegion::Intersect(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
176{
177 Unshare();
178 M_REGION &= MGLRect(x, y, x + width, y + height);
179 return TRUE;
180}
181
182bool wxRegion::Intersect(const wxRegion& region)
183{
184 Unshare();
185 M_REGION &= M_REGION_OF(region);
186 return TRUE;
187}
188
189// Subtract rectangle or region from this:
190// Combines the parts of 'this' that are not part of the second region.
191bool wxRegion::Subtract(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
192{
193 Unshare();
194 M_REGION -= MGLRect(x, y, x + width, y + height);
195 return TRUE;
196}
197
198bool wxRegion::Subtract(const wxRegion& region)
199{
200 Unshare();
201 M_REGION -= M_REGION_OF(region);
202 return TRUE;
203}
204
205// XOR: the union of two combined regions except for any overlapping areas.
206bool wxRegion::Xor(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
207{
208 Unshare();
209 MGLRect rect(x, y, x + width, y + height);
210 MGLRegion rg1 = M_REGION + rect,
211 rg2 = M_REGION & rect;
212 M_REGION = rg1 - rg2;
213 return TRUE;
214}
215
216bool wxRegion::Xor(const wxRegion& region)
217{
218 Unshare();
219 MGLRegion rg1 = M_REGION + M_REGION_OF(region),
220 rg2 = M_REGION & M_REGION_OF(region);
221 M_REGION = rg1 - rg2;
222 return TRUE;
223}
224
225
226//-----------------------------------------------------------------------------
227// Tests
228//-----------------------------------------------------------------------------
229
230// Does the region contain the point (x,y)?
231wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y) const
232{
233 if (!m_refData)
234 return wxOutRegion;
235
236 if (M_REGION.includes((int)x, (int)y))
237 return wxInRegion;
238 else
239 return wxOutRegion;
240}
241
242// Does the region contain the point pt?
243wxRegionContain wxRegion::Contains(const wxPoint& pt) const
244{
245 return Contains(pt.x, pt.y);
246}
247
248// Does the region contain the rectangle (x, y, w, h)?
249wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y, wxCoord w, wxCoord h) const
250{
251 if (!m_refData)
252 return wxOutRegion;
253
254 MGLRect rect(x, y, x + w, y + h);
255 MGLRegion rg;
256
257 // 1) is the rectangle entirely covered by the region?
258 rg = MGLRegion(rect) - M_REGION;
259 if (rg.isEmpty()) return wxInRegion;
260
261 // 2) is the rectangle completely outside the region?
262 rg = M_REGION & rect; // intersection
263 if (rg.isEmpty()) return wxOutRegion;
264
265 // 3) neither case happened => it is partially covered:
266 return wxPartRegion;
267}
268
269// Does the region contain the rectangle rect
270wxRegionContain wxRegion::Contains(const wxRect& rect) const
271{
272 return Contains(rect.x, rect.y, rect.width, rect.height);
273}
274
275
276
277void wxRegion::Unshare()
278{
279 if (!m_refData)
280 {
281 m_refData = new wxRegionRefData();
282 }
283 else
284 {
285 wxRegionRefData* ref = new wxRegionRefData(*(wxRegionRefData*)m_refData);
286 UnRef();
287 m_refData = ref;
288 }
289}
290
291
292
293
294
295///////////////////////////////////////////////////////////////////////////////
296// wxRegionIterator //
297///////////////////////////////////////////////////////////////////////////////
298
299/*
300 * Initialize empty iterator
301 */
302wxRegionIterator::wxRegionIterator() : m_currentNode(NULL)
303{
304 m_rects.DeleteContents(TRUE);
305}
306
307wxRegionIterator::~wxRegionIterator()
308{
309}
310
311/*
312 * Initialize iterator for region
313 */
314wxRegionIterator::wxRegionIterator(const wxRegion& region)
315{
316 m_rects.DeleteContents(TRUE);
317 Reset(region);
318}
319
320/*
321 * Reset iterator for a new /e region.
322 */
323
324
325static wxRegionRectList *gs_rectList;
326
a246f95e 327static void MGLAPI wxMGL_region_callback(const rect_t *r)
32b8ec41
VZ
328{
329 gs_rectList->Append(new wxRect(r->left, r->top,
330 r->right - r->left, r->bottom - r->top));
331}
332
333void wxRegionIterator::Reset(const wxRegion& region)
334{
335 m_currentNode = NULL;
336 m_rects.Clear();
337
338 if (!region.Empty())
339 {
340 wxMutexGuiEnter();
341 gs_rectList = &m_rects;
342 M_REGION_OF(region).traverse(wxMGL_region_callback);
343 wxMutexGuiLeave();
344 m_currentNode = m_rects.GetFirst();
345 }
346}
347
348/*
349 * Increment iterator. The rectangle returned is the one after the
350 * incrementation.
351 */
352void wxRegionIterator::operator ++ ()
353{
354 if (m_currentNode)
355 m_currentNode = m_currentNode->GetNext();
356}
357
358/*
359 * Increment iterator. The rectangle returned is the one before the
360 * incrementation.
361 */
362void wxRegionIterator::operator ++ (int)
363{
364 if (m_currentNode)
365 m_currentNode = m_currentNode->GetNext();
366}
367
368wxCoord wxRegionIterator::GetX() const
369{
370 if (m_currentNode)
371 return m_currentNode->GetData()->x;
372 else
373 return 0;
374}
375
376wxCoord wxRegionIterator::GetY() const
377{
378 if (m_currentNode)
379 return m_currentNode->GetData()->y;
380 else
381 return 0;
382}
383
384wxCoord wxRegionIterator::GetW() const
385{
386 if (m_currentNode)
387 return m_currentNode->GetData()->width;
388 else
389 return 0;
390}
391
392wxCoord wxRegionIterator::GetH() const
393{
394 if (m_currentNode)
395 return m_currentNode->GetData()->height;
396 else
397 return 0;
398}
399