]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk/region.cpp
another GetInt/GetId bug fix
[wxWidgets.git] / src / gtk / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: gtk/region.cpp
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "region.h"
12#endif
13
14#include "wx/region.h"
15
16#include <gdk/gdk.h>
17#include <gtk/gtk.h>
18
19#define OLDCODE 0
20
21//-----------------------------------------------------------------------------
22// wxRegion
23//-----------------------------------------------------------------------------
24
25class wxRegionRefData: public wxObjectRefData
26{
27public:
28 wxRegionRefData();
29 ~wxRegionRefData();
30
31 GdkRegion *m_region;
32#if OLDCODE
33 wxList m_rects;
34#endif
35};
36
37wxRegionRefData::wxRegionRefData()
38{
39 m_region = (GdkRegion *) NULL;
40}
41
42wxRegionRefData::~wxRegionRefData()
43{
44 if (m_region) gdk_region_destroy( m_region );
45
46#if OLDCODE
47 wxNode *node = m_rects.First();
48 while (node)
49 {
50 wxRect *r = (wxRect*)node->Data();
51 delete r;
52 node = node->Next();
53 }
54#endif
55}
56
57//-----------------------------------------------------------------------------
58
59#define M_REGIONDATA ((wxRegionRefData *)m_refData)
60
61IMPLEMENT_DYNAMIC_CLASS(wxRegion,wxGDIObject);
62
63wxRegion::wxRegion( wxCoord x, wxCoord y, wxCoord w, wxCoord h )
64{
65 m_refData = new wxRegionRefData();
66 GdkRegion *reg = gdk_region_new();
67 GdkRectangle rect;
68 rect.x = x;
69 rect.y = y;
70 rect.width = w;
71 rect.height = h;
72#ifdef __WXGTK20__
73 gdk_region_union_with_rect( reg, &rect );
74 M_REGIONDATA->m_region = reg;
75#else
76 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
77 gdk_region_destroy( reg );
78#endif
79#if OLDCODE
80 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,w,h) );
81#endif
82}
83
84wxRegion::wxRegion( const wxPoint& topLeft, const wxPoint& bottomRight )
85{
86 m_refData = new wxRegionRefData();
87 GdkRegion *reg = gdk_region_new();
88 GdkRectangle rect;
89 rect.x = topLeft.x;
90 rect.y = topLeft.y;
91 rect.width = bottomRight.x - rect.x;
92 rect.height = bottomRight.y - rect.y;
93#ifdef __WXGTK20__
94 gdk_region_union_with_rect( reg, &rect );
95 M_REGIONDATA->m_region = reg;
96#else
97 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
98 gdk_region_destroy( reg );
99#endif
100#if OLDCODE
101 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(topLeft,bottomRight) );
102#endif
103}
104
105wxRegion::wxRegion( const wxRect& rect )
106{
107 m_refData = new wxRegionRefData();
108 GdkRegion *reg = gdk_region_new();
109 GdkRectangle g_rect;
110 g_rect.x = rect.x;
111 g_rect.y = rect.y;
112 g_rect.width = rect.width;
113 g_rect.height = rect.height;
114#ifdef __WXGTK20__
115 gdk_region_union_with_rect( reg, &g_rect );
116 M_REGIONDATA->m_region = reg;
117#else
118 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &g_rect );
119 gdk_region_destroy( reg );
120#endif
121#if OLDCODE
122 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(rect.x,rect.y,rect.width,rect.height) );
123#endif
124}
125
126wxRegion::wxRegion()
127{
128}
129
130wxRegion::~wxRegion()
131{
132}
133
134bool wxRegion::operator == ( const wxRegion& region )
135{
136 return m_refData == region.m_refData;
137}
138
139bool wxRegion::operator != ( const wxRegion& region )
140{
141 return m_refData != region.m_refData;
142}
143
144void wxRegion::Clear()
145{
146 UnRef();
147}
148
149bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
150{
151 GdkRectangle rect;
152 rect.x = x;
153 rect.y = y;
154 rect.width = width;
155 rect.height = height;
156 if (!m_refData)
157 {
158 m_refData = new wxRegionRefData();
159 GdkRegion *reg = gdk_region_new();
160#ifdef __WXGTK20__
161 gdk_region_union_with_rect( reg, &rect );
162 M_REGIONDATA->m_region = reg;
163#else
164 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
165 gdk_region_destroy( reg );
166#endif
167 }
168 else
169 {
170#ifdef __WXGTK20__
171 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
172#else
173 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
174 gdk_region_destroy( M_REGIONDATA->m_region );
175 M_REGIONDATA->m_region = reg;
176#endif
177 }
178
179#if OLDCODE
180 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(x,y,width,height) );
181#endif
182
183 return TRUE;
184}
185
186bool wxRegion::Union( const wxRect& rect )
187{
188 return Union( rect.x, rect.y, rect.width, rect.height );
189}
190
191bool wxRegion::Union( const wxRegion& region )
192{
193 if (region.IsNull())
194 return FALSE;
195
196 if (!m_refData)
197 {
198 m_refData = new wxRegionRefData();
199 M_REGIONDATA->m_region = gdk_region_new();
200 }
201
202#ifdef __WXGTK20__
203 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
204#else
205 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
206 gdk_region_destroy( M_REGIONDATA->m_region );
207 M_REGIONDATA->m_region = reg;
208#endif
209
210#if OLDCODE
211 wxNode *node = region.GetRectList()->First();
212 while (node)
213 {
214 wxRect *r = (wxRect*)node->Data();
215 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
216 node = node->Next();
217 }
218#endif
219
220 return TRUE;
221}
222
223bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
224{
225 if (!m_refData)
226 {
227 m_refData = new wxRegionRefData();
228 M_REGIONDATA->m_region = gdk_region_new();
229 }
230
231 wxRegion reg( x, y, width, height );
232 Intersect( reg );
233 return TRUE;
234}
235
236bool wxRegion::Intersect( const wxRect& rect )
237{
238 if (!m_refData)
239 {
240 m_refData = new wxRegionRefData();
241 M_REGIONDATA->m_region = gdk_region_new();
242 }
243
244 wxRegion reg( rect );
245 Intersect( reg );
246 return TRUE;
247}
248
249bool wxRegion::Intersect( const wxRegion& region )
250{
251 if (region.IsNull())
252 return FALSE;
253
254 if (!m_refData)
255 {
256 m_refData = new wxRegionRefData();
257 M_REGIONDATA->m_region = gdk_region_new();
258 return TRUE;
259 }
260
261#ifdef __WXGTK20__
262 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
263#else
264 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
265 gdk_region_destroy( M_REGIONDATA->m_region );
266 M_REGIONDATA->m_region = reg;
267#endif
268 return TRUE;
269}
270
271bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
272{
273 if (!m_refData)
274 {
275 m_refData = new wxRegionRefData();
276 M_REGIONDATA->m_region = gdk_region_new();
277 }
278
279 wxRegion reg( x, y, width, height );
280 Subtract( reg );
281 return TRUE;
282}
283
284bool wxRegion::Subtract( const wxRect& rect )
285{
286 if (!m_refData)
287 {
288 m_refData = new wxRegionRefData();
289 M_REGIONDATA->m_region = gdk_region_new();
290 }
291
292 wxRegion reg( rect );
293 Subtract( reg );
294 return TRUE;
295}
296
297bool wxRegion::Subtract( const wxRegion& region )
298{
299 if (region.IsNull())
300 return FALSE;
301
302 if (!m_refData)
303 {
304 m_refData = new wxRegionRefData();
305 M_REGIONDATA->m_region = gdk_region_new();
306 }
307
308#ifdef __WXGTK20__
309 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
310#else
311 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
312 gdk_region_destroy( M_REGIONDATA->m_region );
313 M_REGIONDATA->m_region = reg;
314#endif
315 return TRUE;
316}
317
318bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
319{
320 if (!m_refData)
321 {
322 m_refData = new wxRegionRefData();
323 M_REGIONDATA->m_region = gdk_region_new();
324 }
325
326 wxRegion reg( x, y, width, height );
327 Xor( reg );
328 return TRUE;
329}
330
331bool wxRegion::Xor( const wxRect& rect )
332{
333 if (!m_refData)
334 {
335 m_refData = new wxRegionRefData();
336 M_REGIONDATA->m_region = gdk_region_new();
337 }
338
339 wxRegion reg( rect );
340 Xor( reg );
341 return TRUE;
342}
343
344bool wxRegion::Xor( const wxRegion& region )
345{
346 if (region.IsNull())
347 return FALSE;
348
349 if (!m_refData)
350 {
351 m_refData = new wxRegionRefData();
352 M_REGIONDATA->m_region = gdk_region_new();
353 }
354
355#ifdef __WXGTK20__
356 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
357#else
358 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
359 gdk_region_destroy( M_REGIONDATA->m_region );
360 M_REGIONDATA->m_region = reg;
361#endif
362
363#if OLDCODE
364 wxNode *node = region.GetRectList()->First();
365 while (node)
366 {
367 wxRect *r = (wxRect*)node->Data();
368 M_REGIONDATA->m_rects.Append( (wxObject*) new wxRect(r->x,r->y,r->width,r->height) );
369 node = node->Next();
370 }
371#endif
372
373 return TRUE;
374}
375
376void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
377{
378 x = 0;
379 y = 0;
380 w = -1;
381 h = -1;
382 if (!m_refData)
383 return;
384
385 GdkRectangle rect;
386 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
387 x = rect.x;
388 y = rect.y;
389 w = rect.width;
390 h = rect.height;
391}
392
393wxRect wxRegion::GetBox() const
394{
395 wxCoord x = 0;
396 wxCoord y = 0;
397 wxCoord w = -1;
398 wxCoord h = -1;
399 GetBox( x, y, w, h );
400 return wxRect( x, y, w, h );
401}
402
403bool wxRegion::Empty() const
404{
405 if (!m_refData)
406 return TRUE;
407
408 return gdk_region_empty( M_REGIONDATA->m_region );
409}
410
411wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
412{
413 if (!m_refData)
414 return wxOutRegion;
415
416 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
417 return wxInRegion;
418 else
419 return wxOutRegion;
420}
421
422wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
423{
424 if (!m_refData)
425 return wxOutRegion;
426
427 GdkRectangle rect;
428 rect.x = x;
429 rect.y = y;
430 rect.width = w;
431 rect.height = h;
432 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
433 switch (res)
434 {
435 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
436 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
437 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
438 }
439 return wxOutRegion;
440}
441
442wxRegionContain wxRegion::Contains(const wxPoint& pt) const
443{
444 return Contains( pt.x, pt.y );
445}
446
447wxRegionContain wxRegion::Contains(const wxRect& rect) const
448{
449 return Contains( rect.x, rect.y, rect.width, rect.height );
450}
451
452GdkRegion *wxRegion::GetRegion() const
453{
454 if (!m_refData)
455 return (GdkRegion*) NULL;
456
457 return M_REGIONDATA->m_region;
458}
459
460wxList *wxRegion::GetRectList() const
461{
462#if OLDCODE
463 if (!m_refData)
464 return (wxList*) NULL;
465
466 return &(M_REGIONDATA->m_rects);
467#else
468 return (wxList*) NULL;
469#endif
470}
471
472//-----------------------------------------------------------------------------
473// wxRegionIterator
474//-----------------------------------------------------------------------------
475
476#if OLDCODE
477
478IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
479
480wxRegionIterator::wxRegionIterator()
481{
482 Reset();
483}
484
485wxRegionIterator::wxRegionIterator( const wxRegion& region )
486{
487 Reset(region);
488}
489
490void wxRegionIterator::Reset( const wxRegion& region )
491{
492 m_region = region;
493 Reset();
494}
495
496wxRegionIterator::operator bool () const
497{
498 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
499}
500
501bool wxRegionIterator::HaveRects() const
502{
503 return m_region.GetRectList() && m_current < (size_t)m_region.GetRectList()->Number();
504}
505
506void wxRegionIterator::operator ++ ()
507{
508 if (HaveRects()) ++m_current;
509}
510
511void wxRegionIterator::operator ++ (int)
512{
513 if (HaveRects()) ++m_current;
514}
515
516wxCoord wxRegionIterator::GetX() const
517{
518 wxNode *node = m_region.GetRectList()->Nth( m_current );
519 if (!node) return 0;
520 wxRect *r = (wxRect*)node->Data();
521 return r->x;
522}
523
524wxCoord wxRegionIterator::GetY() const
525{
526 wxNode *node = m_region.GetRectList()->Nth( m_current );
527 if (!node) return 0;
528 wxRect *r = (wxRect*)node->Data();
529 return r->y;
530}
531
532wxCoord wxRegionIterator::GetW() const
533{
534 wxNode *node = m_region.GetRectList()->Nth( m_current );
535 if (!node) return 0;
536 wxRect *r = (wxRect*)node->Data();
537 return r->width;
538}
539
540wxCoord wxRegionIterator::GetH() const
541{
542 wxNode *node = m_region.GetRectList()->Nth( m_current );
543 if (!node) return 0;
544 wxRect *r = (wxRect*)node->Data();
545 return r->height;
546}
547
548#else
549
550// the following structures must match the private structures
551// in X11 region code ( xc/lib/X11/region.h )
552
553// this makes the Region type transparent
554// and we have access to the region rectangles
555
556struct _XBox {
557 short x1, x2, y1, y2;
558};
559
560struct _XRegion {
561 long size , numRects;
562 _XBox *rects, extents;
563};
564
565class wxRIRefData: public wxObjectRefData
566{
567public:
568
569 wxRIRefData() : m_rects(0), m_numRects(0){}
570 ~wxRIRefData();
571
572 wxRect *m_rects;
573 size_t m_numRects;
574
575 void CreateRects( const wxRegion& r );
576};
577
578wxRIRefData::~wxRIRefData()
579{
580 delete m_rects;
581}
582
583#include <gdk/gdkprivate.h>
584
585void wxRIRefData::CreateRects( const wxRegion& region )
586{
587 if( m_rects )
588 delete m_rects;
589 m_rects = 0;
590 m_numRects= 0;
591 GdkRegion *gdkregion= region.GetRegion();
592 if( gdkregion ){
593 Region r= ((GdkRegionPrivate *)gdkregion)->xregion;
594 if( r ){
595 m_numRects= r->numRects;
596 if( m_numRects )
597 {
598 m_rects= new wxRect[m_numRects];
599 for( size_t i=0; i<m_numRects; ++i )
600 {
601 _XBox &xr= r->rects[i];
602 wxRect&wr= m_rects[i];
603 wr.x = xr.x1;
604 wr.y = xr.y1;
605 wr.width = xr.x2-xr.x1;
606 wr.height= xr.y2-xr.y1;
607 }
608 }
609 }
610 }
611}
612
613IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
614
615wxRegionIterator::wxRegionIterator()
616{
617 m_refData = new wxRIRefData();
618 Reset();
619}
620
621wxRegionIterator::wxRegionIterator( const wxRegion& region )
622{
623 m_refData = new wxRIRefData();
624 Reset(region);
625}
626
627void wxRegionIterator::Reset( const wxRegion& region )
628{
629 m_region = region;
630 ((wxRIRefData*)m_refData)->CreateRects(region);
631 Reset();
632}
633
634bool wxRegionIterator::HaveRects() const
635{
636 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
637}
638
639wxRegionIterator::operator bool () const
640{
641 return HaveRects();
642}
643
644void wxRegionIterator::operator ++ ()
645{
646 if (HaveRects()) ++m_current;
647}
648
649void wxRegionIterator::operator ++ (int)
650{
651 if (HaveRects()) ++m_current;
652}
653
654wxCoord wxRegionIterator::GetX() const
655{
656 if( !HaveRects() ) return 0;
657 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
658}
659
660wxCoord wxRegionIterator::GetY() const
661{
662 if( !HaveRects() ) return 0;
663 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
664}
665
666wxCoord wxRegionIterator::GetW() const
667{
668 if( !HaveRects() ) return -1;
669 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
670}
671
672wxCoord wxRegionIterator::GetH() const
673{
674 if( !HaveRects() ) return -1;
675 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
676}
677
678#endif
679