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