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