]> git.saurik.com Git - wxWidgets.git/blob - src/mac/region.cpp
fixed (rare but fatal) bug in wxWindowDisabler
[wxWidgets.git] / src / mac / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // File: region.cpp
3 // Purpose: Region class
4 // Author: Markus Holzem/Julian Smart/AUTHOR
5 // Created: Fri Oct 24 10:46:34 MET 1997
6 // RCS-ID: $Id$
7 // Copyright: (c) 1997 Markus Holzem/Julian Smart/AUTHOR
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
12 #pragma implementation "region.h"
13 #endif
14
15 #include "wx/region.h"
16 #include "wx/gdicmn.h"
17
18 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
19 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
20
21 //-----------------------------------------------------------------------------
22 // wxRegionRefData implementation
23 //-----------------------------------------------------------------------------
24
25 class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
26 public:
27 wxRegionRefData()
28 {
29 m_macRgn = NewRgn() ;
30 }
31
32 wxRegionRefData(const wxRegionRefData& data)
33 {
34 m_macRgn = NewRgn() ;
35 CopyRgn( data.m_macRgn , m_macRgn ) ;
36 }
37
38 ~wxRegionRefData()
39 {
40 DisposeRgn( m_macRgn ) ;
41 }
42 RgnHandle m_macRgn ;
43 };
44
45 #define M_REGION (((wxRegionRefData*)m_refData)->m_macRgn)
46 #define OTHER_M_REGION(a) (((wxRegionRefData*)(a.m_refData))->m_macRgn)
47
48 //-----------------------------------------------------------------------------
49 // wxRegion
50 //-----------------------------------------------------------------------------
51
52 /*!
53 * Create an empty region.
54 */
55 wxRegion::wxRegion()
56 {
57 m_refData = new wxRegionRefData;
58 }
59
60 wxRegion::wxRegion(WXHRGN hRegion )
61 {
62 m_refData = new wxRegionRefData;
63 CopyRgn( hRegion , M_REGION ) ;
64 }
65
66 wxRegion::wxRegion(long x, long y, long w, long h)
67 {
68 m_refData = new wxRegionRefData;
69 SetRectRgn( M_REGION , x , y , x+w , y+h ) ;
70 }
71
72 wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
73 {
74 m_refData = new wxRegionRefData;
75 SetRectRgn( M_REGION , topLeft.x , topLeft.y , bottomRight.x , bottomRight.y ) ;
76 }
77
78 wxRegion::wxRegion(const wxRect& rect)
79 {
80 m_refData = new wxRegionRefData;
81 SetRectRgn( M_REGION , rect.x , rect.y , rect.x+rect.width , rect.y+rect.height ) ;
82 }
83
84 /*!
85 * Destroy the region.
86 */
87 wxRegion::~wxRegion()
88 {
89 // m_refData unrefed in ~wxObject
90 }
91
92 //-----------------------------------------------------------------------------
93 //# Modify region
94 //-----------------------------------------------------------------------------
95
96 //! Clear current region
97 void wxRegion::Clear()
98 {
99 UnRef();
100 }
101
102 //! Combine rectangle (x, y, w, h) with this.
103 bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
104 {
105 // Don't change shared data
106 if (!m_refData)
107 {
108 m_refData = new wxRegionRefData();
109 }
110 else if (m_refData->GetRefCount() > 1)
111 {
112 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
113 UnRef();
114 m_refData = new wxRegionRefData(*ref);
115 }
116 RgnHandle rgn = NewRgn() ;
117 SetRectRgn( rgn , x , y, x+width,y + height ) ;
118
119 switch (op)
120 {
121 case wxRGN_AND:
122 SectRgn( M_REGION , rgn , M_REGION ) ;
123 break ;
124 case wxRGN_OR:
125 UnionRgn( M_REGION , rgn , M_REGION ) ;
126 break ;
127 case wxRGN_XOR:
128 XorRgn( M_REGION , rgn , M_REGION ) ;
129 break ;
130 case wxRGN_DIFF:
131 DiffRgn( M_REGION , rgn , M_REGION ) ;
132 break ;
133 case wxRGN_COPY:
134 default:
135 CopyRgn( rgn ,M_REGION ) ;
136 break ;
137 }
138
139 DisposeRgn( rgn ) ;
140
141 return TRUE;
142 }
143
144 //! Union /e region with this.
145 bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
146 {
147 if (region.Empty())
148 return FALSE;
149
150 // Don't change shared data
151 if (!m_refData) {
152 m_refData = new wxRegionRefData();
153 }
154 else if (m_refData->GetRefCount() > 1)
155 {
156 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
157 UnRef();
158 m_refData = new wxRegionRefData(*ref);
159 }
160
161 switch (op)
162 {
163 case wxRGN_AND:
164 SectRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
165 break ;
166 case wxRGN_OR:
167 UnionRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
168 break ;
169 case wxRGN_XOR:
170 XorRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
171 break ;
172 case wxRGN_DIFF:
173 DiffRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
174 break ;
175 case wxRGN_COPY:
176 default:
177 CopyRgn( OTHER_M_REGION(region) ,M_REGION ) ;
178 break ;
179 }
180
181 return TRUE;
182 }
183
184 bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
185 {
186 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
187 }
188
189 //-----------------------------------------------------------------------------
190 //# Information on region
191 //-----------------------------------------------------------------------------
192
193 // Outer bounds of region
194 void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
195 {
196 if (m_refData)
197 {
198 Rect box = (**M_REGION).rgnBBox ;
199 x = box.left ;
200 y = box.top ;
201 w = box.right - box.left ;
202 h = box.bottom - box.top ;
203 }
204 else
205 {
206 x = y = w = h = 0;
207 }
208 }
209
210 wxRect wxRegion::GetBox() const
211 {
212 long x, y, w, h;
213 GetBox(x, y, w, h);
214 return wxRect(x, y, w, h);
215 }
216
217 // Is region empty?
218 bool wxRegion::Empty() const
219 {
220 return EmptyRgn( M_REGION ) ;
221 }
222
223 const WXHRGN wxRegion::GetWXHRGN() const
224 {
225 return M_REGION ;
226 }
227
228 //-----------------------------------------------------------------------------
229 //# Tests
230 //-----------------------------------------------------------------------------
231
232 // Does the region contain the point (x,y)?
233 wxRegionContain wxRegion::Contains(long x, long y) const
234 {
235 if (!m_refData)
236 return wxOutRegion;
237
238 // TODO. Return wxInRegion if within region.
239 if (0)
240 return wxInRegion;
241 return wxOutRegion;
242 }
243
244 // Does the region contain the point pt?
245 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
246 {
247 if (!m_refData)
248 return wxOutRegion;
249
250 Point p = { pt.y , pt.x } ;
251 if (PtInRgn( p , M_REGION ) )
252 return wxInRegion;
253
254 return wxOutRegion;
255 }
256
257 // Does the region contain the rectangle (x, y, w, h)?
258 wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
259 {
260 if (!m_refData)
261 return wxOutRegion;
262
263 Rect rect = { y , x , y + h , x + w } ;
264 if (RectInRgn( &rect , M_REGION ) )
265 return wxInRegion;
266 else
267 return wxOutRegion;
268 }
269
270 // Does the region contain the rectangle rect
271 wxRegionContain wxRegion::Contains(const wxRect& rect) const
272 {
273 if (!m_refData)
274 return wxOutRegion;
275
276 long x, y, w, h;
277 x = rect.x;
278 y = rect.y;
279 w = rect.GetWidth();
280 h = rect.GetHeight();
281 return Contains(x, y, w, h);
282 }
283
284 ///////////////////////////////////////////////////////////////////////////////
285 // //
286 // wxRegionIterator //
287 // //
288 ///////////////////////////////////////////////////////////////////////////////
289
290 /*!
291 * Initialize empty iterator
292 */
293 wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
294 {
295 }
296
297 wxRegionIterator::~wxRegionIterator()
298 {
299 if (m_rects)
300 delete[] m_rects;
301 }
302
303 /*!
304 * Initialize iterator for region
305 */
306 wxRegionIterator::wxRegionIterator(const wxRegion& region)
307 {
308 m_rects = NULL;
309
310 Reset(region);
311 }
312
313 /*!
314 * Reset iterator for a new /e region.
315 */
316 void wxRegionIterator::Reset(const wxRegion& region)
317 {
318 m_current = 0;
319 m_region = region;
320
321 if (m_rects)
322 delete[] m_rects;
323
324 m_rects = NULL;
325
326 if (m_region.Empty())
327 m_numRects = 0;
328 else
329 {
330 // we cannot dissolve it into rects on mac
331 m_rects = new wxRect[1];
332 Rect rect = (**OTHER_M_REGION( region )).rgnBBox ;
333 m_rects[0].x = rect.left;
334 m_rects[0].y = rect.top;
335 m_rects[0].width = rect.right - rect.left;
336 m_rects[0].height = rect.bottom - rect.top;
337 m_numRects = 1;
338 }
339 }
340
341 /*!
342 * Increment iterator. The rectangle returned is the one after the
343 * incrementation.
344 */
345 void wxRegionIterator::operator ++ ()
346 {
347 if (m_current < m_numRects)
348 ++m_current;
349 }
350
351 /*!
352 * Increment iterator. The rectangle returned is the one before the
353 * incrementation.
354 */
355 void wxRegionIterator::operator ++ (int)
356 {
357 if (m_current < m_numRects)
358 ++m_current;
359 }
360
361 long wxRegionIterator::GetX() const
362 {
363 if (m_current < m_numRects)
364 return m_rects[m_current].x;
365 return 0;
366 }
367
368 long wxRegionIterator::GetY() const
369 {
370 if (m_current < m_numRects)
371 return m_rects[m_current].y;
372 return 0;
373 }
374
375 long wxRegionIterator::GetW() const
376 {
377 if (m_current < m_numRects)
378 return m_rects[m_current].width ;
379 return 0;
380 }
381
382 long wxRegionIterator::GetH() const
383 {
384 if (m_current < m_numRects)
385 return m_rects[m_current].height;
386 return 0;
387 }
388