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