]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/carbon/region.cpp
hide the MDI parent frame instead of just moving it away (why didn't I do it like...
[wxWidgets.git] / src / mac / carbon / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// File: 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#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
12#pragma implementation "region.h"
13#endif
14
15#include "wx/wxprec.h"
16
17#include "wx/region.h"
18#include "wx/gdicmn.h"
19#include "wx/mac/uma.h"
20
21IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
22IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
23
24//-----------------------------------------------------------------------------
25// wxRegionRefData implementation
26//-----------------------------------------------------------------------------
27
28class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
29public:
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 ~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 */
59wxRegion::wxRegion()
60{
61 m_refData = new wxRegionRefData;
62}
63
64wxRegion::wxRegion(WXHRGN hRegion )
65{
66 m_refData = new wxRegionRefData;
67 CopyRgn( (RgnHandle) hRegion , (RgnHandle) M_REGION ) ;
68}
69
70wxRegion::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
76wxRegion::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
82wxRegion::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
88wxRegion::wxRegion(size_t n, const wxPoint *points, int WXUNUSED(fillStyle))
89{
90 m_refData = new wxRegionRefData;
91
92 // OS X somehow does not collect the region invisibly as before, so sometimes things
93 // get drawn on screen instead of just being combined into a region, therefore we allocate a temp gworld now
94
95 GWorldPtr gWorld = NULL;
96 GWorldPtr oldWorld;
97 GDHandle oldGDHandle;
98 OSStatus err ;
99 Rect destRect = {0,0,1,1};
100
101 ::GetGWorld( &oldWorld, &oldGDHandle );
102 err = ::NewGWorld( &gWorld, 32, &destRect, nil, nil, 0 );
103 if ( err == noErr )
104 {
105 ::SetGWorld( gWorld, GetGDevice() );
106
107 OpenRgn();
108
109 wxCoord x1, x2 , y1 , y2 ;
110 x2 = x1 = points[0].x ;
111 y2 = y1 = points[0].y ;
112 ::MoveTo(x1,y1);
113 for (size_t i = 1; i < n; i++)
114 {
115 x2 = points[i].x ;
116 y2 = points[i].y ;
117 ::LineTo(x2, y2);
118 }
119 // close the polyline if necessary
120 if ( x1 != x2 || y1 != y2 )
121 {
122 ::LineTo(x1,y1 ) ;
123 }
124 CloseRgn( M_REGION ) ;
125 ::SetGWorld( oldWorld, oldGDHandle );
126 }
127}
128
129/*!
130 * Destroy the region.
131 */
132wxRegion::~wxRegion()
133{
134 // m_refData unrefed in ~wxObject
135}
136
137//-----------------------------------------------------------------------------
138//# Modify region
139//-----------------------------------------------------------------------------
140
141//! Clear current region
142void wxRegion::Clear()
143{
144 UnRef();
145}
146
147// Move the region
148bool wxRegion::Offset(wxCoord x, wxCoord y)
149{
150 wxCHECK_MSG( M_REGION, false, _T("invalid wxRegion") );
151
152 if ( !x && !y )
153 {
154 // nothing to do
155 return true;
156 }
157
158 OffsetRgn( M_REGION , x , y ) ;
159 return true ;
160}
161
162
163//! Combine rectangle (x, y, w, h) with this.
164bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
165{
166 // Don't change shared data
167 if (!m_refData)
168 {
169 m_refData = new wxRegionRefData();
170 }
171 else if (m_refData->GetRefCount() > 1)
172 {
173 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
174 UnRef();
175 m_refData = new wxRegionRefData(*ref);
176 }
177 RgnHandle rgn = NewRgn() ;
178 SetRectRgn( rgn , x , y, x+width,y + height ) ;
179
180 switch (op)
181 {
182 case wxRGN_AND:
183 SectRgn( M_REGION , rgn , M_REGION ) ;
184 break ;
185 case wxRGN_OR:
186 UnionRgn( M_REGION , rgn , M_REGION ) ;
187 break ;
188 case wxRGN_XOR:
189 XorRgn( M_REGION , rgn , M_REGION ) ;
190 break ;
191 case wxRGN_DIFF:
192 DiffRgn( M_REGION , rgn , M_REGION ) ;
193 break ;
194 case wxRGN_COPY:
195 default:
196 CopyRgn( rgn ,M_REGION ) ;
197 break ;
198 }
199
200 DisposeRgn( rgn ) ;
201
202 return TRUE;
203}
204
205//! Union /e region with this.
206bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
207{
208 if (region.Empty())
209 return FALSE;
210
211 // Don't change shared data
212 if (!m_refData) {
213 m_refData = new wxRegionRefData();
214 }
215 else if (m_refData->GetRefCount() > 1)
216 {
217 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
218 UnRef();
219 m_refData = new wxRegionRefData(*ref);
220 }
221
222 switch (op)
223 {
224 case wxRGN_AND:
225 SectRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
226 break ;
227 case wxRGN_OR:
228 UnionRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
229 break ;
230 case wxRGN_XOR:
231 XorRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
232 break ;
233 case wxRGN_DIFF:
234 DiffRgn( M_REGION , OTHER_M_REGION(region) , M_REGION ) ;
235 break ;
236 case wxRGN_COPY:
237 default:
238 CopyRgn( OTHER_M_REGION(region) ,M_REGION ) ;
239 break ;
240 }
241
242 return TRUE;
243}
244
245bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
246{
247 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
248}
249
250//-----------------------------------------------------------------------------
251//# Information on region
252//-----------------------------------------------------------------------------
253
254// Outer bounds of region
255void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord& w, wxCoord& h) const
256{
257 if (m_refData)
258 {
259 Rect box ;
260 GetRegionBounds( M_REGION , &box ) ;
261 x = box.left ;
262 y = box.top ;
263 w = box.right - box.left ;
264 h = box.bottom - box.top ;
265 }
266 else
267 {
268 x = y = w = h = 0;
269 }
270}
271
272wxRect wxRegion::GetBox() const
273{
274 wxCoord x, y, w, h;
275 GetBox(x, y, w, h);
276 return wxRect(x, y, w, h);
277}
278
279// Is region empty?
280bool wxRegion::Empty() const
281{
282 return EmptyRgn( M_REGION ) ;
283}
284
285const WXHRGN wxRegion::GetWXHRGN() const
286{
287 return M_REGION ;
288}
289
290//-----------------------------------------------------------------------------
291//# Tests
292//-----------------------------------------------------------------------------
293
294// Does the region contain the point (x,y)?
295wxRegionContain wxRegion::Contains(long x, long y) const
296{
297 if (!m_refData)
298 return wxOutRegion;
299
300 // TODO. Return wxInRegion if within region.
301 if (0)
302 return wxInRegion;
303 return wxOutRegion;
304}
305
306// Does the region contain the point pt?
307wxRegionContain wxRegion::Contains(const wxPoint& pt) const
308{
309 if (!m_refData)
310 return wxOutRegion;
311
312 Point p = { pt.y , pt.x } ;
313 if (PtInRgn( p , M_REGION ) )
314 return wxInRegion;
315
316 return wxOutRegion;
317}
318
319// Does the region contain the rectangle (x, y, w, h)?
320wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
321{
322 if (!m_refData)
323 return wxOutRegion;
324
325 Rect rect = { y , x , y + h , x + w } ;
326 if (RectInRgn( &rect , M_REGION ) )
327 return wxInRegion;
328 else
329 return wxOutRegion;
330}
331
332// Does the region contain the rectangle rect
333wxRegionContain wxRegion::Contains(const wxRect& rect) const
334{
335 if (!m_refData)
336 return wxOutRegion;
337
338 long x, y, w, h;
339 x = rect.x;
340 y = rect.y;
341 w = rect.GetWidth();
342 h = rect.GetHeight();
343 return Contains(x, y, w, h);
344}
345
346///////////////////////////////////////////////////////////////////////////////
347// //
348// wxRegionIterator //
349// //
350///////////////////////////////////////////////////////////////////////////////
351
352/*!
353 * Initialize empty iterator
354 */
355wxRegionIterator::wxRegionIterator()
356 : m_current(0), m_numRects(0), m_rects(NULL)
357{
358}
359
360wxRegionIterator::~wxRegionIterator()
361{
362 if (m_rects) {
363 delete[] m_rects;
364 m_rects = NULL;
365 }
366}
367
368wxRegionIterator::wxRegionIterator(const wxRegionIterator& iterator)
369 : wxObject()
370 , m_current(iterator.m_current)
371 , m_numRects(0)
372 , m_rects(NULL)
373{
374 SetRects(iterator.m_numRects, iterator.m_rects);
375}
376
377wxRegionIterator& wxRegionIterator::operator=(const wxRegionIterator& iterator)
378{
379 m_current = iterator.m_current;
380 SetRects(iterator.m_numRects, iterator.m_rects);
381 return *this;
382}
383
384/*!
385 * Set iterator rects for region
386 */
387void wxRegionIterator::SetRects(long numRects, wxRect *rects)
388{
389 if (m_rects) {
390 delete[] m_rects;
391 m_rects = NULL;
392 }
393 if (rects)
394 {
395 int i;
396 m_rects = new wxRect[numRects];
397 for (i = 0; i < numRects; i++)
398 m_rects[i] = rects[i];
399 }
400 m_numRects = numRects;
401}
402
403/*!
404 * Initialize iterator for region
405 */
406wxRegionIterator::wxRegionIterator(const wxRegion& region)
407{
408 m_rects = NULL;
409
410 Reset(region);
411}
412
413/*!
414 * Reset iterator for a new /e region.
415 */
416
417OSStatus wxMacRegionToRectsCounterCallback (
418 UInt16 message, RgnHandle region, const Rect *rect, void *data)
419{
420 long *m_numRects = (long*) data ;
421 if ( message == kQDRegionToRectsMsgInit )
422 {
423 (*m_numRects) = 0 ;
424 }
425 else if (message == kQDRegionToRectsMsgParse)
426 {
427 (*m_numRects) += 1 ;
428 }
429 return noErr;
430}
431
432class RegionToRectsCallbackData
433{
434public :
435 wxRect* m_rects ;
436 long m_current ;
437} ;
438
439OSStatus wxMacRegionToRectsSetterCallback (
440 UInt16 message, RgnHandle region, const Rect *rect, void *data)
441{
442 if (message == kQDRegionToRectsMsgParse)
443 {
444 RegionToRectsCallbackData *cb = (RegionToRectsCallbackData*) data ;
445 cb->m_rects[cb->m_current++] = wxRect( rect->left , rect->top , rect->right - rect->left , rect->bottom - rect->top ) ;
446 }
447 return noErr;
448}
449
450void wxRegionIterator::Reset(const wxRegion& region)
451{
452 m_current = 0;
453 m_region = region;
454
455 if (m_rects) {
456 delete[] m_rects;
457 m_rects = NULL;
458 }
459
460 if (m_region.Empty())
461 m_numRects = 0;
462 else
463 {
464 RegionToRectsUPP proc = NewRegionToRectsUPP (wxMacRegionToRectsCounterCallback);
465
466 OSStatus err = noErr;
467 err = QDRegionToRects (OTHER_M_REGION( region ) , kQDParseRegionFromTopLeft, proc, (void*)&m_numRects);
468 if (err == noErr)
469 {
470 DisposeRegionToRectsUPP (proc);
471 proc = NewRegionToRectsUPP (wxMacRegionToRectsSetterCallback);
472 m_rects = new wxRect[m_numRects];
473 RegionToRectsCallbackData data ;
474 data.m_rects = m_rects ;
475 data.m_current = 0 ;
476 QDRegionToRects (OTHER_M_REGION( region ) , kQDParseRegionFromTopLeft, proc, (void*)&data);
477 }
478 else
479 {
480 m_numRects = 0 ;
481 }
482 DisposeRegionToRectsUPP (proc);
483 }
484}
485
486/*!
487 * Increment iterator. The rectangle returned is the one after the
488 * incrementation.
489 */
490wxRegionIterator& wxRegionIterator::operator ++ ()
491{
492 if (m_current < m_numRects)
493 ++m_current;
494 return *this;
495}
496
497/*!
498 * Increment iterator. The rectangle returned is the one before the
499 * incrementation.
500 */
501wxRegionIterator wxRegionIterator::operator ++ (int)
502{
503 wxRegionIterator previous(*this);
504
505 if (m_current < m_numRects)
506 ++m_current;
507
508 return previous;
509}
510
511long wxRegionIterator::GetX() const
512{
513 if (m_current < m_numRects)
514 return m_rects[m_current].x;
515 return 0;
516}
517
518long wxRegionIterator::GetY() const
519{
520 if (m_current < m_numRects)
521 return m_rects[m_current].y;
522 return 0;
523}
524
525long wxRegionIterator::GetW() const
526{
527 if (m_current < m_numRects)
528 return m_rects[m_current].width ;
529 return 0;
530}
531
532long wxRegionIterator::GetH() const
533{
534 if (m_current < m_numRects)
535 return m_rects[m_current].height;
536 return 0;
537}
538