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