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